summaryrefslogtreecommitdiff
path: root/src/libimcv
diff options
context:
space:
mode:
authorRomain Francoise <rfrancoise@debian.org>2014-10-21 19:28:38 +0200
committerRomain Francoise <rfrancoise@debian.org>2014-10-21 19:41:50 +0200
commitb23b0e5609ed4b3d29396a1727aab035fa4a395f (patch)
tree091d0b144dd92a0c124b7fbe9eae68f79cb975dc /src/libimcv
parent4a01a7e2574040cf246fd00ebff173b873c17349 (diff)
downloadvyos-strongswan-b23b0e5609ed4b3d29396a1727aab035fa4a395f.tar.gz
vyos-strongswan-b23b0e5609ed4b3d29396a1727aab035fa4a395f.zip
Import upstream release 5.2.1
Diffstat (limited to 'src/libimcv')
-rw-r--r--src/libimcv/Android.mk57
-rw-r--r--src/libimcv/Makefile.am106
-rw-r--r--src/libimcv/Makefile.in777
-rw-r--r--src/libimcv/ietf/ietf_attr.c29
-rw-r--r--src/libimcv/ietf/ietf_attr.h8
-rw-r--r--src/libimcv/ietf/ietf_attr_assess_result.c29
-rw-r--r--src/libimcv/ietf/ietf_attr_assess_result.h8
-rw-r--r--src/libimcv/ietf/ietf_attr_attr_request.c30
-rw-r--r--src/libimcv/ietf/ietf_attr_attr_request.h10
-rw-r--r--src/libimcv/ietf/ietf_attr_default_pwd_enabled.c26
-rw-r--r--src/libimcv/ietf/ietf_attr_default_pwd_enabled.h6
-rw-r--r--src/libimcv/ietf/ietf_attr_fwd_enabled.c26
-rw-r--r--src/libimcv/ietf/ietf_attr_fwd_enabled.h8
-rw-r--r--src/libimcv/ietf/ietf_attr_installed_packages.c138
-rw-r--r--src/libimcv/ietf/ietf_attr_installed_packages.h18
-rw-r--r--src/libimcv/ietf/ietf_attr_numeric_version.c29
-rw-r--r--src/libimcv/ietf/ietf_attr_numeric_version.h8
-rw-r--r--src/libimcv/ietf/ietf_attr_op_status.c24
-rw-r--r--src/libimcv/ietf/ietf_attr_op_status.h8
-rw-r--r--src/libimcv/ietf/ietf_attr_pa_tnc_error.c82
-rw-r--r--src/libimcv/ietf/ietf_attr_pa_tnc_error.h28
-rw-r--r--src/libimcv/ietf/ietf_attr_port_filter.c30
-rw-r--r--src/libimcv/ietf/ietf_attr_port_filter.h8
-rw-r--r--src/libimcv/ietf/ietf_attr_product_info.c30
-rw-r--r--src/libimcv/ietf/ietf_attr_product_info.h8
-rw-r--r--src/libimcv/ietf/ietf_attr_remediation_instr.c26
-rw-r--r--src/libimcv/ietf/ietf_attr_remediation_instr.h8
-rw-r--r--src/libimcv/ietf/ietf_attr_string_version.c26
-rw-r--r--src/libimcv/ietf/ietf_attr_string_version.h8
-rw-r--r--src/libimcv/imc/imc_agent.c28
-rw-r--r--src/libimcv/imc/imc_agent.h12
-rw-r--r--src/libimcv/imc/imc_msg.c239
-rw-r--r--src/libimcv/imc/imc_msg.h6
-rw-r--r--src/libimcv/imc/imc_os_info.h2
-rw-r--r--src/libimcv/imc/imc_state.h11
-rw-r--r--src/libimcv/imcv.c45
-rw-r--r--src/libimcv/imcv.h12
-rw-r--r--src/libimcv/imcv_tests.c45
-rw-r--r--src/libimcv/imcv_tests.h17
-rw-r--r--src/libimcv/imv/data.sql35
-rw-r--r--src/libimcv/imv/imv_agent.c26
-rw-r--r--src/libimcv/imv/imv_agent.h10
-rw-r--r--src/libimcv/imv/imv_msg.c238
-rw-r--r--src/libimcv/imv/imv_msg.h6
-rw-r--r--src/libimcv/imv/imv_os_info.h2
-rw-r--r--src/libimcv/imv/imv_state.h8
-rw-r--r--src/libimcv/ita/ita_attr.c19
-rw-r--r--src/libimcv/ita/ita_attr.h8
-rw-r--r--src/libimcv/ita/ita_attr_angel.c12
-rw-r--r--src/libimcv/ita/ita_attr_angel.h5
-rw-r--r--src/libimcv/ita/ita_attr_command.c30
-rw-r--r--src/libimcv/ita/ita_attr_command.h7
-rw-r--r--src/libimcv/ita/ita_attr_device_id.c27
-rw-r--r--src/libimcv/ita/ita_attr_device_id.h7
-rw-r--r--src/libimcv/ita/ita_attr_dummy.c34
-rw-r--r--src/libimcv/ita/ita_attr_dummy.h9
-rw-r--r--src/libimcv/ita/ita_attr_get_settings.c29
-rw-r--r--src/libimcv/ita/ita_attr_get_settings.h8
-rw-r--r--src/libimcv/ita/ita_attr_settings.c28
-rw-r--r--src/libimcv/ita/ita_attr_settings.h5
-rw-r--r--src/libimcv/os_info/os_info.h1
-rw-r--r--src/libimcv/pa_tnc/pa_tnc_attr.h13
-rw-r--r--src/libimcv/pa_tnc/pa_tnc_attr_manager.c161
-rw-r--r--src/libimcv/pa_tnc/pa_tnc_attr_manager.h26
-rw-r--r--src/libimcv/pa_tnc/pa_tnc_msg.c221
-rw-r--r--src/libimcv/pa_tnc/pa_tnc_msg.h6
-rw-r--r--src/libimcv/plugins/imc_attestation/Makefile.am18
-rw-r--r--src/libimcv/plugins/imc_attestation/Makefile.in765
-rw-r--r--src/libimcv/plugins/imc_attestation/imc_attestation.c335
-rw-r--r--src/libimcv/plugins/imc_attestation/imc_attestation_process.c480
-rw-r--r--src/libimcv/plugins/imc_attestation/imc_attestation_process.h49
-rw-r--r--src/libimcv/plugins/imc_attestation/imc_attestation_state.c260
-rw-r--r--src/libimcv/plugins/imc_attestation/imc_attestation_state.h86
-rw-r--r--src/libimcv/plugins/imc_os/Makefile.in8
-rw-r--r--src/libimcv/plugins/imc_os/imc_os.c70
-rw-r--r--src/libimcv/plugins/imc_os/imc_os_state.c16
-rw-r--r--src/libimcv/plugins/imc_scanner/Makefile.in8
-rw-r--r--src/libimcv/plugins/imc_scanner/imc_scanner.c10
-rw-r--r--src/libimcv/plugins/imc_scanner/imc_scanner_state.c16
-rw-r--r--src/libimcv/plugins/imc_swid/Makefile.am37
-rw-r--r--src/libimcv/plugins/imc_swid/Makefile.in826
-rw-r--r--src/libimcv/plugins/imc_swid/imc_swid.c424
-rw-r--r--src/libimcv/plugins/imc_swid/imc_swid_state.c203
-rw-r--r--src/libimcv/plugins/imc_swid/imc_swid_state.h57
-rw-r--r--src/libimcv/plugins/imc_swid/regid.2004-03.org.strongswan_strongSwan.swidtag.in12
-rw-r--r--src/libimcv/plugins/imc_test/Makefile.in8
-rw-r--r--src/libimcv/plugins/imc_test/imc_test.c36
-rw-r--r--src/libimcv/plugins/imc_test/imc_test_state.c16
-rw-r--r--src/libimcv/plugins/imv_attestation/Makefile.am33
-rw-r--r--src/libimcv/plugins/imv_attestation/Makefile.in847
-rw-r--r--src/libimcv/plugins/imv_attestation/attest.c484
-rw-r--r--src/libimcv/plugins/imv_attestation/attest_db.c1995
-rw-r--r--src/libimcv/plugins/imv_attestation/attest_db.h267
-rw-r--r--src/libimcv/plugins/imv_attestation/attest_usage.c111
-rw-r--r--src/libimcv/plugins/imv_attestation/attest_usage.h25
-rwxr-xr-xsrc/libimcv/plugins/imv_attestation/build-database.sh84
-rw-r--r--src/libimcv/plugins/imv_attestation/imv_attestation.c24
-rw-r--r--src/libimcv/plugins/imv_attestation/imv_attestation_agent.c931
-rw-r--r--src/libimcv/plugins/imv_attestation/imv_attestation_agent.h36
-rw-r--r--src/libimcv/plugins/imv_attestation/imv_attestation_build.c155
-rw-r--r--src/libimcv/plugins/imv_attestation/imv_attestation_build.h46
-rw-r--r--src/libimcv/plugins/imv_attestation/imv_attestation_process.c567
-rw-r--r--src/libimcv/plugins/imv_attestation/imv_attestation_process.h57
-rw-r--r--src/libimcv/plugins/imv_attestation/imv_attestation_state.c560
-rw-r--r--src/libimcv/plugins/imv_attestation/imv_attestation_state.h192
-rw-r--r--src/libimcv/plugins/imv_os/Makefile.in8
-rw-r--r--src/libimcv/plugins/imv_os/imv_os_agent.c65
-rw-r--r--src/libimcv/plugins/imv_os/imv_os_state.c32
-rw-r--r--src/libimcv/plugins/imv_os/imv_os_state.h12
-rw-r--r--src/libimcv/plugins/imv_scanner/Makefile.in8
-rw-r--r--src/libimcv/plugins/imv_scanner/imv_scanner_agent.c23
-rw-r--r--src/libimcv/plugins/imv_scanner/imv_scanner_state.c14
-rw-r--r--src/libimcv/plugins/imv_swid/Makefile.am21
-rw-r--r--src/libimcv/plugins/imv_swid/Makefile.in769
-rw-r--r--src/libimcv/plugins/imv_swid/imv_swid.c24
-rw-r--r--src/libimcv/plugins/imv_swid/imv_swid_agent.c726
-rw-r--r--src/libimcv/plugins/imv_swid/imv_swid_agent.h36
-rw-r--r--src/libimcv/plugins/imv_swid/imv_swid_rest.c122
-rw-r--r--src/libimcv/plugins/imv_swid/imv_swid_rest.h63
-rw-r--r--src/libimcv/plugins/imv_swid/imv_swid_state.c402
-rw-r--r--src/libimcv/plugins/imv_swid/imv_swid_state.h136
-rw-r--r--src/libimcv/plugins/imv_test/Makefile.in8
-rw-r--r--src/libimcv/plugins/imv_test/imv_test_agent.c30
-rw-r--r--src/libimcv/plugins/imv_test/imv_test_state.c16
-rw-r--r--src/libimcv/pts/components/ita/ita_comp_func_name.c45
-rw-r--r--src/libimcv/pts/components/ita/ita_comp_func_name.h85
-rw-r--r--src/libimcv/pts/components/ita/ita_comp_ima.c914
-rw-r--r--src/libimcv/pts/components/ita/ita_comp_ima.h35
-rw-r--r--src/libimcv/pts/components/ita/ita_comp_tboot.c362
-rw-r--r--src/libimcv/pts/components/ita/ita_comp_tboot.h35
-rw-r--r--src/libimcv/pts/components/ita/ita_comp_tgrub.c208
-rw-r--r--src/libimcv/pts/components/ita/ita_comp_tgrub.h35
-rw-r--r--src/libimcv/pts/components/pts_comp_evidence.c255
-rw-r--r--src/libimcv/pts/components/pts_comp_evidence.h170
-rw-r--r--src/libimcv/pts/components/pts_comp_func_name.c162
-rw-r--r--src/libimcv/pts/components/pts_comp_func_name.h103
-rw-r--r--src/libimcv/pts/components/pts_component.h109
-rw-r--r--src/libimcv/pts/components/pts_component_manager.c315
-rw-r--r--src/libimcv/pts/components/pts_component_manager.h124
-rw-r--r--src/libimcv/pts/components/tcg/tcg_comp_func_name.c48
-rw-r--r--src/libimcv/pts/components/tcg/tcg_comp_func_name.h98
-rw-r--r--src/libimcv/pts/pts.c1198
-rw-r--r--src/libimcv/pts/pts.h315
-rw-r--r--src/libimcv/pts/pts_creds.c136
-rw-r--r--src/libimcv/pts/pts_creds.h55
-rw-r--r--src/libimcv/pts/pts_database.c432
-rw-r--r--src/libimcv/pts/pts_database.h155
-rw-r--r--src/libimcv/pts/pts_dh_group.c184
-rw-r--r--src/libimcv/pts/pts_dh_group.h107
-rw-r--r--src/libimcv/pts/pts_error.c99
-rw-r--r--src/libimcv/pts/pts_error.h89
-rw-r--r--src/libimcv/pts/pts_file_meas.c414
-rw-r--r--src/libimcv/pts/pts_file_meas.h112
-rw-r--r--src/libimcv/pts/pts_file_meta.c96
-rw-r--r--src/libimcv/pts/pts_file_meta.h85
-rw-r--r--src/libimcv/pts/pts_file_type.c33
-rw-r--r--src/libimcv/pts/pts_file_type.h63
-rw-r--r--src/libimcv/pts/pts_ima_bios_list.c294
-rw-r--r--src/libimcv/pts/pts_ima_bios_list.h74
-rw-r--r--src/libimcv/pts/pts_ima_event_list.c330
-rw-r--r--src/libimcv/pts/pts_ima_event_list.h80
-rw-r--r--src/libimcv/pts/pts_meas_algo.c176
-rw-r--r--src/libimcv/pts/pts_meas_algo.h106
-rw-r--r--src/libimcv/pts/pts_pcr.c289
-rw-r--r--src/libimcv/pts/pts_pcr.h118
-rw-r--r--src/libimcv/pts/pts_proto_caps.h44
-rw-r--r--src/libimcv/pts/pts_req_func_comp_evid.h42
-rw-r--r--src/libimcv/pts/pts_simple_evid_final.h47
-rw-r--r--src/libimcv/seg/seg_contract.c479
-rw-r--r--src/libimcv/seg/seg_contract.h180
-rw-r--r--src/libimcv/seg/seg_contract_manager.c94
-rw-r--r--src/libimcv/seg/seg_contract_manager.h63
-rw-r--r--src/libimcv/seg/seg_env.c306
-rw-r--r--src/libimcv/seg/seg_env.h119
-rw-r--r--src/libimcv/suites/test_imcv_seg.c738
-rw-r--r--src/libimcv/swid/swid_error.c55
-rw-r--r--src/libimcv/swid/swid_error.h58
-rw-r--r--src/libimcv/swid/swid_inventory.c454
-rw-r--r--src/libimcv/swid/swid_inventory.h84
-rw-r--r--src/libimcv/swid/swid_tag.c102
-rw-r--r--src/libimcv/swid/swid_tag.h70
-rw-r--r--src/libimcv/swid/swid_tag_id.c114
-rw-r--r--src/libimcv/swid/swid_tag_id.h73
-rw-r--r--src/libimcv/tcg/pts/tcg_pts_attr_aik.c266
-rw-r--r--src/libimcv/tcg/pts/tcg_pts_attr_aik.h67
-rw-r--r--src/libimcv/tcg/pts/tcg_pts_attr_dh_nonce_finish.c287
-rw-r--r--src/libimcv/tcg/pts/tcg_pts_attr_dh_nonce_finish.h92
-rw-r--r--src/libimcv/tcg/pts/tcg_pts_attr_dh_nonce_params_req.c258
-rw-r--r--src/libimcv/tcg/pts/tcg_pts_attr_dh_nonce_params_req.h75
-rw-r--r--src/libimcv/tcg/pts/tcg_pts_attr_dh_nonce_params_resp.c306
-rw-r--r--src/libimcv/tcg/pts/tcg_pts_attr_dh_nonce_params_resp.h96
-rw-r--r--src/libimcv/tcg/pts/tcg_pts_attr_file_meas.c356
-rw-r--r--src/libimcv/tcg/pts/tcg_pts_attr_file_meas.h68
-rw-r--r--src/libimcv/tcg/pts/tcg_pts_attr_gen_attest_evid.c225
-rw-r--r--src/libimcv/tcg/pts/tcg_pts_attr_gen_attest_evid.h56
-rw-r--r--src/libimcv/tcg/pts/tcg_pts_attr_get_aik.c222
-rw-r--r--src/libimcv/tcg/pts/tcg_pts_attr_get_aik.h56
-rw-r--r--src/libimcv/tcg/pts/tcg_pts_attr_get_tpm_version_info.c225
-rw-r--r--src/libimcv/tcg/pts/tcg_pts_attr_get_tpm_version_info.h57
-rw-r--r--src/libimcv/tcg/pts/tcg_pts_attr_meas_algo.c243
-rw-r--r--src/libimcv/tcg/pts/tcg_pts_attr_meas_algo.h71
-rw-r--r--src/libimcv/tcg/pts/tcg_pts_attr_proto_caps.c244
-rw-r--r--src/libimcv/tcg/pts/tcg_pts_attr_proto_caps.h70
-rw-r--r--src/libimcv/tcg/pts/tcg_pts_attr_req_file_meas.c314
-rw-r--r--src/libimcv/tcg/pts/tcg_pts_attr_req_file_meas.h93
-rw-r--r--src/libimcv/tcg/pts/tcg_pts_attr_req_file_meta.c296
-rw-r--r--src/libimcv/tcg/pts/tcg_pts_attr_req_file_meta.h84
-rw-r--r--src/libimcv/tcg/pts/tcg_pts_attr_req_func_comp_evid.c389
-rw-r--r--src/libimcv/tcg/pts/tcg_pts_attr_req_func_comp_evid.h83
-rw-r--r--src/libimcv/tcg/pts/tcg_pts_attr_simple_comp_evid.c532
-rw-r--r--src/libimcv/tcg/pts/tcg_pts_attr_simple_comp_evid.h67
-rw-r--r--src/libimcv/tcg/pts/tcg_pts_attr_simple_evid_final.c405
-rw-r--r--src/libimcv/tcg/pts/tcg_pts_attr_simple_evid_final.h96
-rw-r--r--src/libimcv/tcg/pts/tcg_pts_attr_tpm_version_info.c248
-rw-r--r--src/libimcv/tcg/pts/tcg_pts_attr_tpm_version_info.h73
-rw-r--r--src/libimcv/tcg/pts/tcg_pts_attr_unix_file_meta.c372
-rw-r--r--src/libimcv/tcg/pts/tcg_pts_attr_unix_file_meta.h68
-rw-r--r--src/libimcv/tcg/seg/tcg_seg_attr_max_size.c254
-rw-r--r--src/libimcv/tcg/seg/tcg_seg_attr_max_size.h73
-rw-r--r--src/libimcv/tcg/seg/tcg_seg_attr_next_seg.c258
-rw-r--r--src/libimcv/tcg/seg/tcg_seg_attr_next_seg.h73
-rw-r--r--src/libimcv/tcg/seg/tcg_seg_attr_seg_env.c257
-rw-r--r--src/libimcv/tcg/seg/tcg_seg_attr_seg_env.h76
-rw-r--r--src/libimcv/tcg/swid/tcg_swid_attr_req.c349
-rw-r--r--src/libimcv/tcg/swid/tcg_swid_attr_req.h106
-rw-r--r--src/libimcv/tcg/swid/tcg_swid_attr_tag_id_inv.c396
-rw-r--r--src/libimcv/tcg/swid/tcg_swid_attr_tag_id_inv.h109
-rw-r--r--src/libimcv/tcg/swid/tcg_swid_attr_tag_inv.c389
-rw-r--r--src/libimcv/tcg/swid/tcg_swid_attr_tag_inv.h108
-rw-r--r--src/libimcv/tcg/tcg_attr.c270
-rw-r--r--src/libimcv/tcg/tcg_attr.h105
231 files changed, 35631 insertions, 583 deletions
diff --git a/src/libimcv/Android.mk b/src/libimcv/Android.mk
index 4253fe274..8269d7296 100644
--- a/src/libimcv/Android.mk
+++ b/src/libimcv/Android.mk
@@ -41,7 +41,62 @@ libimcv_la_SOURCES := \
os_info/os_info.h os_info/os_info.c \
pa_tnc/pa_tnc_attr.h \
pa_tnc/pa_tnc_msg.h pa_tnc/pa_tnc_msg.c \
- pa_tnc/pa_tnc_attr_manager.h pa_tnc/pa_tnc_attr_manager.c
+ pa_tnc/pa_tnc_attr_manager.h pa_tnc/pa_tnc_attr_manager.c \
+ pts/pts.h pts/pts.c \
+ pts/pts_error.h pts/pts_error.c \
+ pts/pts_pcr.h pts/pts_pcr.c \
+ pts/pts_proto_caps.h \
+ pts/pts_req_func_comp_evid.h \
+ pts/pts_simple_evid_final.h \
+ pts/pts_creds.h pts/pts_creds.c \
+ pts/pts_database.h pts/pts_database.c \
+ pts/pts_dh_group.h pts/pts_dh_group.c \
+ pts/pts_file_meas.h pts/pts_file_meas.c \
+ pts/pts_file_meta.h pts/pts_file_meta.c \
+ pts/pts_file_type.h pts/pts_file_type.c \
+ pts/pts_ima_bios_list.h pts/pts_ima_bios_list.c \
+ pts/pts_ima_event_list.h pts/pts_ima_event_list.c \
+ pts/pts_meas_algo.h pts/pts_meas_algo.c \
+ pts/components/pts_component.h \
+ pts/components/pts_component_manager.h pts/components/pts_component_manager.c \
+ pts/components/pts_comp_evidence.h pts/components/pts_comp_evidence.c \
+ pts/components/pts_comp_func_name.h pts/components/pts_comp_func_name.c \
+ pts/components/ita/ita_comp_func_name.h pts/components/ita/ita_comp_func_name.c \
+ pts/components/ita/ita_comp_ima.h pts/components/ita/ita_comp_ima.c \
+ pts/components/ita/ita_comp_tboot.h pts/components/ita/ita_comp_tboot.c \
+ pts/components/ita/ita_comp_tgrub.h pts/components/ita/ita_comp_tgrub.c \
+ pts/components/tcg/tcg_comp_func_name.h pts/components/tcg/tcg_comp_func_name.c \
+ seg/seg_contract.h seg/seg_contract.c \
+ seg/seg_contract_manager.h seg/seg_contract_manager.c \
+ seg/seg_env.h seg/seg_env.c \
+ swid/swid_error.h swid/swid_error.c \
+ swid/swid_inventory.h swid/swid_inventory.c \
+ swid/swid_tag.h swid/swid_tag.c \
+ swid/swid_tag_id.h swid/swid_tag_id.c \
+ tcg/tcg_attr.h tcg/tcg_attr.c \
+ tcg/pts/tcg_pts_attr_proto_caps.h tcg/pts/tcg_pts_attr_proto_caps.c \
+ tcg/pts/tcg_pts_attr_dh_nonce_params_req.h tcg/pts/tcg_pts_attr_dh_nonce_params_req.c \
+ tcg/pts/tcg_pts_attr_dh_nonce_params_resp.h tcg/pts/tcg_pts_attr_dh_nonce_params_resp.c \
+ tcg/pts/tcg_pts_attr_dh_nonce_finish.h tcg/pts/tcg_pts_attr_dh_nonce_finish.c \
+ tcg/pts/tcg_pts_attr_meas_algo.h tcg/pts/tcg_pts_attr_meas_algo.c \
+ tcg/pts/tcg_pts_attr_get_tpm_version_info.h tcg/pts/tcg_pts_attr_get_tpm_version_info.c \
+ tcg/pts/tcg_pts_attr_tpm_version_info.h tcg/pts/tcg_pts_attr_tpm_version_info.c \
+ tcg/pts/tcg_pts_attr_get_aik.h tcg/pts/tcg_pts_attr_get_aik.c \
+ tcg/pts/tcg_pts_attr_aik.h tcg/pts/tcg_pts_attr_aik.c \
+ tcg/pts/tcg_pts_attr_req_func_comp_evid.h tcg/pts/tcg_pts_attr_req_func_comp_evid.c \
+ tcg/pts/tcg_pts_attr_gen_attest_evid.h tcg/pts/tcg_pts_attr_gen_attest_evid.c \
+ tcg/pts/tcg_pts_attr_simple_comp_evid.h tcg/pts/tcg_pts_attr_simple_comp_evid.c \
+ tcg/pts/tcg_pts_attr_simple_evid_final.h tcg/pts/tcg_pts_attr_simple_evid_final.c \
+ tcg/pts/tcg_pts_attr_req_file_meas.h tcg/pts/tcg_pts_attr_req_file_meas.c \
+ tcg/pts/tcg_pts_attr_file_meas.h tcg/pts/tcg_pts_attr_file_meas.c \
+ tcg/pts/tcg_pts_attr_req_file_meta.h tcg/pts/tcg_pts_attr_req_file_meta.c \
+ tcg/pts/tcg_pts_attr_unix_file_meta.h tcg/pts/tcg_pts_attr_unix_file_meta.c \
+ tcg/seg/tcg_seg_attr_max_size.h tcg/seg/tcg_seg_attr_max_size.c \
+ tcg/seg/tcg_seg_attr_seg_env.h tcg/seg/tcg_seg_attr_seg_env.c \
+ tcg/seg/tcg_seg_attr_next_seg.h tcg/seg/tcg_seg_attr_next_seg.c \
+ tcg/swid/tcg_swid_attr_req.h tcg/swid/tcg_swid_attr_req.c \
+ tcg/swid/tcg_swid_attr_tag_id_inv.h tcg/swid/tcg_swid_attr_tag_id_inv.c \
+ tcg/swid/tcg_swid_attr_tag_inv.h tcg/swid/tcg_swid_attr_tag_inv.c
LOCAL_SRC_FILES := $(filter %.c,$(libimcv_la_SOURCES))
diff --git a/src/libimcv/Makefile.am b/src/libimcv/Makefile.am
index 4bed3bf03..d9a5cd50d 100644
--- a/src/libimcv/Makefile.am
+++ b/src/libimcv/Makefile.am
@@ -1,6 +1,7 @@
AM_CPPFLAGS = \
-I$(top_srcdir)/src/libstrongswan \
- -I$(top_srcdir)/src/libtncif
+ -I$(top_srcdir)/src/libtncif \
+ -DIPSEC_SCRIPT=\"${ipsec_script}\"
ipseclib_LTLIBRARIES = libimcv.la
@@ -11,6 +12,10 @@ libimcv_la_LIBADD = \
$(top_builddir)/src/libstrongswan/libstrongswan.la \
$(top_builddir)/src/libtncif/libtncif.la
+if USE_TROUSERS
+ libimcv_la_LIBADD += -ltspi
+endif
+
if USE_WINDOWS
libimcv_la_LIBADD += -lws2_32
endif
@@ -54,7 +59,62 @@ libimcv_la_SOURCES = \
os_info/os_info.h os_info/os_info.c \
pa_tnc/pa_tnc_attr.h \
pa_tnc/pa_tnc_msg.h pa_tnc/pa_tnc_msg.c \
- pa_tnc/pa_tnc_attr_manager.h pa_tnc/pa_tnc_attr_manager.c
+ pa_tnc/pa_tnc_attr_manager.h pa_tnc/pa_tnc_attr_manager.c \
+ pts/pts.h pts/pts.c \
+ pts/pts_error.h pts/pts_error.c \
+ pts/pts_pcr.h pts/pts_pcr.c \
+ pts/pts_proto_caps.h \
+ pts/pts_req_func_comp_evid.h \
+ pts/pts_simple_evid_final.h \
+ pts/pts_creds.h pts/pts_creds.c \
+ pts/pts_database.h pts/pts_database.c \
+ pts/pts_dh_group.h pts/pts_dh_group.c \
+ pts/pts_file_meas.h pts/pts_file_meas.c \
+ pts/pts_file_meta.h pts/pts_file_meta.c \
+ pts/pts_file_type.h pts/pts_file_type.c \
+ pts/pts_ima_bios_list.h pts/pts_ima_bios_list.c \
+ pts/pts_ima_event_list.h pts/pts_ima_event_list.c \
+ pts/pts_meas_algo.h pts/pts_meas_algo.c \
+ pts/components/pts_component.h \
+ pts/components/pts_component_manager.h pts/components/pts_component_manager.c \
+ pts/components/pts_comp_evidence.h pts/components/pts_comp_evidence.c \
+ pts/components/pts_comp_func_name.h pts/components/pts_comp_func_name.c \
+ pts/components/ita/ita_comp_func_name.h pts/components/ita/ita_comp_func_name.c \
+ pts/components/ita/ita_comp_ima.h pts/components/ita/ita_comp_ima.c \
+ pts/components/ita/ita_comp_tboot.h pts/components/ita/ita_comp_tboot.c \
+ pts/components/ita/ita_comp_tgrub.h pts/components/ita/ita_comp_tgrub.c \
+ pts/components/tcg/tcg_comp_func_name.h pts/components/tcg/tcg_comp_func_name.c \
+ seg/seg_contract.h seg/seg_contract.c \
+ seg/seg_contract_manager.h seg/seg_contract_manager.c \
+ seg/seg_env.h seg/seg_env.c \
+ swid/swid_error.h swid/swid_error.c \
+ swid/swid_inventory.h swid/swid_inventory.c \
+ swid/swid_tag.h swid/swid_tag.c \
+ swid/swid_tag_id.h swid/swid_tag_id.c \
+ tcg/tcg_attr.h tcg/tcg_attr.c \
+ tcg/pts/tcg_pts_attr_proto_caps.h tcg/pts/tcg_pts_attr_proto_caps.c \
+ tcg/pts/tcg_pts_attr_dh_nonce_params_req.h tcg/pts/tcg_pts_attr_dh_nonce_params_req.c \
+ tcg/pts/tcg_pts_attr_dh_nonce_params_resp.h tcg/pts/tcg_pts_attr_dh_nonce_params_resp.c \
+ tcg/pts/tcg_pts_attr_dh_nonce_finish.h tcg/pts/tcg_pts_attr_dh_nonce_finish.c \
+ tcg/pts/tcg_pts_attr_meas_algo.h tcg/pts/tcg_pts_attr_meas_algo.c \
+ tcg/pts/tcg_pts_attr_get_tpm_version_info.h tcg/pts/tcg_pts_attr_get_tpm_version_info.c \
+ tcg/pts/tcg_pts_attr_tpm_version_info.h tcg/pts/tcg_pts_attr_tpm_version_info.c \
+ tcg/pts/tcg_pts_attr_get_aik.h tcg/pts/tcg_pts_attr_get_aik.c \
+ tcg/pts/tcg_pts_attr_aik.h tcg/pts/tcg_pts_attr_aik.c \
+ tcg/pts/tcg_pts_attr_req_func_comp_evid.h tcg/pts/tcg_pts_attr_req_func_comp_evid.c \
+ tcg/pts/tcg_pts_attr_gen_attest_evid.h tcg/pts/tcg_pts_attr_gen_attest_evid.c \
+ tcg/pts/tcg_pts_attr_simple_comp_evid.h tcg/pts/tcg_pts_attr_simple_comp_evid.c \
+ tcg/pts/tcg_pts_attr_simple_evid_final.h tcg/pts/tcg_pts_attr_simple_evid_final.c \
+ tcg/pts/tcg_pts_attr_req_file_meas.h tcg/pts/tcg_pts_attr_req_file_meas.c \
+ tcg/pts/tcg_pts_attr_file_meas.h tcg/pts/tcg_pts_attr_file_meas.c \
+ tcg/pts/tcg_pts_attr_req_file_meta.h tcg/pts/tcg_pts_attr_req_file_meta.c \
+ tcg/pts/tcg_pts_attr_unix_file_meta.h tcg/pts/tcg_pts_attr_unix_file_meta.c \
+ tcg/seg/tcg_seg_attr_max_size.h tcg/seg/tcg_seg_attr_max_size.c \
+ tcg/seg/tcg_seg_attr_seg_env.h tcg/seg/tcg_seg_attr_seg_env.c \
+ tcg/seg/tcg_seg_attr_next_seg.h tcg/seg/tcg_seg_attr_next_seg.c \
+ tcg/swid/tcg_swid_attr_req.h tcg/swid/tcg_swid_attr_req.c \
+ tcg/swid/tcg_swid_attr_tag_id_inv.h tcg/swid/tcg_swid_attr_tag_id_inv.c \
+ tcg/swid/tcg_swid_attr_tag_inv.h tcg/swid/tcg_swid_attr_tag_inv.c
ipsec_SCRIPTS = imv/_imv_policy
EXTRA_DIST = imv/_imv_policy Android.mk
@@ -95,3 +155,45 @@ endif
if USE_IMV_OS
SUBDIRS += plugins/imv_os
endif
+
+if USE_IMC_ATTESTATION
+ SUBDIRS += plugins/imc_attestation
+endif
+
+if USE_IMV_ATTESTATION
+ SUBDIRS += plugins/imv_attestation
+endif
+
+if USE_IMC_SWID
+ SUBDIRS += plugins/imc_swid
+endif
+
+if USE_IMV_SWID
+ SUBDIRS += plugins/imv_swid
+endif
+
+TESTS = imcv_tests
+
+check_PROGRAMS = $(TESTS)
+
+imcv_tests_SOURCES = \
+ ita/ita_attr_command.c \
+ pa_tnc/pa_tnc_attr_manager.c \
+ seg/seg_env.c seg/seg_contract.c \
+ seg/seg_contract_manager.c \
+ suites/test_imcv_seg.c \
+ ietf/ietf_attr_pa_tnc_error.c \
+ tcg/seg/tcg_seg_attr_seg_env.c \
+ imcv.c imcv_tests.h imcv_tests.c
+
+imcv_tests_CFLAGS = \
+ -I$(top_srcdir)/src/libimcv \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libstrongswan/tests \
+ @COVERAGE_CFLAGS@
+
+imcv_tests_LDFLAGS = @COVERAGE_LDFLAGS@
+imcv_tests_LDADD = \
+ $(top_builddir)/src/libimcv/libimcv.la \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la \
+ $(top_builddir)/src/libstrongswan/tests/libtest.la
diff --git a/src/libimcv/Makefile.in b/src/libimcv/Makefile.in
index 4614dd607..239e62a17 100644
--- a/src/libimcv/Makefile.in
+++ b/src/libimcv/Makefile.in
@@ -81,14 +81,21 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
-@USE_WINDOWS_TRUE@am__append_1 = -lws2_32
+@USE_TROUSERS_TRUE@am__append_1 = -ltspi
+@USE_WINDOWS_TRUE@am__append_2 = -lws2_32
ipsec_PROGRAMS = imv_policy_manager$(EXEEXT)
-@USE_IMC_TEST_TRUE@am__append_2 = plugins/imc_test
-@USE_IMV_TEST_TRUE@am__append_3 = plugins/imv_test
-@USE_IMC_SCANNER_TRUE@am__append_4 = plugins/imc_scanner
-@USE_IMV_SCANNER_TRUE@am__append_5 = plugins/imv_scanner
-@USE_IMC_OS_TRUE@am__append_6 = plugins/imc_os
-@USE_IMV_OS_TRUE@am__append_7 = plugins/imv_os
+@USE_IMC_TEST_TRUE@am__append_3 = plugins/imc_test
+@USE_IMV_TEST_TRUE@am__append_4 = plugins/imv_test
+@USE_IMC_SCANNER_TRUE@am__append_5 = plugins/imc_scanner
+@USE_IMV_SCANNER_TRUE@am__append_6 = plugins/imv_scanner
+@USE_IMC_OS_TRUE@am__append_7 = plugins/imc_os
+@USE_IMV_OS_TRUE@am__append_8 = plugins/imv_os
+@USE_IMC_ATTESTATION_TRUE@am__append_9 = plugins/imc_attestation
+@USE_IMV_ATTESTATION_TRUE@am__append_10 = plugins/imv_attestation
+@USE_IMC_SWID_TRUE@am__append_11 = plugins/imc_swid
+@USE_IMV_SWID_TRUE@am__append_12 = plugins/imv_swid
+TESTS = imcv_tests$(EXEEXT)
+check_PROGRAMS = $(am__EXEEXT_1)
subdir = src/libimcv
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(top_srcdir)/depcomp $(dist_templates_DATA)
@@ -142,7 +149,8 @@ LTLIBRARIES = $(ipseclib_LTLIBRARIES)
am__DEPENDENCIES_1 =
libimcv_la_DEPENDENCIES = \
$(top_builddir)/src/libstrongswan/libstrongswan.la \
- $(top_builddir)/src/libtncif/libtncif.la $(am__DEPENDENCIES_1)
+ $(top_builddir)/src/libtncif/libtncif.la $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
am__dirstamp = $(am__leading_dot)dirstamp
am_libimcv_la_OBJECTS = imcv.lo imc/imc_agent.lo imc/imc_msg.lo \
imc/imc_os_info.lo imv/imv_agent.lo imv/imv_database.lo \
@@ -163,7 +171,42 @@ am_libimcv_la_OBJECTS = imcv.lo imc/imc_agent.lo imc/imc_msg.lo \
ita/ita_attr_get_settings.lo ita/ita_attr_settings.lo \
ita/ita_attr_angel.lo ita/ita_attr_device_id.lo \
os_info/os_info.lo pa_tnc/pa_tnc_msg.lo \
- pa_tnc/pa_tnc_attr_manager.lo
+ pa_tnc/pa_tnc_attr_manager.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_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 \
+ pts/components/ita/ita_comp_func_name.lo \
+ pts/components/ita/ita_comp_ima.lo \
+ pts/components/ita/ita_comp_tboot.lo \
+ pts/components/ita/ita_comp_tgrub.lo \
+ pts/components/tcg/tcg_comp_func_name.lo seg/seg_contract.lo \
+ seg/seg_contract_manager.lo seg/seg_env.lo swid/swid_error.lo \
+ swid/swid_inventory.lo swid/swid_tag.lo swid/swid_tag_id.lo \
+ tcg/tcg_attr.lo tcg/pts/tcg_pts_attr_proto_caps.lo \
+ tcg/pts/tcg_pts_attr_dh_nonce_params_req.lo \
+ tcg/pts/tcg_pts_attr_dh_nonce_params_resp.lo \
+ tcg/pts/tcg_pts_attr_dh_nonce_finish.lo \
+ tcg/pts/tcg_pts_attr_meas_algo.lo \
+ tcg/pts/tcg_pts_attr_get_tpm_version_info.lo \
+ tcg/pts/tcg_pts_attr_tpm_version_info.lo \
+ tcg/pts/tcg_pts_attr_get_aik.lo tcg/pts/tcg_pts_attr_aik.lo \
+ tcg/pts/tcg_pts_attr_req_func_comp_evid.lo \
+ tcg/pts/tcg_pts_attr_gen_attest_evid.lo \
+ tcg/pts/tcg_pts_attr_simple_comp_evid.lo \
+ tcg/pts/tcg_pts_attr_simple_evid_final.lo \
+ tcg/pts/tcg_pts_attr_req_file_meas.lo \
+ tcg/pts/tcg_pts_attr_file_meas.lo \
+ tcg/pts/tcg_pts_attr_req_file_meta.lo \
+ tcg/pts/tcg_pts_attr_unix_file_meta.lo \
+ tcg/seg/tcg_seg_attr_max_size.lo \
+ tcg/seg/tcg_seg_attr_seg_env.lo \
+ tcg/seg/tcg_seg_attr_next_seg.lo tcg/swid/tcg_swid_attr_req.lo \
+ tcg/swid/tcg_swid_attr_tag_id_inv.lo \
+ tcg/swid/tcg_swid_attr_tag_inv.lo
libimcv_la_OBJECTS = $(am_libimcv_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
@@ -172,7 +215,24 @@ am__v_lt_1 =
libimcv_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libimcv_la_LDFLAGS) $(LDFLAGS) -o $@
+am__EXEEXT_1 = imcv_tests$(EXEEXT)
PROGRAMS = $(ipsec_PROGRAMS)
+am_imcv_tests_OBJECTS = ita/imcv_tests-ita_attr_command.$(OBJEXT) \
+ pa_tnc/imcv_tests-pa_tnc_attr_manager.$(OBJEXT) \
+ seg/imcv_tests-seg_env.$(OBJEXT) \
+ seg/imcv_tests-seg_contract.$(OBJEXT) \
+ seg/imcv_tests-seg_contract_manager.$(OBJEXT) \
+ suites/imcv_tests-test_imcv_seg.$(OBJEXT) \
+ ietf/imcv_tests-ietf_attr_pa_tnc_error.$(OBJEXT) \
+ tcg/seg/imcv_tests-tcg_seg_attr_seg_env.$(OBJEXT) \
+ imcv_tests-imcv.$(OBJEXT) imcv_tests-imcv_tests.$(OBJEXT)
+imcv_tests_OBJECTS = $(am_imcv_tests_OBJECTS)
+imcv_tests_DEPENDENCIES = $(top_builddir)/src/libimcv/libimcv.la \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la \
+ $(top_builddir)/src/libstrongswan/tests/libtest.la
+imcv_tests_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(imcv_tests_CFLAGS) \
+ $(CFLAGS) $(imcv_tests_LDFLAGS) $(LDFLAGS) -o $@
am_imv_policy_manager_OBJECTS = imv/imv_policy_manager.$(OBJEXT) \
imv/imv_policy_manager_usage.$(OBJEXT)
imv_policy_manager_OBJECTS = $(am_imv_policy_manager_OBJECTS)
@@ -213,8 +273,10 @@ AM_V_CCLD = $(am__v_CCLD_@AM_V@)
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 =
-SOURCES = $(libimcv_la_SOURCES) $(imv_policy_manager_SOURCES)
-DIST_SOURCES = $(libimcv_la_SOURCES) $(imv_policy_manager_SOURCES)
+SOURCES = $(libimcv_la_SOURCES) $(imcv_tests_SOURCES) \
+ $(imv_policy_manager_SOURCES)
+DIST_SOURCES = $(libimcv_la_SOURCES) $(imcv_tests_SOURCES) \
+ $(imv_policy_manager_SOURCES)
RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
ctags-recursive dvi-recursive html-recursive info-recursive \
install-data-recursive install-dvi-recursive \
@@ -256,8 +318,32 @@ am__define_uniq_tagged_files = \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
+am__tty_colors_dummy = \
+ mgn= red= grn= lgn= blu= brg= std=; \
+ am__color_tests=no
+am__tty_colors = { \
+ $(am__tty_colors_dummy); \
+ if test "X$(AM_COLOR_TESTS)" = Xno; then \
+ am__color_tests=no; \
+ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \
+ am__color_tests=yes; \
+ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \
+ am__color_tests=yes; \
+ fi; \
+ if test $$am__color_tests = yes; then \
+ red=''; \
+ grn=''; \
+ lgn=''; \
+ blu=''; \
+ mgn=''; \
+ brg=''; \
+ std=''; \
+ fi; \
+}
DIST_SUBDIRS = . plugins/imc_test plugins/imv_test plugins/imc_scanner \
- plugins/imv_scanner plugins/imc_os plugins/imv_os
+ plugins/imv_scanner plugins/imc_os plugins/imv_os \
+ plugins/imc_attestation plugins/imv_attestation \
+ plugins/imc_swid plugins/imv_swid
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
am__relativize = \
dir0=`pwd`; \
@@ -315,6 +401,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -375,6 +462,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -440,6 +528,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -487,6 +577,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
@@ -498,7 +592,8 @@ xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
AM_CPPFLAGS = \
-I$(top_srcdir)/src/libstrongswan \
- -I$(top_srcdir)/src/libtncif
+ -I$(top_srcdir)/src/libtncif \
+ -DIPSEC_SCRIPT=\"${ipsec_script}\"
ipseclib_LTLIBRARIES = libimcv.la
libimcv_la_LDFLAGS = \
@@ -506,7 +601,8 @@ libimcv_la_LDFLAGS = \
libimcv_la_LIBADD = \
$(top_builddir)/src/libstrongswan/libstrongswan.la \
- $(top_builddir)/src/libtncif/libtncif.la $(am__append_1)
+ $(top_builddir)/src/libtncif/libtncif.la $(am__append_1) \
+ $(am__append_2)
libimcv_la_SOURCES = \
imcv.h imcv.c \
imc/imc_agent.h imc/imc_agent.c imc/imc_state.h \
@@ -546,7 +642,62 @@ libimcv_la_SOURCES = \
os_info/os_info.h os_info/os_info.c \
pa_tnc/pa_tnc_attr.h \
pa_tnc/pa_tnc_msg.h pa_tnc/pa_tnc_msg.c \
- pa_tnc/pa_tnc_attr_manager.h pa_tnc/pa_tnc_attr_manager.c
+ pa_tnc/pa_tnc_attr_manager.h pa_tnc/pa_tnc_attr_manager.c \
+ pts/pts.h pts/pts.c \
+ pts/pts_error.h pts/pts_error.c \
+ pts/pts_pcr.h pts/pts_pcr.c \
+ pts/pts_proto_caps.h \
+ pts/pts_req_func_comp_evid.h \
+ pts/pts_simple_evid_final.h \
+ pts/pts_creds.h pts/pts_creds.c \
+ pts/pts_database.h pts/pts_database.c \
+ pts/pts_dh_group.h pts/pts_dh_group.c \
+ pts/pts_file_meas.h pts/pts_file_meas.c \
+ pts/pts_file_meta.h pts/pts_file_meta.c \
+ pts/pts_file_type.h pts/pts_file_type.c \
+ pts/pts_ima_bios_list.h pts/pts_ima_bios_list.c \
+ pts/pts_ima_event_list.h pts/pts_ima_event_list.c \
+ pts/pts_meas_algo.h pts/pts_meas_algo.c \
+ pts/components/pts_component.h \
+ pts/components/pts_component_manager.h pts/components/pts_component_manager.c \
+ pts/components/pts_comp_evidence.h pts/components/pts_comp_evidence.c \
+ pts/components/pts_comp_func_name.h pts/components/pts_comp_func_name.c \
+ pts/components/ita/ita_comp_func_name.h pts/components/ita/ita_comp_func_name.c \
+ pts/components/ita/ita_comp_ima.h pts/components/ita/ita_comp_ima.c \
+ pts/components/ita/ita_comp_tboot.h pts/components/ita/ita_comp_tboot.c \
+ pts/components/ita/ita_comp_tgrub.h pts/components/ita/ita_comp_tgrub.c \
+ pts/components/tcg/tcg_comp_func_name.h pts/components/tcg/tcg_comp_func_name.c \
+ seg/seg_contract.h seg/seg_contract.c \
+ seg/seg_contract_manager.h seg/seg_contract_manager.c \
+ seg/seg_env.h seg/seg_env.c \
+ swid/swid_error.h swid/swid_error.c \
+ swid/swid_inventory.h swid/swid_inventory.c \
+ swid/swid_tag.h swid/swid_tag.c \
+ swid/swid_tag_id.h swid/swid_tag_id.c \
+ tcg/tcg_attr.h tcg/tcg_attr.c \
+ tcg/pts/tcg_pts_attr_proto_caps.h tcg/pts/tcg_pts_attr_proto_caps.c \
+ tcg/pts/tcg_pts_attr_dh_nonce_params_req.h tcg/pts/tcg_pts_attr_dh_nonce_params_req.c \
+ tcg/pts/tcg_pts_attr_dh_nonce_params_resp.h tcg/pts/tcg_pts_attr_dh_nonce_params_resp.c \
+ tcg/pts/tcg_pts_attr_dh_nonce_finish.h tcg/pts/tcg_pts_attr_dh_nonce_finish.c \
+ tcg/pts/tcg_pts_attr_meas_algo.h tcg/pts/tcg_pts_attr_meas_algo.c \
+ tcg/pts/tcg_pts_attr_get_tpm_version_info.h tcg/pts/tcg_pts_attr_get_tpm_version_info.c \
+ tcg/pts/tcg_pts_attr_tpm_version_info.h tcg/pts/tcg_pts_attr_tpm_version_info.c \
+ tcg/pts/tcg_pts_attr_get_aik.h tcg/pts/tcg_pts_attr_get_aik.c \
+ tcg/pts/tcg_pts_attr_aik.h tcg/pts/tcg_pts_attr_aik.c \
+ tcg/pts/tcg_pts_attr_req_func_comp_evid.h tcg/pts/tcg_pts_attr_req_func_comp_evid.c \
+ tcg/pts/tcg_pts_attr_gen_attest_evid.h tcg/pts/tcg_pts_attr_gen_attest_evid.c \
+ tcg/pts/tcg_pts_attr_simple_comp_evid.h tcg/pts/tcg_pts_attr_simple_comp_evid.c \
+ tcg/pts/tcg_pts_attr_simple_evid_final.h tcg/pts/tcg_pts_attr_simple_evid_final.c \
+ tcg/pts/tcg_pts_attr_req_file_meas.h tcg/pts/tcg_pts_attr_req_file_meas.c \
+ tcg/pts/tcg_pts_attr_file_meas.h tcg/pts/tcg_pts_attr_file_meas.c \
+ tcg/pts/tcg_pts_attr_req_file_meta.h tcg/pts/tcg_pts_attr_req_file_meta.c \
+ tcg/pts/tcg_pts_attr_unix_file_meta.h tcg/pts/tcg_pts_attr_unix_file_meta.c \
+ tcg/seg/tcg_seg_attr_max_size.h tcg/seg/tcg_seg_attr_max_size.c \
+ tcg/seg/tcg_seg_attr_seg_env.h tcg/seg/tcg_seg_attr_seg_env.c \
+ tcg/seg/tcg_seg_attr_next_seg.h tcg/seg/tcg_seg_attr_next_seg.c \
+ tcg/swid/tcg_swid_attr_req.h tcg/swid/tcg_swid_attr_req.c \
+ tcg/swid/tcg_swid_attr_tag_id_inv.h tcg/swid/tcg_swid_attr_tag_id_inv.c \
+ tcg/swid/tcg_swid_attr_tag_inv.h tcg/swid/tcg_swid_attr_tag_inv.c
ipsec_SCRIPTS = imv/_imv_policy
EXTRA_DIST = imv/_imv_policy Android.mk
@@ -560,8 +711,32 @@ imv_policy_manager_LDADD = \
$(top_builddir)/src/libstrongswan/libstrongswan.la
#imv/imv_policy_manager.o : $(top_builddir)/config.status
-SUBDIRS = . $(am__append_2) $(am__append_3) $(am__append_4) \
- $(am__append_5) $(am__append_6) $(am__append_7)
+SUBDIRS = . $(am__append_3) $(am__append_4) $(am__append_5) \
+ $(am__append_6) $(am__append_7) $(am__append_8) \
+ $(am__append_9) $(am__append_10) $(am__append_11) \
+ $(am__append_12)
+imcv_tests_SOURCES = \
+ ita/ita_attr_command.c \
+ pa_tnc/pa_tnc_attr_manager.c \
+ seg/seg_env.c seg/seg_contract.c \
+ seg/seg_contract_manager.c \
+ suites/test_imcv_seg.c \
+ ietf/ietf_attr_pa_tnc_error.c \
+ tcg/seg/tcg_seg_attr_seg_env.c \
+ imcv.c imcv_tests.h imcv_tests.c
+
+imcv_tests_CFLAGS = \
+ -I$(top_srcdir)/src/libimcv \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libstrongswan/tests \
+ @COVERAGE_CFLAGS@
+
+imcv_tests_LDFLAGS = @COVERAGE_LDFLAGS@
+imcv_tests_LDADD = \
+ $(top_builddir)/src/libimcv/libimcv.la \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la \
+ $(top_builddir)/src/libstrongswan/tests/libtest.la
+
all: all-recursive
.SUFFIXES:
@@ -728,9 +903,176 @@ pa_tnc/pa_tnc_msg.lo: pa_tnc/$(am__dirstamp) \
pa_tnc/$(DEPDIR)/$(am__dirstamp)
pa_tnc/pa_tnc_attr_manager.lo: pa_tnc/$(am__dirstamp) \
pa_tnc/$(DEPDIR)/$(am__dirstamp)
+pts/$(am__dirstamp):
+ @$(MKDIR_P) pts
+ @: > pts/$(am__dirstamp)
+pts/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) pts/$(DEPDIR)
+ @: > pts/$(DEPDIR)/$(am__dirstamp)
+pts/pts.lo: pts/$(am__dirstamp) pts/$(DEPDIR)/$(am__dirstamp)
+pts/pts_error.lo: pts/$(am__dirstamp) pts/$(DEPDIR)/$(am__dirstamp)
+pts/pts_pcr.lo: pts/$(am__dirstamp) pts/$(DEPDIR)/$(am__dirstamp)
+pts/pts_creds.lo: pts/$(am__dirstamp) pts/$(DEPDIR)/$(am__dirstamp)
+pts/pts_database.lo: pts/$(am__dirstamp) pts/$(DEPDIR)/$(am__dirstamp)
+pts/pts_dh_group.lo: pts/$(am__dirstamp) pts/$(DEPDIR)/$(am__dirstamp)
+pts/pts_file_meas.lo: pts/$(am__dirstamp) \
+ pts/$(DEPDIR)/$(am__dirstamp)
+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):
+ @$(MKDIR_P) pts/components
+ @: > pts/components/$(am__dirstamp)
+pts/components/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) pts/components/$(DEPDIR)
+ @: > pts/components/$(DEPDIR)/$(am__dirstamp)
+pts/components/pts_component_manager.lo: \
+ pts/components/$(am__dirstamp) \
+ pts/components/$(DEPDIR)/$(am__dirstamp)
+pts/components/pts_comp_evidence.lo: pts/components/$(am__dirstamp) \
+ pts/components/$(DEPDIR)/$(am__dirstamp)
+pts/components/pts_comp_func_name.lo: pts/components/$(am__dirstamp) \
+ pts/components/$(DEPDIR)/$(am__dirstamp)
+pts/components/ita/$(am__dirstamp):
+ @$(MKDIR_P) pts/components/ita
+ @: > pts/components/ita/$(am__dirstamp)
+pts/components/ita/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) pts/components/ita/$(DEPDIR)
+ @: > pts/components/ita/$(DEPDIR)/$(am__dirstamp)
+pts/components/ita/ita_comp_func_name.lo: \
+ pts/components/ita/$(am__dirstamp) \
+ pts/components/ita/$(DEPDIR)/$(am__dirstamp)
+pts/components/ita/ita_comp_ima.lo: \
+ pts/components/ita/$(am__dirstamp) \
+ pts/components/ita/$(DEPDIR)/$(am__dirstamp)
+pts/components/ita/ita_comp_tboot.lo: \
+ pts/components/ita/$(am__dirstamp) \
+ pts/components/ita/$(DEPDIR)/$(am__dirstamp)
+pts/components/ita/ita_comp_tgrub.lo: \
+ pts/components/ita/$(am__dirstamp) \
+ pts/components/ita/$(DEPDIR)/$(am__dirstamp)
+pts/components/tcg/$(am__dirstamp):
+ @$(MKDIR_P) pts/components/tcg
+ @: > pts/components/tcg/$(am__dirstamp)
+pts/components/tcg/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) pts/components/tcg/$(DEPDIR)
+ @: > pts/components/tcg/$(DEPDIR)/$(am__dirstamp)
+pts/components/tcg/tcg_comp_func_name.lo: \
+ pts/components/tcg/$(am__dirstamp) \
+ pts/components/tcg/$(DEPDIR)/$(am__dirstamp)
+seg/$(am__dirstamp):
+ @$(MKDIR_P) seg
+ @: > seg/$(am__dirstamp)
+seg/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) seg/$(DEPDIR)
+ @: > seg/$(DEPDIR)/$(am__dirstamp)
+seg/seg_contract.lo: seg/$(am__dirstamp) seg/$(DEPDIR)/$(am__dirstamp)
+seg/seg_contract_manager.lo: seg/$(am__dirstamp) \
+ seg/$(DEPDIR)/$(am__dirstamp)
+seg/seg_env.lo: seg/$(am__dirstamp) seg/$(DEPDIR)/$(am__dirstamp)
+swid/$(am__dirstamp):
+ @$(MKDIR_P) swid
+ @: > swid/$(am__dirstamp)
+swid/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) swid/$(DEPDIR)
+ @: > swid/$(DEPDIR)/$(am__dirstamp)
+swid/swid_error.lo: swid/$(am__dirstamp) \
+ swid/$(DEPDIR)/$(am__dirstamp)
+swid/swid_inventory.lo: swid/$(am__dirstamp) \
+ swid/$(DEPDIR)/$(am__dirstamp)
+swid/swid_tag.lo: swid/$(am__dirstamp) swid/$(DEPDIR)/$(am__dirstamp)
+swid/swid_tag_id.lo: swid/$(am__dirstamp) \
+ swid/$(DEPDIR)/$(am__dirstamp)
+tcg/$(am__dirstamp):
+ @$(MKDIR_P) tcg
+ @: > tcg/$(am__dirstamp)
+tcg/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) tcg/$(DEPDIR)
+ @: > tcg/$(DEPDIR)/$(am__dirstamp)
+tcg/tcg_attr.lo: tcg/$(am__dirstamp) tcg/$(DEPDIR)/$(am__dirstamp)
+tcg/pts/$(am__dirstamp):
+ @$(MKDIR_P) tcg/pts
+ @: > tcg/pts/$(am__dirstamp)
+tcg/pts/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) tcg/pts/$(DEPDIR)
+ @: > tcg/pts/$(DEPDIR)/$(am__dirstamp)
+tcg/pts/tcg_pts_attr_proto_caps.lo: tcg/pts/$(am__dirstamp) \
+ tcg/pts/$(DEPDIR)/$(am__dirstamp)
+tcg/pts/tcg_pts_attr_dh_nonce_params_req.lo: tcg/pts/$(am__dirstamp) \
+ tcg/pts/$(DEPDIR)/$(am__dirstamp)
+tcg/pts/tcg_pts_attr_dh_nonce_params_resp.lo: tcg/pts/$(am__dirstamp) \
+ tcg/pts/$(DEPDIR)/$(am__dirstamp)
+tcg/pts/tcg_pts_attr_dh_nonce_finish.lo: tcg/pts/$(am__dirstamp) \
+ tcg/pts/$(DEPDIR)/$(am__dirstamp)
+tcg/pts/tcg_pts_attr_meas_algo.lo: tcg/pts/$(am__dirstamp) \
+ tcg/pts/$(DEPDIR)/$(am__dirstamp)
+tcg/pts/tcg_pts_attr_get_tpm_version_info.lo: tcg/pts/$(am__dirstamp) \
+ tcg/pts/$(DEPDIR)/$(am__dirstamp)
+tcg/pts/tcg_pts_attr_tpm_version_info.lo: tcg/pts/$(am__dirstamp) \
+ tcg/pts/$(DEPDIR)/$(am__dirstamp)
+tcg/pts/tcg_pts_attr_get_aik.lo: tcg/pts/$(am__dirstamp) \
+ tcg/pts/$(DEPDIR)/$(am__dirstamp)
+tcg/pts/tcg_pts_attr_aik.lo: tcg/pts/$(am__dirstamp) \
+ tcg/pts/$(DEPDIR)/$(am__dirstamp)
+tcg/pts/tcg_pts_attr_req_func_comp_evid.lo: tcg/pts/$(am__dirstamp) \
+ tcg/pts/$(DEPDIR)/$(am__dirstamp)
+tcg/pts/tcg_pts_attr_gen_attest_evid.lo: tcg/pts/$(am__dirstamp) \
+ tcg/pts/$(DEPDIR)/$(am__dirstamp)
+tcg/pts/tcg_pts_attr_simple_comp_evid.lo: tcg/pts/$(am__dirstamp) \
+ tcg/pts/$(DEPDIR)/$(am__dirstamp)
+tcg/pts/tcg_pts_attr_simple_evid_final.lo: tcg/pts/$(am__dirstamp) \
+ tcg/pts/$(DEPDIR)/$(am__dirstamp)
+tcg/pts/tcg_pts_attr_req_file_meas.lo: tcg/pts/$(am__dirstamp) \
+ tcg/pts/$(DEPDIR)/$(am__dirstamp)
+tcg/pts/tcg_pts_attr_file_meas.lo: tcg/pts/$(am__dirstamp) \
+ tcg/pts/$(DEPDIR)/$(am__dirstamp)
+tcg/pts/tcg_pts_attr_req_file_meta.lo: tcg/pts/$(am__dirstamp) \
+ tcg/pts/$(DEPDIR)/$(am__dirstamp)
+tcg/pts/tcg_pts_attr_unix_file_meta.lo: tcg/pts/$(am__dirstamp) \
+ tcg/pts/$(DEPDIR)/$(am__dirstamp)
+tcg/seg/$(am__dirstamp):
+ @$(MKDIR_P) tcg/seg
+ @: > tcg/seg/$(am__dirstamp)
+tcg/seg/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) tcg/seg/$(DEPDIR)
+ @: > tcg/seg/$(DEPDIR)/$(am__dirstamp)
+tcg/seg/tcg_seg_attr_max_size.lo: tcg/seg/$(am__dirstamp) \
+ tcg/seg/$(DEPDIR)/$(am__dirstamp)
+tcg/seg/tcg_seg_attr_seg_env.lo: tcg/seg/$(am__dirstamp) \
+ tcg/seg/$(DEPDIR)/$(am__dirstamp)
+tcg/seg/tcg_seg_attr_next_seg.lo: tcg/seg/$(am__dirstamp) \
+ tcg/seg/$(DEPDIR)/$(am__dirstamp)
+tcg/swid/$(am__dirstamp):
+ @$(MKDIR_P) tcg/swid
+ @: > tcg/swid/$(am__dirstamp)
+tcg/swid/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) tcg/swid/$(DEPDIR)
+ @: > tcg/swid/$(DEPDIR)/$(am__dirstamp)
+tcg/swid/tcg_swid_attr_req.lo: tcg/swid/$(am__dirstamp) \
+ tcg/swid/$(DEPDIR)/$(am__dirstamp)
+tcg/swid/tcg_swid_attr_tag_id_inv.lo: tcg/swid/$(am__dirstamp) \
+ tcg/swid/$(DEPDIR)/$(am__dirstamp)
+tcg/swid/tcg_swid_attr_tag_inv.lo: tcg/swid/$(am__dirstamp) \
+ tcg/swid/$(DEPDIR)/$(am__dirstamp)
libimcv.la: $(libimcv_la_OBJECTS) $(libimcv_la_DEPENDENCIES) $(EXTRA_libimcv_la_DEPENDENCIES)
$(AM_V_CCLD)$(libimcv_la_LINK) -rpath $(ipseclibdir) $(libimcv_la_OBJECTS) $(libimcv_la_LIBADD) $(LIBS)
+
+clean-checkPROGRAMS:
+ @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
install-ipsecPROGRAMS: $(ipsec_PROGRAMS)
@$(NORMAL_INSTALL)
@list='$(ipsec_PROGRAMS)'; test -n "$(ipsecdir)" || list=; \
@@ -780,6 +1122,32 @@ clean-ipsecPROGRAMS:
list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
echo " rm -f" $$list; \
rm -f $$list
+ita/imcv_tests-ita_attr_command.$(OBJEXT): ita/$(am__dirstamp) \
+ ita/$(DEPDIR)/$(am__dirstamp)
+pa_tnc/imcv_tests-pa_tnc_attr_manager.$(OBJEXT): \
+ pa_tnc/$(am__dirstamp) pa_tnc/$(DEPDIR)/$(am__dirstamp)
+seg/imcv_tests-seg_env.$(OBJEXT): seg/$(am__dirstamp) \
+ seg/$(DEPDIR)/$(am__dirstamp)
+seg/imcv_tests-seg_contract.$(OBJEXT): seg/$(am__dirstamp) \
+ seg/$(DEPDIR)/$(am__dirstamp)
+seg/imcv_tests-seg_contract_manager.$(OBJEXT): seg/$(am__dirstamp) \
+ seg/$(DEPDIR)/$(am__dirstamp)
+suites/$(am__dirstamp):
+ @$(MKDIR_P) suites
+ @: > suites/$(am__dirstamp)
+suites/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) suites/$(DEPDIR)
+ @: > suites/$(DEPDIR)/$(am__dirstamp)
+suites/imcv_tests-test_imcv_seg.$(OBJEXT): suites/$(am__dirstamp) \
+ suites/$(DEPDIR)/$(am__dirstamp)
+ietf/imcv_tests-ietf_attr_pa_tnc_error.$(OBJEXT): \
+ ietf/$(am__dirstamp) ietf/$(DEPDIR)/$(am__dirstamp)
+tcg/seg/imcv_tests-tcg_seg_attr_seg_env.$(OBJEXT): \
+ tcg/seg/$(am__dirstamp) tcg/seg/$(DEPDIR)/$(am__dirstamp)
+
+imcv_tests$(EXEEXT): $(imcv_tests_OBJECTS) $(imcv_tests_DEPENDENCIES) $(EXTRA_imcv_tests_DEPENDENCIES)
+ @rm -f imcv_tests$(EXEEXT)
+ $(AM_V_CCLD)$(imcv_tests_LINK) $(imcv_tests_OBJECTS) $(imcv_tests_LDADD) $(LIBS)
imv/imv_policy_manager.$(OBJEXT): imv/$(am__dirstamp) \
imv/$(DEPDIR)/$(am__dirstamp)
imv/imv_policy_manager_usage.$(OBJEXT): imv/$(am__dirstamp) \
@@ -838,11 +1206,34 @@ mostlyclean-compile:
-rm -f os_info/*.lo
-rm -f pa_tnc/*.$(OBJEXT)
-rm -f pa_tnc/*.lo
+ -rm -f pts/*.$(OBJEXT)
+ -rm -f pts/*.lo
+ -rm -f pts/components/*.$(OBJEXT)
+ -rm -f pts/components/*.lo
+ -rm -f pts/components/ita/*.$(OBJEXT)
+ -rm -f pts/components/ita/*.lo
+ -rm -f pts/components/tcg/*.$(OBJEXT)
+ -rm -f pts/components/tcg/*.lo
+ -rm -f seg/*.$(OBJEXT)
+ -rm -f seg/*.lo
+ -rm -f suites/*.$(OBJEXT)
+ -rm -f swid/*.$(OBJEXT)
+ -rm -f swid/*.lo
+ -rm -f tcg/*.$(OBJEXT)
+ -rm -f tcg/*.lo
+ -rm -f tcg/pts/*.$(OBJEXT)
+ -rm -f tcg/pts/*.lo
+ -rm -f tcg/seg/*.$(OBJEXT)
+ -rm -f tcg/seg/*.lo
+ -rm -f tcg/swid/*.$(OBJEXT)
+ -rm -f tcg/swid/*.lo
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imcv.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imcv_tests-imcv.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imcv_tests-imcv_tests.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ietf/$(DEPDIR)/ietf_attr.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ietf/$(DEPDIR)/ietf_attr_assess_result.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ietf/$(DEPDIR)/ietf_attr_attr_request.Plo@am__quote@
@@ -856,6 +1247,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@ietf/$(DEPDIR)/ietf_attr_product_info.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ietf/$(DEPDIR)/ietf_attr_remediation_instr.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ietf/$(DEPDIR)/ietf_attr_string_version.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@ietf/$(DEPDIR)/imcv_tests-ietf_attr_pa_tnc_error.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@imc/$(DEPDIR)/imc_agent.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@imc/$(DEPDIR)/imc_msg.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@imc/$(DEPDIR)/imc_os_info.Plo@am__quote@
@@ -871,6 +1263,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@imv/$(DEPDIR)/imv_session.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@imv/$(DEPDIR)/imv_session_manager.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@imv/$(DEPDIR)/imv_workitem.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@ita/$(DEPDIR)/imcv_tests-ita_attr_command.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ita/$(DEPDIR)/ita_attr.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ita/$(DEPDIR)/ita_attr_angel.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ita/$(DEPDIR)/ita_attr_command.Plo@am__quote@
@@ -879,8 +1272,65 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@ita/$(DEPDIR)/ita_attr_get_settings.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ita/$(DEPDIR)/ita_attr_settings.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@os_info/$(DEPDIR)/os_info.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@pa_tnc/$(DEPDIR)/imcv_tests-pa_tnc_attr_manager.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@pa_tnc/$(DEPDIR)/pa_tnc_attr_manager.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@pa_tnc/$(DEPDIR)/pa_tnc_msg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@pts/$(DEPDIR)/pts.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@pts/$(DEPDIR)/pts_creds.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@pts/$(DEPDIR)/pts_database.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@pts/$(DEPDIR)/pts_dh_group.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@pts/$(DEPDIR)/pts_error.Plo@am__quote@
+@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@
+@AMDEP_TRUE@@am__include@ @am__quote@pts/components/$(DEPDIR)/pts_comp_func_name.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@pts/components/$(DEPDIR)/pts_component_manager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@pts/components/ita/$(DEPDIR)/ita_comp_func_name.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@pts/components/ita/$(DEPDIR)/ita_comp_ima.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@pts/components/ita/$(DEPDIR)/ita_comp_tboot.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@pts/components/ita/$(DEPDIR)/ita_comp_tgrub.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@pts/components/tcg/$(DEPDIR)/tcg_comp_func_name.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@seg/$(DEPDIR)/imcv_tests-seg_contract.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@seg/$(DEPDIR)/imcv_tests-seg_contract_manager.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@seg/$(DEPDIR)/imcv_tests-seg_env.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@seg/$(DEPDIR)/seg_contract.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@seg/$(DEPDIR)/seg_contract_manager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@seg/$(DEPDIR)/seg_env.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@suites/$(DEPDIR)/imcv_tests-test_imcv_seg.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@swid/$(DEPDIR)/swid_error.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@swid/$(DEPDIR)/swid_inventory.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@swid/$(DEPDIR)/swid_tag.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@swid/$(DEPDIR)/swid_tag_id.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@tcg/$(DEPDIR)/tcg_attr.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@tcg/pts/$(DEPDIR)/tcg_pts_attr_aik.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@tcg/pts/$(DEPDIR)/tcg_pts_attr_dh_nonce_finish.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@tcg/pts/$(DEPDIR)/tcg_pts_attr_dh_nonce_params_req.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@tcg/pts/$(DEPDIR)/tcg_pts_attr_dh_nonce_params_resp.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@tcg/pts/$(DEPDIR)/tcg_pts_attr_file_meas.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@tcg/pts/$(DEPDIR)/tcg_pts_attr_gen_attest_evid.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@tcg/pts/$(DEPDIR)/tcg_pts_attr_get_aik.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@tcg/pts/$(DEPDIR)/tcg_pts_attr_get_tpm_version_info.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@tcg/pts/$(DEPDIR)/tcg_pts_attr_meas_algo.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@tcg/pts/$(DEPDIR)/tcg_pts_attr_proto_caps.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@tcg/pts/$(DEPDIR)/tcg_pts_attr_req_file_meas.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@tcg/pts/$(DEPDIR)/tcg_pts_attr_req_file_meta.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@tcg/pts/$(DEPDIR)/tcg_pts_attr_req_func_comp_evid.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@tcg/pts/$(DEPDIR)/tcg_pts_attr_simple_comp_evid.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@tcg/pts/$(DEPDIR)/tcg_pts_attr_simple_evid_final.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@tcg/pts/$(DEPDIR)/tcg_pts_attr_tpm_version_info.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@tcg/pts/$(DEPDIR)/tcg_pts_attr_unix_file_meta.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@tcg/seg/$(DEPDIR)/imcv_tests-tcg_seg_attr_seg_env.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@tcg/seg/$(DEPDIR)/tcg_seg_attr_max_size.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@tcg/seg/$(DEPDIR)/tcg_seg_attr_next_seg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@tcg/seg/$(DEPDIR)/tcg_seg_attr_seg_env.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@tcg/swid/$(DEPDIR)/tcg_swid_attr_req.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@tcg/swid/$(DEPDIR)/tcg_swid_attr_tag_id_inv.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@tcg/swid/$(DEPDIR)/tcg_swid_attr_tag_inv.Plo@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
@@ -906,6 +1356,146 @@ distclean-compile:
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+ita/imcv_tests-ita_attr_command.o: ita/ita_attr_command.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(imcv_tests_CFLAGS) $(CFLAGS) -MT ita/imcv_tests-ita_attr_command.o -MD -MP -MF ita/$(DEPDIR)/imcv_tests-ita_attr_command.Tpo -c -o ita/imcv_tests-ita_attr_command.o `test -f 'ita/ita_attr_command.c' || echo '$(srcdir)/'`ita/ita_attr_command.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ita/$(DEPDIR)/imcv_tests-ita_attr_command.Tpo ita/$(DEPDIR)/imcv_tests-ita_attr_command.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ita/ita_attr_command.c' object='ita/imcv_tests-ita_attr_command.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(imcv_tests_CFLAGS) $(CFLAGS) -c -o ita/imcv_tests-ita_attr_command.o `test -f 'ita/ita_attr_command.c' || echo '$(srcdir)/'`ita/ita_attr_command.c
+
+ita/imcv_tests-ita_attr_command.obj: ita/ita_attr_command.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(imcv_tests_CFLAGS) $(CFLAGS) -MT ita/imcv_tests-ita_attr_command.obj -MD -MP -MF ita/$(DEPDIR)/imcv_tests-ita_attr_command.Tpo -c -o ita/imcv_tests-ita_attr_command.obj `if test -f 'ita/ita_attr_command.c'; then $(CYGPATH_W) 'ita/ita_attr_command.c'; else $(CYGPATH_W) '$(srcdir)/ita/ita_attr_command.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ita/$(DEPDIR)/imcv_tests-ita_attr_command.Tpo ita/$(DEPDIR)/imcv_tests-ita_attr_command.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ita/ita_attr_command.c' object='ita/imcv_tests-ita_attr_command.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(imcv_tests_CFLAGS) $(CFLAGS) -c -o ita/imcv_tests-ita_attr_command.obj `if test -f 'ita/ita_attr_command.c'; then $(CYGPATH_W) 'ita/ita_attr_command.c'; else $(CYGPATH_W) '$(srcdir)/ita/ita_attr_command.c'; fi`
+
+pa_tnc/imcv_tests-pa_tnc_attr_manager.o: pa_tnc/pa_tnc_attr_manager.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(imcv_tests_CFLAGS) $(CFLAGS) -MT pa_tnc/imcv_tests-pa_tnc_attr_manager.o -MD -MP -MF pa_tnc/$(DEPDIR)/imcv_tests-pa_tnc_attr_manager.Tpo -c -o pa_tnc/imcv_tests-pa_tnc_attr_manager.o `test -f 'pa_tnc/pa_tnc_attr_manager.c' || echo '$(srcdir)/'`pa_tnc/pa_tnc_attr_manager.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) pa_tnc/$(DEPDIR)/imcv_tests-pa_tnc_attr_manager.Tpo pa_tnc/$(DEPDIR)/imcv_tests-pa_tnc_attr_manager.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pa_tnc/pa_tnc_attr_manager.c' object='pa_tnc/imcv_tests-pa_tnc_attr_manager.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(imcv_tests_CFLAGS) $(CFLAGS) -c -o pa_tnc/imcv_tests-pa_tnc_attr_manager.o `test -f 'pa_tnc/pa_tnc_attr_manager.c' || echo '$(srcdir)/'`pa_tnc/pa_tnc_attr_manager.c
+
+pa_tnc/imcv_tests-pa_tnc_attr_manager.obj: pa_tnc/pa_tnc_attr_manager.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(imcv_tests_CFLAGS) $(CFLAGS) -MT pa_tnc/imcv_tests-pa_tnc_attr_manager.obj -MD -MP -MF pa_tnc/$(DEPDIR)/imcv_tests-pa_tnc_attr_manager.Tpo -c -o pa_tnc/imcv_tests-pa_tnc_attr_manager.obj `if test -f 'pa_tnc/pa_tnc_attr_manager.c'; then $(CYGPATH_W) 'pa_tnc/pa_tnc_attr_manager.c'; else $(CYGPATH_W) '$(srcdir)/pa_tnc/pa_tnc_attr_manager.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) pa_tnc/$(DEPDIR)/imcv_tests-pa_tnc_attr_manager.Tpo pa_tnc/$(DEPDIR)/imcv_tests-pa_tnc_attr_manager.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pa_tnc/pa_tnc_attr_manager.c' object='pa_tnc/imcv_tests-pa_tnc_attr_manager.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(imcv_tests_CFLAGS) $(CFLAGS) -c -o pa_tnc/imcv_tests-pa_tnc_attr_manager.obj `if test -f 'pa_tnc/pa_tnc_attr_manager.c'; then $(CYGPATH_W) 'pa_tnc/pa_tnc_attr_manager.c'; else $(CYGPATH_W) '$(srcdir)/pa_tnc/pa_tnc_attr_manager.c'; fi`
+
+seg/imcv_tests-seg_env.o: seg/seg_env.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(imcv_tests_CFLAGS) $(CFLAGS) -MT seg/imcv_tests-seg_env.o -MD -MP -MF seg/$(DEPDIR)/imcv_tests-seg_env.Tpo -c -o seg/imcv_tests-seg_env.o `test -f 'seg/seg_env.c' || echo '$(srcdir)/'`seg/seg_env.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) seg/$(DEPDIR)/imcv_tests-seg_env.Tpo seg/$(DEPDIR)/imcv_tests-seg_env.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='seg/seg_env.c' object='seg/imcv_tests-seg_env.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(imcv_tests_CFLAGS) $(CFLAGS) -c -o seg/imcv_tests-seg_env.o `test -f 'seg/seg_env.c' || echo '$(srcdir)/'`seg/seg_env.c
+
+seg/imcv_tests-seg_env.obj: seg/seg_env.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(imcv_tests_CFLAGS) $(CFLAGS) -MT seg/imcv_tests-seg_env.obj -MD -MP -MF seg/$(DEPDIR)/imcv_tests-seg_env.Tpo -c -o seg/imcv_tests-seg_env.obj `if test -f 'seg/seg_env.c'; then $(CYGPATH_W) 'seg/seg_env.c'; else $(CYGPATH_W) '$(srcdir)/seg/seg_env.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) seg/$(DEPDIR)/imcv_tests-seg_env.Tpo seg/$(DEPDIR)/imcv_tests-seg_env.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='seg/seg_env.c' object='seg/imcv_tests-seg_env.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(imcv_tests_CFLAGS) $(CFLAGS) -c -o seg/imcv_tests-seg_env.obj `if test -f 'seg/seg_env.c'; then $(CYGPATH_W) 'seg/seg_env.c'; else $(CYGPATH_W) '$(srcdir)/seg/seg_env.c'; fi`
+
+seg/imcv_tests-seg_contract.o: seg/seg_contract.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(imcv_tests_CFLAGS) $(CFLAGS) -MT seg/imcv_tests-seg_contract.o -MD -MP -MF seg/$(DEPDIR)/imcv_tests-seg_contract.Tpo -c -o seg/imcv_tests-seg_contract.o `test -f 'seg/seg_contract.c' || echo '$(srcdir)/'`seg/seg_contract.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) seg/$(DEPDIR)/imcv_tests-seg_contract.Tpo seg/$(DEPDIR)/imcv_tests-seg_contract.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='seg/seg_contract.c' object='seg/imcv_tests-seg_contract.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(imcv_tests_CFLAGS) $(CFLAGS) -c -o seg/imcv_tests-seg_contract.o `test -f 'seg/seg_contract.c' || echo '$(srcdir)/'`seg/seg_contract.c
+
+seg/imcv_tests-seg_contract.obj: seg/seg_contract.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(imcv_tests_CFLAGS) $(CFLAGS) -MT seg/imcv_tests-seg_contract.obj -MD -MP -MF seg/$(DEPDIR)/imcv_tests-seg_contract.Tpo -c -o seg/imcv_tests-seg_contract.obj `if test -f 'seg/seg_contract.c'; then $(CYGPATH_W) 'seg/seg_contract.c'; else $(CYGPATH_W) '$(srcdir)/seg/seg_contract.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) seg/$(DEPDIR)/imcv_tests-seg_contract.Tpo seg/$(DEPDIR)/imcv_tests-seg_contract.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='seg/seg_contract.c' object='seg/imcv_tests-seg_contract.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(imcv_tests_CFLAGS) $(CFLAGS) -c -o seg/imcv_tests-seg_contract.obj `if test -f 'seg/seg_contract.c'; then $(CYGPATH_W) 'seg/seg_contract.c'; else $(CYGPATH_W) '$(srcdir)/seg/seg_contract.c'; fi`
+
+seg/imcv_tests-seg_contract_manager.o: seg/seg_contract_manager.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(imcv_tests_CFLAGS) $(CFLAGS) -MT seg/imcv_tests-seg_contract_manager.o -MD -MP -MF seg/$(DEPDIR)/imcv_tests-seg_contract_manager.Tpo -c -o seg/imcv_tests-seg_contract_manager.o `test -f 'seg/seg_contract_manager.c' || echo '$(srcdir)/'`seg/seg_contract_manager.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) seg/$(DEPDIR)/imcv_tests-seg_contract_manager.Tpo seg/$(DEPDIR)/imcv_tests-seg_contract_manager.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='seg/seg_contract_manager.c' object='seg/imcv_tests-seg_contract_manager.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(imcv_tests_CFLAGS) $(CFLAGS) -c -o seg/imcv_tests-seg_contract_manager.o `test -f 'seg/seg_contract_manager.c' || echo '$(srcdir)/'`seg/seg_contract_manager.c
+
+seg/imcv_tests-seg_contract_manager.obj: seg/seg_contract_manager.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(imcv_tests_CFLAGS) $(CFLAGS) -MT seg/imcv_tests-seg_contract_manager.obj -MD -MP -MF seg/$(DEPDIR)/imcv_tests-seg_contract_manager.Tpo -c -o seg/imcv_tests-seg_contract_manager.obj `if test -f 'seg/seg_contract_manager.c'; then $(CYGPATH_W) 'seg/seg_contract_manager.c'; else $(CYGPATH_W) '$(srcdir)/seg/seg_contract_manager.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) seg/$(DEPDIR)/imcv_tests-seg_contract_manager.Tpo seg/$(DEPDIR)/imcv_tests-seg_contract_manager.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='seg/seg_contract_manager.c' object='seg/imcv_tests-seg_contract_manager.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(imcv_tests_CFLAGS) $(CFLAGS) -c -o seg/imcv_tests-seg_contract_manager.obj `if test -f 'seg/seg_contract_manager.c'; then $(CYGPATH_W) 'seg/seg_contract_manager.c'; else $(CYGPATH_W) '$(srcdir)/seg/seg_contract_manager.c'; fi`
+
+suites/imcv_tests-test_imcv_seg.o: suites/test_imcv_seg.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(imcv_tests_CFLAGS) $(CFLAGS) -MT suites/imcv_tests-test_imcv_seg.o -MD -MP -MF suites/$(DEPDIR)/imcv_tests-test_imcv_seg.Tpo -c -o suites/imcv_tests-test_imcv_seg.o `test -f 'suites/test_imcv_seg.c' || echo '$(srcdir)/'`suites/test_imcv_seg.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) suites/$(DEPDIR)/imcv_tests-test_imcv_seg.Tpo suites/$(DEPDIR)/imcv_tests-test_imcv_seg.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='suites/test_imcv_seg.c' object='suites/imcv_tests-test_imcv_seg.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(imcv_tests_CFLAGS) $(CFLAGS) -c -o suites/imcv_tests-test_imcv_seg.o `test -f 'suites/test_imcv_seg.c' || echo '$(srcdir)/'`suites/test_imcv_seg.c
+
+suites/imcv_tests-test_imcv_seg.obj: suites/test_imcv_seg.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(imcv_tests_CFLAGS) $(CFLAGS) -MT suites/imcv_tests-test_imcv_seg.obj -MD -MP -MF suites/$(DEPDIR)/imcv_tests-test_imcv_seg.Tpo -c -o suites/imcv_tests-test_imcv_seg.obj `if test -f 'suites/test_imcv_seg.c'; then $(CYGPATH_W) 'suites/test_imcv_seg.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_imcv_seg.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) suites/$(DEPDIR)/imcv_tests-test_imcv_seg.Tpo suites/$(DEPDIR)/imcv_tests-test_imcv_seg.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='suites/test_imcv_seg.c' object='suites/imcv_tests-test_imcv_seg.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(imcv_tests_CFLAGS) $(CFLAGS) -c -o suites/imcv_tests-test_imcv_seg.obj `if test -f 'suites/test_imcv_seg.c'; then $(CYGPATH_W) 'suites/test_imcv_seg.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_imcv_seg.c'; fi`
+
+ietf/imcv_tests-ietf_attr_pa_tnc_error.o: ietf/ietf_attr_pa_tnc_error.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(imcv_tests_CFLAGS) $(CFLAGS) -MT ietf/imcv_tests-ietf_attr_pa_tnc_error.o -MD -MP -MF ietf/$(DEPDIR)/imcv_tests-ietf_attr_pa_tnc_error.Tpo -c -o ietf/imcv_tests-ietf_attr_pa_tnc_error.o `test -f 'ietf/ietf_attr_pa_tnc_error.c' || echo '$(srcdir)/'`ietf/ietf_attr_pa_tnc_error.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ietf/$(DEPDIR)/imcv_tests-ietf_attr_pa_tnc_error.Tpo ietf/$(DEPDIR)/imcv_tests-ietf_attr_pa_tnc_error.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ietf/ietf_attr_pa_tnc_error.c' object='ietf/imcv_tests-ietf_attr_pa_tnc_error.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(imcv_tests_CFLAGS) $(CFLAGS) -c -o ietf/imcv_tests-ietf_attr_pa_tnc_error.o `test -f 'ietf/ietf_attr_pa_tnc_error.c' || echo '$(srcdir)/'`ietf/ietf_attr_pa_tnc_error.c
+
+ietf/imcv_tests-ietf_attr_pa_tnc_error.obj: ietf/ietf_attr_pa_tnc_error.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(imcv_tests_CFLAGS) $(CFLAGS) -MT ietf/imcv_tests-ietf_attr_pa_tnc_error.obj -MD -MP -MF ietf/$(DEPDIR)/imcv_tests-ietf_attr_pa_tnc_error.Tpo -c -o ietf/imcv_tests-ietf_attr_pa_tnc_error.obj `if test -f 'ietf/ietf_attr_pa_tnc_error.c'; then $(CYGPATH_W) 'ietf/ietf_attr_pa_tnc_error.c'; else $(CYGPATH_W) '$(srcdir)/ietf/ietf_attr_pa_tnc_error.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ietf/$(DEPDIR)/imcv_tests-ietf_attr_pa_tnc_error.Tpo ietf/$(DEPDIR)/imcv_tests-ietf_attr_pa_tnc_error.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ietf/ietf_attr_pa_tnc_error.c' object='ietf/imcv_tests-ietf_attr_pa_tnc_error.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(imcv_tests_CFLAGS) $(CFLAGS) -c -o ietf/imcv_tests-ietf_attr_pa_tnc_error.obj `if test -f 'ietf/ietf_attr_pa_tnc_error.c'; then $(CYGPATH_W) 'ietf/ietf_attr_pa_tnc_error.c'; else $(CYGPATH_W) '$(srcdir)/ietf/ietf_attr_pa_tnc_error.c'; fi`
+
+tcg/seg/imcv_tests-tcg_seg_attr_seg_env.o: tcg/seg/tcg_seg_attr_seg_env.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(imcv_tests_CFLAGS) $(CFLAGS) -MT tcg/seg/imcv_tests-tcg_seg_attr_seg_env.o -MD -MP -MF tcg/seg/$(DEPDIR)/imcv_tests-tcg_seg_attr_seg_env.Tpo -c -o tcg/seg/imcv_tests-tcg_seg_attr_seg_env.o `test -f 'tcg/seg/tcg_seg_attr_seg_env.c' || echo '$(srcdir)/'`tcg/seg/tcg_seg_attr_seg_env.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tcg/seg/$(DEPDIR)/imcv_tests-tcg_seg_attr_seg_env.Tpo tcg/seg/$(DEPDIR)/imcv_tests-tcg_seg_attr_seg_env.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tcg/seg/tcg_seg_attr_seg_env.c' object='tcg/seg/imcv_tests-tcg_seg_attr_seg_env.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(imcv_tests_CFLAGS) $(CFLAGS) -c -o tcg/seg/imcv_tests-tcg_seg_attr_seg_env.o `test -f 'tcg/seg/tcg_seg_attr_seg_env.c' || echo '$(srcdir)/'`tcg/seg/tcg_seg_attr_seg_env.c
+
+tcg/seg/imcv_tests-tcg_seg_attr_seg_env.obj: tcg/seg/tcg_seg_attr_seg_env.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(imcv_tests_CFLAGS) $(CFLAGS) -MT tcg/seg/imcv_tests-tcg_seg_attr_seg_env.obj -MD -MP -MF tcg/seg/$(DEPDIR)/imcv_tests-tcg_seg_attr_seg_env.Tpo -c -o tcg/seg/imcv_tests-tcg_seg_attr_seg_env.obj `if test -f 'tcg/seg/tcg_seg_attr_seg_env.c'; then $(CYGPATH_W) 'tcg/seg/tcg_seg_attr_seg_env.c'; else $(CYGPATH_W) '$(srcdir)/tcg/seg/tcg_seg_attr_seg_env.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tcg/seg/$(DEPDIR)/imcv_tests-tcg_seg_attr_seg_env.Tpo tcg/seg/$(DEPDIR)/imcv_tests-tcg_seg_attr_seg_env.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tcg/seg/tcg_seg_attr_seg_env.c' object='tcg/seg/imcv_tests-tcg_seg_attr_seg_env.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(imcv_tests_CFLAGS) $(CFLAGS) -c -o tcg/seg/imcv_tests-tcg_seg_attr_seg_env.obj `if test -f 'tcg/seg/tcg_seg_attr_seg_env.c'; then $(CYGPATH_W) 'tcg/seg/tcg_seg_attr_seg_env.c'; else $(CYGPATH_W) '$(srcdir)/tcg/seg/tcg_seg_attr_seg_env.c'; fi`
+
+imcv_tests-imcv.o: imcv.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(imcv_tests_CFLAGS) $(CFLAGS) -MT imcv_tests-imcv.o -MD -MP -MF $(DEPDIR)/imcv_tests-imcv.Tpo -c -o imcv_tests-imcv.o `test -f 'imcv.c' || echo '$(srcdir)/'`imcv.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/imcv_tests-imcv.Tpo $(DEPDIR)/imcv_tests-imcv.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='imcv.c' object='imcv_tests-imcv.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(imcv_tests_CFLAGS) $(CFLAGS) -c -o imcv_tests-imcv.o `test -f 'imcv.c' || echo '$(srcdir)/'`imcv.c
+
+imcv_tests-imcv.obj: imcv.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(imcv_tests_CFLAGS) $(CFLAGS) -MT imcv_tests-imcv.obj -MD -MP -MF $(DEPDIR)/imcv_tests-imcv.Tpo -c -o imcv_tests-imcv.obj `if test -f 'imcv.c'; then $(CYGPATH_W) 'imcv.c'; else $(CYGPATH_W) '$(srcdir)/imcv.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/imcv_tests-imcv.Tpo $(DEPDIR)/imcv_tests-imcv.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='imcv.c' object='imcv_tests-imcv.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(imcv_tests_CFLAGS) $(CFLAGS) -c -o imcv_tests-imcv.obj `if test -f 'imcv.c'; then $(CYGPATH_W) 'imcv.c'; else $(CYGPATH_W) '$(srcdir)/imcv.c'; fi`
+
+imcv_tests-imcv_tests.o: imcv_tests.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(imcv_tests_CFLAGS) $(CFLAGS) -MT imcv_tests-imcv_tests.o -MD -MP -MF $(DEPDIR)/imcv_tests-imcv_tests.Tpo -c -o imcv_tests-imcv_tests.o `test -f 'imcv_tests.c' || echo '$(srcdir)/'`imcv_tests.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/imcv_tests-imcv_tests.Tpo $(DEPDIR)/imcv_tests-imcv_tests.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='imcv_tests.c' object='imcv_tests-imcv_tests.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(imcv_tests_CFLAGS) $(CFLAGS) -c -o imcv_tests-imcv_tests.o `test -f 'imcv_tests.c' || echo '$(srcdir)/'`imcv_tests.c
+
+imcv_tests-imcv_tests.obj: imcv_tests.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(imcv_tests_CFLAGS) $(CFLAGS) -MT imcv_tests-imcv_tests.obj -MD -MP -MF $(DEPDIR)/imcv_tests-imcv_tests.Tpo -c -o imcv_tests-imcv_tests.obj `if test -f 'imcv_tests.c'; then $(CYGPATH_W) 'imcv_tests.c'; else $(CYGPATH_W) '$(srcdir)/imcv_tests.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/imcv_tests-imcv_tests.Tpo $(DEPDIR)/imcv_tests-imcv_tests.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='imcv_tests.c' object='imcv_tests-imcv_tests.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(imcv_tests_CFLAGS) $(CFLAGS) -c -o imcv_tests-imcv_tests.obj `if test -f 'imcv_tests.c'; then $(CYGPATH_W) 'imcv_tests.c'; else $(CYGPATH_W) '$(srcdir)/imcv_tests.c'; fi`
+
mostlyclean-libtool:
-rm -f *.lo
@@ -917,6 +1507,16 @@ clean-libtool:
-rm -rf ita/.libs ita/_libs
-rm -rf os_info/.libs os_info/_libs
-rm -rf pa_tnc/.libs pa_tnc/_libs
+ -rm -rf pts/.libs pts/_libs
+ -rm -rf pts/components/.libs pts/components/_libs
+ -rm -rf pts/components/ita/.libs pts/components/ita/_libs
+ -rm -rf pts/components/tcg/.libs pts/components/tcg/_libs
+ -rm -rf seg/.libs seg/_libs
+ -rm -rf swid/.libs swid/_libs
+ -rm -rf tcg/.libs tcg/_libs
+ -rm -rf tcg/pts/.libs tcg/pts/_libs
+ -rm -rf tcg/seg/.libs tcg/seg/_libs
+ -rm -rf tcg/swid/.libs tcg/swid/_libs
install-dist_templatesDATA: $(dist_templates_DATA)
@$(NORMAL_INSTALL)
@list='$(dist_templates_DATA)'; test -n "$(templatesdir)" || list=; \
@@ -1038,6 +1638,99 @@ cscopelist-am: $(am__tagged_files)
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+check-TESTS: $(TESTS)
+ @failed=0; all=0; xfail=0; xpass=0; skip=0; \
+ srcdir=$(srcdir); export srcdir; \
+ list=' $(TESTS) '; \
+ $(am__tty_colors); \
+ if test -n "$$list"; then \
+ for tst in $$list; do \
+ if test -f ./$$tst; then dir=./; \
+ elif test -f $$tst; then dir=; \
+ else dir="$(srcdir)/"; fi; \
+ if $(TESTS_ENVIRONMENT) $${dir}$$tst $(AM_TESTS_FD_REDIRECT); then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$tst[\ \ ]*) \
+ xpass=`expr $$xpass + 1`; \
+ failed=`expr $$failed + 1`; \
+ col=$$red; res=XPASS; \
+ ;; \
+ *) \
+ col=$$grn; res=PASS; \
+ ;; \
+ esac; \
+ elif test $$? -ne 77; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$tst[\ \ ]*) \
+ xfail=`expr $$xfail + 1`; \
+ col=$$lgn; res=XFAIL; \
+ ;; \
+ *) \
+ failed=`expr $$failed + 1`; \
+ col=$$red; res=FAIL; \
+ ;; \
+ esac; \
+ else \
+ skip=`expr $$skip + 1`; \
+ col=$$blu; res=SKIP; \
+ fi; \
+ echo "$${col}$$res$${std}: $$tst"; \
+ done; \
+ if test "$$all" -eq 1; then \
+ tests="test"; \
+ All=""; \
+ else \
+ tests="tests"; \
+ All="All "; \
+ fi; \
+ if test "$$failed" -eq 0; then \
+ if test "$$xfail" -eq 0; then \
+ banner="$$All$$all $$tests passed"; \
+ else \
+ if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \
+ banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \
+ fi; \
+ else \
+ if test "$$xpass" -eq 0; then \
+ banner="$$failed of $$all $$tests failed"; \
+ else \
+ if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \
+ banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \
+ fi; \
+ fi; \
+ dashes="$$banner"; \
+ skipped=""; \
+ if test "$$skip" -ne 0; then \
+ if test "$$skip" -eq 1; then \
+ skipped="($$skip test was not run)"; \
+ else \
+ skipped="($$skip tests were not run)"; \
+ fi; \
+ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$skipped"; \
+ fi; \
+ report=""; \
+ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
+ report="Please report to $(PACKAGE_BUGREPORT)"; \
+ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$report"; \
+ fi; \
+ dashes=`echo "$$dashes" | sed s/./=/g`; \
+ if test "$$failed" -eq 0; then \
+ col="$$grn"; \
+ else \
+ col="$$red"; \
+ fi; \
+ echo "$${col}$$dashes$${std}"; \
+ echo "$${col}$$banner$${std}"; \
+ test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \
+ test -z "$$report" || echo "$${col}$$report$${std}"; \
+ echo "$${col}$$dashes$${std}"; \
+ test "$$failed" -eq 0; \
+ else :; fi
+
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
@@ -1094,6 +1787,8 @@ distdir: $(DISTFILES)
fi; \
done
check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
+ $(MAKE) $(AM_MAKEFLAGS) check-TESTS
check: check-recursive
all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(SCRIPTS) $(DATA)
installdirs: installdirs-recursive
@@ -1139,17 +1834,39 @@ distclean-generic:
-rm -f os_info/$(am__dirstamp)
-rm -f pa_tnc/$(DEPDIR)/$(am__dirstamp)
-rm -f pa_tnc/$(am__dirstamp)
+ -rm -f pts/$(DEPDIR)/$(am__dirstamp)
+ -rm -f pts/$(am__dirstamp)
+ -rm -f pts/components/$(DEPDIR)/$(am__dirstamp)
+ -rm -f pts/components/$(am__dirstamp)
+ -rm -f pts/components/ita/$(DEPDIR)/$(am__dirstamp)
+ -rm -f pts/components/ita/$(am__dirstamp)
+ -rm -f pts/components/tcg/$(DEPDIR)/$(am__dirstamp)
+ -rm -f pts/components/tcg/$(am__dirstamp)
+ -rm -f seg/$(DEPDIR)/$(am__dirstamp)
+ -rm -f seg/$(am__dirstamp)
+ -rm -f suites/$(DEPDIR)/$(am__dirstamp)
+ -rm -f suites/$(am__dirstamp)
+ -rm -f swid/$(DEPDIR)/$(am__dirstamp)
+ -rm -f swid/$(am__dirstamp)
+ -rm -f tcg/$(DEPDIR)/$(am__dirstamp)
+ -rm -f tcg/$(am__dirstamp)
+ -rm -f tcg/pts/$(DEPDIR)/$(am__dirstamp)
+ -rm -f tcg/pts/$(am__dirstamp)
+ -rm -f tcg/seg/$(DEPDIR)/$(am__dirstamp)
+ -rm -f tcg/seg/$(am__dirstamp)
+ -rm -f tcg/swid/$(DEPDIR)/$(am__dirstamp)
+ -rm -f tcg/swid/$(am__dirstamp)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-recursive
-clean-am: clean-generic clean-ipsecPROGRAMS clean-ipseclibLTLIBRARIES \
- clean-libtool mostlyclean-am
+clean-am: clean-checkPROGRAMS clean-generic clean-ipsecPROGRAMS \
+ clean-ipseclibLTLIBRARIES clean-libtool mostlyclean-am
distclean: distclean-recursive
- -rm -rf ./$(DEPDIR) ietf/$(DEPDIR) imc/$(DEPDIR) imv/$(DEPDIR) ita/$(DEPDIR) os_info/$(DEPDIR) pa_tnc/$(DEPDIR)
+ -rm -rf ./$(DEPDIR) ietf/$(DEPDIR) imc/$(DEPDIR) imv/$(DEPDIR) ita/$(DEPDIR) os_info/$(DEPDIR) pa_tnc/$(DEPDIR) pts/$(DEPDIR) pts/components/$(DEPDIR) pts/components/ita/$(DEPDIR) pts/components/tcg/$(DEPDIR) seg/$(DEPDIR) suites/$(DEPDIR) swid/$(DEPDIR) tcg/$(DEPDIR) tcg/pts/$(DEPDIR) tcg/seg/$(DEPDIR) tcg/swid/$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
@@ -1196,7 +1913,7 @@ install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-recursive
- -rm -rf ./$(DEPDIR) ietf/$(DEPDIR) imc/$(DEPDIR) imv/$(DEPDIR) ita/$(DEPDIR) os_info/$(DEPDIR) pa_tnc/$(DEPDIR)
+ -rm -rf ./$(DEPDIR) ietf/$(DEPDIR) imc/$(DEPDIR) imv/$(DEPDIR) ita/$(DEPDIR) os_info/$(DEPDIR) pa_tnc/$(DEPDIR) pts/$(DEPDIR) pts/components/$(DEPDIR) pts/components/ita/$(DEPDIR) pts/components/tcg/$(DEPDIR) seg/$(DEPDIR) suites/$(DEPDIR) swid/$(DEPDIR) tcg/$(DEPDIR) tcg/pts/$(DEPDIR) tcg/seg/$(DEPDIR) tcg/swid/$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
@@ -1216,17 +1933,17 @@ ps-am:
uninstall-am: uninstall-dist_templatesDATA uninstall-ipsecPROGRAMS \
uninstall-ipsecSCRIPTS uninstall-ipseclibLTLIBRARIES
-.MAKE: $(am__recursive_targets) install-am install-strip
+.MAKE: $(am__recursive_targets) check-am install-am install-strip
.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \
- check-am clean clean-generic clean-ipsecPROGRAMS \
- clean-ipseclibLTLIBRARIES clean-libtool cscopelist-am ctags \
- ctags-am distclean distclean-compile distclean-generic \
- distclean-libtool distclean-tags distdir dvi dvi-am html \
- html-am info info-am install install-am install-data \
- install-data-am install-dist_templatesDATA install-dvi \
- install-dvi-am install-exec install-exec-am install-html \
- install-html-am install-info install-info-am \
+ check-TESTS check-am clean clean-checkPROGRAMS clean-generic \
+ clean-ipsecPROGRAMS clean-ipseclibLTLIBRARIES clean-libtool \
+ cscopelist-am ctags ctags-am distclean distclean-compile \
+ distclean-generic distclean-libtool distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dist_templatesDATA \
+ install-dvi install-dvi-am install-exec install-exec-am \
+ install-html install-html-am install-info install-info-am \
install-ipsecPROGRAMS install-ipsecSCRIPTS \
install-ipseclibLTLIBRARIES install-man install-pdf \
install-pdf-am install-ps install-ps-am install-strip \
diff --git a/src/libimcv/ietf/ietf_attr.c b/src/libimcv/ietf/ietf_attr.c
index 2f3819898..67269af53 100644
--- a/src/libimcv/ietf/ietf_attr.c
+++ b/src/libimcv/ietf/ietf_attr.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
@@ -47,34 +47,35 @@ ENUM(ietf_attr_names, IETF_ATTR_TESTING, IETF_ATTR_FACTORY_DEFAULT_PWD_ENABLED,
/**
* See header
*/
-pa_tnc_attr_t* ietf_attr_create_from_data(u_int32_t type, chunk_t value)
+pa_tnc_attr_t* ietf_attr_create_from_data(u_int32_t type, size_t length,
+ chunk_t value)
{
switch (type)
{
case IETF_ATTR_ATTRIBUTE_REQUEST:
- return ietf_attr_attr_request_create_from_data(value);
+ return ietf_attr_attr_request_create_from_data(length, value);
case IETF_ATTR_PRODUCT_INFORMATION:
- return ietf_attr_product_info_create_from_data(value);
+ return ietf_attr_product_info_create_from_data(length, value);
case IETF_ATTR_NUMERIC_VERSION:
- return ietf_attr_numeric_version_create_from_data(value);
+ return ietf_attr_numeric_version_create_from_data(length, value);
case IETF_ATTR_STRING_VERSION:
- return ietf_attr_string_version_create_from_data(value);
+ return ietf_attr_string_version_create_from_data(length, value);
case IETF_ATTR_OPERATIONAL_STATUS:
- return ietf_attr_op_status_create_from_data(value);
+ return ietf_attr_op_status_create_from_data(length, value);
case IETF_ATTR_PORT_FILTER:
- return ietf_attr_port_filter_create_from_data(value);
+ return ietf_attr_port_filter_create_from_data(length, value);
case IETF_ATTR_INSTALLED_PACKAGES:
- return ietf_attr_installed_packages_create_from_data(value);
+ return ietf_attr_installed_packages_create_from_data(length, value);
case IETF_ATTR_PA_TNC_ERROR:
- return ietf_attr_pa_tnc_error_create_from_data(value);
+ return ietf_attr_pa_tnc_error_create_from_data(length, value);
case IETF_ATTR_ASSESSMENT_RESULT:
- return ietf_attr_assess_result_create_from_data(value);
+ return ietf_attr_assess_result_create_from_data(length, value);
case IETF_ATTR_REMEDIATION_INSTRUCTIONS:
- return ietf_attr_remediation_instr_create_from_data(value);
+ return ietf_attr_remediation_instr_create_from_data(length, value);
case IETF_ATTR_FORWARDING_ENABLED:
- return ietf_attr_fwd_enabled_create_from_data(value);
+ return ietf_attr_fwd_enabled_create_from_data(length, value);
case IETF_ATTR_FACTORY_DEFAULT_PWD_ENABLED:
- return ietf_attr_default_pwd_enabled_create_from_data(value);
+ return ietf_attr_default_pwd_enabled_create_from_data(length, value);
case IETF_ATTR_TESTING:
case IETF_ATTR_RESERVED:
default:
diff --git a/src/libimcv/ietf/ietf_attr.h b/src/libimcv/ietf/ietf_attr.h
index d22175d94..169ed78e8 100644
--- a/src/libimcv/ietf/ietf_attr.h
+++ b/src/libimcv/ietf/ietf_attr.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
@@ -56,8 +56,10 @@ extern enum_name_t *ietf_attr_names;
* Create an IETF PA-TNC attribute from data
*
* @param type attribute type
- * @param value attribute value
+ * @param length attribute length
+ * @param value attribute value or segment
*/
-pa_tnc_attr_t* ietf_attr_create_from_data(u_int32_t type, chunk_t value);
+pa_tnc_attr_t* ietf_attr_create_from_data(u_int32_t type, size_t length,
+ chunk_t value);
#endif /** IETF_ATTR_H_ @}*/
diff --git a/src/libimcv/ietf/ietf_attr_assess_result.c b/src/libimcv/ietf/ietf_attr_assess_result.c
index 55226e3bb..1cffdcaae 100644
--- a/src/libimcv/ietf/ietf_attr_assess_result.c
+++ b/src/libimcv/ietf/ietf_attr_assess_result.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Andreas Steffen
+ * Copyright (C) 2012-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -50,7 +50,12 @@ struct private_ietf_attr_assess_result_t {
pen_type_t type;
/**
- * Attribute value
+ * Length of attribute value
+ */
+ size_t length;
+
+ /**
+ * Attribute value or segment
*/
chunk_t value;
@@ -107,6 +112,7 @@ METHOD(pa_tnc_attr_t, build, void,
writer = bio_writer_create(ASSESS_RESULT_SIZE);
writer->write_uint32(writer, this->result);
this->value = writer->extract_buf(writer);
+ this->length = this->value.len;
writer->destroy(writer);
}
@@ -115,10 +121,15 @@ METHOD(pa_tnc_attr_t, process, status_t,
{
bio_reader_t *reader;
+ *offset = 0;
+
+ if (this->value.len < this->length)
+ {
+ return NEED_MORE;
+ }
if (this->value.len < ASSESS_RESULT_SIZE)
{
DBG1(DBG_TNC, "insufficient data for IETF assessment result");
- *offset = 0;
return FAILED;
}
reader = bio_reader_create(this->value);
@@ -128,6 +139,12 @@ METHOD(pa_tnc_attr_t, process, status_t,
return SUCCESS;
}
+METHOD(pa_tnc_attr_t, add_segment, void,
+ private_ietf_attr_assess_result_t *this, chunk_t segment)
+{
+ this->value = chunk_cat("mc", this->value, segment);
+}
+
METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
private_ietf_attr_assess_result_t *this)
{
@@ -167,6 +184,7 @@ pa_tnc_attr_t *ietf_attr_assess_result_create(u_int32_t result)
.set_noskip_flag = _set_noskip_flag,
.build = _build,
.process = _process,
+ .add_segment = _add_segment,
.get_ref = _get_ref,
.destroy = _destroy,
},
@@ -183,7 +201,8 @@ pa_tnc_attr_t *ietf_attr_assess_result_create(u_int32_t result)
/**
* Described in header.
*/
-pa_tnc_attr_t *ietf_attr_assess_result_create_from_data(chunk_t data)
+pa_tnc_attr_t *ietf_attr_assess_result_create_from_data(size_t length,
+ chunk_t data)
{
private_ietf_attr_assess_result_t *this;
@@ -196,12 +215,14 @@ pa_tnc_attr_t *ietf_attr_assess_result_create_from_data(chunk_t data)
.set_noskip_flag = _set_noskip_flag,
.build = _build,
.process = _process,
+ .add_segment = _add_segment,
.get_ref = _get_ref,
.destroy = _destroy,
},
.get_result = _get_result,
},
.type = { PEN_IETF, IETF_ATTR_ASSESSMENT_RESULT },
+ .length = length,
.value = chunk_clone(data),
.ref = 1,
);
diff --git a/src/libimcv/ietf/ietf_attr_assess_result.h b/src/libimcv/ietf/ietf_attr_assess_result.h
index e94b57b88..b1a5166dc 100644
--- a/src/libimcv/ietf/ietf_attr_assess_result.h
+++ b/src/libimcv/ietf/ietf_attr_assess_result.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Andreas Steffen
+ * Copyright (C) 2012-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -56,8 +56,10 @@ pa_tnc_attr_t* ietf_attr_assess_result_create(u_int32_t result);
/**
* Creates an ietf_attr_assess_result_t object from received data
*
- * @param value unparsed attribute value
+ * @param length Total length of attribute value
+ * @param value Unparsed attribute value (might be a segment)
*/
-pa_tnc_attr_t* ietf_attr_assess_result_create_from_data(chunk_t value);
+pa_tnc_attr_t* ietf_attr_assess_result_create_from_data(size_t length,
+ chunk_t value);
#endif /** IETF_ATTR_ASSESS_RESULT_H_ @}*/
diff --git a/src/libimcv/ietf/ietf_attr_attr_request.c b/src/libimcv/ietf/ietf_attr_attr_request.c
index 3b4fd26cd..3862a0aa8 100644
--- a/src/libimcv/ietf/ietf_attr_attr_request.c
+++ b/src/libimcv/ietf/ietf_attr_attr_request.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Andreas Steffen
+ * Copyright (C) 2012-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -59,7 +59,12 @@ struct private_ietf_attr_attr_request_t {
pen_type_t type;
/**
- * Attribute value
+ * Length of attribute value
+ */
+ size_t length;
+
+ /**
+ * Attribute value or segment
*/
chunk_t value;
@@ -126,6 +131,7 @@ METHOD(pa_tnc_attr_t, build, void,
enumerator->destroy(enumerator);
this->value = writer->extract_buf(writer);
+ this->length = this->value.len;
writer->destroy(writer);
}
@@ -150,11 +156,17 @@ METHOD(pa_tnc_attr_t, process, status_t,
u_int8_t reserved;
int count;
+ *offset = 0;
+
+ if (this->value.len < this->length)
+ {
+ return NEED_MORE;
+ }
+
count = this->value.len / ATTR_REQUEST_ENTRY_SIZE;
if (this->value.len != ATTR_REQUEST_ENTRY_SIZE * count)
{
DBG1(DBG_TNC, "incorrect attribute length for IETF attribute request");
- *offset = 0;
return FAILED;
}
@@ -184,6 +196,12 @@ METHOD(pa_tnc_attr_t, process, status_t,
return SUCCESS;
}
+METHOD(pa_tnc_attr_t, add_segment, void,
+ private_ietf_attr_attr_request_t *this, chunk_t segment)
+{
+ this->value = chunk_cat("mc", this->value, segment);
+}
+
METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
private_ietf_attr_attr_request_t *this)
{
@@ -224,6 +242,7 @@ pa_tnc_attr_t *ietf_attr_attr_request_create(pen_t vendor_id, u_int32_t type)
.set_noskip_flag = _set_noskip_flag,
.build = _build,
.process = _process,
+ .add_segment = _add_segment,
.get_ref = _get_ref,
.destroy = _destroy,
},
@@ -246,7 +265,8 @@ pa_tnc_attr_t *ietf_attr_attr_request_create(pen_t vendor_id, u_int32_t type)
/**
* Described in header.
*/
-pa_tnc_attr_t *ietf_attr_attr_request_create_from_data(chunk_t data)
+pa_tnc_attr_t *ietf_attr_attr_request_create_from_data(size_t length,
+ chunk_t data)
{
private_ietf_attr_attr_request_t *this;
@@ -259,6 +279,7 @@ pa_tnc_attr_t *ietf_attr_attr_request_create_from_data(chunk_t data)
.set_noskip_flag = _set_noskip_flag,
.build = _build,
.process = _process,
+ .add_segment = _add_segment,
.get_ref = _get_ref,
.destroy = _destroy,
},
@@ -266,6 +287,7 @@ pa_tnc_attr_t *ietf_attr_attr_request_create_from_data(chunk_t data)
.create_enumerator = _create_enumerator,
},
.type = { PEN_IETF, IETF_ATTR_ATTRIBUTE_REQUEST },
+ .length = length,
.value = chunk_clone(data),
.list = linked_list_create(),
.ref = 1,
diff --git a/src/libimcv/ietf/ietf_attr_attr_request.h b/src/libimcv/ietf/ietf_attr_attr_request.h
index fc9e08676..47b038605 100644
--- a/src/libimcv/ietf/ietf_attr_attr_request.h
+++ b/src/libimcv/ietf/ietf_attr_attr_request.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Andreas Steffen
+ * Copyright (C) 2012-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -62,10 +62,10 @@ struct ietf_attr_attr_request_t {
pa_tnc_attr_t* ietf_attr_attr_request_create(pen_t vendor_id, u_int32_t type);
/**
- * Creates an ietf_attr_attr_request_t object from received data
- *
- * @param value unparsed attribute value
+ * @param length Total length of attribute value
+ * @param value Unparsed attribute value (might be a segment)
*/
-pa_tnc_attr_t* ietf_attr_attr_request_create_from_data(chunk_t value);
+pa_tnc_attr_t* ietf_attr_attr_request_create_from_data(size_t length,
+ chunk_t value);
#endif /** IETF_ATTR_ATTR_REQUEST_H_ @}*/
diff --git a/src/libimcv/ietf/ietf_attr_default_pwd_enabled.c b/src/libimcv/ietf/ietf_attr_default_pwd_enabled.c
index 2c6b3d542..ee5864d29 100644
--- a/src/libimcv/ietf/ietf_attr_default_pwd_enabled.c
+++ b/src/libimcv/ietf/ietf_attr_default_pwd_enabled.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Andreas Steffen
+ * Copyright (C) 2012-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -50,7 +50,12 @@ struct private_ietf_attr_default_pwd_enabled_t {
pen_type_t type;
/**
- * Attribute value
+ * Length of attribute value
+ */
+ size_t length;
+
+ /**
+ * Attribute value or segment
*/
chunk_t value;
@@ -107,6 +112,7 @@ METHOD(pa_tnc_attr_t, build, void,
writer->write_uint32(writer, this->status);
this->value = writer->extract_buf(writer);
+ this->length = this->value.len;
writer->destroy(writer);
}
@@ -118,6 +124,10 @@ METHOD(pa_tnc_attr_t, process, status_t,
*offset = 0;
+ if (this->value.len < this->length)
+ {
+ return NEED_MORE;
+ }
if (this->value.len != DEFAULT_PWD_ENABLED_SIZE)
{
DBG1(DBG_TNC, "incorrect size for IETF factory default password "
@@ -139,6 +149,12 @@ METHOD(pa_tnc_attr_t, process, status_t,
return SUCCESS;
}
+METHOD(pa_tnc_attr_t, add_segment, void,
+ private_ietf_attr_default_pwd_enabled_t *this, chunk_t segment)
+{
+ this->value = chunk_cat("mc", this->value, segment);
+}
+
METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
private_ietf_attr_default_pwd_enabled_t *this)
{
@@ -178,6 +194,7 @@ pa_tnc_attr_t *ietf_attr_default_pwd_enabled_create(bool status)
.set_noskip_flag = _set_noskip_flag,
.build = _build,
.process = _process,
+ .add_segment = _add_segment,
.get_ref = _get_ref,
.destroy = _destroy,
},
@@ -194,7 +211,8 @@ pa_tnc_attr_t *ietf_attr_default_pwd_enabled_create(bool status)
/**
* Described in header.
*/
-pa_tnc_attr_t *ietf_attr_default_pwd_enabled_create_from_data(chunk_t data)
+pa_tnc_attr_t *ietf_attr_default_pwd_enabled_create_from_data(size_t length,
+ chunk_t data)
{
private_ietf_attr_default_pwd_enabled_t *this;
@@ -207,12 +225,14 @@ pa_tnc_attr_t *ietf_attr_default_pwd_enabled_create_from_data(chunk_t data)
.set_noskip_flag = _set_noskip_flag,
.build = _build,
.process = _process,
+ .add_segment = _add_segment,
.get_ref = _get_ref,
.destroy = _destroy,
},
.get_status = _get_status,
},
.type = { PEN_IETF, IETF_ATTR_FACTORY_DEFAULT_PWD_ENABLED },
+ .length = length,
.value = chunk_clone(data),
.ref = 1,
);
diff --git a/src/libimcv/ietf/ietf_attr_default_pwd_enabled.h b/src/libimcv/ietf/ietf_attr_default_pwd_enabled.h
index 6fe1a02b1..3999590d4 100644
--- a/src/libimcv/ietf/ietf_attr_default_pwd_enabled.h
+++ b/src/libimcv/ietf/ietf_attr_default_pwd_enabled.h
@@ -56,8 +56,10 @@ pa_tnc_attr_t* ietf_attr_default_pwd_enabled_create(bool status);
/**
* Creates an ietf_attr_default_pwd_enabled_t object from received data
*
- * @param value unparsed attribute value
+ * @param length Total length of attribute value
+ * @param value Unparsed attribute value (might be a segment)
*/
-pa_tnc_attr_t* ietf_attr_default_pwd_enabled_create_from_data(chunk_t value);
+pa_tnc_attr_t* ietf_attr_default_pwd_enabled_create_from_data(size_t length,
+ chunk_t value);
#endif /** IETF_ATTR_PWD_ENABLED_H_ @}*/
diff --git a/src/libimcv/ietf/ietf_attr_fwd_enabled.c b/src/libimcv/ietf/ietf_attr_fwd_enabled.c
index a906b2258..c00a5efc2 100644
--- a/src/libimcv/ietf/ietf_attr_fwd_enabled.c
+++ b/src/libimcv/ietf/ietf_attr_fwd_enabled.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Andreas Steffen
+ * Copyright (C) 2012-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -50,7 +50,12 @@ struct private_ietf_attr_fwd_enabled_t {
pen_type_t type;
/**
- * Attribute value
+ * Length of attribute value
+ */
+ size_t length;
+
+ /**
+ * Attribute value or segment
*/
chunk_t value;
@@ -107,6 +112,7 @@ METHOD(pa_tnc_attr_t, build, void,
writer->write_uint32(writer, this->fwd_status);
this->value = writer->extract_buf(writer);
+ this->length = this->value.len;
writer->destroy(writer);
}
@@ -118,6 +124,10 @@ METHOD(pa_tnc_attr_t, process, status_t,
*offset = 0;
+ if (this->value.len < this->length)
+ {
+ return NEED_MORE;
+ }
if (this->value.len != FORWARDING_ENABLED_SIZE)
{
DBG1(DBG_TNC, "incorrect size for IETF forwarding enabled attribute");
@@ -138,6 +148,12 @@ METHOD(pa_tnc_attr_t, process, status_t,
return SUCCESS;
}
+METHOD(pa_tnc_attr_t, add_segment, void,
+ private_ietf_attr_fwd_enabled_t *this, chunk_t segment)
+{
+ this->value = chunk_cat("mc", this->value, segment);
+}
+
METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
private_ietf_attr_fwd_enabled_t *this)
{
@@ -177,6 +193,7 @@ pa_tnc_attr_t *ietf_attr_fwd_enabled_create(os_fwd_status_t fwd_status)
.set_noskip_flag = _set_noskip_flag,
.build = _build,
.process = _process,
+ .add_segment = _add_segment,
.get_ref = _get_ref,
.destroy = _destroy,
},
@@ -193,7 +210,8 @@ pa_tnc_attr_t *ietf_attr_fwd_enabled_create(os_fwd_status_t fwd_status)
/**
* Described in header.
*/
-pa_tnc_attr_t *ietf_attr_fwd_enabled_create_from_data(chunk_t data)
+pa_tnc_attr_t *ietf_attr_fwd_enabled_create_from_data(size_t length,
+ chunk_t data)
{
private_ietf_attr_fwd_enabled_t *this;
@@ -206,12 +224,14 @@ pa_tnc_attr_t *ietf_attr_fwd_enabled_create_from_data(chunk_t data)
.set_noskip_flag = _set_noskip_flag,
.build = _build,
.process = _process,
+ .add_segment = _add_segment,
.get_ref = _get_ref,
.destroy = _destroy,
},
.get_status = _get_status,
},
.type = { PEN_IETF, IETF_ATTR_FORWARDING_ENABLED },
+ .length = length,
.value = chunk_clone(data),
.ref = 1,
);
diff --git a/src/libimcv/ietf/ietf_attr_fwd_enabled.h b/src/libimcv/ietf/ietf_attr_fwd_enabled.h
index 41714380e..c4b6c1547 100644
--- a/src/libimcv/ietf/ietf_attr_fwd_enabled.h
+++ b/src/libimcv/ietf/ietf_attr_fwd_enabled.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Andreas Steffen
+ * Copyright (C) 2012-14 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -57,8 +57,10 @@ pa_tnc_attr_t* ietf_attr_fwd_enabled_create(os_fwd_status_t fwd_status);
/**
* Creates an ietf_attr_fwd_enabled_t object from received data
*
- * @param value unparsed attribute value
+ * @param length Total length of attribute value
+ * @param value Unparsed attribute value (might be a segment)
*/
-pa_tnc_attr_t* ietf_attr_fwd_enabled_create_from_data(chunk_t value);
+pa_tnc_attr_t* ietf_attr_fwd_enabled_create_from_data(size_t length,
+ chunk_t value);
#endif /** IETF_ATTR_FWD_ENABLED_H_ @}*/
diff --git a/src/libimcv/ietf/ietf_attr_installed_packages.c b/src/libimcv/ietf/ietf_attr_installed_packages.c
index f33f643af..39eea555a 100644
--- a/src/libimcv/ietf/ietf_attr_installed_packages.c
+++ b/src/libimcv/ietf/ietf_attr_installed_packages.c
@@ -57,16 +57,36 @@ struct private_ietf_attr_installed_packages_t {
pen_type_t type;
/**
- * Attribute value
+ * Length of attribute value
+ */
+ size_t length;
+
+ /**
+ * Offset up to which attribute value has been processed
+ */
+ size_t offset;
+
+ /**
+ * Current position of attribute value pointer
*/
chunk_t value;
/**
+ * Contains complete attribute or current segment
+ */
+ chunk_t segment;
+
+ /**
* Noskip flag
*/
bool noskip_flag;
/**
+ * Number of Installed Packages in attribute
+ */
+ uint16_t count;
+
+ /**
* List of Installed Package entries
*/
linked_list_t *packages;
@@ -143,6 +163,8 @@ METHOD(pa_tnc_attr_t, build, void,
enumerator->destroy(enumerator);
this->value = writer->extract_buf(writer);
+ this->segment = this->value;
+ this->length = this->value.len;
writer->destroy(writer);
}
@@ -151,72 +173,91 @@ METHOD(pa_tnc_attr_t, process, status_t,
{
bio_reader_t *reader;
package_entry_t *entry;
- status_t status = FAILED;
+ status_t status = NEED_MORE;
chunk_t name, version;
- u_int16_t reserved, count;
+ u_int16_t reserved;
u_char *pos;
- *offset = 0;
-
- if (this->value.len < IETF_INSTALLED_PACKAGES_MIN_SIZE)
- {
- DBG1(DBG_TNC, "insufficient data for IETF installed packages");
- return FAILED;
+ if (this->offset == 0)
+ {
+ if (this->length < IETF_INSTALLED_PACKAGES_MIN_SIZE)
+ {
+ DBG1(DBG_TNC, "insufficient data for %N/%N", pen_names, PEN_IETF,
+ ietf_attr_names, this->type.type);
+ *offset = this->offset;
+ return FAILED;
+ }
+ if (this->value.len < IETF_INSTALLED_PACKAGES_MIN_SIZE)
+ {
+ return NEED_MORE;
+ }
+ reader = bio_reader_create(this->value);
+ reader->read_uint16(reader, &reserved);
+ reader->read_uint16(reader, &this->count);
+ this->offset = IETF_INSTALLED_PACKAGES_MIN_SIZE;
+ this->value = reader->peek(reader);
+ reader->destroy(reader);
}
+
reader = bio_reader_create(this->value);
- reader->read_uint16(reader, &reserved);
- reader->read_uint16(reader, &count);
- *offset = IETF_INSTALLED_PACKAGES_MIN_SIZE;
- while (reader->remaining(reader))
+ while (this->count)
{
- if (!reader->read_data8(reader, &name))
+ if (!reader->read_data8(reader, &name) ||
+ !reader->read_data8(reader, &version))
{
- DBG1(DBG_TNC, "insufficient data for IETF installed package name");
goto end;
}
pos = memchr(name.ptr, '\0', name.len);
if (pos)
{
DBG1(DBG_TNC, "nul termination in IETF installed package name");
- *offset += 1 + (pos - name.ptr);
- goto end;
- }
- *offset += 1 + name.len;
-
- if (!reader->read_data8(reader, &version))
- {
- DBG1(DBG_TNC, "insufficient data for IETF installed package version");
+ *offset = this->offset + 1 + (pos - name.ptr);
+ status = FAILED;
goto end;
}
pos = memchr(version.ptr, '\0', version.len);
if (pos)
{
DBG1(DBG_TNC, "nul termination in IETF installed package version");
- *offset += 1 + (pos - version.ptr);
+ *offset = this->offset + 1 + name.len + 1 + (pos - version.ptr);
+ status = FAILED;
goto end;
}
- *offset += 1 + version.len;
+ this->offset += this->value.len - reader->remaining(reader);
+ this->value = reader->peek(reader);
entry = malloc_thing(package_entry_t);
entry->name = chunk_clone(name);
entry->version = chunk_clone(version);
this->packages->insert_last(this->packages, entry);
+
+ /* at least one tag ID was processed */
+ status = SUCCESS;
+ this->count--;
}
- if (count != this->packages->get_count(this->packages))
+ if (this->length != this->offset)
{
- DBG1(DBG_TNC, "IETF installed package count unequal to "
- "number of included packages");
- goto end;
+ DBG1(DBG_TNC, "inconsistent length for %N/%N", pen_names, PEN_IETF,
+ ietf_attr_names, this->type.type);
+ *offset = this->offset;
+ status = FAILED;
}
- status = SUCCESS;
end:
reader->destroy(reader);
return status;
}
+METHOD(pa_tnc_attr_t, add_segment, void,
+ private_ietf_attr_installed_packages_t *this, chunk_t segment)
+{
+ this->value = chunk_cat("cc", this->value, segment);
+ chunk_free(&this->segment);
+ this->segment = this->value;
+}
+
METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
private_ietf_attr_installed_packages_t *this)
{
@@ -230,7 +271,7 @@ METHOD(pa_tnc_attr_t, destroy, void,
if (ref_put(&this->ref))
{
this->packages->destroy_function(this->packages, (void*)free_package_entry);
- free(this->value.ptr);
+ free(this->segment.ptr);
free(this);
}
}
@@ -269,6 +310,23 @@ METHOD(ietf_attr_installed_packages_t, create_enumerator, enumerator_t*,
(void*)package_filter, NULL, NULL);
}
+METHOD(ietf_attr_installed_packages_t, get_count, uint16_t,
+ private_ietf_attr_installed_packages_t *this)
+{
+ return this->count;
+}
+
+METHOD(ietf_attr_installed_packages_t, clear_packages, void,
+ private_ietf_attr_installed_packages_t *this)
+{
+ package_entry_t *entry;
+
+ while (this->packages->remove_first(this->packages,(void**)&entry) == SUCCESS)
+ {
+ free_package_entry(entry);
+ }
+}
+
/**
* Described in header.
*/
@@ -285,11 +343,14 @@ pa_tnc_attr_t *ietf_attr_installed_packages_create(void)
.set_noskip_flag = _set_noskip_flag,
.build = _build,
.process = _process,
+ .add_segment = _add_segment,
.get_ref = _get_ref,
.destroy = _destroy,
},
.add = _add,
.create_enumerator = _create_enumerator,
+ .get_count = _get_count,
+ .clear_packages = _clear_packages,
},
.type = { PEN_IETF, IETF_ATTR_INSTALLED_PACKAGES },
.packages = linked_list_create(),
@@ -300,9 +361,11 @@ pa_tnc_attr_t *ietf_attr_installed_packages_create(void)
}
/**
- * Described in header.
+ * Described in header. .length = length,
+
*/
-pa_tnc_attr_t *ietf_attr_installed_packages_create_from_data(chunk_t data)
+pa_tnc_attr_t *ietf_attr_installed_packages_create_from_data(size_t length,
+ chunk_t data)
{
private_ietf_attr_installed_packages_t *this;
@@ -315,18 +378,25 @@ pa_tnc_attr_t *ietf_attr_installed_packages_create_from_data(chunk_t data)
.set_noskip_flag = _set_noskip_flag,
.build = _build,
.process = _process,
+ .add_segment = _add_segment,
.get_ref = _get_ref,
.destroy = _destroy,
},
.add = _add,
.create_enumerator = _create_enumerator,
+ .get_count = _get_count,
+ .clear_packages = _clear_packages,
},
.type = {PEN_IETF, IETF_ATTR_INSTALLED_PACKAGES },
- .value = chunk_clone(data),
+ .length = length,
+ .segment = chunk_clone(data),
.packages = linked_list_create(),
.ref = 1,
);
+ /* received either complete attribute value or first segment */
+ this->value = this->segment;
+
return &this->public.pa_tnc_attribute;
}
diff --git a/src/libimcv/ietf/ietf_attr_installed_packages.h b/src/libimcv/ietf/ietf_attr_installed_packages.h
index e19d0f47b..9f7b7cbcf 100644
--- a/src/libimcv/ietf/ietf_attr_installed_packages.h
+++ b/src/libimcv/ietf/ietf_attr_installed_packages.h
@@ -56,6 +56,18 @@ struct ietf_attr_installed_packages_t {
*/
enumerator_t* (*create_enumerator)(ietf_attr_installed_packages_t *this);
+ /**
+ * Number of Installed Packages still missing
+ *
+ * @return Number of missing installed packages
+ */
+ uint16_t (*get_count)(ietf_attr_installed_packages_t *this);
+
+ /**
+ * Remove all Installed Packages from list
+ */
+ void (*clear_packages)(ietf_attr_installed_packages_t *this);
+
};
/**
@@ -67,8 +79,10 @@ pa_tnc_attr_t* ietf_attr_installed_packages_create(void);
/**
* Creates an ietf_attr_installed_packages_t object from received data
*
- * @param value unparsed attribute value
+ * @param length Total length of attribute value
+ * @param value Unparsed attribute value (might be a segment)
*/
-pa_tnc_attr_t* ietf_attr_installed_packages_create_from_data(chunk_t value);
+pa_tnc_attr_t* ietf_attr_installed_packages_create_from_data(size_t length,
+ chunk_t value);
#endif /** IETF_ATTR_INSTALLED_PACKAGES_H_ @}*/
diff --git a/src/libimcv/ietf/ietf_attr_numeric_version.c b/src/libimcv/ietf/ietf_attr_numeric_version.c
index 739256457..c8fd6c1ca 100644
--- a/src/libimcv/ietf/ietf_attr_numeric_version.c
+++ b/src/libimcv/ietf/ietf_attr_numeric_version.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Andreas Steffen
+ * Copyright (C) 2012-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -56,7 +56,12 @@ struct private_ietf_attr_numeric_version_t {
pen_type_t type;
/**
- * Attribute value
+ * Length of attribute value
+ */
+ size_t length;
+
+ /**
+ * Attribute value or segment
*/
chunk_t value;
@@ -138,6 +143,7 @@ METHOD(pa_tnc_attr_t, build, void,
writer->write_uint16(writer, this->service_pack_minor);
this->value = writer->extract_buf(writer);
+ this->length = this->value.len;
writer->destroy(writer);
}
@@ -146,10 +152,15 @@ METHOD(pa_tnc_attr_t, process, status_t,
{
bio_reader_t *reader;
+ *offset = 0;
+
+ if (this->value.len < this->length)
+ {
+ return NEED_MORE;
+ }
if (this->value.len < NUMERIC_VERSION_SIZE)
{
DBG1(DBG_TNC, "insufficient data for IETF numeric version");
- *offset = 0;
return FAILED;
}
reader = bio_reader_create(this->value);
@@ -163,6 +174,12 @@ METHOD(pa_tnc_attr_t, process, status_t,
return SUCCESS;
}
+METHOD(pa_tnc_attr_t, add_segment, void,
+ private_ietf_attr_numeric_version_t *this, chunk_t segment)
+{
+ this->value = chunk_cat("mc", this->value, segment);
+}
+
METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
private_ietf_attr_numeric_version_t *this)
{
@@ -231,6 +248,7 @@ pa_tnc_attr_t *ietf_attr_numeric_version_create(u_int32_t major, u_int32_t minor
.set_noskip_flag = _set_noskip_flag,
.build = _build,
.process = _process,
+ .add_segment = _add_segment,
.get_ref = _get_ref,
.destroy = _destroy,
},
@@ -253,7 +271,8 @@ pa_tnc_attr_t *ietf_attr_numeric_version_create(u_int32_t major, u_int32_t minor
/**
* Described in header.
*/
-pa_tnc_attr_t *ietf_attr_numeric_version_create_from_data(chunk_t data)
+pa_tnc_attr_t *ietf_attr_numeric_version_create_from_data(size_t length,
+ chunk_t data)
{
private_ietf_attr_numeric_version_t *this;
@@ -266,6 +285,7 @@ pa_tnc_attr_t *ietf_attr_numeric_version_create_from_data(chunk_t data)
.set_noskip_flag = _set_noskip_flag,
.build = _build,
.process = _process,
+ .add_segment = _add_segment,
.get_ref = _get_ref,
.destroy = _destroy,
},
@@ -274,6 +294,7 @@ pa_tnc_attr_t *ietf_attr_numeric_version_create_from_data(chunk_t data)
.get_service_pack = _get_service_pack,
},
.type = { PEN_IETF, IETF_ATTR_NUMERIC_VERSION },
+ .length = length,
.value = chunk_clone(data),
.ref = 1,
);
diff --git a/src/libimcv/ietf/ietf_attr_numeric_version.h b/src/libimcv/ietf/ietf_attr_numeric_version.h
index bbda6b895..34393c673 100644
--- a/src/libimcv/ietf/ietf_attr_numeric_version.h
+++ b/src/libimcv/ietf/ietf_attr_numeric_version.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Andreas Steffen
+ * Copyright (C) 2012-14 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -77,8 +77,10 @@ pa_tnc_attr_t* ietf_attr_numeric_version_create(u_int32_t major, u_int32_t minor
/**
* Creates an ietf_attr_numeric_version_t object from received data
*
- * @param value unparsed attribute value
+ * @param length Total length of attribute value
+ * @param value Unparsed attribute value (might be a segment)
*/
-pa_tnc_attr_t* ietf_attr_numeric_version_create_from_data(chunk_t value);
+pa_tnc_attr_t* ietf_attr_numeric_version_create_from_data(size_t length,
+ chunk_t value);
#endif /** IETF_ATTR_NUMERIC_VERSION_H_ @}*/
diff --git a/src/libimcv/ietf/ietf_attr_op_status.c b/src/libimcv/ietf/ietf_attr_op_status.c
index 23530684a..d061a52f9 100644
--- a/src/libimcv/ietf/ietf_attr_op_status.c
+++ b/src/libimcv/ietf/ietf_attr_op_status.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Andreas Steffen
+ * Copyright (C) 2012-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -76,7 +76,12 @@ struct private_ietf_attr_op_status_t {
pen_type_t type;
/**
- * Attribute value
+ * Length of attribute value
+ */
+ size_t length;
+
+ /**
+ * Attribute value or segment
*/
chunk_t value;
@@ -154,6 +159,7 @@ METHOD(pa_tnc_attr_t, build, void,
writer->write_data (writer, chunk_create(last_use, 20));
this->value = writer->extract_buf(writer);
+ this->length = this->value.len;
writer->destroy(writer);
}
@@ -167,6 +173,10 @@ METHOD(pa_tnc_attr_t, process, status_t,
*offset = 0;
+ if (this->value.len < this->length)
+ {
+ return NEED_MORE;
+ }
if (this->value.len != OP_STATUS_SIZE)
{
DBG1(DBG_TNC, "incorrect size for IETF operational status");
@@ -212,6 +222,12 @@ METHOD(pa_tnc_attr_t, process, status_t,
return SUCCESS;
}
+METHOD(pa_tnc_attr_t, add_segment, void,
+ private_ietf_attr_op_status_t *this, chunk_t segment)
+{
+ this->value = chunk_cat("mc", this->value, segment);
+}
+
METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
private_ietf_attr_op_status_t *this)
{
@@ -264,6 +280,7 @@ pa_tnc_attr_t *ietf_attr_op_status_create(u_int8_t status, u_int8_t result,
.set_noskip_flag = _set_noskip_flag,
.build = _build,
.process = _process,
+ .add_segment = _add_segment,
.get_ref = _get_ref,
.destroy = _destroy,
},
@@ -284,7 +301,7 @@ pa_tnc_attr_t *ietf_attr_op_status_create(u_int8_t status, u_int8_t result,
/**
* Described in header.
*/
-pa_tnc_attr_t *ietf_attr_op_status_create_from_data(chunk_t data)
+pa_tnc_attr_t *ietf_attr_op_status_create_from_data(size_t length, chunk_t data)
{
private_ietf_attr_op_status_t *this;
@@ -297,6 +314,7 @@ pa_tnc_attr_t *ietf_attr_op_status_create_from_data(chunk_t data)
.set_noskip_flag = _set_noskip_flag,
.build = _build,
.process = _process,
+ .add_segment = _add_segment,
.get_ref = _get_ref,
.destroy = _destroy,
},
diff --git a/src/libimcv/ietf/ietf_attr_op_status.h b/src/libimcv/ietf/ietf_attr_op_status.h
index b70fab608..f19185f0a 100644
--- a/src/libimcv/ietf/ietf_attr_op_status.h
+++ b/src/libimcv/ietf/ietf_attr_op_status.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Andreas Steffen
+ * Copyright (C) 2012-14 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -100,8 +100,10 @@ pa_tnc_attr_t* ietf_attr_op_status_create(u_int8_t status, u_int8_t result,
/**
* Creates an ietf_attr_op_status_t object from received data
*
- * @param value unparsed attribute value
+ * @param length Total length of attribute value
+ * @param value Unparsed attribute value (might be a segment)
*/
-pa_tnc_attr_t* ietf_attr_op_status_create_from_data(chunk_t value);
+pa_tnc_attr_t* ietf_attr_op_status_create_from_data(size_t length,
+ chunk_t value);
#endif /** IETF_ATTR_OP_STATUS_H_ @}*/
diff --git a/src/libimcv/ietf/ietf_attr_pa_tnc_error.c b/src/libimcv/ietf/ietf_attr_pa_tnc_error.c
index 5f20f8958..0dbb4aaef 100644
--- a/src/libimcv/ietf/ietf_attr_pa_tnc_error.c
+++ b/src/libimcv/ietf/ietf_attr_pa_tnc_error.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
@@ -113,7 +113,12 @@ struct private_ietf_attr_pa_tnc_error_t {
pen_type_t type;
/**
- * Attribute value
+ * Length of attribute value
+ */
+ size_t length;
+
+ /**
+ * Attribute value or segment
*/
chunk_t value;
@@ -133,14 +138,19 @@ struct private_ietf_attr_pa_tnc_error_t {
chunk_t msg_info;
/**
- * First 8 bytes of unsupported PA-TNC attribute
+ * Flags of unsupported PA-TNC attribute
+ */
+ uint8_t flags;
+
+ /**
+ * Vendor ID and type of unsupported PA-TNC attribute
*/
- chunk_t attr_info;
+ pen_type_t unsupported_type;
/**
* PA-TNC error offset
*/
- u_int32_t error_offset;
+ uint32_t error_offset;
/**
* Reference count
@@ -200,26 +210,35 @@ METHOD(pa_tnc_attr_t, build, void,
writer->write_uint16(writer, PA_ERROR_VERSION_RESERVED);
break;
case PA_ERROR_ATTR_TYPE_NOT_SUPPORTED:
- writer->write_data(writer, this->attr_info);
+ writer->write_uint8 (writer, this->flags);
+ writer->write_uint24(writer, this->unsupported_type.vendor_id);
+ writer->write_uint32(writer, this->unsupported_type.type);
break;
default:
break;
}
}
this->value = writer->extract_buf(writer);
+ this->length = this->value.len;
writer->destroy(writer);
}
METHOD(pa_tnc_attr_t, process, status_t,
- private_ietf_attr_pa_tnc_error_t *this, u_int32_t *offset)
+ private_ietf_attr_pa_tnc_error_t *this, uint32_t *offset)
{
bio_reader_t *reader;
- u_int8_t reserved;
+ uint8_t reserved;
+ uint32_t vendor_id, type;
+ *offset = 0;
+
+ if (this->value.len < this->length)
+ {
+ return NEED_MORE;
+ }
if (this->value.len < PA_ERROR_HEADER_SIZE)
{
DBG1(DBG_TNC, "insufficient data for PA-TNC error header");
- *offset = 0;
return FAILED;
}
reader = bio_reader_create(this->value);
@@ -250,8 +269,7 @@ METHOD(pa_tnc_attr_t, process, status_t,
}
break;
case PA_ERROR_ATTR_TYPE_NOT_SUPPORTED:
- if (!reader->read_data(reader, PA_ERROR_ATTR_INFO_SIZE,
- &this->attr_info))
+ if (reader->remaining(reader) < PA_ERROR_ATTR_INFO_SIZE)
{
reader->destroy(reader);
DBG1(DBG_TNC, "insufficient data for unsupported attribute "
@@ -259,7 +277,10 @@ METHOD(pa_tnc_attr_t, process, status_t,
*offset = PA_ERROR_HEADER_SIZE + PA_ERROR_MSG_INFO_SIZE;
return FAILED;
}
- this->attr_info = chunk_clone(this->attr_info);
+ reader->read_uint8 (reader, &this->flags);
+ reader->read_uint24(reader, &vendor_id);
+ reader->read_uint32(reader, &type);
+ this->unsupported_type = pen_type_create(vendor_id, type);
break;
default:
break;
@@ -275,6 +296,12 @@ METHOD(pa_tnc_attr_t, process, status_t,
return SUCCESS;
}
+METHOD(pa_tnc_attr_t, add_segment, void,
+ private_ietf_attr_pa_tnc_error_t *this, chunk_t segment)
+{
+ this->value = chunk_cat("mc", this->value, segment);
+}
+
METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
private_ietf_attr_pa_tnc_error_t *this)
{
@@ -289,7 +316,6 @@ METHOD(pa_tnc_attr_t, destroy, void,
{
free(this->value.ptr);
free(this->msg_info.ptr);
- free(this->attr_info.ptr);
free(this);
}
}
@@ -306,19 +332,24 @@ METHOD(ietf_attr_pa_tnc_error_t, get_msg_info, chunk_t,
return this->msg_info;
}
-METHOD(ietf_attr_pa_tnc_error_t, get_attr_info, chunk_t,
- private_ietf_attr_pa_tnc_error_t *this)
+METHOD(ietf_attr_pa_tnc_error_t, get_unsupported_attr, pen_type_t,
+ private_ietf_attr_pa_tnc_error_t *this, uint8_t *flags)
{
- return this->attr_info;
+ if (flags)
+ {
+ *flags = this->flags;
+ }
+ return this->unsupported_type;
}
-METHOD(ietf_attr_pa_tnc_error_t, set_attr_info, void,
- private_ietf_attr_pa_tnc_error_t *this, chunk_t attr_info)
+METHOD(ietf_attr_pa_tnc_error_t, set_unsupported_attr, void,
+ private_ietf_attr_pa_tnc_error_t *this, uint8_t flags, pen_type_t type)
{
- this->attr_info = chunk_clone(attr_info);
+ this->flags = flags;
+ this->unsupported_type = type;
}
-METHOD(ietf_attr_pa_tnc_error_t, get_offset, u_int32_t,
+METHOD(ietf_attr_pa_tnc_error_t, get_offset, uint32_t,
private_ietf_attr_pa_tnc_error_t *this)
{
return this->error_offset;
@@ -340,13 +371,14 @@ static private_ietf_attr_pa_tnc_error_t* create_generic()
.set_noskip_flag = _set_noskip_flag,
.build = _build,
.process = _process,
+ .add_segment = _add_segment,
.get_ref = _get_ref,
.destroy = _destroy,
},
.get_error_code = _get_error_code,
.get_msg_info = _get_msg_info,
- .get_attr_info = _get_attr_info,
- .set_attr_info = _set_attr_info,
+ .get_unsupported_attr = _get_unsupported_attr,
+ .set_unsupported_attr = _set_unsupported_attr,
.get_offset = _get_offset,
},
.type = { PEN_IETF, IETF_ATTR_PA_TNC_ERROR },
@@ -385,7 +417,7 @@ pa_tnc_attr_t *ietf_attr_pa_tnc_error_create(pen_type_t error_code,
*/
pa_tnc_attr_t *ietf_attr_pa_tnc_error_create_with_offset(pen_type_t error_code,
chunk_t msg_info,
- u_int32_t error_offset)
+ uint32_t error_offset)
{
private_ietf_attr_pa_tnc_error_t *this;
@@ -403,11 +435,13 @@ pa_tnc_attr_t *ietf_attr_pa_tnc_error_create_with_offset(pen_type_t error_code,
/**
* Described in header.
*/
-pa_tnc_attr_t *ietf_attr_pa_tnc_error_create_from_data(chunk_t data)
+pa_tnc_attr_t *ietf_attr_pa_tnc_error_create_from_data(size_t length,
+ chunk_t data)
{
private_ietf_attr_pa_tnc_error_t *this;
this = create_generic();
+ this->length = length;
this->value = chunk_clone(data);
return &this->public.pa_tnc_attribute;
diff --git a/src/libimcv/ietf/ietf_attr_pa_tnc_error.h b/src/libimcv/ietf/ietf_attr_pa_tnc_error.h
index faa38f8f9..b1df1945a 100644
--- a/src/libimcv/ietf/ietf_attr_pa_tnc_error.h
+++ b/src/libimcv/ietf/ietf_attr_pa_tnc_error.h
@@ -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
@@ -69,25 +69,29 @@ struct ietf_attr_pa_tnc_error_t {
chunk_t (*get_msg_info)(ietf_attr_pa_tnc_error_t *this);
/**
- * Get first 8 bytes of unsupported PA-TNC attribute
+ * Get flags, vendor ID and type of unsupported PA-TNC attribute
*
- * @return PA-TNC attribute info
+ * @param flags PA-TNC attribute flags
+ * @return PA-TNC attribute vendor ID and type
*/
- chunk_t (*get_attr_info)(ietf_attr_pa_tnc_error_t *this);
+ pen_type_t (*get_unsupported_attr)(ietf_attr_pa_tnc_error_t *this,
+ uint8_t *flags);
/**
- * Set first 8 bytes of unsupported PA-TNC attribute
+ * Set flags, vendor ID and type of unsupported PA-TNC attribute
*
- * @param attr_info PA-TNC message info
+ * @param flags PA-TNC attribute flags
+ * @param attr_info PA-TNC attribute vendor ID and type
*/
- void (*set_attr_info)(ietf_attr_pa_tnc_error_t *this, chunk_t attr_info);
+ void (*set_unsupported_attr)(ietf_attr_pa_tnc_error_t *this, uint8_t flags,
+ pen_type_t type);
/**
* Get the PA-TNC error offset
*
* @return PA-TNC error offset
*/
- u_int32_t (*get_offset)(ietf_attr_pa_tnc_error_t *this);
+ uint32_t (*get_offset)(ietf_attr_pa_tnc_error_t *this);
};
@@ -111,13 +115,15 @@ pa_tnc_attr_t* ietf_attr_pa_tnc_error_create(pen_type_t error_code,
*/
pa_tnc_attr_t* ietf_attr_pa_tnc_error_create_with_offset(pen_type_t error_code,
chunk_t header,
- u_int32_t error_offset);
+ uint32_t error_offset);
/**
* Creates an ietf_attr_pa_tnc_error_t object from received data
*
- * @param value unparsed attribute value
+ * @param length Total length of attribute value
+ * @param value Unparsed attribute value (might be a segment)
*/
-pa_tnc_attr_t* ietf_attr_pa_tnc_error_create_from_data(chunk_t value);
+pa_tnc_attr_t* ietf_attr_pa_tnc_error_create_from_data(size_t length,
+ chunk_t value);
#endif /** IETF_ATTR_PA_TNC_ERROR_H_ @}*/
diff --git a/src/libimcv/ietf/ietf_attr_port_filter.c b/src/libimcv/ietf/ietf_attr_port_filter.c
index 1d516a51f..46824406a 100644
--- a/src/libimcv/ietf/ietf_attr_port_filter.c
+++ b/src/libimcv/ietf/ietf_attr_port_filter.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ * 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
@@ -63,7 +64,12 @@ struct private_ietf_attr_port_filter_t {
pen_type_t type;
/**
- * Attribute value
+ * Length of attribute value
+ */
+ size_t length;
+
+ /**
+ * Attribute value or segment
*/
chunk_t value;
@@ -131,6 +137,7 @@ METHOD(pa_tnc_attr_t, build, void,
enumerator->destroy(enumerator);
this->value = writer->extract_buf(writer);
+ this->length = this->value.len;
writer->destroy(writer);
}
@@ -141,11 +148,16 @@ METHOD(pa_tnc_attr_t, process, status_t,
port_entry_t *entry;
u_int8_t blocked;
+ *offset = 0;
+
+ if (this->value.len < this->length)
+ {
+ return NEED_MORE;
+ }
if (this->value.len % PORT_FILTER_ENTRY_SIZE)
{
DBG1(DBG_TNC, "ietf port filter attribute value is not a multiple of %d",
PORT_FILTER_ENTRY_SIZE);
- *offset = 0;
return FAILED;
}
reader = bio_reader_create(this->value);
@@ -164,6 +176,12 @@ METHOD(pa_tnc_attr_t, process, status_t,
return SUCCESS;
}
+METHOD(pa_tnc_attr_t, add_segment, void,
+ private_ietf_attr_port_filter_t *this, chunk_t segment)
+{
+ this->value = chunk_cat("mc", this->value, segment);
+}
+
METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
private_ietf_attr_port_filter_t *this)
{
@@ -231,6 +249,7 @@ pa_tnc_attr_t *ietf_attr_port_filter_create(void)
.set_noskip_flag = _set_noskip_flag,
.build = _build,
.process = _process,
+ .add_segment = _add_segment,
.get_ref = _get_ref,
.destroy = _destroy,
},
@@ -248,7 +267,8 @@ pa_tnc_attr_t *ietf_attr_port_filter_create(void)
/**
* Described in header.
*/
-pa_tnc_attr_t *ietf_attr_port_filter_create_from_data(chunk_t data)
+pa_tnc_attr_t *ietf_attr_port_filter_create_from_data(size_t length,
+ chunk_t data)
{
private_ietf_attr_port_filter_t *this;
@@ -261,6 +281,7 @@ pa_tnc_attr_t *ietf_attr_port_filter_create_from_data(chunk_t data)
.set_noskip_flag = _set_noskip_flag,
.build = _build,
.process = _process,
+ .add_segment = _add_segment,
.get_ref = _get_ref,
.destroy = _destroy,
},
@@ -268,6 +289,7 @@ pa_tnc_attr_t *ietf_attr_port_filter_create_from_data(chunk_t data)
.create_port_enumerator = _create_port_enumerator,
},
.type = {PEN_IETF, IETF_ATTR_PORT_FILTER },
+ .length = length,
.value = chunk_clone(data),
.ports = linked_list_create(),
.ref = 1,
diff --git a/src/libimcv/ietf/ietf_attr_port_filter.h b/src/libimcv/ietf/ietf_attr_port_filter.h
index 93b696e45..d383b19a2 100644
--- a/src/libimcv/ietf/ietf_attr_port_filter.h
+++ b/src/libimcv/ietf/ietf_attr_port_filter.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
@@ -67,8 +67,10 @@ pa_tnc_attr_t* ietf_attr_port_filter_create(void);
/**
* Creates an ietf_attr_port_filter_t object from received data
*
- * @param value unparsed attribute value
+ * @param length Total length of attribute value
+ * @param value Unparsed attribute value (might be a segment)
*/
-pa_tnc_attr_t* ietf_attr_port_filter_create_from_data(chunk_t value);
+pa_tnc_attr_t* ietf_attr_port_filter_create_from_data(size_t length,
+ chunk_t value);
#endif /** IETF_ATTR_PORT_FILTER_H_ @}*/
diff --git a/src/libimcv/ietf/ietf_attr_product_info.c b/src/libimcv/ietf/ietf_attr_product_info.c
index a107c27d3..37c89e9e5 100644
--- a/src/libimcv/ietf/ietf_attr_product_info.c
+++ b/src/libimcv/ietf/ietf_attr_product_info.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ * 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
@@ -51,7 +52,12 @@ struct private_ietf_attr_product_info_t {
pen_type_t type;
/**
- * Attribute value
+ * Length of attribute value
+ */
+ size_t length;
+
+ /**
+ * Attribute value or segment
*/
chunk_t value;
@@ -120,6 +126,7 @@ METHOD(pa_tnc_attr_t, build, void,
writer->write_data (writer, this->product_name);
this->value = writer->extract_buf(writer);
+ this->length = this->value.len;
writer->destroy(writer);
}
@@ -129,10 +136,15 @@ METHOD(pa_tnc_attr_t, process, status_t,
bio_reader_t *reader;
chunk_t product_name;
+ *offset = 0;
+
+ if (this->value.len < this->length)
+ {
+ return NEED_MORE;
+ }
if (this->value.len < PRODUCT_INFO_MIN_SIZE)
{
DBG1(DBG_TNC, "insufficient data for IETF product information");
- *offset = 0;
return FAILED;
}
reader = bio_reader_create(this->value);
@@ -153,6 +165,12 @@ METHOD(pa_tnc_attr_t, process, status_t,
return SUCCESS;
}
+METHOD(pa_tnc_attr_t, add_segment, void,
+ private_ietf_attr_product_info_t *this, chunk_t segment)
+{
+ this->value = chunk_cat("mc", this->value, segment);
+}
+
METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
private_ietf_attr_product_info_t *this)
{
@@ -202,6 +220,7 @@ pa_tnc_attr_t *ietf_attr_product_info_create(pen_t vendor_id, u_int16_t id,
.set_noskip_flag = _set_noskip_flag,
.build = _build,
.process = _process,
+ .add_segment = _add_segment,
.get_ref = _get_ref,
.destroy = _destroy,
},
@@ -220,7 +239,8 @@ pa_tnc_attr_t *ietf_attr_product_info_create(pen_t vendor_id, u_int16_t id,
/**
* Described in header.
*/
-pa_tnc_attr_t *ietf_attr_product_info_create_from_data(chunk_t data)
+pa_tnc_attr_t *ietf_attr_product_info_create_from_data(size_t length,
+ chunk_t data)
{
private_ietf_attr_product_info_t *this;
@@ -233,12 +253,14 @@ pa_tnc_attr_t *ietf_attr_product_info_create_from_data(chunk_t data)
.set_noskip_flag = _set_noskip_flag,
.build = _build,
.process = _process,
+ .add_segment = _add_segment,
.get_ref = _get_ref,
.destroy = _destroy,
},
.get_info = _get_info,
},
.type = { PEN_IETF, IETF_ATTR_PRODUCT_INFORMATION },
+ .length = length,
.value = chunk_clone(data),
.ref = 1,
);
diff --git a/src/libimcv/ietf/ietf_attr_product_info.h b/src/libimcv/ietf/ietf_attr_product_info.h
index d0b2d2a84..5151b5808 100644
--- a/src/libimcv/ietf/ietf_attr_product_info.h
+++ b/src/libimcv/ietf/ietf_attr_product_info.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
@@ -60,8 +60,10 @@ pa_tnc_attr_t* ietf_attr_product_info_create(pen_t vendor_id, u_int16_t id,
/**
* Creates an ietf_attr_product_info_t object from received data
*
- * @param value unparsed attribute value
+ * @param length Total length of attribute value
+ * @param value Unparsed attribute value (might be a segment)
*/
-pa_tnc_attr_t* ietf_attr_product_info_create_from_data(chunk_t value);
+pa_tnc_attr_t* ietf_attr_product_info_create_from_data(size_t length,
+ chunk_t value);
#endif /** IETF_ATTR_PRODUCT_INFO_H_ @}*/
diff --git a/src/libimcv/ietf/ietf_attr_remediation_instr.c b/src/libimcv/ietf/ietf_attr_remediation_instr.c
index 5d85e5d89..64070374e 100644
--- a/src/libimcv/ietf/ietf_attr_remediation_instr.c
+++ b/src/libimcv/ietf/ietf_attr_remediation_instr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Andreas Steffen
+ * Copyright (C) 2012-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -79,7 +79,12 @@ struct private_ietf_attr_remediation_instr_t {
pen_type_t type;
/**
- * Attribute value
+ * Length of attribute value
+ */
+ size_t length;
+
+ /**
+ * Attribute value or segment
*/
chunk_t value;
@@ -155,6 +160,7 @@ METHOD(pa_tnc_attr_t, build, void,
writer->write_data (writer, this->parameters);
this->value = writer->extract_buf(writer);
+ this->length = this->value.len;
writer->destroy(writer);
}
@@ -168,6 +174,10 @@ METHOD(pa_tnc_attr_t, process, status_t,
*offset = 0;
+ if (this->value.len < this->length)
+ {
+ return NEED_MORE;
+ }
if (this->value.len < REMEDIATION_INSTR_MIN_SIZE)
{
DBG1(DBG_TNC, "insufficient data for IETF remediation instructions");
@@ -218,6 +228,12 @@ end:
return status;
}
+METHOD(pa_tnc_attr_t, add_segment, void,
+ private_ietf_attr_remediation_instr_t *this, chunk_t segment)
+{
+ this->value = chunk_cat("mc", this->value, segment);
+}
+
METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
private_ietf_attr_remediation_instr_t *this)
{
@@ -275,6 +291,7 @@ pa_tnc_attr_t *ietf_attr_remediation_instr_create(pen_type_t parameters_type,
.set_noskip_flag = _set_noskip_flag,
.build = _build,
.process = _process,
+ .add_segment = _add_segment,
.get_ref = _get_ref,
.destroy = _destroy,
},
@@ -328,7 +345,8 @@ pa_tnc_attr_t *ietf_attr_remediation_instr_create_from_string(chunk_t string,
/**
* Described in header.
*/
-pa_tnc_attr_t *ietf_attr_remediation_instr_create_from_data(chunk_t data)
+pa_tnc_attr_t *ietf_attr_remediation_instr_create_from_data(size_t length,
+ chunk_t data)
{
private_ietf_attr_remediation_instr_t *this;
@@ -341,6 +359,7 @@ pa_tnc_attr_t *ietf_attr_remediation_instr_create_from_data(chunk_t data)
.set_noskip_flag = _set_noskip_flag,
.build = _build,
.process = _process,
+ .add_segment = _add_segment,
.get_ref = _get_ref,
.destroy = _destroy,
},
@@ -350,6 +369,7 @@ pa_tnc_attr_t *ietf_attr_remediation_instr_create_from_data(chunk_t data)
.get_string = _get_string,
},
.type = { PEN_IETF, IETF_ATTR_REMEDIATION_INSTRUCTIONS },
+ .length = length,
.value = chunk_clone(data),
.ref = 1,
);
diff --git a/src/libimcv/ietf/ietf_attr_remediation_instr.h b/src/libimcv/ietf/ietf_attr_remediation_instr.h
index 5c7c8891b..bc03e995a 100644
--- a/src/libimcv/ietf/ietf_attr_remediation_instr.h
+++ b/src/libimcv/ietf/ietf_attr_remediation_instr.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Andreas Steffen
+ * Copyright (C) 2012-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -102,8 +102,10 @@ pa_tnc_attr_t* ietf_attr_remediation_instr_create_from_string(chunk_t string,
/**
* Creates an ietf_attr_remediation_instr_t object from received data
*
- * @param value unparsed attribute value
+ * @param length Total length of attribute value
+ * @param value Unparsed attribute value (might be a segment)
*/
-pa_tnc_attr_t* ietf_attr_remediation_instr_create_from_data(chunk_t value);
+pa_tnc_attr_t* ietf_attr_remediation_instr_create_from_data(size_t length,
+ chunk_t value);
#endif /** IETF_ATTR_REMEDIATION_INSTR_H_ @}*/
diff --git a/src/libimcv/ietf/ietf_attr_string_version.c b/src/libimcv/ietf/ietf_attr_string_version.c
index 68adde612..c46200b8f 100644
--- a/src/libimcv/ietf/ietf_attr_string_version.c
+++ b/src/libimcv/ietf/ietf_attr_string_version.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Andreas Steffen
+ * Copyright (C) 2012-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -54,7 +54,12 @@ struct private_ietf_attr_string_version_t {
pen_type_t type;
/**
- * Attribute value
+ * Length of attribute value
+ */
+ size_t length;
+
+ /**
+ * Attribute value or segment
*/
chunk_t value;
@@ -124,6 +129,7 @@ METHOD(pa_tnc_attr_t, build, void,
writer->write_data8(writer, this->config);
this->value = writer->extract_buf(writer);
+ this->length = this->value.len;
writer->destroy(writer);
}
@@ -137,6 +143,10 @@ METHOD(pa_tnc_attr_t, process, status_t,
*offset = 0;
+ if (this->value.len < this->length)
+ {
+ return NEED_MORE;
+ }
if (this->value.len < STRING_VERSION_MIN_SIZE)
{
DBG1(DBG_TNC, "insufficient data for IETF string version");
@@ -198,6 +208,12 @@ end:
return status;
}
+METHOD(pa_tnc_attr_t, add_segment, void,
+ private_ietf_attr_string_version_t *this, chunk_t segment)
+{
+ this->value = chunk_cat("mc", this->value, segment);
+}
+
METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
private_ietf_attr_string_version_t *this)
{
@@ -254,6 +270,7 @@ pa_tnc_attr_t *ietf_attr_string_version_create(chunk_t version, chunk_t build,
.set_noskip_flag = _set_noskip_flag,
.build = _build,
.process = _process,
+ .add_segment = _add_segment,
.get_ref = _get_ref,
.destroy = _destroy,
},
@@ -272,7 +289,8 @@ pa_tnc_attr_t *ietf_attr_string_version_create(chunk_t version, chunk_t build,
/**
* Described in header.
*/
-pa_tnc_attr_t *ietf_attr_string_version_create_from_data(chunk_t data)
+pa_tnc_attr_t *ietf_attr_string_version_create_from_data(size_t length,
+ chunk_t data)
{
private_ietf_attr_string_version_t *this;
@@ -285,12 +303,14 @@ pa_tnc_attr_t *ietf_attr_string_version_create_from_data(chunk_t data)
.set_noskip_flag = _set_noskip_flag,
.build = _build,
.process = _process,
+ .add_segment = _add_segment,
.get_ref = _get_ref,
.destroy = _destroy,
},
.get_version = _get_version,
},
.type = { PEN_IETF, IETF_ATTR_STRING_VERSION },
+ .length = length,
.value = chunk_clone(data),
.ref = 1,
);
diff --git a/src/libimcv/ietf/ietf_attr_string_version.h b/src/libimcv/ietf/ietf_attr_string_version.h
index 9ccc1f0ee..432ed4a0f 100644
--- a/src/libimcv/ietf/ietf_attr_string_version.h
+++ b/src/libimcv/ietf/ietf_attr_string_version.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Andreas Steffen
+ * Copyright (C) 2012-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -60,8 +60,10 @@ pa_tnc_attr_t* ietf_attr_string_version_create(chunk_t version, chunk_t build,
/**
* Creates an ietf_attr_string_version_t object from received data
*
- * @param value unparsed attribute value
+ * @param length Total length of attribute value
+ * @param value Unparsed attribute value (might be a segment)
*/
-pa_tnc_attr_t* ietf_attr_string_version_create_from_data(chunk_t value);
+pa_tnc_attr_t* ietf_attr_string_version_create_from_data(size_t length,
+ chunk_t value);
#endif /** IETF_ATTR_STRING_VERSION_H_ @}*/
diff --git a/src/libimcv/imc/imc_agent.c b/src/libimcv/imc/imc_agent.c
index 533151799..0d622f1b8 100644
--- a/src/libimcv/imc/imc_agent.c
+++ b/src/libimcv/imc/imc_agent.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
@@ -59,6 +59,11 @@ struct private_imc_agent_t {
linked_list_t *additional_ids;
/**
+ * list of non-fatal unsupported PA-TNC attribute types
+ */
+ linked_list_t *non_fatal_attr_types;
+
+ /**
* list of TNCC connection entries
*/
linked_list_t *connections;
@@ -510,11 +515,29 @@ METHOD(imc_agent_t, create_id_enumerator, enumerator_t*,
return this->additional_ids->create_enumerator(this->additional_ids);
}
+METHOD(imc_agent_t, add_non_fatal_attr_type, void,
+ private_imc_agent_t *this, pen_type_t type)
+{
+ pen_type_t *type_p;
+
+ type_p = malloc_thing(pen_type_t);
+ *type_p = type;
+ this->non_fatal_attr_types->insert_last(this->non_fatal_attr_types, type_p);
+}
+
+METHOD(imc_agent_t, get_non_fatal_attr_types, linked_list_t*,
+ private_imc_agent_t *this)
+{
+ return this->non_fatal_attr_types;
+}
+
METHOD(imc_agent_t, destroy, void,
private_imc_agent_t *this)
{
DBG1(DBG_IMC, "IMC %u \"%s\" terminated", this->id, this->name);
this->additional_ids->destroy(this->additional_ids);
+ this->non_fatal_attr_types->destroy_function(this->non_fatal_attr_types,
+ free);
this->connections->destroy_function(this->connections, free);
this->connection_lock->destroy(this->connection_lock);
free(this);
@@ -550,6 +573,8 @@ imc_agent_t *imc_agent_create(const char *name,
.reserve_additional_ids = _reserve_additional_ids,
.count_additional_ids = _count_additional_ids,
.create_id_enumerator = _create_id_enumerator,
+ .add_non_fatal_attr_type = _add_non_fatal_attr_type,
+ .get_non_fatal_attr_types = _get_non_fatal_attr_types,
.destroy = _destroy,
},
.name = name,
@@ -557,6 +582,7 @@ imc_agent_t *imc_agent_create(const char *name,
.type_count = type_count,
.id = id,
.additional_ids = linked_list_create(),
+ .non_fatal_attr_types = linked_list_create(),
.connections = linked_list_create(),
.connection_lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
);
diff --git a/src/libimcv/imc/imc_agent.h b/src/libimcv/imc/imc_agent.h
index 0a1638f47..8bdfb6c32 100644
--- a/src/libimcv/imc/imc_agent.h
+++ b/src/libimcv/imc/imc_agent.h
@@ -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
@@ -172,6 +172,16 @@ struct imc_agent_t {
enumerator_t* (*create_id_enumerator)(imc_agent_t *this);
/**
+ * Add an item to the list of non-fatal unsupported PA-TNC attribute types
+ */
+ void (*add_non_fatal_attr_type)(imc_agent_t *this, pen_type_t type);
+
+ /**
+ * Get a list of non-fatal unsupported PA-TNC attribute types
+ */
+ linked_list_t* (*get_non_fatal_attr_types)(imc_agent_t *this);
+
+ /**
* Destroys an imc_agent_t object
*/
void (*destroy)(imc_agent_t *this);
diff --git a/src/libimcv/imc/imc_msg.c b/src/libimcv/imc/imc_msg.c
index 1cf81c730..83337cf7b 100644
--- a/src/libimcv/imc/imc_msg.c
+++ b/src/libimcv/imc/imc_msg.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Andreas Steffen
+ * Copyright (C) 2012-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -18,8 +18,12 @@
#include "ietf/ietf_attr.h"
#include "ietf/ietf_attr_assess_result.h"
#include "ietf/ietf_attr_remediation_instr.h"
+#include "tcg/seg/tcg_seg_attr_max_size.h"
+#include "tcg/seg/tcg_seg_attr_seg_env.h"
+#include "tcg/seg/tcg_seg_attr_next_seg.h"
#include <tncif_names.h>
+#include <tncif_pa_subtypes.h>
#include <pen/pen.h>
#include <collections/linked_list.h>
@@ -104,11 +108,18 @@ METHOD(imc_msg_t, send_, TNC_Result,
pa_tnc_attr_t *attr;
TNC_UInt32 msg_flags;
TNC_MessageType msg_type;
- bool attr_added;
+ bool attr_added, oversize;
chunk_t msg;
+ seg_contract_t *contract;
+ seg_contract_manager_t *contracts;
enumerator_t *enumerator;
TNC_Result result = TNC_RESULT_SUCCESS;
+ /* Get IF-M segmentation contract for this subtype if any */
+ contracts = this->state->get_contracts(this->state);
+ contract = contracts->get_contract(contracts, this->msg_type,
+ FALSE, this->dst_id);
+
while (this->attr_list->get_count(this->attr_list))
{
pa_tnc_msg = pa_tnc_msg_create(this->state->get_max_msg_len(this->state));
@@ -117,6 +128,17 @@ METHOD(imc_msg_t, send_, TNC_Result,
enumerator = this->attr_list->create_enumerator(this->attr_list);
while (enumerator->enumerate(enumerator, &attr))
{
+ if (contract && contract->check_size(contract, attr, &oversize))
+ {
+ if (oversize)
+ {
+ /* TODO generate SWID error msg */
+ }
+ else
+ {
+ attr = contract->first_segment(contract, attr);
+ }
+ }
if (pa_tnc_msg->add_attribute(pa_tnc_msg, attr))
{
attr_added = TRUE;
@@ -208,8 +230,9 @@ static void print_assessment_trailer(bool first)
}
METHOD(imc_msg_t, receive, TNC_Result,
- private_imc_msg_t *this, bool *fatal_error)
+ private_imc_msg_t *this, imc_msg_t *out_msg, bool *fatal_error)
{
+ linked_list_t *non_fatal_types;
TNC_UInt32 target_imc_id;
enumerator_t *enumerator;
pa_tnc_attr_t *attr;
@@ -251,26 +274,14 @@ METHOD(imc_msg_t, receive, TNC_Result,
break;
case VERIFY_ERROR:
{
- imc_msg_t *error_msg;
- TNC_Result result;
-
- error_msg = imc_msg_create_as_reply(&this->public);
-
/* extract and copy by reference all error attributes */
enumerator = this->pa_msg->create_error_enumerator(this->pa_msg);
while (enumerator->enumerate(enumerator, &attr))
{
- error_msg->add_attribute(error_msg, attr->get_ref(attr));
+ out_msg->add_attribute(out_msg, attr->get_ref(attr));
}
enumerator->destroy(enumerator);
-
- /*
- * send the PA-TNC message containing all error attributes
- * with the excl flag set
- */
- result = error_msg->send(error_msg, TRUE);
- error_msg->destroy(error_msg);
- return result;
+ return TNC_RESULT_SUCCESS;
}
case FAILED:
default:
@@ -281,8 +292,192 @@ METHOD(imc_msg_t, receive, TNC_Result,
target_imc_id = (this->dst_id != TNC_IMCID_ANY) ?
this->dst_id : this->agent->get_id(this->agent);
+ /* process any IF-M segmentation contracts */
+ enumerator = this->pa_msg->create_attribute_enumerator(this->pa_msg);
+ while (enumerator->enumerate(enumerator, &attr))
+ {
+ uint32_t max_attr_size, max_seg_size, my_max_attr_size, my_max_seg_size;
+ seg_contract_t *contract;
+ seg_contract_manager_t *contracts;
+ char buf[BUF_LEN];
+ pen_type_t type;
+
+ type = attr->get_type(attr);
+
+ contracts = this->state->get_contracts(this->state);
+
+ if (type.vendor_id != PEN_TCG)
+ {
+ continue;
+ }
+
+ switch (type.type)
+ {
+ case TCG_SEG_MAX_ATTR_SIZE_REQ:
+ {
+ tcg_seg_attr_max_size_t *attr_cast;
+
+ attr_cast = (tcg_seg_attr_max_size_t*)attr;
+ attr_cast->get_attr_size(attr_cast, &max_attr_size,
+ &max_seg_size);
+ contract = contracts->get_contract(contracts, this->msg_type,
+ FALSE, this->src_id);
+ if (contract)
+ {
+ contract->set_max_size(contract, max_attr_size,
+ max_seg_size);
+ }
+ else
+ {
+ contract = seg_contract_create(this->msg_type, max_attr_size,
+ max_seg_size, FALSE, this->src_id, TRUE);
+ contract->set_responder(contract, target_imc_id);
+ contracts->add_contract(contracts, contract);
+ }
+ contract->get_info_string(contract, buf, BUF_LEN, TRUE);
+ DBG2(DBG_IMC, "%s", buf);
+
+ /* Determine maximum PA-TNC attribute segment size */
+ my_max_seg_size = this->state->get_max_msg_len(this->state)
+ - PA_TNC_HEADER_SIZE
+ - PA_TNC_ATTR_HEADER_SIZE
+ - TCG_SEG_ATTR_SEG_ENV_HEADER
+ - PA_TNC_ATTR_HEADER_SIZE
+ - TCG_SEG_ATTR_MAX_SIZE_SIZE;
+
+ /* If segmentation is possible select lower segment size */
+ if (max_seg_size != SEG_CONTRACT_NO_FRAGMENTATION &&
+ max_seg_size > my_max_seg_size)
+ {
+ max_seg_size = my_max_seg_size;
+ contract->set_max_size(contract, max_attr_size,
+ max_seg_size);
+ DBG2(DBG_IMC, " lowered maximum segment size to %u bytes",
+ max_seg_size);
+ }
+
+ /* Add Maximum Attribute Size Response attribute */
+ attr = tcg_seg_attr_max_size_create(max_attr_size,
+ max_seg_size, FALSE);
+ out_msg->add_attribute(out_msg, attr);
+ break;
+ }
+ case TCG_SEG_MAX_ATTR_SIZE_RESP:
+ {
+ tcg_seg_attr_max_size_t *attr_cast;
+
+ attr_cast = (tcg_seg_attr_max_size_t*)attr;
+ attr_cast->get_attr_size(attr_cast, &max_attr_size,
+ &max_seg_size);
+ contract = contracts->get_contract(contracts, this->msg_type,
+ TRUE, this->src_id);
+ if (!contract)
+ {
+ contract = contracts->get_contract(contracts, this->msg_type,
+ TRUE, TNC_IMCID_ANY);
+ if (contract)
+ {
+ contract = contract->clone(contract);
+ contract->set_responder(contract, this->src_id);
+ contracts->add_contract(contracts, contract);
+ }
+ }
+ if (contract)
+ {
+ contract->get_max_size(contract, &my_max_attr_size,
+ &my_max_seg_size);
+ if (my_max_seg_size != SEG_CONTRACT_NO_FRAGMENTATION &&
+ my_max_seg_size > max_seg_size)
+ {
+ my_max_seg_size = max_seg_size;
+ contract->set_max_size(contract, my_max_attr_size,
+ my_max_seg_size);
+ }
+ contract->get_info_string(contract, buf, BUF_LEN, FALSE);
+ DBG2(DBG_IMC, "%s", buf);
+ }
+ else
+ {
+ /* TODO no request pending */
+ DBG1(DBG_IMC, "no contract for this PA message type found");
+ }
+ break;
+ }
+ case TCG_SEG_ATTR_SEG_ENV:
+ {
+ tcg_seg_attr_seg_env_t *seg_env_attr;
+ pa_tnc_attr_t *error;
+ uint32_t base_attr_id;
+ bool more;
+
+ seg_env_attr = (tcg_seg_attr_seg_env_t*)attr;
+ base_attr_id = seg_env_attr->get_base_attr_id(seg_env_attr);
+
+ contract = contracts->get_contract(contracts, this->msg_type,
+ TRUE, this->src_id);
+ if (!contract)
+ {
+ DBG2(DBG_IMC, "no contract for received attribute segment "
+ "with base attribute ID %u", base_attr_id);
+ continue;
+ }
+ attr = contract->add_segment(contract, attr, &error, &more);
+ if (error)
+ {
+ out_msg->add_attribute(out_msg, error);
+ }
+ if (attr)
+ {
+ this->pa_msg->add_attribute(this->pa_msg, attr);
+ }
+ if (more)
+ {
+ /* Send Next Segment Request */
+ attr = tcg_seg_attr_next_seg_create(base_attr_id, FALSE);
+ out_msg->add_attribute(out_msg, attr);
+ }
+ break;
+ }
+ case TCG_SEG_NEXT_SEG_REQ:
+ {
+ tcg_seg_attr_next_seg_t *attr_cast;
+ uint32_t base_attr_id;
+
+ attr_cast = (tcg_seg_attr_next_seg_t*)attr;
+ base_attr_id = attr_cast->get_base_attr_id(attr_cast);
+
+ contract = contracts->get_contract(contracts, this->msg_type,
+ FALSE, this->src_id);
+ if (!contract)
+ {
+ /* TODO no contract - generate error message */
+ DBG1(DBG_IMC, "no contract for received next segment "
+ "request with base attribute ID %u", base_attr_id);
+ continue;
+ }
+ attr = contract->next_segment(contract, base_attr_id);
+ if (attr)
+ {
+ out_msg->add_attribute(out_msg, attr);
+ }
+ else
+ {
+ /* TODO no more segments - generate error message */
+ DBG1(DBG_IMC, "no more segments found for "
+ "base attribute ID %u", base_attr_id);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
/* preprocess any received IETF standard error attributes */
- *fatal_error = this->pa_msg->process_ietf_std_errors(this->pa_msg);
+ non_fatal_types = this->agent->get_non_fatal_attr_types(this->agent);
+ *fatal_error = this->pa_msg->process_ietf_std_errors(this->pa_msg,
+ non_fatal_types);
/* preprocess any received IETF assessment result attribute */
enumerator = this->pa_msg->create_attribute_enumerator(this->pa_msg);
@@ -297,16 +492,16 @@ METHOD(imc_msg_t, receive, TNC_Result,
if (attr_type.type == IETF_ATTR_ASSESSMENT_RESULT)
{
ietf_attr_assess_result_t *attr_cast;
- TNC_IMV_Evaluation_Result result;
+ TNC_IMV_Evaluation_Result res;
attr_cast = (ietf_attr_assess_result_t*)attr;
- result = attr_cast->get_result(attr_cast);
- this->state->set_result(this->state, target_imc_id, result);
+ res = attr_cast->get_result(attr_cast);
+ this->state->set_result(this->state, target_imc_id, res);
print_assessment_header(this->agent->get_name(this->agent),
target_imc_id, this->src_id, &first);
DBG1(DBG_IMC, "assessment result is '%N'",
- TNC_IMV_Evaluation_Result_names, result);
+ TNC_IMV_Evaluation_Result_names, res);
}
else if (attr_type.type == IETF_ATTR_REMEDIATION_INSTRUCTIONS)
{
diff --git a/src/libimcv/imc/imc_msg.h b/src/libimcv/imc/imc_msg.h
index 588225dbe..a8c4d3c02 100644
--- a/src/libimcv/imc/imc_msg.h
+++ b/src/libimcv/imc/imc_msg.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Andreas Steffen
+ * Copyright (C) 2012-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -65,10 +65,12 @@ struct imc_msg_t {
/**
* Processes a received PA-TNC message
*
+ * @param out_msg outgoing PA-TN message
* @param fatal_error TRUE if IMV sent a fatal error message
* @return TNC result code
*/
- TNC_Result (*receive)(imc_msg_t *this, bool *fatal_error);
+ TNC_Result (*receive)(imc_msg_t *this, imc_msg_t *out_msg,
+ bool *fatal_error);
/**
* Add a PA-TNC attribute to the send queue
diff --git a/src/libimcv/imc/imc_os_info.h b/src/libimcv/imc/imc_os_info.h
index a6db44314..6bb0e960c 100644
--- a/src/libimcv/imc/imc_os_info.h
+++ b/src/libimcv/imc/imc_os_info.h
@@ -15,7 +15,7 @@
/**
* @defgroup imc_os_info imc_os_info
- * @{ @ingroup libimcv
+ * @{ @ingroup libimcv_imc
*/
#ifndef IMC_OS_INFO_H_
diff --git a/src/libimcv/imc/imc_state.h b/src/libimcv/imc/imc_state.h
index 7e763fbe1..efcf567f0 100644
--- a/src/libimcv/imc/imc_state.h
+++ b/src/libimcv/imc/imc_state.h
@@ -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
@@ -22,6 +22,8 @@
#ifndef IMC_STATE_H_
#define IMC_STATE_H_
+#include "seg/seg_contract_manager.h"
+
#include <tncif.h>
#include <tncifimv.h>
#include <tncifimc.h>
@@ -80,6 +82,13 @@ struct imc_state_t {
u_int32_t (*get_max_msg_len)(imc_state_t *this);
/**
+ * Get attribute segmentation contracts associated with TNCCS Connection
+ *
+ * @return contracts associated with TNCCS Connection
+ */
+ seg_contract_manager_t* (*get_contracts)(imc_state_t *this);
+
+ /**
* Change the connection state
*
* @param new_state new connection state
diff --git a/src/libimcv/imcv.c b/src/libimcv/imcv.c
index 30679a33d..bd4156c19 100644
--- a/src/libimcv/imcv.c
+++ b/src/libimcv/imcv.c
@@ -15,6 +15,14 @@
#include "imcv.h"
#include "ietf/ietf_attr.h"
#include "ita/ita_attr.h"
+#include "tcg/tcg_attr.h"
+#include "pts/components/pts_component.h"
+#include "pts/components/pts_component_manager.h"
+#include "pts/components/tcg/tcg_comp_func_name.h"
+#include "pts/components/ita/ita_comp_func_name.h"
+#include "pts/components/ita/ita_comp_ima.h"
+#include "pts/components/ita/ita_comp_tboot.h"
+#include "pts/components/ita/ita_comp_tgrub.h"
#include <utils/debug.h>
#include <utils/utils.h>
@@ -24,8 +32,12 @@
#include <syslog.h>
#endif
+#ifndef IPSEC_SCRIPT
+#define IPSEC_SCRIPT "ipsec"
+#endif
+
#define IMCV_DEBUG_LEVEL 1
-#define IMCV_DEFAULT_POLICY_SCRIPT "ipsec _imv_policy"
+#define IMCV_DEFAULT_POLICY_SCRIPT IPSEC_SCRIPT " _imv_policy"
/**
@@ -44,6 +56,11 @@ imv_session_manager_t *imcv_sessions;
imv_database_t *imcv_db;
/**
+ * PTS Functional Component manager
+ */
+pts_component_manager_t *imcv_pts_components;
+
+/**
* Reference count for libimcv
*/
static refcount_t libimcv_ref = 0;
@@ -162,7 +179,26 @@ bool libimcv_init(bool is_imv)
ietf_attr_create_from_data, ietf_attr_names);
imcv_pa_tnc_attributes->add_vendor(imcv_pa_tnc_attributes, PEN_ITA,
ita_attr_create_from_data, ita_attr_names);
-
+ imcv_pa_tnc_attributes->add_vendor(imcv_pa_tnc_attributes, PEN_TCG,
+ tcg_attr_create_from_data, tcg_attr_names);
+
+ imcv_pts_components = pts_component_manager_create();
+ imcv_pts_components->add_vendor(imcv_pts_components, PEN_TCG,
+ pts_tcg_comp_func_names, PTS_TCG_QUALIFIER_TYPE_SIZE,
+ pts_tcg_qualifier_flag_names, pts_tcg_qualifier_type_names);
+ imcv_pts_components->add_vendor(imcv_pts_components, PEN_ITA,
+ pts_ita_comp_func_names, PTS_ITA_QUALIFIER_TYPE_SIZE,
+ pts_ita_qualifier_flag_names, pts_ita_qualifier_type_names);
+
+ imcv_pts_components->add_component(imcv_pts_components, PEN_ITA,
+ PTS_ITA_COMP_FUNC_NAME_TGRUB,
+ pts_ita_comp_tgrub_create);
+ imcv_pts_components->add_component(imcv_pts_components, PEN_ITA,
+ PTS_ITA_COMP_FUNC_NAME_TBOOT,
+ pts_ita_comp_tboot_create);
+ imcv_pts_components->add_component(imcv_pts_components, PEN_ITA,
+ PTS_ITA_COMP_FUNC_NAME_IMA,
+ pts_ita_comp_ima_create);
if (is_imv)
{
/* instantiate global IMV session manager */
@@ -193,8 +229,13 @@ void libimcv_deinit(void)
{
if (ref_put(&libimcv_ref))
{
+ imcv_pts_components->remove_vendor(imcv_pts_components, PEN_TCG);
+ imcv_pts_components->remove_vendor(imcv_pts_components, PEN_ITA);
+ imcv_pts_components->destroy(imcv_pts_components);
+
imcv_pa_tnc_attributes->remove_vendor(imcv_pa_tnc_attributes, PEN_IETF);
imcv_pa_tnc_attributes->remove_vendor(imcv_pa_tnc_attributes, PEN_ITA);
+ imcv_pa_tnc_attributes->remove_vendor(imcv_pa_tnc_attributes, PEN_TCG);
DESTROY_IF(imcv_pa_tnc_attributes);
imcv_pa_tnc_attributes = NULL;
DESTROY_IF(imcv_db);
diff --git a/src/libimcv/imcv.h b/src/libimcv/imcv.h
index 771038803..31536eca5 100644
--- a/src/libimcv/imcv.h
+++ b/src/libimcv/imcv.h
@@ -27,6 +27,12 @@
* @defgroup libimcv_plugins plugins
* @ingroup libimcv
*
+ * @defgroup libimcv_seg seg
+ * @ingroup libimcv
+ *
+ * @defgroup libimcv_swid swid
+ * @ingroup libimcv
+ *
* @addtogroup libimcv
* @{
*/
@@ -37,6 +43,7 @@
#include "pa_tnc/pa_tnc_attr_manager.h"
#include "imv/imv_database.h"
#include "imv/imv_session_manager.h"
+#include "pts/components/pts_component_manager.h"
#include <library.h>
@@ -68,4 +75,9 @@ extern imv_database_t* imcv_db;
*/
extern imv_session_manager_t* imcv_sessions;
+/**
+ * PTS Functional Component manager
+ */
+extern pts_component_manager_t* imcv_pts_components;
+
#endif /** IMCV_H_ @}*/
diff --git a/src/libimcv/imcv_tests.c b/src/libimcv/imcv_tests.c
new file mode 100644
index 000000000..e9bb303b4
--- /dev/null
+++ b/src/libimcv/imcv_tests.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <test_runner.h>
+
+#include <library.h>
+
+/* declare test suite constructors */
+#define TEST_SUITE(x) test_suite_t* x();
+#include "imcv_tests.h"
+#undef TEST_SUITE
+
+static test_configuration_t tests[] = {
+#define TEST_SUITE(x) \
+ { .suite = x, },
+#include "imcv_tests.h"
+ { .suite = NULL, }
+};
+
+static bool test_runner_init(bool init)
+{
+ if (!init)
+ {
+ lib->processor->set_threads(lib->processor, 0);
+ lib->processor->cancel(lib->processor);
+ }
+ return TRUE;
+}
+
+int main(int argc, char *argv[])
+{
+ return test_runner_run("libimcv", tests, test_runner_init);
+}
diff --git a/src/libimcv/imcv_tests.h b/src/libimcv/imcv_tests.h
new file mode 100644
index 000000000..d3ea24b1f
--- /dev/null
+++ b/src/libimcv/imcv_tests.h
@@ -0,0 +1,17 @@
+/*
+ * 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.
+ */
+
+TEST_SUITE(imcv_seg_suite_create)
+
diff --git a/src/libimcv/imv/data.sql b/src/libimcv/imv/data.sql
index b45cad487..425748f59 100644
--- a/src/libimcv/imv/data.sql
+++ b/src/libimcv/imv/data.sql
@@ -306,6 +306,23 @@ INSERT INTO products ( /* 51 */
'Android 4.4.4'
);
+INSERT INTO products ( /* 52 */
+ name
+) VALUES (
+ 'Debian 7.6 i686'
+);
+
+INSERT INTO products ( /* 53 */
+ name
+) VALUES (
+ 'Debian 7.6 x86_64'
+);
+INSERT INTO products ( /* 54 */
+ name
+) VALUES (
+ 'Debian 7.6 armv6l'
+);
+
/* Directories */
INSERT INTO directories ( /* 1 */
@@ -777,6 +794,12 @@ INSERT INTO groups_product_defaults (
INSERT INTO groups_product_defaults (
group_id, product_id
) VALUES (
+ 4, 52
+);
+
+INSERT INTO groups_product_defaults (
+ group_id, product_id
+) VALUES (
5, 2
);
@@ -825,6 +848,12 @@ INSERT INTO groups_product_defaults (
INSERT INTO groups_product_defaults (
group_id, product_id
) VALUES (
+ 5, 53
+);
+
+INSERT INTO groups_product_defaults (
+ group_id, product_id
+) VALUES (
6, 9
);
@@ -1026,6 +1055,12 @@ INSERT INTO groups_product_defaults (
14, 48
);
+INSERT INTO groups_product_defaults (
+ group_id, product_id
+) VALUES (
+ 14, 54
+);
+
/* Policies */
INSERT INTO policies ( /* 1 */
diff --git a/src/libimcv/imv/imv_agent.c b/src/libimcv/imv/imv_agent.c
index a46455d47..6b24f4b28 100644
--- a/src/libimcv/imv/imv_agent.c
+++ b/src/libimcv/imv/imv_agent.c
@@ -65,6 +65,11 @@ struct private_imv_agent_t {
linked_list_t *additional_ids;
/**
+ * list of non-fatal unsupported PA-TNC attribute types
+ */
+ linked_list_t *non_fatal_attr_types;
+
+ /**
* list of TNCS connection entries
*/
linked_list_t *connections;
@@ -772,11 +777,29 @@ METHOD(imv_agent_t, provide_recommendation, TNC_Result,
return this->provide_recommendation(this->id, connection_id, rec, eval);
}
+METHOD(imv_agent_t, add_non_fatal_attr_type, void,
+ private_imv_agent_t *this, pen_type_t type)
+{
+ pen_type_t *type_p;
+
+ type_p = malloc_thing(pen_type_t);
+ *type_p = type;
+ this->non_fatal_attr_types->insert_last(this->non_fatal_attr_types, type_p);
+}
+
+METHOD(imv_agent_t, get_non_fatal_attr_types, linked_list_t*,
+ private_imv_agent_t *this)
+{
+ return this->non_fatal_attr_types;
+}
+
METHOD(imv_agent_t, destroy, void,
private_imv_agent_t *this)
{
DBG1(DBG_IMV, "IMV %u \"%s\" terminated", this->id, this->name);
this->additional_ids->destroy(this->additional_ids);
+ this->non_fatal_attr_types->destroy_function(this->non_fatal_attr_types,
+ free);
this->connections->destroy_offset(this->connections,
offsetof(imv_state_t, destroy));
this->connection_lock->destroy(this->connection_lock);
@@ -815,6 +838,8 @@ imv_agent_t *imv_agent_create(const char *name,
.create_id_enumerator = _create_id_enumerator,
.create_language_enumerator = _create_language_enumerator,
.provide_recommendation = _provide_recommendation,
+ .add_non_fatal_attr_type = _add_non_fatal_attr_type,
+ .get_non_fatal_attr_types = _get_non_fatal_attr_types,
.destroy = _destroy,
},
.name = name,
@@ -822,6 +847,7 @@ imv_agent_t *imv_agent_create(const char *name,
.type_count = type_count,
.id = id,
.additional_ids = linked_list_create(),
+ .non_fatal_attr_types = linked_list_create(),
.connections = linked_list_create(),
.connection_lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
);
diff --git a/src/libimcv/imv/imv_agent.h b/src/libimcv/imv/imv_agent.h
index 47ce770bc..1f6a10b7c 100644
--- a/src/libimcv/imv/imv_agent.h
+++ b/src/libimcv/imv/imv_agent.h
@@ -189,6 +189,16 @@ struct imv_agent_t {
TNC_Result (*provide_recommendation)(imv_agent_t *this, imv_state_t* state);
/**
+ * Add an item to the list of non-fatal unsupported PA-TNC attribute types
+ */
+ void (*add_non_fatal_attr_type)(imv_agent_t *this, pen_type_t type);
+
+ /**
+ * Get a list of non-fatal unsupported PA-TNC attribute types
+ */
+ linked_list_t* (*get_non_fatal_attr_types)(imv_agent_t *this);
+
+ /**
* Destroys an imv_agent_t object
*/
void (*destroy)(imv_agent_t *this);
diff --git a/src/libimcv/imv/imv_msg.c b/src/libimcv/imv/imv_msg.c
index e7181750c..fdf63325d 100644
--- a/src/libimcv/imv/imv_msg.c
+++ b/src/libimcv/imv/imv_msg.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Andreas Steffen
+ * Copyright (C) 2012-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -18,8 +18,12 @@
#include "ietf/ietf_attr.h"
#include "ietf/ietf_attr_assess_result.h"
#include "ietf/ietf_attr_remediation_instr.h"
+#include "tcg/seg/tcg_seg_attr_max_size.h"
+#include "tcg/seg/tcg_seg_attr_seg_env.h"
+#include "tcg/seg/tcg_seg_attr_next_seg.h"
#include <tncif_names.h>
+#include <tncif_pa_subtypes.h>
#include <pen/pen.h>
#include <collections/linked_list.h>
@@ -121,11 +125,18 @@ METHOD(imv_msg_t, send_, TNC_Result,
pa_tnc_attr_t *attr;
TNC_UInt32 msg_flags;
TNC_MessageType msg_type;
- bool attr_added;
+ bool attr_added, oversize;
chunk_t msg;
+ seg_contract_t *contract;
+ seg_contract_manager_t *contracts;
enumerator_t *enumerator;
TNC_Result result = TNC_RESULT_SUCCESS;
+ /* Get IF-M segmentation contract for this subtype if any */
+ contracts = this->state->get_contracts(this->state);
+ contract = contracts->get_contract(contracts, this->msg_type,
+ FALSE, this->dst_id);
+
while (this->attr_list->get_count(this->attr_list))
{
pa_tnc_msg = pa_tnc_msg_create(this->state->get_max_msg_len(this->state));
@@ -134,6 +145,17 @@ METHOD(imv_msg_t, send_, TNC_Result,
enumerator = this->attr_list->create_enumerator(this->attr_list);
while (enumerator->enumerate(enumerator, &attr))
{
+ if (contract && contract->check_size(contract, attr, &oversize))
+ {
+ if (oversize)
+ {
+ /* TODO generate SWID error msg */
+ }
+ else
+ {
+ attr = contract->first_segment(contract, attr);
+ }
+ }
if (pa_tnc_msg->add_attribute(pa_tnc_msg, attr))
{
attr_added = TRUE;
@@ -246,8 +268,11 @@ METHOD(imv_msg_t, send_assessment, TNC_Result,
}
METHOD(imv_msg_t, receive, TNC_Result,
- private_imv_msg_t *this, bool *fatal_error)
+ private_imv_msg_t *this, imv_msg_t *out_msg, bool *fatal_error)
{
+ TNC_Result result = TNC_RESULT_SUCCESS;
+ TNC_UInt32 target_imv_id;
+ linked_list_t *non_fatal_types;
enumerator_t *enumerator;
pa_tnc_attr_t *attr;
chunk_t msg;
@@ -286,36 +311,211 @@ METHOD(imv_msg_t, receive, TNC_Result,
break;
case VERIFY_ERROR:
{
- imv_msg_t *error_msg;
- TNC_Result result;
-
- error_msg = imv_msg_create_as_reply(&this->public);
-
/* extract and copy by reference all error attributes */
enumerator = this->pa_msg->create_error_enumerator(this->pa_msg);
while (enumerator->enumerate(enumerator, &attr))
{
- error_msg->add_attribute(error_msg, attr->get_ref(attr));
+ out_msg->add_attribute(out_msg, attr->get_ref(attr));
}
enumerator->destroy(enumerator);
-
- /*
- * send the PA-TNC message containing all error attributes
- * with the excl flag set
- */
- result = error_msg->send(error_msg, TRUE);
- error_msg->destroy(error_msg);
- return result;
}
case FAILED:
default:
return TNC_RESULT_FATAL;
}
+ /* determine target IMV ID */
+ target_imv_id = (this->dst_id != TNC_IMVID_ANY) ?
+ this->dst_id : this->agent->get_id(this->agent);
+
+ /* process IF-M segmentation attributes */
+ enumerator = this->pa_msg->create_attribute_enumerator(this->pa_msg);
+ while (enumerator->enumerate(enumerator, &attr))
+ {
+ uint32_t max_attr_size, max_seg_size, my_max_attr_size, my_max_seg_size;
+ seg_contract_manager_t *contracts;
+ seg_contract_t *contract;
+ char buf[BUF_LEN];
+ pen_type_t type;
+
+ type = attr->get_type(attr);
+
+ if (type.vendor_id != PEN_TCG)
+ {
+ continue;
+ }
+
+ contracts = this->state->get_contracts(this->state);
+
+ switch (type.type)
+ {
+ case TCG_SEG_MAX_ATTR_SIZE_REQ:
+ {
+ tcg_seg_attr_max_size_t *attr_cast;
+
+ attr_cast = (tcg_seg_attr_max_size_t*)attr;
+ attr_cast->get_attr_size(attr_cast, &max_attr_size,
+ &max_seg_size);
+ contract = contracts->get_contract(contracts, this->msg_type,
+ FALSE, this->src_id);
+ if (contract)
+ {
+ contract->set_max_size(contract, max_attr_size,
+ max_seg_size);
+ }
+ else
+ {
+ contract = seg_contract_create(this->msg_type, max_attr_size,
+ max_seg_size, FALSE, this->src_id, FALSE);
+ contract->set_responder(contract, target_imv_id);
+ contracts->add_contract(contracts, contract);
+ }
+ contract->get_info_string(contract, buf, BUF_LEN, TRUE);
+ DBG2(DBG_IMV, "%s", buf);
+
+ /* Determine maximum PA-TNC attribute segment size */
+ my_max_seg_size = this->state->get_max_msg_len(this->state)
+ - PA_TNC_HEADER_SIZE
+ - PA_TNC_ATTR_HEADER_SIZE
+ - TCG_SEG_ATTR_SEG_ENV_HEADER
+ - PA_TNC_ATTR_HEADER_SIZE
+ - TCG_SEG_ATTR_MAX_SIZE_SIZE;
+
+ /* If segmentation is possible select lower segment size */
+ if (max_seg_size != SEG_CONTRACT_NO_FRAGMENTATION &&
+ max_seg_size > my_max_seg_size)
+ {
+ max_seg_size = my_max_seg_size;
+ contract->set_max_size(contract, max_attr_size,
+ max_seg_size);
+ DBG2(DBG_IMV, " lowered maximum segment size to %u bytes",
+ max_seg_size);
+ }
+
+ /* Add Maximum Attribute Size Response attribute */
+ attr = tcg_seg_attr_max_size_create(max_attr_size,
+ max_seg_size, FALSE);
+ out_msg->add_attribute(out_msg, attr);
+ break;
+ }
+ case TCG_SEG_MAX_ATTR_SIZE_RESP:
+ {
+ tcg_seg_attr_max_size_t *attr_cast;
+
+ attr_cast = (tcg_seg_attr_max_size_t*)attr;
+ attr_cast->get_attr_size(attr_cast, &max_attr_size,
+ &max_seg_size);
+ contract = contracts->get_contract(contracts, this->msg_type,
+ TRUE, this->src_id);
+ if (!contract)
+ {
+ contract = contracts->get_contract(contracts, this->msg_type,
+ TRUE, TNC_IMCID_ANY);
+ if (contract)
+ {
+ contract = contract->clone(contract);
+ contract->set_responder(contract, this->src_id);
+ contracts->add_contract(contracts, contract);
+ }
+ }
+ if (contract)
+ {
+ contract->get_max_size(contract, &my_max_attr_size,
+ &my_max_seg_size);
+ if (my_max_seg_size != SEG_CONTRACT_NO_FRAGMENTATION &&
+ my_max_seg_size > max_seg_size)
+ {
+ my_max_seg_size = max_seg_size;
+ contract->set_max_size(contract, my_max_attr_size,
+ my_max_seg_size);
+ }
+ contract->get_info_string(contract, buf, BUF_LEN, FALSE);
+ DBG2(DBG_IMV, "%s", buf);
+ }
+ else
+ {
+ /* TODO no request pending */
+ DBG1(DBG_IMV, "no contract for this PA message type found");
+ }
+ break;
+ }
+ case TCG_SEG_ATTR_SEG_ENV:
+ {
+ tcg_seg_attr_seg_env_t *seg_env_attr;
+ pa_tnc_attr_t *error;
+ uint32_t base_attr_id;
+ bool more;
+
+ seg_env_attr = (tcg_seg_attr_seg_env_t*)attr;
+ base_attr_id = seg_env_attr->get_base_attr_id(seg_env_attr);
+
+ contract = contracts->get_contract(contracts, this->msg_type,
+ TRUE, this->src_id);
+ if (!contract)
+ {
+ DBG2(DBG_IMV, "no contract for received attribute segment "
+ "with base attribute ID %u", base_attr_id);
+ continue;
+ }
+ attr = contract->add_segment(contract, attr, &error, &more);
+ if (error)
+ {
+ out_msg->add_attribute(out_msg, error);
+ }
+ if (attr)
+ {
+ this->pa_msg->add_attribute(this->pa_msg, attr);
+ }
+ if (more)
+ {
+ /* Send Next Segment Request */
+ attr = tcg_seg_attr_next_seg_create(base_attr_id, FALSE);
+ out_msg->add_attribute(out_msg, attr);
+ }
+ break;
+ }
+ case TCG_SEG_NEXT_SEG_REQ:
+ {
+ tcg_seg_attr_next_seg_t *attr_cast;
+ uint32_t base_attr_id;
+
+ attr_cast = (tcg_seg_attr_next_seg_t*)attr;
+ base_attr_id = attr_cast->get_base_attr_id(attr_cast);
+
+ contract = contracts->get_contract(contracts, this->msg_type,
+ FALSE, this->src_id);
+ if (!contract)
+ {
+ /* TODO no contract - generate error message */
+ DBG1(DBG_IMV, "no contract for received next segment "
+ "request with base attribute ID %u", base_attr_id);
+ continue;
+ }
+ attr = contract->next_segment(contract, base_attr_id);
+ if (attr)
+ {
+ out_msg->add_attribute(out_msg, attr);
+ }
+ else
+ {
+ /* TODO no more segments - generate error message */
+ DBG1(DBG_IMV, "no more segments found for "
+ "base attribute ID %u", base_attr_id);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
/* preprocess any received IETF standard error attributes */
- *fatal_error = this->pa_msg->process_ietf_std_errors(this->pa_msg);
+ non_fatal_types = this->agent->get_non_fatal_attr_types(this->agent);
+ *fatal_error = this->pa_msg->process_ietf_std_errors(this->pa_msg,
+ non_fatal_types);
- return TNC_RESULT_SUCCESS;
+ return result;
}
METHOD(imv_msg_t, get_attribute_count, int,
diff --git a/src/libimcv/imv/imv_msg.h b/src/libimcv/imv/imv_msg.h
index dfec169cc..43b91e908 100644
--- a/src/libimcv/imv/imv_msg.h
+++ b/src/libimcv/imv/imv_msg.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Andreas Steffen
+ * Copyright (C) 2012-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -79,10 +79,12 @@ struct imv_msg_t {
/**
* Processes a received PA-TNC message
*
+ * @param out_msg outgoing PA-TN message
* @param fatal_error TRUE if IMC sent a fatal error message
* @return TNC result code
*/
- TNC_Result (*receive)(imv_msg_t *this, bool *fatal_error);
+ TNC_Result (*receive)(imv_msg_t *this, imv_msg_t *out_msg,
+ bool *fatal_error);
/**
* Add a PA-TNC attribute to the send queue
diff --git a/src/libimcv/imv/imv_os_info.h b/src/libimcv/imv/imv_os_info.h
index b68a17ee7..7cd609a22 100644
--- a/src/libimcv/imv/imv_os_info.h
+++ b/src/libimcv/imv/imv_os_info.h
@@ -15,7 +15,7 @@
/**
* @defgroup imv_os_info imv_os_info
- * @{ @ingroup libimcv
+ * @{ @ingroup libimcv_imv
*/
#ifndef IMV_OS_INFO_H_
diff --git a/src/libimcv/imv/imv_state.h b/src/libimcv/imv/imv_state.h
index d11d15e0d..30ed612b3 100644
--- a/src/libimcv/imv/imv_state.h
+++ b/src/libimcv/imv/imv_state.h
@@ -23,6 +23,7 @@
#define IMV_STATE_H_
#include "imv_session.h"
+#include "seg/seg_contract_manager.h"
#include <tncifimv.h>
@@ -108,6 +109,13 @@ struct imv_state_t {
imv_session_t* (*get_session)(imv_state_t *this);
/**
+ * Get attribute segmentation contracts associated with TNCCS Connection
+ *
+ * @return Contracts associated with TNCCS Connection
+ */
+ seg_contract_manager_t* (*get_contracts)(imv_state_t *this);
+
+ /**
* Change the connection state
*
* @param new_state new connection state
diff --git a/src/libimcv/ita/ita_attr.c b/src/libimcv/ita/ita_attr.c
index f3956717d..9d7706dba 100644
--- a/src/libimcv/ita/ita_attr.c
+++ b/src/libimcv/ita/ita_attr.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
@@ -35,24 +35,25 @@ ENUM(ita_attr_names, ITA_ATTR_COMMAND, ITA_ATTR_DEVICE_ID,
/**
* See header
*/
-pa_tnc_attr_t* ita_attr_create_from_data(u_int32_t type, chunk_t value)
+pa_tnc_attr_t* ita_attr_create_from_data(u_int32_t type, size_t length,
+ chunk_t value)
{
switch (type)
{
case ITA_ATTR_COMMAND:
- return ita_attr_command_create_from_data(value);
+ return ita_attr_command_create_from_data(length, value);
case ITA_ATTR_DUMMY:
- return ita_attr_dummy_create_from_data(value);
+ return ita_attr_dummy_create_from_data(length, value);
case ITA_ATTR_GET_SETTINGS:
- return ita_attr_get_settings_create_from_data(value);
+ return ita_attr_get_settings_create_from_data(length, value);
case ITA_ATTR_SETTINGS:
- return ita_attr_settings_create_from_data(value);
+ return ita_attr_settings_create_from_data(length, value);
case ITA_ATTR_START_ANGEL:
- return ita_attr_angel_create_from_data(TRUE, value);
+ return ita_attr_angel_create_from_data(TRUE);
case ITA_ATTR_STOP_ANGEL:
- return ita_attr_angel_create_from_data(FALSE, value);
+ return ita_attr_angel_create_from_data(FALSE);
case ITA_ATTR_DEVICE_ID:
- return ita_attr_device_id_create_from_data(value);
+ return ita_attr_device_id_create_from_data(length, value);
default:
return NULL;
}
diff --git a/src/libimcv/ita/ita_attr.h b/src/libimcv/ita/ita_attr.h
index ac5d8abaa..7378a1cbe 100644
--- a/src/libimcv/ita/ita_attr.h
+++ b/src/libimcv/ita/ita_attr.h
@@ -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
@@ -50,8 +50,10 @@ extern enum_name_t *ita_attr_names;
* Create a ITA PA-TNC attribute from data
*
* @param type attribute type
- * @param value attribute value
+ * @param length attribute length
+ * @param value attribute value or segment
*/
-pa_tnc_attr_t* ita_attr_create_from_data(u_int32_t type, chunk_t value);
+pa_tnc_attr_t* ita_attr_create_from_data(u_int32_t type, size_t length,
+ chunk_t value);
#endif /** ITA_ATTR_H_ @}*/
diff --git a/src/libimcv/ita/ita_attr_angel.c b/src/libimcv/ita/ita_attr_angel.c
index 0e9cff0a9..110863608 100644
--- a/src/libimcv/ita/ita_attr_angel.c
+++ b/src/libimcv/ita/ita_attr_angel.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Andreas Steffen
+ * Copyright (C) 2012-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -86,6 +86,12 @@ METHOD(pa_tnc_attr_t, process, status_t,
return SUCCESS;
}
+METHOD(pa_tnc_attr_t, add_segment, void,
+ private_ita_attr_angel_t *this, chunk_t segment)
+{
+ /* nothing to add */
+}
+
METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
private_ita_attr_angel_t *this)
{
@@ -118,6 +124,7 @@ pa_tnc_attr_t *ita_attr_angel_create(bool start)
.set_noskip_flag = _set_noskip_flag,
.build = _build,
.process = _process,
+ .add_segment = _add_segment,
.get_ref = _get_ref,
.destroy = _destroy,
},
@@ -132,7 +139,7 @@ pa_tnc_attr_t *ita_attr_angel_create(bool start)
/**
* Described in header.
*/
-pa_tnc_attr_t *ita_attr_angel_create_from_data(bool start, chunk_t data)
+pa_tnc_attr_t *ita_attr_angel_create_from_data(bool start)
{
private_ita_attr_angel_t *this;
@@ -145,6 +152,7 @@ pa_tnc_attr_t *ita_attr_angel_create_from_data(bool start, chunk_t data)
.set_noskip_flag = _set_noskip_flag,
.build = _build,
.process = _process,
+ .add_segment = _add_segment,
.get_ref = _get_ref,
.destroy = _destroy,
},
diff --git a/src/libimcv/ita/ita_attr_angel.h b/src/libimcv/ita/ita_attr_angel.h
index d42e7119a..8cd979b01 100644
--- a/src/libimcv/ita/ita_attr_angel.h
+++ b/src/libimcv/ita/ita_attr_angel.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Andreas Steffen
+ * Copyright (C) 2012-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -49,8 +49,7 @@ pa_tnc_attr_t* ita_attr_angel_create(bool start);
* Creates an ita_attr_angel_t object from received data
*
* @param start TRUE for Start, FALSE for Stop Angel attribute
- * @param value binary value blob
*/
-pa_tnc_attr_t* ita_attr_angel_create_from_data(bool start, chunk_t value);
+pa_tnc_attr_t* ita_attr_angel_create_from_data(bool start);
#endif /** ITA_ATTR_ANGEL_H_ @}*/
diff --git a/src/libimcv/ita/ita_attr_command.c b/src/libimcv/ita/ita_attr_command.c
index 9692e1ffd..a6b187f13 100644
--- a/src/libimcv/ita/ita_attr_command.c
+++ b/src/libimcv/ita/ita_attr_command.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
@@ -40,7 +40,12 @@ struct private_ita_attr_command_t {
pen_type_t type;
/**
- * Attribute value
+ * Length of attribute value
+ */
+ size_t length;
+
+ /**
+ * Attribute value or segment
*/
chunk_t value;
@@ -91,18 +96,30 @@ METHOD(pa_tnc_attr_t, build, void,
{
return;
}
- this->value = chunk_create(this->command, strlen(this->command));
- this->value = chunk_clone(this->value);
+ this->value = chunk_clone(chunk_from_str(this->command));
+ this->length = this->value.len;
}
METHOD(pa_tnc_attr_t, process, status_t,
private_ita_attr_command_t *this, u_int32_t *offset)
{
+ *offset = 0;
+
+ if (this->value.len < this->length)
+ {
+ return NEED_MORE;
+ }
this->command = strndup(this->value.ptr, this->value.len);
return SUCCESS;
}
+METHOD(pa_tnc_attr_t, add_segment, void,
+ private_ita_attr_command_t *this, chunk_t segment)
+{
+ this->value = chunk_cat("mc", this->value, segment);
+}
+
METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
private_ita_attr_command_t *this)
{
@@ -143,6 +160,7 @@ pa_tnc_attr_t *ita_attr_command_create(char *command)
.set_noskip_flag = _set_noskip_flag,
.build = _build,
.process = _process,
+ .add_segment = _add_segment,
.get_ref = _get_ref,
.destroy = _destroy,
},
@@ -159,7 +177,7 @@ pa_tnc_attr_t *ita_attr_command_create(char *command)
/**
* Described in header.
*/
-pa_tnc_attr_t *ita_attr_command_create_from_data(chunk_t data)
+pa_tnc_attr_t *ita_attr_command_create_from_data(size_t length, chunk_t data)
{
private_ita_attr_command_t *this;
@@ -172,12 +190,14 @@ pa_tnc_attr_t *ita_attr_command_create_from_data(chunk_t data)
.set_noskip_flag = _set_noskip_flag,
.build = _build,
.process = _process,
+ .add_segment = _add_segment,
.get_ref = _get_ref,
.destroy = _destroy,
},
.get_command = _get_command,
},
.type = {PEN_ITA, ITA_ATTR_COMMAND },
+ .length = length,
.value = chunk_clone(data),
.ref = 1,
);
diff --git a/src/libimcv/ita/ita_attr_command.h b/src/libimcv/ita/ita_attr_command.h
index 3926c3887..dd4701e12 100644
--- a/src/libimcv/ita/ita_attr_command.h
+++ b/src/libimcv/ita/ita_attr_command.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
@@ -54,8 +54,9 @@ pa_tnc_attr_t* ita_attr_command_create(char *command);
/**
* Creates an ita_attr_command_t object from received data
*
- * @param value binary value blob
+ * @param length Total length of attribute value
+ * @param value Unparsed attribute value (might be a segment)
*/
-pa_tnc_attr_t* ita_attr_command_create_from_data(chunk_t value);
+pa_tnc_attr_t* ita_attr_command_create_from_data(size_t length, chunk_t value);
#endif /** ITA_ATTR_COMMAND_H_ @}*/
diff --git a/src/libimcv/ita/ita_attr_device_id.c b/src/libimcv/ita/ita_attr_device_id.c
index 36907eb34..232842695 100644
--- a/src/libimcv/ita/ita_attr_device_id.c
+++ b/src/libimcv/ita/ita_attr_device_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
@@ -38,7 +38,12 @@ struct private_ita_attr_device_id_t {
pen_type_t type;
/**
- * Attribute value
+ * Length of attribute value
+ */
+ size_t length;
+
+ /**
+ * Attribute value or segment
*/
chunk_t value;
@@ -86,9 +91,21 @@ METHOD(pa_tnc_attr_t, build, void,
METHOD(pa_tnc_attr_t, process, status_t,
private_ita_attr_device_id_t *this, u_int32_t *offset)
{
+ *offset = 0;
+
+ if (this->value.len < this->length)
+ {
+ return NEED_MORE;
+ }
return SUCCESS;
}
+METHOD(pa_tnc_attr_t, add_segment, void,
+ private_ita_attr_device_id_t *this, chunk_t segment)
+{
+ this->value = chunk_cat("mc", this->value, segment);
+}
+
METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
private_ita_attr_device_id_t *this)
{
@@ -109,7 +126,7 @@ METHOD(pa_tnc_attr_t, destroy, void,
/**
* Described in header.
*/
-pa_tnc_attr_t *ita_attr_device_id_create_from_data(chunk_t value)
+pa_tnc_attr_t *ita_attr_device_id_create_from_data(size_t length, chunk_t value)
{
private_ita_attr_device_id_t *this;
@@ -122,11 +139,13 @@ pa_tnc_attr_t *ita_attr_device_id_create_from_data(chunk_t value)
.set_noskip_flag = _set_noskip_flag,
.build = _build,
.process = _process,
+ .add_segment = _add_segment,
.get_ref = _get_ref,
.destroy = _destroy,
},
},
.type = { PEN_ITA, ITA_ATTR_DEVICE_ID },
+ .length = length,
.value = chunk_clone(value),
.ref = 1,
);
@@ -139,6 +158,6 @@ pa_tnc_attr_t *ita_attr_device_id_create_from_data(chunk_t value)
*/
pa_tnc_attr_t *ita_attr_device_id_create(chunk_t value)
{
- return ita_attr_device_id_create_from_data(value);
+ return ita_attr_device_id_create_from_data(value.len, value);
}
diff --git a/src/libimcv/ita/ita_attr_device_id.h b/src/libimcv/ita/ita_attr_device_id.h
index ffacdba1e..94bb778c0 100644
--- a/src/libimcv/ita/ita_attr_device_id.h
+++ b/src/libimcv/ita/ita_attr_device_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
@@ -48,8 +48,9 @@ pa_tnc_attr_t* ita_attr_device_id_create(chunk_t value);
/**
* Creates an ita_attr_device_id_t object from received data
*
- * @param value binary value blob
+ * @param length Total length of attribute value
+ * @param value Unparsed attribute value (might be a segment)
*/
-pa_tnc_attr_t* ita_attr_device_id_create_from_data(chunk_t value);
+pa_tnc_attr_t* ita_attr_device_id_create_from_data(size_t length, chunk_t value);
#endif /** ITA_ATTR_DEVICE_ID_H_ @}*/
diff --git a/src/libimcv/ita/ita_attr_dummy.c b/src/libimcv/ita/ita_attr_dummy.c
index 6497d4645..0d21ac6ea 100644
--- a/src/libimcv/ita/ita_attr_dummy.c
+++ b/src/libimcv/ita/ita_attr_dummy.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Andreas Steffen
+ * Copyright (C) 2012-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -38,7 +38,12 @@ struct private_ita_attr_dummy_t {
pen_type_t type;
/**
- * Attribute value
+ * Length of attribute value
+ */
+ size_t length;
+
+ /**
+ * Attribute value or segment
*/
chunk_t value;
@@ -89,18 +94,28 @@ METHOD(pa_tnc_attr_t, build, void,
{
return;
}
- this->value = chunk_alloc(this->size);
+ this->value = chunk_alloc(this->length);
memset(this->value.ptr, 0xdd, this->value.len);
}
METHOD(pa_tnc_attr_t, process, status_t,
private_ita_attr_dummy_t *this, u_int32_t *offset)
{
- this->size = this->value.len;
+ *offset = 0;
+ if (this->value.len < this->length)
+ {
+ return NEED_MORE;
+ }
return SUCCESS;
}
+METHOD(pa_tnc_attr_t, add_segment, void,
+ private_ita_attr_dummy_t *this, chunk_t segment)
+{
+ this->value = chunk_cat("mc", this->value, segment);
+}
+
METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
private_ita_attr_dummy_t *this)
{
@@ -121,13 +136,13 @@ METHOD(pa_tnc_attr_t, destroy, void,
METHOD(ita_attr_dummy_t, get_size, int,
private_ita_attr_dummy_t *this)
{
- return this->size;
+ return this->length;
}
/**
* Described in header.
*/
-pa_tnc_attr_t *ita_attr_dummy_create(int size)
+pa_tnc_attr_t *ita_attr_dummy_create(size_t size)
{
private_ita_attr_dummy_t *this;
@@ -140,13 +155,14 @@ pa_tnc_attr_t *ita_attr_dummy_create(int size)
.set_noskip_flag = _set_noskip_flag,
.build = _build,
.process = _process,
+ .add_segment = _add_segment,
.get_ref = _get_ref,
.destroy = _destroy,
},
.get_size = _get_size,
},
.type = { PEN_ITA, ITA_ATTR_DUMMY },
- .size = size,
+ .length = size,
.ref = 1,
);
@@ -156,7 +172,7 @@ pa_tnc_attr_t *ita_attr_dummy_create(int size)
/**
* Described in header.
*/
-pa_tnc_attr_t *ita_attr_dummy_create_from_data(chunk_t data)
+pa_tnc_attr_t *ita_attr_dummy_create_from_data(size_t length, chunk_t data)
{
private_ita_attr_dummy_t *this;
@@ -169,12 +185,14 @@ pa_tnc_attr_t *ita_attr_dummy_create_from_data(chunk_t data)
.set_noskip_flag = _set_noskip_flag,
.build = _build,
.process = _process,
+ .add_segment = _add_segment,
.get_ref = _get_ref,
.destroy = _destroy,
},
.get_size = _get_size,
},
.type = { PEN_ITA, ITA_ATTR_DUMMY },
+ .length = length,
.value = chunk_clone(data),
.ref = 1,
);
diff --git a/src/libimcv/ita/ita_attr_dummy.h b/src/libimcv/ita/ita_attr_dummy.h
index 1f85ece54..717862efe 100644
--- a/src/libimcv/ita/ita_attr_dummy.h
+++ b/src/libimcv/ita/ita_attr_dummy.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Andreas Steffen
+ * Copyright (C) 2012-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -49,13 +49,14 @@ struct ita_attr_dummy_t {
*
* @param size size of dummy attribute value
*/
-pa_tnc_attr_t* ita_attr_dummy_create(int size);
+pa_tnc_attr_t* ita_attr_dummy_create(size_t size);
/**
* Creates an ita_attr_dummy_t object from received data
*
- * @param value binary value blob
+ * @param length Total length of attribute value
+ * @param value Unparsed attribute value (might be a segment)
*/
-pa_tnc_attr_t* ita_attr_dummy_create_from_data(chunk_t value);
+pa_tnc_attr_t* ita_attr_dummy_create_from_data(size_t length, chunk_t value);
#endif /** ITA_ATTR_DUMMY_H_ @}*/
diff --git a/src/libimcv/ita/ita_attr_get_settings.c b/src/libimcv/ita/ita_attr_get_settings.c
index d0bc31d32..3c047fb82 100644
--- a/src/libimcv/ita/ita_attr_get_settings.c
+++ b/src/libimcv/ita/ita_attr_get_settings.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Andreas Steffen
+ * Copyright (C) 2012-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -64,7 +64,12 @@ struct private_ita_attr_get_settings_t {
pen_type_t type;
/**
- * Attribute value
+ * Length of attribute value
+ */
+ size_t length;
+
+ /**
+ * Attribute value or segment
*/
chunk_t value;
@@ -130,6 +135,7 @@ METHOD(pa_tnc_attr_t, build, void,
enumerator->destroy(enumerator);
this->value = writer->extract_buf(writer);
+ this->length = this->value.len;
writer->destroy(writer);
}
@@ -141,10 +147,15 @@ METHOD(pa_tnc_attr_t, process, status_t,
chunk_t name;
status_t status = FAILED;
+ *offset = 0;
+
+ if (this->value.len < this->length)
+ {
+ return NEED_MORE;
+ }
if (this->value.len < ITA_GET_SETTINGS_MIN_SIZE)
{
DBG1(DBG_TNC, "insufficient data for ITA Get Settings attribute");
- *offset = 0;
return FAILED;
}
@@ -171,6 +182,12 @@ end:
return status;
}
+METHOD(pa_tnc_attr_t, add_segment, void,
+ private_ita_attr_get_settings_t *this, chunk_t segment)
+{
+ this->value = chunk_cat("mc", this->value, segment);
+}
+
METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
private_ita_attr_get_settings_t *this)
{
@@ -217,6 +234,7 @@ pa_tnc_attr_t *ita_attr_get_settings_create(char *name)
.set_noskip_flag = _set_noskip_flag,
.build = _build,
.process = _process,
+ .add_segment = _add_segment,
.get_ref = _get_ref,
.destroy = _destroy,
},
@@ -238,7 +256,8 @@ pa_tnc_attr_t *ita_attr_get_settings_create(char *name)
/**
* Described in header.
*/
-pa_tnc_attr_t *ita_attr_get_settings_create_from_data(chunk_t data)
+pa_tnc_attr_t *ita_attr_get_settings_create_from_data(size_t length,
+ chunk_t data)
{
private_ita_attr_get_settings_t *this;
@@ -251,6 +270,7 @@ pa_tnc_attr_t *ita_attr_get_settings_create_from_data(chunk_t data)
.set_noskip_flag = _set_noskip_flag,
.build = _build,
.process = _process,
+ .add_segment = _add_segment,
.get_ref = _get_ref,
.destroy = _destroy,
},
@@ -258,6 +278,7 @@ pa_tnc_attr_t *ita_attr_get_settings_create_from_data(chunk_t data)
.create_enumerator = _create_enumerator,
},
.type = { PEN_ITA, ITA_ATTR_GET_SETTINGS },
+ .length = length,
.value = chunk_clone(data),
.list = linked_list_create(),
.ref = 1,
diff --git a/src/libimcv/ita/ita_attr_get_settings.h b/src/libimcv/ita/ita_attr_get_settings.h
index 975fd0d9d..2eb43f5c1 100644
--- a/src/libimcv/ita/ita_attr_get_settings.h
+++ b/src/libimcv/ita/ita_attr_get_settings.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Andreas Steffen
+ * Copyright (C) 2012-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -61,8 +61,10 @@ pa_tnc_attr_t* ita_attr_get_settings_create(char *name);
/**
* Creates an ita_attr_get_settings_t object from received data
*
- * @param value binary value blob
+ * @param length Total length of attribute value
+ * @param value Unparsed attribute value (might be a segment)
*/
-pa_tnc_attr_t* ita_attr_get_settings_create_from_data(chunk_t value);
+pa_tnc_attr_t* ita_attr_get_settings_create_from_data(size_t length,
+ chunk_t value);
#endif /** ITA_ATTR_GET_SETTINGS_H_ @}*/
diff --git a/src/libimcv/ita/ita_attr_settings.c b/src/libimcv/ita/ita_attr_settings.c
index 0d2967e66..ced347705 100644
--- a/src/libimcv/ita/ita_attr_settings.c
+++ b/src/libimcv/ita/ita_attr_settings.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Andreas Steffen
+ * Copyright (C) 2012-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -91,7 +91,12 @@ struct private_ita_attr_settings_t {
pen_type_t type;
/**
- * Attribute value
+ * Length of attribute value
+ */
+ size_t length;
+
+ /**
+ * Attribute value or segment
*/
chunk_t value;
@@ -159,6 +164,7 @@ METHOD(pa_tnc_attr_t, build, void,
enumerator->destroy(enumerator);
this->value = writer->extract_buf(writer);
+ this->length = this->value.len;
writer->destroy(writer);
}
@@ -171,10 +177,15 @@ METHOD(pa_tnc_attr_t, process, status_t,
entry_t *entry;
status_t status = FAILED;
+ *offset = 0;
+
+ if (this->value.len < this->length)
+ {
+ return NEED_MORE;
+ }
if (this->value.len < ITA_SETTINGS_MIN_SIZE)
{
DBG1(DBG_TNC, "insufficient data for ITA Settings attribute");
- *offset = 0;
return FAILED;
}
@@ -216,6 +227,12 @@ end:
return status;
}
+METHOD(pa_tnc_attr_t, add_segment, void,
+ private_ita_attr_settings_t *this, chunk_t segment)
+{
+ this->value = chunk_cat("mc", this->value, segment);
+}
+
METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
private_ita_attr_settings_t *this)
{
@@ -279,6 +296,7 @@ pa_tnc_attr_t *ita_attr_settings_create(void)
.set_noskip_flag = _set_noskip_flag,
.build = _build,
.process = _process,
+ .add_segment = _add_segment,
.get_ref = _get_ref,
.destroy = _destroy,
},
@@ -296,7 +314,7 @@ pa_tnc_attr_t *ita_attr_settings_create(void)
/**
* Described in header.
*/
-pa_tnc_attr_t *ita_attr_settings_create_from_data(chunk_t data)
+pa_tnc_attr_t *ita_attr_settings_create_from_data(size_t length, chunk_t data)
{
private_ita_attr_settings_t *this;
@@ -309,6 +327,7 @@ pa_tnc_attr_t *ita_attr_settings_create_from_data(chunk_t data)
.set_noskip_flag = _set_noskip_flag,
.build = _build,
.process = _process,
+ .add_segment = _add_segment,
.get_ref = _get_ref,
.destroy = _destroy,
},
@@ -316,6 +335,7 @@ pa_tnc_attr_t *ita_attr_settings_create_from_data(chunk_t data)
.create_enumerator = _create_enumerator,
},
.type = { PEN_ITA, ITA_ATTR_SETTINGS },
+ .length = length,
.value = chunk_clone(data),
.list = linked_list_create(),
.ref = 1,
diff --git a/src/libimcv/ita/ita_attr_settings.h b/src/libimcv/ita/ita_attr_settings.h
index eb7eedae3..87eb87f60 100644
--- a/src/libimcv/ita/ita_attr_settings.h
+++ b/src/libimcv/ita/ita_attr_settings.h
@@ -60,8 +60,9 @@ pa_tnc_attr_t* ita_attr_settings_create(void);
/**
* Creates an ita_attr_settings_t object from received data
*
- * @param value binary value blob
+ * @param length Total length of attribute value
+ * @param value Unparsed attribute value (might be a segment)
*/
-pa_tnc_attr_t* ita_attr_settings_create_from_data(chunk_t value);
+pa_tnc_attr_t* ita_attr_settings_create_from_data(size_t length, chunk_t value);
#endif /** ITA_ATTR_SETTINGS_H_ @}*/
diff --git a/src/libimcv/os_info/os_info.h b/src/libimcv/os_info/os_info.h
index 031355458..aa7b137dc 100644
--- a/src/libimcv/os_info/os_info.h
+++ b/src/libimcv/os_info/os_info.h
@@ -21,7 +21,6 @@
#ifndef OS_INFO_H_
#define OS_INFO_H_
-typedef struct os_info_t os_info_t;
typedef enum os_type_t os_type_t;
typedef enum os_fwd_status_t os_fwd_status_t;
typedef enum os_package_state_t os_package_state_t;
diff --git a/src/libimcv/pa_tnc/pa_tnc_attr.h b/src/libimcv/pa_tnc/pa_tnc_attr.h
index 1e0c339c9..be0bef32e 100644
--- a/src/libimcv/pa_tnc/pa_tnc_attr.h
+++ b/src/libimcv/pa_tnc/pa_tnc_attr.h
@@ -26,8 +26,12 @@ typedef struct pa_tnc_attr_t pa_tnc_attr_t;
#include <library.h>
#include <pen/pen.h>
+#define PA_TNC_ATTR_INFO_SIZE 8
#define PA_TNC_ATTR_HEADER_SIZE 12
+#define PA_TNC_ATTR_FLAG_NONE 0x00
+#define PA_TNC_ATTR_FLAG_NOSKIP (1<<7)
+
/**
* Interface for an RFC 5792 PA-TNC Posture Attribute.
*
@@ -70,12 +74,19 @@ struct pa_tnc_attr_t {
/**
* Process the value of an PA-TNC attribute to extract its parameters
*
- * @param relative error offset within attribute body
+ * @param offset relative error offset within attribute body
* @return result status
*/
status_t (*process)(pa_tnc_attr_t *this, uint32_t *offset);
/**
+ * Add a data segment to an attribute allowing incremental processing
+ *
+ * @param segment data segment to be appended
+ */
+ void (*add_segment)(pa_tnc_attr_t *this, chunk_t segment);
+
+ /**
* Get a new reference to the PA-TNC attribute
*
* @return this, with an increased refcount
diff --git a/src/libimcv/pa_tnc/pa_tnc_attr_manager.c b/src/libimcv/pa_tnc/pa_tnc_attr_manager.c
index 900a55716..522213bd5 100644
--- a/src/libimcv/pa_tnc/pa_tnc_attr_manager.c
+++ b/src/libimcv/pa_tnc/pa_tnc_attr_manager.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Andreas Steffen
+ * Copyright (C) 2011-2014 Andreas Steffen
*
* HSR Hochschule fuer Technik Rapperswil
*
@@ -16,6 +16,10 @@
#include "pa_tnc_attr_manager.h"
+#include "imcv.h"
+#include "pa_tnc_attr.h"
+#include "ietf/ietf_attr_pa_tnc_error.h"
+
#include <collections/linked_list.h>
#include <utils/debug.h>
@@ -100,14 +104,102 @@ METHOD(pa_tnc_attr_manager_t, get_names, enum_name_t*,
return attr_names;
}
+/**
+ * PA-TNC attribute
+ *
+ * 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Flags | PA-TNC Attribute Vendor ID |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | PA-TNC Attribute Type |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | PA-TNC Attribute Length |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Attribute Value (Variable Length) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
METHOD(pa_tnc_attr_manager_t, create, pa_tnc_attr_t*,
- private_pa_tnc_attr_manager_t *this, pen_t vendor_id, u_int32_t type,
- chunk_t value)
+ private_pa_tnc_attr_manager_t *this, bio_reader_t *reader, bool segmented,
+ uint32_t *offset, chunk_t msg_info, pa_tnc_attr_t **error)
{
+ uint8_t flags;
+ uint32_t type, length, value_len;
+ chunk_t value;
+ ietf_attr_pa_tnc_error_t *error_attr;
+ pen_t vendor_id;
+ pen_type_t unsupported_type;
+ pen_type_t error_code = { PEN_IETF, PA_ERROR_INVALID_PARAMETER };
+ enum_name_t *pa_attr_names;
+ pa_tnc_attr_t *attr = NULL;
enumerator_t *enumerator;
entry_t *entry;
- pa_tnc_attr_t *attr = NULL;
+ /* properly initialize error return argument in case of no error */
+ *error = NULL;
+
+ if (reader->remaining(reader) < PA_TNC_ATTR_HEADER_SIZE)
+ {
+ DBG1(DBG_TNC, "insufficient bytes for PA-TNC attribute header");
+ *error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
+ msg_info, *offset);
+ return NULL;
+ }
+ reader->read_uint8 (reader, &flags);
+ reader->read_uint24(reader, &vendor_id);
+ reader->read_uint32(reader, &type);
+ reader->read_uint32(reader, &length);
+
+ pa_attr_names = imcv_pa_tnc_attributes->get_names(imcv_pa_tnc_attributes,
+ vendor_id);
+ if (pa_attr_names)
+ {
+ DBG2(DBG_TNC, "processing PA-TNC attribute type '%N/%N' "
+ "0x%06x/0x%08x", pen_names, vendor_id,
+ pa_attr_names, type, vendor_id, type);
+ }
+ else
+ {
+ DBG2(DBG_TNC, "processing PA-TNC attribute type '%N' "
+ "0x%06x/0x%08x", pen_names, vendor_id,
+ vendor_id, type);
+ }
+
+ if (length < PA_TNC_ATTR_HEADER_SIZE)
+ {
+ DBG1(DBG_TNC, "%u bytes too small for PA-TNC attribute length",
+ length);
+ *error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
+ msg_info, *offset + PA_TNC_ATTR_INFO_SIZE);
+ return NULL;
+ }
+ length -= PA_TNC_ATTR_HEADER_SIZE;
+ value_len = segmented ? reader->remaining(reader) : length;
+
+ if (!reader->read_data(reader, value_len, &value))
+ {
+ DBG1(DBG_TNC, "insufficient bytes for PA-TNC attribute value");
+ *error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
+ msg_info, *offset + PA_TNC_ATTR_INFO_SIZE);
+ return NULL;
+ }
+ DBG3(DBG_TNC, "%B", &value);
+
+ if (vendor_id == PEN_RESERVED)
+ {
+ *error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
+ msg_info, *offset + 1);
+ return NULL;
+ }
+ if (type == IETF_ATTR_RESERVED)
+ {
+ *error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
+ msg_info, *offset + 4);
+ return NULL;
+ }
+
+ /* check if the attribute type is registered */
enumerator = this->list->create_enumerator(this->list);
while (enumerator->enumerate(enumerator, &entry))
{
@@ -115,13 +207,71 @@ METHOD(pa_tnc_attr_manager_t, create, pa_tnc_attr_t*,
{
if (entry->attr_create)
{
- attr = entry->attr_create(type, value);
+ attr = entry->attr_create(type, length, value);
}
break;
}
}
enumerator->destroy(enumerator);
+ if (!attr)
+ {
+ if (!(flags & PA_TNC_ATTR_FLAG_NOSKIP))
+ {
+ DBG1(DBG_TNC, "skipping unsupported PA-TNC attribute");
+ (*offset) += PA_TNC_ATTR_HEADER_SIZE + length;
+ return NULL;
+ }
+
+ DBG1(DBG_TNC, "unsupported PA-TNC attribute with NOSKIP flag");
+ unsupported_type = pen_type_create(vendor_id, type);
+ error_code = pen_type_create(PEN_IETF, PA_ERROR_ATTR_TYPE_NOT_SUPPORTED);
+ *error = ietf_attr_pa_tnc_error_create(error_code, msg_info);
+ error_attr = (ietf_attr_pa_tnc_error_t*)(*error);
+ error_attr->set_unsupported_attr(error_attr, flags, unsupported_type);
+ return NULL;
+ }
+ (*offset) += PA_TNC_ATTR_HEADER_SIZE;
+
+ return attr;
+}
+
+METHOD(pa_tnc_attr_manager_t, construct, pa_tnc_attr_t*,
+ private_pa_tnc_attr_manager_t *this, pen_t vendor_id, uint32_t type,
+ chunk_t value)
+{
+ enum_name_t *pa_attr_names;
+ pa_tnc_attr_t *attr = NULL;
+ enumerator_t *enumerator;
+ entry_t *entry;
+
+ pa_attr_names = imcv_pa_tnc_attributes->get_names(imcv_pa_tnc_attributes,
+ vendor_id);
+ if (pa_attr_names)
+ {
+ DBG2(DBG_TNC, "generating PA-TNC attribute type '%N/%N' "
+ "0x%06x/0x%08x", pen_names, vendor_id,
+ pa_attr_names, type, vendor_id, type);
+ }
+ else
+ {
+ DBG2(DBG_TNC, "generating PA-TNC attribute type '%N' "
+ "0x%06x/0x%08x", pen_names, vendor_id,
+ vendor_id, type);
+ }
+ enumerator = this->list->create_enumerator(this->list);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->vendor_id == vendor_id)
+ {
+ if (entry->attr_create)
+ {
+ attr = entry->attr_create(type, value.len, value);
+ }
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
return attr;
}
@@ -145,6 +295,7 @@ pa_tnc_attr_manager_t *pa_tnc_attr_manager_create(void)
.remove_vendor = _remove_vendor,
.get_names = _get_names,
.create = _create,
+ .construct = _construct,
.destroy = _destroy,
},
.list = linked_list_create(),
diff --git a/src/libimcv/pa_tnc/pa_tnc_attr_manager.h b/src/libimcv/pa_tnc/pa_tnc_attr_manager.h
index 121be7f90..8607feede 100644
--- a/src/libimcv/pa_tnc/pa_tnc_attr_manager.h
+++ b/src/libimcv/pa_tnc/pa_tnc_attr_manager.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
@@ -26,8 +26,10 @@ typedef struct pa_tnc_attr_manager_t pa_tnc_attr_manager_t;
#include "pa_tnc_attr.h"
#include <library.h>
+#include <bio/bio_reader.h>
-typedef pa_tnc_attr_t* (*pa_tnc_attr_create_t)(u_int32_t type, chunk_t value);
+typedef pa_tnc_attr_t* (*pa_tnc_attr_create_t)(u_int32_t type, size_t length,
+ chunk_t value);
/**
* Manages PA-TNC attributes for arbitrary PENs
@@ -61,15 +63,29 @@ struct pa_tnc_attr_manager_t {
enum_name_t* (*get_names)(pa_tnc_attr_manager_t *this, pen_t vendor_id);
/**
- * Create a PA-TNC attribute object from data for a given vendor ID and type
+ * Create and pre-parse a PA-TNC attribute object from data
+ *
+ * @param reader PA-TNC attribute as encoded data
+ * @param segmented TRUE if attribute is segmented
+ * @param offset Offset in bytes where an error has been found
+ * @param msg_info Message info added to an error attribute
+ * @param error Error attribute if an error occurred
+ * @return PA-TNC attribute object if supported, NULL else
+ */
+ pa_tnc_attr_t* (*create)(pa_tnc_attr_manager_t *this, bio_reader_t *reader,
+ bool segmented, uint32_t *offset, chunk_t msg_info,
+ pa_tnc_attr_t **error);
+
+ /**
+ * Generically construct a PA-TNC attribute from type and data
*
* @param vendor_id Private Enterprise Number (PEN)
* @param type PA-TNC attribute type
* @param value PA-TNC attribute value as encoded data
* @return PA-TNC attribute object if supported, NULL else
*/
- pa_tnc_attr_t* (*create)(pa_tnc_attr_manager_t *this, pen_t vendor_id,
- u_int32_t type, chunk_t value);
+ pa_tnc_attr_t* (*construct)(pa_tnc_attr_manager_t *this, pen_t vendor_id,
+ uint32_t type, chunk_t value);
/**
* Destroys a pa_tnc_attr_manager_t object.
diff --git a/src/libimcv/pa_tnc/pa_tnc_msg.c b/src/libimcv/pa_tnc/pa_tnc_msg.c
index 77d383b93..d9b441707 100644
--- a/src/libimcv/pa_tnc/pa_tnc_msg.c
+++ b/src/libimcv/pa_tnc/pa_tnc_msg.c
@@ -40,26 +40,6 @@ typedef struct private_pa_tnc_msg_t private_pa_tnc_msg_t;
#define PA_TNC_RESERVED 0x000000
/**
- * PA-TNC attribute
- *
- * 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Flags | PA-TNC Attribute Vendor ID |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | PA-TNC Attribute Type |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | PA-TNC Attribute Length |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Attribute Value (Variable Length) |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-
-#define PA_TNC_ATTR_FLAG_NONE 0x00
-#define PA_TNC_ATTR_FLAG_NOSKIP (1<<7)
-#define PA_TNC_ATTR_INFO_SIZE 8
-
-/**
* Private data of a pa_tnc_msg_t object.
*
*/
@@ -96,6 +76,11 @@ struct private_pa_tnc_msg_t {
size_t max_msg_len;
/**
+ * TRUE if attribute was extracted from data
+ */
+ bool from_data;
+
+ /**
* Encoded message
*/
chunk_t encoding;
@@ -113,17 +98,19 @@ METHOD(pa_tnc_msg_t, add_attribute, bool,
chunk_t attr_value;
size_t attr_len;
- attr->build(attr);
- attr_value = attr->get_value(attr);
- attr_len = PA_TNC_ATTR_HEADER_SIZE + attr_value.len;
-
- if (this->max_msg_len && this->msg_len + attr_len > this->max_msg_len)
+ if (!this->from_data)
{
- /* attribute just does not fit into this message */
- return FALSE;
- }
- this->msg_len += attr_len;
+ attr->build(attr);
+ attr_value = attr->get_value(attr);
+ attr_len = PA_TNC_ATTR_HEADER_SIZE + attr_value.len;
+ if (this->max_msg_len && this->msg_len + attr_len > this->max_msg_len)
+ {
+ /* attribute just does not fit into this message */
+ return FALSE;
+ }
+ this->msg_len += attr_len;
+ }
this->attributes->insert_last(this->attributes, attr);
return TRUE;
}
@@ -201,7 +188,9 @@ METHOD(pa_tnc_msg_t, process, status_t,
private_pa_tnc_msg_t *this)
{
bio_reader_t *reader;
- pa_tnc_attr_t *error;
+ pa_tnc_attr_t *attr, *error;
+ pen_type_t attr_type;
+ chunk_t attr_value;
uint8_t version;
uint32_t reserved, offset, attr_offset;
pen_type_t error_code = { PEN_IETF, PA_ERROR_INVALID_PARAMETER };
@@ -231,119 +220,38 @@ METHOD(pa_tnc_msg_t, process, status_t,
offset = PA_TNC_HEADER_SIZE;
/* pre-process PA-TNC attributes */
- while (reader->remaining(reader) >= PA_TNC_ATTR_HEADER_SIZE)
+ while (reader->remaining(reader) > 0)
{
- pen_t vendor_id;
- uint8_t flags;
- uint32_t type, length;
- chunk_t value, attr_info;
- pa_tnc_attr_t *attr;
- enum_name_t *pa_attr_names;
- ietf_attr_pa_tnc_error_t *error_attr;
-
- attr_info = reader->peek(reader);
- attr_info.len = PA_TNC_ATTR_INFO_SIZE;
- reader->read_uint8 (reader, &flags);
- reader->read_uint24(reader, &vendor_id);
- reader->read_uint32(reader, &type);
- reader->read_uint32(reader, &length);
-
- pa_attr_names = imcv_pa_tnc_attributes->get_names(imcv_pa_tnc_attributes,
- vendor_id);
- if (pa_attr_names)
- {
- DBG2(DBG_TNC, "processing PA-TNC attribute type '%N/%N' "
- "0x%06x/0x%08x", pen_names, vendor_id,
- pa_attr_names, type, vendor_id, type);
- }
- else
- {
- DBG2(DBG_TNC, "processing PA-TNC attribute type '%N' "
- "0x%06x/0x%08x", pen_names, vendor_id,
- vendor_id, type);
- }
-
- if (length < PA_TNC_ATTR_HEADER_SIZE)
- {
- DBG1(DBG_TNC, "%u bytes too small for PA-TNC attribute length",
- length);
- error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
- this->encoding, offset + PA_TNC_ATTR_INFO_SIZE);
- goto err;
- }
-
- if (!reader->read_data(reader, length - PA_TNC_ATTR_HEADER_SIZE, &value))
- {
- DBG1(DBG_TNC, "insufficient bytes for PA-TNC attribute value");
- error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
- this->encoding, offset + PA_TNC_ATTR_INFO_SIZE);
- goto err;
- }
- DBG3(DBG_TNC, "%B", &value);
-
- if (vendor_id == PEN_RESERVED)
- {
- error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
- this->encoding, offset + 1);
- goto err;
- }
- if (type == IETF_ATTR_RESERVED)
- {
- error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
- this->encoding, offset + 4);
- goto err;
- }
attr = imcv_pa_tnc_attributes->create(imcv_pa_tnc_attributes,
- vendor_id, type, value);
+ reader, FALSE, &offset, this->encoding, &error);
if (!attr)
{
- if (flags & PA_TNC_ATTR_FLAG_NOSKIP)
- {
- DBG1(DBG_TNC, "unsupported PA-TNC attribute with NOSKIP flag");
- error_code = pen_type_create(PEN_IETF,
- PA_ERROR_ATTR_TYPE_NOT_SUPPORTED);
- error = ietf_attr_pa_tnc_error_create(error_code,
- this->encoding);
- error_attr = (ietf_attr_pa_tnc_error_t*)error;
- error_attr->set_attr_info(error_attr, attr_info);
- goto err;
- }
- else
- {
- DBG1(DBG_TNC, "skipping unsupported PA-TNC attribute");
- offset += length;
- continue;
- }
+ goto err;
}
+ attr_value = attr->get_value(attr);
+ attr_type = attr->get_type(attr);
if (attr->process(attr, &attr_offset) != SUCCESS)
{
attr->destroy(attr);
- if (vendor_id == PEN_IETF && type == IETF_ATTR_PA_TNC_ERROR)
+
+ if (attr_type.vendor_id == PEN_IETF &&
+ attr_type.type == IETF_ATTR_PA_TNC_ERROR)
{
- /* error while processing a PA-TNC error attribute - abort */
- reader->destroy(reader);
- return FAILED;
+ /* suppress error while processing a PA-TNC error attribute */
+ offset += attr_value.len;
+ continue;
}
- error_code = pen_type_create(PEN_IETF,
- PA_ERROR_INVALID_PARAMETER);
+ error_code = pen_type_create(PEN_IETF, PA_ERROR_INVALID_PARAMETER);
error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
- this->encoding,
- offset + PA_TNC_ATTR_HEADER_SIZE + attr_offset);
+ this->encoding, offset + attr_offset);
goto err;
}
+ offset += attr_value.len;
this->attributes->insert_last(this->attributes, attr);
- offset += length;
}
-
- if (reader->remaining(reader) == 0)
- {
- reader->destroy(reader);
- return SUCCESS;
- }
- DBG1(DBG_TNC, "insufficient bytes for PA-TNC attribute header");
- error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
- this->encoding, offset);
+ reader->destroy(reader);
+ return SUCCESS;
err:
reader->destroy(reader);
@@ -352,24 +260,27 @@ err:
}
METHOD(pa_tnc_msg_t, process_ietf_std_errors, bool,
- private_pa_tnc_msg_t *this)
+ private_pa_tnc_msg_t *this, linked_list_t *non_fatal_types)
{
- enumerator_t *enumerator;
+ enumerator_t *e1, *e2;
+ enum_name_t *pa_attr_names;
pa_tnc_attr_t *attr;
- pen_type_t type;
+ pen_type_t type, unsupported_type;
+ uint8_t flags;
bool fatal_error = FALSE;
- enumerator = this->attributes->create_enumerator(this->attributes);
- while (enumerator->enumerate(enumerator, &attr))
+ e1 = this->attributes->create_enumerator(this->attributes);
+ while (e1->enumerate(e1, &attr))
{
type = attr->get_type(attr);
if (type.vendor_id == PEN_IETF && type.type == IETF_ATTR_PA_TNC_ERROR)
{
ietf_attr_pa_tnc_error_t *error_attr;
- pen_type_t error_code;
- chunk_t msg_info, attr_info;
+ pen_type_t error_code, *non_fatal_type;
+ chunk_t msg_info;
uint32_t offset;
+ bool fatal_current_error = TRUE;
error_attr = (ietf_attr_pa_tnc_error_t*)attr;
error_code = error_attr->get_error_code(error_attr);
@@ -391,16 +302,49 @@ METHOD(pa_tnc_msg_t, process_ietf_std_errors, bool,
DBG1(DBG_TNC, " occurred at offset of %u bytes", offset);
break;
case PA_ERROR_ATTR_TYPE_NOT_SUPPORTED:
- attr_info = error_attr->get_attr_info(error_attr);
- DBG1(DBG_TNC, " unsupported attribute %#B", &attr_info);
+ unsupported_type =
+ error_attr->get_unsupported_attr(error_attr, &flags);
+ pa_attr_names =
+ imcv_pa_tnc_attributes->get_names(imcv_pa_tnc_attributes,
+ unsupported_type.vendor_id);
+ if (pa_attr_names)
+ {
+ DBG1(DBG_TNC, " unsupported attribute type '%N/%N' "
+ "0x%06x/0x%08x, flags 0x%02x",
+ pen_names, unsupported_type.vendor_id,
+ pa_attr_names, unsupported_type.type,
+ unsupported_type.vendor_id, unsupported_type.type,
+ flags);
+ }
+ else
+ {
+ DBG1(DBG_TNC, " unsupported attribute type '%N' "
+ "0x%06x/0x%08x, flags 0x%02x",
+ pen_names, unsupported_type.vendor_id,
+ unsupported_type.vendor_id, unsupported_type.type,
+ flags);
+ }
+ e2 = non_fatal_types->create_enumerator(non_fatal_types);
+ while (e2->enumerate(e2, &non_fatal_type))
+ {
+ if (pen_type_equals(unsupported_type, *non_fatal_type))
+ {
+ fatal_current_error = FALSE;
+ break;
+ }
+ }
+ e2->destroy(e2);
break;
default:
break;
}
- fatal_error = TRUE;
+ if (fatal_current_error)
+ {
+ fatal_error = TRUE;
+ }
}
}
- enumerator->destroy(enumerator);
+ e1->destroy(e1);
return fatal_error;
}
@@ -476,6 +420,7 @@ pa_tnc_msg_t *pa_tnc_msg_create_from_data(chunk_t data)
.encoding = chunk_clone(data),
.attributes = linked_list_create(),
.errors = linked_list_create(),
+ .from_data = TRUE,
);
return &this->public;
diff --git a/src/libimcv/pa_tnc/pa_tnc_msg.h b/src/libimcv/pa_tnc/pa_tnc_msg.h
index 84814b92b..57ff1a04c 100644
--- a/src/libimcv/pa_tnc/pa_tnc_msg.h
+++ b/src/libimcv/pa_tnc/pa_tnc_msg.h
@@ -68,9 +68,11 @@ struct pa_tnc_msg_t {
/**
* Process all IETF standard error PA-TNC attributes
*
- * @return TRUE if at least one error attribute processed
+ * @param non_fatal_types list of non fatal unsupported attribute types
+ * @return TRUE if at least one fatal error processed
*/
- bool (*process_ietf_std_errors)(pa_tnc_msg_t *this);
+ bool (*process_ietf_std_errors)(pa_tnc_msg_t *this,
+ linked_list_t *non_fatal_types);
/**
* Enumerates over all PA-TNC attributes
diff --git a/src/libimcv/plugins/imc_attestation/Makefile.am b/src/libimcv/plugins/imc_attestation/Makefile.am
new file mode 100644
index 000000000..e7b1f1ce1
--- /dev/null
+++ b/src/libimcv/plugins/imc_attestation/Makefile.am
@@ -0,0 +1,18 @@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libtncif \
+ -I$(top_srcdir)/src/libimcv
+
+AM_CFLAGS = \
+ $(PLUGIN_CFLAGS)
+
+imcv_LTLIBRARIES = imc-attestation.la
+
+imc_attestation_la_LIBADD = $(top_builddir)/src/libimcv/libimcv.la \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la
+
+imc_attestation_la_SOURCES = imc_attestation.c \
+ imc_attestation_state.h imc_attestation_state.c \
+ imc_attestation_process.h imc_attestation_process.c
+
+imc_attestation_la_LDFLAGS = -module -avoid-version -no-undefined
diff --git a/src/libimcv/plugins/imc_attestation/Makefile.in b/src/libimcv/plugins/imc_attestation/Makefile.in
new file mode 100644
index 000000000..3c5017f32
--- /dev/null
+++ b/src/libimcv/plugins/imc_attestation/Makefile.in
@@ -0,0 +1,765 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/libimcv/plugins/imc_attestation
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/depcomp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
+ $(top_srcdir)/m4/config/ltoptions.m4 \
+ $(top_srcdir)/m4/config/ltsugar.m4 \
+ $(top_srcdir)/m4/config/ltversion.m4 \
+ $(top_srcdir)/m4/config/lt~obsolete.m4 \
+ $(top_srcdir)/m4/macros/split-package-version.m4 \
+ $(top_srcdir)/m4/macros/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/m4/macros/add-plugin.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(imcvdir)"
+LTLIBRARIES = $(imcv_LTLIBRARIES)
+imc_attestation_la_DEPENDENCIES = \
+ $(top_builddir)/src/libimcv/libimcv.la \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la
+am_imc_attestation_la_OBJECTS = imc_attestation.lo \
+ imc_attestation_state.lo imc_attestation_process.lo
+imc_attestation_la_OBJECTS = $(am_imc_attestation_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+imc_attestation_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(imc_attestation_la_LDFLAGS) \
+ $(LDFLAGS) -o $@
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(imc_attestation_la_SOURCES)
+DIST_SOURCES = $(imc_attestation_la_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BFDLIB = @BFDLIB@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+COVERAGE_CFLAGS = @COVERAGE_CFLAGS@
+COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GEM = @GEM@
+GENHTML = @GENHTML@
+GPERF = @GPERF@
+GPRBUILD = @GPRBUILD@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LCOV = @LCOV@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQLCFLAG = @MYSQLCFLAG@
+MYSQLCONFIG = @MYSQLCONFIG@
+MYSQLLIB = @MYSQLLIB@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PACKAGE_VERSION_BUILD = @PACKAGE_VERSION_BUILD@
+PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@
+PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@
+PACKAGE_VERSION_REVIEW = @PACKAGE_VERSION_REVIEW@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+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@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
+RUBYINCLUDE = @RUBYINCLUDE@
+RUBYLIB = @RUBYLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+UNWINDLIB = @UNWINDLIB@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+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@
+am__tar = @am__tar@
+am__untar = @am__untar@
+attest_plugins = @attest_plugins@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+c_plugins = @c_plugins@
+charon_natt_port = @charon_natt_port@
+charon_plugins = @charon_plugins@
+charon_udp_port = @charon_udp_port@
+clearsilver_LIBS = @clearsilver_LIBS@
+cmd_plugins = @cmd_plugins@
+datadir = @datadir@
+datarootdir = @datarootdir@
+dbusservicedir = @dbusservicedir@
+dev_headers = @dev_headers@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+fips_mode = @fips_mode@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+h_plugins = @h_plugins@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+imcvdir = @imcvdir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsec_script = @ipsec_script@
+ipsec_script_upper = @ipsec_script_upper@
+ipsecdir = @ipsecdir@
+ipsecgroup = @ipsecgroup@
+ipseclibdir = @ipseclibdir@
+ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
+libdir = @libdir@
+libexecdir = @libexecdir@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+maemo_CFLAGS = @maemo_CFLAGS@
+maemo_LIBS = @maemo_LIBS@
+manager_plugins = @manager_plugins@
+mandir = @mandir@
+medsrv_plugins = @medsrv_plugins@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
+oldincludedir = @oldincludedir@
+pcsclite_CFLAGS = @pcsclite_CFLAGS@
+pcsclite_LIBS = @pcsclite_LIBS@
+pdfdir = @pdfdir@
+piddir = @piddir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+pki_plugins = @pki_plugins@
+plugindir = @plugindir@
+pool_plugins = @pool_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+s_plugins = @s_plugins@
+sbindir = @sbindir@
+scepclient_plugins = @scepclient_plugins@
+scripts_plugins = @scripts_plugins@
+sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
+srcdir = @srcdir@
+starter_plugins = @starter_plugins@
+strongswan_conf = @strongswan_conf@
+strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
+sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
+systemdsystemunitdir = @systemdsystemunitdir@
+t_plugins = @t_plugins@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+urandom_device = @urandom_device@
+xml_CFLAGS = @xml_CFLAGS@
+xml_LIBS = @xml_LIBS@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libtncif \
+ -I$(top_srcdir)/src/libimcv
+
+AM_CFLAGS = \
+ $(PLUGIN_CFLAGS)
+
+imcv_LTLIBRARIES = imc-attestation.la
+imc_attestation_la_LIBADD = $(top_builddir)/src/libimcv/libimcv.la \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la
+
+imc_attestation_la_SOURCES = imc_attestation.c \
+ imc_attestation_state.h imc_attestation_state.c \
+ imc_attestation_process.h imc_attestation_process.c
+
+imc_attestation_la_LDFLAGS = -module -avoid-version -no-undefined
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libimcv/plugins/imc_attestation/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libimcv/plugins/imc_attestation/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+install-imcvLTLIBRARIES: $(imcv_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ @list='$(imcv_LTLIBRARIES)'; test -n "$(imcvdir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(MKDIR_P) '$(DESTDIR)$(imcvdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(imcvdir)" || exit 1; \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(imcvdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(imcvdir)"; \
+ }
+
+uninstall-imcvLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(imcv_LTLIBRARIES)'; test -n "$(imcvdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(imcvdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(imcvdir)/$$f"; \
+ done
+
+clean-imcvLTLIBRARIES:
+ -test -z "$(imcv_LTLIBRARIES)" || rm -f $(imcv_LTLIBRARIES)
+ @list='$(imcv_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+imc-attestation.la: $(imc_attestation_la_OBJECTS) $(imc_attestation_la_DEPENDENCIES) $(EXTRA_imc_attestation_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(imc_attestation_la_LINK) -rpath $(imcvdir) $(imc_attestation_la_OBJECTS) $(imc_attestation_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imc_attestation.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imc_attestation_process.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imc_attestation_state.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(imcvdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-imcvLTLIBRARIES clean-libtool \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-imcvLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-imcvLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+ clean-imcvLTLIBRARIES clean-libtool cscopelist-am ctags \
+ ctags-am distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am \
+ install-imcvLTLIBRARIES install-info install-info-am \
+ install-man install-pdf install-pdf-am install-ps \
+ install-ps-am install-strip installcheck installcheck-am \
+ installdirs maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
+ uninstall-am uninstall-imcvLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libimcv/plugins/imc_attestation/imc_attestation.c b/src/libimcv/plugins/imc_attestation/imc_attestation.c
new file mode 100644
index 000000000..0dd88b6a7
--- /dev/null
+++ b/src/libimcv/plugins/imc_attestation/imc_attestation.c
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2011-2012 Sansar Choinyambuu
+ * Copyright (C) 2011-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "imc_attestation_state.h"
+#include "imc_attestation_process.h"
+
+#include <imc/imc_agent.h>
+#include <imc/imc_msg.h>
+#include <ietf/ietf_attr.h>
+#include <ietf/ietf_attr_pa_tnc_error.h>
+#include <ietf/ietf_attr_product_info.h>
+#include <ietf/ietf_attr_string_version.h>
+#include <ietf/ietf_attr_assess_result.h>
+#include <tcg/pts/tcg_pts_attr_proto_caps.h>
+#include <tcg/pts/tcg_pts_attr_meas_algo.h>
+#include <os_info/os_info.h>
+#include <pts/pts_error.h>
+
+#include <tncif_pa_subtypes.h>
+
+#include <pen/pen.h>
+#include <utils/debug.h>
+#include <collections/linked_list.h>
+
+/* IMC definitions */
+
+static const char imc_name[] = "Attestation";
+
+static pen_type_t msg_types[] = {
+ { PEN_TCG, PA_SUBTYPE_TCG_PTS }
+};
+
+static imc_agent_t *imc_attestation;
+
+/**
+ * Supported PTS measurement algorithms
+ */
+static pts_meas_algorithms_t supported_algorithms = PTS_MEAS_ALGO_NONE;
+
+/**
+ * Supported PTS Diffie Hellman Groups
+ */
+static pts_dh_group_t supported_dh_groups = PTS_DH_GROUP_NONE;
+
+/**
+ * see section 3.8.1 of TCG TNC IF-IMC Specification 1.3
+ */
+TNC_Result TNC_IMC_API TNC_IMC_Initialize(TNC_IMCID imc_id,
+ TNC_Version min_version,
+ TNC_Version max_version,
+ TNC_Version *actual_version)
+{
+ bool mandatory_dh_groups;
+
+ if (imc_attestation)
+ {
+ DBG1(DBG_IMC, "IMC \"%s\" has already been initialized", imc_name);
+ return TNC_RESULT_ALREADY_INITIALIZED;
+ }
+ imc_attestation = imc_agent_create(imc_name, msg_types, countof(msg_types),
+ imc_id, actual_version);
+ if (!imc_attestation)
+ {
+ return TNC_RESULT_FATAL;
+ }
+
+ mandatory_dh_groups = lib->settings->get_bool(lib->settings,
+ "%s.plugins.imc-attestation.mandatory_dh_groups", TRUE, lib->ns);
+
+ if (!pts_meas_algo_probe(&supported_algorithms) ||
+ !pts_dh_group_probe(&supported_dh_groups, mandatory_dh_groups))
+ {
+ imc_attestation->destroy(imc_attestation);
+ imc_attestation = NULL;
+ return TNC_RESULT_FATAL;
+ }
+
+ if (min_version > TNC_IFIMC_VERSION_1 || max_version < TNC_IFIMC_VERSION_1)
+ {
+ DBG1(DBG_IMC, "no common IF-IMC version");
+ return TNC_RESULT_NO_COMMON_VERSION;
+ }
+ return TNC_RESULT_SUCCESS;
+}
+
+/**
+ * see section 3.8.2 of TCG TNC IF-IMC Specification 1.3
+ */
+TNC_Result TNC_IMC_API TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id,
+ TNC_ConnectionID connection_id,
+ TNC_ConnectionState new_state)
+{
+ imc_state_t *state;
+
+ if (!imc_attestation)
+ {
+ DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
+ return TNC_RESULT_NOT_INITIALIZED;
+ }
+ switch (new_state)
+ {
+ case TNC_CONNECTION_STATE_CREATE:
+ state = imc_attestation_state_create(connection_id);
+ return imc_attestation->create_state(imc_attestation, state);
+ case TNC_CONNECTION_STATE_HANDSHAKE:
+ if (imc_attestation->change_state(imc_attestation, connection_id,
+ new_state, &state) != TNC_RESULT_SUCCESS)
+ {
+ return TNC_RESULT_FATAL;
+ }
+ state->set_result(state, imc_id,
+ TNC_IMV_EVALUATION_RESULT_DONT_KNOW);
+ return TNC_RESULT_SUCCESS;
+ case TNC_CONNECTION_STATE_DELETE:
+ return imc_attestation->delete_state(imc_attestation, connection_id);
+ case TNC_CONNECTION_STATE_ACCESS_ISOLATED:
+ case TNC_CONNECTION_STATE_ACCESS_NONE:
+ default:
+ return imc_attestation->change_state(imc_attestation, connection_id,
+ new_state, NULL);
+ }
+}
+
+
+/**
+ * see section 3.8.3 of TCG TNC IF-IMC Specification 1.3
+ */
+TNC_Result TNC_IMC_API TNC_IMC_BeginHandshake(TNC_IMCID imc_id,
+ TNC_ConnectionID connection_id)
+{
+ if (!imc_attestation)
+ {
+ DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
+ return TNC_RESULT_NOT_INITIALIZED;
+ }
+
+ return TNC_RESULT_SUCCESS;
+}
+
+static TNC_Result receive_message(imc_state_t *state, imc_msg_t *in_msg)
+{
+ imc_msg_t *out_msg;
+ imc_attestation_state_t *attestation_state;
+ enumerator_t *enumerator;
+ pa_tnc_attr_t *attr;
+ pen_type_t type;
+ TNC_Result result;
+ bool fatal_error = FALSE;
+
+ /* generate an outgoing PA-TNC message - we might need it */
+ out_msg = imc_msg_create_as_reply(in_msg);
+
+ /* parse received PA-TNC message and handle local and remote errors */
+ result = in_msg->receive(in_msg, out_msg, &fatal_error);
+ if (result != TNC_RESULT_SUCCESS)
+ {
+ out_msg->destroy(out_msg);
+ return result;
+ }
+
+ /* analyze PA-TNC attributes */
+ enumerator = in_msg->create_attribute_enumerator(in_msg);
+ while (enumerator->enumerate(enumerator, &attr))
+ {
+ type = attr->get_type(attr);
+
+ if (type.vendor_id == PEN_IETF)
+ {
+ if (type.type == IETF_ATTR_PA_TNC_ERROR)
+ {
+ ietf_attr_pa_tnc_error_t *error_attr;
+ pen_type_t error_code;
+ chunk_t msg_info;
+
+ error_attr = (ietf_attr_pa_tnc_error_t*)attr;
+ error_code = error_attr->get_error_code(error_attr);
+
+ if (error_code.vendor_id == PEN_TCG)
+ {
+ msg_info = error_attr->get_msg_info(error_attr);
+
+ DBG1(DBG_IMC, "received TCG-PTS error '%N'",
+ pts_error_code_names, error_code.type);
+ DBG1(DBG_IMC, "error information: %B", &msg_info);
+
+ result = TNC_RESULT_FATAL;
+ }
+ }
+ }
+ else if (type.vendor_id == PEN_TCG)
+ {
+ attestation_state = (imc_attestation_state_t*)state;
+
+ if (!imc_attestation_process(attr, out_msg, attestation_state,
+ supported_algorithms, supported_dh_groups))
+ {
+ result = TNC_RESULT_FATAL;
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (result == TNC_RESULT_SUCCESS)
+ {
+ /* send PA-TNC message with the EXCL flag set */
+ result = out_msg->send(out_msg, TRUE);
+ }
+ out_msg->destroy(out_msg);
+
+ return result;
+}
+
+/**
+ * see section 3.8.4 of TCG TNC IF-IMC Specification 1.3
+ */
+TNC_Result TNC_IMC_API TNC_IMC_ReceiveMessage(TNC_IMCID imc_id,
+ TNC_ConnectionID connection_id,
+ TNC_BufferReference msg,
+ TNC_UInt32 msg_len,
+ TNC_MessageType msg_type)
+{
+ imc_state_t *state;
+ imc_msg_t *in_msg;
+ TNC_Result result;
+
+ if (!imc_attestation)
+ {
+ DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
+ return TNC_RESULT_NOT_INITIALIZED;
+ }
+ if (!imc_attestation->get_state(imc_attestation, connection_id, &state))
+ {
+ return TNC_RESULT_FATAL;
+ }
+
+ in_msg = imc_msg_create_from_data(imc_attestation, state, connection_id,
+ msg_type, chunk_create(msg, msg_len));
+ result = receive_message(state, in_msg);
+ in_msg->destroy(in_msg);
+
+ return result;
+}
+
+/**
+ * see section 3.8.6 of TCG TNC IF-IMV Specification 1.3
+ */
+TNC_Result TNC_IMC_API TNC_IMC_ReceiveMessageLong(TNC_IMCID imc_id,
+ TNC_ConnectionID connection_id,
+ TNC_UInt32 msg_flags,
+ TNC_BufferReference msg,
+ TNC_UInt32 msg_len,
+ TNC_VendorID msg_vid,
+ TNC_MessageSubtype msg_subtype,
+ TNC_UInt32 src_imv_id,
+ TNC_UInt32 dst_imc_id)
+{
+ imc_state_t *state;
+ imc_msg_t *in_msg;
+ TNC_Result result;
+
+ if (!imc_attestation)
+ {
+ DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
+ return TNC_RESULT_NOT_INITIALIZED;
+ }
+ if (!imc_attestation->get_state(imc_attestation, connection_id, &state))
+ {
+ return TNC_RESULT_FATAL;
+ }
+ in_msg = imc_msg_create_from_long_data(imc_attestation, state, connection_id,
+ src_imv_id, dst_imc_id, msg_vid, msg_subtype,
+ chunk_create(msg, msg_len));
+ result =receive_message(state, in_msg);
+ in_msg->destroy(in_msg);
+
+ return result;
+}
+
+/**
+ * see section 3.8.7 of TCG TNC IF-IMC Specification 1.3
+ */
+TNC_Result TNC_IMC_API TNC_IMC_BatchEnding(TNC_IMCID imc_id,
+ TNC_ConnectionID connection_id)
+{
+ if (!imc_attestation)
+ {
+ DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
+ return TNC_RESULT_NOT_INITIALIZED;
+ }
+ return TNC_RESULT_SUCCESS;
+}
+
+/**
+ * see section 3.8.8 of TCG TNC IF-IMC Specification 1.3
+ */
+TNC_Result TNC_IMC_API TNC_IMC_Terminate(TNC_IMCID imc_id)
+{
+ if (!imc_attestation)
+ {
+ DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
+ return TNC_RESULT_NOT_INITIALIZED;
+ }
+ imc_attestation->destroy(imc_attestation);
+ imc_attestation = NULL;
+
+ return TNC_RESULT_SUCCESS;
+}
+
+/**
+ * see section 4.2.8.1 of TCG TNC IF-IMC Specification 1.3
+ */
+TNC_Result TNC_IMC_API TNC_IMC_ProvideBindFunction(TNC_IMCID imc_id,
+ TNC_TNCC_BindFunctionPointer bind_function)
+{
+ if (!imc_attestation)
+ {
+ DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
+ return TNC_RESULT_NOT_INITIALIZED;
+ }
+ return imc_attestation->bind_functions(imc_attestation, bind_function);
+}
diff --git a/src/libimcv/plugins/imc_attestation/imc_attestation_process.c b/src/libimcv/plugins/imc_attestation/imc_attestation_process.c
new file mode 100644
index 000000000..2fc2998e1
--- /dev/null
+++ b/src/libimcv/plugins/imc_attestation/imc_attestation_process.c
@@ -0,0 +1,480 @@
+/*
+ * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+/* for isdigit */
+#include <ctype.h>
+
+#include "imc_attestation_process.h"
+
+#include <ietf/ietf_attr_pa_tnc_error.h>
+
+#include <pts/pts.h>
+
+#include <tcg/pts/tcg_pts_attr_proto_caps.h>
+#include <tcg/pts/tcg_pts_attr_meas_algo.h>
+#include <tcg/pts/tcg_pts_attr_dh_nonce_params_req.h>
+#include <tcg/pts/tcg_pts_attr_dh_nonce_params_resp.h>
+#include <tcg/pts/tcg_pts_attr_dh_nonce_finish.h>
+#include <tcg/pts/tcg_pts_attr_get_tpm_version_info.h>
+#include <tcg/pts/tcg_pts_attr_tpm_version_info.h>
+#include <tcg/pts/tcg_pts_attr_get_aik.h>
+#include <tcg/pts/tcg_pts_attr_aik.h>
+#include <tcg/pts/tcg_pts_attr_req_func_comp_evid.h>
+#include <tcg/pts/tcg_pts_attr_gen_attest_evid.h>
+#include <tcg/pts/tcg_pts_attr_simple_comp_evid.h>
+#include <tcg/pts/tcg_pts_attr_simple_evid_final.h>
+#include <tcg/pts/tcg_pts_attr_req_file_meas.h>
+#include <tcg/pts/tcg_pts_attr_file_meas.h>
+#include <tcg/pts/tcg_pts_attr_req_file_meta.h>
+#include <tcg/pts/tcg_pts_attr_unix_file_meta.h>
+
+#include <utils/debug.h>
+#include <utils/lexparser.h>
+
+#define DEFAULT_NONCE_LEN 20
+
+bool imc_attestation_process(pa_tnc_attr_t *attr, imc_msg_t *msg,
+ imc_attestation_state_t *attestation_state,
+ pts_meas_algorithms_t supported_algorithms,
+ pts_dh_group_t supported_dh_groups)
+{
+ chunk_t attr_info;
+ pts_t *pts;
+ pts_error_code_t pts_error;
+ pen_type_t attr_type;
+ bool valid_path;
+
+ pts = attestation_state->get_pts(attestation_state);
+ attr_type = attr->get_type(attr);
+
+ switch (attr_type.type)
+ {
+ case TCG_PTS_REQ_PROTO_CAPS:
+ {
+ tcg_pts_attr_proto_caps_t *attr_cast;
+ pts_proto_caps_flag_t imc_caps, imv_caps;
+
+ attr_cast = (tcg_pts_attr_proto_caps_t*)attr;
+ imv_caps = attr_cast->get_flags(attr_cast);
+ imc_caps = pts->get_proto_caps(pts);
+ pts->set_proto_caps(pts, imc_caps & imv_caps);
+
+ /* Send PTS Protocol Capabilities attribute */
+ attr = tcg_pts_attr_proto_caps_create(imc_caps & imv_caps, FALSE);
+ msg->add_attribute(msg, attr);
+ break;
+ }
+ case TCG_PTS_MEAS_ALGO:
+ {
+ tcg_pts_attr_meas_algo_t *attr_cast;
+ pts_meas_algorithms_t offered_algorithms, selected_algorithm;
+
+ attr_cast = (tcg_pts_attr_meas_algo_t*)attr;
+ offered_algorithms = attr_cast->get_algorithms(attr_cast);
+ selected_algorithm = pts_meas_algo_select(supported_algorithms,
+ offered_algorithms);
+ if (selected_algorithm == PTS_MEAS_ALGO_NONE)
+ {
+ attr = pts_hash_alg_error_create(supported_algorithms);
+ msg->add_attribute(msg, attr);
+ break;
+ }
+
+ /* Send Measurement Algorithm Selection attribute */
+ pts->set_meas_algorithm(pts, selected_algorithm);
+ attr = tcg_pts_attr_meas_algo_create(selected_algorithm, TRUE);
+ msg->add_attribute(msg, attr);
+ break;
+ }
+ case TCG_PTS_DH_NONCE_PARAMS_REQ:
+ {
+ tcg_pts_attr_dh_nonce_params_req_t *attr_cast;
+ pts_dh_group_t offered_dh_groups, selected_dh_group;
+ chunk_t responder_value, responder_nonce;
+ int nonce_len, min_nonce_len;
+
+ nonce_len = lib->settings->get_int(lib->settings,
+ "%s.plugins.imc-attestation.nonce_len",
+ DEFAULT_NONCE_LEN, lib->ns);
+
+ attr_cast = (tcg_pts_attr_dh_nonce_params_req_t*)attr;
+ min_nonce_len = attr_cast->get_min_nonce_len(attr_cast);
+ if (nonce_len < PTS_MIN_NONCE_LEN ||
+ (min_nonce_len > 0 && nonce_len < min_nonce_len))
+ {
+ attr = pts_dh_nonce_error_create(nonce_len, PTS_MAX_NONCE_LEN);
+ msg->add_attribute(msg, attr);
+ break;
+ }
+
+ offered_dh_groups = attr_cast->get_dh_groups(attr_cast);
+ selected_dh_group = pts_dh_group_select(supported_dh_groups,
+ offered_dh_groups);
+ if (selected_dh_group == PTS_DH_GROUP_NONE)
+ {
+ attr = pts_dh_group_error_create(supported_dh_groups);
+ msg->add_attribute(msg, attr);
+ break;
+ }
+
+ /* Create own DH factor and nonce */
+ if (!pts->create_dh_nonce(pts, selected_dh_group, nonce_len))
+ {
+ return FALSE;
+ }
+ pts->get_my_public_value(pts, &responder_value, &responder_nonce);
+
+ /* Send DH Nonce Parameters Response attribute */
+ attr = tcg_pts_attr_dh_nonce_params_resp_create(selected_dh_group,
+ supported_algorithms, responder_nonce, responder_value);
+ msg->add_attribute(msg, attr);
+ break;
+ }
+ case TCG_PTS_DH_NONCE_FINISH:
+ {
+ tcg_pts_attr_dh_nonce_finish_t *attr_cast;
+ pts_meas_algorithms_t selected_algorithm;
+ chunk_t initiator_nonce, initiator_value;
+ int nonce_len;
+
+ attr_cast = (tcg_pts_attr_dh_nonce_finish_t*)attr;
+ selected_algorithm = attr_cast->get_hash_algo(attr_cast);
+ if (!(selected_algorithm & supported_algorithms))
+ {
+ DBG1(DBG_IMC, "PTS-IMV selected unsupported DH hash algorithm");
+ return FALSE;
+ }
+ pts->set_dh_hash_algorithm(pts, selected_algorithm);
+
+ initiator_value = attr_cast->get_initiator_value(attr_cast);
+ initiator_nonce = attr_cast->get_initiator_nonce(attr_cast);
+
+ nonce_len = lib->settings->get_int(lib->settings,
+ "%s.plugins.imc-attestation.nonce_len",
+ DEFAULT_NONCE_LEN, lib->ns);
+ if (nonce_len != initiator_nonce.len)
+ {
+ DBG1(DBG_IMC, "initiator and responder DH nonces "
+ "have differing lengths");
+ return FALSE;
+ }
+
+ pts->set_peer_public_value(pts, initiator_value, initiator_nonce);
+ if (!pts->calculate_secret(pts))
+ {
+ return FALSE;
+ }
+ break;
+ }
+ case TCG_PTS_GET_TPM_VERSION_INFO:
+ {
+ chunk_t tpm_version_info, attr_info;
+ pen_type_t error_code = { PEN_TCG, TCG_PTS_TPM_VERS_NOT_SUPPORTED };
+
+ if (!pts->get_tpm_version_info(pts, &tpm_version_info))
+ {
+ attr_info = attr->get_value(attr);
+ attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
+ msg->add_attribute(msg, attr);
+ break;
+ }
+
+ /* Send TPM Version Info attribute */
+ attr = tcg_pts_attr_tpm_version_info_create(tpm_version_info);
+ msg->add_attribute(msg, attr);
+ break;
+ }
+ case TCG_PTS_GET_AIK:
+ {
+ certificate_t *aik;
+
+ aik = pts->get_aik(pts);
+ if (!aik)
+ {
+ DBG1(DBG_IMC, "no AIK certificate or public key available");
+ break;
+ }
+
+ /* Send AIK attribute */
+ attr = tcg_pts_attr_aik_create(aik);
+ msg->add_attribute(msg, attr);
+ break;
+ }
+ case TCG_PTS_REQ_FILE_MEAS:
+ {
+ tcg_pts_attr_req_file_meas_t *attr_cast;
+ char *pathname;
+ u_int16_t request_id;
+ bool is_directory;
+ u_int32_t delimiter;
+ pts_file_meas_t *measurements;
+ pen_type_t error_code;
+
+ attr_info = attr->get_value(attr);
+ attr_cast = (tcg_pts_attr_req_file_meas_t*)attr;
+ is_directory = attr_cast->get_directory_flag(attr_cast);
+ request_id = attr_cast->get_request_id(attr_cast);
+ delimiter = attr_cast->get_delimiter(attr_cast);
+ pathname = attr_cast->get_pathname(attr_cast);
+ valid_path = pts->is_path_valid(pts, pathname, &pts_error);
+
+ if (valid_path && pts_error)
+ {
+ error_code = pen_type_create(PEN_TCG, pts_error);
+ attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
+ msg->add_attribute(msg, attr);
+ break;
+ }
+ else if (!valid_path)
+ {
+ break;
+ }
+
+ if (delimiter != SOLIDUS_UTF && delimiter != REVERSE_SOLIDUS_UTF)
+ {
+ error_code = pen_type_create(PEN_TCG,
+ TCG_PTS_INVALID_DELIMITER);
+ attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
+ msg->add_attribute(msg, attr);
+ break;
+ }
+
+ /* Do PTS File Measurements and send them to PTS-IMV */
+ DBG2(DBG_IMC, "measurement request %d for %s '%s'",
+ request_id, is_directory ? "directory" : "file",
+ pathname);
+ measurements = pts_file_meas_create_from_path(request_id,
+ pathname, is_directory, TRUE,
+ pts->get_meas_algorithm(pts));
+ if (!measurements)
+ {
+ /* TODO handle error codes from measurements */
+ return FALSE;
+ }
+ attr = tcg_pts_attr_file_meas_create(measurements);
+ attr->set_noskip_flag(attr, TRUE);
+ msg->add_attribute(msg, attr);
+ break;
+ }
+ case TCG_PTS_REQ_FILE_META:
+ {
+ tcg_pts_attr_req_file_meta_t *attr_cast;
+ char *pathname;
+ bool is_directory;
+ u_int8_t delimiter;
+ pts_file_meta_t *metadata;
+ pen_type_t error_code;
+
+ attr_info = attr->get_value(attr);
+ attr_cast = (tcg_pts_attr_req_file_meta_t*)attr;
+ is_directory = attr_cast->get_directory_flag(attr_cast);
+ delimiter = attr_cast->get_delimiter(attr_cast);
+ pathname = attr_cast->get_pathname(attr_cast);
+
+ valid_path = pts->is_path_valid(pts, pathname, &pts_error);
+ if (valid_path && pts_error)
+ {
+ error_code = pen_type_create(PEN_TCG, pts_error);
+ attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
+ msg->add_attribute(msg, attr);
+ break;
+ }
+ else if (!valid_path)
+ {
+ break;
+ }
+ if (delimiter != SOLIDUS_UTF && delimiter != REVERSE_SOLIDUS_UTF)
+ {
+ error_code = pen_type_create(PEN_TCG,
+ TCG_PTS_INVALID_DELIMITER);
+ attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
+ msg->add_attribute(msg, attr);
+ break;
+ }
+ /* Get File Metadata and send them to PTS-IMV */
+ DBG2(DBG_IMC, "metadata request for %s '%s'",
+ is_directory ? "directory" : "file",
+ pathname);
+ metadata = pts->get_metadata(pts, pathname, is_directory);
+
+ if (!metadata)
+ {
+ /* TODO handle error codes from measurements */
+ return FALSE;
+ }
+ attr = tcg_pts_attr_unix_file_meta_create(metadata);
+ attr->set_noskip_flag(attr, TRUE);
+ msg->add_attribute(msg, attr);
+ break;
+ }
+ case TCG_PTS_REQ_FUNC_COMP_EVID:
+ {
+ tcg_pts_attr_req_func_comp_evid_t *attr_cast;
+ pts_proto_caps_flag_t negotiated_caps;
+ pts_comp_func_name_t *name;
+ pts_comp_evidence_t *evid;
+ pts_component_t *comp;
+ pen_type_t error_code;
+ u_int32_t depth;
+ u_int8_t flags;
+ status_t status;
+ enumerator_t *e;
+
+ attr_info = attr->get_value(attr);
+ attr_cast = (tcg_pts_attr_req_func_comp_evid_t*)attr;
+
+ DBG1(DBG_IMC, "evidence requested for %d functional components",
+ attr_cast->get_count(attr_cast));
+
+ e = attr_cast->create_enumerator(attr_cast);
+ while (e->enumerate(e, &flags, &depth, &name))
+ {
+ name->log(name, "* ");
+ negotiated_caps = pts->get_proto_caps(pts);
+
+ if (flags & PTS_REQ_FUNC_COMP_EVID_TTC)
+ {
+ error_code = pen_type_create(PEN_TCG,
+ TCG_PTS_UNABLE_DET_TTC);
+ attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
+ msg->add_attribute(msg, attr);
+ break;
+ }
+ if (flags & PTS_REQ_FUNC_COMP_EVID_VER &&
+ !(negotiated_caps & PTS_PROTO_CAPS_V))
+ {
+ error_code = pen_type_create(PEN_TCG,
+ TCG_PTS_UNABLE_LOCAL_VAL);
+ attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
+ msg->add_attribute(msg, attr);
+ break;
+ }
+ if (flags & PTS_REQ_FUNC_COMP_EVID_CURR &&
+ !(negotiated_caps & PTS_PROTO_CAPS_C))
+ {
+ error_code = pen_type_create(PEN_TCG,
+ TCG_PTS_UNABLE_CUR_EVID);
+ attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
+ msg->add_attribute(msg, attr);
+ break;
+ }
+ if (flags & PTS_REQ_FUNC_COMP_EVID_PCR &&
+ !(negotiated_caps & PTS_PROTO_CAPS_T))
+ {
+ error_code = pen_type_create(PEN_TCG,
+ TCG_PTS_UNABLE_DET_PCR);
+ attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
+ msg->add_attribute(msg, attr);
+ break;
+ }
+ if (depth > 0)
+ {
+ DBG1(DBG_IMC, "the Attestation IMC currently does not "
+ "support sub component measurements");
+ return FALSE;
+ }
+ comp = attestation_state->create_component(attestation_state,
+ name, depth);
+ if (!comp)
+ {
+ DBG2(DBG_IMC, " not registered: no evidence provided");
+ continue;
+ }
+
+ /* do the component evidence measurement[s] and cache them */
+ do
+ {
+ status = comp->measure(comp, name->get_qualifier(name),
+ pts, &evid);
+ if (status == FAILED)
+ {
+ break;
+ }
+ attestation_state->add_evidence(attestation_state, evid);
+ }
+ while (status == NEED_MORE);
+ }
+ e->destroy(e);
+ break;
+ }
+ case TCG_PTS_GEN_ATTEST_EVID:
+ {
+ pts_simple_evid_final_flag_t flags;
+ pts_meas_algorithms_t comp_hash_algorithm;
+ pts_comp_evidence_t *evid;
+ chunk_t pcr_composite, quote_sig;
+ bool use_quote2;
+
+ /* Send cached Component Evidence entries */
+ while (attestation_state->next_evidence(attestation_state, &evid))
+ {
+ attr = tcg_pts_attr_simple_comp_evid_create(evid);
+ msg->add_attribute(msg, attr);
+ }
+
+ use_quote2 = lib->settings->get_bool(lib->settings,
+ "%s.plugins.imc-attestation.use_quote2", TRUE,
+ lib->ns);
+ if (!pts->quote_tpm(pts, use_quote2, &pcr_composite, &quote_sig))
+ {
+ DBG1(DBG_IMC, "error occurred during TPM quote operation");
+ return FALSE;
+ }
+
+ /* Send Simple Evidence Final attribute */
+ flags = use_quote2 ? PTS_SIMPLE_EVID_FINAL_QUOTE_INFO2 :
+ PTS_SIMPLE_EVID_FINAL_QUOTE_INFO;
+ comp_hash_algorithm = PTS_MEAS_ALGO_SHA1;
+
+ attr = tcg_pts_attr_simple_evid_final_create(flags,
+ comp_hash_algorithm, pcr_composite, quote_sig);
+ msg->add_attribute(msg, attr);
+ break;
+ }
+ case TCG_SEG_MAX_ATTR_SIZE_REQ:
+ case TCG_SEG_NEXT_SEG_REQ:
+ break;
+
+ /* TODO: Not implemented yet */
+ case TCG_PTS_REQ_INTEG_MEAS_LOG:
+ /* Attributes using XML */
+ case TCG_PTS_REQ_TEMPL_REF_MANI_SET_META:
+ case TCG_PTS_UPDATE_TEMPL_REF_MANI:
+ /* On Windows only*/
+ case TCG_PTS_REQ_REGISTRY_VALUE:
+ /* Received on IMV side only*/
+ case TCG_PTS_PROTO_CAPS:
+ case TCG_PTS_DH_NONCE_PARAMS_RESP:
+ case TCG_PTS_MEAS_ALGO_SELECTION:
+ case TCG_PTS_TPM_VERSION_INFO:
+ case TCG_PTS_TEMPL_REF_MANI_SET_META:
+ case TCG_PTS_AIK:
+ case TCG_PTS_SIMPLE_COMP_EVID:
+ case TCG_PTS_SIMPLE_EVID_FINAL:
+ case TCG_PTS_VERIFICATION_RESULT:
+ case TCG_PTS_INTEG_REPORT:
+ case TCG_PTS_UNIX_FILE_META:
+ case TCG_PTS_FILE_MEAS:
+ case TCG_PTS_INTEG_MEAS_LOG:
+ default:
+ DBG1(DBG_IMC, "received unsupported attribute '%N/%N'",
+ pen_names, PEN_TCG, tcg_attr_names, attr_type.type);
+ break;
+ }
+ return TRUE;
+}
diff --git a/src/libimcv/plugins/imc_attestation/imc_attestation_process.h b/src/libimcv/plugins/imc_attestation/imc_attestation_process.h
new file mode 100644
index 000000000..a2f1b4e3c
--- /dev/null
+++ b/src/libimcv/plugins/imc_attestation/imc_attestation_process.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup imc_attestation_process_t imc_attestation_process
+ * @{ @ingroup imc_attestation
+ */
+
+#ifndef IMC_ATTESTATION_PROCESS_H_
+#define IMC_ATTESTATION_PROCESS_H_
+
+#include "imc_attestation_state.h"
+
+#include <library.h>
+
+#include <imc/imc_msg.h>
+#include <pa_tnc/pa_tnc_attr.h>
+
+#include <pts/pts_dh_group.h>
+#include <pts/pts_meas_algo.h>
+
+/**
+ * Process a TCG PTS attribute
+ *
+ * @param attr PA-TNC attribute to be processed
+ * @param msg outbound PA-TNC message to be assembled
+ * @param attestation_state attestation state of a given connection
+ * @param supported_algorithms supported PTS measurement algorithms
+ * @param supported_dh_groups supported DH groups
+ * @return TRUE if successful
+ */
+bool imc_attestation_process(pa_tnc_attr_t *attr, imc_msg_t *msg,
+ imc_attestation_state_t *attestation_state,
+ pts_meas_algorithms_t supported_algorithms,
+ pts_dh_group_t supported_dh_groups);
+
+#endif /** IMC_ATTESTATION_PROCESS_H_ @}*/
diff --git a/src/libimcv/plugins/imc_attestation/imc_attestation_state.c b/src/libimcv/plugins/imc_attestation/imc_attestation_state.c
new file mode 100644
index 000000000..0b594cb10
--- /dev/null
+++ b/src/libimcv/plugins/imc_attestation/imc_attestation_state.c
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2011-2012 Sansar Choinyambuu
+ * Copyright (C) 2011-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "imc_attestation_state.h"
+
+#include <imcv.h>
+
+#include <tncif_names.h>
+
+#include <collections/linked_list.h>
+#include <utils/debug.h>
+
+typedef struct private_imc_attestation_state_t private_imc_attestation_state_t;
+typedef struct func_comp_t func_comp_t;
+
+/**
+ * Private data of an imc_attestation_state_t object.
+ */
+struct private_imc_attestation_state_t {
+
+ /**
+ * Public members of imc_attestation_state_t
+ */
+ imc_attestation_state_t public;
+
+ /**
+ * TNCCS connection ID
+ */
+ TNC_ConnectionID connection_id;
+
+ /**
+ * TNCCS connection state
+ */
+ TNC_ConnectionState state;
+
+ /**
+ * Assessment/Evaluation Result
+ */
+ TNC_IMV_Evaluation_Result result;
+
+ /**
+ * Does the TNCCS connection support long message types?
+ */
+ bool has_long;
+
+ /**
+ * Does the TNCCS connection support exclusive delivery?
+ */
+ bool has_excl;
+
+ /**
+ * Maximum PA-TNC message size for this TNCCS connection
+ */
+ u_int32_t max_msg_len;
+
+ /**
+ * PA-TNC attribute segmentation contracts associated with TNCCS connection
+ */
+ seg_contract_manager_t *contracts;
+
+ /**
+ * PTS object
+ */
+ pts_t *pts;
+
+ /**
+ * List of Functional Components
+ */
+ linked_list_t *components;
+
+ /**
+ * Functional Component Evidence cache list
+ */
+ linked_list_t *list;
+
+};
+
+METHOD(imc_state_t, get_connection_id, TNC_ConnectionID,
+ private_imc_attestation_state_t *this)
+{
+ return this->connection_id;
+}
+
+METHOD(imc_state_t, has_long, bool,
+ private_imc_attestation_state_t *this)
+{
+ return this->has_long;
+}
+
+METHOD(imc_state_t, has_excl, bool,
+ private_imc_attestation_state_t *this)
+{
+ return this->has_excl;
+}
+
+METHOD(imc_state_t, set_flags, void,
+ private_imc_attestation_state_t *this, bool has_long, bool has_excl)
+{
+ this->has_long = has_long;
+ this->has_excl = has_excl;
+}
+
+METHOD(imc_state_t, set_max_msg_len, void,
+ private_imc_attestation_state_t *this, u_int32_t max_msg_len)
+{
+ this->max_msg_len = max_msg_len;
+}
+
+METHOD(imc_state_t, get_max_msg_len, u_int32_t,
+ private_imc_attestation_state_t *this)
+{
+ return this->max_msg_len;
+}
+
+METHOD(imc_state_t, get_contracts, seg_contract_manager_t*,
+ private_imc_attestation_state_t *this)
+{
+ return this->contracts;
+}
+
+METHOD(imc_state_t, change_state, void,
+ private_imc_attestation_state_t *this, TNC_ConnectionState new_state)
+{
+ this->state = new_state;
+}
+
+METHOD(imc_state_t, set_result, void,
+ private_imc_attestation_state_t *this, TNC_IMCID id,
+ TNC_IMV_Evaluation_Result result)
+{
+ this->result = result;
+}
+
+METHOD(imc_state_t, get_result, bool,
+ private_imc_attestation_state_t *this, TNC_IMCID id,
+ TNC_IMV_Evaluation_Result *result)
+{
+ if (result)
+ {
+ *result = this->result;
+ }
+ return this->result != TNC_IMV_EVALUATION_RESULT_DONT_KNOW;
+}
+
+METHOD(imc_state_t, destroy, void,
+ private_imc_attestation_state_t *this)
+{
+ this->pts->destroy(this->pts);
+ this->components->destroy_offset(this->components,
+ offsetof(pts_component_t, destroy));
+ this->list->destroy_offset(this->list,
+ offsetof(pts_comp_evidence_t, destroy));
+ this->contracts->destroy(this->contracts);
+ free(this);
+}
+
+METHOD(imc_attestation_state_t, get_pts, pts_t*,
+ private_imc_attestation_state_t *this)
+{
+ return this->pts;
+}
+
+METHOD(imc_attestation_state_t, create_component, pts_component_t*,
+ private_imc_attestation_state_t *this, pts_comp_func_name_t *name,
+ u_int32_t depth)
+{
+ enumerator_t *enumerator;
+ pts_component_t *component;
+ bool found = FALSE;
+
+ enumerator = this->components->create_enumerator(this->components);
+ while (enumerator->enumerate(enumerator, &component))
+ {
+ if (name->equals(name, component->get_comp_func_name(component)))
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (!found)
+ {
+ component = imcv_pts_components->create(imcv_pts_components,
+ name, depth, NULL);
+ if (!component)
+ {
+ return NULL;
+ }
+ this->components->insert_last(this->components, component);
+
+ }
+ return component;
+}
+
+METHOD(imc_attestation_state_t, add_evidence, void,
+ private_imc_attestation_state_t *this, pts_comp_evidence_t *evid)
+{
+ this->list->insert_last(this->list, evid);
+}
+
+METHOD(imc_attestation_state_t, next_evidence, bool,
+ private_imc_attestation_state_t *this, pts_comp_evidence_t **evid)
+{
+ return this->list->remove_first(this->list, (void**)evid) == SUCCESS;
+}
+
+/**
+ * Described in header.
+ */
+imc_state_t *imc_attestation_state_create(TNC_ConnectionID connection_id)
+{
+ private_imc_attestation_state_t *this;
+
+ INIT(this,
+ .public = {
+ .interface = {
+ .get_connection_id = _get_connection_id,
+ .has_long = _has_long,
+ .has_excl = _has_excl,
+ .set_flags = _set_flags,
+ .set_max_msg_len = _set_max_msg_len,
+ .get_max_msg_len = _get_max_msg_len,
+ .get_contracts = _get_contracts,
+ .change_state = _change_state,
+ .set_result = _set_result,
+ .get_result = _get_result,
+ .destroy = _destroy,
+ },
+ .get_pts = _get_pts,
+ .create_component = _create_component,
+ .add_evidence = _add_evidence,
+ .next_evidence = _next_evidence,
+ },
+ .connection_id = connection_id,
+ .state = TNC_CONNECTION_STATE_CREATE,
+ .result = TNC_IMV_EVALUATION_RESULT_DONT_KNOW,
+ .contracts = seg_contract_manager_create(),
+ .pts = pts_create(TRUE),
+ .components = linked_list_create(),
+ .list = linked_list_create(),
+ );
+
+ return &this->public.interface;
+}
+
+
diff --git a/src/libimcv/plugins/imc_attestation/imc_attestation_state.h b/src/libimcv/plugins/imc_attestation/imc_attestation_state.h
new file mode 100644
index 000000000..854c8825b
--- /dev/null
+++ b/src/libimcv/plugins/imc_attestation/imc_attestation_state.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup imc_attestation imc_attestation
+ * @ingroup libimcv_plugins
+ *
+ * @defgroup imc_attestation_state_t imc_attestation_state
+ * @{ @ingroup imc_attestation
+ */
+
+#ifndef IMC_ATTESTATION_STATE_H_
+#define IMC_ATTESTATION_STATE_H_
+
+#include <imc/imc_state.h>
+#include <pts/pts.h>
+#include <pts/components/pts_component.h>
+#include <pts/components/pts_comp_evidence.h>
+#include <library.h>
+
+typedef struct imc_attestation_state_t imc_attestation_state_t;
+
+/**
+ * Internal state of an imc_attestation_t connection instance
+ */
+struct imc_attestation_state_t {
+
+ /**
+ * imc_state_t interface
+ */
+ imc_state_t interface;
+
+ /**
+ * Get the PTS object
+ *
+ * @return PTS object
+ */
+ pts_t* (*get_pts)(imc_attestation_state_t *this);
+
+ /**
+ * Create and add an entry to the list of Functional Components
+ *
+ * @param name Component Functional Name
+ * @param depth Sub-component Depth
+ * @return created functional component instance or NULL
+ */
+ pts_component_t* (*create_component)(imc_attestation_state_t *this,
+ pts_comp_func_name_t *name, u_int32_t depth);
+
+ /**
+ * Add an entry to the Component Evidence cache list
+ *
+ * @param evid Component Evidence entry
+ */
+ void (*add_evidence)(imc_attestation_state_t *this, pts_comp_evidence_t *evid);
+
+ /**
+ * Removes next entry from the Component Evidence cache list and returns it
+ *
+ * @param evid Next Component Evidence entry
+ * @return TRUE if next entry is available
+ */
+ bool (*next_evidence)(imc_attestation_state_t *this, pts_comp_evidence_t** evid);
+
+};
+
+/**
+ * Create an imc_attestation_state_t instance
+ *
+ * @param id connection ID
+ */
+imc_state_t* imc_attestation_state_create(TNC_ConnectionID id);
+
+#endif /** IMC_ATTESTATION_STATE_H_ @}*/
diff --git a/src/libimcv/plugins/imc_os/Makefile.in b/src/libimcv/plugins/imc_os/Makefile.in
index 2f0b85404..3f4cf41a9 100644
--- a/src/libimcv/plugins/imc_os/Makefile.in
+++ b/src/libimcv/plugins/imc_os/Makefile.in
@@ -230,6 +230,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -290,6 +291,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -355,6 +357,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -402,6 +406,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libimcv/plugins/imc_os/imc_os.c b/src/libimcv/plugins/imc_os/imc_os.c
index c624d26b1..86d2e09ca 100644
--- a/src/libimcv/plugins/imc_os/imc_os.c
+++ b/src/libimcv/plugins/imc_os/imc_os.c
@@ -30,7 +30,6 @@
#include <ita/ita_attr.h>
#include <ita/ita_attr_get_settings.h>
#include <ita/ita_attr_settings.h>
-#include <ita/ita_attr_angel.h>
#include <ita/ita_attr_device_id.h>
#include <tncif_pa_subtypes.h>
@@ -341,69 +340,24 @@ static void add_device_id(imc_msg_t *msg)
*/
static void add_installed_packages(imc_state_t *state, imc_msg_t *msg)
{
- pa_tnc_attr_t *attr = NULL, *attr_angel;
+ pa_tnc_attr_t *attr;
ietf_attr_installed_packages_t *attr_cast;
enumerator_t *enumerator;
chunk_t name, version;
- size_t max_attr_size, attr_size, entry_size;
- bool first = TRUE;
-
- /**
- * Compute the maximum IETF Installed Packages 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;
- /* At least one IETF Installed Packages attribute is sent */
attr = ietf_attr_installed_packages_create();
- attr_size = PA_TNC_ATTR_HEADER_SIZE + IETF_INSTALLED_PACKAGES_MIN_SIZE;
enumerator = os->create_package_enumerator(os);
- if (enumerator)
+ while (enumerator->enumerate(enumerator, &name, &version))
{
- while (enumerator->enumerate(enumerator, &name, &version))
- {
- DBG2(DBG_IMC, "package '%.*s' (%.*s)",
- name.len, name.ptr, version.len, version.ptr);
-
- entry_size = 2 + name.len + version.len;
- if (attr_size + entry_size > max_attr_size)
- {
- if (first)
- {
- /**
- * Send an ITA Start Angel attribute to the IMV signalling
- * that multiple ITA Installed Package 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 IETF Installed Packages attribute */
- attr = ietf_attr_installed_packages_create();
- attr_size = PA_TNC_ATTR_HEADER_SIZE +
- IETF_INSTALLED_PACKAGES_MIN_SIZE;
- }
- attr_cast = (ietf_attr_installed_packages_t*)attr;
- attr_cast->add(attr_cast, name, version);
- attr_size += entry_size;
- }
- enumerator->destroy(enumerator);
+ DBG2(DBG_IMC, "package '%.*s' (%.*s)",
+ name.len, name.ptr, version.len, version.ptr);
+ attr_cast = (ietf_attr_installed_packages_t*)attr;
+ attr_cast->add(attr_cast, name, version);
}
- msg->add_attribute(msg, attr);
+ enumerator->destroy(enumerator);
- 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);
- }
+ msg->add_attribute(msg, attr);
}
/**
@@ -491,13 +445,16 @@ static TNC_Result receive_message(imc_state_t *state, imc_msg_t *in_msg)
TNC_Result result;
bool fatal_error = FALSE;
+ /* generate an outgoing PA-TNC message - we might need it */
+ out_msg = imc_msg_create_as_reply(in_msg);
+
/* parse received PA-TNC message and handle local and remote errors */
- result = in_msg->receive(in_msg, &fatal_error);
+ result = in_msg->receive(in_msg, out_msg, &fatal_error);
if (result != TNC_RESULT_SUCCESS)
{
+ out_msg->destroy(out_msg);
return result;
}
- out_msg = imc_msg_create_as_reply(in_msg);
/* analyze PA-TNC attributes */
enumerator = in_msg->create_attribute_enumerator(in_msg);
@@ -582,6 +539,7 @@ static TNC_Result receive_message(imc_state_t *state, imc_msg_t *in_msg)
}
else
{
+ /* send PA-TNC message with the EXCL flag set */
result = out_msg->send(out_msg, TRUE);
}
out_msg->destroy(out_msg);
diff --git a/src/libimcv/plugins/imc_os/imc_os_state.c b/src/libimcv/plugins/imc_os/imc_os_state.c
index f49959ab9..139ab0597 100644
--- a/src/libimcv/plugins/imc_os/imc_os_state.c
+++ b/src/libimcv/plugins/imc_os/imc_os_state.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Andreas Steffen
+ * Copyright (C) 2012-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -60,6 +60,11 @@ struct private_imc_os_state_t {
* Maximum PA-TNC message size for this TNCCS connection
*/
u_int32_t max_msg_len;
+
+ /**
+ * PA-TNC attribute segmentation contracts associated with TNCCS connection
+ */
+ seg_contract_manager_t *contracts;
};
METHOD(imc_state_t, get_connection_id, TNC_ConnectionID,
@@ -99,6 +104,12 @@ METHOD(imc_state_t, get_max_msg_len, u_int32_t,
return this->max_msg_len;
}
+METHOD(imc_state_t, get_contracts, seg_contract_manager_t*,
+ private_imc_os_state_t *this)
+{
+ return this->contracts;
+}
+
METHOD(imc_state_t, change_state, void,
private_imc_os_state_t *this, TNC_ConnectionState new_state)
{
@@ -126,6 +137,7 @@ METHOD(imc_state_t, get_result, bool,
METHOD(imc_state_t, destroy, void,
private_imc_os_state_t *this)
{
+ this->contracts->destroy(this->contracts);
free(this);
}
@@ -145,6 +157,7 @@ imc_state_t *imc_os_state_create(TNC_ConnectionID connection_id)
.set_flags = _set_flags,
.set_max_msg_len = _set_max_msg_len,
.get_max_msg_len = _get_max_msg_len,
+ .get_contracts = _get_contracts,
.change_state = _change_state,
.set_result = _set_result,
.get_result = _get_result,
@@ -154,6 +167,7 @@ imc_state_t *imc_os_state_create(TNC_ConnectionID connection_id)
.state = TNC_CONNECTION_STATE_CREATE,
.result = TNC_IMV_EVALUATION_RESULT_DONT_KNOW,
.connection_id = connection_id,
+ .contracts = seg_contract_manager_create(),
);
return &this->public.interface;
diff --git a/src/libimcv/plugins/imc_scanner/Makefile.in b/src/libimcv/plugins/imc_scanner/Makefile.in
index c66bb1afa..a192b0a41 100644
--- a/src/libimcv/plugins/imc_scanner/Makefile.in
+++ b/src/libimcv/plugins/imc_scanner/Makefile.in
@@ -231,6 +231,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -291,6 +292,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -356,6 +358,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -403,6 +407,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libimcv/plugins/imc_scanner/imc_scanner.c b/src/libimcv/plugins/imc_scanner/imc_scanner.c
index 2be6a87df..0478841cb 100644
--- a/src/libimcv/plugins/imc_scanner/imc_scanner.c
+++ b/src/libimcv/plugins/imc_scanner/imc_scanner.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
@@ -299,13 +299,16 @@ static TNC_Result receive_message(imc_msg_t *in_msg)
TNC_Result result = TNC_RESULT_SUCCESS;
bool fatal_error = FALSE;
+ /* generate an outgoing PA-TNC message - we might need it */
+ out_msg = imc_msg_create_as_reply(in_msg);
+
/* parse received PA-TNC message and handle local and remote errors */
- result = in_msg->receive(in_msg, &fatal_error);
+ result = in_msg->receive(in_msg, out_msg, &fatal_error);
if (result != TNC_RESULT_SUCCESS)
{
+ out_msg->destroy(out_msg);
return result;
}
- out_msg = imc_msg_create_as_reply(in_msg);
/* analyze PA-TNC attributes */
enumerator = in_msg->create_attribute_enumerator(in_msg);
@@ -352,6 +355,7 @@ static TNC_Result receive_message(imc_msg_t *in_msg)
}
else if (result == TNC_RESULT_SUCCESS)
{
+ /* send PA-TNC message with the EXCL flag set */
result = out_msg->send(out_msg, TRUE);
}
out_msg->destroy(out_msg);
diff --git a/src/libimcv/plugins/imc_scanner/imc_scanner_state.c b/src/libimcv/plugins/imc_scanner/imc_scanner_state.c
index b5a6cdd20..d357859fa 100644
--- a/src/libimcv/plugins/imc_scanner/imc_scanner_state.c
+++ b/src/libimcv/plugins/imc_scanner/imc_scanner_state.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
@@ -60,6 +60,11 @@ struct private_imc_scanner_state_t {
* Maximum PA-TNC message size for this TNCCS connection
*/
u_int32_t max_msg_len;
+
+ /**
+ * PA-TNC attribute segmentation contracts associated with TNCCS connection
+ */
+ seg_contract_manager_t *contracts;
};
METHOD(imc_state_t, get_connection_id, TNC_ConnectionID,
@@ -99,6 +104,12 @@ METHOD(imc_state_t, get_max_msg_len, u_int32_t,
return this->max_msg_len;
}
+METHOD(imc_state_t, get_contracts, seg_contract_manager_t*,
+ private_imc_scanner_state_t *this)
+{
+ return this->contracts;
+}
+
METHOD(imc_state_t, change_state, void,
private_imc_scanner_state_t *this, TNC_ConnectionState new_state)
{
@@ -126,6 +137,7 @@ METHOD(imc_state_t, get_result, bool,
METHOD(imc_state_t, destroy, void,
private_imc_scanner_state_t *this)
{
+ this->contracts->destroy(this->contracts);
free(this);
}
@@ -145,6 +157,7 @@ imc_state_t *imc_scanner_state_create(TNC_ConnectionID connection_id)
.set_flags = _set_flags,
.set_max_msg_len = _set_max_msg_len,
.get_max_msg_len = _get_max_msg_len,
+ .get_contracts = _get_contracts,
.change_state = _change_state,
.set_result = _set_result,
.get_result = _get_result,
@@ -154,6 +167,7 @@ imc_state_t *imc_scanner_state_create(TNC_ConnectionID connection_id)
.state = TNC_CONNECTION_STATE_CREATE,
.result = TNC_IMV_EVALUATION_RESULT_DONT_KNOW,
.connection_id = connection_id,
+ .contracts = seg_contract_manager_create(),
);
return &this->public.interface;
diff --git a/src/libimcv/plugins/imc_swid/Makefile.am b/src/libimcv/plugins/imc_swid/Makefile.am
new file mode 100644
index 000000000..c1cdb988a
--- /dev/null
+++ b/src/libimcv/plugins/imc_swid/Makefile.am
@@ -0,0 +1,37 @@
+regid = regid.2004-03.org.strongswan
+unique_sw_id = strongSwan-$(PACKAGE_VERSION_MAJOR)-$(PACKAGE_VERSION_MINOR)-$(PACKAGE_VERSION_BUILD)$(PACKAGE_VERSION_REVIEW)
+swid_tag = $(regid)_$(unique_sw_id).swidtag
+
+swiddir = $(prefix)/share/$(regid)
+swid_DATA = $(swid_tag)
+ipsec_DATA = $(swid_tag)
+EXTRA_DIST = $(regid)_strongSwan.swidtag.in
+CLEANFILES = $(regid)_strongSwan*.swidtag
+
+$(swid_tag) : regid.2004-03.org.strongswan_strongSwan.swidtag.in
+ $(AM_V_GEN) \
+ sed \
+ -e "s:@VERSION_MAJOR@:$(PACKAGE_VERSION_MAJOR):" \
+ -e "s:@VERSION_MINOR@:$(PACKAGE_VERSION_MINOR):" \
+ -e "s:@VERSION_BUILD@:$(PACKAGE_VERSION_BUILD):" \
+ -e "s:@VERSION_REVIEW@:$(PACKAGE_VERSION_REVIEW):" \
+ $(srcdir)/$(regid)_strongSwan.swidtag.in > $@
+
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libtncif \
+ -I$(top_srcdir)/src/libimcv \
+ -DSWID_DIRECTORY=\"${prefix}/share\"
+
+AM_CFLAGS = \
+ $(PLUGIN_CFLAGS)
+
+imcv_LTLIBRARIES = imc-swid.la
+
+imc_swid_la_LIBADD = \
+ $(top_builddir)/src/libimcv/libimcv.la \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la
+
+imc_swid_la_SOURCES = imc_swid.c imc_swid_state.h imc_swid_state.c
+
+imc_swid_la_LDFLAGS = -module -avoid-version -no-undefined
diff --git a/src/libimcv/plugins/imc_swid/Makefile.in b/src/libimcv/plugins/imc_swid/Makefile.in
new file mode 100644
index 000000000..f1859a2cb
--- /dev/null
+++ b/src/libimcv/plugins/imc_swid/Makefile.in
@@ -0,0 +1,826 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/libimcv/plugins/imc_swid
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/depcomp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
+ $(top_srcdir)/m4/config/ltoptions.m4 \
+ $(top_srcdir)/m4/config/ltsugar.m4 \
+ $(top_srcdir)/m4/config/ltversion.m4 \
+ $(top_srcdir)/m4/config/lt~obsolete.m4 \
+ $(top_srcdir)/m4/macros/split-package-version.m4 \
+ $(top_srcdir)/m4/macros/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/m4/macros/add-plugin.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(imcvdir)" "$(DESTDIR)$(ipsecdir)" \
+ "$(DESTDIR)$(swiddir)"
+LTLIBRARIES = $(imcv_LTLIBRARIES)
+imc_swid_la_DEPENDENCIES = $(top_builddir)/src/libimcv/libimcv.la \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la
+am_imc_swid_la_OBJECTS = imc_swid.lo imc_swid_state.lo
+imc_swid_la_OBJECTS = $(am_imc_swid_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+imc_swid_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(imc_swid_la_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(imc_swid_la_SOURCES)
+DIST_SOURCES = $(imc_swid_la_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+DATA = $(ipsec_DATA) $(swid_DATA)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BFDLIB = @BFDLIB@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+COVERAGE_CFLAGS = @COVERAGE_CFLAGS@
+COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GEM = @GEM@
+GENHTML = @GENHTML@
+GPERF = @GPERF@
+GPRBUILD = @GPRBUILD@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LCOV = @LCOV@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQLCFLAG = @MYSQLCFLAG@
+MYSQLCONFIG = @MYSQLCONFIG@
+MYSQLLIB = @MYSQLLIB@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PACKAGE_VERSION_BUILD = @PACKAGE_VERSION_BUILD@
+PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@
+PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@
+PACKAGE_VERSION_REVIEW = @PACKAGE_VERSION_REVIEW@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+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@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
+RUBYINCLUDE = @RUBYINCLUDE@
+RUBYLIB = @RUBYLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+UNWINDLIB = @UNWINDLIB@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+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@
+am__tar = @am__tar@
+am__untar = @am__untar@
+attest_plugins = @attest_plugins@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+c_plugins = @c_plugins@
+charon_natt_port = @charon_natt_port@
+charon_plugins = @charon_plugins@
+charon_udp_port = @charon_udp_port@
+clearsilver_LIBS = @clearsilver_LIBS@
+cmd_plugins = @cmd_plugins@
+datadir = @datadir@
+datarootdir = @datarootdir@
+dbusservicedir = @dbusservicedir@
+dev_headers = @dev_headers@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+fips_mode = @fips_mode@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+h_plugins = @h_plugins@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+imcvdir = @imcvdir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsec_script = @ipsec_script@
+ipsec_script_upper = @ipsec_script_upper@
+ipsecdir = @ipsecdir@
+ipsecgroup = @ipsecgroup@
+ipseclibdir = @ipseclibdir@
+ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
+libdir = @libdir@
+libexecdir = @libexecdir@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+maemo_CFLAGS = @maemo_CFLAGS@
+maemo_LIBS = @maemo_LIBS@
+manager_plugins = @manager_plugins@
+mandir = @mandir@
+medsrv_plugins = @medsrv_plugins@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
+oldincludedir = @oldincludedir@
+pcsclite_CFLAGS = @pcsclite_CFLAGS@
+pcsclite_LIBS = @pcsclite_LIBS@
+pdfdir = @pdfdir@
+piddir = @piddir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+pki_plugins = @pki_plugins@
+plugindir = @plugindir@
+pool_plugins = @pool_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+s_plugins = @s_plugins@
+sbindir = @sbindir@
+scepclient_plugins = @scepclient_plugins@
+scripts_plugins = @scripts_plugins@
+sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
+srcdir = @srcdir@
+starter_plugins = @starter_plugins@
+strongswan_conf = @strongswan_conf@
+strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
+sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
+systemdsystemunitdir = @systemdsystemunitdir@
+t_plugins = @t_plugins@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+urandom_device = @urandom_device@
+xml_CFLAGS = @xml_CFLAGS@
+xml_LIBS = @xml_LIBS@
+regid = regid.2004-03.org.strongswan
+unique_sw_id = strongSwan-$(PACKAGE_VERSION_MAJOR)-$(PACKAGE_VERSION_MINOR)-$(PACKAGE_VERSION_BUILD)$(PACKAGE_VERSION_REVIEW)
+swid_tag = $(regid)_$(unique_sw_id).swidtag
+swiddir = $(prefix)/share/$(regid)
+swid_DATA = $(swid_tag)
+ipsec_DATA = $(swid_tag)
+EXTRA_DIST = $(regid)_strongSwan.swidtag.in
+CLEANFILES = $(regid)_strongSwan*.swidtag
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libtncif \
+ -I$(top_srcdir)/src/libimcv \
+ -DSWID_DIRECTORY=\"${prefix}/share\"
+
+AM_CFLAGS = \
+ $(PLUGIN_CFLAGS)
+
+imcv_LTLIBRARIES = imc-swid.la
+imc_swid_la_LIBADD = \
+ $(top_builddir)/src/libimcv/libimcv.la \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la
+
+imc_swid_la_SOURCES = imc_swid.c imc_swid_state.h imc_swid_state.c
+imc_swid_la_LDFLAGS = -module -avoid-version -no-undefined
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libimcv/plugins/imc_swid/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libimcv/plugins/imc_swid/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+install-imcvLTLIBRARIES: $(imcv_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ @list='$(imcv_LTLIBRARIES)'; test -n "$(imcvdir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(MKDIR_P) '$(DESTDIR)$(imcvdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(imcvdir)" || exit 1; \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(imcvdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(imcvdir)"; \
+ }
+
+uninstall-imcvLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(imcv_LTLIBRARIES)'; test -n "$(imcvdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(imcvdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(imcvdir)/$$f"; \
+ done
+
+clean-imcvLTLIBRARIES:
+ -test -z "$(imcv_LTLIBRARIES)" || rm -f $(imcv_LTLIBRARIES)
+ @list='$(imcv_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+imc-swid.la: $(imc_swid_la_OBJECTS) $(imc_swid_la_DEPENDENCIES) $(EXTRA_imc_swid_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(imc_swid_la_LINK) -rpath $(imcvdir) $(imc_swid_la_OBJECTS) $(imc_swid_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imc_swid.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imc_swid_state.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-ipsecDATA: $(ipsec_DATA)
+ @$(NORMAL_INSTALL)
+ @list='$(ipsec_DATA)'; test -n "$(ipsecdir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(ipsecdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(ipsecdir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(ipsecdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(ipsecdir)" || exit $$?; \
+ done
+
+uninstall-ipsecDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(ipsec_DATA)'; test -n "$(ipsecdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(ipsecdir)'; $(am__uninstall_files_from_dir)
+install-swidDATA: $(swid_DATA)
+ @$(NORMAL_INSTALL)
+ @list='$(swid_DATA)'; test -n "$(swiddir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(swiddir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(swiddir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(swiddir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(swiddir)" || exit $$?; \
+ done
+
+uninstall-swidDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(swid_DATA)'; test -n "$(swiddir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(swiddir)'; $(am__uninstall_files_from_dir)
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(DATA)
+installdirs:
+ for dir in "$(DESTDIR)$(imcvdir)" "$(DESTDIR)$(ipsecdir)" "$(DESTDIR)$(swiddir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-imcvLTLIBRARIES clean-libtool \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-imcvLTLIBRARIES install-ipsecDATA \
+ install-swidDATA
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-imcvLTLIBRARIES uninstall-ipsecDATA \
+ uninstall-swidDATA
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+ clean-imcvLTLIBRARIES clean-libtool cscopelist-am ctags \
+ ctags-am distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am \
+ install-imcvLTLIBRARIES install-info install-info-am \
+ install-ipsecDATA install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip install-swidDATA \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags tags-am uninstall uninstall-am uninstall-imcvLTLIBRARIES \
+ uninstall-ipsecDATA uninstall-swidDATA
+
+
+$(swid_tag) : regid.2004-03.org.strongswan_strongSwan.swidtag.in
+ $(AM_V_GEN) \
+ sed \
+ -e "s:@VERSION_MAJOR@:$(PACKAGE_VERSION_MAJOR):" \
+ -e "s:@VERSION_MINOR@:$(PACKAGE_VERSION_MINOR):" \
+ -e "s:@VERSION_BUILD@:$(PACKAGE_VERSION_BUILD):" \
+ -e "s:@VERSION_REVIEW@:$(PACKAGE_VERSION_REVIEW):" \
+ $(srcdir)/$(regid)_strongSwan.swidtag.in > $@
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libimcv/plugins/imc_swid/imc_swid.c b/src/libimcv/plugins/imc_swid/imc_swid.c
new file mode 100644
index 000000000..40f352ad9
--- /dev/null
+++ b/src/libimcv/plugins/imc_swid/imc_swid.c
@@ -0,0 +1,424 @@
+/*
+ * Copyright (C) 2013-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "imc_swid_state.h"
+
+#include <imc/imc_agent.h>
+#include <imc/imc_msg.h>
+#include "tcg/seg/tcg_seg_attr_max_size.h"
+#include "tcg/seg/tcg_seg_attr_seg_env.h"
+#include "tcg/swid/tcg_swid_attr_req.h"
+#include "tcg/swid/tcg_swid_attr_tag_inv.h"
+#include "tcg/swid/tcg_swid_attr_tag_id_inv.h"
+#include "swid/swid_inventory.h"
+#include "swid/swid_error.h"
+
+#include <tncif_pa_subtypes.h>
+
+#include <pen/pen.h>
+#include <utils/debug.h>
+
+#define SWID_GENERATOR "/usr/local/bin/swid_generator"
+
+/* IMC definitions */
+
+static const char imc_name[] = "SWID";
+
+static pen_type_t msg_types[] = {
+ { PEN_TCG, PA_SUBTYPE_TCG_SWID }
+};
+
+static imc_agent_t *imc_swid;
+
+/**
+ * see section 3.8.1 of TCG TNC IF-IMC Specification 1.3
+ */
+TNC_Result TNC_IMC_Initialize(TNC_IMCID imc_id,
+ TNC_Version min_version,
+ TNC_Version max_version,
+ TNC_Version *actual_version)
+{
+ if (imc_swid)
+ {
+ DBG1(DBG_IMC, "IMC \"%s\" has already been initialized", imc_name);
+ return TNC_RESULT_ALREADY_INITIALIZED;
+ }
+ imc_swid = imc_agent_create(imc_name, msg_types, countof(msg_types),
+ imc_id, actual_version);
+ if (!imc_swid)
+ {
+ return TNC_RESULT_FATAL;
+ }
+ if (min_version > TNC_IFIMC_VERSION_1 || max_version < TNC_IFIMC_VERSION_1)
+ {
+ DBG1(DBG_IMC, "no common IF-IMC version");
+ return TNC_RESULT_NO_COMMON_VERSION;
+ }
+ return TNC_RESULT_SUCCESS;
+}
+
+/**
+ * see section 3.8.2 of TCG TNC IF-IMC Specification 1.3
+ */
+TNC_Result TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id,
+ TNC_ConnectionID connection_id,
+ TNC_ConnectionState new_state)
+{
+ imc_state_t *state;
+
+ if (!imc_swid)
+ {
+ DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
+ return TNC_RESULT_NOT_INITIALIZED;
+ }
+ switch (new_state)
+ {
+ case TNC_CONNECTION_STATE_CREATE:
+ state = imc_swid_state_create(connection_id);
+ return imc_swid->create_state(imc_swid, state);
+ case TNC_CONNECTION_STATE_HANDSHAKE:
+ if (imc_swid->change_state(imc_swid, connection_id, new_state,
+ &state) != TNC_RESULT_SUCCESS)
+ {
+ return TNC_RESULT_FATAL;
+ }
+ state->set_result(state, imc_id,
+ TNC_IMV_EVALUATION_RESULT_DONT_KNOW);
+ return TNC_RESULT_SUCCESS;
+ case TNC_CONNECTION_STATE_DELETE:
+ return imc_swid->delete_state(imc_swid, connection_id);
+ default:
+ return imc_swid->change_state(imc_swid, connection_id,
+ new_state, NULL);
+ }
+}
+
+/**
+ * see section 3.8.3 of TCG TNC IF-IMC Specification 1.3
+ */
+TNC_Result TNC_IMC_BeginHandshake(TNC_IMCID imc_id,
+ TNC_ConnectionID connection_id)
+{
+ imc_state_t *state;
+ imc_msg_t *out_msg;
+ pa_tnc_attr_t *attr;
+ seg_contract_t *contract;
+ seg_contract_manager_t *contracts;
+ size_t max_attr_size = SWID_MAX_ATTR_SIZE;
+ size_t max_seg_size;
+ char buf[BUF_LEN];
+ TNC_Result result = TNC_RESULT_SUCCESS;
+
+ if (!imc_swid)
+ {
+ DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
+ return TNC_RESULT_NOT_INITIALIZED;
+ }
+ if (!imc_swid->get_state(imc_swid, connection_id, &state))
+ {
+ return TNC_RESULT_FATAL;
+ }
+
+ /* Determine maximum PA-TNC attribute segment size */
+ max_seg_size = state->get_max_msg_len(state) - PA_TNC_HEADER_SIZE
+ - PA_TNC_ATTR_HEADER_SIZE
+ - TCG_SEG_ATTR_SEG_ENV_HEADER
+ - PA_TNC_ATTR_HEADER_SIZE
+ - TCG_SEG_ATTR_MAX_SIZE_SIZE;
+
+ /* Announce support of PA-TNC segmentation to IMV */
+ contract = seg_contract_create(msg_types[0], max_attr_size, max_seg_size,
+ TRUE, imc_id, TRUE);
+ contract->get_info_string(contract, buf, BUF_LEN, TRUE);
+ DBG2(DBG_IMC, "%s", buf);
+ contracts = state->get_contracts(state);
+ contracts->add_contract(contracts, contract);
+ attr = tcg_seg_attr_max_size_create(max_attr_size, max_seg_size, TRUE);
+
+ /* send PA-TNC message with the excl flag not set */
+ out_msg = imc_msg_create(imc_swid, state, connection_id, imc_id,
+ TNC_IMVID_ANY, msg_types[0]);
+ out_msg->add_attribute(out_msg, attr);
+ result = out_msg->send(out_msg, FALSE);
+ out_msg->destroy(out_msg);
+
+ return result;
+}
+
+/**
+ * Add one or multiple SWID Inventory attributes to the send queue
+ */
+static bool add_swid_inventory(imc_state_t *state, imc_msg_t *msg,
+ uint32_t request_id, bool full_tags,
+ swid_inventory_t *targets)
+{
+ pa_tnc_attr_t *attr, *attr_error;
+ imc_swid_state_t *swid_state;
+ swid_inventory_t *swid_inventory;
+ char *swid_directory, *swid_generator;
+ uint32_t eid_epoch;
+ bool 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);
+
+ if (full_tags)
+ {
+ tcg_swid_attr_tag_inv_t *swid_attr;
+ swid_tag_t *tag;
+
+ /* Send a TCG SWID Tag Inventory attribute */
+ attr = tcg_swid_attr_tag_inv_create(request_id, eid_epoch, 1);
+ swid_attr = (tcg_swid_attr_tag_inv_t*)attr;
+
+ enumerator = swid_inventory->create_enumerator(swid_inventory);
+ while (enumerator->enumerate(enumerator, &tag))
+ {
+ swid_attr->add(swid_attr, tag->get_ref(tag));
+ }
+ enumerator->destroy(enumerator);
+ }
+ else
+ {
+ tcg_swid_attr_tag_id_inv_t *swid_id_attr;
+ swid_tag_id_t *tag_id;
+
+ /* Send a TCG SWID Tag ID Inventory attribute */
+ attr = tcg_swid_attr_tag_id_inv_create(request_id, eid_epoch, 1);
+ swid_id_attr = (tcg_swid_attr_tag_id_inv_t*)attr;
+
+ enumerator = swid_inventory->create_enumerator(swid_inventory);
+ while (enumerator->enumerate(enumerator, &tag_id))
+ {
+ swid_id_attr->add(swid_id_attr, tag_id->get_ref(tag_id));
+ }
+ enumerator->destroy(enumerator);
+ }
+
+ msg->add_attribute(msg, attr);
+ swid_inventory->destroy(swid_inventory);
+
+ return TRUE;
+}
+
+static TNC_Result receive_message(imc_state_t *state, imc_msg_t *in_msg)
+{
+ imc_msg_t *out_msg;
+ pa_tnc_attr_t *attr;
+ enumerator_t *enumerator;
+ pen_type_t type;
+ TNC_Result result;
+ bool fatal_error = FALSE;
+
+ /* generate an outgoing PA-TNC message - we might need it */
+ out_msg = imc_msg_create_as_reply(in_msg);
+
+ /* parse received PA-TNC message and handle local and remote errors */
+ result = in_msg->receive(in_msg, out_msg, &fatal_error);
+ if (result != TNC_RESULT_SUCCESS)
+ {
+ out_msg->destroy(out_msg);
+ return result;
+ }
+
+ /* analyze PA-TNC attributes */
+ enumerator = in_msg->create_attribute_enumerator(in_msg);
+ while (enumerator->enumerate(enumerator, &attr))
+ {
+ tcg_swid_attr_req_t *attr_req;
+ uint8_t flags;
+ uint32_t request_id;
+ bool full_tags;
+ swid_inventory_t *targets;
+
+ type = attr->get_type(attr);
+
+ if (type.vendor_id != PEN_TCG || type.type != TCG_SWID_REQUEST)
+ {
+ continue;
+ }
+
+ attr_req = (tcg_swid_attr_req_t*)attr;
+ flags = attr_req->get_flags(attr_req);
+ request_id = attr_req->get_request_id(attr_req);
+ targets = attr_req->get_targets(attr_req);
+
+ if (flags & (TCG_SWID_ATTR_REQ_FLAG_S | TCG_SWID_ATTR_REQ_FLAG_C))
+ {
+ attr = swid_error_create(TCG_SWID_SUBSCRIPTION_DENIED, request_id,
+ 0, "no subscription available yet");
+ out_msg->add_attribute(out_msg, attr);
+ break;
+ }
+ full_tags = (flags & TCG_SWID_ATTR_REQ_FLAG_R) == 0;
+
+ if (!add_swid_inventory(state, out_msg, request_id, full_tags, targets))
+ {
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (fatal_error)
+ {
+ result = TNC_RESULT_FATAL;
+ }
+ else
+ {
+ /* send PA-TNC message with the EXCL flag set */
+ result = out_msg->send(out_msg, TRUE);
+ }
+ out_msg->destroy(out_msg);
+
+ return result;
+}
+
+/**
+ * see section 3.8.4 of TCG TNC IF-IMC Specification 1.3
+
+ */
+TNC_Result TNC_IMC_ReceiveMessage(TNC_IMCID imc_id,
+ TNC_ConnectionID connection_id,
+ TNC_BufferReference msg,
+ TNC_UInt32 msg_len,
+ TNC_MessageType msg_type)
+{
+ imc_state_t *state;
+ imc_msg_t *in_msg;
+ TNC_Result result;
+
+ if (!imc_swid)
+ {
+ DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
+ return TNC_RESULT_NOT_INITIALIZED;
+ }
+ if (!imc_swid->get_state(imc_swid, connection_id, &state))
+ {
+ return TNC_RESULT_FATAL;
+ }
+ in_msg = imc_msg_create_from_data(imc_swid, state, connection_id, msg_type,
+ chunk_create(msg, msg_len));
+ result = receive_message(state, in_msg);
+ in_msg->destroy(in_msg);
+
+ return result;
+}
+
+/**
+ * see section 3.8.6 of TCG TNC IF-IMV Specification 1.3
+ */
+TNC_Result TNC_IMC_ReceiveMessageLong(TNC_IMCID imc_id,
+ TNC_ConnectionID connection_id,
+ TNC_UInt32 msg_flags,
+ TNC_BufferReference msg,
+ TNC_UInt32 msg_len,
+ TNC_VendorID msg_vid,
+ TNC_MessageSubtype msg_subtype,
+ TNC_UInt32 src_imv_id,
+ TNC_UInt32 dst_imc_id)
+{
+ imc_state_t *state;
+ imc_msg_t *in_msg;
+ TNC_Result result;
+
+ if (!imc_swid)
+ {
+ DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
+ return TNC_RESULT_NOT_INITIALIZED;
+ }
+ if (!imc_swid->get_state(imc_swid, connection_id, &state))
+ {
+ return TNC_RESULT_FATAL;
+ }
+ in_msg = imc_msg_create_from_long_data(imc_swid, state, connection_id,
+ src_imv_id, dst_imc_id,msg_vid, msg_subtype,
+ chunk_create(msg, msg_len));
+ result =receive_message(state, in_msg);
+ in_msg->destroy(in_msg);
+
+ return result;
+}
+
+/**
+ * see section 3.8.7 of TCG TNC IF-IMC Specification 1.3
+ */
+TNC_Result TNC_IMC_BatchEnding(TNC_IMCID imc_id,
+ TNC_ConnectionID connection_id)
+{
+ if (!imc_swid)
+ {
+ DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
+ return TNC_RESULT_NOT_INITIALIZED;
+ }
+ return TNC_RESULT_SUCCESS;
+}
+
+/**
+ * see section 3.8.8 of TCG TNC IF-IMC Specification 1.3
+ */
+TNC_Result TNC_IMC_Terminate(TNC_IMCID imc_id)
+{
+ if (!imc_swid)
+ {
+ DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
+ return TNC_RESULT_NOT_INITIALIZED;
+ }
+ imc_swid->destroy(imc_swid);
+ imc_swid = NULL;
+
+ return TNC_RESULT_SUCCESS;
+}
+
+/**
+ * see section 4.2.8.1 of TCG TNC IF-IMC Specification 1.3
+ */
+TNC_Result TNC_IMC_ProvideBindFunction(TNC_IMCID imc_id,
+ TNC_TNCC_BindFunctionPointer bind_function)
+{
+ if (!imc_swid)
+ {
+ DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
+ return TNC_RESULT_NOT_INITIALIZED;
+ }
+ return imc_swid->bind_functions(imc_swid, bind_function);
+}
diff --git a/src/libimcv/plugins/imc_swid/imc_swid_state.c b/src/libimcv/plugins/imc_swid/imc_swid_state.c
new file mode 100644
index 000000000..65c279b3f
--- /dev/null
+++ b/src/libimcv/plugins/imc_swid/imc_swid_state.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2013-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "imc_swid_state.h"
+
+#include <tncif_names.h>
+
+#include <utils/debug.h>
+
+typedef struct private_imc_swid_state_t private_imc_swid_state_t;
+
+/**
+ * Private data of an imc_swid_state_t object.
+ */
+struct private_imc_swid_state_t {
+
+ /**
+ * Public members of imc_swid_state_t
+ */
+ imc_swid_state_t public;
+
+ /**
+ * TNCCS connection ID
+ */
+ TNC_ConnectionID connection_id;
+
+ /**
+ * TNCCS connection state
+ */
+ TNC_ConnectionState state;
+
+ /**
+ * Assessment/Evaluation Result
+ */
+ TNC_IMV_Evaluation_Result result;
+
+ /**
+ * Does the TNCCS connection support long message types?
+ */
+ bool has_long;
+
+ /**
+ * Does the TNCCS connection support exclusive delivery?
+ */
+ bool has_excl;
+
+ /**
+ * Maximum PA-TNC message size for this TNCCS connection
+ */
+ u_int32_t max_msg_len;
+
+ /**
+ * PA-TNC attribute segmentation contracts associated with TNCCS connection
+ */
+ seg_contract_manager_t *contracts;
+
+ /**
+ * Event ID Epoch
+ */
+ u_int32_t eid_epoch;
+};
+
+METHOD(imc_state_t, get_connection_id, TNC_ConnectionID,
+ private_imc_swid_state_t *this)
+{
+ return this->connection_id;
+}
+
+METHOD(imc_state_t, has_long, bool,
+ private_imc_swid_state_t *this)
+{
+ return this->has_long;
+}
+
+METHOD(imc_state_t, has_excl, bool,
+ private_imc_swid_state_t *this)
+{
+ return this->has_excl;
+}
+
+METHOD(imc_state_t, set_flags, void,
+ private_imc_swid_state_t *this, bool has_long, bool has_excl)
+{
+ this->has_long = has_long;
+ this->has_excl = has_excl;
+}
+
+METHOD(imc_state_t, set_max_msg_len, void,
+ private_imc_swid_state_t *this, u_int32_t max_msg_len)
+{
+ this->max_msg_len = max_msg_len;
+}
+
+METHOD(imc_state_t, get_max_msg_len, u_int32_t,
+ private_imc_swid_state_t *this)
+{
+ return this->max_msg_len;
+}
+
+METHOD(imc_state_t, get_contracts, seg_contract_manager_t*,
+ private_imc_swid_state_t *this)
+{
+ return this->contracts;
+}
+
+METHOD(imc_state_t, change_state, void,
+ private_imc_swid_state_t *this, TNC_ConnectionState new_state)
+{
+ this->state = new_state;
+}
+
+METHOD(imc_state_t, set_result, void,
+ private_imc_swid_state_t *this, TNC_IMCID id,
+ TNC_IMV_Evaluation_Result result)
+{
+ this->result = result;
+}
+
+METHOD(imc_state_t, get_result, bool,
+ private_imc_swid_state_t *this, TNC_IMCID id,
+ TNC_IMV_Evaluation_Result *result)
+{
+ if (result)
+ {
+ *result = this->result;
+ }
+ return this->result != TNC_IMV_EVALUATION_RESULT_DONT_KNOW;
+}
+
+METHOD(imc_state_t, destroy, void,
+ private_imc_swid_state_t *this)
+{
+ this->contracts->destroy(this->contracts);
+ free(this);
+}
+
+METHOD(imc_swid_state_t, get_eid_epoch, u_int32_t,
+ private_imc_swid_state_t *this)
+{
+ return this->eid_epoch;
+}
+
+/**
+ * Described in header.
+ */
+imc_state_t *imc_swid_state_create(TNC_ConnectionID connection_id)
+{
+ private_imc_swid_state_t *this;
+ u_int32_t eid_epoch;
+ nonce_gen_t *ng;
+
+ ng = lib->crypto->create_nonce_gen(lib->crypto);
+ if (!ng || !ng->get_nonce(ng, 4, (u_int8_t*)&eid_epoch))
+ {
+ DBG1(DBG_TNC, "failed to generate random EID epoch value");
+ DESTROY_IF(ng);
+ return NULL;
+ }
+ ng->destroy(ng);
+
+ DBG1(DBG_IMC, "creating random EID epoch 0x%08x", eid_epoch);
+
+ INIT(this,
+ .public = {
+ .interface = {
+ .get_connection_id = _get_connection_id,
+ .has_long = _has_long,
+ .has_excl = _has_excl,
+ .set_flags = _set_flags,
+ .set_max_msg_len = _set_max_msg_len,
+ .get_max_msg_len = _get_max_msg_len,
+ .get_contracts = _get_contracts,
+ .change_state = _change_state,
+ .set_result = _set_result,
+ .get_result = _get_result,
+ .destroy = _destroy,
+ },
+ .get_eid_epoch = _get_eid_epoch,
+ },
+ .state = TNC_CONNECTION_STATE_CREATE,
+ .result = TNC_IMV_EVALUATION_RESULT_DONT_KNOW,
+ .connection_id = connection_id,
+ .contracts = seg_contract_manager_create(),
+ .eid_epoch = eid_epoch,
+ );
+
+
+ return &this->public.interface;
+}
+
+
diff --git a/src/libimcv/plugins/imc_swid/imc_swid_state.h b/src/libimcv/plugins/imc_swid/imc_swid_state.h
new file mode 100644
index 000000000..cb3ac4589
--- /dev/null
+++ b/src/libimcv/plugins/imc_swid/imc_swid_state.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2013 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup imc_swid imc_swid
+ * @ingroup libimcv_plugins
+ *
+ * @defgroup imc_swid_state_t imc_swid_state
+ * @{ @ingroup imc_swid
+ */
+
+#ifndef IMC_SWID_STATE_H_
+#define IMC_SWID_STATE_H_
+
+#include <imc/imc_state.h>
+#include <library.h>
+
+typedef struct imc_swid_state_t imc_swid_state_t;
+
+/**
+ * Internal state of an imc_swid_t connection instance
+ */
+struct imc_swid_state_t {
+
+ /**
+ * imc_state_t interface
+ */
+ imc_state_t interface;
+
+ /**
+ * Get Event ID Epoch
+ *
+ * @return Event ID Epoch
+ */
+ u_int32_t (*get_eid_epoch)(imc_swid_state_t *this);
+
+};
+
+/**
+ * Create an imc_swid_state_t instance
+ *
+ * @param id connection ID
+ */
+imc_state_t* imc_swid_state_create(TNC_ConnectionID id);
+
+#endif /** IMC_SWID_STATE_H_ @}*/
diff --git a/src/libimcv/plugins/imc_swid/regid.2004-03.org.strongswan_strongSwan.swidtag.in b/src/libimcv/plugins/imc_swid/regid.2004-03.org.strongswan_strongSwan.swidtag.in
new file mode 100644
index 000000000..8b7b50fdf
--- /dev/null
+++ b/src/libimcv/plugins/imc_swid/regid.2004-03.org.strongswan_strongSwan.swidtag.in
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<SoftwareIdentity
+ name="strongSwan"
+ uniqueId="strongSwan-@VERSION_MAJOR@-@VERSION_MINOR@-@VERSION_BUILD@@VERSION_REVIEW@"
+ version="@VERSION_MAJOR@.@VERSION_MINOR@.@VERSION_BUILD@@VERSION_REVIEW@" versionScheme="alphanumeric"
+ xmlns="http://standards.iso.org/iso/19770/-2/2014/schema.xsd">
+ <Entity
+ name="strongSwan Project"
+ regid="regid.2004-03.org.strongswan"
+ role="publisher licensor tagcreator"/>
+</SoftwareIdentity>
diff --git a/src/libimcv/plugins/imc_test/Makefile.in b/src/libimcv/plugins/imc_test/Makefile.in
index 1702574f9..3e1d0232f 100644
--- a/src/libimcv/plugins/imc_test/Makefile.in
+++ b/src/libimcv/plugins/imc_test/Makefile.in
@@ -230,6 +230,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -290,6 +291,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -355,6 +357,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -402,6 +406,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libimcv/plugins/imc_test/imc_test.c b/src/libimcv/plugins/imc_test/imc_test.c
index ee982d93b..d38ace140 100644
--- a/src/libimcv/plugins/imc_test/imc_test.c
+++ b/src/libimcv/plugins/imc_test/imc_test.c
@@ -181,7 +181,7 @@ TNC_Result TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id,
}
}
-static TNC_Result send_message(imc_state_t *state, imc_msg_t *out_msg)
+static void create_message(imc_state_t *state, imc_msg_t *out_msg)
{
imc_test_state_t *test_state;
pa_tnc_attr_t *attr;
@@ -196,9 +196,6 @@ static TNC_Result send_message(imc_state_t *state, imc_msg_t *out_msg)
attr = ita_attr_command_create(test_state->get_command(test_state));
attr->set_noskip_flag(attr, TRUE);
out_msg->add_attribute(out_msg, attr);
-
- /* send PA-TNC message with the excl flag set */
- return out_msg->send(out_msg, TRUE);
}
/**
@@ -224,10 +221,11 @@ TNC_Result TNC_IMC_BeginHandshake(TNC_IMCID imc_id,
return TNC_RESULT_FATAL;
}
- /* send PA message for primary IMC ID */
+ /* send PA message for primary IMC ID with the EXCL flag set */
out_msg = imc_msg_create(imc_test, state, connection_id, imc_id,
TNC_IMVID_ANY, msg_types[0]);
- result = send_message(state, out_msg);
+ create_message(state, out_msg);
+ result = out_msg->send(out_msg, TRUE);
out_msg->destroy(out_msg);
/* Exit if there are no additional IMC IDs */
@@ -253,7 +251,8 @@ TNC_Result TNC_IMC_BeginHandshake(TNC_IMCID imc_id,
additional_id = (TNC_UInt32)pointer;
out_msg = imc_msg_create(imc_test, state, connection_id, additional_id,
TNC_IMVID_ANY, msg_types[0]);
- result = send_message(state, out_msg);
+ create_message(state, out_msg);
+ result = out_msg->send(out_msg, TRUE);
out_msg->destroy(out_msg);
}
enumerator->destroy(enumerator);
@@ -267,13 +266,17 @@ static TNC_Result receive_message(imc_state_t *state, imc_msg_t *in_msg)
enumerator_t *enumerator;
pa_tnc_attr_t *attr;
pen_type_t attr_type;
- TNC_Result result;
+ TNC_Result result = TNC_RESULT_SUCCESS;
bool fatal_error = FALSE;
+ /* generate an outgoing PA-TNC message - we might need it */
+ out_msg = imc_msg_create_as_reply(in_msg);
+
/* parse received PA-TNC message and handle local and remote errors */
- result = in_msg->receive(in_msg, &fatal_error);
+ result = in_msg->receive(in_msg, out_msg, &fatal_error);
if (result != TNC_RESULT_SUCCESS)
{
+ out_msg->destroy(out_msg);
return result;
}
@@ -308,16 +311,17 @@ static TNC_Result receive_message(imc_state_t *state, imc_msg_t *in_msg)
if (fatal_error)
{
- return TNC_RESULT_FATAL;
+ result = TNC_RESULT_FATAL;
}
-
- /* if no assessment result is known then repeat the measurement */
- if (state->get_result(state, in_msg->get_dst_id(in_msg), NULL))
+ else
{
- return TNC_RESULT_SUCCESS;
+ /* if no assessment result is known then repeat the measurement */
+ if (!state->get_result(state, in_msg->get_dst_id(in_msg), NULL))
+ {
+ create_message(state, out_msg);
+ }
+ result = out_msg->send(out_msg, TRUE);
}
- out_msg = imc_msg_create_as_reply(in_msg);
- result = send_message(state, out_msg);
out_msg->destroy(out_msg);
return result;
diff --git a/src/libimcv/plugins/imc_test/imc_test_state.c b/src/libimcv/plugins/imc_test/imc_test_state.c
index e7beca0aa..d3f6805ad 100644
--- a/src/libimcv/plugins/imc_test/imc_test_state.c
+++ b/src/libimcv/plugins/imc_test/imc_test_state.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
@@ -64,6 +64,11 @@ struct private_imc_test_state_t {
u_int32_t max_msg_len;
/**
+ * PA-TNC attribute segmentation contracts associated with TNCCS connection
+ */
+ seg_contract_manager_t *contracts;
+
+ /**
* Command to transmit to IMV
*/
char *command;
@@ -130,6 +135,12 @@ METHOD(imc_state_t, get_max_msg_len, u_int32_t,
return this->max_msg_len;
}
+METHOD(imc_state_t, get_contracts, seg_contract_manager_t*,
+ private_imc_test_state_t *this)
+{
+ return this->contracts;
+}
+
METHOD(imc_state_t, change_state, void,
private_imc_test_state_t *this, TNC_ConnectionState new_state)
{
@@ -195,6 +206,7 @@ METHOD(imc_state_t, destroy, void,
private_imc_test_state_t *this)
{
this->results->destroy_function(this->results, free);
+ this->contracts->destroy(this->contracts);
free(this->command);
free(this);
}
@@ -261,6 +273,7 @@ imc_state_t *imc_test_state_create(TNC_ConnectionID connection_id,
.set_flags = _set_flags,
.set_max_msg_len = _set_max_msg_len,
.get_max_msg_len = _get_max_msg_len,
+ .get_contracts = _get_contracts,
.change_state = _change_state,
.set_result = _set_result,
.get_result = _get_result,
@@ -275,6 +288,7 @@ imc_state_t *imc_test_state_create(TNC_ConnectionID connection_id,
.state = TNC_CONNECTION_STATE_CREATE,
.results = linked_list_create(),
.connection_id = connection_id,
+ .contracts = seg_contract_manager_create(),
.command = strdup(command),
.dummy_size = dummy_size,
.first_handshake = TRUE,
diff --git a/src/libimcv/plugins/imv_attestation/Makefile.am b/src/libimcv/plugins/imv_attestation/Makefile.am
new file mode 100644
index 000000000..6c5bf8913
--- /dev/null
+++ b/src/libimcv/plugins/imv_attestation/Makefile.am
@@ -0,0 +1,33 @@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libtncif \
+ -I$(top_srcdir)/src/libimcv \
+ -DPLUGINS=\""${attest_plugins}\""
+
+AM_CFLAGS = \
+ $(PLUGIN_CFLAGS)
+
+imcv_LTLIBRARIES = imv-attestation.la
+
+imv_attestation_la_LIBADD = \
+ $(top_builddir)/src/libimcv/libimcv.la \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la
+
+imv_attestation_la_SOURCES = imv_attestation.c \
+ imv_attestation_state.h imv_attestation_state.c \
+ imv_attestation_agent.h imv_attestation_agent.c \
+ imv_attestation_process.h imv_attestation_process.c \
+ imv_attestation_build.h imv_attestation_build.c
+
+imv_attestation_la_LDFLAGS = -module -avoid-version -no-undefined
+
+ipsec_PROGRAMS = attest
+attest_SOURCES = attest.c \
+ attest_usage.h attest_usage.c \
+ attest_db.h attest_db.c
+attest_LDADD = \
+ $(top_builddir)/src/libimcv/libimcv.la \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la
+attest.o : $(top_builddir)/config.status
+
+EXTRA_DIST = build-database.sh
diff --git a/src/libimcv/plugins/imv_attestation/Makefile.in b/src/libimcv/plugins/imv_attestation/Makefile.in
new file mode 100644
index 000000000..3ba7c8c88
--- /dev/null
+++ b/src/libimcv/plugins/imv_attestation/Makefile.in
@@ -0,0 +1,847 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+ipsec_PROGRAMS = attest$(EXEEXT)
+subdir = src/libimcv/plugins/imv_attestation
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/depcomp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
+ $(top_srcdir)/m4/config/ltoptions.m4 \
+ $(top_srcdir)/m4/config/ltsugar.m4 \
+ $(top_srcdir)/m4/config/ltversion.m4 \
+ $(top_srcdir)/m4/config/lt~obsolete.m4 \
+ $(top_srcdir)/m4/macros/split-package-version.m4 \
+ $(top_srcdir)/m4/macros/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/m4/macros/add-plugin.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(imcvdir)" "$(DESTDIR)$(ipsecdir)"
+LTLIBRARIES = $(imcv_LTLIBRARIES)
+imv_attestation_la_DEPENDENCIES = \
+ $(top_builddir)/src/libimcv/libimcv.la \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la
+am_imv_attestation_la_OBJECTS = imv_attestation.lo \
+ imv_attestation_state.lo imv_attestation_agent.lo \
+ imv_attestation_process.lo imv_attestation_build.lo
+imv_attestation_la_OBJECTS = $(am_imv_attestation_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+imv_attestation_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(imv_attestation_la_LDFLAGS) \
+ $(LDFLAGS) -o $@
+PROGRAMS = $(ipsec_PROGRAMS)
+am_attest_OBJECTS = attest.$(OBJEXT) attest_usage.$(OBJEXT) \
+ attest_db.$(OBJEXT)
+attest_OBJECTS = $(am_attest_OBJECTS)
+attest_DEPENDENCIES = $(top_builddir)/src/libimcv/libimcv.la \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(imv_attestation_la_SOURCES) $(attest_SOURCES)
+DIST_SOURCES = $(imv_attestation_la_SOURCES) $(attest_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BFDLIB = @BFDLIB@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+COVERAGE_CFLAGS = @COVERAGE_CFLAGS@
+COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GEM = @GEM@
+GENHTML = @GENHTML@
+GPERF = @GPERF@
+GPRBUILD = @GPRBUILD@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LCOV = @LCOV@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQLCFLAG = @MYSQLCFLAG@
+MYSQLCONFIG = @MYSQLCONFIG@
+MYSQLLIB = @MYSQLLIB@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PACKAGE_VERSION_BUILD = @PACKAGE_VERSION_BUILD@
+PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@
+PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@
+PACKAGE_VERSION_REVIEW = @PACKAGE_VERSION_REVIEW@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+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@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
+RUBYINCLUDE = @RUBYINCLUDE@
+RUBYLIB = @RUBYLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+UNWINDLIB = @UNWINDLIB@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+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@
+am__tar = @am__tar@
+am__untar = @am__untar@
+attest_plugins = @attest_plugins@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+c_plugins = @c_plugins@
+charon_natt_port = @charon_natt_port@
+charon_plugins = @charon_plugins@
+charon_udp_port = @charon_udp_port@
+clearsilver_LIBS = @clearsilver_LIBS@
+cmd_plugins = @cmd_plugins@
+datadir = @datadir@
+datarootdir = @datarootdir@
+dbusservicedir = @dbusservicedir@
+dev_headers = @dev_headers@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+fips_mode = @fips_mode@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+h_plugins = @h_plugins@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+imcvdir = @imcvdir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsec_script = @ipsec_script@
+ipsec_script_upper = @ipsec_script_upper@
+ipsecdir = @ipsecdir@
+ipsecgroup = @ipsecgroup@
+ipseclibdir = @ipseclibdir@
+ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
+libdir = @libdir@
+libexecdir = @libexecdir@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+maemo_CFLAGS = @maemo_CFLAGS@
+maemo_LIBS = @maemo_LIBS@
+manager_plugins = @manager_plugins@
+mandir = @mandir@
+medsrv_plugins = @medsrv_plugins@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
+oldincludedir = @oldincludedir@
+pcsclite_CFLAGS = @pcsclite_CFLAGS@
+pcsclite_LIBS = @pcsclite_LIBS@
+pdfdir = @pdfdir@
+piddir = @piddir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+pki_plugins = @pki_plugins@
+plugindir = @plugindir@
+pool_plugins = @pool_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+s_plugins = @s_plugins@
+sbindir = @sbindir@
+scepclient_plugins = @scepclient_plugins@
+scripts_plugins = @scripts_plugins@
+sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
+srcdir = @srcdir@
+starter_plugins = @starter_plugins@
+strongswan_conf = @strongswan_conf@
+strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
+sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
+systemdsystemunitdir = @systemdsystemunitdir@
+t_plugins = @t_plugins@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+urandom_device = @urandom_device@
+xml_CFLAGS = @xml_CFLAGS@
+xml_LIBS = @xml_LIBS@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libtncif \
+ -I$(top_srcdir)/src/libimcv \
+ -DPLUGINS=\""${attest_plugins}\""
+
+AM_CFLAGS = \
+ $(PLUGIN_CFLAGS)
+
+imcv_LTLIBRARIES = imv-attestation.la
+imv_attestation_la_LIBADD = \
+ $(top_builddir)/src/libimcv/libimcv.la \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la
+
+imv_attestation_la_SOURCES = imv_attestation.c \
+ imv_attestation_state.h imv_attestation_state.c \
+ imv_attestation_agent.h imv_attestation_agent.c \
+ imv_attestation_process.h imv_attestation_process.c \
+ imv_attestation_build.h imv_attestation_build.c
+
+imv_attestation_la_LDFLAGS = -module -avoid-version -no-undefined
+attest_SOURCES = attest.c \
+ attest_usage.h attest_usage.c \
+ attest_db.h attest_db.c
+
+attest_LDADD = \
+ $(top_builddir)/src/libimcv/libimcv.la \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la
+
+EXTRA_DIST = build-database.sh
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libimcv/plugins/imv_attestation/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libimcv/plugins/imv_attestation/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+install-imcvLTLIBRARIES: $(imcv_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ @list='$(imcv_LTLIBRARIES)'; test -n "$(imcvdir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(MKDIR_P) '$(DESTDIR)$(imcvdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(imcvdir)" || exit 1; \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(imcvdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(imcvdir)"; \
+ }
+
+uninstall-imcvLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(imcv_LTLIBRARIES)'; test -n "$(imcvdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(imcvdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(imcvdir)/$$f"; \
+ done
+
+clean-imcvLTLIBRARIES:
+ -test -z "$(imcv_LTLIBRARIES)" || rm -f $(imcv_LTLIBRARIES)
+ @list='$(imcv_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+imv-attestation.la: $(imv_attestation_la_OBJECTS) $(imv_attestation_la_DEPENDENCIES) $(EXTRA_imv_attestation_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(imv_attestation_la_LINK) -rpath $(imcvdir) $(imv_attestation_la_OBJECTS) $(imv_attestation_la_LIBADD) $(LIBS)
+install-ipsecPROGRAMS: $(ipsec_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ @list='$(ipsec_PROGRAMS)'; test -n "$(ipsecdir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(ipsecdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(ipsecdir)" || exit 1; \
+ fi; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p \
+ || test -f $$p1 \
+ ; then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' \
+ -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(ipsecdir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(ipsecdir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-ipsecPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(ipsec_PROGRAMS)'; test -n "$(ipsecdir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' \
+ `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(ipsecdir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(ipsecdir)" && rm -f $$files
+
+clean-ipsecPROGRAMS:
+ @list='$(ipsec_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+
+attest$(EXEEXT): $(attest_OBJECTS) $(attest_DEPENDENCIES) $(EXTRA_attest_DEPENDENCIES)
+ @rm -f attest$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(attest_OBJECTS) $(attest_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/attest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/attest_db.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/attest_usage.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imv_attestation.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imv_attestation_agent.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imv_attestation_build.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imv_attestation_process.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imv_attestation_state.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(PROGRAMS)
+installdirs:
+ for dir in "$(DESTDIR)$(imcvdir)" "$(DESTDIR)$(ipsecdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-imcvLTLIBRARIES clean-ipsecPROGRAMS \
+ clean-libtool mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-imcvLTLIBRARIES install-ipsecPROGRAMS
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-imcvLTLIBRARIES uninstall-ipsecPROGRAMS
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+ clean-imcvLTLIBRARIES clean-ipsecPROGRAMS clean-libtool \
+ cscopelist-am ctags ctags-am distclean distclean-compile \
+ distclean-generic distclean-libtool distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-imcvLTLIBRARIES install-info install-info-am \
+ install-ipsecPROGRAMS install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags tags-am uninstall uninstall-am uninstall-imcvLTLIBRARIES \
+ uninstall-ipsecPROGRAMS
+
+attest.o : $(top_builddir)/config.status
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libimcv/plugins/imv_attestation/attest.c b/src/libimcv/plugins/imv_attestation/attest.c
new file mode 100644
index 000000000..1143a0356
--- /dev/null
+++ b/src/libimcv/plugins/imv_attestation/attest.c
@@ -0,0 +1,484 @@
+/*
+ * Copyright (C) 2011-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#define _GNU_SOURCE
+#include <getopt.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <libgen.h>
+#ifdef HAVE_SYSLOG
+# include <syslog.h>
+#endif
+
+#include <library.h>
+#include <utils/debug.h>
+
+#include <imcv.h>
+#include <pts/pts_meas_algo.h>
+
+#include "attest_db.h"
+#include "attest_usage.h"
+
+/**
+ * global debug output variables
+ */
+static int debug_level = 1;
+static bool stderr_quiet = TRUE;
+
+/**
+ * attest dbg function
+ */
+static void attest_dbg(debug_t group, level_t level, char *fmt, ...)
+{
+ va_list args;
+
+ if (level <= debug_level)
+ {
+ if (!stderr_quiet)
+ {
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ fprintf(stderr, "\n");
+ va_end(args);
+ }
+
+#ifdef HAVE_SYSLOG
+ {
+ int priority = LOG_INFO;
+ char buffer[8192];
+ char *current = buffer, *next;
+
+ /* write in memory buffer first */
+ va_start(args, fmt);
+ vsnprintf(buffer, sizeof(buffer), fmt, args);
+ va_end(args);
+
+ /* do a syslog with every line */
+ while (current)
+ {
+ next = strchr(current, '\n');
+ if (next)
+ {
+ *(next++) = '\0';
+ }
+ syslog(priority, "%s\n", current);
+ current = next;
+ }
+ }
+#endif /* HAVE_SYSLOG */
+ }
+}
+
+/**
+ * global attestation database object
+ */
+attest_db_t *attest;
+
+
+/**
+ * atexit handler to close db on shutdown
+ */
+static void cleanup(void)
+{
+ attest->destroy(attest);
+ libimcv_deinit();
+#ifdef HAVE_SYSLOG
+ closelog();
+#endif
+}
+
+static void do_args(int argc, char *argv[])
+{
+ enum {
+ OP_UNDEF,
+ OP_USAGE,
+ OP_KEYS,
+ OP_COMPONENTS,
+ OP_DEVICES,
+ OP_DIRECTORIES,
+ OP_FILES,
+ OP_HASHES,
+ OP_MEASUREMENTS,
+ OP_PACKAGES,
+ OP_PRODUCTS,
+ OP_SESSIONS,
+ OP_ADD,
+ OP_DEL,
+ } op = OP_UNDEF;
+
+ /* reinit getopt state */
+ optind = 0;
+
+ while (TRUE)
+ {
+ int c;
+
+ struct option long_opts[] = {
+ { "help", no_argument, NULL, 'h' },
+ { "components", no_argument, NULL, 'c' },
+ { "devices", no_argument, NULL, 'e' },
+ { "directories", no_argument, NULL, 'd' },
+ { "dirs", no_argument, NULL, 'd' },
+ { "files", no_argument, NULL, 'f' },
+ { "keys", no_argument, NULL, 'k' },
+ { "packages", no_argument, NULL, 'g' },
+ { "products", no_argument, NULL, 'p' },
+ { "hashes", no_argument, NULL, 'H' },
+ { "measurements", no_argument, NULL, 'm' },
+ { "sessions", no_argument, NULL, 's' },
+ { "add", no_argument, NULL, 'a' },
+ { "delete", no_argument, NULL, 'r' },
+ { "del", no_argument, NULL, 'r' },
+ { "remove", no_argument, NULL, 'r' },
+ { "aik", required_argument, NULL, 'A' },
+ { "blacklist", no_argument, NULL, 'B' },
+ { "component", required_argument, NULL, 'C' },
+ { "comp", required_argument, NULL, 'C' },
+ { "directory", required_argument, NULL, 'D' },
+ { "dir", required_argument, NULL, 'D' },
+ { "file", required_argument, NULL, 'F' },
+ { "package", required_argument, NULL, 'G' },
+ { "key", required_argument, NULL, 'K' },
+ { "measdir", required_argument, NULL, 'M' },
+ { "owner", required_argument, NULL, 'O' },
+ { "product", required_argument, NULL, 'P' },
+ { "relative", no_argument, NULL, 'R' },
+ { "rel", no_argument, NULL, 'R' },
+ { "sequence", required_argument, NULL, 'S' },
+ { "seq", required_argument, NULL, 'S' },
+ { "utc", no_argument, NULL, 'U' },
+ { "version", required_argument, NULL, 'V' },
+ { "security", no_argument, NULL, 'Y' },
+ { "sha1", no_argument, NULL, '1' },
+ { "sha256", no_argument, NULL, '2' },
+ { "sha384", no_argument, NULL, '3' },
+ { "did", required_argument, NULL, '4' },
+ { "fid", required_argument, NULL, '5' },
+ { "pid", required_argument, NULL, '6' },
+ { "cid", required_argument, NULL, '7' },
+ { "kid", required_argument, NULL, '8' },
+ { "gid", required_argument, NULL, '9' },
+ { 0,0,0,0 }
+ };
+
+ c = getopt_long(argc, argv, "", long_opts, NULL);
+ switch (c)
+ {
+ case EOF:
+ break;
+ case 'h':
+ op = OP_USAGE;
+ break;
+ case 'c':
+ op = OP_COMPONENTS;
+ continue;
+ case 'd':
+ op = OP_DIRECTORIES;
+ continue;
+ case 'e':
+ op = OP_DEVICES;
+ continue;
+ case 'f':
+ op = OP_FILES;
+ continue;
+ case 'g':
+ op = OP_PACKAGES;
+ continue;
+ case 'k':
+ op = OP_KEYS;
+ continue;
+ case 'p':
+ op = OP_PRODUCTS;
+ continue;
+ case 'H':
+ op = OP_HASHES;
+ continue;
+ case 'm':
+ op = OP_MEASUREMENTS;
+ continue;
+ case 's':
+ op = OP_SESSIONS;
+ continue;
+ case 'a':
+ op = OP_ADD;
+ continue;
+ case 'r':
+ op = OP_DEL;
+ continue;
+ case 'A':
+ {
+ certificate_t *aik_cert;
+ public_key_t *aik_key;
+ chunk_t aik;
+
+ aik_cert = lib->creds->create(lib->creds, CRED_CERTIFICATE,
+ CERT_X509, BUILD_FROM_FILE, optarg, BUILD_END);
+ if (!aik_cert)
+ {
+ printf("AIK certificate '%s' could not be loaded\n", optarg);
+ exit(EXIT_FAILURE);
+ }
+ aik_key = aik_cert->get_public_key(aik_cert);
+ aik_cert->destroy(aik_cert);
+
+ if (!aik_key)
+ {
+ printf("AIK public key could not be retrieved\n");
+ exit(EXIT_FAILURE);
+ }
+ if (!aik_key->get_fingerprint(aik_key, KEYID_PUBKEY_INFO_SHA1,
+ &aik))
+ {
+ printf("AIK fingerprint could not be computed\n");
+ aik_key->destroy(aik_key);
+ exit(EXIT_FAILURE);
+ }
+ aik = chunk_clone(aik);
+ aik_key->destroy(aik_key);
+
+ if (!attest->set_key(attest, aik, op == OP_ADD))
+ {
+ exit(EXIT_FAILURE);
+ }
+ continue;
+ }
+ case 'B':
+ attest->set_package_state(attest, OS_PACKAGE_STATE_BLACKLIST);
+ continue;
+ case 'C':
+ if (!attest->set_component(attest, optarg, op == OP_ADD))
+ {
+ exit(EXIT_FAILURE);
+ }
+ continue;
+ case 'D':
+ if (!attest->set_directory(attest, optarg, op == OP_ADD))
+ {
+ exit(EXIT_FAILURE);
+ }
+ continue;
+ case 'F':
+ {
+ char *dir = path_dirname(optarg);
+ char *file = path_basename(optarg);
+
+ if (*dir != '.')
+ {
+ if (!attest->set_directory(attest, dir, op == OP_ADD))
+ {
+ free(file);
+ free(dir);
+ exit(EXIT_FAILURE);
+ }
+ }
+ free(dir);
+
+ if (!attest->set_file(attest, file, op == OP_ADD))
+ {
+ free(file);
+ exit(EXIT_FAILURE);
+ }
+ free(file);
+ continue;
+ }
+ case 'G':
+ if (!attest->set_package(attest, optarg, op == OP_ADD))
+ {
+ exit(EXIT_FAILURE);
+ }
+ continue;
+ case 'K':
+ {
+ chunk_t aik;
+
+ aik = chunk_from_hex(chunk_create(optarg, strlen(optarg)), NULL);
+ if (!attest->set_key(attest, aik, op == OP_ADD))
+ {
+ exit(EXIT_FAILURE);
+ }
+ continue;
+ }
+ case 'M':
+ if (!attest->set_meas_directory(attest, optarg))
+ {
+ exit(EXIT_FAILURE);
+ }
+ continue;
+ case 'O':
+ attest->set_owner(attest, optarg);
+ continue;
+ case 'P':
+ if (!attest->set_product(attest, optarg, op == OP_ADD))
+ {
+ exit(EXIT_FAILURE);
+ }
+ continue;
+ case 'R':
+ attest->set_relative(attest);
+ continue;
+ case 'S':
+ attest->set_sequence(attest, atoi(optarg));
+ continue;
+ case 'U':
+ attest->set_utc(attest);
+ continue;
+ case 'V':
+ if (!attest->set_version(attest, optarg))
+ {
+ exit(EXIT_FAILURE);
+ }
+ continue;
+ case 'Y':
+ attest->set_package_state(attest, OS_PACKAGE_STATE_SECURITY);
+ continue;
+ case '1':
+ attest->set_algo(attest, PTS_MEAS_ALGO_SHA1);
+ continue;
+ case '2':
+ attest->set_algo(attest, PTS_MEAS_ALGO_SHA256);
+ continue;
+ case '3':
+ attest->set_algo(attest, PTS_MEAS_ALGO_SHA384);
+ continue;
+ case '4':
+ if (!attest->set_did(attest, atoi(optarg)))
+ {
+ exit(EXIT_FAILURE);
+ }
+ continue;
+ case '5':
+ if (!attest->set_fid(attest, atoi(optarg)))
+ {
+ exit(EXIT_FAILURE);
+ }
+ continue;
+ case '6':
+ if (!attest->set_pid(attest, atoi(optarg)))
+ {
+ exit(EXIT_FAILURE);
+ }
+ continue;
+ case '7':
+ if (!attest->set_cid(attest, atoi(optarg)))
+ {
+ exit(EXIT_FAILURE);
+ }
+ continue;
+ case '8':
+ if (!attest->set_kid(attest, atoi(optarg)))
+ {
+ exit(EXIT_FAILURE);
+ }
+ continue;
+ case '9':
+ if (!attest->set_gid(attest, atoi(optarg)))
+ {
+ exit(EXIT_FAILURE);
+ }
+ continue;
+ }
+ break;
+ }
+
+ switch (op)
+ {
+ case OP_USAGE:
+ usage();
+ break;
+ case OP_PACKAGES:
+ attest->list_packages(attest);
+ break;
+ case OP_PRODUCTS:
+ attest->list_products(attest);
+ break;
+ case OP_KEYS:
+ attest->list_keys(attest);
+ break;
+ case OP_COMPONENTS:
+ attest->list_components(attest);
+ break;
+ case OP_DEVICES:
+ attest->list_devices(attest);
+ break;
+ case OP_DIRECTORIES:
+ attest->list_directories(attest);
+ break;
+ case OP_FILES:
+ attest->list_files(attest);
+ break;
+ case OP_HASHES:
+ attest->list_hashes(attest);
+ break;
+ case OP_MEASUREMENTS:
+ attest->list_measurements(attest);
+ break;
+ case OP_SESSIONS:
+ attest->list_sessions(attest);
+ break;
+ case OP_ADD:
+ attest->add(attest);
+ break;
+ case OP_DEL:
+ attest->delete(attest);
+ break;
+ default:
+ usage();
+ exit(EXIT_FAILURE);
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ char *uri;
+
+ /* enable attest debugging hook */
+ dbg = attest_dbg;
+#ifdef HAVE_SYSLOG
+ openlog("attest", 0, LOG_DEBUG);
+#endif
+
+ atexit(library_deinit);
+
+ /* initialize library */
+ if (!library_init(NULL, "attest"))
+ {
+ exit(SS_RC_LIBSTRONGSWAN_INTEGRITY);
+ }
+ if (!lib->plugins->load(lib->plugins,
+ lib->settings->get_str(lib->settings, "attest.load", PLUGINS)))
+ {
+ exit(SS_RC_INITIALIZATION_FAILED);
+ }
+
+ uri = lib->settings->get_str(lib->settings, "attest.database", NULL);
+ if (!uri)
+ {
+ fprintf(stderr, "database URI attest.database not set.\n");
+ exit(SS_RC_INITIALIZATION_FAILED);
+ }
+ attest = attest_db_create(uri);
+ if (!attest)
+ {
+ exit(SS_RC_INITIALIZATION_FAILED);
+ }
+ atexit(cleanup);
+ libimcv_init(FALSE);
+
+ do_args(argc, argv);
+
+ exit(EXIT_SUCCESS);
+}
diff --git a/src/libimcv/plugins/imv_attestation/attest_db.c b/src/libimcv/plugins/imv_attestation/attest_db.c
new file mode 100644
index 000000000..f85a02b3d
--- /dev/null
+++ b/src/libimcv/plugins/imv_attestation/attest_db.c
@@ -0,0 +1,1995 @@
+/*
+ * Copyright (C) 2011-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <libgen.h>
+#include <time.h>
+
+#include <tncif_names.h>
+
+#include "attest_db.h"
+
+#include "imcv.h"
+#include "pts/pts_meas_algo.h"
+#include "pts/pts_file_meas.h"
+#include "pts/components/pts_comp_func_name.h"
+
+#define IMA_MAX_NAME_LEN 255
+#define DEVICE_MAX_LEN 20
+
+typedef struct private_attest_db_t private_attest_db_t;
+
+/**
+ * Private data of an attest_db_t object.
+ */
+struct private_attest_db_t {
+
+ /**
+ * Public members of attest_db_state_t
+ */
+ attest_db_t public;
+
+ /**
+ * Component Functional Name to be queried
+ */
+ pts_comp_func_name_t *cfn;
+
+ /**
+ * Primary key of the Component Functional Name to be queried
+ */
+ int cid;
+
+ /**
+ * TRUE if Component Functional Name has been set
+ */
+ bool comp_set;
+
+ /**
+ * Directory containing the Measurement file to be queried
+ */
+ char *dir;
+
+ /**
+ * Primary key of the directory to be queried
+ */
+ int did;
+
+ /**
+ * Measurement file to be queried
+ */
+ char *file;
+
+ /**
+ * Primary key of measurement file to be queried
+ */
+ int fid;
+
+ /**
+ * Directory where file measurement are to be taken
+ */
+ char *meas_dir;
+
+ /**
+ * AIK to be queried
+ */
+ chunk_t key;
+
+ /**
+ * Primary key of the AIK to be queried
+ */
+ int kid;
+
+ /**
+ * TRUE if AIK has been set
+ */
+ bool key_set;
+
+ /**
+ * Software package to be queried
+ */
+ char *package;
+
+ /**
+ * Primary key of software package to be queried
+ */
+ int gid;
+
+ /**
+ * TRUE if package has been set
+ */
+ bool package_set;
+
+ /**
+ * Software product to be queried
+ */
+ char *product;
+
+ /**
+ * Primary key of software product to be queried
+ */
+ int pid;
+
+ /**
+ * TRUE if product has been set
+ */
+ bool product_set;
+
+ /**
+ * Software package version to be queried
+ */
+ char *version;
+
+ /**
+ * TRUE if version has been set
+ */
+ bool version_set;
+
+ /**
+ * TRUE if relative filenames are to be used
+ */
+ bool relative;
+
+ /**
+ * TRUE if dates are to be displayed in UTC
+ */
+ bool utc;
+
+ /**
+ * Package security or blacklist state
+ */
+ os_package_state_t package_state;
+
+ /**
+ * Sequence number for ordering entries
+ */
+ int seq_no;
+
+ /**
+ * File measurement hash algorithm
+ */
+ pts_meas_algorithms_t algo;
+
+ /**
+ * Optional owner (user/host name)
+ */
+ char *owner;
+
+ /**
+ * Attestation database
+ */
+ database_t *db;
+
+};
+
+char* print_cfn(pts_comp_func_name_t *cfn)
+{
+ static char buf[BUF_LEN];
+ char flags[8];
+ int type, vid, name, qualifier, n;
+ enum_name_t *names, *types;
+
+ vid = cfn->get_vendor_id(cfn),
+ name = cfn->get_name(cfn);
+ qualifier = cfn->get_qualifier(cfn);
+ n = snprintf(buf, BUF_LEN, "0x%06x/0x%08x-0x%02x", vid, name, qualifier);
+
+ names = imcv_pts_components->get_comp_func_names(imcv_pts_components, vid);
+ types = imcv_pts_components->get_qualifier_type_names(imcv_pts_components,
+ vid);
+ type = imcv_pts_components->get_qualifier(imcv_pts_components, cfn, flags);
+ if (names && types)
+ {
+ n = snprintf(buf + n, BUF_LEN - n, " %N/%N [%s] %N",
+ pen_names, vid, names, name, flags, types, type);
+ }
+ 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)
+{
+ enumerator_t *e;
+ char *pos1, *pos2;
+ int vid, name, qualifier;
+ pts_comp_func_name_t *cfn;
+
+ if (this->comp_set)
+ {
+ printf("component has already been set\n");
+ return FALSE;
+ }
+
+ /* parse component string */
+ pos1 = strchr(comp, '/');
+ pos2 = strchr(comp, '-');
+ if (!pos1 || !pos2)
+ {
+ printf("component string must have the form \"vendor_id/name-qualifier\"\n");
+ return FALSE;
+ }
+ vid = atoi(comp);
+ name = atoi(pos1 + 1);
+ qualifier = atoi(pos2 + 1);
+ cfn = pts_comp_func_name_create(vid, name, qualifier);
+
+ e = this->db->query(this->db,
+ "SELECT id FROM components "
+ "WHERE vendor_id = ? AND name = ? AND qualifier = ?",
+ DB_UINT, vid, DB_INT, name, DB_INT, qualifier, DB_INT);
+ if (e)
+ {
+ if (e->enumerate(e, &this->cid))
+ {
+ this->comp_set = TRUE;
+ this->cfn = cfn;
+ }
+ e->destroy(e);
+ }
+ if (this->comp_set)
+ {
+ return TRUE;
+ }
+
+ if (!create)
+ {
+ printf("component '%s' not found in database\n", print_cfn(cfn));
+ cfn->destroy(cfn);
+ return FALSE;
+ }
+
+ /* Add a new database entry */
+ this->comp_set = this->db->execute(this->db, &this->cid,
+ "INSERT INTO components (vendor_id, name, qualifier) "
+ "VALUES (?, ?, ?)",
+ DB_INT, vid, DB_INT, name, DB_INT, qualifier) == 1;
+
+ printf("component '%s' %sinserted into database\n", print_cfn(cfn),
+ this->comp_set ? "" : "could not be ");
+ if (this->comp_set)
+ {
+ this->cfn = cfn;
+ }
+ else
+ {
+ cfn->destroy(cfn);
+ }
+ return this->comp_set;
+}
+
+METHOD(attest_db_t, set_cid, bool,
+ private_attest_db_t *this, int cid)
+{
+ enumerator_t *e;
+ int vid, name, qualifier;
+
+ if (this->comp_set)
+ {
+ printf("component has already been set\n");
+ return FALSE;
+ }
+ this->cid = cid;
+
+ e = this->db->query(this->db, "SELECT vendor_id, name, qualifier "
+ "FROM components WHERE id = ?",
+ DB_UINT, cid, DB_INT, DB_INT, DB_INT);
+ if (e)
+ {
+ if (e->enumerate(e, &vid, &name, &qualifier))
+ {
+ this->cfn = pts_comp_func_name_create(vid, name, qualifier);
+ this->comp_set = TRUE;
+ }
+ else
+ {
+ printf("no component found with cid %d\n", cid);
+ }
+ e->destroy(e);
+ }
+ return this->comp_set;
+}
+
+METHOD(attest_db_t, set_directory, bool,
+ private_attest_db_t *this, char *dir, bool create)
+{
+ enumerator_t *e;
+ int did;
+ size_t len;
+
+ if (this->did)
+ {
+ printf("directory has already been set\n");
+ return FALSE;
+ }
+
+ /* remove trailing '/' or '\' character if not root directory */
+ len = strlen(dir);
+ if (len > 1 && dir[len-1] == DIRECTORY_SEPARATOR[0])
+ {
+ dir[len-1] = '\0';
+ }
+ this->dir = strdup(dir);
+
+ e = this->db->query(this->db,
+ "SELECT id FROM directories WHERE path = ?",
+ DB_TEXT, dir, DB_INT);
+ if (e)
+ {
+ if (e->enumerate(e, &did))
+ {
+ this->did = did;
+ }
+ e->destroy(e);
+ }
+ if (this->did)
+ {
+ return TRUE;
+ }
+
+ if (!create)
+ {
+ printf("directory '%s' not found in database\n", dir);
+ return FALSE;
+ }
+
+ /* Add a new database entry */
+ if (1 == this->db->execute(this->db, &did,
+ "INSERT INTO directories (path) VALUES (?)", DB_TEXT, dir))
+ {
+ this->did = did;
+ }
+ printf("directory '%s' %sinserted into database\n", dir,
+ this->did ? "" : "could not be ");
+
+ return this->did > 0;
+}
+
+METHOD(attest_db_t, set_did, bool,
+ private_attest_db_t *this, int did)
+{
+ enumerator_t *e;
+ char *dir;
+
+ if (this->did)
+ {
+ printf("directory has already been set\n");
+ return FALSE;
+ }
+
+ e = this->db->query(this->db, "SELECT path FROM directories WHERE id = ?",
+ DB_UINT, did, DB_TEXT);
+ if (e)
+ {
+ if (e->enumerate(e, &dir))
+ {
+ this->dir = strdup(dir);
+ this->did = did;
+ }
+ else
+ {
+ printf("no directory found with did %d\n", did);
+ }
+ e->destroy(e);
+ }
+ return this->did > 0;
+}
+
+METHOD(attest_db_t, set_file, bool,
+ private_attest_db_t *this, char *file, bool create)
+{
+ int fid;
+ enumerator_t *e;
+
+ if (this->file)
+ {
+ printf("file has already been set\n");
+ return FALSE;
+ }
+ this->file = strdup(file);
+
+ if (!this->did)
+ {
+ return TRUE;
+ }
+ e = this->db->query(this->db, "SELECT id FROM files "
+ "WHERE dir = ? AND name = ?",
+ DB_INT, this->did, DB_TEXT, file, DB_INT);
+ if (e)
+ {
+ if (e->enumerate(e, &fid))
+ {
+ this->fid = fid;
+ }
+ e->destroy(e);
+ }
+ if (this->fid)
+ {
+ return TRUE;
+ }
+
+ if (!create)
+ {
+ printf("file '%s%s%s' not found in database\n",
+ this->dir, get_separator(this->dir), file);
+ return FALSE;
+ }
+
+ /* Add a new database entry */
+ if (1 == this->db->execute(this->db, &fid,
+ "INSERT INTO files (dir, name) VALUES (?, ?)",
+ DB_INT, this->did, DB_TEXT, file))
+ {
+ this->fid = fid;
+ }
+ 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;
+}
+
+METHOD(attest_db_t, set_fid, bool,
+ private_attest_db_t *this, int fid)
+{
+ enumerator_t *e;
+ int did;
+ char *file;
+
+ if (this->fid)
+ {
+ printf("file has already been set\n");
+ return FALSE;
+ }
+
+ e = this->db->query(this->db, "SELECT dir, name FROM files WHERE id = ?",
+ DB_UINT, fid, DB_INT, DB_TEXT);
+ if (e)
+ {
+ if (e->enumerate(e, &did, &file))
+ {
+ if (did)
+ {
+ set_did(this, did);
+ }
+ this->file = strdup(file);
+ this->fid = fid;
+ }
+ else
+ {
+ printf("no file found with fid %d\n", fid);
+ }
+ e->destroy(e);
+ }
+ 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)
+{
+ enumerator_t *e;
+ char *owner;
+
+ if (this->key_set)
+ {
+ printf("key has already been set\n");
+ return FALSE;
+ }
+ this->key = key;
+
+ e = this->db->query(this->db, "SELECT id, owner FROM keys WHERE keyid= ?",
+ DB_BLOB, this->key, DB_INT, DB_TEXT);
+ if (e)
+ {
+ if (e->enumerate(e, &this->kid, &owner))
+ {
+ free(this->owner);
+ this->owner = strdup(owner);
+ this->key_set = TRUE;
+ }
+ e->destroy(e);
+ }
+ if (this->key_set)
+ {
+ return TRUE;
+ }
+
+ if (!create)
+ {
+ printf("key '%#B' not found in database\n", &this->key);
+ return FALSE;
+ }
+
+ /* Add a new database entry */
+ if (!this->owner)
+ {
+ this->owner = strdup("");
+ }
+ this->key_set = this->db->execute(this->db, &this->kid,
+ "INSERT INTO keys (keyid, owner) VALUES (?, ?)",
+ DB_BLOB, this->key, DB_TEXT, this->owner) == 1;
+
+ printf("key '%#B' %sinserted into database\n", &this->key,
+ this->key_set ? "" : "could not be ");
+
+ return this->key_set;
+
+};
+
+METHOD(attest_db_t, set_kid, bool,
+ private_attest_db_t *this, int kid)
+{
+ enumerator_t *e;
+ chunk_t key;
+ char *owner;
+
+ if (this->key_set)
+ {
+ printf("key has already been set\n");
+ return FALSE;
+ }
+ this->kid = kid;
+
+ e = this->db->query(this->db, "SELECT keyid, owner FROM keys WHERE id = ?",
+ DB_UINT, kid, DB_BLOB, DB_TEXT);
+ if (e)
+ {
+ if (e->enumerate(e, &key, &owner))
+ {
+ this->owner = strdup(owner);
+ this->key = chunk_clone(key);
+ this->key_set = TRUE;
+ }
+ else
+ {
+ printf("no key found with kid %d\n", kid);
+ }
+ e->destroy(e);
+ }
+ return this->key_set;
+
+};
+
+METHOD(attest_db_t, set_product, bool,
+ private_attest_db_t *this, char *product, bool create)
+{
+ enumerator_t *e;
+
+ if (this->product_set)
+ {
+ printf("product has already been set\n");
+ return FALSE;
+ }
+ this->product = strdup(product);
+
+ e = this->db->query(this->db, "SELECT id FROM products WHERE name = ?",
+ DB_TEXT, product, DB_INT);
+ if (e)
+ {
+ if (e->enumerate(e, &this->pid))
+ {
+ this->product_set = TRUE;
+ }
+ e->destroy(e);
+ }
+ if (this->product_set)
+ {
+ return TRUE;
+ }
+
+ if (!create)
+ {
+ printf("product '%s' not found in database\n", product);
+ return FALSE;
+ }
+
+ /* Add a new database entry */
+ this->product_set = this->db->execute(this->db, &this->pid,
+ "INSERT INTO products (name) VALUES (?)",
+ DB_TEXT, product) == 1;
+
+ printf("product '%s' %sinserted into database\n", product,
+ this->product_set ? "" : "could not be ");
+
+ return this->product_set;
+}
+
+METHOD(attest_db_t, set_pid, bool,
+ private_attest_db_t *this, int pid)
+{
+ enumerator_t *e;
+ char *product;
+
+ if (this->product_set)
+ {
+ printf("product has already been set\n");
+ return FALSE;
+ }
+ this->pid = pid;
+
+ e = this->db->query(this->db, "SELECT name FROM products WHERE id = ?",
+ DB_UINT, pid, DB_TEXT);
+ if (e)
+ {
+ if (e->enumerate(e, &product))
+ {
+ this->product = strdup(product);
+ this->product_set = TRUE;
+ }
+ else
+ {
+ printf("no product found with pid %d in database\n", pid);
+ }
+ e->destroy(e);
+ }
+ return this->product_set;
+}
+
+METHOD(attest_db_t, set_package, bool,
+ private_attest_db_t *this, char *package, bool create)
+{
+ enumerator_t *e;
+
+ if (this->package_set)
+ {
+ printf("package has already been set\n");
+ return FALSE;
+ }
+ this->package = strdup(package);
+
+ e = this->db->query(this->db, "SELECT id FROM packages WHERE name = ?",
+ DB_TEXT, package, DB_INT);
+ if (e)
+ {
+ if (e->enumerate(e, &this->gid))
+ {
+ this->package_set = TRUE;
+ }
+ e->destroy(e);
+ }
+ if (this->package_set)
+ {
+ return TRUE;
+ }
+
+ if (!create)
+ {
+ printf("package '%s' not found in database\n", package);
+ return FALSE;
+ }
+
+ /* Add a new database entry */
+ this->package_set = this->db->execute(this->db, &this->gid,
+ "INSERT INTO packages (name) VALUES (?)",
+ DB_TEXT, package) == 1;
+
+ printf("package '%s' %sinserted into database\n", package,
+ this->package_set ? "" : "could not be ");
+
+ return this->package_set;
+}
+
+METHOD(attest_db_t, set_gid, bool,
+ private_attest_db_t *this, int gid)
+{
+ enumerator_t *e;
+ char *package;
+
+ if (this->package_set)
+ {
+ printf("package has already been set\n");
+ return FALSE;
+ }
+ this->gid = gid;
+
+ e = this->db->query(this->db, "SELECT name FROM packages WHERE id = ?",
+ DB_UINT, gid, DB_TEXT);
+ if (e)
+ {
+ if (e->enumerate(e, &package))
+ {
+ this->package = strdup(package);
+ this->package_set = TRUE;
+ }
+ else
+ {
+ printf("no package found with gid %d in database\n", gid);
+ }
+ e->destroy(e);
+ }
+ return this->package_set;
+}
+
+METHOD(attest_db_t, set_version, bool,
+ private_attest_db_t *this, char *version)
+{
+ if (this->version_set)
+ {
+ printf("version has already been set\n");
+ return FALSE;
+ }
+ this->version = strdup(version);
+ this->version_set = TRUE;
+
+ return TRUE;
+}
+
+
+METHOD(attest_db_t, set_algo, void,
+ private_attest_db_t *this, pts_meas_algorithms_t algo)
+{
+ this->algo = algo;
+}
+
+METHOD(attest_db_t, set_relative, void,
+ private_attest_db_t *this)
+{
+ this->relative = TRUE;
+}
+
+METHOD(attest_db_t, set_package_state, void,
+ private_attest_db_t *this, os_package_state_t package_state)
+{
+ this->package_state = package_state;
+}
+
+METHOD(attest_db_t, set_sequence, void,
+ private_attest_db_t *this, int seq_no)
+{
+ this->seq_no = seq_no;
+}
+
+METHOD(attest_db_t, set_owner, void,
+ private_attest_db_t *this, char *owner)
+{
+ free(this->owner);
+ this->owner = strdup(owner);
+}
+
+METHOD(attest_db_t, set_utc, void,
+ private_attest_db_t *this)
+{
+ this->utc = TRUE;
+}
+
+METHOD(attest_db_t, list_components, void,
+ private_attest_db_t *this)
+{
+ enumerator_t *e;
+ pts_comp_func_name_t *cfn;
+ int seq_no, cid, vid, name, qualifier, count = 0;
+
+ if (this->kid)
+ {
+ e = this->db->query(this->db,
+ "SELECT kc.seq_no, c.id, c.vendor_id, c.name, c.qualifier "
+ "FROM components AS c "
+ "JOIN key_component AS kc ON c.id = kc.component "
+ "WHERE kc.key = ? ORDER BY kc.seq_no",
+ DB_UINT, this->kid, DB_INT, DB_INT, DB_INT, DB_INT, DB_INT);
+ if (e)
+ {
+ while (e->enumerate(e, &cid, &seq_no, &vid, &name, &qualifier))
+ {
+ cfn = pts_comp_func_name_create(vid, name, qualifier);
+ printf("%4d: #%-2d %s\n", seq_no, cid, print_cfn(cfn));
+ cfn->destroy(cfn);
+ count++;
+ }
+ e->destroy(e);
+ printf("%d component%s found for key %#B\n", count,
+ (count == 1) ? "" : "s", &this->key);
+ }
+ }
+ else
+ {
+ e = this->db->query(this->db,
+ "SELECT id, vendor_id, name, qualifier FROM components "
+ "ORDER BY vendor_id, name, qualifier",
+ DB_INT, DB_INT, DB_INT, DB_INT);
+ if (e)
+ {
+ while (e->enumerate(e, &cid, &vid, &name, &qualifier))
+ {
+ cfn = pts_comp_func_name_create(vid, name, qualifier);
+ printf("%4d: %s\n", cid, print_cfn(cfn));
+ cfn->destroy(cfn);
+ count++;
+ }
+ e->destroy(e);
+ printf("%d component%s found\n", count, (count == 1) ? "" : "s");
+ }
+ }
+}
+
+METHOD(attest_db_t, list_devices, void,
+ private_attest_db_t *this)
+{
+ enumerator_t *e, *e_ar;
+ chunk_t ar_id_value = chunk_empty;
+ char *product, *device;
+ time_t timestamp;
+ int id, last_id = 0, ar_id = 0, last_ar_id = 0, device_count = 0;
+ int session_id, rec;
+ u_int32_t ar_id_type;
+ u_int tstamp;
+
+ e = this->db->query(this->db,
+ "SELECT d.id, d.value, s.id, s.time, s.identity, s.rec, p.name "
+ "FROM devices AS d "
+ "JOIN sessions AS s ON d.id = s.device "
+ "JOIN products AS p ON p.id = s.product "
+ "ORDER BY d.value, s.time DESC", DB_INT, DB_TEXT, DB_INT, DB_UINT,
+ DB_INT, DB_INT, DB_TEXT);
+
+ if (e)
+ {
+ while (e->enumerate(e, &id, &device, &session_id, &tstamp, &ar_id, &rec,
+ &product))
+ {
+ if (id != last_id)
+ {
+ printf("%4d: %s - %s\n", id, device, product);
+ device_count++;
+ last_id = id;
+ }
+ timestamp = tstamp;
+ printf("%4d: %T", session_id, &timestamp, this->utc);
+ if (ar_id)
+ {
+ if (ar_id != last_ar_id)
+ {
+ chunk_free(&ar_id_value);
+ e_ar = this->db->query(this->db,
+ "SELECT type, value FROM identities "
+ "WHERE id = ?", DB_INT, ar_id, DB_INT, DB_BLOB);
+ if (e_ar)
+ {
+ e_ar->enumerate(e_ar, &ar_id_type, &ar_id_value);
+ ar_id_value = chunk_clone(ar_id_value);
+ e_ar->destroy(e_ar);
+ }
+ }
+ if (ar_id_value.len)
+ {
+ printf(" %.*s", (int)ar_id_value.len, ar_id_value.ptr);
+ }
+ last_ar_id = ar_id;
+ }
+ printf(" - %N\n", TNC_IMV_Action_Recommendation_names, rec);
+ }
+ e->destroy(e);
+ free(ar_id_value.ptr);
+
+ printf("%d device%s found\n", device_count,
+ (device_count == 1) ? "" : "s");
+ }
+}
+
+METHOD(attest_db_t, list_keys, void,
+ private_attest_db_t *this)
+{
+ enumerator_t *e;
+ chunk_t keyid;
+ char *owner;
+ int kid, count = 0;
+
+ if (this->cid)
+ {
+ e = this->db->query(this->db,
+ "SELECT k.id, k.keyid, k.owner FROM keys AS k "
+ "JOIN key_component AS kc ON k.id = kc.key "
+ "WHERE kc.component = ? ORDER BY k.keyid",
+ DB_UINT, this->cid, DB_INT, DB_BLOB, DB_TEXT);
+ if (e)
+ {
+ while (e->enumerate(e, &kid, &keyid, &owner))
+ {
+ printf("%4d: %#B '%s'\n", kid, &keyid, owner);
+ count++;
+ }
+ e->destroy(e);
+ }
+ }
+ else
+ {
+ e = this->db->query(this->db, "SELECT id, keyid, owner FROM keys "
+ "ORDER BY keyid",
+ DB_INT, DB_BLOB, DB_TEXT);
+ if (e)
+ {
+ while (e->enumerate(e, &kid, &keyid, &owner))
+ {
+ printf("%4d: %#B '%s'\n", kid, &keyid, owner);
+ count++;
+ }
+ e->destroy(e);
+ }
+ }
+
+ printf("%d key%s found", count, (count == 1) ? "" : "s");
+ if (this->comp_set)
+ {
+ printf(" for component '%s'", print_cfn(this->cfn));
+ }
+ printf("\n");
+}
+
+METHOD(attest_db_t, list_files, void,
+ private_attest_db_t *this)
+{
+ enumerator_t *e;
+ char *dir, *file;
+ int did, last_did = 0, fid, count = 0;
+
+ if (this->did)
+ {
+ e = this->db->query(this->db,
+ "SELECT id, name FROM files WHERE dir = ? ORDER BY name",
+ DB_INT, this->did, DB_INT, DB_TEXT);
+ if (e)
+ {
+ while (e->enumerate(e, &fid, &file))
+ {
+ printf("%4d: %s\n", fid, file);
+ count++;
+ }
+ e->destroy(e);
+ }
+ printf("%d file%s found in directory '%s'\n", count,
+ (count == 1) ? "" : "s", this->dir);
+ }
+ else
+ {
+ e = this->db->query(this->db,
+ "SELECT d.id, d.path, f.id, f.name FROM files AS f "
+ "JOIN directories AS d ON f.dir = d.id "
+ "ORDER BY d.path, f.name",
+ DB_INT, DB_TEXT, DB_INT, DB_TEXT);
+ if (e)
+ {
+ while (e->enumerate(e, &did, &dir, &fid, &file))
+ {
+ if (did != last_did)
+ {
+ printf("%4d: %s\n", did, dir);
+ last_did = did;
+ }
+ printf("%4d: %s\n", fid, file);
+ count++;
+ }
+ e->destroy(e);
+ }
+ printf("%d file%s found\n", count, (count == 1) ? "" : "s");
+ }
+}
+
+METHOD(attest_db_t, list_directories, void,
+ private_attest_db_t *this)
+{
+ enumerator_t *e;
+ char *dir;
+ int did, count = 0;
+
+ if (this->file)
+ {
+ e = this->db->query(this->db,
+ "SELECT d.id, d.path FROM directories AS d "
+ "JOIN files AS f ON f.dir = d.id WHERE f.name = ? "
+ "ORDER BY path", DB_TEXT, this->file, DB_INT, DB_TEXT);
+ if (e)
+ {
+ while (e->enumerate(e, &did, &dir))
+ {
+ printf("%4d: %s\n", did, dir);
+ count++;
+ }
+ e->destroy(e);
+ }
+ printf("%d director%s found containing file '%s'\n", count,
+ (count == 1) ? "y" : "ies", this->file);
+ }
+ else
+ {
+ e = this->db->query(this->db,
+ "SELECT id, path FROM directories ORDER BY path",
+ DB_INT, DB_TEXT);
+ if (e)
+ {
+ while (e->enumerate(e, &did, &dir))
+ {
+ printf("%4d: %s\n", did, dir);
+ count++;
+ }
+ e->destroy(e);
+ }
+ printf("%d director%s found\n", count, (count == 1) ? "y" : "ies");
+ }
+}
+
+METHOD(attest_db_t, list_packages, void,
+ private_attest_db_t *this)
+{
+ enumerator_t *e;
+ char *package, *version;
+ os_package_state_t package_state;
+ int blacklist, security, gid, gid_old = 0, spaces, count = 0, t;
+ time_t timestamp;
+
+ if (this->pid)
+ {
+ e = this->db->query(this->db,
+ "SELECT p.id, p.name, "
+ "v.release, v.security, v.blacklist, v.time "
+ "FROM packages AS p JOIN versions AS v ON v.package = p.id "
+ "WHERE v.product = ? ORDER BY p.name, v.release",
+ DB_INT, this->pid,
+ DB_INT, DB_TEXT, DB_TEXT, DB_INT, DB_INT, DB_INT);
+ if (e)
+ {
+ while (e->enumerate(e, &gid, &package,
+ &version, &security, &blacklist, &t))
+ {
+ if (gid != gid_old)
+ {
+ printf("%5d: %s,", gid, package);
+ gid_old = gid;
+ }
+ else
+ {
+ spaces = 8 + strlen(package);
+ while (spaces--)
+ {
+ printf(" ");
+ }
+ }
+ timestamp = t;
+ if (blacklist)
+ {
+ package_state = OS_PACKAGE_STATE_BLACKLIST;
+ }
+ else
+ {
+ package_state = security ? OS_PACKAGE_STATE_SECURITY :
+ OS_PACKAGE_STATE_UPDATE;
+ }
+ printf(" %T (%s)%N\n", &timestamp, this->utc, version,
+ os_package_state_names, package_state);
+ count++;
+ }
+ e->destroy(e);
+ }
+ }
+ else
+ {
+ e = this->db->query(this->db, "SELECT id, name FROM packages "
+ "ORDER BY name",
+ DB_INT, DB_TEXT);
+ if (e)
+ {
+ while (e->enumerate(e, &gid, &package))
+ {
+ printf("%4d: %s\n", gid, package);
+ count++;
+ }
+ e->destroy(e);
+ }
+ }
+
+ printf("%d package%s found", count, (count == 1) ? "" : "s");
+ if (this->product_set)
+ {
+ printf(" for product '%s'", this->product);
+ }
+ printf("\n");
+}
+
+METHOD(attest_db_t, list_products, void,
+ private_attest_db_t *this)
+{
+ enumerator_t *e;
+ char *product;
+ int pid, meas, meta, count = 0;
+
+ if (this->fid)
+ {
+ e = this->db->query(this->db,
+ "SELECT p.id, p.name, pf.measurement, pf.metadata "
+ "FROM products AS p "
+ "JOIN product_file AS pf ON p.id = pf.product "
+ "WHERE pf.file = ? ORDER BY p.name",
+ DB_UINT, this->fid, DB_INT, DB_TEXT, DB_INT, DB_INT);
+ if (e)
+ {
+ while (e->enumerate(e, &pid, &product, &meas, &meta))
+ {
+ printf("%4d: |%s%s| %s\n", pid, meas ? "M":" ", meta ? "T":" ",
+ product);
+ count++;
+ }
+ e->destroy(e);
+ }
+ }
+ else
+ {
+ e = this->db->query(this->db, "SELECT id, name FROM products "
+ "ORDER BY name",
+ DB_INT, DB_TEXT);
+ if (e)
+ {
+ while (e->enumerate(e, &pid, &product))
+ {
+ printf("%4d: %s\n", pid, product);
+ count++;
+ }
+ e->destroy(e);
+ }
+ }
+
+ printf("%d product%s found", count, (count == 1) ? "" : "s");
+ if (this->fid)
+ {
+ printf(" for file '%s'", this->file);
+ }
+ printf("\n");
+}
+
+METHOD(attest_db_t, list_hashes, void,
+ private_attest_db_t *this)
+{
+ enumerator_t *e;
+ chunk_t hash;
+ char *file, *dir, *product;
+ int id, fid, fid_old = 0, did, did_old = 0, pid, pid_old = 0, count = 0;
+
+ if (this->pid && this->fid && this->did)
+ {
+ printf("%4d: %s\n", this->did, this->dir);
+ printf("%4d: %s\n", this->fid, this->file);
+ e = this->db->query(this->db,
+ "SELECT id, hash FROM file_hashes "
+ "WHERE algo = ? AND file = ? AND product = ?",
+ DB_INT, this->algo, DB_INT, this->fid, DB_INT, this->pid,
+ DB_INT, DB_BLOB);
+ if (e)
+ {
+ while (e->enumerate(e, &id, &hash))
+ {
+ printf("%4d: %#B\n", id, &hash);
+ count++;
+ }
+ e->destroy(e);
+
+ printf("%d %N value%s found for product '%s'\n", count,
+ pts_meas_algorithm_names, this->algo,
+ (count == 1) ? "" : "s", this->product);
+ }
+ }
+ else if (this->pid && this->file)
+ {
+ e = this->db->query(this->db,
+ "SELECT h.id, h.hash, f.id, d.id, d.path "
+ "FROM file_hashes AS h "
+ "JOIN files AS f ON h.file = f.id "
+ "JOIN directories AS d ON f.dir = d.id "
+ "WHERE h.algo = ? AND h.product = ? AND f.name = ? "
+ "ORDER BY d.path, f.name, h.hash",
+ DB_INT, this->algo, DB_INT, this->pid, DB_TEXT, this->file,
+ DB_INT, DB_BLOB, DB_INT, DB_INT, DB_TEXT);
+ if (e)
+ {
+ while (e->enumerate(e, &id, &hash, &fid, &did, &dir))
+ {
+ if (did != did_old)
+ {
+ printf("%4d: %s\n", did, dir);
+ did_old = did;
+ }
+ if (fid != fid_old)
+ {
+ printf("%4d: %s\n", fid, this->file);
+ fid_old = fid;
+ }
+ printf("%4d: %#B\n", id, &hash);
+ count++;
+ }
+ e->destroy(e);
+
+ printf("%d %N value%s found for product '%s'\n", count,
+ pts_meas_algorithm_names, this->algo,
+ (count == 1) ? "" : "s", this->product);
+ }
+ }
+ else if (this->pid && this->did)
+ {
+ printf("%4d: %s\n", this->did, this->dir);
+ e = this->db->query(this->db,
+ "SELECT h.id, h.hash, f.id, f.name "
+ "FROM file_hashes AS h "
+ "JOIN files AS f ON h.file = f.id "
+ "WHERE h.algo = ? AND h.product = ? AND f.dir = ? "
+ "ORDER BY f.name, h.hash",
+ DB_INT, this->algo, DB_INT, this->pid, DB_INT, this->did,
+ DB_INT, DB_BLOB, DB_INT, DB_TEXT);
+ if (e)
+ {
+ while (e->enumerate(e, &id, &hash, &fid, &file))
+ {
+ if (fid != fid_old)
+ {
+ printf("%4d: %s\n", fid, file);
+ fid_old = fid;
+ }
+ printf("%4d: %#B\n", id, &hash);
+ count++;
+ }
+ e->destroy(e);
+
+ printf("%d %N value%s found for product '%s'\n", count,
+ pts_meas_algorithm_names, this->algo,
+ (count == 1) ? "" : "s", this->product);
+ }
+ }
+ else if (this->pid)
+ {
+ e = this->db->query(this->db,
+ "SELECT h.id, h.hash, f.id, f.name, d.id, d.path "
+ "FROM file_hashes AS h "
+ "JOIN files AS f ON h.file = f.id "
+ "JOIN directories AS d ON f.dir = d.id "
+ "WHERE h.algo = ? AND h.product = ? "
+ "ORDER BY d.path, f.name, h.hash",
+ DB_INT, this->algo, DB_INT, this->pid,
+ DB_INT, DB_BLOB, DB_INT, DB_TEXT, DB_INT, DB_TEXT);
+ if (e)
+ {
+ while (e->enumerate(e, &id, &hash, &fid, &file, &did, &dir))
+ {
+ if (did != did_old)
+ {
+ printf("%4d: %s\n", did, dir);
+ did_old = did;
+ }
+ if (fid != fid_old)
+ {
+ printf("%4d: %s\n", fid, file);
+ fid_old = fid;
+ }
+ printf("%4d: %#B\n", id, &hash);
+ count++;
+ }
+ e->destroy(e);
+
+ printf("%d %N value%s found for product '%s'\n", count,
+ pts_meas_algorithm_names, this->algo,
+ (count == 1) ? "" : "s", this->product);
+ }
+ }
+ else if (this->fid && this->did)
+ {
+ e = this->db->query(this->db,
+ "SELECT h.id, h.hash, p.id, p.name FROM file_hashes AS h "
+ "JOIN products AS p ON h.product = p.id "
+ "WHERE h.algo = ? AND h.file = ? "
+ "ORDER BY p.name, h.hash",
+ DB_INT, this->algo, DB_INT, this->fid,
+ DB_INT, DB_BLOB, DB_INT, DB_TEXT);
+ if (e)
+ {
+ while (e->enumerate(e, &id, &hash, &pid, &product))
+ {
+ if (pid != pid_old)
+ {
+ printf("%4d: %s\n", pid, product);
+ pid_old = pid;
+ }
+ printf("%4d: %#B\n", id, &hash);
+ count++;
+ }
+ e->destroy(e);
+
+ printf("%d %N value%s found for file '%s%s%s'\n", count,
+ pts_meas_algorithm_names, this->algo,
+ (count == 1) ? "" : "s", this->dir,
+ get_separator(this->dir), this->file);
+ }
+ }
+ else if (this->file)
+ {
+ e = this->db->query(this->db,
+ "SELECT h.id, h.hash, f.id, d.id, d.path, p.id, p.name "
+ "FROM file_hashes AS h "
+ "JOIN files AS f ON h.file = f.id "
+ "JOIN directories AS d ON f.dir = d.id "
+ "JOIN products AS p ON h.product = p.id "
+ "WHERE h.algo = ? AND f.name = ? "
+ "ORDER BY d.path, f.name, p.name, h.hash",
+ DB_INT, this->algo, DB_TEXT, this->file,
+ DB_INT, DB_BLOB, DB_INT, DB_INT, DB_TEXT, DB_INT, DB_TEXT);
+ if (e)
+ {
+ while (e->enumerate(e, &id, &hash, &fid, &did, &dir, &pid, &product))
+ {
+ if (did != did_old)
+ {
+ printf("%4d: %s\n", did, dir);
+ did_old = did;
+ }
+ if (fid != fid_old)
+ {
+ printf("%4d: %s\n", fid, this->file);
+ fid_old = fid;
+ pid_old = 0;
+ }
+ if (pid != pid_old)
+ {
+ printf("%4d: %s\n", pid, product);
+ pid_old = pid;
+ }
+ printf("%4d: %#B\n", id, &hash);
+ count++;
+ }
+ e->destroy(e);
+
+ printf("%d %N value%s found\n", count, pts_meas_algorithm_names,
+ this->algo, (count == 1) ? "" : "s");
+ }
+
+ }
+ else if (this->did)
+ {
+ e = this->db->query(this->db,
+ "SELECT h.id, h.hash, f.id, f.name, p.id, p.name "
+ "FROM file_hashes AS h "
+ "JOIN files AS f ON h.file = f.id "
+ "JOIN products AS p ON h.product = p.id "
+ "WHERE h.algo = ? AND f.dir = ? "
+ "ORDER BY f.name, p.name, h.hash",
+ DB_INT, this->algo, DB_INT, this->did,
+ DB_INT, DB_BLOB, DB_INT, DB_TEXT, DB_INT, DB_TEXT);
+ if (e)
+ {
+ while (e->enumerate(e, &id, &hash, &fid, &file, &pid, &product))
+ {
+ if (fid != fid_old)
+ {
+ printf("%4d: %s\n", fid, file);
+ fid_old = fid;
+ pid_old = 0;
+ }
+ if (pid != pid_old)
+ {
+ printf("%4d: %s\n", pid, product);
+ pid_old = pid;
+ }
+ printf("%4d: %#B\n", id, &hash);
+ count++;
+ }
+ e->destroy(e);
+
+ printf("%d %N value%s found for directory '%s'\n", count,
+ pts_meas_algorithm_names, this->algo,
+ (count == 1) ? "" : "s", this->dir);
+ }
+ }
+ else
+ {
+ e = this->db->query(this->db,
+ "SELECT h.id, h.hash, f.id, f.name, d.id, d.path, p.id, p.name "
+ "FROM file_hashes AS h "
+ "JOIN files AS f ON h.file = f.id "
+ "JOIN directories AS d ON f.dir = d.id "
+ "JOIN products AS p on h.product = p.id "
+ "WHERE h.algo = ? "
+ "ORDER BY d.path, f.name, p.name, h.hash",
+ DB_INT, this->algo, DB_INT, DB_BLOB, DB_INT, DB_TEXT,
+ DB_INT, DB_TEXT, DB_INT, DB_TEXT);
+ if (e)
+ {
+ while (e->enumerate(e, &id, &hash, &fid, &file, &did, &dir, &pid,
+ &product))
+ {
+ if (did != did_old)
+ {
+ printf("%4d: %s\n", did, dir);
+ did_old = did;
+ }
+ if (fid != fid_old)
+ {
+ printf("%4d: %s\n", fid, file);
+ fid_old = fid;
+ pid_old = 0;
+ }
+ if (pid != pid_old)
+ {
+ printf("%4d: %s\n", pid, product);
+ pid_old = pid;
+ }
+ printf("%4d: %#B\n", id, &hash);
+ count++;
+ }
+ e->destroy(e);
+
+ printf("%d %N value%s found\n", count, pts_meas_algorithm_names,
+ this->algo, (count == 1) ? "" : "s");
+ }
+ }
+}
+
+METHOD(attest_db_t, list_measurements, void,
+ private_attest_db_t *this)
+{
+ enumerator_t *e;
+ chunk_t hash, keyid;
+ pts_comp_func_name_t *cfn;
+ char *owner;
+ int seq_no, pcr, vid, name, qualifier;
+ int cid, cid_old = 0, kid, kid_old = 0, count = 0;
+
+ if (this->kid && this->cid)
+ {
+ e = this->db->query(this->db,
+ "SELECT ch.seq_no, ch.pcr, ch.hash, k.owner "
+ "FROM component_hashes AS ch "
+ "JOIN keys AS k ON k.id = ch.key "
+ "WHERE ch.algo = ? AND ch.key = ? AND ch.component = ? "
+ "ORDER BY seq_no",
+ DB_INT, this->algo, DB_UINT, this->kid, DB_UINT, this->cid,
+ DB_INT, DB_INT, DB_BLOB, DB_TEXT);
+ if (e)
+ {
+ while (e->enumerate(e, &seq_no, &pcr, &hash, &owner))
+ {
+ if (this->kid != kid_old)
+ {
+ printf("%4d: %#B '%s'\n", this->kid, &this->key, owner);
+ kid_old = this->kid;
+ }
+ printf("%7d %02d %#B\n", seq_no, pcr, &hash);
+ count++;
+ }
+ e->destroy(e);
+
+ printf("%d %N value%s found for component '%s'\n", count,
+ pts_meas_algorithm_names, this->algo,
+ (count == 1) ? "" : "s", print_cfn(this->cfn));
+ }
+ }
+ else if (this->cid)
+ {
+ e = this->db->query(this->db,
+ "SELECT ch.seq_no, ch.pcr, ch.hash, k.id, k.keyid, k.owner "
+ "FROM component_hashes AS ch "
+ "JOIN keys AS k ON k.id = ch.key "
+ "WHERE ch.algo = ? AND ch.component = ? "
+ "ORDER BY keyid, seq_no",
+ DB_INT, this->algo, DB_UINT, this->cid,
+ DB_INT, DB_INT, DB_BLOB, DB_INT, DB_BLOB, DB_TEXT);
+ if (e)
+ {
+ while (e->enumerate(e, &seq_no, &pcr, &hash, &kid, &keyid, &owner))
+ {
+ if (kid != kid_old)
+ {
+ printf("%4d: %#B '%s'\n", kid, &keyid, owner);
+ kid_old = kid;
+ }
+ printf("%7d %02d %#B\n", seq_no, pcr, &hash);
+ count++;
+ }
+ e->destroy(e);
+
+ printf("%d %N value%s found for component '%s'\n", count,
+ pts_meas_algorithm_names, this->algo,
+ (count == 1) ? "" : "s", print_cfn(this->cfn));
+ }
+
+ }
+ else if (this->kid)
+ {
+ e = this->db->query(this->db,
+ "SELECT ch.seq_no, ch.pcr, ch.hash, "
+ "c.id, c.vendor_id, c.name, c.qualifier "
+ "FROM component_hashes AS ch "
+ "JOIN components AS c ON c.id = ch.component "
+ "WHERE ch.algo = ? AND ch.key = ? "
+ "ORDER BY vendor_id, name, qualifier, seq_no",
+ DB_INT, this->algo, DB_UINT, this->kid, DB_INT, DB_INT, DB_BLOB,
+ DB_INT, DB_INT, DB_INT, DB_INT);
+ if (e)
+ {
+ while (e->enumerate(e, &seq_no, &pcr, &hash, &cid, &vid, &name,
+ &qualifier))
+ {
+ if (cid != cid_old)
+ {
+ cfn = pts_comp_func_name_create(vid, name, qualifier);
+ printf("%4d: %s\n", cid, print_cfn(cfn));
+ cfn->destroy(cfn);
+ cid_old = cid;
+ }
+ printf("%5d %02d %#B\n", seq_no, pcr, &hash);
+ count++;
+ }
+ e->destroy(e);
+
+ printf("%d %N value%s found for key %#B '%s'\n", count,
+ pts_meas_algorithm_names, this->algo,
+ (count == 1) ? "" : "s", &this->key, this->owner);
+ }
+ }
+}
+
+METHOD(attest_db_t, list_sessions, void,
+ private_attest_db_t *this)
+{
+ enumerator_t *e;
+ chunk_t identity;
+ char *product, *device;
+ int session_id, conn_id, rec, device_len;
+ time_t created;
+ u_int t;
+
+ e = this->db->query(this->db,
+ "SELECT s.id, s.time, s.connection, s.rec, p.name, d.value, i.value "
+ "FROM sessions AS s "
+ "LEFT JOIN products AS p ON s.product = p.id "
+ "LEFT JOIN devices AS d ON s.device = d.id "
+ "LEFT JOIN identities AS i ON s.identity = i.id "
+ "ORDER BY s.time DESC",
+ DB_INT, DB_UINT, DB_INT, DB_INT, DB_TEXT, DB_TEXT, DB_BLOB);
+ if (e)
+ {
+ while (e->enumerate(e, &session_id, &t, &conn_id, &rec, &product,
+ &device, &identity))
+ {
+ created = t;
+ product = product ? product : "-";
+ device = strlen(device) ? device : "-";
+ device_len = min(strlen(device), DEVICE_MAX_LEN);
+ identity = identity.len ? identity : chunk_from_str("-");
+ printf("%4d: %T %2d %-20s %.*s%*s%.*s - %N\n", session_id, &created,
+ this->utc, conn_id, product, device_len, device,
+ DEVICE_MAX_LEN - device_len + 1, " ", (int)identity.len,
+ identity.ptr, TNC_IMV_Action_Recommendation_names, rec);
+ }
+ e->destroy(e);
+ }
+}
+
+/**
+ * Insert a file hash into the database
+ */
+static bool insert_file_hash(private_attest_db_t *this,
+ pts_meas_algorithms_t algo,
+ 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";
+
+ e = this->db->query(this->db,
+ "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;
+ }
+
+ while (e->enumerate(e, &hash))
+ {
+ update = TRUE;
+
+ if (chunk_equals(measurement, hash))
+ {
+ label = "exists and equals";
+ insert = FALSE;
+ break;
+ }
+ }
+ 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)
+ {
+ printf("file_hash insertion failed\n");
+ return FALSE;
+ }
+ if (update)
+ {
+ label = "updated";
+ (*hashes_updated)++;
+ }
+ else
+ {
+ label = "created";
+ (*hashes_added)++;
+ }
+ }
+ printf(" %#B - %s\n", &measurement, label);
+ return TRUE;
+}
+
+/**
+ * Add hash measurement for a single file or all files in a directory
+ */
+static bool add_hash(private_attest_db_t *this)
+{
+ char *pathname, *filename, *label;
+ const char *sep;
+ pts_file_meas_t *measurements;
+ chunk_t measurement;
+ hasher_t *hasher = NULL;
+ int fid, files_added = 0, hashes_added = 0, hashes_updated = 0;
+ enumerator_t *enumerator, *e;
+
+ if (!this->meas_dir)
+ {
+ this->meas_dir = strdup(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->meas_dir, sep, this->file) == -1)
+ {
+ return FALSE;
+ }
+ measurements = pts_file_meas_create_from_path(0, pathname, FALSE,
+ TRUE, this->algo);
+ free(pathname);
+ }
+ else
+ {
+ measurements = pts_file_meas_create_from_path(0, this->meas_dir, TRUE,
+ TRUE, this->algo);
+ }
+ if (!measurements)
+ {
+ printf("file measurement failed\n");
+ DESTROY_IF(hasher);
+ return FALSE;
+ }
+
+ enumerator = measurements->create_enumerator(measurements);
+ while (enumerator->enumerate(enumerator, &filename, &measurement))
+ {
+ if (this->fid)
+ {
+ /* a single file already exists */
+ filename = this->file;
+ fid = this->fid;
+ label = "exists";
+ }
+ else
+ {
+ /* retrieve or create filename */
+ label = "could not be created";
+
+ e = this->db->query(this->db,
+ "SELECT id FROM files WHERE name = ? AND dir = ?",
+ DB_TEXT, filename, DB_INT, this->did, DB_INT);
+ if (!e)
+ {
+ printf("files query failed\n");
+ break;
+ }
+ if (e->enumerate(e, &fid))
+ {
+ label = "exists";
+ }
+ else
+ {
+ if (this->db->execute(this->db, &fid,
+ "INSERT INTO files (name, dir) VALUES (?, ?)",
+ DB_TEXT, filename, DB_INT, this->did) == 1)
+ {
+ label = "created";
+ files_added++;
+ }
+ }
+ e->destroy(e);
+ }
+ printf("%4d: %s - %s\n", fid, filename, label);
+
+ /* compute file measurement hash */
+ if (!insert_file_hash(this, this->algo, measurement, fid,
+ &hashes_added, &hashes_updated))
+ {
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ 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;
+}
+
+METHOD(attest_db_t, add, bool,
+ private_attest_db_t *this)
+{
+ bool success = FALSE;
+
+ /* add directory or file hash measurement for a given product */
+ if (this->did && this->pid)
+ {
+ return add_hash(this);
+ }
+
+ /* insert package version */
+ if (this->version_set && this->gid && this->pid)
+ {
+ time_t t = time(NULL);
+ int security, blacklist;
+
+ security = this->package_state == OS_PACKAGE_STATE_SECURITY;
+ blacklist = this->package_state == OS_PACKAGE_STATE_BLACKLIST;
+
+ success = this->db->execute(this->db, NULL,
+ "INSERT INTO versions "
+ "(package, product, release, security, blacklist, time) "
+ "VALUES (?, ?, ?, ?, ?, ?)",
+ DB_UINT, this->gid, DB_INT, this->pid, DB_TEXT,
+ this->version, DB_INT, security, DB_INT, blacklist,
+ DB_INT, t) == 1;
+
+ printf("'%s' package %s (%s)%N %sinserted into database\n",
+ this->product, this->package, this->version,
+ os_package_state_names, this->package_state,
+ success ? "" : "could not be ");
+ }
+ return success;
+}
+
+METHOD(attest_db_t, delete, bool,
+ private_attest_db_t *this)
+{
+ bool success;
+ int id, count = 0;
+ char *name;
+ enumerator_t *e;
+
+ /* delete a file measurement hash for a given product */
+ if (this->algo && this->pid && this->fid)
+ {
+ success = this->db->execute(this->db, NULL,
+ "DELETE FROM file_hashes "
+ "WHERE algo = ? AND product = ? AND file = ?",
+ DB_UINT, this->algo, DB_UINT, this->pid,
+ DB_UINT, this->fid) > 0;
+
+ 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 ");
+
+ return success;
+ }
+
+ /* delete product/file entries */
+ if (this->pid && (this->fid || this->did))
+ {
+ success = this->db->execute(this->db, NULL,
+ "DELETE FROM product_file "
+ "WHERE product = ? AND file = ?",
+ DB_UINT, this->pid,
+ DB_UINT, this->fid ? this->fid : this->did) > 0;
+
+ printf("product/file pair (%d/%d) %sdeleted from database\n",
+ this->pid, this->fid ? this->fid : this->did,
+ success ? "" : "could not be ");
+
+ return success;
+ }
+
+ if (this->cid)
+ {
+ success = this->db->execute(this->db, NULL,
+ "DELETE FROM components WHERE id = ?",
+ DB_UINT, this->cid) > 0;
+
+ printf("component '%s' %sdeleted from database\n", print_cfn(this->cfn),
+ success ? "" : "could not be ");
+ return success;
+ }
+
+ if (this->fid)
+ {
+ success = this->db->execute(this->db, NULL,
+ "DELETE FROM files WHERE id = ?",
+ DB_UINT, this->fid) > 0;
+
+ printf("file '%s%s%s' %sdeleted from database\n", this->dir,
+ get_separator(this->dir), this->file,
+ success ? "" : "could not be ");
+ return success;
+ }
+
+ if (this->did)
+ {
+ e = this->db->query(this->db,
+ "SELECT id, name FROM files WHERE dir = ? ORDER BY name",
+ DB_INT, this->did, DB_INT, DB_TEXT);
+ if (e)
+ {
+ while (e->enumerate(e, &id, &name))
+ {
+ printf("%4d: %s\n", id, name);
+ count++;
+ }
+ e->destroy(e);
+
+ if (count)
+ {
+ printf("%d dependent file%s found, "
+ "directory '%s' could not deleted\n",
+ count, (count == 1) ? "" : "s", this->dir);
+ return FALSE;
+ }
+ }
+ success = this->db->execute(this->db, NULL,
+ "DELETE FROM directories WHERE id = ?",
+ DB_UINT, this->did) > 0;
+ printf("directory '%s' %sdeleted from database\n", this->dir,
+ success ? "" : "could not be ");
+ return success;
+ }
+
+ if (this->kid)
+ {
+ success = this->db->execute(this->db, NULL,
+ "DELETE FROM keys WHERE id = ?",
+ DB_UINT, this->kid) > 0;
+
+ printf("key %#B %sdeleted from database\n", &this->key,
+ success ? "" : "could not be ");
+ return success;
+ }
+ if (this->pid)
+ {
+ success = this->db->execute(this->db, NULL,
+ "DELETE FROM products WHERE id = ?",
+ DB_UINT, this->pid) > 0;
+
+ printf("product '%s' %sdeleted from database\n", this->product,
+ success ? "" : "could not be ");
+ return success;
+ }
+
+ printf("empty delete command\n");
+ return FALSE;
+}
+
+METHOD(attest_db_t, destroy, void,
+ private_attest_db_t *this)
+{
+ DESTROY_IF(this->db);
+ DESTROY_IF(this->cfn);
+ free(this->package);
+ free(this->product);
+ free(this->version);
+ free(this->file);
+ free(this->dir);
+ free(this->meas_dir);
+ free(this->owner);
+ free(this->key.ptr);
+ free(this);
+}
+
+/**
+ * Described in header.
+ */
+attest_db_t *attest_db_create(char *uri)
+{
+ private_attest_db_t *this;
+
+ INIT(this,
+ .public = {
+ .set_component = _set_component,
+ .set_cid = _set_cid,
+ .set_directory = _set_directory,
+ .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,
+ .set_gid = _set_gid,
+ .set_product = _set_product,
+ .set_pid = _set_pid,
+ .set_version = _set_version,
+ .set_algo = _set_algo,
+ .set_relative = _set_relative,
+ .set_package_state = _set_package_state,
+ .set_sequence = _set_sequence,
+ .set_owner = _set_owner,
+ .set_utc = _set_utc,
+ .list_packages = _list_packages,
+ .list_products = _list_products,
+ .list_files = _list_files,
+ .list_directories = _list_directories,
+ .list_components = _list_components,
+ .list_devices = _list_devices,
+ .list_keys = _list_keys,
+ .list_hashes = _list_hashes,
+ .list_measurements = _list_measurements,
+ .list_sessions = _list_sessions,
+ .add = _add,
+ .delete = _delete,
+ .destroy = _destroy,
+ },
+ .db = lib->db->create(lib->db, uri),
+ );
+
+ if (!this->db)
+ {
+ fprintf(stderr, "opening database failed.\n");
+ destroy(this);
+ return NULL;
+ }
+
+ return &this->public;
+}
diff --git a/src/libimcv/plugins/imv_attestation/attest_db.h b/src/libimcv/plugins/imv_attestation/attest_db.h
new file mode 100644
index 000000000..ab3d046b3
--- /dev/null
+++ b/src/libimcv/plugins/imv_attestation/attest_db.h
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2011-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup attest_db_t attest_db
+ * @{ @ingroup libimcv
+ */
+
+#ifndef ATTEST_DB_H_
+#define ATTEST_DB_H_
+
+#include <pts/pts_meas_algo.h>
+#include <os_info/os_info.h>
+#include <library.h>
+
+typedef struct attest_db_t attest_db_t;
+
+/**
+ * Attestation database object
+ */
+struct attest_db_t {
+
+ /**
+ * Set functional component to be queried
+ *
+ * @param comp functional component
+ * @param create if TRUE create database entry if it doesn't exist
+ * @return TRUE if successful
+ */
+ bool (*set_component)(attest_db_t *this, char *comp, bool create);
+
+ /**
+ * Set primary key of the functional component to be queried
+ *
+ * @param fid primary key of functional component
+ * @return TRUE if successful
+ */
+ bool (*set_cid)(attest_db_t *this, int fid);
+
+ /**
+ * Set directory to be queried
+ *
+ * @param dir directory
+ * @param create if TRUE create database entry if it doesn't exist
+ * @return TRUE if successful
+ */
+ bool (*set_directory)(attest_db_t *this, char *dir, bool create);
+
+ /**
+ * Set primary key of the directory to be queried
+ *
+ * @param did primary key of directory
+ * @return TRUE if successful
+ */
+ bool (*set_did)(attest_db_t *this, int did);
+
+ /**
+ * Set measurement file to be queried
+ *
+ * @param file measurement file
+ * @param create if TRUE create database entry if it doesn't exist
+ * @return TRUE if successful
+ */
+ bool (*set_file)(attest_db_t *this, char *file, bool create);
+
+ /**
+ * Set primary key of the measurement file to be queried
+ *
+ * @param fid primary key of measurement file
+ * @return TRUE if successful
+ */
+ bool (*set_fid)(attest_db_t *this, int fid);
+
+ /**
+ * Set path to directory where file[s] are to be measured
+ *
+ * @param meas_dir measurement directory
+ * @return TRUE if successful
+ */
+ bool (*set_meas_directory)(attest_db_t *this, char *dir);
+
+ /**
+ * Set functional component to be queried
+ *
+ * @param key AIK
+ * @param create if TRUE create database entry if it doesn't exist
+ * @return TRUE if successful
+ */
+ bool (*set_key)(attest_db_t *this, chunk_t key, bool create);
+
+ /**
+ * Set primary key of the AIK to be queried
+ *
+ * @param kid primary key of AIK
+ * @return TRUE if successful
+ */
+ bool (*set_kid)(attest_db_t *this, int kid);
+
+ /**
+ * Set software package to be queried
+ *
+ * @param product software package
+ * @param create if TRUE create database entry if it doesn't exist
+ * @return TRUE if successful
+ */
+ bool (*set_package)(attest_db_t *this, char *package, bool create);
+
+ /**
+ * Set primary key of the software package to be queried
+ *
+ * @param gid primary key of software package
+ * @return TRUE if successful
+ */
+ bool (*set_gid)(attest_db_t *this, int gid);
+
+ /**
+ * Set software product to be queried
+ *
+ * @param product software product
+ * @param create if TRUE create database entry if it doesn't exist
+ * @return TRUE if successful
+ */
+ bool (*set_product)(attest_db_t *this, char *product, bool create);
+
+ /**
+ * Set primary key of the software product to be queried
+ *
+ * @param pid primary key of software product
+ * @return TRUE if successful
+ */
+ bool (*set_pid)(attest_db_t *this, int pid);
+
+ /**
+ * Set software package version to be queried
+ *
+ * @param version software package version
+ * @return TRUE if successful
+ */
+ bool (*set_version)(attest_db_t *this, char *version);
+
+ /**
+ * Set measurement hash algorithm
+ *
+ * @param algo hash algorithm
+ */
+ void (*set_algo)(attest_db_t *this, pts_meas_algorithms_t algo);
+
+ /**
+ * Set that the IMA-specific SHA-1 template hash be computed
+ */
+ void (*set_ima)(attest_db_t *this);
+
+ /**
+ * Set that relative filenames are to be used
+ */
+ void (*set_relative)(attest_db_t *this);
+
+ /**
+ * Set the package security or blacklist state
+ */
+ void (*set_package_state)(attest_db_t *this, os_package_state_t package_state);
+
+ /**
+ * Set the sequence number
+ */
+ void (*set_sequence)(attest_db_t *this, int seq_no);
+
+ /**
+ * Set owner [user/host] of an AIK
+ *
+ * @param owner user/host name
+ * @return TRUE if successful
+ */
+ void (*set_owner)(attest_db_t *this, char *owner);
+
+ /**
+ * Display all dates in UTC
+ */
+ void (*set_utc)(attest_db_t *this);
+
+ /**
+ * List all packages stored in the database
+ */
+ void (*list_packages)(attest_db_t *this);
+
+ /**
+ * List all products stored in the database
+ */
+ void (*list_products)(attest_db_t *this);
+
+ /**
+ * List all directories stored in the database
+ */
+ void (*list_directories)(attest_db_t *this);
+
+ /**
+ * List selected files stored in the database
+ */
+ void (*list_files)(attest_db_t *this);
+
+ /**
+ * List all components stored in the database
+ */
+ void (*list_components)(attest_db_t *this);
+
+ /**
+ * List all devices stored in the database
+ */
+ void (*list_devices)(attest_db_t *this);
+
+ /**
+ * List all AIKs stored in the database
+ */
+ void (*list_keys)(attest_db_t *this);
+
+ /**
+ * List selected measurement hashes stored in the database
+ */
+ void (*list_hashes)(attest_db_t *this);
+
+ /**
+ * List selected component measurement stored in the database
+ */
+ void (*list_measurements)(attest_db_t *this);
+
+ /**
+ * List sessions stored in the database
+ */
+ void (*list_sessions)(attest_db_t *this);
+
+ /**
+ * Add an entry to the database
+ */
+ bool (*add)(attest_db_t *this);
+
+ /**
+ * Delete an entry from the database
+ */
+ bool (*delete)(attest_db_t *this);
+
+ /**
+ * Destroy attest_db_t object
+ */
+ void (*destroy)(attest_db_t *this);
+
+};
+
+/**
+ * Create an attest_db_t instance
+ *
+ * @param uri database URI
+ */
+attest_db_t* attest_db_create(char *uri);
+
+#endif /** ATTEST_DB_H_ @}*/
diff --git a/src/libimcv/plugins/imv_attestation/attest_usage.c b/src/libimcv/plugins/imv_attestation/attest_usage.c
new file mode 100644
index 000000000..8f4afdbad
--- /dev/null
+++ b/src/libimcv/plugins/imv_attestation/attest_usage.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2011-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <stdio.h>
+
+#include "attest_usage.h"
+
+/**
+ * print attest usage info
+ */
+void usage(void)
+{
+ printf("\
+Usage:\n\
+ ipsec attest --components|--devices|--sessions|--files|--hashes|--keys [options]\n\
+ \n\
+ ipsec attest --measurements|--packages|--products|--add|--del [options]\n\
+ \n\
+ ipsec attest --components [--key <digest>|--kid <id>]\n\
+ Show a list of components with an AIK digest or\n\
+ its primary key as an optional selector.\n\
+ \n\
+ ipsec attest --devices [--utc]\n\
+ Show a list of registered devices and associated collected information\n\
+ \n\
+ ipsec attest --sessions [--utc]\n\
+ Show a chronologically sorted list of all TNC sessions\n\
+ \n\
+ ipsec attest --files [--product <name>|--pid <id>]\n\
+ Show a list of files with a software product name or\n\
+ its primary key as an optional selector.\n\
+ \n\
+ ipsec attest --hashes [--sha1|--sha256|--sha384] [--product <name>|--pid <id>]\n\
+ Show a list of measurement hashes for a given software product or\n\
+ its primary key as an optional selector.\n\
+ \n\
+ ipsec attest --hashes [--sha1|--sha1-ima|--sha256|--sha384] [--file <path>|--fid <id>]\n\
+ Show a list of measurement hashes for a given file or\n\
+ its primary key as an optional selector.\n\
+ \n\
+ ipsec attest --keys [--components <cfn>|--cid <id>]\n\
+ Show a list of AIK key digests with a component or\n\
+ its primary key as an optional selector.\n\
+ \n\
+ ipsec attest --measurements --sha1|--sha256|--sha384 [--component <cfn>|--cid <id>]\n\
+ Show a list of component measurements for a given component or\n\
+ its primary key as an optional selector.\n\
+ \n\
+ ipsec attest --measurements --sha1|--sha256|--sha384 [--key <digest>|--kid <id>|--aik <path>]\n\
+ Show a list of component measurements for a given AIK or\n\
+ its primary key as an optional selector.\n\
+ \n\
+ ipsec attest --packages [--product <name>|--pid <id>] [--utc]\n\
+ Show a list of software packages for a given product or\n\
+ its primary key as an optional selector.\n\
+ \n\
+ ipsec attest --products [--file <path>|--fid <id>]\n\
+ Show a list of supported software products with a file path or\n\
+ its primary key as an optional selector.\n\
+ \n\
+ ipsec attest --add --file <path>|--dir <path>|--product <name>|--component <cfn>\n\
+ Add a file, directory, product or component entry\n\
+ Component <cfn> entries must be of the form <vendor_id>/<name>-<qualifier>\n\
+ \n\
+ ipsec attest --add [--owner <name>] --key <digest>|--aik <path>\n\
+ Add an AIK public key digest entry preceded by an optional owner name\n\
+ \n\
+ ipsec attest --add --product <name>|--pid <id> --sha1|--sha1-ima|--sha256|--sha384\n\
+ [--relative|--rel] --dir <path>|--file <path>\n\
+ Add hashes of a single file or all files in a directory under absolute or relative filenames\n\
+ \n\
+ ipsec attest --add --key <digest|--kid <id> --component <cfn>|--cid <id> --sequence <no>|--seq <no>\n\
+ Add an ordered key/component entry\n\
+ \n\
+ ipsec attest --add --package <name> --version <string> [--security|--blacklist]\n\
+ [--product <name>|--pid <id>]\n\
+ Add a package version for a given product optionally with security or blacklist flag\n\
+ \n\
+ ipsec attest --del --file <path>|--fid <id>|--dir <path>|--did <id>\n\
+ Delete a file or directory entry referenced either by value or primary key\n\
+ \n\
+ ipsec attest --del --product <name>|--pid <id>|--component <cfn>|--cid <id>\n\
+ Delete a product or component entry referenced either by value or primary key\n\
+ \n\
+ ipsec attest --del --product <name>|--pid <id> --file <path>|--fid <id>|--dir <path>|--did <id>\n\
+ Delete a product/file entry referenced either by value or primary key\n\
+ \n\
+ ipsec attest --del --key <digest>|--kid <id>|--aik <path>\n\
+ Delete an AIK entry referenced either by value or primary key\n\
+ \n\
+ ipsec attest --del --key <digest|--kid <id> --component <cfn>|--cid <id>\n\
+ Delete a key/component entry\n\
+ \n\
+ ipsec attest --del --product <name>|--pid <id> --sha1|--sha1-ima|--sha256|--sha384\n\
+ [--dir <path>|--did <id>] --file <path>|--fid <id>\n\
+ Delete a file hash given an absolute or relative filename\n\
+ \n");
+}
+
diff --git a/src/libimcv/plugins/imv_attestation/attest_usage.h b/src/libimcv/plugins/imv_attestation/attest_usage.h
new file mode 100644
index 000000000..bce801e9d
--- /dev/null
+++ b/src/libimcv/plugins/imv_attestation/attest_usage.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2011 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#ifndef ATTEST_USAGE_H_
+#define ATTEST_USAGE_H_
+
+/**
+ * print attest usage info
+ */
+void usage(void);
+
+
+#endif /* ATTEST_USAGE_H_ */
diff --git a/src/libimcv/plugins/imv_attestation/build-database.sh b/src/libimcv/plugins/imv_attestation/build-database.sh
new file mode 100755
index 000000000..ca2939b49
--- /dev/null
+++ b/src/libimcv/plugins/imv_attestation/build-database.sh
@@ -0,0 +1,84 @@
+#!/bin/sh
+
+p="Ubuntu 14.04 x86_64"
+a="x86_64-linux-gnu"
+k="3.13.0-37-generic"
+
+for hash in sha1 sha256
+do
+ ipsec attest --add --product "$p" --$hash --dir /sbin
+ ipsec attest --add --product "$p" --$hash --dir /usr/sbin
+ ipsec attest --add --product "$p" --$hash --dir /bin
+ ipsec attest --add --product "$p" --$hash --dir /usr/bin
+
+ ipsec attest --add --product "$p" --$hash --file /etc/init.d/rc
+ ipsec attest --add --product "$p" --$hash --file /etc/init.d/rcS
+ ipsec attest --add --product "$p" --$hash --dir /etc/network/if-pre-up.d
+ ipsec attest --add --product "$p" --$hash --dir /etc/network/if-up.d
+ ipsec attest --add --product "$p" --$hash --dir /etc/ppp/ip-down.d
+ ipsec attest --add --product "$p" --$hash --dir /etc/rcS.d
+ ipsec attest --add --product "$p" --$hash --dir /etc/rc2.d
+ ipsec attest --add --product "$p" --$hash --file /etc/rc.local
+ ipsec attest --add --product "$p" --$hash --dir /etc/resolvconf/update.d
+ ipsec attest --add --product "$p" --$hash --file /etc/resolvconf/update-libc.d/avahi-daemon
+ ipsec attest --add --product "$p" --$hash --dir /etc/update-motd.d
+
+ ipsec attest --add --product "$p" --$hash --dir /lib
+ ipsec attest --add --product "$p" --$hash --file /lib/crda/setregdomain
+ ipsec attest --add --product "$p" --$hash --dir /lib/ebtables
+ ipsec attest --add --product "$p" --$hash --file /lib/init/apparmor-profile-load
+ ipsec attest --add --product "$p" --$hash --file /lib/resolvconf/list-records
+ ipsec attest --add --product "$p" --$hash --dir /lib/ufw
+ ipsec attest --add --product "$p" --$hash --dir /lib/udev
+ ipsec attest --add --product "$p" --$hash --dir /lib/systemd
+ ipsec attest --add --product "$p" --$hash --dir /lib/xtables
+ ipsec attest --add --product "$p" --$hash --dir /lib/$a
+ ipsec attest --add --product "$p" --$hash --dir /lib/$a/plymouth
+ ipsec attest --add --product "$p" --$hash --dir /lib/$a/plymouth/renderers
+ ipsec attest --add --product "$p" --$hash --dir /lib/$a/security
+
+ ipsec attest --add --product "$p" --$hash --file /lib64/ld-linux-x86-64.so.2
+
+ for file in `find /usr/lib -name *.so`
+ do
+ ipsec attest --add --product "$p" --$hash --file $file
+ done
+
+ for file in `find /usr/lib -name *service`
+ do
+ ipsec attest --add --product "$p" --$hash --file $file
+ done
+
+ ipsec attest --add --product "$p" --$hash --dir /usr/lib
+ ipsec attest --add --product "$p" --$hash --dir /usr/lib/accountsservice
+ ipsec attest --add --product "$p" --$hash --dir /usr/lib/at-spi2-core
+ ipsec attest --add --product "$p" --$hash --file /usr/lib/avahi/avahi-daemon-check-dns.sh
+ ipsec attest --add --product "$p" --$hash --file /usr/lib/dbus-1.0/dbus-daemon-launch-helper
+ ipsec attest --add --product "$p" --$hash --dir /usr/lib/gvfs
+ ipsec attest --add --product "$p" --$hash --file /usr/lib/firefox/firefox
+ ipsec attest --add --product "$p" --$hash --dir /usr/lib/NetworkManager
+ ipsec attest --add --product "$p" --$hash --dir /usr/lib/pm-utils/power.d
+ ipsec attest --add --product "$p" --$hash --file /usr/lib/policykit-1/polkitd
+ ipsec attest --add --product "$p" --$hash --file /usr/lib/thunderbird/thunderbird
+ ipsec attest --add --product "$p" --$hash --dir /usr/lib/ubuntu-release-upgrader
+ ipsec attest --add --product "$p" --$hash --dir /usr/lib/update-notifier
+
+ ipsec attest --add --product "$p" --$hash --dir /usr/lib/$a
+ ipsec attest --add --product "$p" --$hash --file /usr/lib/$a/mesa/libGL.so.1.2.0
+ ipsec attest --add --product "$p" --$hash --dir /usr/lib/$a/samba
+ ipsec attest --add --product "$p" --$hash --dir /usr/lib/$a/sasl2
+
+ ipsec attest --add --product "$p" --$hash --dir /usr/share/language-tools
+
+ ipsec attest --add --product "$p" --$hash --file /init \
+ --measdir /usr/share/initramfs-tools
+
+ ipsec attest --add --product "$p" --$hash --file /scripts/functions \
+ --measdir /usr/share/initramfs-tools/scripts
+
+ for file in `find /lib/modules/$k -name *.ko`
+ do
+ ipsec attest --add --product "$p" --$hash --file $file
+ done
+done
+
diff --git a/src/libimcv/plugins/imv_attestation/imv_attestation.c b/src/libimcv/plugins/imv_attestation/imv_attestation.c
new file mode 100644
index 000000000..542a561aa
--- /dev/null
+++ b/src/libimcv/plugins/imv_attestation/imv_attestation.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2013 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "imv_attestation_agent.h"
+
+static const char imv_name[] = "Attestation";
+static const imv_agent_create_t imv_agent_create = imv_attestation_agent_create;
+
+/* include generic TGC TNC IF-IMV API code below */
+
+#include <imv/imv_if.h>
+
diff --git a/src/libimcv/plugins/imv_attestation/imv_attestation_agent.c b/src/libimcv/plugins/imv_attestation/imv_attestation_agent.c
new file mode 100644
index 000000000..8e3736857
--- /dev/null
+++ b/src/libimcv/plugins/imv_attestation/imv_attestation_agent.c
@@ -0,0 +1,931 @@
+/*
+ * Copyright (C) 2011-2012 Sansar Choinyambuu
+ * Copyright (C) 2011-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#define _GNU_SOURCE /* for stdndup() */
+#include <string.h>
+
+#include "imv_attestation_agent.h"
+#include "imv_attestation_state.h"
+#include "imv_attestation_process.h"
+#include "imv_attestation_build.h"
+
+#include <imcv.h>
+#include <imv/imv_agent.h>
+#include <imv/imv_msg.h>
+#include <imv/imv_session.h>
+#include <imv/imv_os_info.h>
+#include <ietf/ietf_attr.h>
+#include <ietf/ietf_attr_attr_request.h>
+#include <ietf/ietf_attr_pa_tnc_error.h>
+#include <ietf/ietf_attr_product_info.h>
+#include <ietf/ietf_attr_string_version.h>
+#include <ita/ita_attr.h>
+#include <ita/ita_attr_device_id.h>
+#include <tcg/tcg_attr.h>
+#include <tcg/pts/tcg_pts_attr_meas_algo.h>
+#include <tcg/pts/tcg_pts_attr_proto_caps.h>
+#include <tcg/pts/tcg_pts_attr_req_file_meas.h>
+#include <tcg/pts/tcg_pts_attr_req_file_meta.h>
+#include "tcg/seg/tcg_seg_attr_max_size.h"
+#include "tcg/seg/tcg_seg_attr_seg_env.h"
+#include <pts/pts.h>
+#include <pts/pts_database.h>
+#include <pts/pts_creds.h>
+#include <pts/components/ita/ita_comp_func_name.h>
+
+#include <tncif_pa_subtypes.h>
+
+#include <pen/pen.h>
+#include <utils/debug.h>
+#include <credentials/credential_manager.h>
+#include <collections/linked_list.h>
+
+#define FILE_MEAS_MAX_ATTR_SIZE 100000000
+
+typedef struct private_imv_attestation_agent_t private_imv_attestation_agent_t;
+
+/* Subscribed PA-TNC message subtypes */
+static pen_type_t msg_types[] = {
+ { PEN_TCG, PA_SUBTYPE_TCG_PTS },
+ { PEN_IETF, PA_SUBTYPE_IETF_OPERATING_SYSTEM }
+};
+
+/**
+ * Private data of an imv_attestation_agent_t object.
+ */
+struct private_imv_attestation_agent_t {
+
+ /**
+ * Public members of imv_attestation_agent_t
+ */
+ imv_agent_if_t public;
+
+ /**
+ * IMV agent responsible for generic functions
+ */
+ imv_agent_t *agent;
+
+ /**
+ * Supported PTS measurement algorithms
+ */
+ pts_meas_algorithms_t supported_algorithms;
+
+ /**
+ * Supported PTS Diffie Hellman Groups
+ */
+ pts_dh_group_t supported_dh_groups;
+
+ /**
+ * PTS file measurement database
+ */
+ pts_database_t *pts_db;
+
+ /**
+ * PTS credentials
+ */
+ pts_creds_t *pts_creds;
+
+ /**
+ * PTS credential manager
+ */
+ credential_manager_t *pts_credmgr;
+
+};
+
+METHOD(imv_agent_if_t, bind_functions, TNC_Result,
+ private_imv_attestation_agent_t *this, TNC_TNCS_BindFunctionPointer bind_function)
+{
+ return this->agent->bind_functions(this->agent, bind_function);
+}
+
+METHOD(imv_agent_if_t, notify_connection_change, TNC_Result,
+ private_imv_attestation_agent_t *this, TNC_ConnectionID id,
+ TNC_ConnectionState new_state)
+{
+ TNC_IMV_Action_Recommendation rec;
+ imv_state_t *state;
+ imv_session_t *session;
+
+ switch (new_state)
+ {
+ case TNC_CONNECTION_STATE_CREATE:
+ state = imv_attestation_state_create(id);
+ return this->agent->create_state(this->agent, state);
+ case TNC_CONNECTION_STATE_DELETE:
+ return this->agent->delete_state(this->agent, id);
+ case TNC_CONNECTION_STATE_ACCESS_ALLOWED:
+ case TNC_CONNECTION_STATE_ACCESS_ISOLATED:
+ case TNC_CONNECTION_STATE_ACCESS_NONE:
+ if (this->agent->get_state(this->agent, id, &state) && imcv_db)
+ {
+ session = state->get_session(state);
+
+ if (session->get_policy_started(session))
+ {
+ switch (new_state)
+ {
+ case TNC_CONNECTION_STATE_ACCESS_ALLOWED:
+ rec = TNC_IMV_ACTION_RECOMMENDATION_ALLOW;
+ break;
+ case TNC_CONNECTION_STATE_ACCESS_ISOLATED:
+ rec = TNC_IMV_ACTION_RECOMMENDATION_ISOLATE;
+ break;
+ case TNC_CONNECTION_STATE_ACCESS_NONE:
+ default:
+ rec = TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS;
+ }
+ imcv_db->add_recommendation(imcv_db, session, rec);
+ if (!imcv_db->policy_script(imcv_db, session, FALSE))
+ {
+ DBG1(DBG_IMV, "error in policy script stop");
+ }
+ }
+ }
+ /* fall through to default state */
+ default:
+ return this->agent->change_state(this->agent, id, new_state, NULL);
+ }
+}
+
+/**
+ * Process a received message
+ */
+static TNC_Result receive_msg(private_imv_attestation_agent_t *this,
+ imv_state_t *state, imv_msg_t *in_msg)
+{
+ imv_msg_t *out_msg;
+ imv_session_t *session;
+ imv_os_info_t *os_info;
+ enumerator_t *enumerator;
+ pa_tnc_attr_t *attr;
+ pen_type_t type;
+ TNC_Result result;
+ chunk_t os_name, os_version;
+ bool fatal_error = FALSE;
+
+ /* generate an outgoing PA-TNC message - we might need it */
+ out_msg = imv_msg_create_as_reply(in_msg);
+ out_msg->set_msg_type(out_msg, msg_types[0]);
+
+ /* parse received PA-TNC message and handle local and remote errors */
+ result = in_msg->receive(in_msg, out_msg, &fatal_error);
+ if (result != TNC_RESULT_SUCCESS)
+ {
+ out_msg->destroy(out_msg);
+ return result;
+ }
+
+ session = state->get_session(state);
+ os_info = session->get_os_info(session);
+
+ /* analyze PA-TNC attributes */
+ enumerator = in_msg->create_attribute_enumerator(in_msg);
+ while (enumerator->enumerate(enumerator, &attr))
+ {
+ type = attr->get_type(attr);
+
+ if (type.vendor_id == PEN_IETF)
+ {
+ switch (type.type)
+ {
+ case IETF_ATTR_PA_TNC_ERROR:
+ {
+ ietf_attr_pa_tnc_error_t *error_attr;
+ pen_type_t error_code;
+ chunk_t msg_info;
+
+ error_attr = (ietf_attr_pa_tnc_error_t*)attr;
+ error_code = error_attr->get_error_code(error_attr);
+
+ if (error_code.vendor_id == PEN_TCG)
+ {
+ msg_info = error_attr->get_msg_info(error_attr);
+
+ DBG1(DBG_IMV, "received TCG-PTS error '%N'",
+ pts_error_code_names, error_code.type);
+ DBG1(DBG_IMV, "error information: %B", &msg_info);
+ fatal_error = TRUE;
+ }
+ break;
+ }
+ case IETF_ATTR_PRODUCT_INFORMATION:
+ {
+ ietf_attr_product_info_t *attr_cast;
+ pen_t vendor_id;
+
+ state->set_action_flags(state,
+ IMV_ATTESTATION_ATTR_PRODUCT_INFO);
+ attr_cast = (ietf_attr_product_info_t*)attr;
+ os_name = attr_cast->get_info(attr_cast, &vendor_id, NULL);
+ os_info->set_name(os_info, os_name);
+
+ if (vendor_id != PEN_IETF)
+ {
+ DBG1(DBG_IMV, "operating system name is '%.*s' "
+ "from vendor %N", os_name.len, os_name.ptr,
+ pen_names, vendor_id);
+ }
+ else
+ {
+ DBG1(DBG_IMV, "operating system name is '%.*s'",
+ os_name.len, os_name.ptr);
+ }
+ break;
+
+ break;
+ }
+ case IETF_ATTR_STRING_VERSION:
+ {
+ ietf_attr_string_version_t *attr_cast;
+
+ state->set_action_flags(state,
+ IMV_ATTESTATION_ATTR_STRING_VERSION);
+ attr_cast = (ietf_attr_string_version_t*)attr;
+ os_version = attr_cast->get_version(attr_cast, NULL, NULL);
+ os_info->set_version(os_info, os_version);
+
+ if (os_version.len)
+ {
+ DBG1(DBG_IMV, "operating system version is '%.*s'",
+ os_version.len, os_version.ptr);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ else if (type.vendor_id == PEN_ITA)
+ {
+ switch (type.type)
+ {
+ case ITA_ATTR_DEVICE_ID:
+ {
+ chunk_t value;
+
+ state->set_action_flags(state,
+ IMV_ATTESTATION_ATTR_DEVICE_ID);
+
+ value = attr->get_value(attr);
+ DBG1(DBG_IMV, "device ID is %.*s", value.len, value.ptr);
+ session->set_device_id(session, value);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ else if (type.vendor_id == PEN_TCG)
+ {
+ if (!imv_attestation_process(attr, out_msg, state,
+ this->supported_algorithms, this->supported_dh_groups,
+ this->pts_db, this->pts_credmgr))
+ {
+ result = TNC_RESULT_FATAL;
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (fatal_error || result != TNC_RESULT_SUCCESS)
+ {
+ state->set_recommendation(state,
+ TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
+ TNC_IMV_EVALUATION_RESULT_ERROR);
+ result = out_msg->send_assessment(out_msg);
+ if (result == TNC_RESULT_SUCCESS)
+ {
+ result = this->agent->provide_recommendation(this->agent, state);
+ }
+ }
+ else
+ {
+ /* send PA-TNC message with the EXCL flag set */
+ result = out_msg->send(out_msg, TRUE);
+ }
+ out_msg->destroy(out_msg);
+
+ return result;
+}
+
+METHOD(imv_agent_if_t, receive_message, TNC_Result,
+ private_imv_attestation_agent_t *this, TNC_ConnectionID id,
+ TNC_MessageType msg_type, chunk_t msg)
+{
+ imv_state_t *state;
+ imv_msg_t *in_msg;
+ TNC_Result result;
+
+ if (!this->agent->get_state(this->agent, id, &state))
+ {
+ return TNC_RESULT_FATAL;
+ }
+ in_msg = imv_msg_create_from_data(this->agent, state, id, msg_type, msg);
+ result = receive_msg(this, state, in_msg);
+ in_msg->destroy(in_msg);
+
+ return result;
+}
+
+METHOD(imv_agent_if_t, receive_message_long, TNC_Result,
+ private_imv_attestation_agent_t *this, TNC_ConnectionID id,
+ TNC_UInt32 src_imc_id, TNC_UInt32 dst_imv_id,
+ TNC_VendorID msg_vid, TNC_MessageSubtype msg_subtype, chunk_t msg)
+{
+ imv_state_t *state;
+ imv_msg_t *in_msg;
+ TNC_Result result;
+
+ if (!this->agent->get_state(this->agent, id, &state))
+ {
+ return TNC_RESULT_FATAL;
+ }
+ in_msg = imv_msg_create_from_long_data(this->agent, state, id,
+ src_imc_id, dst_imv_id, msg_vid, msg_subtype, msg);
+ result = receive_msg(this, state, in_msg);
+ in_msg->destroy(in_msg);
+
+ return result;
+}
+
+/**
+ * Build an IETF Attribute Request attribute for missing attributes
+ */
+static pa_tnc_attr_t* build_attr_request(uint32_t received)
+{
+ pa_tnc_attr_t *attr;
+ ietf_attr_attr_request_t *attr_cast;
+
+ attr = ietf_attr_attr_request_create(PEN_RESERVED, 0);
+ attr_cast = (ietf_attr_attr_request_t*)attr;
+
+ if (!(received & IMV_ATTESTATION_ATTR_PRODUCT_INFO) ||
+ !(received & IMV_ATTESTATION_ATTR_STRING_VERSION))
+ {
+ attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_PRODUCT_INFORMATION);
+ attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_STRING_VERSION);
+ }
+ if (!(received & IMV_ATTESTATION_ATTR_DEVICE_ID))
+ {
+ attr_cast->add(attr_cast, PEN_ITA, ITA_ATTR_DEVICE_ID);
+ }
+
+ return attr;
+}
+
+METHOD(imv_agent_if_t, batch_ending, TNC_Result,
+ private_imv_attestation_agent_t *this, TNC_ConnectionID id)
+{
+ imv_msg_t *out_msg;
+ imv_state_t *state;
+ imv_session_t *session;
+ imv_attestation_state_t *attestation_state;
+ imv_attestation_handshake_state_t handshake_state;
+ imv_workitem_t *workitem;
+ TNC_IMV_Action_Recommendation rec;
+ TNC_IMV_Evaluation_Result eval;
+ TNC_IMVID imv_id;
+ TNC_Result result = TNC_RESULT_SUCCESS;
+ pts_t *pts;
+ int pid;
+ uint32_t actions;
+ enumerator_t *enumerator;
+
+ if (!this->agent->get_state(this->agent, id, &state))
+ {
+ return TNC_RESULT_FATAL;
+ }
+ attestation_state = (imv_attestation_state_t*)state;
+ pts = attestation_state->get_pts(attestation_state);
+ handshake_state = attestation_state->get_handshake_state(attestation_state);
+ actions = state->get_action_flags(state);
+ session = state->get_session(state);
+ imv_id = this->agent->get_id(this->agent);
+
+ /* exit if a recommendation has already been provided */
+ if (actions & IMV_ATTESTATION_REC)
+ {
+ return TNC_RESULT_SUCCESS;
+ }
+
+ /* send an IETF attribute request if no platform info was received */
+ if (!(actions & IMV_ATTESTATION_ATTR_REQ))
+ {
+ if ((actions & IMV_ATTESTATION_ATTR_MUST) != IMV_ATTESTATION_ATTR_MUST)
+ {
+ imv_msg_t *os_msg;
+
+ /* create attribute request for missing mandatory attributes */
+ os_msg = imv_msg_create(this->agent, state, id, imv_id,
+ TNC_IMCID_ANY, msg_types[1]);
+ os_msg->add_attribute(os_msg, build_attr_request(actions));
+ result = os_msg->send(os_msg, FALSE);
+ os_msg->destroy(os_msg);
+
+ if (result != TNC_RESULT_SUCCESS)
+ {
+ return result;
+ }
+ }
+ state->set_action_flags(state, IMV_ATTESTATION_ATTR_REQ);
+ }
+
+ if (!session->get_policy_started(session) &&
+ (actions & IMV_ATTESTATION_ATTR_PRODUCT_INFO) &&
+ (actions & IMV_ATTESTATION_ATTR_STRING_VERSION) &&
+ (actions & IMV_ATTESTATION_ATTR_DEVICE_ID))
+ {
+ if (imcv_db)
+ {
+ /* start the policy script */
+ if (!imcv_db->policy_script(imcv_db, session, TRUE))
+ {
+ DBG1(DBG_IMV, "error in policy script start");
+ }
+ }
+ else
+ {
+ DBG2(DBG_IMV, "no workitems available - no evaluation possible");
+ state->set_recommendation(state,
+ TNC_IMV_ACTION_RECOMMENDATION_ALLOW,
+ TNC_IMV_EVALUATION_RESULT_DONT_KNOW);
+ session->set_policy_started(session, TRUE);
+ }
+ }
+
+ if (handshake_state == IMV_ATTESTATION_STATE_INIT)
+ {
+ size_t max_attr_size = FILE_MEAS_MAX_ATTR_SIZE;
+ size_t max_seg_size;
+ seg_contract_t *contract;
+ seg_contract_manager_t *contracts;
+ pa_tnc_attr_t *attr;
+ pts_proto_caps_flag_t flags;
+ char buf[BUF_LEN];
+
+ out_msg = imv_msg_create(this->agent, state, id, imv_id, TNC_IMCID_ANY,
+ msg_types[0]);
+
+ /* Determine maximum PA-TNC attribute segment size */
+ max_seg_size = state->get_max_msg_len(state)
+ - PA_TNC_HEADER_SIZE
+ - PA_TNC_ATTR_HEADER_SIZE
+ - TCG_SEG_ATTR_SEG_ENV_HEADER
+ - PA_TNC_ATTR_HEADER_SIZE
+ - TCG_SEG_ATTR_MAX_SIZE_SIZE;
+
+ /* Announce support of PA-TNC segmentation to IMC */
+ contract = seg_contract_create(msg_types[0], max_attr_size,
+ max_seg_size, TRUE, imv_id, FALSE);
+ contract->get_info_string(contract, buf, BUF_LEN, TRUE);
+ DBG2(DBG_IMV, "%s", buf);
+ contracts = state->get_contracts(state);
+ contracts->add_contract(contracts, contract);
+ attr = tcg_seg_attr_max_size_create(max_attr_size, max_seg_size, TRUE);
+ out_msg->add_attribute(out_msg, attr);
+
+ /* Send Request Protocol Capabilities attribute */
+ flags = pts->get_proto_caps(pts);
+ attr = tcg_pts_attr_proto_caps_create(flags, TRUE);
+ attr->set_noskip_flag(attr, TRUE);
+ out_msg->add_attribute(out_msg, attr);
+
+ /* Send Measurement Algorithms attribute */
+ attr = tcg_pts_attr_meas_algo_create(this->supported_algorithms, FALSE);
+ attr->set_noskip_flag(attr, TRUE);
+ out_msg->add_attribute(out_msg, attr);
+
+ attestation_state->set_handshake_state(attestation_state,
+ IMV_ATTESTATION_STATE_DISCOVERY);
+
+ /* send these initial PTS attributes and exit */
+ result = out_msg->send(out_msg, FALSE);
+ out_msg->destroy(out_msg);
+
+ return result;
+ }
+
+ /* exit if we are not ready yet for PTS measurements */
+ if (!(actions & IMV_ATTESTATION_ALGO))
+ {
+ return TNC_RESULT_SUCCESS;
+ }
+
+ session->get_session_id(session, &pid, NULL);
+ pts->set_platform_id(pts, pid);
+
+ /* create an empty out message - we might need it */
+ out_msg = imv_msg_create(this->agent, state, id, imv_id, TNC_IMCID_ANY,
+ msg_types[0]);
+
+ /* establish the PTS measurements to be taken */
+ if (!(actions & IMV_ATTESTATION_FILE_MEAS))
+ {
+ bool is_dir, no_workitems = TRUE;
+ uint32_t delimiter = SOLIDUS_UTF;
+ uint16_t request_id;
+ pa_tnc_attr_t *attr;
+ char *pathname;
+
+ attestation_state->set_handshake_state(attestation_state,
+ IMV_ATTESTATION_STATE_END);
+
+ enumerator = session->create_workitem_enumerator(session);
+ if (enumerator)
+ {
+ while (enumerator->enumerate(enumerator, &workitem))
+ {
+ if (workitem->get_imv_id(workitem) != TNC_IMVID_ANY)
+ {
+ continue;
+ }
+
+ switch (workitem->get_type(workitem))
+ {
+ case IMV_WORKITEM_FILE_REF_MEAS:
+ case IMV_WORKITEM_FILE_MEAS:
+ case IMV_WORKITEM_FILE_META:
+ is_dir = FALSE;
+ break;
+ case IMV_WORKITEM_DIR_REF_MEAS:
+ case IMV_WORKITEM_DIR_MEAS:
+ case IMV_WORKITEM_DIR_META:
+ is_dir = TRUE;
+ break;
+ case IMV_WORKITEM_TPM_ATTEST:
+ {
+ pts_component_t *comp;
+ pts_comp_func_name_t *comp_name;
+ bool no_d_flag, no_t_flag;
+ char result_str[BUF_LEN];
+
+ workitem->set_imv_id(workitem, imv_id);
+ no_workitems = FALSE;
+ no_d_flag = !(pts->get_proto_caps(pts) & PTS_PROTO_CAPS_D);
+ no_t_flag = !(pts->get_proto_caps(pts) & PTS_PROTO_CAPS_T);
+ if (no_d_flag || no_t_flag)
+ {
+ snprintf(result_str, BUF_LEN, "%s%s%s",
+ (no_t_flag) ? "no TPM available" : "",
+ (no_t_flag && no_d_flag) ? ", " : "",
+ (no_d_flag) ? "no DH nonce negotiation" : "");
+ eval = TNC_IMV_EVALUATION_RESULT_ERROR;
+ session->remove_workitem(session, enumerator);
+ rec = workitem->set_result(workitem, result_str, eval);
+ state->update_recommendation(state, rec, eval);
+ imcv_db->finalize_workitem(imcv_db, workitem);
+ workitem->destroy(workitem);
+ continue;
+ }
+
+ /* do TPM BIOS measurements */
+ if (strchr(workitem->get_arg_str(workitem), 'B'))
+ {
+ comp_name = pts_comp_func_name_create(PEN_ITA,
+ PTS_ITA_COMP_FUNC_NAME_IMA,
+ PTS_ITA_QUALIFIER_FLAG_KERNEL |
+ PTS_ITA_QUALIFIER_TYPE_TRUSTED);
+ comp = attestation_state->create_component(
+ attestation_state, comp_name,
+ 0, this->pts_db);
+ if (!comp)
+ {
+ comp_name->log(comp_name, "unregistered ");
+ comp_name->destroy(comp_name);
+ }
+ }
+
+ /* do TPM IMA measurements */
+ if (strchr(workitem->get_arg_str(workitem), 'I'))
+ {
+ comp_name = pts_comp_func_name_create(PEN_ITA,
+ PTS_ITA_COMP_FUNC_NAME_IMA,
+ PTS_ITA_QUALIFIER_FLAG_KERNEL |
+ PTS_ITA_QUALIFIER_TYPE_OS);
+ comp = attestation_state->create_component(
+ attestation_state, comp_name,
+ 0, this->pts_db);
+ if (!comp)
+ {
+ comp_name->log(comp_name, "unregistered ");
+ comp_name->destroy(comp_name);
+ }
+ }
+
+ /* do TPM TRUSTED BOOT measurements */
+ if (strchr(workitem->get_arg_str(workitem), 'T'))
+ {
+ comp_name = pts_comp_func_name_create(PEN_ITA,
+ PTS_ITA_COMP_FUNC_NAME_TBOOT,
+ PTS_ITA_QUALIFIER_FLAG_KERNEL |
+ PTS_ITA_QUALIFIER_TYPE_TRUSTED);
+ comp = attestation_state->create_component(
+ attestation_state, comp_name,
+ 0, this->pts_db);
+ if (!comp)
+ {
+ comp_name->log(comp_name, "unregistered ");
+ comp_name->destroy(comp_name);
+ }
+ }
+ attestation_state->set_handshake_state(attestation_state,
+ IMV_ATTESTATION_STATE_NONCE_REQ);
+ continue;
+ }
+ default:
+ continue;
+ }
+
+ /* initiate file and directory measurements */
+ pathname = this->pts_db->get_pathname(this->pts_db, is_dir,
+ workitem->get_arg_int(workitem));
+ if (!pathname)
+ {
+ continue;
+ }
+ workitem->set_imv_id(workitem, imv_id);
+ no_workitems = FALSE;
+
+ if (workitem->get_type(workitem) == IMV_WORKITEM_FILE_META)
+ {
+ TNC_IMV_Action_Recommendation rec;
+ TNC_IMV_Evaluation_Result eval;
+ char result_str[BUF_LEN];
+
+ DBG2(DBG_IMV, "IMV %d requests metadata for %s '%s'",
+ imv_id, is_dir ? "directory" : "file", pathname);
+
+ /* currently just fire and forget metadata requests */
+ attr = tcg_pts_attr_req_file_meta_create(is_dir,
+ delimiter, pathname);
+ snprintf(result_str, BUF_LEN, "%s metadata requested",
+ is_dir ? "directory" : "file");
+ eval = TNC_IMV_EVALUATION_RESULT_COMPLIANT;
+ session->remove_workitem(session, enumerator);
+ rec = workitem->set_result(workitem, result_str, eval);
+ state->update_recommendation(state, rec, eval);
+ imcv_db->finalize_workitem(imcv_db, workitem);
+ workitem->destroy(workitem);
+ }
+ else
+ {
+ /* use lower 16 bits of the workitem ID as request ID */
+ request_id = workitem->get_id(workitem) & 0xffff;
+
+ DBG2(DBG_IMV, "IMV %d requests measurement %d for %s '%s'",
+ imv_id, request_id, is_dir ? "directory" : "file",
+ pathname);
+ attr = tcg_pts_attr_req_file_meas_create(is_dir, request_id,
+ delimiter, pathname);
+ }
+ free(pathname);
+ attr->set_noskip_flag(attr, TRUE);
+ out_msg->add_attribute(out_msg, attr);
+ }
+ enumerator->destroy(enumerator);
+
+ /* sent all file and directory measurement and metadata requests */
+ state->set_action_flags(state, IMV_ATTESTATION_FILE_MEAS);
+
+ if (no_workitems)
+ {
+ DBG2(DBG_IMV, "IMV %d has no workitems - "
+ "no evaluation requested", imv_id);
+ state->set_recommendation(state,
+ TNC_IMV_ACTION_RECOMMENDATION_ALLOW,
+ TNC_IMV_EVALUATION_RESULT_DONT_KNOW);
+ }
+ }
+ }
+
+ /* check the IMV state for the next PA-TNC attributes to send */
+ enumerator = session->create_workitem_enumerator(session);
+ while (enumerator->enumerate(enumerator, &workitem))
+ {
+ if (workitem->get_type(workitem) == IMV_WORKITEM_TPM_ATTEST)
+ {
+ if (!imv_attestation_build(out_msg, state,
+ this->supported_dh_groups, this->pts_db))
+ {
+ imv_reason_string_t *reason_string;
+ chunk_t result;
+ char *result_str;
+
+ reason_string = imv_reason_string_create("en", ", ");
+ attestation_state->add_comp_evid_reasons(attestation_state,
+ reason_string);
+ result = reason_string->get_encoding(reason_string);
+ result_str = strndup(result.ptr, result.len);
+ reason_string->destroy(reason_string);
+
+ eval = TNC_IMV_EVALUATION_RESULT_ERROR;
+ session->remove_workitem(session, enumerator);
+ rec = workitem->set_result(workitem, result_str, eval);
+ state->update_recommendation(state, rec, eval);
+ imcv_db->finalize_workitem(imcv_db, workitem);
+ }
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ /* finalized all workitems? */
+ if (session->get_policy_started(session) &&
+ session->get_workitem_count(session, imv_id) == 0 &&
+ attestation_state->get_handshake_state(attestation_state) ==
+ IMV_ATTESTATION_STATE_END)
+ {
+ result = out_msg->send_assessment(out_msg);
+ out_msg->destroy(out_msg);
+ state->set_action_flags(state, IMV_ATTESTATION_REC);
+
+ if (result != TNC_RESULT_SUCCESS)
+ {
+ return result;
+ }
+ return this->agent->provide_recommendation(this->agent, state);
+ }
+
+ /* send non-empty PA-TNC message with excl flag not set */
+ if (out_msg->get_attribute_count(out_msg))
+ {
+ result = out_msg->send(out_msg, FALSE);
+ }
+ out_msg->destroy(out_msg);
+
+ return result;
+}
+
+METHOD(imv_agent_if_t, solicit_recommendation, TNC_Result,
+ private_imv_attestation_agent_t *this, TNC_ConnectionID id)
+{
+ TNC_IMVID imv_id;
+ imv_state_t *state;
+ imv_attestation_state_t *attestation_state;
+ imv_session_t *session;
+
+ if (!this->agent->get_state(this->agent, id, &state))
+ {
+ return TNC_RESULT_FATAL;
+ }
+ attestation_state = (imv_attestation_state_t*)state;
+ session = state->get_session(state);
+ imv_id = this->agent->get_id(this->agent);
+
+ if (imcv_db)
+ {
+ TNC_IMV_Evaluation_Result eval;
+ TNC_IMV_Action_Recommendation rec;
+ imv_workitem_t *workitem;
+ enumerator_t *enumerator;
+ int pending_file_meas = 0;
+ char *result_str;
+ chunk_t result_buf;
+ bio_writer_t *result;
+
+ enumerator = session->create_workitem_enumerator(session);
+ if (enumerator)
+ {
+ while (enumerator->enumerate(enumerator, &workitem))
+ {
+ if (workitem->get_imv_id(workitem) != imv_id)
+ {
+ continue;
+ }
+ result = bio_writer_create(128);
+
+ switch (workitem->get_type(workitem))
+ {
+ case IMV_WORKITEM_FILE_REF_MEAS:
+ case IMV_WORKITEM_FILE_MEAS:
+ case IMV_WORKITEM_DIR_REF_MEAS:
+ case IMV_WORKITEM_DIR_MEAS:
+ result_str = "pending file measurements";
+ pending_file_meas++;
+ break;
+ case IMV_WORKITEM_TPM_ATTEST:
+ attestation_state->finalize_components(attestation_state,
+ result);
+ result->write_data(result,
+ chunk_from_str("; pending component evidence"));
+ result->write_uint8(result, '\0');
+ result_buf = result->get_buf(result);
+ result_str = result_buf.ptr;
+ break;
+ default:
+ result->destroy(result);
+ continue;
+ }
+ session->remove_workitem(session, enumerator);
+ eval = TNC_IMV_EVALUATION_RESULT_ERROR;
+ rec = workitem->set_result(workitem, result_str, eval);
+ state->update_recommendation(state, rec, eval);
+ imcv_db->finalize_workitem(imcv_db, workitem);
+ workitem->destroy(workitem);
+ result->destroy(result);
+ }
+ enumerator->destroy(enumerator);
+
+ if (pending_file_meas)
+ {
+ DBG1(DBG_IMV, "failure due to %d pending file measurements",
+ pending_file_meas);
+ attestation_state->set_measurement_error(attestation_state,
+ IMV_ATTESTATION_ERROR_FILE_MEAS_PEND);
+ }
+ }
+ }
+ return this->agent->provide_recommendation(this->agent, state);
+}
+
+METHOD(imv_agent_if_t, destroy, void,
+ private_imv_attestation_agent_t *this)
+{
+ if (this->pts_creds)
+ {
+ this->pts_credmgr->remove_set(this->pts_credmgr,
+ this->pts_creds->get_set(this->pts_creds));
+ this->pts_creds->destroy(this->pts_creds);
+ }
+ DESTROY_IF(this->pts_db);
+ DESTROY_IF(this->pts_credmgr);
+ DESTROY_IF(this->agent);
+ free(this);
+}
+
+/**
+ * Described in header.
+ */
+imv_agent_if_t *imv_attestation_agent_create(const char *name, TNC_IMVID id,
+ TNC_Version *actual_version)
+{
+ private_imv_attestation_agent_t *this;
+ imv_agent_t *agent;
+ char *hash_alg, *dh_group, *cadir;
+ bool mandatory_dh_groups;
+
+ agent = imv_agent_create(name, msg_types, countof(msg_types), id,
+ actual_version);
+ if (!agent)
+ {
+ return NULL;
+ }
+
+ hash_alg = lib->settings->get_str(lib->settings,
+ "%s.plugins.imv-attestation.hash_algorithm", "sha256", lib->ns);
+ dh_group = lib->settings->get_str(lib->settings,
+ "%s.plugins.imv-attestation.dh_group", "ecp256", lib->ns);
+ mandatory_dh_groups = lib->settings->get_bool(lib->settings,
+ "%s.plugins.imv-attestation.mandatory_dh_groups", TRUE, lib->ns);
+ cadir = lib->settings->get_str(lib->settings,
+ "%s.plugins.imv-attestation.cadir", NULL, lib->ns);
+
+ INIT(this,
+ .public = {
+ .bind_functions = _bind_functions,
+ .notify_connection_change = _notify_connection_change,
+ .receive_message = _receive_message,
+ .receive_message_long = _receive_message_long,
+ .batch_ending = _batch_ending,
+ .solicit_recommendation = _solicit_recommendation,
+ .destroy = _destroy,
+ },
+ .agent = agent,
+ .supported_algorithms = PTS_MEAS_ALGO_NONE,
+ .supported_dh_groups = PTS_DH_GROUP_NONE,
+ .pts_credmgr = credential_manager_create(),
+ .pts_creds = pts_creds_create(cadir),
+ .pts_db = pts_database_create(imcv_db),
+ );
+
+ if (!pts_meas_algo_probe(&this->supported_algorithms) ||
+ !pts_dh_group_probe(&this->supported_dh_groups, mandatory_dh_groups) ||
+ !pts_meas_algo_update(hash_alg, &this->supported_algorithms) ||
+ !pts_dh_group_update(dh_group, &this->supported_dh_groups))
+ {
+ destroy(this);
+ return NULL;
+ }
+
+ if (this->pts_creds)
+ {
+ this->pts_credmgr->add_set(this->pts_credmgr,
+ this->pts_creds->get_set(this->pts_creds));
+ }
+
+ return &this->public;
+}
diff --git a/src/libimcv/plugins/imv_attestation/imv_attestation_agent.h b/src/libimcv/plugins/imv_attestation/imv_attestation_agent.h
new file mode 100644
index 000000000..cc421a29a
--- /dev/null
+++ b/src/libimcv/plugins/imv_attestation/imv_attestation_agent.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2013 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup imv_attestation_agent_t imv_attestation_agent
+ * @{ @ingroup imv_attestation
+ */
+
+#ifndef IMV_ATTESTATION_AGENT_H_
+#define IMV_ATTESTATION_AGENT_H_
+
+#include <imv/imv_agent_if.h>
+
+/**
+ * Creates a Attestation IMV agent
+ *
+ * @param name Name of the IMV
+ * @param id ID of the IMV
+ * @param actual_version TNC IF-IMV version
+ */
+imv_agent_if_t* imv_attestation_agent_create(const char* name, TNC_IMVID id,
+ TNC_Version *actual_version);
+
+#endif /** IMV_ATTESTATION_AGENT_H_ @}*/
diff --git a/src/libimcv/plugins/imv_attestation/imv_attestation_build.c b/src/libimcv/plugins/imv_attestation/imv_attestation_build.c
new file mode 100644
index 000000000..c39fe8d47
--- /dev/null
+++ b/src/libimcv/plugins/imv_attestation/imv_attestation_build.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2011-2012 Sansar Choinyambuu
+ * Copyright (C) 2011-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "imv_attestation_build.h"
+#include "imv_attestation_state.h"
+
+#include <tcg/pts/tcg_pts_attr_dh_nonce_params_req.h>
+#include <tcg/pts/tcg_pts_attr_dh_nonce_finish.h>
+#include <tcg/pts/tcg_pts_attr_get_tpm_version_info.h>
+#include <tcg/pts/tcg_pts_attr_get_aik.h>
+#include <tcg/pts/tcg_pts_attr_req_func_comp_evid.h>
+#include <tcg/pts/tcg_pts_attr_gen_attest_evid.h>
+
+#include <utils/debug.h>
+
+bool imv_attestation_build(imv_msg_t *out_msg, imv_state_t *state,
+ pts_dh_group_t supported_dh_groups,
+ pts_database_t *pts_db)
+{
+ imv_attestation_state_t *attestation_state;
+ imv_attestation_handshake_state_t handshake_state;
+ pts_t *pts;
+ pa_tnc_attr_t *attr = NULL;
+
+ attestation_state = (imv_attestation_state_t*)state;
+ handshake_state = attestation_state->get_handshake_state(attestation_state);
+ pts = attestation_state->get_pts(attestation_state);
+
+ switch (handshake_state)
+ {
+ case IMV_ATTESTATION_STATE_NONCE_REQ:
+ {
+ int min_nonce_len;
+
+ /* Send DH nonce parameters request attribute */
+ min_nonce_len = lib->settings->get_int(lib->settings,
+ "%s.plugins.imv-attestation.min_nonce_len", 0, lib->ns);
+ attr = tcg_pts_attr_dh_nonce_params_req_create(min_nonce_len,
+ supported_dh_groups);
+ attr->set_noskip_flag(attr, TRUE);
+ out_msg->add_attribute(out_msg, attr);
+
+ attestation_state->set_handshake_state(attestation_state,
+ IMV_ATTESTATION_STATE_TPM_INIT);
+ break;
+ }
+ case IMV_ATTESTATION_STATE_TPM_INIT:
+ {
+ pts_meas_algorithms_t selected_algorithm;
+ chunk_t initiator_value, initiator_nonce;
+
+ if (!(state->get_action_flags(state) & IMV_ATTESTATION_DH_NONCE))
+ {
+ break;
+ }
+
+ /* Send DH nonce finish attribute */
+ selected_algorithm = pts->get_meas_algorithm(pts);
+ pts->get_my_public_value(pts, &initiator_value, &initiator_nonce);
+ attr = tcg_pts_attr_dh_nonce_finish_create(selected_algorithm,
+ initiator_value, initiator_nonce);
+ attr->set_noskip_flag(attr, TRUE);
+ out_msg->add_attribute(out_msg, attr);
+
+ /* Send Get TPM Version attribute */
+ attr = tcg_pts_attr_get_tpm_version_info_create();
+ attr->set_noskip_flag(attr, TRUE);
+ out_msg->add_attribute(out_msg, attr);
+
+ /* Send Get AIK attribute */
+ attr = tcg_pts_attr_get_aik_create();
+ attr->set_noskip_flag(attr, TRUE);
+ out_msg->add_attribute(out_msg, attr);
+
+ attestation_state->set_handshake_state(attestation_state,
+ IMV_ATTESTATION_STATE_COMP_EVID);
+ break;
+ }
+ case IMV_ATTESTATION_STATE_COMP_EVID:
+ {
+ tcg_pts_attr_req_func_comp_evid_t *attr_cast;
+ enumerator_t *enumerator;
+ pts_comp_func_name_t *name;
+ uint8_t flags;
+ uint32_t depth;
+ bool first_component = TRUE;
+
+ if (!(state->get_action_flags(state) & IMV_ATTESTATION_AIK))
+ {
+ break;
+ }
+
+ attestation_state->set_handshake_state(attestation_state,
+ IMV_ATTESTATION_STATE_END);
+
+ if (!pts->get_aik_id(pts))
+ {
+ attestation_state->set_measurement_error(attestation_state,
+ IMV_ATTESTATION_ERROR_NO_TRUSTED_AIK);
+ return FALSE;
+ }
+
+ enumerator = attestation_state->create_component_enumerator(
+ attestation_state);
+ while (enumerator->enumerate(enumerator, &flags, &depth, &name))
+ {
+ if (first_component)
+ {
+ attr = tcg_pts_attr_req_func_comp_evid_create();
+ attr->set_noskip_flag(attr, TRUE);
+ first_component = FALSE;
+ DBG2(DBG_IMV, "evidence request by");
+ }
+ name->log(name, " ");
+
+ /* TODO check flags against negotiated_caps */
+ attr_cast = (tcg_pts_attr_req_func_comp_evid_t *)attr;
+ attr_cast->add_component(attr_cast, flags, depth, name);
+ }
+ enumerator->destroy(enumerator);
+
+ if (attr)
+ {
+ /* Send Request Functional Component Evidence attribute */
+ out_msg->add_attribute(out_msg, attr);
+
+ /* Send Generate Attestation Evidence attribute */
+ attr = tcg_pts_attr_gen_attest_evid_create();
+ attr->set_noskip_flag(attr, TRUE);
+ out_msg->add_attribute(out_msg, attr);
+
+ attestation_state->set_handshake_state(attestation_state,
+ IMV_ATTESTATION_STATE_EVID_FINAL);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ return TRUE;
+}
diff --git a/src/libimcv/plugins/imv_attestation/imv_attestation_build.h b/src/libimcv/plugins/imv_attestation/imv_attestation_build.h
new file mode 100644
index 000000000..88538b198
--- /dev/null
+++ b/src/libimcv/plugins/imv_attestation/imv_attestation_build.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup imv_attestation_build_t imv_attestation_build
+ * @{ @ingroup imv_attestation
+ */
+
+#ifndef IMV_ATTESTATION_BUILD_H_
+#define IMV_ATTESTATION_BUILD_H_
+
+#include "imv_attestation_state.h"
+
+#include <imv/imv_msg.h>
+#include <library.h>
+
+#include <pts/pts_database.h>
+#include <pts/pts_dh_group.h>
+#include <pts/pts_meas_algo.h>
+
+/**
+ * Process a TCG PTS attribute
+ *
+ * @param out_msg outbound PA-TNC message to be built
+ * @param state state of a given connection
+ * @param supported_dh_groups supported DH groups
+ * @param pts_db PTS configuration database
+ * @return TRUE if successful
+ */
+bool imv_attestation_build(imv_msg_t *out_msg, imv_state_t *state,
+ pts_dh_group_t supported_dh_groups,
+ pts_database_t *pts_db);
+
+#endif /** IMV_ATTESTATION_BUILD_H_ @}*/
diff --git a/src/libimcv/plugins/imv_attestation/imv_attestation_process.c b/src/libimcv/plugins/imv_attestation/imv_attestation_process.c
new file mode 100644
index 000000000..89a1f02cf
--- /dev/null
+++ b/src/libimcv/plugins/imv_attestation/imv_attestation_process.c
@@ -0,0 +1,567 @@
+/*
+ * Copyright (C) 2011-2012 Sansar Choinyambuu
+ * Copyright (C) 2011-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#define _GNU_SOURCE /* for stdndup() */
+#include <string.h>
+
+#include "imv_attestation_process.h"
+
+#include <imcv.h>
+#include <ietf/ietf_attr_pa_tnc_error.h>
+
+#include <pts/pts.h>
+
+#include <tcg/pts/tcg_pts_attr_aik.h>
+#include <tcg/pts/tcg_pts_attr_dh_nonce_params_resp.h>
+#include <tcg/pts/tcg_pts_attr_file_meas.h>
+#include <tcg/pts/tcg_pts_attr_meas_algo.h>
+#include <tcg/pts/tcg_pts_attr_proto_caps.h>
+#include <tcg/pts/tcg_pts_attr_simple_comp_evid.h>
+#include <tcg/pts/tcg_pts_attr_simple_evid_final.h>
+#include <tcg/pts/tcg_pts_attr_tpm_version_info.h>
+#include <tcg/pts/tcg_pts_attr_unix_file_meta.h>
+
+#include <utils/debug.h>
+#include <crypto/hashers/hasher.h>
+
+#include <inttypes.h>
+
+bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg,
+ imv_state_t *state,
+ pts_meas_algorithms_t supported_algorithms,
+ pts_dh_group_t supported_dh_groups,
+ pts_database_t *pts_db,
+ credential_manager_t *pts_credmgr)
+{
+ imv_session_t *session;
+ imv_attestation_state_t *attestation_state;
+ pen_type_t attr_type;
+ pts_t *pts;
+
+ session = state->get_session(state);
+ attestation_state = (imv_attestation_state_t*)state;
+ pts = attestation_state->get_pts(attestation_state);
+ attr_type = attr->get_type(attr);
+
+ switch (attr_type.type)
+ {
+ case TCG_PTS_PROTO_CAPS:
+ {
+ tcg_pts_attr_proto_caps_t *attr_cast;
+ pts_proto_caps_flag_t flags;
+
+ attr_cast = (tcg_pts_attr_proto_caps_t*)attr;
+ flags = attr_cast->get_flags(attr_cast);
+ pts->set_proto_caps(pts, flags);
+ break;
+ }
+ case TCG_PTS_MEAS_ALGO_SELECTION:
+ {
+ tcg_pts_attr_meas_algo_t *attr_cast;
+ pts_meas_algorithms_t selected_algorithm;
+
+ attr_cast = (tcg_pts_attr_meas_algo_t*)attr;
+ selected_algorithm = attr_cast->get_algorithms(attr_cast);
+ if (!(selected_algorithm & supported_algorithms))
+ {
+ DBG1(DBG_IMV, "PTS-IMC selected unsupported"
+ " measurement algorithm");
+ return FALSE;
+ }
+ pts->set_meas_algorithm(pts, selected_algorithm);
+ state->set_action_flags(state, IMV_ATTESTATION_ALGO);
+ break;
+ }
+ case TCG_PTS_DH_NONCE_PARAMS_RESP:
+ {
+ tcg_pts_attr_dh_nonce_params_resp_t *attr_cast;
+ int nonce_len, min_nonce_len;
+ pts_dh_group_t dh_group;
+ pts_meas_algorithms_t offered_algorithms, selected_algorithm;
+ chunk_t responder_value, responder_nonce;
+
+ attr_cast = (tcg_pts_attr_dh_nonce_params_resp_t*)attr;
+ responder_nonce = attr_cast->get_responder_nonce(attr_cast);
+
+ /* check compliance of responder nonce length */
+ min_nonce_len = lib->settings->get_int(lib->settings,
+ "%s.plugins.imv-attestation.min_nonce_len", 0, lib->ns);
+ nonce_len = responder_nonce.len;
+ if (nonce_len < PTS_MIN_NONCE_LEN ||
+ (min_nonce_len > 0 && nonce_len < min_nonce_len))
+ {
+ attr = pts_dh_nonce_error_create(
+ max(PTS_MIN_NONCE_LEN, min_nonce_len),
+ PTS_MAX_NONCE_LEN);
+ out_msg->add_attribute(out_msg, attr);
+ break;
+ }
+
+ dh_group = attr_cast->get_dh_group(attr_cast);
+ if (!(dh_group & supported_dh_groups))
+ {
+ DBG1(DBG_IMV, "PTS-IMC selected unsupported DH group");
+ return FALSE;
+ }
+
+ offered_algorithms = attr_cast->get_hash_algo_set(attr_cast);
+ selected_algorithm = pts_meas_algo_select(supported_algorithms,
+ offered_algorithms);
+ if (selected_algorithm == PTS_MEAS_ALGO_NONE)
+ {
+ attr = pts_hash_alg_error_create(supported_algorithms);
+ out_msg->add_attribute(out_msg, attr);
+ break;
+ }
+ pts->set_dh_hash_algorithm(pts, selected_algorithm);
+
+ if (!pts->create_dh_nonce(pts, dh_group, nonce_len))
+ {
+ return FALSE;
+ }
+
+ responder_value = attr_cast->get_responder_value(attr_cast);
+ pts->set_peer_public_value(pts, responder_value,
+ responder_nonce);
+
+ /* Calculate secret assessment value */
+ if (!pts->calculate_secret(pts))
+ {
+ return FALSE;
+ }
+ state->set_action_flags(state, IMV_ATTESTATION_DH_NONCE);
+ break;
+ }
+ case TCG_PTS_TPM_VERSION_INFO:
+ {
+ tcg_pts_attr_tpm_version_info_t *attr_cast;
+ chunk_t tpm_version_info;
+
+ attr_cast = (tcg_pts_attr_tpm_version_info_t*)attr;
+ tpm_version_info = attr_cast->get_tpm_version_info(attr_cast);
+ pts->set_tpm_version_info(pts, tpm_version_info);
+ break;
+ }
+ case TCG_PTS_AIK:
+ {
+ tcg_pts_attr_aik_t *attr_cast;
+ certificate_t *aik, *issuer;
+ public_key_t *public;
+ chunk_t keyid, keyid_hex, device_id;
+ int aik_id;
+ enumerator_t *e;
+ bool trusted = FALSE, trusted_chain = FALSE;
+
+ attr_cast = (tcg_pts_attr_aik_t*)attr;
+ aik = attr_cast->get_aik(attr_cast);
+ if (!aik)
+ {
+ DBG1(DBG_IMV, "AIK unavailable");
+ attestation_state->set_measurement_error(attestation_state,
+ IMV_ATTESTATION_ERROR_NO_TRUSTED_AIK);
+ break;
+ }
+
+ /* check trust into public key as stored in the database */
+ public = aik->get_public_key(aik);
+ public->get_fingerprint(public, KEYID_PUBKEY_INFO_SHA1, &keyid);
+ DBG1(DBG_IMV, "verifying AIK with keyid %#B", &keyid);
+ keyid_hex = chunk_to_hex(keyid, NULL, FALSE);
+ if (session->get_device_id(session, &device_id) &&
+ chunk_equals(keyid_hex, device_id))
+ {
+ trusted = session->get_device_trust(session);
+ }
+ else
+ {
+ DBG1(DBG_IMV, "device ID unknown or different from AIK keyid");
+ }
+ DBG1(DBG_IMV, "AIK public key is %strusted", trusted ? "" : "not ");
+ public->destroy(public);
+ chunk_free(&keyid_hex);
+
+ if (aik->get_type(aik) == CERT_X509)
+ {
+
+ e = pts_credmgr->create_trusted_enumerator(pts_credmgr,
+ KEY_ANY, aik->get_issuer(aik), FALSE);
+ while (e->enumerate(e, &issuer))
+ {
+ if (aik->issued_by(aik, issuer, NULL))
+ {
+ trusted_chain = TRUE;
+ break;
+ }
+ }
+ e->destroy(e);
+ DBG1(DBG_IMV, "AIK certificate is %strusted",
+ trusted_chain ? "" : "not ");
+ if (!trusted || !trusted_chain)
+ {
+ attestation_state->set_measurement_error(attestation_state,
+ IMV_ATTESTATION_ERROR_NO_TRUSTED_AIK);
+ break;
+ }
+ }
+ session->get_session_id(session, NULL, &aik_id);
+ pts->set_aik(pts, aik, aik_id);
+ state->set_action_flags(state, IMV_ATTESTATION_AIK);
+ break;
+ }
+ case TCG_PTS_FILE_MEAS:
+ {
+ TNC_IMV_Evaluation_Result eval;
+ TNC_IMV_Action_Recommendation rec;
+ tcg_pts_attr_file_meas_t *attr_cast;
+ uint16_t request_id;
+ int arg_int, file_count;
+ pts_meas_algorithms_t algo;
+ pts_file_meas_t *measurements;
+ imv_workitem_t *workitem, *found = NULL;
+ imv_workitem_type_t type;
+ char result_str[BUF_LEN];
+ bool is_dir, correct;
+ enumerator_t *enumerator;
+
+ eval = TNC_IMV_EVALUATION_RESULT_COMPLIANT;
+ algo = pts->get_meas_algorithm(pts);
+ attr_cast = (tcg_pts_attr_file_meas_t*)attr;
+ measurements = attr_cast->get_measurements(attr_cast);
+ request_id = measurements->get_request_id(measurements);
+ file_count = measurements->get_file_count(measurements);
+
+ DBG1(DBG_IMV, "measurement request %d returned %d file%s:",
+ request_id, file_count, (file_count == 1) ? "":"s");
+
+ if (request_id)
+ {
+ enumerator = session->create_workitem_enumerator(session);
+ while (enumerator->enumerate(enumerator, &workitem))
+ {
+ /* request ID consist of lower 16 bits of workitem ID */
+ if ((workitem->get_id(workitem) & 0xffff) == request_id)
+ {
+ found = workitem;
+ break;
+ }
+ }
+
+ if (!found)
+ {
+ DBG1(DBG_IMV, " no entry found for file measurement "
+ "request %d", request_id);
+ enumerator->destroy(enumerator);
+ break;
+ }
+ type = found->get_type(found);
+ arg_int = found->get_arg_int(found);
+
+ switch (type)
+ {
+ default:
+ case IMV_WORKITEM_FILE_REF_MEAS:
+ case IMV_WORKITEM_FILE_MEAS:
+ is_dir = FALSE;
+ break;
+ case IMV_WORKITEM_DIR_REF_MEAS:
+ case IMV_WORKITEM_DIR_MEAS:
+ is_dir = TRUE;
+ }
+
+ switch (type)
+ {
+ case IMV_WORKITEM_FILE_MEAS:
+ case IMV_WORKITEM_DIR_MEAS:
+ {
+ enumerator_t *e;
+
+ /* check hashes from database against measurements */
+ e = pts_db->create_file_hash_enumerator(pts_db,
+ pts->get_platform_id(pts),
+ algo, is_dir, arg_int);
+ if (!e)
+ {
+ eval = TNC_IMV_EVALUATION_RESULT_ERROR;
+ break;
+ }
+ correct = measurements->verify(measurements, e, is_dir);
+ if (!correct)
+ {
+ attestation_state->set_measurement_error(
+ attestation_state,
+ IMV_ATTESTATION_ERROR_FILE_MEAS_FAIL);
+ eval = TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR;
+ }
+ e->destroy(e);
+
+ snprintf(result_str, BUF_LEN, "%s measurement%s correct",
+ is_dir ? "directory" : "file",
+ correct ? "" : " not");
+ break;
+ }
+ case IMV_WORKITEM_FILE_REF_MEAS:
+ case IMV_WORKITEM_DIR_REF_MEAS:
+ {
+ enumerator_t *e;
+ char *filename;
+ chunk_t measurement;
+
+ e = measurements->create_enumerator(measurements);
+ while (e->enumerate(e, &filename, &measurement))
+ {
+ if (pts_db->add_file_measurement(pts_db,
+ pts->get_platform_id(pts), algo, measurement,
+ filename, is_dir, arg_int) != SUCCESS)
+ {
+ eval = TNC_IMV_EVALUATION_RESULT_ERROR;
+ }
+ }
+ e->destroy(e);
+ snprintf(result_str, BUF_LEN, "%s reference measurement "
+ "successful", is_dir ? "directory" : "file");
+ break;
+ }
+ default:
+ break;
+ }
+
+ session->remove_workitem(session, enumerator);
+ enumerator->destroy(enumerator);
+ rec = found->set_result(found, result_str, eval);
+ state->update_recommendation(state, rec, eval);
+ imcv_db->finalize_workitem(imcv_db, found);
+ found->destroy(found);
+ }
+ else
+ {
+ measurements->check(measurements, pts_db,
+ pts->get_platform_id(pts), algo);
+ }
+ break;
+ }
+ case TCG_PTS_UNIX_FILE_META:
+ {
+ tcg_pts_attr_file_meta_t *attr_cast;
+ int file_count;
+ pts_file_meta_t *metadata;
+ pts_file_metadata_t *entry;
+ time_t created, modified, accessed;
+ bool utc = FALSE;
+ enumerator_t *e;
+
+ attr_cast = (tcg_pts_attr_file_meta_t*)attr;
+ metadata = attr_cast->get_metadata(attr_cast);
+ file_count = metadata->get_file_count(metadata);
+
+ DBG1(DBG_IMV, "metadata request returned %d file%s:",
+ file_count, (file_count == 1) ? "":"s");
+
+ e = metadata->create_enumerator(metadata);
+ while (e->enumerate(e, &entry))
+ {
+ DBG1(DBG_IMV, " '%s' (%"PRIu64" bytes)"
+ " owner %"PRIu64", group %"PRIu64", type %N",
+ entry->filename, entry->filesize, entry->owner,
+ entry->group, pts_file_type_names, entry->type);
+
+ created = entry->created;
+ modified = entry->modified;
+ accessed = entry->accessed;
+
+ DBG1(DBG_IMV, " created %T, modified %T, accessed %T",
+ &created, utc, &modified, utc, &accessed, utc);
+ }
+ e->destroy(e);
+ break;
+ }
+ case TCG_PTS_SIMPLE_COMP_EVID:
+ {
+ tcg_pts_attr_simple_comp_evid_t *attr_cast;
+ pts_comp_func_name_t *name;
+ pts_comp_evidence_t *evidence;
+ pts_component_t *comp;
+ uint32_t depth;
+ status_t status;
+
+ attr_cast = (tcg_pts_attr_simple_comp_evid_t*)attr;
+ evidence = attr_cast->get_comp_evidence(attr_cast);
+ name = evidence->get_comp_func_name(evidence, &depth);
+
+ comp = attestation_state->get_component(attestation_state, name);
+ if (!comp)
+ {
+ DBG1(DBG_IMV, " no entry found for component evidence request");
+ break;
+ }
+ status = comp->verify(comp, name->get_qualifier(name), pts, evidence);
+ if (status == VERIFY_ERROR || status == FAILED)
+ {
+ attestation_state->set_measurement_error(attestation_state,
+ IMV_ATTESTATION_ERROR_COMP_EVID_FAIL);
+ name->log(name, " measurement mismatch for ");
+ }
+ break;
+ }
+ case TCG_PTS_SIMPLE_EVID_FINAL:
+ {
+ tcg_pts_attr_simple_evid_final_t *attr_cast;
+ uint8_t flags;
+ pts_meas_algorithms_t comp_hash_algorithm;
+ chunk_t pcr_comp, tpm_quote_sig, evid_sig;
+ chunk_t pcr_composite, quote_info, result_buf;
+ imv_workitem_t *workitem;
+ imv_reason_string_t *reason_string;
+ enumerator_t *enumerator;
+ bool use_quote2, use_ver_info;
+ bio_writer_t *result;
+
+ attr_cast = (tcg_pts_attr_simple_evid_final_t*)attr;
+ flags = attr_cast->get_quote_info(attr_cast, &comp_hash_algorithm,
+ &pcr_comp, &tpm_quote_sig);
+
+ if (flags != PTS_SIMPLE_EVID_FINAL_NO)
+ {
+ use_quote2 = (flags == PTS_SIMPLE_EVID_FINAL_QUOTE_INFO2 ||
+ flags == PTS_SIMPLE_EVID_FINAL_QUOTE_INFO2_CAP_VER);
+ use_ver_info = (flags == PTS_SIMPLE_EVID_FINAL_QUOTE_INFO2_CAP_VER);
+
+ /* Construct PCR Composite and TPM Quote Info structures */
+ if (!pts->get_quote_info(pts, use_quote2, use_ver_info,
+ comp_hash_algorithm, &pcr_composite, &quote_info))
+ {
+ DBG1(DBG_IMV, "unable to construct TPM Quote Info");
+ return FALSE;
+ }
+
+ if (!chunk_equals(pcr_comp, pcr_composite))
+ {
+ DBG1(DBG_IMV, "received PCR Composite does not match "
+ "constructed one");
+ attestation_state->set_measurement_error(attestation_state,
+ IMV_ATTESTATION_ERROR_TPM_QUOTE_FAIL);
+ goto quote_error;
+ }
+ DBG2(DBG_IMV, "received PCR Composite matches constructed one");
+
+ if (!pts->verify_quote_signature(pts, quote_info, tpm_quote_sig))
+ {
+ attestation_state->set_measurement_error(attestation_state,
+ IMV_ATTESTATION_ERROR_TPM_QUOTE_FAIL);
+ goto quote_error;
+ }
+ DBG2(DBG_IMV, "TPM Quote Info signature verification successful");
+
+quote_error:
+ free(pcr_composite.ptr);
+ free(quote_info.ptr);
+
+ /**
+ * Finalize any pending measurement registrations and check
+ * if all expected component measurements were received
+ */
+ result = bio_writer_create(128);
+ attestation_state->finalize_components(attestation_state,
+ result);
+
+ enumerator = session->create_workitem_enumerator(session);
+ while (enumerator->enumerate(enumerator, &workitem))
+ {
+ if (workitem->get_type(workitem) == IMV_WORKITEM_TPM_ATTEST)
+ {
+ TNC_IMV_Action_Recommendation rec;
+ TNC_IMV_Evaluation_Result eval;
+ uint32_t error;
+
+ error = attestation_state->get_measurement_error(
+ attestation_state);
+ if (error & (IMV_ATTESTATION_ERROR_COMP_EVID_FAIL |
+ IMV_ATTESTATION_ERROR_COMP_EVID_PEND |
+ IMV_ATTESTATION_ERROR_TPM_QUOTE_FAIL))
+ {
+ reason_string = imv_reason_string_create("en", ", ");
+ attestation_state->add_comp_evid_reasons(
+ attestation_state, reason_string);
+ result->write_data(result, chunk_from_str("; "));
+ result->write_data(result,
+ reason_string->get_encoding(reason_string));
+ reason_string->destroy(reason_string);
+ eval = TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR;
+ }
+ else
+ {
+ eval = TNC_IMV_EVALUATION_RESULT_COMPLIANT;
+ }
+ session->remove_workitem(session, enumerator);
+
+ result->write_uint8(result, '\0');
+ result_buf = result->get_buf(result);
+ rec = workitem->set_result(workitem, result_buf.ptr,
+ eval);
+ state->update_recommendation(state, rec, eval);
+ imcv_db->finalize_workitem(imcv_db, workitem);
+ workitem->destroy(workitem);
+ attestation_state->set_handshake_state(attestation_state,
+ IMV_ATTESTATION_STATE_END);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ result->destroy(result);
+ }
+
+ if (attr_cast->get_evid_sig(attr_cast, &evid_sig))
+ {
+ /** TODO: What to do with Evidence Signature */
+ DBG1(DBG_IMV, "this version of the Attestation IMV can not "
+ "handle Evidence Signatures");
+ }
+ break;
+ }
+ case TCG_SEG_MAX_ATTR_SIZE_RESP:
+ case TCG_SEG_ATTR_SEG_ENV:
+ break;
+
+ /* TODO: Not implemented yet */
+ case TCG_PTS_INTEG_MEAS_LOG:
+ /* Attributes using XML */
+ case TCG_PTS_TEMPL_REF_MANI_SET_META:
+ case TCG_PTS_VERIFICATION_RESULT:
+ case TCG_PTS_INTEG_REPORT:
+ /* On Windows only*/
+ case TCG_PTS_WIN_FILE_META:
+ case TCG_PTS_REGISTRY_VALUE:
+ /* Received on IMC side only*/
+ case TCG_PTS_REQ_PROTO_CAPS:
+ case TCG_PTS_DH_NONCE_PARAMS_REQ:
+ case TCG_PTS_DH_NONCE_FINISH:
+ case TCG_PTS_MEAS_ALGO:
+ case TCG_PTS_GET_TPM_VERSION_INFO:
+ case TCG_PTS_REQ_TEMPL_REF_MANI_SET_META:
+ case TCG_PTS_UPDATE_TEMPL_REF_MANI:
+ case TCG_PTS_GET_AIK:
+ case TCG_PTS_REQ_FUNC_COMP_EVID:
+ case TCG_PTS_GEN_ATTEST_EVID:
+ case TCG_PTS_REQ_FILE_META:
+ case TCG_PTS_REQ_FILE_MEAS:
+ case TCG_PTS_REQ_INTEG_MEAS_LOG:
+ default:
+ DBG1(DBG_IMV, "received unsupported attribute '%N/%N'",
+ pen_names, PEN_TCG, tcg_attr_names, attr_type.type);
+ break;
+ }
+ return TRUE;
+}
+
diff --git a/src/libimcv/plugins/imv_attestation/imv_attestation_process.h b/src/libimcv/plugins/imv_attestation/imv_attestation_process.h
new file mode 100644
index 000000000..af8666b66
--- /dev/null
+++ b/src/libimcv/plugins/imv_attestation/imv_attestation_process.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup imv_attestation_process_t imv_attestation_process
+ * @{ @ingroup imv_attestation
+ */
+
+#ifndef IMV_ATTESTATION_PROCESS_H_
+#define IMV_ATTESTATION_PROCESS_H_
+
+#include "imv_attestation_state.h"
+
+#include <library.h>
+#include <collections/linked_list.h>
+#include <credentials/credential_manager.h>
+#include <crypto/hashers/hasher.h>
+
+#include <imv/imv_msg.h>
+#include <pa_tnc/pa_tnc_attr.h>
+
+#include <pts/pts_database.h>
+#include <pts/pts_dh_group.h>
+#include <pts/pts_meas_algo.h>
+
+/**
+ * Process a TCG PTS attribute
+ *
+ * @param attr PA-TNC attribute to be processed
+ * @param out_msg PA-TNC message containing error messages
+ * @param state state of a given connection
+ * @param supported_algorithms supported PTS measurement algorithms
+ * @param supported_dh_groups supported DH groups
+ * @param pts_db PTS configuration database
+ * @param pts_credmgr PTS credential manager
+ * @return TRUE if successful
+ */
+bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg,
+ imv_state_t *state,
+ pts_meas_algorithms_t supported_algorithms,
+ pts_dh_group_t supported_dh_groups,
+ pts_database_t *pts_db,
+ credential_manager_t *pts_credmgr);
+
+#endif /** IMV_ATTESTATION_PROCESS_H_ @}*/
diff --git a/src/libimcv/plugins/imv_attestation/imv_attestation_state.c b/src/libimcv/plugins/imv_attestation/imv_attestation_state.c
new file mode 100644
index 000000000..1c3b91aeb
--- /dev/null
+++ b/src/libimcv/plugins/imv_attestation/imv_attestation_state.c
@@ -0,0 +1,560 @@
+/*
+ * Copyright (C) 2011-2012 Sansar Choinyambuu
+ * Copyright (C) 2011-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "imv_attestation_state.h"
+
+#include <imcv.h>
+#include <imv/imv_lang_string.h>
+#include "imv/imv_reason_string.h"
+
+#include <tncif_policy.h>
+
+#include <collections/linked_list.h>
+#include <utils/debug.h>
+
+typedef struct private_imv_attestation_state_t private_imv_attestation_state_t;
+typedef struct file_meas_request_t file_meas_request_t;
+typedef struct func_comp_t func_comp_t;
+
+/**
+ * Private data of an imv_attestation_state_t object.
+ */
+struct private_imv_attestation_state_t {
+
+ /**
+ * Public members of imv_attestation_state_t
+ */
+ imv_attestation_state_t public;
+
+ /**
+ * TNCCS connection ID
+ */
+ TNC_ConnectionID connection_id;
+
+ /**
+ * TNCCS connection state
+ */
+ TNC_ConnectionState state;
+
+ /**
+ * Does the TNCCS connection support long message types?
+ */
+ bool has_long;
+
+ /**
+ * Does the TNCCS connection support exclusive delivery?
+ */
+ bool has_excl;
+
+ /**
+ * Maximum PA-TNC message size for this TNCCS connection
+ */
+ uint32_t max_msg_len;
+
+ /**
+ * Flags set for completed actions
+ */
+ uint32_t action_flags;
+
+ /**
+ * IMV database session associated with TNCCS connection
+ */
+ imv_session_t *session;
+
+ /**
+ * PA-TNC attribute segmentation contracts associated with TNCCS connection
+ */
+ seg_contract_manager_t *contracts;
+
+ /**
+ * IMV Attestation handshake state
+ */
+ imv_attestation_handshake_state_t handshake_state;
+
+ /**
+ * IMV action recommendation
+ */
+ TNC_IMV_Action_Recommendation rec;
+
+ /**
+ * IMV evaluation result
+ */
+ TNC_IMV_Evaluation_Result eval;
+
+ /**
+ * List of Functional Components
+ */
+ linked_list_t *components;
+
+ /**
+ * PTS object
+ */
+ pts_t *pts;
+
+ /**
+ * Measurement error flags
+ */
+ uint32_t measurement_error;
+
+ /**
+ * TNC Reason String
+ */
+ imv_reason_string_t *reason_string;
+
+};
+
+/**
+ * PTS Functional Component entry
+ */
+struct func_comp_t {
+ pts_component_t *comp;
+ pts_comp_func_name_t* name;
+};
+
+/**
+ * Frees a func_comp_t object
+ */
+static void free_func_comp(func_comp_t *this)
+{
+ this->comp->destroy(this->comp);
+ this->name->destroy(this->name);
+ free(this);
+}
+
+/**
+ * Supported languages
+ */
+static char* languages[] = { "en", "de", "mn" };
+
+/**
+ * Table of reason strings
+ */
+static imv_lang_string_t reason_file_meas_fail[] = {
+ { "en", "Incorrect file measurement" },
+ { "de", "Falsche Dateimessung" },
+ { "mn", "Буруу байгаа файл" },
+ { NULL, NULL }
+};
+
+static imv_lang_string_t reason_file_meas_pend[] = {
+ { "en", "Pending file measurement" },
+ { "de", "Ausstehende Dateimessung" },
+ { "mn", "Xүлээгдэж байгаа файл" },
+ { NULL, NULL }
+};
+
+static imv_lang_string_t reason_no_trusted_aik[] = {
+ { "en", "No trusted AIK available" },
+ { "de", "Kein vetrauenswürdiger AIK verfügbar" },
+ { NULL, NULL }
+};
+
+static imv_lang_string_t reason_comp_evid_fail[] = {
+ { "en", "Incorrect component evidence" },
+ { "de", "Falsche Komponenten-Evidenz" },
+ { "mn", "Буруу компонент хэмжилт" },
+ { NULL, NULL }
+};
+
+static imv_lang_string_t reason_comp_evid_pend[] = {
+ { "en", "Pending component evidence" },
+ { "de", "Ausstehende Komponenten-Evidenz" },
+ { "mn", "Xүлээгдэж компонент хэмжилт" },
+ { NULL, NULL }
+};
+
+static imv_lang_string_t reason_tpm_quote_fail[] = {
+ { "en", "Invalid TPM Quote signature received" },
+ { "de", "Falsche TPM Quote Signature erhalten" },
+ { "mn", "Буруу TPM Quote гарын үсэг" },
+ { NULL, NULL }
+};
+
+METHOD(imv_state_t, get_connection_id, TNC_ConnectionID,
+ private_imv_attestation_state_t *this)
+{
+ return this->connection_id;
+}
+
+METHOD(imv_state_t, has_long, bool,
+ private_imv_attestation_state_t *this)
+{
+ return this->has_long;
+}
+
+METHOD(imv_state_t, has_excl, bool,
+ private_imv_attestation_state_t *this)
+{
+ return this->has_excl;
+}
+
+METHOD(imv_state_t, set_flags, void,
+ private_imv_attestation_state_t *this, bool has_long, bool has_excl)
+{
+ this->has_long = has_long;
+ this->has_excl = has_excl;
+}
+
+METHOD(imv_state_t, set_max_msg_len, void,
+ private_imv_attestation_state_t *this, uint32_t max_msg_len)
+{
+ this->max_msg_len = max_msg_len;
+}
+
+METHOD(imv_state_t, get_max_msg_len, uint32_t,
+ private_imv_attestation_state_t *this)
+{
+ return this->max_msg_len;
+}
+
+METHOD(imv_state_t, set_action_flags, void,
+ private_imv_attestation_state_t *this, uint32_t flags)
+{
+ this->action_flags |= flags;
+}
+
+METHOD(imv_state_t, get_action_flags, uint32_t,
+ private_imv_attestation_state_t *this)
+{
+ return this->action_flags;
+}
+
+METHOD(imv_state_t, set_session, void,
+ private_imv_attestation_state_t *this, imv_session_t *session)
+{
+ this->session = session;
+}
+
+METHOD(imv_state_t, get_session, imv_session_t*,
+ private_imv_attestation_state_t *this)
+{
+ return this->session;
+}
+
+METHOD(imv_state_t, get_contracts, seg_contract_manager_t*,
+ private_imv_attestation_state_t *this)
+{
+ return this->contracts;
+}
+
+METHOD(imv_state_t, change_state, void,
+ private_imv_attestation_state_t *this, TNC_ConnectionState new_state)
+{
+ this->state = new_state;
+}
+
+METHOD(imv_state_t, get_recommendation, void,
+ private_imv_attestation_state_t *this, TNC_IMV_Action_Recommendation *rec,
+ TNC_IMV_Evaluation_Result *eval)
+{
+ *rec = this->rec;
+ *eval = this->eval;
+}
+
+METHOD(imv_state_t, set_recommendation, void,
+ private_imv_attestation_state_t *this, TNC_IMV_Action_Recommendation rec,
+ TNC_IMV_Evaluation_Result eval)
+{
+ this->rec = rec;
+ this->eval = eval;
+}
+
+METHOD(imv_state_t, update_recommendation, void,
+ private_imv_attestation_state_t *this, TNC_IMV_Action_Recommendation rec,
+ TNC_IMV_Evaluation_Result eval)
+{
+ this->rec = tncif_policy_update_recommendation(this->rec, rec);
+ this->eval = tncif_policy_update_evaluation(this->eval, eval);
+}
+
+METHOD(imv_attestation_state_t, add_file_meas_reasons, void,
+ private_imv_attestation_state_t *this, imv_reason_string_t *reason_string)
+{
+ if (this->measurement_error & IMV_ATTESTATION_ERROR_FILE_MEAS_FAIL)
+ {
+ reason_string->add_reason(reason_string, reason_file_meas_fail);
+ }
+ if (this->measurement_error & IMV_ATTESTATION_ERROR_FILE_MEAS_PEND)
+ {
+ reason_string->add_reason(reason_string, reason_file_meas_pend);
+ }
+}
+
+METHOD(imv_attestation_state_t, add_comp_evid_reasons, void,
+ private_imv_attestation_state_t *this, imv_reason_string_t *reason_string)
+{
+ if (this->measurement_error & IMV_ATTESTATION_ERROR_NO_TRUSTED_AIK)
+ {
+ reason_string->add_reason(reason_string, reason_no_trusted_aik);
+ }
+ if (this->measurement_error & IMV_ATTESTATION_ERROR_COMP_EVID_FAIL)
+ {
+ reason_string->add_reason(reason_string, reason_comp_evid_fail);
+ }
+ if (this->measurement_error & IMV_ATTESTATION_ERROR_COMP_EVID_PEND)
+ {
+ reason_string->add_reason(reason_string, reason_comp_evid_pend);
+ }
+ if (this->measurement_error & IMV_ATTESTATION_ERROR_TPM_QUOTE_FAIL)
+ {
+ reason_string->add_reason(reason_string, reason_tpm_quote_fail);
+ }
+}
+
+METHOD(imv_state_t, get_reason_string, bool,
+ private_imv_attestation_state_t *this, enumerator_t *language_enumerator,
+ chunk_t *reason_string, char **reason_language)
+{
+ *reason_language = imv_lang_string_select_lang(language_enumerator,
+ languages, countof(languages));
+
+ /* Instantiate a TNC Reason String object */
+ DESTROY_IF(this->reason_string);
+ this->reason_string = imv_reason_string_create(*reason_language, "\n");
+ add_file_meas_reasons(this, this->reason_string);
+ add_comp_evid_reasons(this, this->reason_string);
+ *reason_string = this->reason_string->get_encoding(this->reason_string);
+
+ return TRUE;
+}
+
+METHOD(imv_state_t, get_remediation_instructions, bool,
+ private_imv_attestation_state_t *this, enumerator_t *language_enumerator,
+ chunk_t *string, char **lang_code, char **uri)
+{
+ return FALSE;
+}
+
+METHOD(imv_state_t, destroy, void,
+ private_imv_attestation_state_t *this)
+{
+ DESTROY_IF(this->session);
+ DESTROY_IF(this->reason_string);
+ this->components->destroy_function(this->components, (void *)free_func_comp);
+ this->pts->destroy(this->pts);
+ this->contracts->destroy(this->contracts);
+ free(this);
+}
+
+METHOD(imv_attestation_state_t, get_handshake_state,
+ imv_attestation_handshake_state_t, private_imv_attestation_state_t *this)
+{
+ return this->handshake_state;
+}
+
+METHOD(imv_attestation_state_t, set_handshake_state, void,
+ private_imv_attestation_state_t *this,
+ imv_attestation_handshake_state_t new_state)
+{
+ this->handshake_state = new_state;
+}
+
+METHOD(imv_attestation_state_t, get_pts, pts_t*,
+ private_imv_attestation_state_t *this)
+{
+ return this->pts;
+}
+
+METHOD(imv_attestation_state_t, create_component, pts_component_t*,
+ private_imv_attestation_state_t *this, pts_comp_func_name_t *name,
+ uint32_t depth, pts_database_t *pts_db)
+{
+ enumerator_t *enumerator;
+ func_comp_t *entry, *new_entry;
+ pts_component_t *component;
+ bool found = FALSE;
+
+ enumerator = this->components->create_enumerator(this->components);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (name->equals(name, entry->comp->get_comp_func_name(entry->comp)))
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (found)
+ {
+ if (name->equals(name, entry->name))
+ {
+ /* duplicate entry */
+ return NULL;
+ }
+ new_entry = malloc_thing(func_comp_t);
+ new_entry->name = name->clone(name);
+ new_entry->comp = entry->comp->get_ref(entry->comp);
+ this->components->insert_last(this->components, new_entry);
+ return entry->comp;
+ }
+ else
+ {
+ component = imcv_pts_components->create(imcv_pts_components,
+ name, depth, pts_db);
+ if (!component)
+ {
+ /* unsupported component */
+ return NULL;
+ }
+ new_entry = malloc_thing(func_comp_t);
+ new_entry->name = name->clone(name);
+ new_entry->comp = component;
+ this->components->insert_last(this->components, new_entry);
+ return component;
+ }
+}
+
+/**
+ * Enumerate file measurement entries
+ */
+static bool entry_filter(void *null, func_comp_t **entry, uint8_t *flags,
+ void *i2, uint32_t *depth,
+ void *i3, pts_comp_func_name_t **comp_name)
+{
+ pts_component_t *comp;
+ pts_comp_func_name_t *name;
+
+ comp = (*entry)->comp;
+ name = (*entry)->name;
+
+ *flags = comp->get_evidence_flags(comp);
+ *depth = comp->get_depth(comp);
+ *comp_name = name;
+
+ return TRUE;
+}
+
+METHOD(imv_attestation_state_t, create_component_enumerator, enumerator_t*,
+ private_imv_attestation_state_t *this)
+{
+ return enumerator_create_filter(
+ this->components->create_enumerator(this->components),
+ (void*)entry_filter, NULL, NULL);
+}
+
+METHOD(imv_attestation_state_t, get_component, pts_component_t*,
+ private_imv_attestation_state_t *this, pts_comp_func_name_t *name)
+{
+ enumerator_t *enumerator;
+ func_comp_t *entry;
+ pts_component_t *found = NULL;
+
+ enumerator = this->components->create_enumerator(this->components);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (name->equals(name, entry->name))
+ {
+ found = entry->comp;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return found;
+}
+
+METHOD(imv_attestation_state_t, get_measurement_error, uint32_t,
+ private_imv_attestation_state_t *this)
+{
+ return this->measurement_error;
+}
+
+METHOD(imv_attestation_state_t, set_measurement_error, void,
+ private_imv_attestation_state_t *this, uint32_t error)
+{
+ this->measurement_error |= error;
+}
+
+METHOD(imv_attestation_state_t, finalize_components, void,
+ private_imv_attestation_state_t *this, bio_writer_t *result)
+{
+ func_comp_t *entry;
+ bool first = TRUE;
+
+ while (this->components->remove_last(this->components,
+ (void**)&entry) == SUCCESS)
+ {
+ if (first)
+ {
+ first = FALSE;
+ }
+ else
+ {
+ result->write_data(result, chunk_from_str("; "));
+ }
+ if (!entry->comp->finalize(entry->comp,
+ entry->name->get_qualifier(entry->name),
+ result))
+ {
+ set_measurement_error(this, IMV_ATTESTATION_ERROR_COMP_EVID_PEND);
+ }
+ free_func_comp(entry);
+ }
+}
+
+/**
+ * Described in header.
+ */
+imv_state_t *imv_attestation_state_create(TNC_ConnectionID connection_id)
+{
+ private_imv_attestation_state_t *this;
+
+ INIT(this,
+ .public = {
+ .interface = {
+ .get_connection_id = _get_connection_id,
+ .has_long = _has_long,
+ .has_excl = _has_excl,
+ .set_flags = _set_flags,
+ .set_max_msg_len = _set_max_msg_len,
+ .get_max_msg_len = _get_max_msg_len,
+ .set_action_flags = _set_action_flags,
+ .get_action_flags = _get_action_flags,
+ .set_session = _set_session,
+ .get_session = _get_session,
+ .get_contracts = _get_contracts,
+ .change_state = _change_state,
+ .get_recommendation = _get_recommendation,
+ .set_recommendation = _set_recommendation,
+ .update_recommendation = _update_recommendation,
+ .get_reason_string = _get_reason_string,
+ .get_remediation_instructions = _get_remediation_instructions,
+ .destroy = _destroy,
+ },
+ .get_handshake_state = _get_handshake_state,
+ .set_handshake_state = _set_handshake_state,
+ .get_pts = _get_pts,
+ .create_component = _create_component,
+ .create_component_enumerator = _create_component_enumerator,
+ .get_component = _get_component,
+ .finalize_components = _finalize_components,
+ .get_measurement_error = _get_measurement_error,
+ .set_measurement_error = _set_measurement_error,
+ .add_file_meas_reasons = _add_file_meas_reasons,
+ .add_comp_evid_reasons = _add_comp_evid_reasons,
+ },
+ .connection_id = connection_id,
+ .state = TNC_CONNECTION_STATE_CREATE,
+ .handshake_state = IMV_ATTESTATION_STATE_INIT,
+ .rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
+ .eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW,
+ .contracts = seg_contract_manager_create(),
+ .components = linked_list_create(),
+ .pts = pts_create(FALSE),
+ );
+
+ return &this->public.interface;
+}
diff --git a/src/libimcv/plugins/imv_attestation/imv_attestation_state.h b/src/libimcv/plugins/imv_attestation/imv_attestation_state.h
new file mode 100644
index 000000000..39a8eee9c
--- /dev/null
+++ b/src/libimcv/plugins/imv_attestation/imv_attestation_state.h
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup imv_attestation imv_attestation
+ * @ingroup libimcv_plugins
+ *
+ * @defgroup imv_attestation_state_t imv_attestation_state
+ * @{ @ingroup imv_attestation
+ */
+
+#ifndef IMV_ATTESTATION_STATE_H_
+#define IMV_ATTESTATION_STATE_H_
+
+#include <imv/imv_state.h>
+#include <imv/imv_reason_string.h>
+#include <pts/pts.h>
+#include <pts/pts_database.h>
+#include <pts/components/pts_component.h>
+
+#include <library.h>
+#include <bio/bio_writer.h>
+
+typedef struct imv_attestation_state_t imv_attestation_state_t;
+typedef enum imv_attestation_flag_t imv_attestation_flag_t;
+typedef enum imv_attestation_handshake_state_t imv_attestation_handshake_state_t;
+typedef enum imv_meas_error_t imv_meas_error_t;
+
+/**
+ * IMV Attestation Flags set for completed actions
+ */
+enum imv_attestation_flag_t {
+ IMV_ATTESTATION_ATTR_PRODUCT_INFO = (1<<0),
+ IMV_ATTESTATION_ATTR_STRING_VERSION = (1<<1),
+ IMV_ATTESTATION_ATTR_DEVICE_ID = (1<<2),
+ IMV_ATTESTATION_ATTR_MUST = (1<<3)-1,
+ IMV_ATTESTATION_ATTR_REQ = (1<<3),
+ IMV_ATTESTATION_ALGO = (1<<4),
+ IMV_ATTESTATION_DH_NONCE = (1<<5),
+ IMV_ATTESTATION_AIK = (1<<6),
+ IMV_ATTESTATION_FILE_MEAS = (1<<7),
+ IMV_ATTESTATION_REC = (1<<8)
+};
+
+/**
+ * IMV Attestation Handshake States (state machine)
+ */
+enum imv_attestation_handshake_state_t {
+ IMV_ATTESTATION_STATE_INIT,
+ IMV_ATTESTATION_STATE_DISCOVERY,
+ IMV_ATTESTATION_STATE_NONCE_REQ,
+ IMV_ATTESTATION_STATE_TPM_INIT,
+ IMV_ATTESTATION_STATE_COMP_EVID,
+ IMV_ATTESTATION_STATE_EVID_FINAL,
+ IMV_ATTESTATION_STATE_END,
+};
+
+/**
+ * IMV Measurement Error Types
+ */
+enum imv_meas_error_t {
+ IMV_ATTESTATION_ERROR_FILE_MEAS_FAIL = 1,
+ IMV_ATTESTATION_ERROR_FILE_MEAS_PEND = 2,
+ IMV_ATTESTATION_ERROR_NO_TRUSTED_AIK = 4,
+ IMV_ATTESTATION_ERROR_COMP_EVID_FAIL = 8,
+ IMV_ATTESTATION_ERROR_COMP_EVID_PEND = 16,
+ IMV_ATTESTATION_ERROR_TPM_QUOTE_FAIL = 32
+};
+
+/**
+ * Internal state of an imv_attestation_t connection instance
+ */
+struct imv_attestation_state_t {
+
+ /**
+ * imv_state_t interface
+ */
+ imv_state_t interface;
+
+ /**
+ * Get state of the handshake
+ *
+ * @return the handshake state of IMV
+ */
+ imv_attestation_handshake_state_t (*get_handshake_state)(
+ imv_attestation_state_t *this);
+
+ /**
+ * Set state of the handshake
+ *
+ * @param new_state the handshake state of IMV
+ */
+ void (*set_handshake_state)(imv_attestation_state_t *this,
+ imv_attestation_handshake_state_t new_state);
+
+ /**
+ * Get the PTS object
+ *
+ * @return PTS object
+ */
+ pts_t* (*get_pts)(imv_attestation_state_t *this);
+
+ /**
+ * Create and add an entry to the list of Functional Components
+ *
+ * @param name Component Functional Name
+ * @param depth Sub-component Depth
+ * @param pts_db PTS measurement database
+ * @return created functional component instance or NULL
+ */
+ pts_component_t* (*create_component)(imv_attestation_state_t *this,
+ pts_comp_func_name_t *name,
+ uint32_t depth,
+ pts_database_t *pts_db);
+
+ /**
+ * Enumerate over all Functional Components
+ *
+ * @return Functional Component enumerator
+ */
+ enumerator_t* (*create_component_enumerator)(imv_attestation_state_t *this);
+
+ /**
+ * Get a Functional Component with a given name
+ *
+ * @param name Name of the requested Functional Component
+ * @return Functional Component if found, NULL otherwise
+ */
+ pts_component_t* (*get_component)(imv_attestation_state_t *this,
+ pts_comp_func_name_t *name);
+
+ /**
+ * Tell the Functional Components to finalize any measurement registrations
+ * and to check if all expected measurements were received
+ *
+ * @param result Writer appending component measurement results
+ */
+ void (*finalize_components)(imv_attestation_state_t *this,
+ bio_writer_t *result);
+
+ /**
+ * Indicates the types of measurement errors that occurred
+ *
+ * @return Measurement error flags
+ */
+ uint32_t (*get_measurement_error)(imv_attestation_state_t *this);
+
+ /**
+ * Call if a measurement error is encountered
+ *
+ * @param error Measurement error type
+ */
+ void (*set_measurement_error)(imv_attestation_state_t *this,
+ uint32_t error);
+
+ /**
+ * Returns a concatenation of File Measurement reason strings
+ *
+ * @param reason_string Concatenated reason strings
+ */
+ void (*add_file_meas_reasons)(imv_attestation_state_t *this,
+ imv_reason_string_t *reason_string);
+
+ /**
+ * Returns a concatenation of Component Evidence reason strings
+ *
+ * @param reason_string Concatenated reason strings
+ */
+ void (*add_comp_evid_reasons)(imv_attestation_state_t *this,
+ imv_reason_string_t *reason_string);
+};
+
+/**
+ * Create an imv_attestation_state_t instance
+ *
+ * @param id connection ID
+ */
+imv_state_t* imv_attestation_state_create(TNC_ConnectionID id);
+
+#endif /** IMV_ATTESTATION_STATE_H_ @}*/
diff --git a/src/libimcv/plugins/imv_os/Makefile.in b/src/libimcv/plugins/imv_os/Makefile.in
index cae6dbe84..36e708fc9 100644
--- a/src/libimcv/plugins/imv_os/Makefile.in
+++ b/src/libimcv/plugins/imv_os/Makefile.in
@@ -238,6 +238,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -298,6 +299,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -363,6 +365,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -410,6 +414,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libimcv/plugins/imv_os/imv_os_agent.c b/src/libimcv/plugins/imv_os/imv_os_agent.c
index ca8bac6ca..f0b1936ab 100644
--- a/src/libimcv/plugins/imv_os/imv_os_agent.c
+++ b/src/libimcv/plugins/imv_os/imv_os_agent.c
@@ -37,8 +37,9 @@
#include <ita/ita_attr.h>
#include <ita/ita_attr_get_settings.h>
#include <ita/ita_attr_settings.h>
-#include <ita/ita_attr_angel.h>
#include <ita/ita_attr_device_id.h>
+#include "tcg/seg/tcg_seg_attr_max_size.h"
+#include "tcg/seg/tcg_seg_attr_seg_env.h"
#include <tncif_names.h>
#include <tncif_pa_subtypes.h>
@@ -46,6 +47,8 @@
#include <pen/pen.h>
#include <utils/debug.h>
+#define INSTALLED_PACKAGES_MAX_ATTR_SIZE 100000000
+
typedef struct private_imv_os_agent_t private_imv_os_agent_t;
typedef enum imv_os_attr_t imv_os_attr_t;
@@ -166,20 +169,23 @@ static TNC_Result receive_msg(private_imv_os_agent_t *this, imv_state_t *state,
chunk_t os_name = chunk_empty;
chunk_t os_version = chunk_empty;
bool fatal_error = FALSE, assessment = FALSE;
+ uint16_t missing;
os_state = (imv_os_state_t*)state;
session = state->get_session(state);
os_info = session->get_os_info(session);
+ /* generate an outgoing PA-TNC message - we might need it */
+ out_msg = imv_msg_create_as_reply(in_msg);
+
/* parse received PA-TNC message and handle local and remote errors */
- result = in_msg->receive(in_msg, &fatal_error);
+ result = in_msg->receive(in_msg,out_msg, &fatal_error);
if (result != TNC_RESULT_SUCCESS)
{
+ out_msg->destroy(out_msg);
return result;
}
- out_msg = imv_msg_create_as_reply(in_msg);
-
/* analyze PA-TNC attributes */
enumerator = in_msg->create_attribute_enumerator(in_msg);
while (enumerator->enumerate(enumerator, &attr))
@@ -323,6 +329,9 @@ static TNC_Result receive_msg(private_imv_os_agent_t *this, imv_state_t *state,
TNC_IMV_EVALUATION_RESULT_ERROR);
assessment = TRUE;
}
+ missing = attr_cast->get_count(attr_cast);
+ os_state->set_missing(os_state, missing);
+ attr_cast->clear_packages(attr_cast);
break;
}
default:
@@ -369,12 +378,6 @@ static TNC_Result receive_msg(private_imv_os_agent_t *this, imv_state_t *state,
session->set_device_id(session, value);
break;
}
- case ITA_ATTR_START_ANGEL:
- os_state->set_angel_count(os_state, TRUE);
- break;
- case ITA_ATTR_STOP_ANGEL:
- os_state->set_angel_count(os_state, FALSE);
- break;
default:
break;
}
@@ -394,20 +397,20 @@ static TNC_Result receive_msg(private_imv_os_agent_t *this, imv_state_t *state,
{
os_state->set_handshake_state(os_state, IMV_OS_STATE_END);
result = out_msg->send_assessment(out_msg);
- out_msg->destroy(out_msg);
- if (result != TNC_RESULT_SUCCESS)
+ if (result == TNC_RESULT_SUCCESS)
{
- return result;
+ result = this->agent->provide_recommendation(this->agent, state);
}
- return this->agent->provide_recommendation(this->agent, state);
}
-
- /* send PA-TNC message with excl flag set */
- result = out_msg->send(out_msg, TRUE);
+ else
+ {
+ /* send PA-TNC message with the EXCL flag set */
+ result = out_msg->send(out_msg, TRUE);
+ }
out_msg->destroy(out_msg);
return result;
- }
+}
METHOD(imv_agent_if_t, receive_message, TNC_Result,
private_imv_os_agent_t *this, TNC_ConnectionID id,
@@ -529,6 +532,30 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
if (handshake_state == IMV_OS_STATE_INIT)
{
+ size_t max_attr_size = INSTALLED_PACKAGES_MAX_ATTR_SIZE;
+ size_t max_seg_size;
+ seg_contract_t *contract;
+ seg_contract_manager_t *contracts;
+ char buf[BUF_LEN];
+
+ /* Determine maximum PA-TNC attribute segment size */
+ max_seg_size = state->get_max_msg_len(state)
+ - PA_TNC_HEADER_SIZE
+ - PA_TNC_ATTR_HEADER_SIZE
+ - TCG_SEG_ATTR_SEG_ENV_HEADER
+ - PA_TNC_ATTR_HEADER_SIZE
+ - TCG_SEG_ATTR_MAX_SIZE_SIZE;
+
+ /* Announce support of PA-TNC segmentation to IMC */
+ contract = seg_contract_create(msg_types[0], max_attr_size,
+ max_seg_size, TRUE, imv_id, FALSE);
+ contract->get_info_string(contract, buf, BUF_LEN, TRUE);
+ DBG2(DBG_IMV, "%s", buf);
+ contracts = state->get_contracts(state);
+ contracts->add_contract(contracts, contract);
+ attr = tcg_seg_attr_max_size_create(max_attr_size, max_seg_size, TRUE);
+ out_msg->add_attribute(out_msg, attr);
+
if ((received & IMV_OS_ATTR_MUST) != IMV_OS_ATTR_MUST)
{
/* create attribute request for missing mandatory attributes */
@@ -671,7 +698,7 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
int count, count_update, count_blacklist, count_ok;
if (!(received & IMV_OS_ATTR_INSTALLED_PACKAGES) ||
- os_state->get_angel_count(os_state) > 0)
+ os_state->get_missing(os_state) > 0)
{
continue;
}
diff --git a/src/libimcv/plugins/imv_os/imv_os_state.c b/src/libimcv/plugins/imv_os/imv_os_state.c
index dc8474ac9..ac826a77c 100644
--- a/src/libimcv/plugins/imv_os/imv_os_state.c
+++ b/src/libimcv/plugins/imv_os/imv_os_state.c
@@ -76,6 +76,11 @@ struct private_imv_os_state_t {
imv_session_t *session;
/**
+ * PA-TNC attribute segmentation contracts associated with TNCCS connection
+ */
+ seg_contract_manager_t *contracts;
+
+ /**
* IMV action recommendation
*/
TNC_IMV_Action_Recommendation rec;
@@ -136,9 +141,9 @@ struct private_imv_os_state_t {
u_int os_settings;
/**
- * Angel count
+ * Number of installed packages still missing
*/
- int angel_count;
+ uint16_t missing;
};
@@ -327,6 +332,12 @@ METHOD(imv_state_t, get_session, imv_session_t*,
return this->session;
}
+METHOD(imv_state_t, get_contracts, seg_contract_manager_t*,
+ private_imv_os_state_t *this)
+{
+ return this->contracts;
+}
+
METHOD(imv_state_t, get_recommendation, void,
private_imv_os_state_t *this, TNC_IMV_Action_Recommendation *rec,
TNC_IMV_Evaluation_Result *eval)
@@ -461,6 +472,7 @@ METHOD(imv_state_t, destroy, void,
DESTROY_IF(this->session);
DESTROY_IF(this->reason_string);
DESTROY_IF(this->remediation_string);
+ this->contracts->destroy(this->contracts);
this->update_packages->destroy_function(this->update_packages, free);
this->remove_packages->destroy_function(this->remove_packages, free);
free(this);
@@ -523,16 +535,16 @@ METHOD(imv_os_state_t, get_os_settings, u_int,
return this->os_settings;
}
-METHOD(imv_os_state_t, set_angel_count, void,
- private_imv_os_state_t *this, bool start)
+METHOD(imv_os_state_t, set_missing, void,
+ private_imv_os_state_t *this, uint16_t missing)
{
- this->angel_count += start ? 1 : -1;
+ this->missing = missing;
}
-METHOD(imv_os_state_t, get_angel_count, int,
+METHOD(imv_os_state_t, get_missing, uint16_t,
private_imv_os_state_t *this)
{
- return this->angel_count;
+ return this->missing;
}
METHOD(imv_os_state_t, add_bad_package, void,
@@ -571,6 +583,7 @@ imv_state_t *imv_os_state_create(TNC_ConnectionID connection_id)
.get_action_flags = _get_action_flags,
.set_session = _set_session,
.get_session = _get_session,
+ .get_contracts = _get_contracts,
.change_state = _change_state,
.get_recommendation = _get_recommendation,
.set_recommendation = _set_recommendation,
@@ -585,14 +598,15 @@ imv_state_t *imv_os_state_create(TNC_ConnectionID connection_id)
.get_count = _get_count,
.set_os_settings = _set_os_settings,
.get_os_settings = _get_os_settings,
- .set_angel_count = _set_angel_count,
- .get_angel_count = _get_angel_count,
+ .set_missing = _set_missing,
+ .get_missing = _get_missing,
.add_bad_package = _add_bad_package,
},
.state = TNC_CONNECTION_STATE_CREATE,
.rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
.eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW,
.connection_id = connection_id,
+ .contracts = seg_contract_manager_create(),
.update_packages = linked_list_create(),
.remove_packages = linked_list_create(),
);
diff --git a/src/libimcv/plugins/imv_os/imv_os_state.h b/src/libimcv/plugins/imv_os/imv_os_state.h
index 82ebb6cc9..aa9b64076 100644
--- a/src/libimcv/plugins/imv_os/imv_os_state.h
+++ b/src/libimcv/plugins/imv_os/imv_os_state.h
@@ -114,18 +114,18 @@ struct imv_os_state_t {
u_int (*get_os_settings)(imv_os_state_t *this);
/**
- * Increase/Decrease the ITA Angel count
+ * Set number of installed packages still missing
*
- * @param start TRUE increases and FALSE decreases count by one
+ * @param missing Number of missing installed packages
*/
- void (*set_angel_count)(imv_os_state_t *this, bool start);
+ void (*set_missing)(imv_os_state_t *this, uint16_t missing);
/**
- * Get the ITA Angel count
+ * Get number of installed packages still missing
*
- * @return ITA Angel count
+ * @return Number of missing installed packages
*/
- int (*get_angel_count)(imv_os_state_t *this);
+ uint16_t (*get_missing)(imv_os_state_t *this);
/**
* Store a bad package that has to be updated or removed
diff --git a/src/libimcv/plugins/imv_scanner/Makefile.in b/src/libimcv/plugins/imv_scanner/Makefile.in
index 18446e73a..2677b339a 100644
--- a/src/libimcv/plugins/imv_scanner/Makefile.in
+++ b/src/libimcv/plugins/imv_scanner/Makefile.in
@@ -232,6 +232,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -292,6 +293,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -357,6 +359,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -404,6 +408,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libimcv/plugins/imv_scanner/imv_scanner_agent.c b/src/libimcv/plugins/imv_scanner/imv_scanner_agent.c
index 85ef23b80..cbabc80bf 100644
--- a/src/libimcv/plugins/imv_scanner/imv_scanner_agent.c
+++ b/src/libimcv/plugins/imv_scanner/imv_scanner_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
@@ -94,10 +94,14 @@ static TNC_Result receive_msg(private_imv_scanner_agent_t *this,
ietf_attr_port_filter_t *port_filter_attr;
bool fatal_error = FALSE;
+ /* generate an outgoing PA-TNC message - we might need it */
+ out_msg = imv_msg_create_as_reply(in_msg);
+
/* parse received PA-TNC message and handle local and remote errors */
- result = in_msg->receive(in_msg, &fatal_error);
+ result = in_msg->receive(in_msg, out_msg, &fatal_error);
if (result != TNC_RESULT_SUCCESS)
{
+ out_msg->destroy(out_msg);
return result;
}
@@ -121,17 +125,20 @@ static TNC_Result receive_msg(private_imv_scanner_agent_t *this,
state->set_recommendation(state,
TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
TNC_IMV_EVALUATION_RESULT_ERROR);
- out_msg = imv_msg_create_as_reply(in_msg);
result = out_msg->send_assessment(out_msg);
- out_msg->destroy(out_msg);
- if (result != TNC_RESULT_SUCCESS)
+ if (result == TNC_RESULT_SUCCESS)
{
- return result;
+ result = this->agent->provide_recommendation(this->agent, state);
}
- return this->agent->provide_recommendation(this->agent, state);
}
+ else
+ {
+ /* send PA-TNC message with the EXCL flag set */
+ result = out_msg->send(out_msg, TRUE);
+ }
+ out_msg->destroy(out_msg);
- return TNC_RESULT_SUCCESS;
+ return result;
}
METHOD(imv_agent_if_t, receive_message, TNC_Result,
diff --git a/src/libimcv/plugins/imv_scanner/imv_scanner_state.c b/src/libimcv/plugins/imv_scanner/imv_scanner_state.c
index 24a49a76c..8f9593f17 100644
--- a/src/libimcv/plugins/imv_scanner/imv_scanner_state.c
+++ b/src/libimcv/plugins/imv_scanner/imv_scanner_state.c
@@ -71,6 +71,11 @@ struct private_imv_scanner_state_t {
imv_session_t *session;
/**
+ * PA-TNC attribute segmentation contracts associated with TNCCS connection
+ */
+ seg_contract_manager_t *contracts;
+
+ /**
* IMV action recommendation
*/
TNC_IMV_Action_Recommendation rec;
@@ -211,6 +216,12 @@ METHOD(imv_state_t, get_session, imv_session_t*,
return this->session;
}
+METHOD(imv_state_t, get_contracts, seg_contract_manager_t*,
+ private_imv_scanner_state_t *this)
+{
+ return this->contracts;
+}
+
METHOD(imv_state_t, change_state, void,
private_imv_scanner_state_t *this, TNC_ConnectionState new_state)
{
@@ -299,6 +310,7 @@ METHOD(imv_state_t, destroy, void,
DESTROY_IF(this->reason_string);
DESTROY_IF(this->remediation_string);
DESTROY_IF(&this->port_filter_attr->pa_tnc_attribute);
+ this->contracts->destroy(this->contracts);
this->violating_ports->destroy_function(this->violating_ports, free);
free(this);
}
@@ -354,6 +366,7 @@ imv_state_t *imv_scanner_state_create(TNC_ConnectionID connection_id)
.get_action_flags = _get_action_flags,
.set_session = _set_session,
.get_session= _get_session,
+ .get_contracts = _get_contracts,
.change_state = _change_state,
.get_recommendation = _get_recommendation,
.set_recommendation = _set_recommendation,
@@ -372,6 +385,7 @@ imv_state_t *imv_scanner_state_create(TNC_ConnectionID connection_id)
.rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
.eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW,
.connection_id = connection_id,
+ .contracts = seg_contract_manager_create(),
.violating_ports = linked_list_create(),
);
diff --git a/src/libimcv/plugins/imv_swid/Makefile.am b/src/libimcv/plugins/imv_swid/Makefile.am
new file mode 100644
index 000000000..3a63b67d2
--- /dev/null
+++ b/src/libimcv/plugins/imv_swid/Makefile.am
@@ -0,0 +1,21 @@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libtncif \
+ -I$(top_srcdir)/src/libimcv
+
+AM_CFLAGS = \
+ $(PLUGIN_CFLAGS) $(json_CFLAGS)
+
+imcv_LTLIBRARIES = imv-swid.la
+
+imv_swid_la_LIBADD = \
+ $(top_builddir)/src/libimcv/libimcv.la \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la \
+ $(json_LIBS)
+
+imv_swid_la_SOURCES = \
+ imv_swid.c imv_swid_state.h imv_swid_state.c \
+ imv_swid_agent.h imv_swid_agent.c \
+ imv_swid_rest.h imv_swid_rest.c
+
+imv_swid_la_LDFLAGS = -module -avoid-version -no-undefined
diff --git a/src/libimcv/plugins/imv_swid/Makefile.in b/src/libimcv/plugins/imv_swid/Makefile.in
new file mode 100644
index 000000000..815722f9c
--- /dev/null
+++ b/src/libimcv/plugins/imv_swid/Makefile.in
@@ -0,0 +1,769 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/libimcv/plugins/imv_swid
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/depcomp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
+ $(top_srcdir)/m4/config/ltoptions.m4 \
+ $(top_srcdir)/m4/config/ltsugar.m4 \
+ $(top_srcdir)/m4/config/ltversion.m4 \
+ $(top_srcdir)/m4/config/lt~obsolete.m4 \
+ $(top_srcdir)/m4/macros/split-package-version.m4 \
+ $(top_srcdir)/m4/macros/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/m4/macros/add-plugin.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(imcvdir)"
+LTLIBRARIES = $(imcv_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+imv_swid_la_DEPENDENCIES = $(top_builddir)/src/libimcv/libimcv.la \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la \
+ $(am__DEPENDENCIES_1)
+am_imv_swid_la_OBJECTS = imv_swid.lo imv_swid_state.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@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+imv_swid_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(imv_swid_la_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(imv_swid_la_SOURCES)
+DIST_SOURCES = $(imv_swid_la_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BFDLIB = @BFDLIB@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+COVERAGE_CFLAGS = @COVERAGE_CFLAGS@
+COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GEM = @GEM@
+GENHTML = @GENHTML@
+GPERF = @GPERF@
+GPRBUILD = @GPRBUILD@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LCOV = @LCOV@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQLCFLAG = @MYSQLCFLAG@
+MYSQLCONFIG = @MYSQLCONFIG@
+MYSQLLIB = @MYSQLLIB@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PACKAGE_VERSION_BUILD = @PACKAGE_VERSION_BUILD@
+PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@
+PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@
+PACKAGE_VERSION_REVIEW = @PACKAGE_VERSION_REVIEW@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+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@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
+RUBYINCLUDE = @RUBYINCLUDE@
+RUBYLIB = @RUBYLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+UNWINDLIB = @UNWINDLIB@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+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@
+am__tar = @am__tar@
+am__untar = @am__untar@
+attest_plugins = @attest_plugins@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+c_plugins = @c_plugins@
+charon_natt_port = @charon_natt_port@
+charon_plugins = @charon_plugins@
+charon_udp_port = @charon_udp_port@
+clearsilver_LIBS = @clearsilver_LIBS@
+cmd_plugins = @cmd_plugins@
+datadir = @datadir@
+datarootdir = @datarootdir@
+dbusservicedir = @dbusservicedir@
+dev_headers = @dev_headers@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+fips_mode = @fips_mode@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+h_plugins = @h_plugins@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+imcvdir = @imcvdir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsec_script = @ipsec_script@
+ipsec_script_upper = @ipsec_script_upper@
+ipsecdir = @ipsecdir@
+ipsecgroup = @ipsecgroup@
+ipseclibdir = @ipseclibdir@
+ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
+libdir = @libdir@
+libexecdir = @libexecdir@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+maemo_CFLAGS = @maemo_CFLAGS@
+maemo_LIBS = @maemo_LIBS@
+manager_plugins = @manager_plugins@
+mandir = @mandir@
+medsrv_plugins = @medsrv_plugins@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
+oldincludedir = @oldincludedir@
+pcsclite_CFLAGS = @pcsclite_CFLAGS@
+pcsclite_LIBS = @pcsclite_LIBS@
+pdfdir = @pdfdir@
+piddir = @piddir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+pki_plugins = @pki_plugins@
+plugindir = @plugindir@
+pool_plugins = @pool_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+s_plugins = @s_plugins@
+sbindir = @sbindir@
+scepclient_plugins = @scepclient_plugins@
+scripts_plugins = @scripts_plugins@
+sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
+srcdir = @srcdir@
+starter_plugins = @starter_plugins@
+strongswan_conf = @strongswan_conf@
+strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
+sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
+systemdsystemunitdir = @systemdsystemunitdir@
+t_plugins = @t_plugins@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+urandom_device = @urandom_device@
+xml_CFLAGS = @xml_CFLAGS@
+xml_LIBS = @xml_LIBS@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libtncif \
+ -I$(top_srcdir)/src/libimcv
+
+AM_CFLAGS = \
+ $(PLUGIN_CFLAGS) $(json_CFLAGS)
+
+imcv_LTLIBRARIES = imv-swid.la
+imv_swid_la_LIBADD = \
+ $(top_builddir)/src/libimcv/libimcv.la \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la \
+ $(json_LIBS)
+
+imv_swid_la_SOURCES = \
+ imv_swid.c imv_swid_state.h imv_swid_state.c \
+ imv_swid_agent.h imv_swid_agent.c \
+ imv_swid_rest.h imv_swid_rest.c
+
+imv_swid_la_LDFLAGS = -module -avoid-version -no-undefined
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libimcv/plugins/imv_swid/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libimcv/plugins/imv_swid/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+install-imcvLTLIBRARIES: $(imcv_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ @list='$(imcv_LTLIBRARIES)'; test -n "$(imcvdir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(MKDIR_P) '$(DESTDIR)$(imcvdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(imcvdir)" || exit 1; \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(imcvdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(imcvdir)"; \
+ }
+
+uninstall-imcvLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(imcv_LTLIBRARIES)'; test -n "$(imcvdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(imcvdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(imcvdir)/$$f"; \
+ done
+
+clean-imcvLTLIBRARIES:
+ -test -z "$(imcv_LTLIBRARIES)" || rm -f $(imcv_LTLIBRARIES)
+ @list='$(imcv_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+imv-swid.la: $(imv_swid_la_OBJECTS) $(imv_swid_la_DEPENDENCIES) $(EXTRA_imv_swid_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(imv_swid_la_LINK) -rpath $(imcvdir) $(imv_swid_la_OBJECTS) $(imv_swid_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@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:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(imcvdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-imcvLTLIBRARIES clean-libtool \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-imcvLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-imcvLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+ clean-imcvLTLIBRARIES clean-libtool cscopelist-am ctags \
+ ctags-am distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am \
+ install-imcvLTLIBRARIES install-info install-info-am \
+ install-man install-pdf install-pdf-am install-ps \
+ install-ps-am install-strip installcheck installcheck-am \
+ installdirs maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
+ uninstall-am uninstall-imcvLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libimcv/plugins/imv_swid/imv_swid.c b/src/libimcv/plugins/imv_swid/imv_swid.c
new file mode 100644
index 000000000..cab011580
--- /dev/null
+++ b/src/libimcv/plugins/imv_swid/imv_swid.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2013 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "imv_swid_agent.h"
+
+static const char imv_name[] = "SWID";
+static const imv_agent_create_t imv_agent_create = imv_swid_agent_create;
+
+/* include generic TGC TNC IF-IMV API code below */
+
+#include <imv/imv_if.h>
+
diff --git a/src/libimcv/plugins/imv_swid/imv_swid_agent.c b/src/libimcv/plugins/imv_swid/imv_swid_agent.c
new file mode 100644
index 000000000..5bebf32c0
--- /dev/null
+++ b/src/libimcv/plugins/imv_swid/imv_swid_agent.c
@@ -0,0 +1,726 @@
+/*
+ * Copyright (C) 2013-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+
+#include "imv_swid_agent.h"
+#include "imv_swid_state.h"
+#include "imv_swid_rest.h"
+
+#include <imcv.h>
+#include <imv/imv_agent.h>
+#include <imv/imv_msg.h>
+#include <ietf/ietf_attr_pa_tnc_error.h>
+#include "tcg/seg/tcg_seg_attr_max_size.h"
+#include "tcg/seg/tcg_seg_attr_seg_env.h"
+#include "tcg/swid/tcg_swid_attr_req.h"
+#include "tcg/swid/tcg_swid_attr_tag_inv.h"
+#include "tcg/swid/tcg_swid_attr_tag_id_inv.h"
+#include "swid/swid_error.h"
+#include "swid/swid_inventory.h"
+
+#include <tncif_names.h>
+#include <tncif_pa_subtypes.h>
+
+#include <pen/pen.h>
+#include <utils/debug.h>
+#include <bio/bio_reader.h>
+
+typedef struct private_imv_swid_agent_t private_imv_swid_agent_t;
+
+/* Subscribed PA-TNC message subtypes */
+static pen_type_t msg_types[] = {
+ { PEN_TCG, PA_SUBTYPE_TCG_SWID }
+};
+
+/**
+ * Flag set when corresponding attribute has been received
+ */
+enum imv_swid_attr_t {
+ IMV_SWID_ATTR_TAG_INV = (1<<0),
+ IMV_SWID_ATTR_TAG_ID_INV = (1<<1)
+};
+
+/**
+ * Private data of an imv_swid_agent_t object.
+ */
+struct private_imv_swid_agent_t {
+
+ /**
+ * Public members of imv_swid_agent_t
+ */
+ imv_agent_if_t public;
+
+ /**
+ * IMV agent responsible for generic functions
+ */
+ imv_agent_t *agent;
+
+ /**
+ * REST API to strongTNC manager
+ */
+ imv_swid_rest_t *rest_api;
+
+};
+
+METHOD(imv_agent_if_t, bind_functions, TNC_Result,
+ private_imv_swid_agent_t *this, TNC_TNCS_BindFunctionPointer bind_function)
+{
+ return this->agent->bind_functions(this->agent, bind_function);
+}
+
+METHOD(imv_agent_if_t, notify_connection_change, TNC_Result,
+ private_imv_swid_agent_t *this, TNC_ConnectionID id,
+ TNC_ConnectionState new_state)
+{
+ imv_state_t *state;
+
+ switch (new_state)
+ {
+ case TNC_CONNECTION_STATE_CREATE:
+ state = imv_swid_state_create(id);
+ return this->agent->create_state(this->agent, state);
+ case TNC_CONNECTION_STATE_DELETE:
+ return this->agent->delete_state(this->agent, id);
+ default:
+ return this->agent->change_state(this->agent, id, new_state, NULL);
+ }
+}
+
+/**
+ * Process a received message
+ */
+static TNC_Result receive_msg(private_imv_swid_agent_t *this,
+ imv_state_t *state, imv_msg_t *in_msg)
+{
+ imv_swid_state_t *swid_state;
+ imv_msg_t *out_msg;
+ enumerator_t *enumerator;
+ pa_tnc_attr_t *attr;
+ TNC_Result result;
+ bool fatal_error = FALSE;
+
+ /* generate an outgoing PA-TNC message - we might need it */
+ out_msg = imv_msg_create_as_reply(in_msg);
+
+ /* parse received PA-TNC message and handle local and remote errors */
+ result = in_msg->receive(in_msg, out_msg, &fatal_error);
+ if (result != TNC_RESULT_SUCCESS)
+ {
+ out_msg->destroy(out_msg);
+ return result;
+ }
+
+ swid_state = (imv_swid_state_t*)state;
+
+ /* analyze PA-TNC attributes */
+ enumerator = in_msg->create_attribute_enumerator(in_msg);
+ while (enumerator->enumerate(enumerator, &attr))
+ {
+ uint32_t request_id = 0, last_eid, eid_epoch;
+ swid_inventory_t *inventory;
+ pen_type_t type;
+
+ type = attr->get_type(attr);
+
+ if (type.vendor_id == PEN_IETF && type.type == IETF_ATTR_PA_TNC_ERROR)
+ {
+ ietf_attr_pa_tnc_error_t *error_attr;
+ pen_type_t error_code;
+ chunk_t msg_info, description;
+ bio_reader_t *reader;
+ uint32_t max_attr_size;
+ bool success;
+
+ error_attr = (ietf_attr_pa_tnc_error_t*)attr;
+ error_code = error_attr->get_error_code(error_attr);
+
+ if (error_code.vendor_id == PEN_TCG)
+ {
+ fatal_error = TRUE;
+ msg_info = error_attr->get_msg_info(error_attr);
+ reader = bio_reader_create(msg_info);
+ success = reader->read_uint32(reader, &request_id);
+
+ DBG1(DBG_IMV, "received TCG error '%N' for request %d",
+ swid_error_code_names, error_code.type, request_id);
+ if (!success)
+ {
+ reader->destroy(reader);
+ continue;
+ }
+ if (error_code.type == TCG_SWID_RESPONSE_TOO_LARGE)
+ {
+ if (!reader->read_uint32(reader, &max_attr_size))
+ {
+ reader->destroy(reader);
+ continue;
+ }
+ DBG1(DBG_IMV, " maximum PA-TNC attribute size is %u bytes",
+ max_attr_size);
+ }
+ description = reader->peek(reader);
+ if (description.len)
+ {
+ DBG1(DBG_IMV, " description: %.*s", description.len,
+ description.ptr);
+ }
+ reader->destroy(reader);
+ }
+ }
+ else if (type.vendor_id != PEN_TCG)
+ {
+ continue;
+ }
+
+ switch (type.type)
+ {
+ case TCG_SWID_TAG_ID_INVENTORY:
+ {
+ tcg_swid_attr_tag_id_inv_t *attr_cast;
+ uint32_t missing;
+ int tag_id_count;
+
+ state->set_action_flags(state, IMV_SWID_ATTR_TAG_ID_INV);
+
+ attr_cast = (tcg_swid_attr_tag_id_inv_t*)attr;
+ request_id = attr_cast->get_request_id(attr_cast);
+ last_eid = attr_cast->get_last_eid(attr_cast, &eid_epoch);
+ inventory = attr_cast->get_inventory(attr_cast);
+ tag_id_count = inventory->get_count(inventory);
+ missing = attr_cast->get_tag_id_count(attr_cast);
+ swid_state->set_missing(swid_state, missing);
+
+ DBG2(DBG_IMV, "received SWID tag ID inventory with %d item%s "
+ "for request %d at eid %d of epoch 0x%08x, %d item%s to "
+ "follow", tag_id_count, (tag_id_count == 1) ? "" : "s",
+ request_id, last_eid, eid_epoch, missing,
+ (missing == 1) ? "" : "s");
+
+ if (request_id == swid_state->get_request_id(swid_state))
+ {
+ swid_state->set_swid_inventory(swid_state, inventory);
+ swid_state->set_count(swid_state, tag_id_count, 0);
+ }
+ else
+ {
+ DBG1(DBG_IMV, "no workitem found for SWID tag ID inventory "
+ "with request ID %d", request_id);
+ }
+ attr_cast->clear_inventory(attr_cast);
+ break;
+ }
+ case TCG_SWID_TAG_INVENTORY:
+ {
+ tcg_swid_attr_tag_inv_t *attr_cast;
+ swid_tag_t *tag;
+ chunk_t tag_encoding;
+ json_object *jobj, *jarray, *jstring;
+ char *tag_str;
+ uint32_t missing;
+ int tag_count;
+ enumerator_t *e;
+
+ state->set_action_flags(state, IMV_SWID_ATTR_TAG_INV);
+
+ attr_cast = (tcg_swid_attr_tag_inv_t*)attr;
+ request_id = attr_cast->get_request_id(attr_cast);
+ last_eid = attr_cast->get_last_eid(attr_cast, &eid_epoch);
+ inventory = attr_cast->get_inventory(attr_cast);
+ tag_count = inventory->get_count(inventory);
+ missing = attr_cast->get_tag_count(attr_cast);
+ swid_state->set_missing(swid_state, missing);
+
+ DBG2(DBG_IMV, "received SWID tag inventory with %d item%s for "
+ "request %d at eid %d of epoch 0x%08x, %d item%s to follow",
+ tag_count, (tag_count == 1) ? "" : "s", request_id,
+ last_eid, eid_epoch, missing, (missing == 1) ? "" : "s");
+
+ if (request_id == swid_state->get_request_id(swid_state))
+ {
+ swid_state->set_count(swid_state, 0, tag_count);
+
+ if (this->rest_api)
+ {
+ jobj = json_object_new_object();
+ jarray = json_object_new_array();
+ json_object_object_add(jobj, "data", jarray);
+
+ e = inventory->create_enumerator(inventory);
+ while (e->enumerate(e, &tag))
+ {
+ tag_encoding = tag->get_encoding(tag);
+ tag_str = strndup(tag_encoding.ptr, tag_encoding.len);
+ DBG3(DBG_IMV, "%s", tag_str);
+ jstring = json_object_new_string(tag_str);
+ json_object_array_add(jarray, jstring);
+ free(tag_str);
+ }
+ e->destroy(e);
+
+ if (this->rest_api->post(this->rest_api,
+ "swid/add-tags/", jobj, NULL) != SUCCESS)
+ {
+ DBG1(DBG_IMV, "error in REST API add-tags request");
+ }
+ json_object_put(jobj);
+ }
+ }
+ else
+ {
+ DBG1(DBG_IMV, "no workitem found for SWID tag inventory "
+ "with request ID %d", request_id);
+ }
+ attr_cast->clear_inventory(attr_cast);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (fatal_error)
+ {
+ state->set_recommendation(state,
+ TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
+ TNC_IMV_EVALUATION_RESULT_ERROR);
+ result = out_msg->send_assessment(out_msg);
+ if (result == TNC_RESULT_SUCCESS)
+ {
+ result = this->agent->provide_recommendation(this->agent, state);
+ }
+ }
+ else
+ {
+ /* send PA-TNC message with the EXCL flag set */
+ result = out_msg->send(out_msg, TRUE);
+ }
+ out_msg->destroy(out_msg);
+
+ return result;
+}
+
+METHOD(imv_agent_if_t, receive_message, TNC_Result,
+ private_imv_swid_agent_t *this, TNC_ConnectionID id,
+ TNC_MessageType msg_type, chunk_t msg)
+{
+ imv_state_t *state;
+ imv_msg_t *in_msg;
+ TNC_Result result;
+
+ if (!this->agent->get_state(this->agent, id, &state))
+ {
+ return TNC_RESULT_FATAL;
+ }
+ in_msg = imv_msg_create_from_data(this->agent, state, id, msg_type, msg);
+ result = receive_msg(this, state, in_msg);
+ in_msg->destroy(in_msg);
+
+ return result;
+}
+
+METHOD(imv_agent_if_t, receive_message_long, TNC_Result,
+ private_imv_swid_agent_t *this, TNC_ConnectionID id,
+ TNC_UInt32 src_imc_id, TNC_UInt32 dst_imv_id,
+ TNC_VendorID msg_vid, TNC_MessageSubtype msg_subtype, chunk_t msg)
+{
+ imv_state_t *state;
+ imv_msg_t *in_msg;
+ TNC_Result result;
+
+ if (!this->agent->get_state(this->agent, id, &state))
+ {
+ return TNC_RESULT_FATAL;
+ }
+ in_msg = imv_msg_create_from_long_data(this->agent, state, id,
+ src_imc_id, dst_imv_id, msg_vid, msg_subtype, msg);
+ result = receive_msg(this, state, in_msg);
+ in_msg->destroy(in_msg);
+
+ return result;
+
+}
+
+METHOD(imv_agent_if_t, batch_ending, TNC_Result,
+ private_imv_swid_agent_t *this, TNC_ConnectionID id)
+{
+ imv_msg_t *out_msg;
+ imv_state_t *state;
+ imv_session_t *session;
+ imv_workitem_t *workitem;
+ imv_swid_state_t *swid_state;
+ imv_swid_handshake_state_t handshake_state;
+ pa_tnc_attr_t *attr;
+ TNC_IMVID imv_id;
+ TNC_Result result = TNC_RESULT_SUCCESS;
+ bool no_workitems = TRUE;
+ uint32_t request_id, received;
+ uint8_t flags;
+ enumerator_t *enumerator;
+
+ if (!this->agent->get_state(this->agent, id, &state))
+ {
+ return TNC_RESULT_FATAL;
+ }
+ swid_state = (imv_swid_state_t*)state;
+ handshake_state = swid_state->get_handshake_state(swid_state);
+ session = state->get_session(state);
+ imv_id = this->agent->get_id(this->agent);
+
+ if (handshake_state == IMV_SWID_STATE_END)
+ {
+ return TNC_RESULT_SUCCESS;
+ }
+
+ /* Create an empty out message - we might need it */
+ out_msg = imv_msg_create(this->agent, state, id, imv_id, TNC_IMCID_ANY,
+ msg_types[0]);
+
+ if (!imcv_db)
+ {
+ DBG2(DBG_IMV, "no workitems available - no evaluation possible");
+ state->set_recommendation(state,
+ TNC_IMV_ACTION_RECOMMENDATION_ALLOW,
+ TNC_IMV_EVALUATION_RESULT_DONT_KNOW);
+ result = out_msg->send_assessment(out_msg);
+ out_msg->destroy(out_msg);
+ swid_state->set_handshake_state(swid_state, IMV_SWID_STATE_END);
+
+ if (result != TNC_RESULT_SUCCESS)
+ {
+ return result;
+ }
+ return this->agent->provide_recommendation(this->agent, state);
+ }
+
+ /* Look for SWID tag workitem and create SWID tag request */
+ if (handshake_state == IMV_SWID_STATE_INIT &&
+ session->get_policy_started(session))
+ {
+ size_t max_attr_size = SWID_MAX_ATTR_SIZE;
+ size_t max_seg_size;
+ seg_contract_t *contract;
+ seg_contract_manager_t *contracts;
+ char buf[BUF_LEN];
+
+ enumerator = session->create_workitem_enumerator(session);
+ if (enumerator)
+ {
+ while (enumerator->enumerate(enumerator, &workitem))
+ {
+ if (workitem->get_imv_id(workitem) != TNC_IMVID_ANY ||
+ workitem->get_type(workitem) != IMV_WORKITEM_SWID_TAGS)
+ {
+ continue;
+ }
+
+ flags = TCG_SWID_ATTR_REQ_FLAG_NONE;
+ if (strchr(workitem->get_arg_str(workitem), 'R'))
+ {
+ flags |= TCG_SWID_ATTR_REQ_FLAG_R;
+ }
+ if (strchr(workitem->get_arg_str(workitem), 'S'))
+ {
+ flags |= TCG_SWID_ATTR_REQ_FLAG_S;
+ }
+ if (strchr(workitem->get_arg_str(workitem), 'C'))
+ {
+ flags |= TCG_SWID_ATTR_REQ_FLAG_C;
+ }
+
+ /* Determine maximum PA-TNC attribute segment size */
+ max_seg_size = state->get_max_msg_len(state)
+ - PA_TNC_HEADER_SIZE
+ - PA_TNC_ATTR_HEADER_SIZE
+ - TCG_SEG_ATTR_SEG_ENV_HEADER
+ - PA_TNC_ATTR_HEADER_SIZE
+ - TCG_SEG_ATTR_MAX_SIZE_SIZE;
+
+ /* Announce support of PA-TNC segmentation to IMC */
+ contract = seg_contract_create(msg_types[0], max_attr_size,
+ max_seg_size, TRUE, imv_id, FALSE);
+ contract->get_info_string(contract, buf, BUF_LEN, TRUE);
+ DBG2(DBG_IMV, "%s", buf);
+ contracts = state->get_contracts(state);
+ contracts->add_contract(contracts, contract);
+ attr = tcg_seg_attr_max_size_create(max_attr_size,
+ max_seg_size, TRUE);
+ out_msg->add_attribute(out_msg, attr);
+
+ /* Issue a SWID request */
+ request_id = workitem->get_id(workitem);
+ swid_state->set_request_id(swid_state, request_id);
+ attr = tcg_swid_attr_req_create(flags, request_id, 0);
+ out_msg->add_attribute(out_msg, attr);
+ workitem->set_imv_id(workitem, imv_id);
+ no_workitems = FALSE;
+ DBG2(DBG_IMV, "IMV %d issues SWID request %d",
+ imv_id, request_id);
+ break;
+ }
+ enumerator->destroy(enumerator);
+
+ if (no_workitems)
+ {
+ DBG2(DBG_IMV, "IMV %d has no workitems - "
+ "no evaluation requested", imv_id);
+ state->set_recommendation(state,
+ TNC_IMV_ACTION_RECOMMENDATION_ALLOW,
+ TNC_IMV_EVALUATION_RESULT_DONT_KNOW);
+ }
+ handshake_state = IMV_SWID_STATE_WORKITEMS;
+ swid_state->set_handshake_state(swid_state, handshake_state);
+ }
+ }
+
+ received = state->get_action_flags(state);
+
+ if (handshake_state == IMV_SWID_STATE_WORKITEMS &&
+ (received & (IMV_SWID_ATTR_TAG_INV|IMV_SWID_ATTR_TAG_ID_INV)) &&
+ swid_state->get_missing(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;
+ 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;
+ }
+
+ /* Create a TCG SWID Request attribute */
+ 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");
+ swid_state->set_missing(swid_state, tag_id_count);
+
+ 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);
+ cast_attr = (tcg_swid_attr_req_t*)attr;
+ cast_attr->add_target(cast_attr, tag_id);
+ }
+ json_object_put(jresponse);
+
+ out_msg->add_attribute(out_msg, attr);
+ break;
+ case FAILED:
+ default:
+ break;
+ }
+
+ if (status == FAILED)
+ {
+ enumerator = session->create_workitem_enumerator(session);
+ while (enumerator->enumerate(enumerator, &workitem))
+ {
+ if (workitem->get_type(workitem) == IMV_WORKITEM_SWID_TAGS)
+ {
+ session->remove_workitem(session, enumerator);
+ eval = TNC_IMV_EVALUATION_RESULT_ERROR;
+ rec = workitem->set_result(workitem, error_str, eval);
+ state->update_recommendation(state, rec, eval);
+ imcv_db->finalize_workitem(imcv_db, workitem);
+ workitem->destroy(workitem);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ }
+
+ /* finalized all workitems ? */
+ if (handshake_state == IMV_SWID_STATE_WORKITEMS &&
+ session->get_workitem_count(session, imv_id) == 0)
+ {
+ result = out_msg->send_assessment(out_msg);
+ out_msg->destroy(out_msg);
+ swid_state->set_handshake_state(swid_state, IMV_SWID_STATE_END);
+
+ if (result != TNC_RESULT_SUCCESS)
+ {
+ return result;
+ }
+ return this->agent->provide_recommendation(this->agent, state);
+ }
+
+ /* send non-empty PA-TNC message with excl flag not set */
+ if (out_msg->get_attribute_count(out_msg))
+ {
+ result = out_msg->send(out_msg, FALSE);
+ }
+ out_msg->destroy(out_msg);
+
+ return result;
+}
+
+METHOD(imv_agent_if_t, solicit_recommendation, TNC_Result,
+ private_imv_swid_agent_t *this, TNC_ConnectionID id)
+{
+ imv_state_t *state;
+
+ if (!this->agent->get_state(this->agent, id, &state))
+ {
+ return TNC_RESULT_FATAL;
+ }
+ return this->agent->provide_recommendation(this->agent, state);
+}
+
+METHOD(imv_agent_if_t, destroy, void,
+ private_imv_swid_agent_t *this)
+{
+ DESTROY_IF(this->rest_api);
+ this->agent->destroy(this->agent);
+ free(this);
+}
+
+/**
+ * Described in header.
+ */
+imv_agent_if_t *imv_swid_agent_create(const char *name, TNC_IMVID id,
+ TNC_Version *actual_version)
+{
+ private_imv_swid_agent_t *this;
+ imv_agent_t *agent;
+ char *rest_api_uri;
+ u_int rest_api_timeout;
+
+ agent = imv_agent_create(name, msg_types, countof(msg_types), id,
+ actual_version);
+ if (!agent)
+ {
+ return NULL;
+ }
+ agent->add_non_fatal_attr_type(agent,
+ pen_type_create(PEN_TCG, TCG_SEG_MAX_ATTR_SIZE_REQ));
+
+ INIT(this,
+ .public = {
+ .bind_functions = _bind_functions,
+ .notify_connection_change = _notify_connection_change,
+ .receive_message = _receive_message,
+ .receive_message_long = _receive_message_long,
+ .batch_ending = _batch_ending,
+ .solicit_recommendation = _solicit_recommendation,
+ .destroy = _destroy,
+ },
+ .agent = agent,
+ );
+
+ rest_api_uri = lib->settings->get_str(lib->settings,
+ "%s.plugins.imv-swid.rest_api_uri", NULL, lib->ns);
+ rest_api_timeout = lib->settings->get_int(lib->settings,
+ "%s.plugins.imv-swid.rest_api_timeout", 120, lib->ns);
+ if (rest_api_uri)
+ {
+ this->rest_api = imv_swid_rest_create(rest_api_uri, rest_api_timeout);
+ }
+
+ return &this->public;
+}
+
diff --git a/src/libimcv/plugins/imv_swid/imv_swid_agent.h b/src/libimcv/plugins/imv_swid/imv_swid_agent.h
new file mode 100644
index 000000000..4218040bc
--- /dev/null
+++ b/src/libimcv/plugins/imv_swid/imv_swid_agent.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2013 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup imv_swid_agent_t imv_swid_agent
+ * @{ @ingroup imv_swid
+ */
+
+#ifndef IMV_SWID_AGENT_H_
+#define IMV_SWID_AGENT_H_
+
+#include <imv/imv_agent_if.h>
+
+/**
+ * Creates an SWID IMV agent
+ *
+ * @param name Name of the IMV
+ * @param id ID of the IMV
+ * @param actual_version TNC IF-IMV version
+ */
+imv_agent_if_t* imv_swid_agent_create(const char* name, TNC_IMVID id,
+ TNC_Version *actual_version);
+
+#endif /** IMV_SWID_AGENT_H_ @}*/
diff --git a/src/libimcv/plugins/imv_swid/imv_swid_rest.c b/src/libimcv/plugins/imv_swid/imv_swid_rest.c
new file mode 100644
index 000000000..143b0b239
--- /dev/null
+++ b/src/libimcv/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/libimcv/plugins/imv_swid/imv_swid_rest.h b/src/libimcv/plugins/imv_swid/imv_swid_rest.h
new file mode 100644
index 000000000..32392cbe6
--- /dev/null
+++ b/src/libimcv/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.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/libimcv/plugins/imv_swid/imv_swid_state.c b/src/libimcv/plugins/imv_swid/imv_swid_state.c
new file mode 100644
index 000000000..04364b030
--- /dev/null
+++ b/src/libimcv/plugins/imv_swid/imv_swid_state.c
@@ -0,0 +1,402 @@
+/*
+ * Copyright (C) 2013-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "imv_swid_state.h"
+
+#include <imv/imv_lang_string.h>
+#include <imv/imv_reason_string.h>
+#include <imv/imv_remediation_string.h>
+#include <swid/swid_tag_id.h>
+
+#include <tncif_policy.h>
+
+#include <utils/lexparser.h>
+#include <utils/debug.h>
+
+typedef struct private_imv_swid_state_t private_imv_swid_state_t;
+
+/**
+ * Private data of an imv_swid_state_t object.
+ */
+struct private_imv_swid_state_t {
+
+ /**
+ * Public members of imv_swid_state_t
+ */
+ imv_swid_state_t public;
+
+ /**
+ * TNCCS connection ID
+ */
+ TNC_ConnectionID connection_id;
+
+ /**
+ * TNCCS connection state
+ */
+ TNC_ConnectionState state;
+
+ /**
+ * Does the TNCCS connection support long message types?
+ */
+ bool has_long;
+
+ /**
+ * Does the TNCCS connection support exclusive delivery?
+ */
+ bool has_excl;
+
+ /**
+ * Maximum PA-TNC message size for this TNCCS connection
+ */
+ uint32_t max_msg_len;
+
+ /**
+ * Flags set for completed actions
+ */
+ uint32_t action_flags;
+
+ /**
+ * IMV database session associated with TNCCS connection
+ */
+ imv_session_t *session;
+
+ /**
+ * PA-TNC attribute segmentation contracts associated with TNCCS connection
+ */
+ seg_contract_manager_t *contracts;
+
+ /**
+ * IMV action recommendation
+ */
+ TNC_IMV_Action_Recommendation rec;
+
+ /**
+ * IMV evaluation result
+ */
+ TNC_IMV_Evaluation_Result eval;
+
+ /**
+ * IMV Scanner handshake state
+ */
+ imv_swid_handshake_state_t handshake_state;
+
+ /**
+ * TNC Reason String
+ */
+ imv_reason_string_t *reason_string;
+
+ /**
+ * IETF Remediation Instructions String
+ */
+ imv_remediation_string_t *remediation_string;
+
+ /**
+ * SWID Tag Request ID
+ */
+ uint32_t request_id;
+
+ /**
+ * Number of processed SWID Tag IDs
+ */
+ int tag_id_count;
+
+ /**
+ * Number of processed SWID Tags
+ */
+ int tag_count;
+
+ /**
+ * Number of missing SWID Tags or Tag IDs
+ */
+ uint32_t missing;
+
+ /**
+ * Top level JSON object
+ */
+ json_object *jobj;
+
+ /**
+ * JSON array containing an inventory of SWID Tag IDs
+ */
+ json_object *jarray;
+
+};
+
+METHOD(imv_state_t, get_connection_id, TNC_ConnectionID,
+ private_imv_swid_state_t *this)
+{
+ return this->connection_id;
+}
+
+METHOD(imv_state_t, has_long, bool,
+ private_imv_swid_state_t *this)
+{
+ return this->has_long;
+}
+
+METHOD(imv_state_t, has_excl, bool,
+ private_imv_swid_state_t *this)
+{
+ return this->has_excl;
+}
+
+METHOD(imv_state_t, set_flags, void,
+ private_imv_swid_state_t *this, bool has_long, bool has_excl)
+{
+ this->has_long = has_long;
+ this->has_excl = has_excl;
+}
+
+METHOD(imv_state_t, set_max_msg_len, void,
+ private_imv_swid_state_t *this, uint32_t max_msg_len)
+{
+ this->max_msg_len = max_msg_len;
+}
+
+METHOD(imv_state_t, get_max_msg_len, uint32_t,
+ private_imv_swid_state_t *this)
+{
+ return this->max_msg_len;
+}
+
+METHOD(imv_state_t, set_action_flags, void,
+ private_imv_swid_state_t *this, uint32_t flags)
+{
+ this->action_flags |= flags;
+}
+
+METHOD(imv_state_t, get_action_flags, uint32_t,
+ private_imv_swid_state_t *this)
+{
+ return this->action_flags;
+}
+
+METHOD(imv_state_t, set_session, void,
+ private_imv_swid_state_t *this, imv_session_t *session)
+{
+ this->session = session;
+}
+
+METHOD(imv_state_t, get_session, imv_session_t*,
+ private_imv_swid_state_t *this)
+{
+ return this->session;
+}
+
+METHOD(imv_state_t, get_contracts, seg_contract_manager_t*,
+ private_imv_swid_state_t *this)
+{
+ return this->contracts;
+}
+
+METHOD(imv_state_t, change_state, void,
+ private_imv_swid_state_t *this, TNC_ConnectionState new_state)
+{
+ this->state = new_state;
+}
+
+METHOD(imv_state_t, get_recommendation, void,
+ private_imv_swid_state_t *this, TNC_IMV_Action_Recommendation *rec,
+ TNC_IMV_Evaluation_Result *eval)
+{
+ *rec = this->rec;
+ *eval = this->eval;
+}
+
+METHOD(imv_state_t, set_recommendation, void,
+ private_imv_swid_state_t *this, TNC_IMV_Action_Recommendation rec,
+ TNC_IMV_Evaluation_Result eval)
+{
+ this->rec = rec;
+ this->eval = eval;
+}
+
+METHOD(imv_state_t, update_recommendation, void,
+ private_imv_swid_state_t *this, TNC_IMV_Action_Recommendation rec,
+ TNC_IMV_Evaluation_Result eval)
+{
+ this->rec = tncif_policy_update_recommendation(this->rec, rec);
+ this->eval = tncif_policy_update_evaluation(this->eval, eval);
+}
+
+METHOD(imv_state_t, get_reason_string, bool,
+ private_imv_swid_state_t *this, enumerator_t *language_enumerator,
+ chunk_t *reason_string, char **reason_language)
+{
+ return FALSE;
+}
+
+METHOD(imv_state_t, get_remediation_instructions, bool,
+ private_imv_swid_state_t *this, enumerator_t *language_enumerator,
+ chunk_t *string, char **lang_code, char **uri)
+{
+ return FALSE;
+}
+
+METHOD(imv_state_t, destroy, void,
+ private_imv_swid_state_t *this)
+{
+ json_object_put(this->jobj);
+ DESTROY_IF(this->session);
+ DESTROY_IF(this->reason_string);
+ DESTROY_IF(this->remediation_string);
+ this->contracts->destroy(this->contracts);
+ free(this);
+}
+
+METHOD(imv_swid_state_t, set_handshake_state, void,
+ private_imv_swid_state_t *this, imv_swid_handshake_state_t new_state)
+{
+ this->handshake_state = new_state;
+}
+
+METHOD(imv_swid_state_t, get_handshake_state, imv_swid_handshake_state_t,
+ private_imv_swid_state_t *this)
+{
+ return this->handshake_state;
+}
+
+METHOD(imv_swid_state_t, set_request_id, void,
+ private_imv_swid_state_t *this, uint32_t request_id)
+{
+ this->request_id = request_id;
+}
+
+METHOD(imv_swid_state_t, get_request_id, uint32_t,
+ private_imv_swid_state_t *this)
+{
+ return this->request_id;
+}
+
+METHOD(imv_swid_state_t, set_swid_inventory, void,
+ private_imv_swid_state_t *this, swid_inventory_t *inventory)
+{
+ chunk_t tag_creator, unique_sw_id;
+ char software_id[256];
+ json_object *jstring;
+ swid_tag_id_t *tag_id;
+ enumerator_t *enumerator;
+
+ enumerator = inventory->create_enumerator(inventory);
+ while (enumerator->enumerate(enumerator, &tag_id))
+ {
+ /* Construct software ID from tag creator and unique software ID */
+ tag_creator = tag_id->get_tag_creator(tag_id);
+ unique_sw_id = tag_id->get_unique_sw_id(tag_id, NULL);
+ snprintf(software_id, 256, "%.*s_%.*s",
+ tag_creator.len, tag_creator.ptr,
+ unique_sw_id.len, unique_sw_id.ptr);
+ DBG3(DBG_IMV, " %s", software_id);
+
+ /* Add software ID to JSON array */
+ jstring = json_object_new_string(software_id);
+ json_object_array_add(this->jarray, jstring);
+ }
+ enumerator->destroy(enumerator);
+}
+
+METHOD(imv_swid_state_t, get_swid_inventory, json_object*,
+ private_imv_swid_state_t *this)
+{
+ return this->jobj;
+}
+
+METHOD(imv_swid_state_t, set_missing, void,
+ private_imv_swid_state_t *this, uint32_t count)
+{
+ this->missing = count;
+}
+
+METHOD(imv_swid_state_t, get_missing, uint32_t,
+ private_imv_swid_state_t *this)
+{
+ return this->missing;
+}
+
+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;
+ }
+}
+
+/**
+ * Described in header.
+ */
+imv_state_t *imv_swid_state_create(TNC_ConnectionID connection_id)
+{
+ private_imv_swid_state_t *this;
+
+ INIT(this,
+ .public = {
+ .interface = {
+ .get_connection_id = _get_connection_id,
+ .has_long = _has_long,
+ .has_excl = _has_excl,
+ .set_flags = _set_flags,
+ .set_max_msg_len = _set_max_msg_len,
+ .get_max_msg_len = _get_max_msg_len,
+ .set_action_flags = _set_action_flags,
+ .get_action_flags = _get_action_flags,
+ .set_session = _set_session,
+ .get_session= _get_session,
+ .get_contracts = _get_contracts,
+ .change_state = _change_state,
+ .get_recommendation = _get_recommendation,
+ .set_recommendation = _set_recommendation,
+ .update_recommendation = _update_recommendation,
+ .get_reason_string = _get_reason_string,
+ .get_remediation_instructions = _get_remediation_instructions,
+ .destroy = _destroy,
+ },
+ .set_handshake_state = _set_handshake_state,
+ .get_handshake_state = _get_handshake_state,
+ .set_request_id = _set_request_id,
+ .get_request_id = _get_request_id,
+ .set_swid_inventory = _set_swid_inventory,
+ .get_swid_inventory = _get_swid_inventory,
+ .set_missing = _set_missing,
+ .get_missing = _get_missing,
+ .set_count = _set_count,
+ .get_count = _get_count,
+ },
+ .state = TNC_CONNECTION_STATE_CREATE,
+ .rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
+ .eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW,
+ .connection_id = connection_id,
+ .contracts = seg_contract_manager_create(),
+ .jobj = json_object_new_object(),
+ .jarray = json_object_new_array(),
+ );
+
+ json_object_object_add(this->jobj, "data", this->jarray);
+
+ return &this->public.interface;
+}
+
+
diff --git a/src/libimcv/plugins/imv_swid/imv_swid_state.h b/src/libimcv/plugins/imv_swid/imv_swid_state.h
new file mode 100644
index 000000000..af5d95c9d
--- /dev/null
+++ b/src/libimcv/plugins/imv_swid/imv_swid_state.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2013-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup imv_swid imv_swid
+ * @ingroup libimcv_plugins
+ *
+ * @defgroup imv_swid_state_t imv_swid_state
+ * @{ @ingroup imv_swid
+ */
+
+#ifndef IMV_SWID_STATE_H_
+#define IMV_SWID_STATE_H_
+
+#include <imv/imv_state.h>
+#include <swid/swid_inventory.h>
+#include <library.h>
+
+#include <json.h>
+
+typedef struct imv_swid_state_t imv_swid_state_t;
+typedef enum imv_swid_handshake_state_t imv_swid_handshake_state_t;
+
+/**
+ * IMV OS Handshake States (state machine)
+ */
+enum imv_swid_handshake_state_t {
+ IMV_SWID_STATE_INIT,
+ IMV_SWID_STATE_WORKITEMS,
+ IMV_SWID_STATE_END
+};
+
+/**
+ * Internal state of an imv_swid_t connection instance
+ */
+struct imv_swid_state_t {
+
+ /**
+ * imv_state_t interface
+ */
+ imv_state_t interface;
+
+ /**
+ * Set state of the handshake
+ *
+ * @param new_state the handshake state of IMV
+ */
+ void (*set_handshake_state)(imv_swid_state_t *this,
+ imv_swid_handshake_state_t new_state);
+
+ /**
+ * Get state of the handshake
+ *
+ * @return the handshake state of IMV
+ */
+ imv_swid_handshake_state_t (*get_handshake_state)(imv_swid_state_t *this);
+
+ /**
+ * Set the SWID request ID
+ *
+ * @param request_id SWID request ID to be set
+ */
+ void (*set_request_id)(imv_swid_state_t *this, uint32_t request_id);
+
+ /**
+ * Get the SWID request ID
+ *
+ * @return SWID request ID
+ */
+ uint32_t (*get_request_id)(imv_swid_state_t *this);
+
+ /**
+ * Set or extend the SWID Tag ID inventory in the state
+ *
+ * @param inventory SWID Tags ID inventory to be added
+ */
+ void (*set_swid_inventory)(imv_swid_state_t *this, swid_inventory_t *inventory);
+
+ /**
+ * Get the encoding of the complete SWID Tag ID inventory
+ *
+ * @return SWID Tags ID inventory as a JSON array
+ */
+ json_object* (*get_swid_inventory)(imv_swid_state_t *this);
+
+ /**
+ * Set the number of still missing SWID Tags or Tag IDs
+ *
+ * @param count Number of missing SWID Tags or Tag IDs
+ */
+ void (*set_missing)(imv_swid_state_t *this, uint32_t count);
+
+ /**
+ * Get the number of still missing SWID Tags or Tag IDs
+ *
+ * @result Number of missing SWID Tags or Tag IDs
+ */
+ uint32_t (*get_missing)(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);
+};
+
+/**
+ * Create an imv_swid_state_t instance
+ *
+ * @param id connection ID
+ */
+imv_state_t* imv_swid_state_create(TNC_ConnectionID id);
+
+#endif /** IMV_SWID_STATE_H_ @}*/
diff --git a/src/libimcv/plugins/imv_test/Makefile.in b/src/libimcv/plugins/imv_test/Makefile.in
index 5ac6a8f7b..66da75a1e 100644
--- a/src/libimcv/plugins/imv_test/Makefile.in
+++ b/src/libimcv/plugins/imv_test/Makefile.in
@@ -231,6 +231,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -291,6 +292,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -356,6 +358,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -403,6 +407,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libimcv/plugins/imv_test/imv_test_agent.c b/src/libimcv/plugins/imv_test/imv_test_agent.c
index 42630003b..5e4b4866a 100644
--- a/src/libimcv/plugins/imv_test/imv_test_agent.c
+++ b/src/libimcv/plugins/imv_test/imv_test_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
@@ -94,10 +94,14 @@ static TNC_Result receive_msg(private_imv_test_agent_t *this, imv_state_t *state
int rounds;
bool fatal_error = FALSE, received_command = FALSE, retry = FALSE;
+ /* generate an outgoing PA-TNC message - we might need it */
+ out_msg = imv_msg_create_as_reply(in_msg);
+
/* parse received PA-TNC message and handle local and remote errors */
- result = in_msg->receive(in_msg, &fatal_error);
+ result = in_msg->receive(in_msg, out_msg, &fatal_error);
if (result != TNC_RESULT_SUCCESS)
{
+ out_msg->destroy(out_msg);
return result;
}
@@ -172,14 +176,12 @@ static TNC_Result receive_msg(private_imv_test_agent_t *this, imv_state_t *state
state->set_recommendation(state,
TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
TNC_IMV_EVALUATION_RESULT_ERROR);
- out_msg = imv_msg_create_as_reply(in_msg);
result = out_msg->send_assessment(out_msg);
- out_msg->destroy(out_msg);
- if (result != TNC_RESULT_SUCCESS)
+ if (result == TNC_RESULT_SUCCESS)
{
- return result;
+ result = this->agent->provide_recommendation(this->agent, state);
}
- return this->agent->provide_recommendation(this->agent, state);
+ return result;
}
/* request a handshake retry ? */
@@ -195,7 +197,6 @@ static TNC_Result receive_msg(private_imv_test_agent_t *this, imv_state_t *state
/* repeat the measurement ? */
if (test_state->another_round(test_state, in_msg->get_src_id(in_msg)))
{
- out_msg = imv_msg_create_as_reply(in_msg);
attr = ita_attr_command_create("repeat");
out_msg->add_attribute(out_msg, attr);
@@ -208,19 +209,20 @@ static TNC_Result receive_msg(private_imv_test_agent_t *this, imv_state_t *state
if (received_command)
{
- out_msg = imv_msg_create_as_reply(in_msg);
result = out_msg->send_assessment(out_msg);
- out_msg->destroy(out_msg);
- if (result != TNC_RESULT_SUCCESS)
+ if (result == TNC_RESULT_SUCCESS)
{
- return result;
+ result = this->agent->provide_recommendation(this->agent, state);
}
- return this->agent->provide_recommendation(this->agent, state);
}
else
{
- return TNC_RESULT_SUCCESS;
+ /* send PA-TNC message with the EXCL flag set */
+ result = out_msg->send(out_msg, TRUE);
}
+ out_msg->destroy(out_msg);
+
+ return result;
}
METHOD(imv_agent_if_t, receive_message, TNC_Result,
diff --git a/src/libimcv/plugins/imv_test/imv_test_state.c b/src/libimcv/plugins/imv_test/imv_test_state.c
index 3564456a8..c20d00bd1 100644
--- a/src/libimcv/plugins/imv_test/imv_test_state.c
+++ b/src/libimcv/plugins/imv_test/imv_test_state.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
@@ -66,6 +66,11 @@ struct private_imv_test_state_t {
imv_session_t *session;
/**
+ * PA-TNC attribute segmentation contracts associated with TNCCS connection
+ */
+ seg_contract_manager_t *contracts;
+
+ /**
* IMV action recommendation
*/
TNC_IMV_Action_Recommendation rec;
@@ -162,6 +167,12 @@ METHOD(imv_state_t, get_session, imv_session_t*,
return this->session;
}
+METHOD(imv_state_t, get_contracts, seg_contract_manager_t*,
+ private_imv_test_state_t *this)
+{
+ return this->contracts;
+}
+
METHOD(imv_state_t, change_state, void,
private_imv_test_state_t *this, TNC_ConnectionState new_state)
{
@@ -220,6 +231,7 @@ METHOD(imv_state_t, destroy, void,
{
DESTROY_IF(this->session);
DESTROY_IF(this->reason_string);
+ this->contracts->destroy(this->contracts);
this->imcs->destroy_function(this->imcs, free);
free(this);
}
@@ -307,6 +319,7 @@ imv_state_t *imv_test_state_create(TNC_ConnectionID connection_id)
.get_max_msg_len = _get_max_msg_len,
.set_session = _set_session,
.get_session = _get_session,
+ .get_contracts = _get_contracts,
.change_state = _change_state,
.get_recommendation = _get_recommendation,
.set_recommendation = _set_recommendation,
@@ -323,6 +336,7 @@ imv_state_t *imv_test_state_create(TNC_ConnectionID connection_id)
.rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
.eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW,
.connection_id = connection_id,
+ .contracts = seg_contract_manager_create(),
.imcs = linked_list_create(),
);
diff --git a/src/libimcv/pts/components/ita/ita_comp_func_name.c b/src/libimcv/pts/components/ita/ita_comp_func_name.c
new file mode 100644
index 000000000..a593281ba
--- /dev/null
+++ b/src/libimcv/pts/components/ita/ita_comp_func_name.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2011 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "ita_comp_func_name.h"
+
+char pts_ita_qualifier_flag_names[] = { 'K', 'S' };
+
+ENUM_BEGIN(pts_ita_qualifier_type_names, PTS_ITA_QUALIFIER_TYPE_UNKNOWN,
+ PTS_ITA_QUALIFIER_TYPE_TNC,
+ "Unknown",
+ "Trusted Platform",
+ "Operating System",
+ "Graphical User Interface",
+ "Application",
+ "Networking",
+ "Library",
+ "TNC Defined Component"
+);
+ENUM_NEXT(pts_ita_qualifier_type_names, PTS_ITA_QUALIFIER_TYPE_ALL,
+ PTS_ITA_QUALIFIER_TYPE_ALL,
+ PTS_ITA_QUALIFIER_TYPE_TNC,
+ "All Matching Components"
+);
+ENUM_END(pts_ita_qualifier_type_names, PTS_ITA_QUALIFIER_TYPE_ALL);
+
+ENUM(pts_ita_comp_func_names, PTS_ITA_COMP_FUNC_NAME_IGNORE,
+ PTS_ITA_COMP_FUNC_NAME_IMA,
+ "Ignore",
+ "Trusted GRUB Boot Loader",
+ "Trusted Boot",
+ "Linux IMA"
+);
+
diff --git a/src/libimcv/pts/components/ita/ita_comp_func_name.h b/src/libimcv/pts/components/ita/ita_comp_func_name.h
new file mode 100644
index 000000000..eb2f363f3
--- /dev/null
+++ b/src/libimcv/pts/components/ita/ita_comp_func_name.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts_ita_comp_func_name pts_ita_comp_func_name
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_ITA_COMP_FUNC_NAME_H_
+#define PTS_ITA_COMP_FUNC_NAME_H_
+
+typedef enum pts_ita_qualifier_type_t pts_ita_qualifier_type_t;
+typedef enum pts_ita_comp_func_name_t pts_ita_comp_func_name_t;
+
+#include <library.h>
+
+/**
+ * PTS Component Functional Name Qualifier Flags for the ITA namespace
+ */
+#define PTS_ITA_QUALIFIER_FLAG_KERNEL (1<<5)
+#define PTS_ITA_QUALIFIER_FLAG_SUB (1<<4)
+
+extern char pts_ita_qualifier_flag_names[];
+
+/**
+ * Size of the PTS Component Functional Name Qualifier Type field
+ */
+#define PTS_ITA_QUALIFIER_TYPE_SIZE 4
+
+/**
+ * PTS Component Functional Name Qualifier Types for the ITA namespace
+ * equal to section 5.2 of PTS Protocol: Binding to TNC IF-M Specification
+ */
+enum pts_ita_qualifier_type_t {
+ /** Unknown */
+ PTS_ITA_QUALIFIER_TYPE_UNKNOWN = 0x0,
+ /** Trusted Platform */
+ PTS_ITA_QUALIFIER_TYPE_TRUSTED = 0x1,
+ /** Operating System */
+ PTS_ITA_QUALIFIER_TYPE_OS = 0x2,
+ /** Graphical User Interface */
+ PTS_ITA_QUALIFIER_TYPE_GUI = 0x3,
+ /** Application */
+ PTS_ITA_QUALIFIER_TYPE_APP = 0x4,
+ /** Networking */
+ PTS_ITA_QUALIFIER_TYPE_NET = 0x5,
+ /** Library */
+ PTS_ITA_QUALIFIER_TYPE_LIB = 0x6,
+ /** TNC Defined Component */
+ PTS_ITA_QUALIFIER_TYPE_TNC = 0x7,
+ /** All Matching Components */
+ PTS_ITA_QUALIFIER_TYPE_ALL = 0xF,
+};
+
+extern enum_name_t *pts_ita_qualifier_type_names;
+
+/**
+ * PTS Component Functional Name Binary Enumeration for the ITA namespace
+ */
+enum pts_ita_comp_func_name_t {
+ /** Ignore */
+ PTS_ITA_COMP_FUNC_NAME_IGNORE = 0x0000,
+ /** Trusted GRUB Boot Loader */
+ PTS_ITA_COMP_FUNC_NAME_TGRUB = 0x0001,
+ /** Trusted Boot */
+ PTS_ITA_COMP_FUNC_NAME_TBOOT = 0x0002,
+ /** Linux Integrity Measurement Architecture */
+ PTS_ITA_COMP_FUNC_NAME_IMA = 0x0003,
+};
+
+extern enum_name_t *pts_ita_comp_func_names;
+
+#endif /** PTS_ITA_COMP_FUNC_NAME_H_ @}*/
diff --git a/src/libimcv/pts/components/ita/ita_comp_ima.c b/src/libimcv/pts/components/ita/ita_comp_ima.c
new file mode 100644
index 000000000..3f92b04b1
--- /dev/null
+++ b/src/libimcv/pts/components/ita/ita_comp_ima.c
@@ -0,0 +1,914 @@
+/*
+ * Copyright (C) 2011-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "ita_comp_ima.h"
+#include "ita_comp_func_name.h"
+
+#include "imcv.h"
+#include "pts/pts_pcr.h"
+#include "pts/pts_ima_bios_list.h"
+#include "pts/pts_ima_event_list.h"
+#include "pts/components/pts_component.h"
+
+#include <utils/debug.h>
+#include <crypto/hashers/hasher.h>
+#include <pen/pen.h>
+
+#define SECURITY_DIR "/sys/kernel/security/"
+#define IMA_BIOS_MEASUREMENTS SECURITY_DIR "tpm0/binary_bios_measurements"
+#define IMA_RUNTIME_MEASUREMENTS SECURITY_DIR "ima/binary_runtime_measurements"
+#define IMA_FILENAME_LEN_MAX 255
+
+typedef struct pts_ita_comp_ima_t pts_ita_comp_ima_t;
+typedef enum ima_state_t ima_state_t;
+
+enum ima_state_t {
+ IMA_STATE_INIT,
+ IMA_STATE_BIOS,
+ IMA_STATE_BOOT_AGGREGATE,
+ IMA_STATE_RUNTIME,
+ IMA_STATE_END
+};
+
+/**
+ * Private data of a pts_ita_comp_ima_t object.
+ *
+ */
+struct pts_ita_comp_ima_t {
+
+ /**
+ * Public pts_component_t interface.
+ */
+ pts_component_t public;
+
+ /**
+ * Component Functional Name
+ */
+ pts_comp_func_name_t *name;
+
+ /**
+ * Sub-component depth
+ */
+ uint32_t depth;
+
+ /**
+ * PTS measurement database
+ */
+ pts_database_t *pts_db;
+
+ /**
+ * Primary key for AIK database entry
+ */
+ int aik_id;
+
+ /**
+ * Primary key for IMA BIOS Component Functional Name database entry
+ */
+ int bios_cid;
+
+ /**
+ * Primary key for IMA Runtime Component Functional Name database entry
+ */
+ int ima_cid;
+
+ /**
+ * Component is registering IMA BIOS measurements
+ */
+ bool is_bios_registering;
+
+ /**
+ * Component is registering IMA boot aggregate measurement
+ */
+ bool is_ima_registering;
+
+ /**
+ * Measurement sequence number
+ */
+ int seq_no;
+
+ /**
+ * Expected IMA BIOS measurement count
+ */
+ int bios_count;
+
+ /**
+ * IMA BIOS measurements
+ */
+ pts_ima_bios_list_t *bios_list;
+
+ /**
+ * IMA runtime file measurements
+ */
+ pts_ima_event_list_t *ima_list;
+
+ /**
+ * Whether to send pcr_before and pcr_after info
+ */
+ bool pcr_info;
+
+ /**
+ * Creation time of measurement
+ */
+ time_t creation_time;
+
+ /**
+ * IMA state machine
+ */
+ ima_state_t state;
+
+ /**
+ * Total number of component measurements
+ */
+ int count;
+
+ /**
+ * Number of successful component measurements
+ */
+ int count_ok;
+
+ /**
+ * Number of unknown component measurements
+ */
+ int count_unknown;
+
+ /**
+ * Number of differing component measurements
+ */
+ int count_differ;
+
+ /**
+ * Number of failed component measurements
+ */
+ int count_failed;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+
+};
+
+/**
+ * Extend measurement into PCR and create evidence
+ */
+static pts_comp_evidence_t* extend_pcr(pts_ita_comp_ima_t* this,
+ uint8_t qualifier, pts_pcr_t *pcrs,
+ uint32_t pcr, chunk_t measurement)
+{
+ size_t pcr_len;
+ pts_pcr_transform_t pcr_transform;
+ pts_meas_algorithms_t hash_algo;
+ pts_comp_func_name_t *name;
+ pts_comp_evidence_t *evidence;
+ chunk_t pcr_before = chunk_empty, pcr_after = chunk_empty;
+
+ hash_algo = PTS_MEAS_ALGO_SHA1;
+ pcr_len = HASH_SIZE_SHA1;
+ pcr_transform = pts_meas_algo_to_pcr_transform(hash_algo, pcr_len);
+
+ if (this->pcr_info)
+ {
+ pcr_before = chunk_clone(pcrs->get(pcrs, pcr));
+ }
+ pcr_after = pcrs->extend(pcrs, pcr, measurement);
+ if (!pcr_after.ptr)
+ {
+ free(pcr_before.ptr);
+ return NULL;
+ }
+ name = this->name->clone(this->name);
+ name->set_qualifier(name, qualifier);
+ evidence = pts_comp_evidence_create(name, this->depth, pcr, hash_algo,
+ pcr_transform, this->creation_time, measurement);
+ if (this->pcr_info)
+ {
+ pcr_after =chunk_clone(pcrs->get(pcrs, pcr));
+ evidence->set_pcr_info(evidence, pcr_before, pcr_after);
+ }
+ return evidence;
+}
+
+/**
+ * Generate an IMA or IMA-NG hash from an event digest and event name
+ *
+ * @param digest event digest
+ * @param ima_algo hash algorithm string ("sha1:", "sha256:", etc.)
+ * @param ima_name event name
+ * @param little_endian endianness of client platform
+ * @param algo hash algorithm used by TPM
+ * @param hash_buf hash value to be compared with TPM measurement
+ */
+static bool ima_hash(chunk_t digest, char *ima_algo, char *ima_name,
+ bool little_endian, pts_meas_algorithms_t algo,
+ char *hash_buf)
+{
+ hash_algorithm_t hash_alg;
+ hasher_t *hasher;
+ bool success;
+
+ hash_alg = pts_meas_algo_to_hash(algo);
+ hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
+ if (!hasher)
+ {
+ DBG1(DBG_PTS, "%N hasher could not be created",
+ hash_algorithm_short_names, hash_alg);
+ return FALSE;
+ }
+
+ if (ima_algo)
+ {
+ uint32_t d_len, n_len;
+ chunk_t algo_name, event_name, digest_len, name_len;
+
+ /* IMA-NG hash */
+ algo_name = chunk_create(ima_algo, strlen(ima_algo) + 1);
+ event_name = chunk_create(ima_name, strlen(ima_name) + 1);
+
+ d_len = algo_name.len + digest.len;
+ digest_len = chunk_create((uint8_t*)&d_len, sizeof(d_len));
+ /* TODO handle endianness of both client and server platforms */
+
+ n_len = event_name.len;
+ name_len = chunk_create((uint8_t*)&n_len, sizeof(n_len));
+ /* TODO handle endianness of both client and server platforms */
+
+ success = hasher->get_hash(hasher, digest_len, NULL) &&
+ hasher->get_hash(hasher, algo_name, NULL) &&
+ hasher->get_hash(hasher, digest, NULL) &&
+ hasher->get_hash(hasher, name_len, NULL) &&
+ hasher->get_hash(hasher, event_name, hash_buf);
+ }
+ else
+ {
+ u_char filename_buffer[IMA_FILENAME_LEN_MAX + 1];
+ chunk_t file_name;
+
+ /* IMA legacy hash */
+ memset(filename_buffer, 0, sizeof(filename_buffer));
+ strncpy(filename_buffer, ima_name, IMA_FILENAME_LEN_MAX);
+ file_name = chunk_create (filename_buffer, sizeof(filename_buffer));
+
+ success = hasher->get_hash(hasher, digest, NULL) &&
+ hasher->get_hash(hasher, file_name, hash_buf);
+ }
+ hasher->destroy(hasher);
+
+ return success;
+}
+
+/**
+ * Compute and check boot aggregate value by hashing PCR0 to PCR7
+ */
+static bool check_boot_aggregate(pts_pcr_t *pcrs, chunk_t measurement,
+ char *algo)
+{
+ u_char pcr_buffer[HASH_SIZE_SHA1];
+ chunk_t boot_aggregate;
+ hasher_t *hasher;
+ uint32_t i;
+ bool success, pcr_ok = TRUE;
+
+ hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
+ if (!hasher)
+ {
+ DBG1(DBG_PTS, "%N hasher could not be created",
+ hash_algorithm_short_names, HASH_SHA1);
+ return FALSE;
+ }
+ for (i = 0; i < 8 && pcr_ok; i++)
+ {
+ pcr_ok = hasher->get_hash(hasher, pcrs->get(pcrs, i), NULL);
+ }
+ if (pcr_ok)
+ {
+ pcr_ok = hasher->get_hash(hasher, chunk_empty, pcr_buffer);
+ }
+ hasher->destroy(hasher);
+
+ if (pcr_ok)
+ {
+ boot_aggregate = chunk_create(pcr_buffer, sizeof(pcr_buffer));
+
+ /* TODO handle endianness of client platform */
+ pcr_ok = ima_hash(boot_aggregate, algo, "boot_aggregate",
+ TRUE, PTS_MEAS_ALGO_SHA1, pcr_buffer);
+ }
+ if (pcr_ok)
+ {
+ success = chunk_equals(boot_aggregate, measurement);
+ DBG1(DBG_PTS, "boot aggregate value is %scorrect",
+ success ? "":"in");
+ return success;
+ }
+ else
+ {
+ DBG1(DBG_PTS, "failed to compute boot aggregate value");
+ return FALSE;
+ }
+}
+
+METHOD(pts_component_t, get_comp_func_name, pts_comp_func_name_t*,
+ pts_ita_comp_ima_t *this)
+{
+ return this->name;
+}
+
+METHOD(pts_component_t, get_evidence_flags, uint8_t,
+ pts_ita_comp_ima_t *this)
+{
+ return PTS_REQ_FUNC_COMP_EVID_PCR;
+}
+
+METHOD(pts_component_t, get_depth, uint32_t,
+ pts_ita_comp_ima_t *this)
+{
+ return this->depth;
+}
+
+METHOD(pts_component_t, measure, status_t,
+ pts_ita_comp_ima_t *this, uint8_t qualifier, pts_t *pts,
+ pts_comp_evidence_t **evidence)
+{
+ pts_pcr_t *pcrs;
+ pts_comp_evidence_t *evid = NULL;
+ size_t algo_len, name_len;
+ chunk_t measurement;
+ char *uri, *algo, *name;
+ uint32_t pcr;
+ status_t status;
+
+ pcrs = pts->get_pcrs(pts);
+
+ if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
+ PTS_ITA_QUALIFIER_TYPE_TRUSTED))
+ {
+ switch (this->state)
+ {
+ case IMA_STATE_INIT:
+ this->bios_list = pts_ima_bios_list_create(
+ IMA_BIOS_MEASUREMENTS);
+ if (!this->bios_list)
+ {
+ return FAILED;
+ }
+ this->creation_time = this->bios_list->get_time(this->bios_list);
+ this->bios_count = this->bios_list->get_count(this->bios_list);
+ this->state = IMA_STATE_BIOS;
+ /* fall through to next state */
+ case IMA_STATE_BIOS:
+ status = this->bios_list->get_next(this->bios_list, &pcr,
+ &measurement);
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_PTS, "could not retrieve bios measurement entry");
+ return status;
+ }
+ evid = extend_pcr(this, qualifier, pcrs, pcr, measurement);
+
+ this->state = this->bios_list->get_count(this->bios_list) ?
+ IMA_STATE_BIOS : IMA_STATE_INIT;
+ break;
+ default:
+ return FAILED;
+ }
+ }
+ else if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
+ PTS_ITA_QUALIFIER_TYPE_OS))
+ {
+ switch (this->state)
+ {
+ case IMA_STATE_INIT:
+ this->ima_list = pts_ima_event_list_create(
+ IMA_RUNTIME_MEASUREMENTS);
+ if (!this->ima_list)
+ {
+ return FAILED;
+ }
+ this->creation_time = this->ima_list->get_time(this->ima_list);
+ this->count = this->ima_list->get_count(this->ima_list);
+ this->state = IMA_STATE_BOOT_AGGREGATE;
+ /* fall through to next state */
+ case IMA_STATE_BOOT_AGGREGATE:
+ case IMA_STATE_RUNTIME:
+ status = this->ima_list->get_next(this->ima_list, &measurement,
+ &algo, &name);
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_PTS, "could not retrieve ima measurement entry");
+ return status;
+ }
+ if (this->state == IMA_STATE_BOOT_AGGREGATE && this->bios_count)
+ {
+ if (!check_boot_aggregate(pcrs, measurement, algo))
+ {
+ return FAILED;
+ }
+ }
+ evid = extend_pcr(this, qualifier, pcrs, IMA_PCR,
+ measurement);
+ if (evid)
+ {
+ if (algo)
+ {
+ algo_len = strlen(algo);
+ name_len = strlen(name);
+ uri = malloc(algo_len + name_len + 1);
+ memcpy(uri, algo, algo_len);
+ strcpy(uri + algo_len, name);
+ }
+ else
+ {
+ uri = strdup(name);
+ }
+ evid->set_validation(evid, PTS_COMP_EVID_VALIDATION_PASSED,
+ uri);
+ free(uri);
+ }
+ free(name);
+ free(algo);
+
+ this->state = this->ima_list->get_count(this->ima_list) ?
+ IMA_STATE_RUNTIME : IMA_STATE_END;
+ break;
+ default:
+ return FAILED;
+ }
+ }
+ else
+ {
+ DBG1(DBG_PTS, "unsupported functional component name qualifier");
+ return FAILED;
+ }
+
+ *evidence = evid;
+ if (!evid)
+ {
+ return FAILED;
+ }
+
+ return (this->state == IMA_STATE_INIT || this->state == IMA_STATE_END) ?
+ SUCCESS : NEED_MORE;
+}
+
+/**
+ * Parse a validation URI of the form <hash algorithm>:<event name>
+ * into its components
+ */
+static pts_meas_algorithms_t parse_validation_uri(pts_comp_evidence_t *evidence,
+ char **ima_name, char **ima_algo, char *algo_buf)
+{
+ pts_meas_algorithms_t hash_algo;
+ char *uri, *pos, *algo, *name;
+
+ evidence->get_validation(evidence, &uri);
+
+ /* IMA-NG format? */
+ pos = strchr(uri, ':');
+ if (pos && (pos - uri + 1) < IMA_ALGO_LEN_MAX)
+ {
+ memset(algo_buf, '\0', IMA_ALGO_LEN_MAX);
+ memcpy(algo_buf, uri, pos - uri + 1);
+ algo = algo_buf;
+ name = pos + 1;
+
+ if (streq(algo, "sha1:") || streq(algo, ":"))
+ {
+ hash_algo = PTS_MEAS_ALGO_SHA1;
+ }
+ else if (streq(algo, "sha256:"))
+ {
+ hash_algo = PTS_MEAS_ALGO_SHA256;
+ }
+ else if (streq(algo, "sha384:"))
+ {
+ hash_algo = PTS_MEAS_ALGO_SHA384;
+ }
+ else
+ {
+ hash_algo = PTS_MEAS_ALGO_NONE;
+ }
+ }
+ else
+ {
+ algo = NULL;
+ name = uri;
+ hash_algo = PTS_MEAS_ALGO_SHA1;
+ }
+
+ if (ima_name)
+ {
+ *ima_name = name;
+ }
+ if (ima_algo)
+ {
+ *ima_algo = algo;
+ }
+
+ return hash_algo;
+}
+
+METHOD(pts_component_t, verify, status_t,
+ pts_ita_comp_ima_t *this, uint8_t qualifier, pts_t *pts,
+ pts_comp_evidence_t *evidence)
+{
+ bool has_pcr_info;
+ uint32_t pcr;
+ pts_meas_algorithms_t algo;
+ pts_pcr_transform_t transform;
+ pts_pcr_t *pcrs;
+ time_t creation_time;
+ chunk_t measurement, pcr_before, pcr_after;
+ status_t status = NOT_FOUND;
+
+ this->aik_id = pts->get_aik_id(pts);
+ pcrs = pts->get_pcrs(pts);
+ measurement = evidence->get_measurement(evidence, &pcr, &algo, &transform,
+ &creation_time);
+
+ if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
+ PTS_ITA_QUALIFIER_TYPE_TRUSTED))
+ {
+ switch (this->state)
+ {
+ case IMA_STATE_INIT:
+ this->name->set_qualifier(this->name, qualifier);
+ status = this->pts_db->get_comp_measurement_count(this->pts_db,
+ this->name, this->aik_id, algo,
+ &this->bios_cid, &this->bios_count);
+ this->name->set_qualifier(this->name, PTS_QUALIFIER_UNKNOWN);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+
+ if (this->bios_count)
+ {
+ DBG1(DBG_PTS, "checking %d BIOS evidence measurements",
+ this->bios_count);
+ }
+ else
+ {
+ DBG1(DBG_PTS, "registering BIOS evidence measurements");
+ this->is_bios_registering = TRUE;
+ }
+
+ this->state = IMA_STATE_BIOS;
+ /* fall through to next state */
+ case IMA_STATE_BIOS:
+ if (this->is_bios_registering)
+ {
+ status = this->pts_db->insert_comp_measurement(this->pts_db,
+ measurement, this->bios_cid, this->aik_id,
+ ++this->seq_no, pcr, algo);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+ this->bios_count = this->seq_no + 1;
+ }
+ else
+ {
+ status = this->pts_db->check_comp_measurement(this->pts_db,
+ measurement, this->bios_cid, this->aik_id,
+ ++this->seq_no, pcr, algo);
+ if (status == FAILED)
+ {
+ return status;
+ }
+ }
+ break;
+ default:
+ return FAILED;
+ }
+ }
+ else if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
+ PTS_ITA_QUALIFIER_TYPE_OS))
+ {
+ int ima_count;
+ char *ima_algo, *ima_name;
+ char algo_buf[IMA_ALGO_LEN_MAX];
+ pts_meas_algorithms_t hash_algo;
+
+ hash_algo = parse_validation_uri(evidence, &ima_name, &ima_algo,
+ algo_buf);
+
+ switch (this->state)
+ {
+ case IMA_STATE_BIOS:
+ this->state = IMA_STATE_RUNTIME;
+
+ if (!streq(ima_name, "boot_aggregate"))
+ {
+ DBG1(DBG_PTS, "ima: name must be 'boot_aggregate' "
+ "but is '%s'", ima_name);
+ return FAILED;
+ }
+ if (hash_algo != PTS_MEAS_ALGO_SHA1)
+ {
+ DBG1(DBG_PTS, "ima: boot_aggregate algorithm must be %N "
+ "but is %N",
+ pts_meas_algorithm_names, PTS_MEAS_ALGO_SHA1,
+ pts_meas_algorithm_names, hash_algo);
+ return FAILED;
+ }
+ if (!check_boot_aggregate(pcrs, measurement, ima_algo))
+ {
+ return FAILED;
+ }
+ this->state = IMA_STATE_INIT;
+ /* fall through to next state */
+ case IMA_STATE_INIT:
+ this->name->set_qualifier(this->name, qualifier);
+ status = this->pts_db->get_comp_measurement_count(this->pts_db,
+ this->name, this->aik_id, algo,
+ &this->ima_cid, &ima_count);
+ this->name->set_qualifier(this->name, PTS_QUALIFIER_UNKNOWN);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+
+ if (ima_count)
+ {
+ DBG1(DBG_PTS, "checking boot aggregate evidence "
+ "measurement");
+ status = this->pts_db->check_comp_measurement(this->pts_db,
+ measurement, this->ima_cid,
+ this->aik_id, 1, pcr, algo);
+ }
+ else
+ {
+ DBG1(DBG_PTS, "registering boot aggregate evidence "
+ "measurement");
+ this->is_ima_registering = TRUE;
+ status = this->pts_db->insert_comp_measurement(this->pts_db,
+ measurement, this->ima_cid,
+ this->aik_id, 1, pcr, algo);
+ }
+ this->state = IMA_STATE_RUNTIME;
+
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+ break;
+ case IMA_STATE_RUNTIME:
+ {
+ uint8_t hash_buf[HASH_SIZE_SHA512];
+ chunk_t digest, hash;
+ enumerator_t *e;
+
+ this->count++;
+ if (evidence->get_validation(evidence, NULL) !=
+ PTS_COMP_EVID_VALIDATION_PASSED)
+ {
+ DBG1(DBG_PTS, "evidence validation failed");
+ this->count_failed++;
+ return FAILED;
+ }
+ hash = chunk_create(hash_buf, pts_meas_algo_hash_size(algo));
+
+ e = this->pts_db->create_file_meas_enumerator(this->pts_db,
+ pts->get_platform_id(pts),
+ hash_algo, ima_name);
+ if (e)
+ {
+ while (e->enumerate(e, &digest))
+ {
+ if (!ima_hash(digest, ima_algo, ima_name,
+ FALSE, algo, hash_buf))
+ {
+ status = FAILED;
+ break;
+ }
+ if (chunk_equals(measurement, hash))
+ {
+ status = SUCCESS;
+ break;
+ }
+ else
+ {
+ status = VERIFY_ERROR;
+ }
+ }
+ e->destroy(e);
+ }
+ else
+ {
+ status = FAILED;
+ }
+
+ switch (status)
+ {
+ case SUCCESS:
+ DBG3(DBG_PTS, "%#B for '%s' is ok",
+ &measurement, ima_name);
+ this->count_ok++;
+ break;
+ case NOT_FOUND:
+ DBG2(DBG_PTS, "%#B for '%s' not found",
+ &measurement, ima_name);
+ this->count_unknown++;
+ break;
+ case VERIFY_ERROR:
+ DBG1(DBG_PTS, "%#B for '%s' differs",
+ &measurement, ima_name);
+ this->count_differ++;
+ break;
+ case FAILED:
+ default:
+ DBG1(DBG_PTS, "%#B for '%s' failed",
+ &measurement, ima_name);
+ this->count_failed++;
+ }
+ break;
+ }
+ default:
+ return FAILED;
+ }
+ }
+ else
+ {
+ DBG1(DBG_PTS, "unsupported functional component name qualifier");
+ return FAILED;
+ }
+
+ has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after);
+ if (has_pcr_info)
+ {
+ if (!chunk_equals(pcr_before, pcrs->get(pcrs, pcr)))
+ {
+ DBG1(DBG_PTS, "PCR %2u: pcr_before is not equal to register value",
+ pcr);
+ }
+ if (pcrs->set(pcrs, pcr, pcr_after))
+ {
+ return status;
+ }
+ }
+ else
+ {
+ pcr_after = pcrs->extend(pcrs, pcr, measurement);
+ if (pcr_after.ptr)
+ {
+ return status;
+ }
+ }
+ return FAILED;
+}
+
+METHOD(pts_component_t, finalize, bool,
+ pts_ita_comp_ima_t *this, uint8_t qualifier, bio_writer_t *result)
+{
+ char result_buf[BUF_LEN];
+ char *pos = result_buf;
+ size_t len = BUF_LEN;
+ int written;
+ bool success = TRUE;
+
+ this->name->set_qualifier(this->name, qualifier);
+
+ if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
+ PTS_ITA_QUALIFIER_TYPE_TRUSTED))
+ {
+ /* finalize BIOS measurements */
+ if (this->is_bios_registering)
+ {
+ /* close registration */
+ this->is_bios_registering = FALSE;
+
+ snprintf(pos, len, "registered %d BIOS evidence measurements",
+ this->seq_no);
+ }
+ else if (this->seq_no < this->bios_count)
+ {
+ snprintf(pos, len, "%d of %d BIOS evidence measurements missing",
+ this->bios_count - this->seq_no, this->bios_count);
+ success = FALSE;
+ }
+ else
+ {
+ snprintf(pos, len, "%d BIOS evidence measurements are ok",
+ this->bios_count);
+ }
+ }
+ else if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
+ PTS_ITA_QUALIFIER_TYPE_OS))
+ {
+ /* finalize IMA file measurements */
+ if (this->is_ima_registering)
+ {
+ /* close registration */
+ this->is_ima_registering = FALSE;
+
+ written = snprintf(pos, len, "registered IMA boot aggregate "
+ "evidence measurement; ");
+ pos += written;
+ len -= written;
+ }
+ if (this->count)
+ {
+ snprintf(pos, len, "processed %d IMA file evidence measurements: "
+ "%d ok, %d unknown, %d differ, %d failed",
+ this->count, this->count_ok, this->count_unknown,
+ this->count_differ, this->count_failed);
+ }
+ else
+ {
+ snprintf(pos, len, "no IMA file evidence measurements");
+ success = FALSE;
+ }
+ }
+ else
+ {
+ snprintf(pos, len, "unsupported functional component name qualifier");
+ success = FALSE;
+ }
+ this->name->set_qualifier(this->name, PTS_QUALIFIER_UNKNOWN);
+
+ DBG1(DBG_PTS, "%s", result_buf);
+ result->write_data(result, chunk_from_str(result_buf));
+
+ return success;
+}
+
+METHOD(pts_component_t, get_ref, pts_component_t*,
+ pts_ita_comp_ima_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public;
+}
+
+METHOD(pts_component_t, destroy, void,
+ pts_ita_comp_ima_t *this)
+{
+ int count;
+
+ if (ref_put(&this->ref))
+ {
+
+ if (this->is_bios_registering)
+ {
+ count = this->pts_db->delete_comp_measurements(this->pts_db,
+ this->bios_cid, this->aik_id);
+ DBG1(DBG_PTS, "deleted %d registered BIOS evidence measurements",
+ count);
+ }
+ if (this->is_ima_registering)
+ {
+ count = this->pts_db->delete_comp_measurements(this->pts_db,
+ this->ima_cid, this->aik_id);
+ DBG1(DBG_PTS, "deleted registered boot aggregate evidence "
+ "measurement");
+ }
+ DESTROY_IF(this->bios_list);
+ DESTROY_IF(this->ima_list);
+ this->name->destroy(this->name);
+
+ free(this);
+ }
+}
+
+/**
+ * See header
+ */
+pts_component_t *pts_ita_comp_ima_create(uint32_t depth,
+ pts_database_t *pts_db)
+{
+ pts_ita_comp_ima_t *this;
+
+ INIT(this,
+ .public = {
+ .get_comp_func_name = _get_comp_func_name,
+ .get_evidence_flags = _get_evidence_flags,
+ .get_depth = _get_depth,
+ .measure = _measure,
+ .verify = _verify,
+ .finalize = _finalize,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .name = pts_comp_func_name_create(PEN_ITA, PTS_ITA_COMP_FUNC_NAME_IMA,
+ PTS_QUALIFIER_UNKNOWN),
+ .depth = depth,
+ .pts_db = pts_db,
+ .pcr_info = lib->settings->get_bool(lib->settings,
+ "%s.plugins.imc-attestation.pcr_info", FALSE, lib->ns),
+ .ref = 1,
+ );
+
+ return &this->public;
+}
+
diff --git a/src/libimcv/pts/components/ita/ita_comp_ima.h b/src/libimcv/pts/components/ita/ita_comp_ima.h
new file mode 100644
index 000000000..546d0a4b2
--- /dev/null
+++ b/src/libimcv/pts/components/ita/ita_comp_ima.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2011-2012 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts_ita_comp_func_name pts_ita_comp_func_name
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_ITA_COMP_IMA_H_
+#define PTS_ITA_COMP_IMA_H_
+
+#include "pts/components/pts_component.h"
+
+/**
+ * Create a PTS ITS Functional Component object
+ *
+ * @param depth Sub-component depth
+ * @param pts_db PTS measurement database
+ */
+pts_component_t* pts_ita_comp_ima_create(u_int32_t depth,
+ pts_database_t *pts_db);
+
+#endif /** PTS_ITA_COMP_IMA_H_ @}*/
diff --git a/src/libimcv/pts/components/ita/ita_comp_tboot.c b/src/libimcv/pts/components/ita/ita_comp_tboot.c
new file mode 100644
index 000000000..273c18f31
--- /dev/null
+++ b/src/libimcv/pts/components/ita/ita_comp_tboot.c
@@ -0,0 +1,362 @@
+/*
+ * Copyright (C) 2011-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "ita_comp_tboot.h"
+#include "ita_comp_func_name.h"
+
+#include "imcv.h"
+#include "pts/components/pts_component.h"
+
+#include <utils/debug.h>
+#include <pen/pen.h>
+
+typedef struct pts_ita_comp_tboot_t pts_ita_comp_tboot_t;
+
+/**
+ * Private data of a pts_ita_comp_tboot_t object.
+ *
+ */
+struct pts_ita_comp_tboot_t {
+
+ /**
+ * Public pts_component_t interface.
+ */
+ pts_component_t public;
+
+ /**
+ * Component Functional Name
+ */
+ pts_comp_func_name_t *name;
+
+ /**
+ * Sub-component depth
+ */
+ u_int32_t depth;
+
+ /**
+ * PTS measurement database
+ */
+ pts_database_t *pts_db;
+
+ /**
+ * Primary key for AIK database entry
+ */
+ int aik_id;
+
+ /**
+ * Primary key for Component Functional Name database entry
+ */
+ int cid;
+
+ /**
+ * Primary key for AIK database entry
+ */
+ int kid;
+
+ /**
+ * Component is registering measurements
+ */
+ bool is_registering;
+
+ /**
+ * Time of TBOOT measurement
+ */
+ time_t measurement_time;
+
+ /**
+ * Expected measurement count
+ */
+ int count;
+
+ /**
+ * Measurement sequence number
+ */
+ int seq_no;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+
+};
+
+METHOD(pts_component_t, get_comp_func_name, pts_comp_func_name_t*,
+ pts_ita_comp_tboot_t *this)
+{
+ return this->name;
+}
+
+METHOD(pts_component_t, get_evidence_flags, u_int8_t,
+ pts_ita_comp_tboot_t *this)
+{
+ return PTS_REQ_FUNC_COMP_EVID_PCR;
+}
+
+METHOD(pts_component_t, get_depth, u_int32_t,
+ pts_ita_comp_tboot_t *this)
+{
+ return this->depth;
+}
+
+METHOD(pts_component_t, measure, status_t,
+ pts_ita_comp_tboot_t *this, u_int8_t qualifier, pts_t *pts,
+ pts_comp_evidence_t **evidence)
+
+{
+ size_t pcr_len;
+ pts_pcr_t *pcrs;
+ pts_pcr_transform_t pcr_transform;
+ pts_meas_algorithms_t hash_algo;
+ pts_comp_evidence_t *evid;
+ char *meas_hex, *pcr_before_hex, *pcr_after_hex;
+ chunk_t measurement, pcr_before, pcr_after;
+ u_int32_t extended_pcr;
+
+ switch (this->seq_no++)
+ {
+ case 0:
+ /* dummy data since currently the TBOOT log is not retrieved */
+ time(&this->measurement_time);
+ meas_hex = lib->settings->get_str(lib->settings,
+ "%s.plugins.imc-attestation.pcr17_meas", NULL, lib->ns);
+ pcr_before_hex = lib->settings->get_str(lib->settings,
+ "%s.plugins.imc-attestation.pcr17_before", NULL, lib->ns);
+ pcr_after_hex = lib->settings->get_str(lib->settings,
+ "%s.plugins.imc-attestation.pcr17_after", NULL, lib->ns);
+ extended_pcr = PCR_TBOOT_POLICY;
+ break;
+ case 1:
+ /* dummy data since currently the TBOOT log is not retrieved */
+ meas_hex = lib->settings->get_str(lib->settings,
+ "%s.plugins.imc-attestation.pcr18_meas", NULL, lib->ns);
+ pcr_before_hex = lib->settings->get_str(lib->settings,
+ "%s.plugins.imc-attestation.pcr18_before", NULL, lib->ns);
+ pcr_after_hex = lib->settings->get_str(lib->settings,
+ "%s.plugins.imc-attestation.pcr18_after", NULL, lib->ns);
+ extended_pcr = PCR_TBOOT_MLE;
+ break;
+ default:
+ return FAILED;
+ }
+
+ if (meas_hex == NULL || pcr_before_hex == NULL || pcr_after_hex == NULL)
+ {
+ return FAILED;
+ }
+
+ hash_algo = PTS_MEAS_ALGO_SHA1;
+ pcr_len = HASH_SIZE_SHA1;
+ pcr_transform = pts_meas_algo_to_pcr_transform(hash_algo, pcr_len);
+
+ /* get and check the measurement data */
+ measurement = chunk_from_hex(
+ chunk_create(meas_hex, strlen(meas_hex)), NULL);
+ pcr_before = chunk_from_hex(
+ chunk_create(pcr_before_hex, strlen(pcr_before_hex)), NULL);
+ pcr_after = chunk_from_hex(
+ chunk_create(pcr_after_hex, strlen(pcr_after_hex)), NULL);
+ if (pcr_before.len != pcr_len || pcr_after.len != pcr_len ||
+ measurement.len != pcr_len)
+ {
+ DBG1(DBG_PTS, "TBOOT measurement or PCR data have the wrong size");
+ free(measurement.ptr);
+ free(pcr_before.ptr);
+ free(pcr_after.ptr);
+ return FAILED;
+ }
+
+ pcrs = pts->get_pcrs(pts);
+ pcrs->set(pcrs, extended_pcr, pcr_after);
+ evid = *evidence = pts_comp_evidence_create(this->name->clone(this->name),
+ this->depth, extended_pcr, hash_algo, pcr_transform,
+ this->measurement_time, measurement);
+ evid->set_pcr_info(evid, pcr_before, pcr_after);
+
+ return (this->seq_no < 2) ? NEED_MORE : SUCCESS;
+}
+
+METHOD(pts_component_t, verify, status_t,
+ pts_ita_comp_tboot_t *this, u_int8_t qualifier,pts_t *pts,
+ pts_comp_evidence_t *evidence)
+{
+ bool has_pcr_info;
+ u_int32_t extended_pcr, vid, name;
+ enum_name_t *names;
+ pts_meas_algorithms_t algo;
+ pts_pcr_transform_t transform;
+ pts_pcr_t *pcrs;
+ time_t measurement_time;
+ chunk_t measurement, pcr_before, pcr_after;
+ status_t status;
+
+ this->aik_id = pts->get_aik_id(pts);
+ pcrs = pts->get_pcrs(pts);
+ measurement = evidence->get_measurement(evidence, &extended_pcr,
+ &algo, &transform, &measurement_time);
+
+ status = this->pts_db->get_comp_measurement_count(this->pts_db,
+ this->name, this->aik_id, algo,
+ &this->cid, &this->count);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+ vid = this->name->get_vendor_id(this->name);
+ name = this->name->get_name(this->name);
+ names = imcv_pts_components->get_comp_func_names(imcv_pts_components, vid);
+
+ if (this->count)
+ {
+ DBG1(DBG_PTS, "checking %d %N '%N' functional component evidence "
+ "measurements", this->count, pen_names, vid, names, name);
+ }
+ else
+ {
+ DBG1(DBG_PTS, "registering %N '%N' functional component evidence "
+ "measurements", pen_names, vid, names, name);
+ this->is_registering = TRUE;
+ }
+
+ if (this->is_registering)
+ {
+ status = this->pts_db->insert_comp_measurement(this->pts_db,
+ measurement, this->cid, this->aik_id,
+ ++this->seq_no, extended_pcr, algo);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+ this->count = this->seq_no + 1;
+ }
+ else
+ {
+ status = this->pts_db->check_comp_measurement(this->pts_db,
+ measurement, this->cid, this->kid,
+ ++this->seq_no, extended_pcr, algo);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+ }
+
+ has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after);
+ if (has_pcr_info)
+ {
+ if (!chunk_equals(pcr_before, pcrs->get(pcrs, extended_pcr)))
+ {
+ DBG1(DBG_PTS, "PCR %2u: pcr_before is not equal to register value",
+ extended_pcr);
+ }
+ if (pcrs->set(pcrs, extended_pcr, pcr_after))
+ {
+ return SUCCESS;
+ }
+ }
+
+ return SUCCESS;
+}
+
+METHOD(pts_component_t, finalize, bool,
+ pts_ita_comp_tboot_t *this, u_int8_t qualifier, bio_writer_t *result)
+{
+ char result_buf[BUF_LEN];
+
+ if (this->is_registering)
+ {
+ /* close registration */
+ this->is_registering = FALSE;
+
+ snprintf(result_buf, BUF_LEN, "registered %d evidence measurements",
+ this->seq_no);
+ }
+ else if (this->seq_no < this->count)
+ {
+ snprintf(result_buf, BUF_LEN, "%d of %d evidence measurements "
+ "missing", this->count - this->seq_no, this->count);
+ return FALSE;
+ }
+ else
+ {
+ snprintf(result_buf, BUF_LEN, "%d evidence measurements are ok",
+ this->count);
+ }
+ DBG1(DBG_PTS, "%s", result_buf);
+ result->write_data(result, chunk_from_str(result_buf));
+
+ return TRUE;
+}
+
+METHOD(pts_component_t, get_ref, pts_component_t*,
+ pts_ita_comp_tboot_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public;
+}
+
+METHOD(pts_component_t, destroy, void,
+ pts_ita_comp_tboot_t *this)
+{
+ int count;
+ u_int32_t vid, name;
+ enum_name_t *names;
+
+ if (ref_put(&this->ref))
+ {
+ if (this->is_registering)
+ {
+ count = this->pts_db->delete_comp_measurements(this->pts_db,
+ this->cid, this->aik_id);
+ vid = this->name->get_vendor_id(this->name);
+ name = this->name->get_name(this->name);
+ names = imcv_pts_components->get_comp_func_names(imcv_pts_components,
+ vid);
+ DBG1(DBG_PTS, "deleted %d registered %N '%N' functional component "
+ "evidence measurements", count, pen_names, vid, names, name);
+ }
+ this->name->destroy(this->name);
+ free(this);
+ }
+}
+
+/**
+ * See header
+ */
+pts_component_t *pts_ita_comp_tboot_create(u_int32_t depth,
+ pts_database_t *pts_db)
+{
+ pts_ita_comp_tboot_t *this;
+
+ INIT(this,
+ .public = {
+ .get_comp_func_name = _get_comp_func_name,
+ .get_evidence_flags = _get_evidence_flags,
+ .get_depth = _get_depth,
+ .measure = _measure,
+ .verify = _verify,
+ .finalize = _finalize,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .name = pts_comp_func_name_create(PEN_ITA, PTS_ITA_COMP_FUNC_NAME_TBOOT,
+ PTS_ITA_QUALIFIER_FLAG_KERNEL |
+ PTS_ITA_QUALIFIER_TYPE_TRUSTED),
+ .depth = depth,
+ .pts_db = pts_db,
+ .ref = 1,
+ );
+
+ return &this->public;
+}
+
diff --git a/src/libimcv/pts/components/ita/ita_comp_tboot.h b/src/libimcv/pts/components/ita/ita_comp_tboot.h
new file mode 100644
index 000000000..1e1a14831
--- /dev/null
+++ b/src/libimcv/pts/components/ita/ita_comp_tboot.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts_ita_comp_func_name pts_ita_comp_func_name
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_ITA_COMP_TBOOT_H_
+#define PTS_ITA_COMP_TBOOT_H_
+
+#include "pts/components/pts_component.h"
+
+/**
+ * Create a PTS ITS Functional Component object
+ *
+ * @param depth Sub-component depth
+ * @param pts_db PTS measurement database
+ */
+pts_component_t* pts_ita_comp_tboot_create(u_int32_t depth,
+ pts_database_t *pts_db);
+
+#endif /** PTS_ITA_COMP_TBOOT_H_ @}*/
diff --git a/src/libimcv/pts/components/ita/ita_comp_tgrub.c b/src/libimcv/pts/components/ita/ita_comp_tgrub.c
new file mode 100644
index 000000000..097e4c89c
--- /dev/null
+++ b/src/libimcv/pts/components/ita/ita_comp_tgrub.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2011-2012 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "ita_comp_tgrub.h"
+#include "ita_comp_func_name.h"
+
+#include "pts/components/pts_component.h"
+
+#include <utils/debug.h>
+#include <pen/pen.h>
+
+typedef struct pts_ita_comp_tgrub_t pts_ita_comp_tgrub_t;
+
+/**
+ * Private data of a pts_ita_comp_tgrub_t object.
+ *
+ */
+struct pts_ita_comp_tgrub_t {
+
+ /**
+ * Public pts_component_t interface.
+ */
+ pts_component_t public;
+
+ /**
+ * Component Functional Name
+ */
+ pts_comp_func_name_t *name;
+
+ /**
+ * Sub-component depth
+ */
+ u_int32_t depth;
+
+ /**
+ * PTS measurement database
+ */
+ pts_database_t *pts_db;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+
+};
+
+METHOD(pts_component_t, get_comp_func_name, pts_comp_func_name_t*,
+ pts_ita_comp_tgrub_t *this)
+{
+ return this->name;
+}
+
+METHOD(pts_component_t, get_evidence_flags, u_int8_t,
+ pts_ita_comp_tgrub_t *this)
+{
+ return PTS_REQ_FUNC_COMP_EVID_PCR;
+}
+
+METHOD(pts_component_t, get_depth, u_int32_t,
+ pts_ita_comp_tgrub_t *this)
+{
+ return this->depth;
+}
+
+METHOD(pts_component_t, measure, status_t,
+ pts_ita_comp_tgrub_t *this, u_int8_t qualifier, pts_t *pts,
+ pts_comp_evidence_t **evidence)
+{
+ size_t pcr_len;
+ pts_pcr_transform_t pcr_transform;
+ pts_meas_algorithms_t hash_algo;
+ pts_comp_evidence_t *evid;
+ u_int32_t extended_pcr;
+ time_t measurement_time;
+ chunk_t measurement, pcr_before, pcr_after;
+
+ /* Provisional implementation for TGRUB */
+ extended_pcr = PCR_DEBUG;
+ time(&measurement_time);
+
+ if (!pts->read_pcr(pts, extended_pcr, &pcr_after))
+ {
+ DBG1(DBG_PTS, "error occurred while reading PCR: %d", extended_pcr);
+ return FAILED;
+ }
+
+ hash_algo = PTS_MEAS_ALGO_SHA1;
+ pcr_len = HASH_SIZE_SHA1;
+ pcr_transform = pts_meas_algo_to_pcr_transform(hash_algo, pcr_len);
+
+ measurement = chunk_alloc(pcr_len);
+ memset(measurement.ptr, 0x00, measurement.len);
+
+ pcr_before = chunk_alloc(pcr_len);
+ memset(pcr_before.ptr, 0x00, pcr_before.len);
+
+ evid = *evidence = pts_comp_evidence_create(this->name->clone(this->name),
+ this->depth, extended_pcr,
+ hash_algo, pcr_transform,
+ measurement_time, measurement);
+ evid->set_pcr_info(evid, pcr_before, pcr_after);
+
+ return SUCCESS;
+}
+
+METHOD(pts_component_t, verify, status_t,
+ pts_ita_comp_tgrub_t *this, u_int8_t qualifier, pts_t *pts,
+ pts_comp_evidence_t *evidence)
+{
+ bool has_pcr_info;
+ u_int32_t extended_pcr;
+ pts_meas_algorithms_t algo;
+ pts_pcr_transform_t transform;
+ pts_pcr_t *pcrs;
+ time_t measurement_time;
+ chunk_t pcr_before, pcr_after;
+ chunk_t measurement __attribute__((unused));
+
+ pcrs = pts->get_pcrs(pts);
+ measurement = evidence->get_measurement(evidence, &extended_pcr,
+ &algo, &transform, &measurement_time);
+ if (extended_pcr != PCR_DEBUG)
+ {
+ return FAILED;
+ }
+
+ /* TODO check measurement in database */
+
+ has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after);
+ if (has_pcr_info)
+ {
+ if (!chunk_equals(pcr_before, pcrs->get(pcrs, extended_pcr)))
+ {
+ DBG1(DBG_PTS, "PCR %2u: pcr_before is not equal to pcr value");
+ }
+ if (pcrs->set(pcrs, extended_pcr, pcr_after))
+ {
+ return SUCCESS;
+ }
+ }
+
+ return SUCCESS;
+}
+
+METHOD(pts_component_t, finalize, bool,
+ pts_ita_comp_tgrub_t *this, u_int8_t qualifier, bio_writer_t *result)
+{
+ return FALSE;
+}
+
+METHOD(pts_component_t, get_ref, pts_component_t*,
+ pts_ita_comp_tgrub_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public;
+}
+
+METHOD(pts_component_t, destroy, void,
+ pts_ita_comp_tgrub_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ this->name->destroy(this->name);
+ free(this);
+ }
+}
+
+/**
+ * See header
+ */
+pts_component_t *pts_ita_comp_tgrub_create(u_int32_t depth,
+ pts_database_t *pts_db)
+{
+ pts_ita_comp_tgrub_t *this;
+
+ INIT(this,
+ .public = {
+ .get_comp_func_name = _get_comp_func_name,
+ .get_evidence_flags = _get_evidence_flags,
+ .get_depth = _get_depth,
+ .measure = _measure,
+ .verify = _verify,
+ .finalize = _finalize,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .name = pts_comp_func_name_create(PEN_ITA, PTS_ITA_COMP_FUNC_NAME_TGRUB,
+ PTS_ITA_QUALIFIER_FLAG_KERNEL |
+ PTS_ITA_QUALIFIER_TYPE_TRUSTED),
+ .depth = depth,
+ .pts_db = pts_db,
+ .ref = 1,
+ );
+
+ return &this->public;
+}
diff --git a/src/libimcv/pts/components/ita/ita_comp_tgrub.h b/src/libimcv/pts/components/ita/ita_comp_tgrub.h
new file mode 100644
index 000000000..59913c82d
--- /dev/null
+++ b/src/libimcv/pts/components/ita/ita_comp_tgrub.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts_ita_comp_func_name pts_ita_comp_func_name
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_ITA_COMP_TGRUB_H_
+#define PTS_ITA_COMP_TGRUB_H_
+
+#include "pts/components/pts_component.h"
+
+/**
+ * Create a PTS ITS Functional Component object
+ *
+ * @param depth Sub-component depth
+ * @param pts_db PTS measurement database
+ */
+pts_component_t* pts_ita_comp_tgrub_create(u_int32_t depth,
+ pts_database_t *pts_db);
+
+#endif /** PTS_ITA_COMP_TGRUB_H_ @}*/
diff --git a/src/libimcv/pts/components/pts_comp_evidence.c b/src/libimcv/pts/components/pts_comp_evidence.c
new file mode 100644
index 000000000..08c3d5e9a
--- /dev/null
+++ b/src/libimcv/pts/components/pts_comp_evidence.c
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu, Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pts/components/pts_comp_evidence.h"
+
+#include <utils/debug.h>
+
+typedef struct private_pts_comp_evidence_t private_pts_comp_evidence_t;
+
+/**
+ * Private data of a pts_comp_evidence_t object.
+ */
+struct private_pts_comp_evidence_t {
+
+ /**
+ * Public pts_comp_evidence_t interface.
+ */
+ pts_comp_evidence_t public;
+
+ /**
+ * Component Functional Name
+ */
+ pts_comp_func_name_t *name;
+
+ /**
+ * Sub-Component Depth
+ */
+ u_int32_t depth;
+
+ /**
+ * Measurement Time
+ */
+ time_t measurement_time;
+
+ /**
+ * Measurement Time
+ */
+ chunk_t measurement;
+
+ /**
+ * Measurement Hash Algorithm
+ */
+ pts_meas_algorithms_t hash_algorithm;
+
+ /**
+ * Is PCR Information included?
+ */
+ bool has_pcr_info;
+
+ /**
+ * PCR the measurement was extended into
+ */
+ u_int32_t extended_pcr;
+
+ /**
+ * PCR value before extension
+ */
+ chunk_t pcr_before;
+
+ /**
+ * PCR value after extension
+ */
+ chunk_t pcr_after;
+
+ /**
+ * Transformation used for extending measurement into PCR
+ */
+ pts_pcr_transform_t transform;
+
+ /**
+ * Component Validation Result
+ */
+ pts_comp_evid_validation_t validation;
+
+ /**
+ * Verification Policy URI
+ */
+ char *policy_uri;
+
+};
+
+METHOD(pts_comp_evidence_t, get_comp_func_name, pts_comp_func_name_t*,
+ private_pts_comp_evidence_t *this, u_int32_t *depth)
+{
+ if (depth)
+ {
+ *depth = this->depth;
+ }
+ return this->name;
+}
+
+METHOD(pts_comp_evidence_t, get_extended_pcr, u_int32_t,
+ private_pts_comp_evidence_t *this)
+{
+ return this->extended_pcr;
+}
+
+METHOD(pts_comp_evidence_t, get_measurement, chunk_t,
+ private_pts_comp_evidence_t *this, u_int32_t *extended_pcr,
+ pts_meas_algorithms_t *algo, pts_pcr_transform_t *transform,
+ time_t *measurement_time)
+{
+ if (extended_pcr)
+ {
+ *extended_pcr = this->extended_pcr;
+ }
+ if (algo)
+ {
+ *algo = this->hash_algorithm;
+ }
+ if (transform)
+ {
+ *transform = this->transform;
+ }
+ if (measurement_time)
+ {
+ *measurement_time = this->measurement_time;
+ }
+ return this->measurement;
+}
+
+METHOD(pts_comp_evidence_t, get_pcr_info, bool,
+ private_pts_comp_evidence_t *this, chunk_t *pcr_before, chunk_t *pcr_after)
+{
+ if (pcr_before)
+ {
+ *pcr_before = this->pcr_before;
+ }
+ if (pcr_after)
+ {
+ *pcr_after = this->pcr_after;
+ }
+ return this->has_pcr_info;
+}
+
+METHOD(pts_comp_evidence_t, set_pcr_info, void,
+ private_pts_comp_evidence_t *this, chunk_t pcr_before, chunk_t pcr_after)
+{
+ this->has_pcr_info = TRUE;
+ this->pcr_before = pcr_before;
+ this->pcr_after = pcr_after;
+
+ DBG3(DBG_PTS, "PCR %2d before value : %#B", this->extended_pcr, &pcr_before);
+ DBG3(DBG_PTS, "PCR %2d after value : %#B", this->extended_pcr, &pcr_after);
+}
+
+METHOD(pts_comp_evidence_t, get_validation, pts_comp_evid_validation_t,
+ private_pts_comp_evidence_t *this, char **uri)
+{
+ if (uri)
+ {
+ *uri = this->policy_uri;
+ }
+ return this->validation;
+}
+
+METHOD(pts_comp_evidence_t, set_validation, void,
+ private_pts_comp_evidence_t *this, pts_comp_evid_validation_t validation,
+ char *uri)
+{
+ this->validation = validation;
+ if (uri)
+ {
+ this->policy_uri = strdup(uri);
+ DBG3(DBG_PTS, "'%s'", uri);
+ }
+}
+
+METHOD(pts_comp_evidence_t, destroy, void,
+ private_pts_comp_evidence_t *this)
+{
+ this->name->destroy(this->name);
+ free(this->measurement.ptr);
+ free(this->pcr_before.ptr);
+ free(this->pcr_after.ptr);
+ free(this->policy_uri);
+ free(this);
+}
+
+/**
+ * See header
+ */
+pts_comp_evidence_t *pts_comp_evidence_create(pts_comp_func_name_t *name,
+ u_int32_t depth,
+ u_int32_t extended_pcr,
+ pts_meas_algorithms_t algo,
+ pts_pcr_transform_t transform,
+ time_t measurement_time,
+ chunk_t measurement)
+{
+ private_pts_comp_evidence_t *this;
+
+ INIT(this,
+ .public = {
+ .get_comp_func_name = _get_comp_func_name,
+ .get_extended_pcr = _get_extended_pcr,
+ .get_measurement = _get_measurement,
+ .get_pcr_info = _get_pcr_info,
+ .set_pcr_info = _set_pcr_info,
+ .get_validation = _get_validation,
+ .set_validation = _set_validation,
+ .destroy = _destroy,
+ },
+ .name = name,
+ .depth = depth,
+ .extended_pcr = extended_pcr,
+ .hash_algorithm = algo,
+ .transform = transform,
+ .measurement_time = measurement_time,
+ .measurement = measurement,
+ );
+
+ name->log(name, "");
+ DBG3(DBG_PTS, "measurement time: %T", &measurement_time, FALSE);
+ DBG3(DBG_PTS, "PCR %2d extended with: %#B", extended_pcr, &measurement);
+
+ return &this->public;
+}
+
+/**
+ * See header
+ */
+pts_pcr_transform_t pts_meas_algo_to_pcr_transform(pts_meas_algorithms_t algo,
+ size_t pcr_len)
+{
+ size_t hash_size;
+
+ hash_size = pts_meas_algo_hash_size(algo);
+ if (hash_size == 0)
+ {
+ return PTS_PCR_TRANSFORM_NO;
+ }
+ if (hash_size == pcr_len)
+ {
+ return PTS_PCR_TRANSFORM_MATCH;
+ }
+ if (hash_size > pcr_len)
+ {
+ return PTS_PCR_TRANSFORM_LONG;
+ }
+ return PTS_PCR_TRANSFORM_SHORT;
+}
+
diff --git a/src/libimcv/pts/components/pts_comp_evidence.h b/src/libimcv/pts/components/pts_comp_evidence.h
new file mode 100644
index 000000000..55776ce8b
--- /dev/null
+++ b/src/libimcv/pts/components/pts_comp_evidence.h
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu, Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts_comp_evidence pts_comp_evidence
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_COMP_EVIDENCE_H_
+#define PTS_COMP_EVIDENCE_H_
+
+typedef struct pts_comp_evidence_t pts_comp_evidence_t;
+typedef enum pts_pcr_transform_t pts_pcr_transform_t;
+typedef enum pts_comp_evid_validation_t pts_comp_evid_validation_t;
+
+#include "pts/pts_meas_algo.h"
+#include "pts/components/pts_comp_func_name.h"
+
+#include <library.h>
+
+/**
+ * PTS PCR Transformations
+ */
+enum pts_pcr_transform_t {
+ /** No Transformation */
+ PTS_PCR_TRANSFORM_NO = 0,
+ /** Hash Value matched PCR size */
+ PTS_PCR_TRANSFORM_MATCH = 1,
+ /** Hash value shorter than PCR size */
+ PTS_PCR_TRANSFORM_SHORT = 2,
+ /** Hash value longer than PCR size */
+ PTS_PCR_TRANSFORM_LONG = 3,
+};
+
+/**
+ * PTS Component Evidence Validation Result Flags
+ */
+enum pts_comp_evid_validation_t {
+ /** No Validation was attempted */
+ PTS_COMP_EVID_VALIDATION_NONE = 0x00,
+ /** Attempted validation, unable to verify */
+ PTS_COMP_EVID_VALIDATION_UNABLE = 0x20,
+ /** Attempted validation, verification failed */
+ PTS_COMP_EVID_VALIDATION_FAILED = 0x40,
+ /** Attempted validation, verification passed */
+ PTS_COMP_EVID_VALIDATION_PASSED = 0x60,
+};
+
+/**
+ * PTS Functional Component Interface
+ */
+struct pts_comp_evidence_t {
+
+ /**
+ * Gets the Component Functional Name and Sub-Component Depth
+ *
+ * @param depth Sub-Component Depth
+ * @result Component Functional Name
+ */
+ pts_comp_func_name_t* (*get_comp_func_name)(pts_comp_evidence_t *this,
+ u_int32_t *depth);
+
+ /**
+ * Gets the PCR the measurement was extended into
+ *
+ * @result PCR the measurement was extended into
+ */
+ u_int32_t (*get_extended_pcr)(pts_comp_evidence_t *this);
+
+ /**
+ * Gets the measurement and the algorithms used
+ *
+ * @param extended_pcr PCR the measurement was extended into
+ * @param algo Measurement hash algorithm
+ * @param transform Transformation used for PCR extension
+ * @param measurement_time Time the measurement was taken
+ * @result Measurement hash value
+ */
+ chunk_t (*get_measurement)(pts_comp_evidence_t *this,
+ u_int32_t *extended_pcr,
+ pts_meas_algorithms_t *algo,
+ pts_pcr_transform_t *transform,
+ time_t *measurement_time);
+
+ /**
+ * Gets the PCR information if available
+ *
+ * @param pcr_before PCR value before extension
+ * @param pcr_after PCR value after extension
+ * @result TRUE if PCR information is available
+ */
+ bool (*get_pcr_info)(pts_comp_evidence_t *this, chunk_t *pcr_before,
+ chunk_t *pcr_after);
+
+ /**
+ * Sets PCR information if available
+ *
+ * @param pcr_before PCR value before extension
+ * @param pcr_after PCR value after extension
+ */
+ void (*set_pcr_info)(pts_comp_evidence_t *this, chunk_t pcr_before,
+ chunk_t pcr_after);
+
+ /**
+ * Gets Validation Result if available
+ *
+ * @param uri Verification Policy URI
+ * @return validation Validation Result
+ */
+ pts_comp_evid_validation_t (*get_validation)(pts_comp_evidence_t *this,
+ char **uri);
+
+ /**
+ * Sets Validation Result if available
+ *
+ * @param validation Validation Result
+ * @param uri Verification Policy URI
+ */
+ void (*set_validation)(pts_comp_evidence_t *this,
+ pts_comp_evid_validation_t validation, char* uri);
+
+ /**
+ * Destroys a pts_comp_evidence_t object.
+ */
+ void (*destroy)(pts_comp_evidence_t *this);
+
+};
+
+/**
+ * Creates a pts_comp_evidence_t object
+ *
+ * @param name Component Functional Name
+ * @param depth Sub-component depth
+ * @param extended_pcr PCR the measurement was extended into
+ * @param algo Measurement hash algorithm
+ * @param transform Transformation used for PCR extension
+ * @param measurement_time Time the measurement was taken, 0 if unknown
+ * @param measurement Measurement hash value
+ */
+pts_comp_evidence_t* pts_comp_evidence_create(pts_comp_func_name_t *name,
+ u_int32_t depth,
+ u_int32_t extended_pcr,
+ pts_meas_algorithms_t algo,
+ pts_pcr_transform_t transform,
+ time_t measurement_time,
+ chunk_t measurement);
+
+/**
+ * Determine transform to fit measurement hash into PCR register
+ *
+ * @param algo Measurement hash algorithm
+ * @param pcr_len Length of the PCR registers in bytes
+ * @return PCR transform type
+ */
+pts_pcr_transform_t pts_meas_algo_to_pcr_transform(pts_meas_algorithms_t algo,
+ size_t pcr_len);
+
+#endif /** PTS_COMP_EVIDENCE_H_ @}*/
diff --git a/src/libimcv/pts/components/pts_comp_func_name.c b/src/libimcv/pts/components/pts_comp_func_name.c
new file mode 100644
index 000000000..e12522ed1
--- /dev/null
+++ b/src/libimcv/pts/components/pts_comp_func_name.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2011-2014 Andreas Steffen
+ *
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "imcv.h"
+#include "pts/components/pts_comp_func_name.h"
+
+#include <utils/debug.h>
+
+typedef struct private_pts_comp_func_name_t private_pts_comp_func_name_t;
+
+/**
+ * Private data of a pts_comp_func_name_t object.
+ *
+ */
+struct private_pts_comp_func_name_t {
+
+ /**
+ * Public pts_comp_func_name_t interface.
+ */
+ pts_comp_func_name_t public;
+
+ /**
+ * PTS Component Functional Name Vendor ID
+ */
+ u_int32_t vid;
+
+ /**
+ * PTS Component Functional Name
+ */
+ u_int32_t name;
+
+ /**
+ * PTS Component Functional Name Qualifier
+ */
+ u_int8_t qualifier;
+
+};
+
+METHOD(pts_comp_func_name_t, get_vendor_id, u_int32_t,
+ private_pts_comp_func_name_t *this)
+{
+ return this->vid;
+}
+
+METHOD(pts_comp_func_name_t, get_name, u_int32_t,
+ private_pts_comp_func_name_t *this)
+{
+ return this->name;
+}
+
+METHOD(pts_comp_func_name_t, get_qualifier, u_int8_t,
+ private_pts_comp_func_name_t *this)
+{
+ return this->qualifier;
+}
+
+METHOD(pts_comp_func_name_t, set_qualifier, void,
+ private_pts_comp_func_name_t *this, u_int8_t qualifier)
+{
+ this->qualifier = qualifier;
+}
+
+static bool equals(private_pts_comp_func_name_t *this,
+ private_pts_comp_func_name_t *other)
+{
+ if (this->vid != other->vid || this->name != other->name)
+ {
+ return FALSE;
+ }
+ if (this->qualifier == PTS_QUALIFIER_UNKNOWN ||
+ other->qualifier == PTS_QUALIFIER_UNKNOWN)
+ {
+ return TRUE;
+ }
+ /* TODO handle qualifier wildcards */
+
+ return this->qualifier == other->qualifier;
+}
+
+METHOD(pts_comp_func_name_t, clone_, pts_comp_func_name_t*,
+ private_pts_comp_func_name_t *this)
+{
+ private_pts_comp_func_name_t *clone;
+
+ clone = malloc_thing(private_pts_comp_func_name_t);
+ memcpy(clone, this, sizeof(private_pts_comp_func_name_t));
+
+ return &clone->public;
+}
+
+METHOD(pts_comp_func_name_t, log_, void,
+ private_pts_comp_func_name_t *this, char *label)
+{
+ enum_name_t *names, *types;
+ char flags[8];
+ int type;
+
+ names = imcv_pts_components->get_comp_func_names(imcv_pts_components,
+ this->vid);
+ types = imcv_pts_components->get_qualifier_type_names(imcv_pts_components,
+ this->vid);
+ type = imcv_pts_components->get_qualifier(imcv_pts_components,
+ &this->public, flags);
+
+ if (names && types)
+ {
+ DBG2(DBG_PTS, "%s%N functional component '%N' [%s] '%N'",
+ label, pen_names, this->vid, names, this->name, flags, types, type);
+ }
+ else
+ {
+ DBG2(DBG_PTS, "%s0x%06x functional component 0x%08x 0x%02x",
+ label, this->vid, this->name, this->qualifier);
+ }
+}
+
+METHOD(pts_comp_func_name_t, destroy, void,
+ private_pts_comp_func_name_t *this)
+{
+ free(this);
+}
+
+/**
+ * See header
+ */
+pts_comp_func_name_t* pts_comp_func_name_create(u_int32_t vid, u_int32_t name,
+ u_int8_t qualifier)
+{
+ private_pts_comp_func_name_t *this;
+
+ INIT(this,
+ .public = {
+ .get_vendor_id = _get_vendor_id,
+ .get_name = _get_name,
+ .get_qualifier = _get_qualifier,
+ .set_qualifier = _set_qualifier,
+ .equals = (bool(*)(pts_comp_func_name_t*,pts_comp_func_name_t*))equals,
+ .clone = _clone_,
+ .log = _log_,
+ .destroy = _destroy,
+ },
+ .vid = vid,
+ .name = name,
+ .qualifier = qualifier,
+ );
+
+ return &this->public;
+}
+
diff --git a/src/libimcv/pts/components/pts_comp_func_name.h b/src/libimcv/pts/components/pts_comp_func_name.h
new file mode 100644
index 000000000..90ad7083f
--- /dev/null
+++ b/src/libimcv/pts/components/pts_comp_func_name.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts_comp_func_name pts_comp_func_name
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_FUNC_COMP_NAME_H_
+#define PTS_FUNC_COMP_NAME_H_
+
+typedef struct pts_comp_func_name_t pts_comp_func_name_t;
+
+#include <library.h>
+
+#define PTS_QUALIFIER_UNKNOWN 0x00
+#define PTS_QUALIFIER_WILDCARD 0x3F
+
+/**
+ * PTS Component Functional Name object
+ */
+struct pts_comp_func_name_t {
+
+ /**
+ * Get the PTS Component Functional Name Vendor ID
+ *
+ * @return PTS Component Functional Name Vendor ID
+ */
+ u_int32_t (*get_vendor_id)(pts_comp_func_name_t *this);
+
+ /**
+ * Get the PTS Component Functional Name
+ *
+ * @return PTS Component Functional Name
+ */
+ u_int32_t (*get_name)(pts_comp_func_name_t *this);
+
+ /**
+ * Get the PTS Component Functional Name Qualifier
+ *
+ * @return PTS Component Functional Name Qualifier
+ */
+ u_int8_t (*get_qualifier)(pts_comp_func_name_t *this);
+
+ /**
+ * Set the PTS Component Functional Name Qualifier
+ *
+ * @param qualifier PTS Component Functional Name Qualifier to be set
+ */
+ void (*set_qualifier)(pts_comp_func_name_t *this, u_int8_t qualifier);
+
+ /**
+ * Check to PTS Component Functional Names for equality
+ *
+ * @param other Other PTS Component Functional Name
+ * @return TRUE if equal
+ */
+ bool (*equals)(pts_comp_func_name_t *this, pts_comp_func_name_t *other);
+
+ /**
+ * Clone a PTS Component Functional Name
+ *
+ * @return Cloned PTS Component Functional Name
+ */
+ pts_comp_func_name_t* (*clone)(pts_comp_func_name_t *this);
+
+ /**
+ * Write PTS Component Functional Name information to the standard logfile
+ *
+ * @param label Label added to log output
+ */
+ void (*log)(pts_comp_func_name_t *this, char *label);
+
+ /**
+ * Destroys a pts_component_t object.
+ */
+ void (*destroy)(pts_comp_func_name_t *this);
+
+};
+
+/**
+ * Create a PTS Component Functional Name object
+ *
+ * @param vid PTS Component Functional Name Vendor ID
+ * @param name PTS Component Functional Name
+ * @param qualifier PTS Component Functional Name Qualifier
+ */
+pts_comp_func_name_t* pts_comp_func_name_create(u_int32_t vid, u_int32_t name,
+ u_int8_t qualifier);
+
+#endif /** PTS_FUNC_COMP_NAME_H_ @}*/
diff --git a/src/libimcv/pts/components/pts_component.h b/src/libimcv/pts/components/pts_component.h
new file mode 100644
index 000000000..71b1ad59c
--- /dev/null
+++ b/src/libimcv/pts/components/pts_component.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2011-2012 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts_component pts_component
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_COMPONENT_H_
+#define PTS_COMPONENT_H_
+
+typedef struct pts_component_t pts_component_t;
+
+#include "pts/pts.h"
+#include "pts/pts_database.h"
+#include "pts/pts_file_meas.h"
+#include "pts/components/pts_comp_func_name.h"
+#include "pts/components/pts_comp_evidence.h"
+
+#include <library.h>
+#include <bio/bio_writer.h>
+
+/**
+ * PTS Functional Component Interface
+ */
+struct pts_component_t {
+
+ /**
+ * Get the PTS Component Functional Name
+ *
+ * @return PTS Component Functional Name
+ */
+ pts_comp_func_name_t* (*get_comp_func_name)(pts_component_t *this);
+
+ /**
+ * Get the PTS Component Evidence Flags
+ *
+ * @return PTS Component Functional Name
+ */
+ u_int8_t (*get_evidence_flags)(pts_component_t *this);
+
+ /**
+ * Get the PTS Sub-component Depth
+ *
+ * @return PTS Sub-component Depth
+ */
+ u_int32_t (*get_depth)(pts_component_t *this);
+
+ /**
+ * Do evidence measurements on the PTS Functional Component
+ *
+ * @param qualifier PTS Component Functional Name Qualifier
+ * @param pts PTS interface
+ * @param evidence returns component evidence measureemt
+ * @param measurements additional file measurements (NULL if not present)
+ * @return status return code
+ */
+ status_t (*measure)(pts_component_t *this, u_int8_t qualifier, pts_t *pts,
+ pts_comp_evidence_t** evidence);
+
+ /**
+ * Verify the evidence measurements of the PTS Functional Component
+ *
+ * @param qualifier PTS Component Functional Name Qualifier
+ * @param pts PTS interface
+ * @param evidence component evidence measurement to be verified
+ * @return status return code
+ */
+ status_t (*verify)(pts_component_t *this, u_int8_t qualifier, pts_t *pts,
+ pts_comp_evidence_t *evidence);
+
+ /**
+ * Tell the PTS Functional Component to finalize pending registrations
+ * and check for missing measurements
+ *
+ * @param qualifier PTS Component Functional Name Qualifier
+ * @param result writer appending concise measurement result
+ * @return TRUE if finalization successful
+ */
+ bool (*finalize)(pts_component_t *this, u_int8_t qualifier,
+ bio_writer_t *result);
+
+ /**
+ * Get a new reference to the PTS Functional Component
+ *
+ * @return this, with an increased refcount
+ */
+ pts_component_t* (*get_ref)(pts_component_t *this);
+
+ /**
+ * Destroys a pts_component_t object.
+ */
+ void (*destroy)(pts_component_t *this);
+
+};
+
+#endif /** PTS_COMPONENT_H_ @}*/
diff --git a/src/libimcv/pts/components/pts_component_manager.c b/src/libimcv/pts/components/pts_component_manager.c
new file mode 100644
index 000000000..9c1375b79
--- /dev/null
+++ b/src/libimcv/pts/components/pts_component_manager.c
@@ -0,0 +1,315 @@
+/*
+ * Copyright (C) 2011-2012 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pts/components/pts_component_manager.h"
+
+#include <collections/linked_list.h>
+#include <utils/debug.h>
+
+typedef struct private_pts_component_manager_t private_pts_component_manager_t;
+typedef struct vendor_entry_t vendor_entry_t;
+typedef struct component_entry_t component_entry_t;
+
+#define PTS_QUALIFIER_SIZE 6
+
+/**
+ * Vendor-specific namespace information and list of registered components
+ */
+struct vendor_entry_t {
+
+ /**
+ * Vendor ID
+ */
+ pen_t vendor_id;
+
+ /**
+ * Vendor-specific Component Functional names
+ */
+ enum_name_t *comp_func_names;
+
+ /**
+ * Vendor-specific Qualifier Type names
+ */
+ enum_name_t *qualifier_type_names;
+
+ /**
+ * Vendor-specific Qualifier Flag names
+ */
+ char *qualifier_flag_names;
+
+ /**
+ * Vendor-specific size of Qualfiier Type field
+ */
+ int qualifier_type_size;
+
+ /**
+ * List of vendor-specific registered Functional Components
+ */
+ linked_list_t *components;
+};
+
+/**
+ * Destroy a vendor_entry_t object
+ */
+static void vendor_entry_destroy(vendor_entry_t *entry)
+{
+ entry->components->destroy_function(entry->components, free);
+ free(entry);
+}
+
+/**
+ * Creation method for a vendor-specific Functional Component
+ */
+struct component_entry_t {
+
+ /**
+ * Vendor-Specific Component Functional Name
+ */
+ u_int32_t name;
+
+ /**
+ * Functional Component creation method
+ */
+ pts_component_create_t create;
+};
+
+/**
+ * Private data of a pts_component_manager_t object.
+ *
+ */
+struct private_pts_component_manager_t {
+
+ /**
+ * Public pts_component_manager_t interface.
+ */
+ pts_component_manager_t public;
+
+ /**
+ * List of vendor-specific namespaces and registered components
+ */
+ linked_list_t *list;
+};
+
+METHOD(pts_component_manager_t, add_vendor, void,
+ private_pts_component_manager_t *this, pen_t vendor_id,
+ enum_name_t *comp_func_names, int qualifier_type_size,
+ char *qualifier_flag_names, enum_name_t *qualifier_type_names)
+{
+ vendor_entry_t *entry;
+
+ entry = malloc_thing(vendor_entry_t);
+ entry->vendor_id = vendor_id;
+ entry->comp_func_names = comp_func_names;
+ entry->qualifier_type_size = qualifier_type_size;
+ entry->qualifier_flag_names = qualifier_flag_names;
+ entry->qualifier_type_names = qualifier_type_names;
+ entry->components = linked_list_create();
+
+ this->list->insert_last(this->list, entry);
+ DBG2(DBG_PTS, "added %N functional component namespace",
+ pen_names, vendor_id);
+}
+
+METHOD(pts_component_manager_t, get_comp_func_names, enum_name_t*,
+ private_pts_component_manager_t *this, pen_t vendor_id)
+{
+ enumerator_t *enumerator;
+ vendor_entry_t *entry;
+ enum_name_t *names = NULL;
+
+ enumerator = this->list->create_enumerator(this->list);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->vendor_id == vendor_id)
+ {
+ names = entry->comp_func_names;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ return names;
+}
+
+METHOD(pts_component_manager_t, get_qualifier_type_names, enum_name_t*,
+ private_pts_component_manager_t *this, pen_t vendor_id)
+{
+ enumerator_t *enumerator;
+ vendor_entry_t *entry;
+ enum_name_t *names = NULL;
+
+ enumerator = this->list->create_enumerator(this->list);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->vendor_id == vendor_id)
+ {
+ names = entry->qualifier_type_names;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ return names;
+}
+
+METHOD(pts_component_manager_t, add_component, void,
+ private_pts_component_manager_t *this, pen_t vendor_id, u_int32_t name,
+ pts_component_create_t create)
+{
+ enumerator_t *enumerator;
+ vendor_entry_t *entry;
+ component_entry_t *component;
+
+ enumerator = this->list->create_enumerator(this->list);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->vendor_id == vendor_id)
+ {
+ component = malloc_thing(component_entry_t);
+ component->name = name;
+ component->create = create;
+
+ entry->components->insert_last(entry->components, component);
+ DBG2(DBG_PTS, "added %N functional component '%N'",
+ pen_names, vendor_id,
+ get_comp_func_names(this, vendor_id), name);
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+METHOD(pts_component_manager_t, remove_vendor, void,
+ private_pts_component_manager_t *this, pen_t vendor_id)
+{
+ enumerator_t *enumerator;
+ vendor_entry_t *entry;
+
+ enumerator = this->list->create_enumerator(this->list);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->vendor_id == vendor_id)
+ {
+ this->list->remove_at(this->list, enumerator);
+ vendor_entry_destroy(entry);
+ DBG2(DBG_PTS, "removed %N functional component namespace",
+ pen_names, vendor_id);
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+METHOD(pts_component_manager_t, get_qualifier, u_int8_t,
+ private_pts_component_manager_t *this, pts_comp_func_name_t *name,
+ char *flags)
+{
+ enumerator_t *enumerator;
+ vendor_entry_t *entry;
+ u_int8_t qualifier, size, flag, type = 0;
+ int i;
+
+ enumerator = this->list->create_enumerator(this->list);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->vendor_id == name->get_vendor_id(name))
+ {
+ qualifier = name->get_qualifier(name);
+ size = entry->qualifier_type_size;
+
+ /* mask qualifier type field */
+ type = qualifier & ((1 << size) - 1);
+
+ /* determine flags */
+ size = PTS_QUALIFIER_SIZE - size;
+ flag = (1 << (PTS_QUALIFIER_SIZE - 1));
+ if (flags)
+ {
+ for (i = 0 ; i < size; i++)
+ {
+ flags[i] = (qualifier & flag) ?
+ entry->qualifier_flag_names[i] : '.';
+ flag >>= 1;
+ }
+ flags[size] = '\0';
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ return type;
+}
+
+METHOD(pts_component_manager_t, create, pts_component_t*,
+ private_pts_component_manager_t *this,
+ pts_comp_func_name_t *name, u_int32_t depth, pts_database_t *pts_db)
+{
+ enumerator_t *enumerator, *e2;
+ vendor_entry_t *entry;
+ component_entry_t *entry2;
+ pts_component_t *component = NULL;
+
+ enumerator = this->list->create_enumerator(this->list);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->vendor_id == name->get_vendor_id(name))
+ {
+ e2 = entry->components->create_enumerator(entry->components);
+ while (e2->enumerate(e2, &entry2))
+ {
+ if (entry2->name == name->get_name(name) && entry2->create)
+ {
+ component = entry2->create(depth, pts_db);
+ break;
+ }
+ }
+ e2->destroy(e2);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ return component;
+}
+
+METHOD(pts_component_manager_t, destroy, void,
+ private_pts_component_manager_t *this)
+{
+ this->list->destroy_function(this->list, (void *)vendor_entry_destroy);
+ free(this);
+}
+
+/**
+ * See header
+ */
+pts_component_manager_t *pts_component_manager_create(void)
+{
+ private_pts_component_manager_t *this;
+
+ INIT(this,
+ .public = {
+ .add_vendor = _add_vendor,
+ .add_component = _add_component,
+ .remove_vendor = _remove_vendor,
+ .get_comp_func_names = _get_comp_func_names,
+ .get_qualifier_type_names = _get_qualifier_type_names,
+ .get_qualifier = _get_qualifier,
+ .create = _create,
+ .destroy = _destroy,
+ },
+ .list = linked_list_create(),
+ );
+
+ return &this->public;
+}
+
diff --git a/src/libimcv/pts/components/pts_component_manager.h b/src/libimcv/pts/components/pts_component_manager.h
new file mode 100644
index 000000000..61055ec74
--- /dev/null
+++ b/src/libimcv/pts/components/pts_component_manager.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2011 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts_component_manager pts_component_manager
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_COMPONENT_MANAGER_H_
+#define PTS_COMPONENT_MANAGER_H_
+
+typedef struct pts_component_manager_t pts_component_manager_t;
+
+#include "pts/pts_database.h"
+#include "pts/components/pts_component.h"
+#include "pts/components/pts_comp_func_name.h"
+
+#include <library.h>
+#include <pen/pen.h>
+
+typedef pts_component_t* (*pts_component_create_t)(u_int32_t depth,
+ pts_database_t *pts_db);
+
+/**
+ * Manages PTS Functional Components
+ */
+struct pts_component_manager_t {
+
+ /**
+ * Add vendor-specific functional component names
+ *
+ * @param vendor_id Private Enterprise Number (PEN)
+ * @param comp_func_names Vendor-specific Component Functional names
+ * @param qualifier_type_size Vendor-specific Qualifier Type size
+ * @param qualifier_flag_names Vendor-specific Qualifier Flag names
+ * @param qualifier_type_names Vendor-specific Qualifier Type names
+ */
+ void (*add_vendor)(pts_component_manager_t *this, pen_t vendor_id,
+ enum_name_t *comp_func_names,
+ int qualifier_type_size,
+ char *qualifier_flag_names,
+ enum_name_t *qualifier_type_names);
+
+ /**
+ * Add vendor-specific functional component
+ *
+ * @param vendor_id Private Enterprise Number (PEN)
+ * @param names Component Functional Name
+ * @param create Functional Component creation method
+ */
+ void (*add_component)(pts_component_manager_t *this, pen_t vendor_id,
+ u_int32_t name, pts_component_create_t create);
+
+ /**
+ * Remove vendor-specific components and associated namespace
+ *
+ * @param vendor_id Private Enterprise Number (PEN)
+ */
+ void (*remove_vendor)(pts_component_manager_t *this, pen_t vendor_id);
+
+ /**
+ * Return the Functional Component names for a given vendor ID
+ *
+ * @param vendor_id Private Enterprise Number (PEN)
+ * @return Comp. Func. names if found, NULL else
+ */
+ enum_name_t* (*get_comp_func_names)(pts_component_manager_t *this,
+ pen_t vendor_id);
+
+ /**
+ * Return the Functional Component Qualifier Type names for a given vendor ID
+ *
+ * @param vendor_id Private Enterprise Number (PEN)
+ * @return Qualifier Type names if found, NULL else
+ */
+ enum_name_t* (*get_qualifier_type_names)(pts_component_manager_t *this,
+ pen_t vendor_id);
+
+ /**
+ * Return the Qualifier Type and Flags
+ *
+ * @param name Component Functional Name
+ * @param flags Qualifier Flags as a string in a char buffer
+ * @return Qualifier Type
+ */
+ u_int8_t (*get_qualifier)(pts_component_manager_t *this,
+ pts_comp_func_name_t *name, char *flags);
+
+ /**
+ * Create a PTS Component object from a Functional Component Name object
+ *
+ * @param name Component Functional Name
+ * @param depth Sub-component Depth
+ * @param pts_db PTS measurement database
+ * @return Component object if supported, NULL else
+ */
+ pts_component_t* (*create)(pts_component_manager_t *this,
+ pts_comp_func_name_t *name, u_int32_t depth,
+ pts_database_t *pts_db);
+
+ /**
+ * Destroys a pts_component_manager_t object.
+ */
+ void (*destroy)(pts_component_manager_t *this);
+};
+
+/**
+ * Create a PA-TNC attribute manager
+ */
+pts_component_manager_t* pts_component_manager_create(void);
+
+#endif /** PTS_COMPONENT_MANAGER_H_ @}*/
diff --git a/src/libimcv/pts/components/tcg/tcg_comp_func_name.c b/src/libimcv/pts/components/tcg/tcg_comp_func_name.c
new file mode 100644
index 000000000..a70c84e48
--- /dev/null
+++ b/src/libimcv/pts/components/tcg/tcg_comp_func_name.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2011 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tcg_comp_func_name.h"
+
+char pts_tcg_qualifier_flag_names[] = { 'K', 'S' };
+
+ENUM_BEGIN(pts_tcg_qualifier_type_names, PTS_TCG_QUALIFIER_TYPE_UNKNOWN,
+ PTS_TCG_QUALIFIER_TYPE_TNC,
+ "Unknown",
+ "Trusted Platform",
+ "Operating System",
+ "Graphical User Interface",
+ "Application",
+ "Networking",
+ "Library",
+ "TNC Defined Component"
+);
+ENUM_NEXT(pts_tcg_qualifier_type_names, PTS_TCG_QUALIFIER_TYPE_ALL,
+ PTS_TCG_QUALIFIER_TYPE_ALL,
+ PTS_TCG_QUALIFIER_TYPE_TNC,
+ "All Matching Components"
+);
+ENUM_END(pts_tcg_qualifier_type_names, PTS_TCG_QUALIFIER_TYPE_ALL);
+
+ENUM(pts_tcg_comp_func_names, PTS_TCG_COMP_FUNC_NAME_IGNORE,
+ PTS_TCG_COMP_FUNC_NAME_OPT_ROMS,
+ "Ignore",
+ "CRTM",
+ "BIOS",
+ "Platform Extensions",
+ "Motherboard Firmware",
+ "Initial Program Loader",
+ "Option ROMs"
+);
+
diff --git a/src/libimcv/pts/components/tcg/tcg_comp_func_name.h b/src/libimcv/pts/components/tcg/tcg_comp_func_name.h
new file mode 100644
index 000000000..9708ad09d
--- /dev/null
+++ b/src/libimcv/pts/components/tcg/tcg_comp_func_name.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts_tcg_comp_func_name pts_tcg_comp_func_name
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_TCG_COMP_FUNC_NAME_H_
+#define PTS_TCG_COMP_FUNC_NAME_H_
+
+typedef enum pts_tcg_qualifier_type_t pts_tcg_qualifier_type_t;
+typedef enum pts_tcg_comp_func_name_t pts_tcp_comp_func_name_t;
+
+#include <library.h>
+
+/**
+ * PTS Component Functional Name Qualifier Flags for the TCG namespace
+ * see section 5.2 of PTS Protocol: Binding to TNC IF-M Specification
+ *
+ * 0 1 2 3 4 5
+ * +-+-+-+-+-+-+
+ * |K|S| Type |
+ * +-+-+-+-+-+-+
+ */
+#define PTS_TCG_QUALIFIER_FLAG_KERNEL (1<<5)
+#define PTS_TCG_QUALIFIER_FLAG_SUB (1<<4)
+
+extern char pts_tcg_qualifier_flag_names[];
+
+/**
+ * Size of the PTS Component Functional Name Qualifier Type field
+ */
+#define PTS_TCG_QUALIFIER_TYPE_SIZE 4
+
+/**
+ * PTS Component Functional Name Qualifier Types for the TCG namespace
+ * see section 5.2 of PTS Protocol: Binding to TNC IF-M Specification
+ */
+enum pts_tcg_qualifier_type_t {
+ /** Unknown */
+ PTS_TCG_QUALIFIER_TYPE_UNKNOWN = 0x0,
+ /** Trusted Platform */
+ PTS_TCG_QUALIFIER_TYPE_TRUSTED = 0x1,
+ /** Operating System */
+ PTS_TCG_QUALIFIER_TYPE_OS = 0x2,
+ /** Graphical User Interface */
+ PTS_TCG_QUALIFIER_TYPE_GUI = 0x3,
+ /** Application */
+ PTS_TCG_QUALIFIER_TYPE_APP = 0x4,
+ /** Networking */
+ PTS_TCG_QUALIFIER_TYPE_NET = 0x5,
+ /** Library */
+ PTS_TCG_QUALIFIER_TYPE_LIB = 0x6,
+ /** TNC Defined Component */
+ PTS_TCG_QUALIFIER_TYPE_TNC = 0x7,
+ /** All matching Components */
+ PTS_TCG_QUALIFIER_TYPE_ALL = 0xF,
+};
+
+extern enum_name_t *pts_tcg_qualifier_type_names;
+
+/**
+ * PTS Component Functional Name Binary Enumeration for the TCG namespace
+ * see section 5.3 of PTS Protocol: Binding to TNC IF-M Specification
+ */
+enum pts_tcg_comp_func_name_t {
+ /** Ignore */
+ PTS_TCG_COMP_FUNC_NAME_IGNORE = 0x0000,
+ /** CRTM */
+ PTS_TCG_COMP_FUNC_NAME_CRTM = 0x0001,
+ /** BIOS */
+ PTS_TCG_COMP_FUNC_NAME_BIOS = 0x0002,
+ /** Platform Extensions */
+ PTS_TCG_COMP_FUNC_NAME_PLATFORM_EXT = 0x0003,
+ /** Motherboard Firmware */
+ PTS_TCG_COMP_FUNC_NAME_BOARD = 0x0004,
+ /** Initial Program Loader */
+ PTS_TCG_COMP_FUNC_NAME_INIT_LOADER = 0x0005,
+ /** Option ROMs */
+ PTS_TCG_COMP_FUNC_NAME_OPT_ROMS = 0x0006,
+};
+
+extern enum_name_t *pts_tcg_comp_func_names;
+
+#endif /** PTS_TCG_COMP_FUNC_NAME_H_ @}*/
diff --git a/src/libimcv/pts/pts.c b/src/libimcv/pts/pts.c
new file mode 100644
index 000000000..2fff4c901
--- /dev/null
+++ b/src/libimcv/pts/pts.c
@@ -0,0 +1,1198 @@
+/*
+ * Copyright (C) 2011-2012 Sansar Choinyambuu
+ * Copyright (C) 2012-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pts.h"
+
+#include <utils/debug.h>
+#include <crypto/hashers/hasher.h>
+#include <bio/bio_writer.h>
+#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
+#ifndef TPM_TAG_QUOTE_INFO2
+#define TPM_TAG_QUOTE_INFO2 0x0036
+#endif
+#ifndef TPM_LOC_ZERO
+#define TPM_LOC_ZERO 0x01
+#endif
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <libgen.h>
+#include <unistd.h>
+#include <errno.h>
+
+typedef struct private_pts_t private_pts_t;
+
+/**
+ * Private data of a pts_t object.
+ *
+ */
+struct private_pts_t {
+
+ /**
+ * Public pts_t interface.
+ */
+ pts_t public;
+
+ /**
+ * PTS Protocol Capabilities
+ */
+ pts_proto_caps_flag_t proto_caps;
+
+ /**
+ * PTS Measurement Algorithm
+ */
+ pts_meas_algorithms_t algorithm;
+
+ /**
+ * DH Hash Algorithm
+ */
+ pts_meas_algorithms_t dh_hash_algorithm;
+
+ /**
+ * PTS Diffie-Hellman Secret
+ */
+ diffie_hellman_t *dh;
+
+ /**
+ * PTS Diffie-Hellman Initiator Nonce
+ */
+ chunk_t initiator_nonce;
+
+ /**
+ * PTS Diffie-Hellman Responder Nonce
+ */
+ chunk_t responder_nonce;
+
+ /**
+ * Secret assessment value to be used for TPM Quote as an external data
+ */
+ chunk_t secret;
+
+ /**
+ * Primary key of platform entry in database
+ */
+ int platform_id;
+
+ /**
+ * TRUE if IMC-PTS, FALSE if IMV-PTS
+ */
+ bool is_imc;
+
+ /**
+ * Do we have an activated TPM
+ */
+ bool has_tpm;
+
+ /**
+ * Contains a TPM_CAP_VERSION_INFO struct
+ */
+ chunk_t tpm_version_info;
+
+ /**
+ * Contains TSS Blob structure for AIK
+ */
+ chunk_t aik_blob;
+
+ /**
+ * Contains a Attestation Identity Key or Certificate
+ */
+ certificate_t *aik;
+
+ /**
+ * Primary key referening AIK in database
+ */
+ int aik_id;
+
+ /**
+ * Shadow PCR set
+ */
+ pts_pcr_t *pcrs;
+
+};
+
+METHOD(pts_t, get_proto_caps, pts_proto_caps_flag_t,
+ private_pts_t *this)
+{
+ return this->proto_caps;
+}
+
+METHOD(pts_t, set_proto_caps, void,
+ private_pts_t *this, pts_proto_caps_flag_t flags)
+{
+ this->proto_caps = flags;
+ DBG2(DBG_PTS, "supported PTS protocol capabilities: %s%s%s%s%s",
+ flags & PTS_PROTO_CAPS_C ? "C" : ".",
+ flags & PTS_PROTO_CAPS_V ? "V" : ".",
+ flags & PTS_PROTO_CAPS_D ? "D" : ".",
+ flags & PTS_PROTO_CAPS_T ? "T" : ".",
+ flags & PTS_PROTO_CAPS_X ? "X" : ".");
+}
+
+METHOD(pts_t, get_meas_algorithm, pts_meas_algorithms_t,
+ private_pts_t *this)
+{
+ return this->algorithm;
+}
+
+METHOD(pts_t, set_meas_algorithm, void,
+ private_pts_t *this, pts_meas_algorithms_t algorithm)
+{
+ hash_algorithm_t hash_alg;
+
+ hash_alg = pts_meas_algo_to_hash(algorithm);
+ DBG2(DBG_PTS, "selected PTS measurement algorithm is %N",
+ hash_algorithm_names, hash_alg);
+ if (hash_alg != HASH_UNKNOWN)
+ {
+ this->algorithm = algorithm;
+ }
+}
+
+METHOD(pts_t, get_dh_hash_algorithm, pts_meas_algorithms_t,
+ private_pts_t *this)
+{
+ return this->dh_hash_algorithm;
+}
+
+METHOD(pts_t, set_dh_hash_algorithm, void,
+ private_pts_t *this, pts_meas_algorithms_t algorithm)
+{
+ hash_algorithm_t hash_alg;
+
+ hash_alg = pts_meas_algo_to_hash(algorithm);
+ DBG2(DBG_PTS, "selected DH hash algorithm is %N",
+ hash_algorithm_names, hash_alg);
+ if (hash_alg != HASH_UNKNOWN)
+ {
+ this->dh_hash_algorithm = algorithm;
+ }
+}
+
+
+METHOD(pts_t, create_dh_nonce, bool,
+ private_pts_t *this, pts_dh_group_t group, int nonce_len)
+{
+ diffie_hellman_group_t dh_group;
+ chunk_t *nonce;
+ rng_t *rng;
+
+ dh_group = pts_dh_group_to_ike(group);
+ DBG2(DBG_PTS, "selected PTS DH group is %N",
+ diffie_hellman_group_names, dh_group);
+ DESTROY_IF(this->dh);
+ this->dh = lib->crypto->create_dh(lib->crypto, dh_group);
+
+ rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
+ if (!rng)
+ {
+ DBG1(DBG_PTS, "no rng available");
+ return FALSE;
+ }
+ DBG2(DBG_PTS, "nonce length is %d", nonce_len);
+ nonce = this->is_imc ? &this->responder_nonce : &this->initiator_nonce;
+ chunk_free(nonce);
+ if (!rng->allocate_bytes(rng, nonce_len, nonce))
+ {
+ DBG1(DBG_PTS, "failed to allocate nonce");
+ rng->destroy(rng);
+ return FALSE;
+ }
+ rng->destroy(rng);
+ return TRUE;
+}
+
+METHOD(pts_t, get_my_public_value, void,
+ private_pts_t *this, chunk_t *value, chunk_t *nonce)
+{
+ this->dh->get_my_public_value(this->dh, value);
+ *nonce = this->is_imc ? this->responder_nonce : this->initiator_nonce;
+}
+
+METHOD(pts_t, set_peer_public_value, void,
+ private_pts_t *this, chunk_t value, chunk_t nonce)
+{
+ this->dh->set_other_public_value(this->dh, value);
+
+ nonce = chunk_clone(nonce);
+ if (this->is_imc)
+ {
+ this->initiator_nonce = nonce;
+ }
+ else
+ {
+ this->responder_nonce = nonce;
+ }
+}
+
+METHOD(pts_t, calculate_secret, bool,
+ private_pts_t *this)
+{
+ hasher_t *hasher;
+ hash_algorithm_t hash_alg;
+ chunk_t shared_secret;
+
+ /* Check presence of nonces */
+ if (!this->initiator_nonce.len || !this->responder_nonce.len)
+ {
+ DBG1(DBG_PTS, "initiator and/or responder nonce is not available");
+ return FALSE;
+ }
+ DBG3(DBG_PTS, "initiator nonce: %B", &this->initiator_nonce);
+ DBG3(DBG_PTS, "responder nonce: %B", &this->responder_nonce);
+
+ /* Calculate the DH secret */
+ if (this->dh->get_shared_secret(this->dh, &shared_secret) != SUCCESS)
+ {
+ DBG1(DBG_PTS, "shared DH secret computation failed");
+ return FALSE;
+ }
+ DBG3(DBG_PTS, "shared DH secret: %B", &shared_secret);
+
+ /* Calculate the secret assessment value */
+ hash_alg = pts_meas_algo_to_hash(this->dh_hash_algorithm);
+ hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
+
+ if (!hasher ||
+ !hasher->get_hash(hasher, chunk_from_chars('1'), NULL) ||
+ !hasher->get_hash(hasher, this->initiator_nonce, NULL) ||
+ !hasher->get_hash(hasher, this->responder_nonce, NULL) ||
+ !hasher->allocate_hash(hasher, shared_secret, &this->secret))
+ {
+ DESTROY_IF(hasher);
+ return FALSE;
+ }
+ hasher->destroy(hasher);
+
+ /* The DH secret must be destroyed */
+ chunk_clear(&shared_secret);
+
+ /*
+ * Truncate the hash to 20 bytes to fit the ExternalData
+ * argument of the TPM Quote command
+ */
+ this->secret.len = min(this->secret.len, 20);
+ DBG3(DBG_PTS, "secret assessment value: %B", &this->secret);
+ return TRUE;
+}
+
+#ifdef TSS_TROUSERS
+
+/**
+ * Print TPM 1.2 Version Info
+ */
+static void print_tpm_version_info(private_pts_t *this)
+{
+ TPM_CAP_VERSION_INFO *info;
+
+ info = (TPM_CAP_VERSION_INFO*)this->tpm_version_info.ptr;
+
+ if (this->tpm_version_info.len >=
+ sizeof(*info) - sizeof(info->vendorSpecific))
+ {
+ 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
+ {
+ DBG1(DBG_PTS, "could not parse tpm version info");
+ }
+}
+
+#else
+
+static void print_tpm_version_info(private_pts_t *this)
+{
+ DBG1(DBG_PTS, "unknown TPM version: no TSS implementation available");
+}
+
+#endif /* TSS_TROUSERS */
+
+METHOD(pts_t, get_platform_id, int,
+ private_pts_t *this)
+{
+ return this->platform_id;
+}
+
+METHOD(pts_t, set_platform_id, void,
+ private_pts_t *this, int pid)
+{
+ this->platform_id = pid;
+}
+
+METHOD(pts_t, get_tpm_version_info, bool,
+ private_pts_t *this, chunk_t *info)
+{
+ if (!this->has_tpm)
+ {
+ return FALSE;
+ }
+ *info = this->tpm_version_info;
+ print_tpm_version_info(this);
+ return TRUE;
+}
+
+METHOD(pts_t, set_tpm_version_info, void,
+ private_pts_t *this, chunk_t info)
+{
+ this->tpm_version_info = chunk_clone(info);
+ print_tpm_version_info(this);
+}
+
+/**
+ * Load an AIK Blob (TSS_TSPATTRIB_KEYBLOB_BLOB attribute)
+ */
+static void load_aik_blob(private_pts_t *this)
+{
+ char *path;
+ chunk_t *map;
+
+ path = lib->settings->get_str(lib->settings,
+ "%s.plugins.imc-attestation.aik_blob", NULL, lib->ns);
+ if (path)
+ {
+ map = chunk_map(path, FALSE);
+ if (map)
+ {
+ 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 map AIK Blob file '%s': %s",
+ path, strerror(errno));
+ }
+ }
+ else
+ {
+ DBG1(DBG_PTS, "AIK Blob is not available");
+ }
+}
+
+/**
+ * Load an AIK certificate or public key
+ * the certificate having precedence over the public key if both are present
+ */
+static void load_aik(private_pts_t *this)
+{
+ char *cert_path, *key_path;
+
+ 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_pubkey", NULL, lib->ns);
+
+ if (cert_path)
+ {
+ this->aik = lib->creds->create(lib->creds, CRED_CERTIFICATE,
+ CERT_X509, BUILD_FROM_FILE,
+ cert_path, BUILD_END);
+ if (this->aik)
+ {
+ DBG2(DBG_PTS, "loaded AIK certificate from '%s'", cert_path);
+ return;
+ }
+ }
+ if (key_path)
+ {
+ this->aik = lib->creds->create(lib->creds, CRED_CERTIFICATE,
+ CERT_TRUSTED_PUBKEY, BUILD_FROM_FILE,
+ key_path, BUILD_END);
+ if (this->aik)
+ {
+ DBG2(DBG_PTS, "loaded AIK public key from '%s'", key_path);
+ return;
+ }
+ }
+
+ DBG1(DBG_PTS, "neither AIK certificate nor public key is available");
+}
+
+METHOD(pts_t, get_aik, certificate_t*,
+ private_pts_t *this)
+{
+ return this->aik;
+}
+
+METHOD(pts_t, set_aik, void,
+ 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_id, int,
+ private_pts_t *this)
+{
+ return this->aik_id;
+}
+
+METHOD(pts_t, is_path_valid, bool,
+ private_pts_t *this, char *path, pts_error_code_t *error_code)
+{
+ struct stat st;
+
+ *error_code = 0;
+
+ if (!stat(path, &st))
+ {
+ return TRUE;
+ }
+ else if (errno == ENOENT || errno == ENOTDIR)
+ {
+ DBG1(DBG_PTS, "file/directory does not exist %s", path);
+ *error_code = TCG_PTS_FILE_NOT_FOUND;
+ }
+ else if (errno == EFAULT)
+ {
+ DBG1(DBG_PTS, "bad address %s", path);
+ *error_code = TCG_PTS_INVALID_PATH;
+ }
+ else
+ {
+ DBG1(DBG_PTS, "error: %s occurred while validating path: %s",
+ strerror(errno), path);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ * Obtain statistical information describing a file
+ */
+static bool file_metadata(char *pathname, pts_file_metadata_t **entry)
+{
+ struct stat st;
+ pts_file_metadata_t *this;
+
+ this = malloc_thing(pts_file_metadata_t);
+
+ if (stat(pathname, &st))
+ {
+ DBG1(DBG_PTS, "unable to obtain statistics about '%s'", pathname);
+ free(this);
+ return FALSE;
+ }
+
+ if (S_ISREG(st.st_mode))
+ {
+ this->type = PTS_FILE_REGULAR;
+ }
+ else if (S_ISDIR(st.st_mode))
+ {
+ this->type = PTS_FILE_DIRECTORY;
+ }
+ else if (S_ISCHR(st.st_mode))
+ {
+ this->type = PTS_FILE_CHAR_SPEC;
+ }
+ else if (S_ISBLK(st.st_mode))
+ {
+ this->type = PTS_FILE_BLOCK_SPEC;
+ }
+ else if (S_ISFIFO(st.st_mode))
+ {
+ this->type = PTS_FILE_FIFO;
+ }
+#ifndef WIN32
+ else if (S_ISLNK(st.st_mode))
+ {
+ this->type = PTS_FILE_SYM_LINK;
+ }
+ else if (S_ISSOCK(st.st_mode))
+ {
+ this->type = PTS_FILE_SOCKET;
+ }
+#endif /* WIN32 */
+ else
+ {
+ this->type = PTS_FILE_OTHER;
+ }
+
+ this->filesize = st.st_size;
+ this->created = st.st_ctime;
+ this->modified = st.st_mtime;
+ this->accessed = st.st_atime;
+ this->owner = st.st_uid;
+ this->group = st.st_gid;
+
+ *entry = this;
+ return TRUE;
+}
+
+METHOD(pts_t, get_metadata, pts_file_meta_t*,
+ private_pts_t *this, char *pathname, bool is_directory)
+{
+ pts_file_meta_t *metadata;
+ pts_file_metadata_t *entry;
+
+ /* Create a metadata object */
+ metadata = pts_file_meta_create();
+
+ if (is_directory)
+ {
+ enumerator_t *enumerator;
+ char *rel_name, *abs_name;
+ struct stat st;
+
+ enumerator = enumerator_create_directory(pathname);
+ if (!enumerator)
+ {
+ DBG1(DBG_PTS," directory '%s' can not be opened, %s", pathname,
+ strerror(errno));
+ metadata->destroy(metadata);
+ return NULL;
+ }
+ while (enumerator->enumerate(enumerator, &rel_name, &abs_name, &st))
+ {
+ /* measure regular files only */
+ if (S_ISREG(st.st_mode) && *rel_name != '.')
+ {
+ if (!file_metadata(abs_name, &entry))
+ {
+ enumerator->destroy(enumerator);
+ metadata->destroy(metadata);
+ return NULL;
+ }
+ entry->filename = strdup(rel_name);
+ metadata->add(metadata, entry);
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ else
+ {
+ if (!file_metadata(pathname, &entry))
+ {
+ metadata->destroy(metadata);
+ return NULL;
+ }
+ entry->filename = path_basename(pathname);
+ metadata->add(metadata, entry);
+ }
+
+ return metadata;
+}
+
+
+#ifdef TSS_TROUSERS
+
+METHOD(pts_t, read_pcr, bool,
+ private_pts_t *this, u_int32_t pcr_num, chunk_t *pcr_value)
+{
+ TSS_HCONTEXT hContext;
+ TSS_HTPM hTPM;
+ TSS_RESULT result;
+ BYTE *buf;
+ UINT32 len;
+
+ bool success = FALSE;
+
+ result = Tspi_Context_Create(&hContext);
+ if (result != TSS_SUCCESS)
+ {
+ DBG1(DBG_PTS, "TPM context could not be created: tss error 0x%x", result);
+ return FALSE;
+ }
+
+ result = Tspi_Context_Connect(hContext, NULL);
+ if (result != TSS_SUCCESS)
+ {
+ goto err;
+ }
+ result = Tspi_Context_GetTpmObject (hContext, &hTPM);
+ if (result != TSS_SUCCESS)
+ {
+ goto err;
+ }
+ result = Tspi_TPM_PcrRead(hTPM, pcr_num, &len, &buf);
+ if (result != TSS_SUCCESS)
+ {
+ goto err;
+ }
+ *pcr_value = chunk_clone(chunk_create(buf, len));
+ DBG3(DBG_PTS, "PCR %d value:%B", pcr_num, pcr_value);
+ success = TRUE;
+
+err:
+ if (!success)
+ {
+ DBG1(DBG_PTS, "TPM not available: tss error 0x%x", result);
+ }
+ Tspi_Context_FreeMemory(hContext, NULL);
+ Tspi_Context_Close(hContext);
+
+ return success;
+}
+
+METHOD(pts_t, extend_pcr, bool,
+ private_pts_t *this, u_int32_t pcr_num, chunk_t input, chunk_t *output)
+{
+ TSS_HCONTEXT hContext;
+ TSS_HTPM hTPM;
+ TSS_RESULT result;
+ u_int32_t pcr_length;
+ chunk_t pcr_value = chunk_empty;
+
+ result = Tspi_Context_Create(&hContext);
+ if (result != TSS_SUCCESS)
+ {
+ DBG1(DBG_PTS, "TPM context could not be created: tss error 0x%x",
+ result);
+ return FALSE;
+ }
+ result = Tspi_Context_Connect(hContext, NULL);
+ if (result != TSS_SUCCESS)
+ {
+ goto err;
+ }
+ result = Tspi_Context_GetTpmObject (hContext, &hTPM);
+ if (result != TSS_SUCCESS)
+ {
+ goto err;
+ }
+
+ pcr_value = chunk_alloc(PTS_PCR_LEN);
+ result = Tspi_TPM_PcrExtend(hTPM, pcr_num, PTS_PCR_LEN, input.ptr,
+ NULL, &pcr_length, &pcr_value.ptr);
+ if (result != TSS_SUCCESS)
+ {
+ goto err;
+ }
+
+ *output = pcr_value;
+ *output = chunk_clone(*output);
+
+ DBG3(DBG_PTS, "PCR %d extended with: %B", pcr_num, &input);
+ DBG3(DBG_PTS, "PCR %d value after extend: %B", pcr_num, output);
+
+ chunk_clear(&pcr_value);
+ Tspi_Context_FreeMemory(hContext, NULL);
+ Tspi_Context_Close(hContext);
+
+ return TRUE;
+
+err:
+ DBG1(DBG_PTS, "TPM not available: tss error 0x%x", result);
+
+ chunk_clear(&pcr_value);
+ Tspi_Context_FreeMemory(hContext, NULL);
+ Tspi_Context_Close(hContext);
+
+ return FALSE;
+}
+
+METHOD(pts_t, quote_tpm, bool,
+ private_pts_t *this, bool use_quote2, chunk_t *pcr_comp, chunk_t *quote_sig)
+{
+ TSS_HCONTEXT hContext;
+ TSS_HTPM hTPM;
+ TSS_HKEY hAIK;
+ TSS_HKEY hSRK;
+ TSS_HPOLICY srkUsagePolicy;
+ TSS_UUID SRK_UUID = TSS_UUID_SRK;
+ BYTE secret[] = TSS_WELL_KNOWN_SECRET;
+ TSS_HPCRS hPcrComposite;
+ TSS_VALIDATION valData;
+ TSS_RESULT result;
+ chunk_t quote_info;
+ BYTE* versionInfo;
+ u_int32_t versionInfoSize, pcr;
+ enumerator_t *enumerator;
+ bool success = FALSE;
+
+ result = Tspi_Context_Create(&hContext);
+ if (result != TSS_SUCCESS)
+ {
+ DBG1(DBG_PTS, "TPM context could not be created: tss error 0x%x",
+ result);
+ return FALSE;
+ }
+ result = Tspi_Context_Connect(hContext, NULL);
+ if (result != TSS_SUCCESS)
+ {
+ goto err1;
+ }
+ result = Tspi_Context_GetTpmObject (hContext, &hTPM);
+ if (result != TSS_SUCCESS)
+ {
+ goto err1;
+ }
+
+ /* Retrieve SRK from TPM and set the authentication to well known secret*/
+ result = Tspi_Context_LoadKeyByUUID(hContext, TSS_PS_TYPE_SYSTEM,
+ SRK_UUID, &hSRK);
+ if (result != TSS_SUCCESS)
+ {
+ goto err1;
+ }
+
+ result = Tspi_GetPolicyObject(hSRK, TSS_POLICY_USAGE, &srkUsagePolicy);
+ if (result != TSS_SUCCESS)
+ {
+ goto err1;
+ }
+ result = Tspi_Policy_SetSecret(srkUsagePolicy, TSS_SECRET_MODE_SHA1,
+ 20, secret);
+ if (result != TSS_SUCCESS)
+ {
+ goto err1;
+ }
+
+ result = Tspi_Context_LoadKeyByBlob (hContext, hSRK, this->aik_blob.len,
+ this->aik_blob.ptr, &hAIK);
+ if (result != TSS_SUCCESS)
+ {
+ goto err1;
+ }
+
+ /* Create PCR composite object */
+ result = use_quote2 ?
+ Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_PCRS,
+ TSS_PCRS_STRUCT_INFO_SHORT, &hPcrComposite) :
+ Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_PCRS,
+ TSS_PCRS_STRUCT_DEFAULT, &hPcrComposite);
+ if (result != TSS_SUCCESS)
+ {
+ goto err2;
+ }
+
+ /* Select PCRs */
+ enumerator = this->pcrs->create_enumerator(this->pcrs);
+ while (enumerator->enumerate(enumerator, &pcr))
+ {
+ result = use_quote2 ?
+ Tspi_PcrComposite_SelectPcrIndexEx(hPcrComposite, pcr,
+ TSS_PCRS_DIRECTION_RELEASE) :
+ Tspi_PcrComposite_SelectPcrIndex(hPcrComposite, pcr);
+ if (result != TSS_SUCCESS)
+ {
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (result != TSS_SUCCESS)
+ {
+ goto err3;
+ }
+
+ /* Set the Validation Data */
+ valData.ulExternalDataLength = this->secret.len;
+ valData.rgbExternalData = (BYTE *)this->secret.ptr;
+
+
+ /* TPM Quote */
+ result = use_quote2 ?
+ Tspi_TPM_Quote2(hTPM, hAIK, FALSE, hPcrComposite, &valData,
+ &versionInfoSize, &versionInfo):
+ Tspi_TPM_Quote(hTPM, hAIK, hPcrComposite, &valData);
+ if (result != TSS_SUCCESS)
+ {
+ goto err4;
+ }
+
+ /* Set output chunks */
+ *pcr_comp = chunk_alloc(HASH_SIZE_SHA1);
+
+ if (use_quote2)
+ {
+ /* TPM_Composite_Hash is last 20 bytes of TPM_Quote_Info2 structure */
+ memcpy(pcr_comp->ptr, valData.rgbData + valData.ulDataLength - HASH_SIZE_SHA1,
+ HASH_SIZE_SHA1);
+ }
+ else
+ {
+ /* TPM_Composite_Hash is 8-28th bytes of TPM_Quote_Info structure */
+ memcpy(pcr_comp->ptr, valData.rgbData + 8, HASH_SIZE_SHA1);
+ }
+ DBG3(DBG_PTS, "Hash of PCR Composite: %#B", pcr_comp);
+
+ quote_info = chunk_create(valData.rgbData, valData.ulDataLength);
+ DBG3(DBG_PTS, "TPM Quote Info: %B",&quote_info);
+
+ *quote_sig = chunk_clone(chunk_create(valData.rgbValidationData,
+ valData.ulValidationDataLength));
+ DBG3(DBG_PTS, "TPM Quote Signature: %B",quote_sig);
+
+ success = TRUE;
+
+ /* Cleanup */
+err4:
+ Tspi_Context_FreeMemory(hContext, NULL);
+
+err3:
+ Tspi_Context_CloseObject(hContext, hPcrComposite);
+
+err2:
+ Tspi_Context_CloseObject(hContext, hAIK);
+
+err1:
+ Tspi_Context_Close(hContext);
+ if (!success)
+ {
+ DBG1(DBG_PTS, "TPM not available: tss error 0x%x", result);
+ }
+ return success;
+}
+
+#else /* TSS_TROUSERS */
+
+METHOD(pts_t, read_pcr, bool,
+ private_pts_t *this, u_int32_t pcr_num, chunk_t *pcr_value)
+{
+ return FALSE;
+}
+
+METHOD(pts_t, extend_pcr, bool,
+ private_pts_t *this, u_int32_t pcr_num, chunk_t input, chunk_t *output)
+{
+ return FALSE;
+}
+
+METHOD(pts_t, quote_tpm, bool,
+ private_pts_t *this, bool use_quote2, chunk_t *pcr_comp, chunk_t *quote_sig)
+{
+ return FALSE;
+}
+
+#endif /* TSS_TROUSERS */
+
+/**
+ * TPM_QUOTE_INFO structure:
+ * 4 bytes of version
+ * 4 bytes 'Q' 'U' 'O' 'T'
+ * 20 byte SHA1 of TCPA_PCR_COMPOSITE
+ * 20 byte nonce
+ *
+ * TPM_QUOTE_INFO2 structure:
+ * 2 bytes Tag 0x0036 TPM_Tag_Quote_info2
+ * 4 bytes 'Q' 'U' 'T' '2'
+ * 20 bytes nonce
+ * 26 bytes PCR_INFO_SHORT
+ */
+
+METHOD(pts_t, get_quote_info, bool,
+ private_pts_t *this, bool use_quote2, bool use_ver_info,
+ pts_meas_algorithms_t comp_hash_algo,
+ chunk_t *out_pcr_comp, chunk_t *out_quote_info)
+{
+ chunk_t selection, pcr_comp, hash_pcr_comp;
+ bio_writer_t *writer;
+ hasher_t *hasher;
+
+ if (!this->pcrs->get_count(this->pcrs))
+ {
+ DBG1(DBG_PTS, "No extended PCR entries available, "
+ "unable to construct TPM Quote Info");
+ return FALSE;
+ }
+ if (!this->secret.ptr)
+ {
+ DBG1(DBG_PTS, "Secret assessment value unavailable, ",
+ "unable to construct TPM Quote Info");
+ return FALSE;
+ }
+ if (use_quote2 && use_ver_info && !this->tpm_version_info.ptr)
+ {
+ DBG1(DBG_PTS, "TPM Version Information unavailable, ",
+ "unable to construct TPM Quote Info2");
+ return FALSE;
+ }
+
+ pcr_comp = this->pcrs->get_composite(this->pcrs);
+
+
+ /* Output the TPM_PCR_COMPOSITE expected from IMC */
+ if (comp_hash_algo)
+ {
+ hash_algorithm_t algo;
+
+ algo = pts_meas_algo_to_hash(comp_hash_algo);
+ hasher = lib->crypto->create_hasher(lib->crypto, algo);
+
+ /* Hash the PCR Composite Structure */
+ if (!hasher || !hasher->allocate_hash(hasher, pcr_comp, out_pcr_comp))
+ {
+ DESTROY_IF(hasher);
+ free(pcr_comp.ptr);
+ return FALSE;
+ }
+ DBG3(DBG_PTS, "constructed PCR Composite hash: %#B", out_pcr_comp);
+ hasher->destroy(hasher);
+ }
+ else
+ {
+ *out_pcr_comp = chunk_clone(pcr_comp);
+ }
+
+ /* SHA1 hash of PCR Composite to construct TPM_QUOTE_INFO */
+ hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
+ if (!hasher || !hasher->allocate_hash(hasher, pcr_comp, &hash_pcr_comp))
+ {
+ DESTROY_IF(hasher);
+ chunk_free(out_pcr_comp);
+ free(pcr_comp.ptr);
+ return FALSE;
+ }
+ hasher->destroy(hasher);
+
+ /* Construct TPM_QUOTE_INFO/TPM_QUOTE_INFO2 structure */
+ writer = bio_writer_create(TPM_QUOTE_INFO_LEN);
+
+ if (use_quote2)
+ {
+ /* TPM Structure Tag */
+ writer->write_uint16(writer, TPM_TAG_QUOTE_INFO2);
+
+ /* Magic QUT2 value */
+ writer->write_data(writer, chunk_create("QUT2", 4));
+
+ /* Secret assessment value 20 bytes (nonce) */
+ writer->write_data(writer, this->secret);
+
+ /* PCR selection */
+ selection.ptr = pcr_comp.ptr;
+ selection.len = 2 + this->pcrs->get_selection_size(this->pcrs);
+ writer->write_data(writer, selection);
+
+ /* TPM Locality Selection */
+ writer->write_uint8(writer, TPM_LOC_ZERO);
+
+ /* PCR Composite Hash */
+ writer->write_data(writer, hash_pcr_comp);
+
+ if (use_ver_info)
+ {
+ /* TPM version Info */
+ writer->write_data(writer, this->tpm_version_info);
+ }
+ }
+ else
+ {
+ /* Version number */
+ writer->write_data(writer, chunk_from_chars(1, 1, 0, 0));
+
+ /* Magic QUOT value */
+ writer->write_data(writer, chunk_create("QUOT", 4));
+
+ /* PCR Composite Hash */
+ writer->write_data(writer, hash_pcr_comp);
+
+ /* Secret assessment value 20 bytes (nonce) */
+ writer->write_data(writer, this->secret);
+ }
+
+ /* TPM Quote Info */
+ *out_quote_info = writer->extract_buf(writer);
+ DBG3(DBG_PTS, "constructed TPM Quote Info: %B", out_quote_info);
+
+ writer->destroy(writer);
+ free(pcr_comp.ptr);
+ free(hash_pcr_comp.ptr);
+
+ return TRUE;
+}
+
+METHOD(pts_t, verify_quote_signature, bool,
+ private_pts_t *this, chunk_t data, chunk_t signature)
+{
+ public_key_t *aik_pub_key;
+
+ aik_pub_key = this->aik->get_public_key(this->aik);
+ if (!aik_pub_key)
+ {
+ DBG1(DBG_PTS, "failed to get public key from AIK certificate");
+ return FALSE;
+ }
+
+ if (!aik_pub_key->verify(aik_pub_key, SIGN_RSA_EMSA_PKCS1_SHA1,
+ data, signature))
+ {
+ DBG1(DBG_PTS, "signature verification failed for TPM Quote Info");
+ DESTROY_IF(aik_pub_key);
+ return FALSE;
+ }
+
+ aik_pub_key->destroy(aik_pub_key);
+ return TRUE;
+}
+
+METHOD(pts_t, get_pcrs, pts_pcr_t*,
+ private_pts_t *this)
+{
+ return this->pcrs;
+}
+
+METHOD(pts_t, destroy, void,
+ private_pts_t *this)
+{
+ DESTROY_IF(this->pcrs);
+ DESTROY_IF(this->aik);
+ DESTROY_IF(this->dh);
+ free(this->initiator_nonce.ptr);
+ free(this->responder_nonce.ptr);
+ free(this->secret.ptr);
+ free(this->aik_blob.ptr);
+ free(this->tpm_version_info.ptr);
+ free(this);
+}
+
+
+#ifdef TSS_TROUSERS
+
+/**
+ * Check for a TPM by querying for TPM Version Info
+ */
+static bool has_tpm(private_pts_t *this)
+{
+ TSS_HCONTEXT hContext;
+ TSS_HTPM hTPM;
+ TSS_RESULT result;
+ u_int32_t version_info_len;
+
+ result = Tspi_Context_Create(&hContext);
+ if (result != TSS_SUCCESS)
+ {
+ DBG1(DBG_PTS, "TPM context could not be created: tss error 0x%x",
+ result);
+ return FALSE;
+ }
+ result = Tspi_Context_Connect(hContext, NULL);
+ if (result != TSS_SUCCESS)
+ {
+ goto err;
+ }
+ result = Tspi_Context_GetTpmObject (hContext, &hTPM);
+ if (result != TSS_SUCCESS)
+ {
+ goto err;
+ }
+ result = Tspi_TPM_GetCapability(hTPM, TSS_TPMCAP_VERSION_VAL, 0, NULL,
+ &version_info_len,
+ &this->tpm_version_info.ptr);
+ this->tpm_version_info.len = version_info_len;
+ if (result != TSS_SUCCESS)
+ {
+ goto err;
+ }
+ this->tpm_version_info = chunk_clone(this->tpm_version_info);
+
+ Tspi_Context_FreeMemory(hContext, NULL);
+ Tspi_Context_Close(hContext);
+ return TRUE;
+
+ err:
+ DBG1(DBG_PTS, "TPM not available: tss error 0x%x", result);
+ Tspi_Context_FreeMemory(hContext, NULL);
+ Tspi_Context_Close(hContext);
+ return FALSE;
+}
+
+#else /* TSS_TROUSERS */
+
+static bool has_tpm(private_pts_t *this)
+{
+ return FALSE;
+}
+
+#endif /* TSS_TROUSERS */
+
+
+/**
+ * See header
+ */
+pts_t *pts_create(bool is_imc)
+{
+ private_pts_t *this;
+ pts_pcr_t *pcrs;
+
+ pcrs = pts_pcr_create();
+ if (!pcrs)
+ {
+ DBG1(DBG_PTS, "shadow PCR set could not be created");
+ return NULL;
+ }
+
+ INIT(this,
+ .public = {
+ .get_proto_caps = _get_proto_caps,
+ .set_proto_caps = _set_proto_caps,
+ .get_meas_algorithm = _get_meas_algorithm,
+ .set_meas_algorithm = _set_meas_algorithm,
+ .get_dh_hash_algorithm = _get_dh_hash_algorithm,
+ .set_dh_hash_algorithm = _set_dh_hash_algorithm,
+ .create_dh_nonce = _create_dh_nonce,
+ .get_my_public_value = _get_my_public_value,
+ .set_peer_public_value = _set_peer_public_value,
+ .calculate_secret = _calculate_secret,
+ .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_id = _get_aik_id,
+ .is_path_valid = _is_path_valid,
+ .get_metadata = _get_metadata,
+ .read_pcr = _read_pcr,
+ .extend_pcr = _extend_pcr,
+ .quote_tpm = _quote_tpm,
+ .get_pcrs = _get_pcrs,
+ .get_quote_info = _get_quote_info,
+ .verify_quote_signature = _verify_quote_signature,
+ .destroy = _destroy,
+ },
+ .is_imc = is_imc,
+ .proto_caps = PTS_PROTO_CAPS_V,
+ .algorithm = PTS_MEAS_ALGO_SHA256,
+ .dh_hash_algorithm = PTS_MEAS_ALGO_SHA256,
+ .pcrs = pcrs,
+ );
+
+ if (is_imc)
+ {
+ if (has_tpm(this))
+ {
+ this->has_tpm = TRUE;
+ this->proto_caps |= PTS_PROTO_CAPS_T | PTS_PROTO_CAPS_D;
+ load_aik(this);
+ load_aik_blob(this);
+ }
+ }
+ else
+ {
+ this->proto_caps |= PTS_PROTO_CAPS_T | PTS_PROTO_CAPS_D;
+ }
+
+ return &this->public;
+}
diff --git a/src/libimcv/pts/pts.h b/src/libimcv/pts/pts.h
new file mode 100644
index 000000000..be32a3464
--- /dev/null
+++ b/src/libimcv/pts/pts.h
@@ -0,0 +1,315 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2012-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts pts
+ * @{ @ingroup libimcv
+ */
+
+#ifndef PTS_H_
+#define PTS_H_
+
+typedef struct pts_t pts_t;
+
+#include "pts_error.h"
+#include "pts_proto_caps.h"
+#include "pts_meas_algo.h"
+#include "pts_file_meas.h"
+#include "pts_file_meta.h"
+#include "pts_dh_group.h"
+#include "pts_pcr.h"
+#include "pts_req_func_comp_evid.h"
+#include "pts_simple_evid_final.h"
+#include "components/pts_comp_func_name.h"
+
+#include <library.h>
+#include <collections/linked_list.h>
+
+/**
+ * UTF-8 encoding of the character used to delimiter the filename
+ */
+#define SOLIDUS_UTF 0x2F
+#define REVERSE_SOLIDUS_UTF 0x5C
+
+/**
+ * PCR indices used for measurements of various functional components
+ */
+#define PCR_BIOS 0
+#define PCR_PLATFORM_EXT 1
+#define PCR_MOTHERBOARD 1
+#define PCR_OPTION_ROMS 2
+#define PCR_IPL 4
+
+#define PCR_TBOOT_POLICY 17
+#define PCR_TBOOT_MLE 18
+
+#define PCR_TGRUB_MBR_STAGE1 4
+#define PCR_TGRUB_STAGE2_PART1 8
+#define PCR_TGRUB_STAGE2_PART2 9
+#define PCR_TGRUB_CMD_LINE_ARGS 12
+#define PCR_TGRUB_CHECKFILE 13
+#define PCR_TGRUB_LOADED_FILES 14
+
+#define PCR_DEBUG 16
+
+/**
+ * Length of the generated nonce used for calculation of shared secret
+ */
+#define ASSESSMENT_SECRET_LEN 20
+
+/**
+ * Length of the TPM_QUOTE_INFO structure, TPM Spec 1.2
+ */
+#define TPM_QUOTE_INFO_LEN 48
+
+/**
+ * Hashing algorithm used by tboot and trustedGRUB
+ */
+#define TRUSTED_HASH_ALGO PTS_MEAS_ALGO_SHA1
+
+/**
+ * Class implementing the TCG Platform Trust Service (PTS)
+ *
+ */
+struct pts_t {
+
+ /**
+ * Get PTS Protocol Capabilities
+ *
+ * @return Protocol capabilities flags
+ */
+ pts_proto_caps_flag_t (*get_proto_caps)(pts_t *this);
+
+ /**
+ * Set PTS Protocol Capabilities
+ *
+ * @param flags Protocol capabilities flags
+ */
+ void (*set_proto_caps)(pts_t *this, pts_proto_caps_flag_t flags);
+
+ /**
+ * Get PTS Measurement Algorithm
+ *
+ * @return PTS measurement algorithm
+ */
+ pts_meas_algorithms_t (*get_meas_algorithm)(pts_t *this);
+
+ /**
+ * Set PTS Measurement Algorithm
+ *
+ * @param algorithm PTS measurement algorithm
+ */
+ void (*set_meas_algorithm)(pts_t *this, pts_meas_algorithms_t algorithm);
+
+ /**
+ * Get DH Hash Algorithm
+ *
+ * @return DH hash algorithm
+ */
+ pts_meas_algorithms_t (*get_dh_hash_algorithm)(pts_t *this);
+
+ /**
+ * Set DH Hash Algorithm
+ *
+ * @param algorithm DH hash algorithm
+ */
+ void (*set_dh_hash_algorithm)(pts_t *this, pts_meas_algorithms_t algorithm);
+
+ /**
+ * Create PTS Diffie-Hellman object and nonce
+ *
+ * @param group PTS DH group
+ * @param nonce_len Nonce length
+ * @return TRUE if creation was successful
+ *
+ */
+ bool (*create_dh_nonce)(pts_t *this, pts_dh_group_t group, int nonce_len);
+
+ /**
+ * Get my Diffie-Hellman public value
+ *
+ * @param value My public DH value
+ * @param nonce My DH nonce
+ */
+ void (*get_my_public_value)(pts_t *this, chunk_t *value, chunk_t *nonce);
+
+ /**
+ * Set peer Diffie.Hellman public value
+ *
+ * @param value Peer public DH value
+ * @param nonce Peer DH nonce
+ */
+ void (*set_peer_public_value) (pts_t *this, chunk_t value, chunk_t nonce);
+
+ /**
+ * Calculates assessment secret to be used for TPM Quote as ExternalData
+ *
+ * @return TRUE unless both DH public values
+ * and nonces are set
+ */
+ bool (*calculate_secret) (pts_t *this);
+
+ /**
+ * Get primary key of platform entry in database
+ *
+ * @return Platform and OS info
+ */
+ int (*get_platform_id)(pts_t *this);
+
+ /**
+ * Set primary key of platform entry in database
+ *
+ * @param pid Primary key of platform entry in database
+ */
+ void (*set_platform_id)(pts_t *this, int pid);
+
+ /**
+ * Get TPM 1.2 Version Info
+ *
+ * @param info chunk containing a TPM_CAP_VERSION_INFO struct
+ * @return TRUE if TPM Version Info available
+ */
+ bool (*get_tpm_version_info)(pts_t *this, chunk_t *info);
+
+ /**
+ * Set TPM 1.2 Version Info
+ *
+ * @param info chunk containing a TPM_CAP_VERSION_INFO struct
+ */
+ void (*set_tpm_version_info)(pts_t *this, chunk_t info);
+
+ /**
+ * Get Attestation Identity Certificate or Public Key
+ *
+ * @return AIK Certificate or Public Key
+ */
+ certificate_t* (*get_aik)(pts_t *this);
+
+ /**
+ * Set Attestation Identity Certificate or Public Key
+ *
+ * @param aik AIK Certificate or Public Key
+ * @param aik_id Primary key referencing AIK in database
+ */
+ void (*set_aik)(pts_t *this, certificate_t *aik, int aik_id);
+
+ /**
+ * Get primary key referencing AIK in database
+ *
+ * @return Primary key referencing AIK in database
+ */
+ int (*get_aik_id)(pts_t *this);
+
+ /**
+ * Check whether path is valid file/directory on filesystem
+ *
+ * @param path Absolute path
+ * @param error_code Output variable for PTS error code
+ * @return TRUE if path is valid or file/directory
+ * doesn't exist or path is invalid
+ * FALSE if local error occurred within stat function
+ */
+ bool (*is_path_valid)(pts_t *this, char *path, pts_error_code_t *error_code);
+
+ /**
+ * Obtain file metadata
+ *
+ * @param pathname Absolute pathname of file/directory
+ * @param is_dir TRUE if directory contents are requested
+ * @return PTS File Metadata or NULL if FAILED
+ */
+ pts_file_meta_t* (*get_metadata)(pts_t *this, char *pathname, bool is_dir);
+
+ /**
+ * Reads given PCR value and returns it
+ * Expects owner secret to be WELL_KNOWN_SECRET
+ *
+ * @param pcr_num Number of PCR to read
+ * @param pcr_value Chunk to save pcr read output
+ * @return NULL in case of TSS error, PCR value otherwise
+ */
+ bool (*read_pcr)(pts_t *this, u_int32_t pcr_num, chunk_t *pcr_value);
+
+ /**
+ * Extends given PCR with given value
+ * Expects owner secret to be WELL_KNOWN_SECRET
+ *
+ * @param pcr_num Number of PCR to extend
+ * @param input Value to extend
+ * @param output Chunk to save PCR value after extension
+ * @return FALSE in case of TSS error, TRUE otherwise
+ */
+ bool (*extend_pcr)(pts_t *this, u_int32_t pcr_num, chunk_t input,
+ chunk_t *output);
+
+ /**
+ * Quote over PCR's
+ * Expects owner and SRK secret to be WELL_KNOWN_SECRET and no password set for AIK
+ *
+ * @param use_quote2 Version of the Quote function to be used
+ * @param pcr_comp Chunk to save PCR composite structure
+ * @param quote_sig Chunk to save quote operation output
+ * without external data (anti-replay protection)
+ * @return FALSE in case of TSS error, TRUE otherwise
+ */
+ bool (*quote_tpm)(pts_t *this, bool use_quote2, chunk_t *pcr_comp,
+ chunk_t *quote_sig);
+
+ /**
+ * Get the shadow PCR set
+ *
+ * @return shadow PCR set
+ */
+ pts_pcr_t* (*get_pcrs)(pts_t *this);
+
+ /**
+ * Constructs and returns TPM Quote Info structure expected from IMC
+ *
+ * @param use_quote2 Version of the TPM_QUOTE_INFO to be constructed
+ * @param use_ver_info Version info is concatenated to TPM_QUOTE_INFO2
+ * @param comp_hash_algo Composite Hash Algorithm
+ * @param pcr_comp Output variable to store PCR Composite
+ * @param quote_info Output variable to store TPM Quote Info
+ * @return FALSE in case of any error, TRUE otherwise
+ */
+ bool (*get_quote_info)(pts_t *this, bool use_quote2, bool ver_info_included,
+ pts_meas_algorithms_t comp_hash_algo,
+ chunk_t *pcr_comp, chunk_t *quote_info);
+
+ /**
+ * Constructs and returns PCR Quote Digest structure expected from IMC
+ *
+ * @param data Calculated TPM Quote Digest
+ * @param signature TPM Quote Signature received from IMC
+ * @return FALSE if signature is not verified
+ */
+ bool (*verify_quote_signature)(pts_t *this, chunk_t data, chunk_t signature);
+
+ /**
+ * Destroys a pts_t object.
+ */
+ void (*destroy)(pts_t *this);
+
+};
+
+/**
+ * Creates an pts_t object
+ *
+ * @param is_imc TRUE if running on an IMC
+ */
+pts_t* pts_create(bool is_imc);
+
+#endif /** PTS_H_ @}*/
diff --git a/src/libimcv/pts/pts_creds.c b/src/libimcv/pts/pts_creds.c
new file mode 100644
index 000000000..bc483eb84
--- /dev/null
+++ b/src/libimcv/pts/pts_creds.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2011 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pts_creds.h"
+
+#include <utils/debug.h>
+#include <credentials/certificates/x509.h>
+#include <credentials/sets/mem_cred.h>
+
+#include <sys/stat.h>
+
+typedef struct private_pts_creds_t private_pts_creds_t;
+
+/**
+ * Private data of a pts_creds_t object.
+ *
+ */
+struct private_pts_creds_t {
+
+ /**
+ * Public pts_creds_t interface.
+ */
+ pts_creds_t public;
+
+ /**
+ * Credential set
+ */
+ mem_cred_t *creds;
+
+};
+
+METHOD(pts_creds_t, get_set, credential_set_t*,
+ private_pts_creds_t *this)
+{
+ return &this->creds->set;
+}
+
+
+METHOD(pts_creds_t, destroy, void,
+ private_pts_creds_t *this)
+{
+ this->creds->destroy(this->creds);
+ free(this);
+}
+
+/**
+ * Load trusted PTS CA certificates from a directory
+ */
+static void load_cacerts(private_pts_creds_t *this, char *path)
+{
+ enumerator_t *enumerator;
+ struct stat st;
+ char *file;
+
+ DBG1(DBG_PTS, "loading PTS ca certificates from '%s'", path);
+
+ enumerator = enumerator_create_directory(path);
+ if (!enumerator)
+ {
+ return;
+ }
+
+ while (enumerator->enumerate(enumerator, NULL, &file, &st))
+ {
+ certificate_t *cert;
+
+ if (!S_ISREG(st.st_mode))
+ {
+ /* skip special file */
+ continue;
+ }
+ cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
+ BUILD_FROM_FILE, file, BUILD_END);
+ if (cert)
+ {
+ x509_t *x509 = (x509_t*)cert;
+
+ if (!(x509->get_flags(x509) & X509_CA))
+ {
+ DBG1(DBG_PTS, " ca certificate \"%Y\" lacks ca basic constraint"
+ ", discarded", cert->get_subject(cert));
+ cert->destroy(cert);
+ }
+ else
+ {
+ DBG1(DBG_PTS, " loaded ca certificate \"%Y\" from '%s'",
+ cert->get_subject(cert), file);
+ this->creds->add_cert(this->creds, TRUE, cert);
+ }
+ }
+ else
+ {
+ DBG1(DBG_PTS, " loading ca certificate from '%s' failed", file);
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * See header
+ */
+pts_creds_t *pts_creds_create(char *path)
+{
+ private_pts_creds_t *this;
+
+ if (!path)
+ {
+ DBG1(DBG_PTS, "no PTS cacerts directory defined");
+ return NULL;
+ }
+
+ INIT(this,
+ .public = {
+ .get_set = _get_set,
+ .destroy = _destroy,
+ },
+ .creds = mem_cred_create(),
+ );
+
+ load_cacerts(this, path);
+
+ return &this->public;
+}
+
diff --git a/src/libimcv/pts/pts_creds.h b/src/libimcv/pts/pts_creds.h
new file mode 100644
index 000000000..eb9c39537
--- /dev/null
+++ b/src/libimcv/pts/pts_creds.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2011 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts_creds pts_creds
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_CREDS_H_
+#define PTS_CREDS_H_
+
+typedef struct pts_creds_t pts_creds_t;
+
+#include <library.h>
+#include <credentials/credential_set.h>
+
+/**
+ * Class implementing a PTS credentials set
+ */
+struct pts_creds_t {
+
+ /**
+ * Get the credential set
+ *
+ * @return credential set
+ */
+ credential_set_t* (*get_set)(pts_creds_t *this);
+
+ /**
+ * Destroys a pts_creds_t object.
+ */
+ void (*destroy)(pts_creds_t *this);
+
+};
+
+/**
+ * Creates an pts_creds_t object
+ *
+ * @param path path to the PTS cacerts directory
+ */
+pts_creds_t* pts_creds_create(char *path);
+
+#endif /** PTS_CREDS_H_ @}*/
diff --git a/src/libimcv/pts/pts_database.c b/src/libimcv/pts/pts_database.c
new file mode 100644
index 000000000..d7b85c138
--- /dev/null
+++ b/src/libimcv/pts/pts_database.c
@@ -0,0 +1,432 @@
+/*
+ * Copyright (C) 2011-2012 Sansar Choinyambuu
+ * Copyright (C) 2012-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <libgen.h>
+
+#include "pts_database.h"
+
+#include <utils/debug.h>
+#include <crypto/hashers/hasher.h>
+
+
+typedef struct private_pts_database_t private_pts_database_t;
+
+/**
+ * Private data of a pts_database_t object.
+ *
+ */
+struct private_pts_database_t {
+
+ /**
+ * Public pts_database_t interface.
+ */
+ pts_database_t public;
+
+ /**
+ * database instance
+ */
+ database_t *db;
+
+};
+
+METHOD(pts_database_t, get_pathname, char*,
+ private_pts_database_t *this, bool is_dir, int id)
+{
+ enumerator_t *e;
+ char *path, *name, *sep, *pathname = NULL;
+
+ if (is_dir)
+ {
+ e = this->db->query(this->db,
+ "SELECT path FROM directories WHERE id = ?",
+ DB_INT, id, DB_TEXT);
+ if (!e || !e->enumerate(e, &path))
+ {
+ pathname = NULL;
+ }
+ else
+ {
+ pathname = strdup(path);
+ }
+ }
+ else
+ {
+ e = this->db->query(this->db,
+ "SELECT d.path, f.name FROM files AS f "
+ "JOIN directories AS d ON d.id = f.dir WHERE f.id = ?",
+ DB_INT, id, DB_TEXT, DB_TEXT);
+ if (e && e->enumerate(e, &path, &name))
+ {
+ if (path[0] == '/')
+ { /* Unix style absolute path */
+ sep = "/";
+ }
+ else
+ { /* Windows absolute path */
+ sep = "\\";
+ }
+ if (asprintf(&pathname, "%s%s%s",
+ path, streq(path, "/") ? "" : sep, name) == -1)
+ {
+ pathname = NULL;
+ }
+ }
+ }
+ DESTROY_IF(e);
+
+ return pathname;
+}
+
+METHOD(pts_database_t, create_file_hash_enumerator, enumerator_t*,
+ private_pts_database_t *this, int pid, pts_meas_algorithms_t algo,
+ bool is_dir, int id)
+{
+ enumerator_t *e;
+
+ if (is_dir)
+ {
+ e = this->db->query(this->db,
+ "SELECT f.id, f.name, fh.hash FROM file_hashes AS fh "
+ "JOIN files AS f ON f.id = fh.file "
+ "JOIN directories as d ON d.id = f.dir "
+ "WHERE fh.product = ? AND fh.algo = ? AND d.id = ? "
+ "ORDER BY f.name",
+ DB_INT, pid, DB_INT, algo, DB_INT, id, DB_INT, DB_TEXT, DB_BLOB);
+ }
+ else
+ {
+ e = this->db->query(this->db,
+ "SELECT f.id, f.name, fh.hash FROM file_hashes AS fh "
+ "JOIN files AS f ON f.id = fh.file "
+ "WHERE fh.product = ? AND fh.algo = ? AND fh.file = ?",
+ DB_INT, pid, DB_INT, algo, DB_INT, id, DB_INT, DB_TEXT, DB_BLOB);
+ }
+ return e;
+}
+
+METHOD(pts_database_t, add_file_measurement, status_t,
+ private_pts_database_t *this, int pid, pts_meas_algorithms_t algo,
+ chunk_t measurement, char *filename, bool is_dir, int id)
+{
+ enumerator_t *e;
+ char *name;
+ chunk_t hash_value;
+ int hash_id, fid;
+ status_t status = SUCCESS;
+
+ if (is_dir)
+ {
+ /* does filename entry already exist? */
+ e = this->db->query(this->db,
+ "SELECT id FROM files WHERE name = ? AND dir = ?",
+ DB_TEXT, filename, DB_INT, id, DB_INT);
+ if (!e)
+ {
+ return FAILED;
+ }
+ if (!e->enumerate(e, &fid))
+ {
+ /* create filename entry */
+ if (this->db->execute(this->db, &fid,
+ "INSERT INTO files (name, dir) VALUES (?, ?)",
+ DB_TEXT, filename, DB_INT, id) != 1)
+ {
+ DBG1(DBG_PTS, "could not insert filename into database");
+ status = FAILED;
+ }
+ }
+ e->destroy(e);
+ }
+ else
+ {
+ fid = id;
+
+ /* verify filename */
+ e = this->db->query(this->db,
+ "SELECT name FROM files WHERE id = ?", DB_INT, fid, DB_TEXT);
+ if (!e)
+ {
+ return FAILED;
+ }
+ if (!e->enumerate(e, &name) || !streq(name, filename))
+ {
+ DBG1(DBG_PTS, "filename of reference measurement does not match");
+ status = FAILED;
+ }
+ e->destroy(e);
+ }
+
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+
+ /* does hash measurement value already exist? */
+ e = this->db->query(this->db,
+ "SELECT fh.id, fh.hash FROM file_hashes AS fh "
+ "WHERE fh.product = ? AND fh.algo = ? AND fh.file = ?",
+ DB_INT, pid, DB_INT, algo, DB_INT, fid, DB_INT, DB_BLOB);
+ if (!e)
+ {
+ return FAILED;
+ }
+ if (e->enumerate(e, &hash_id, &hash_value))
+ {
+ if (!chunk_equals(measurement, hash_value))
+ {
+ /* update hash measurement value */
+ if (this->db->execute(this->db, &hash_id,
+ "UPDATE file_hashes SET hash = ? WHERE id = ?",
+ DB_BLOB, measurement, DB_INT, hash_id) != 1)
+ {
+ status = FAILED;
+ }
+ }
+ }
+ else
+ {
+ /* insert hash measurement value */
+ if (this->db->execute(this->db, &hash_id,
+ "INSERT INTO file_hashes (file, product, algo, hash) "
+ "VALUES (?, ?, ?, ?)", DB_INT, fid, DB_INT, pid,
+ DB_INT, algo, DB_BLOB, measurement) != 1)
+ {
+ status = FAILED;
+ }
+ }
+ e->destroy(e);
+
+ return status;
+}
+
+METHOD(pts_database_t, create_file_meas_enumerator, enumerator_t*,
+ private_pts_database_t *this, int pid, pts_meas_algorithms_t algo,
+ char *filename)
+{
+ enumerator_t *e;
+ char *dir, *file;
+
+ if (strlen(filename) < 1)
+ {
+ return NULL;
+ }
+
+ /* separate filename into directory and basename components */
+ dir = path_dirname(filename);
+ file = path_basename(filename);
+
+ if (*dir == '.')
+ { /* relative pathname */
+ e = this->db->query(this->db,
+ "SELECT fh.hash FROM file_hashes AS fh "
+ "JOIN files AS f ON f.id = fh.file "
+ "WHERE fh.product = ? AND f.name = ? AND fh.algo = ?",
+ DB_INT, pid, DB_TEXT, file, DB_INT, algo, DB_BLOB);
+ }
+ else
+ { /* absolute pathname */
+ int did;
+
+ /* find directory entry first */
+ e = this->db->query(this->db,
+ "SELECT id FROM directories WHERE path = ?",
+ DB_TEXT, dir, DB_INT);
+
+ if (!e || !e->enumerate(e, &did))
+ {
+ goto err;
+ }
+ e->destroy(e);
+
+ e = this->db->query(this->db,
+ "SELECT fh.hash FROM file_hashes AS fh "
+ "JOIN files AS f ON f.id = fh.file "
+ "WHERE fh.product = ? AND f.dir = ? AND f.name = ? AND fh.algo = ?",
+ DB_INT, pid, DB_INT, did, DB_TEXT, file, DB_INT, algo, DB_BLOB);
+ }
+
+err:
+ free(file);
+ free(dir);
+
+ return e;
+}
+
+METHOD(pts_database_t, check_comp_measurement, status_t,
+ private_pts_database_t *this, chunk_t measurement, int cid, int aik_id,
+ int seq_no, int pcr, pts_meas_algorithms_t algo)
+{
+ enumerator_t *e;
+ chunk_t hash;
+ status_t status = NOT_FOUND;
+
+ e = this->db->query(this->db,
+ "SELECT hash FROM component_hashes "
+ "WHERE component = ? AND key = ? "
+ "AND seq_no = ? AND pcr = ? AND algo = ? ",
+ DB_INT, cid, DB_INT, aik_id, DB_INT, seq_no,
+ DB_INT, pcr, DB_INT, algo, DB_BLOB);
+ if (!e)
+ {
+ DBG1(DBG_PTS, "no database query enumerator returned");
+ return FAILED;
+ }
+
+ while (e->enumerate(e, &hash))
+ {
+ if (chunk_equals(hash, measurement))
+ {
+ status = SUCCESS;
+ break;
+ }
+ else
+ {
+ DBG1(DBG_PTS, "PCR %2d no matching component measurement #%d "
+ "found in database", pcr, seq_no);
+ DBG1(DBG_PTS, " expected: %#B", &hash);
+ DBG1(DBG_PTS, " received: %#B", &measurement);
+ status = VERIFY_ERROR;
+ break;
+ }
+ }
+ e->destroy(e);
+
+ if (status == NOT_FOUND)
+ {
+ DBG1(DBG_PTS, "PCR %2d no measurement #%d "
+ "found in database", pcr, seq_no);
+ }
+
+ return status;
+}
+
+METHOD(pts_database_t, insert_comp_measurement, status_t,
+ private_pts_database_t *this, chunk_t measurement, int cid, int aik_id,
+ int seq_no, int pcr, pts_meas_algorithms_t algo)
+{
+ int id;
+
+ if (this->db->execute(this->db, &id,
+ "INSERT INTO component_hashes "
+ "(component, key, seq_no, pcr, algo, hash) "
+ "VALUES (?, ?, ?, ?, ?, ?)",
+ DB_INT, cid, DB_INT, aik_id, DB_INT, seq_no, DB_INT, pcr,
+ DB_INT, algo, DB_BLOB, measurement) == 1)
+ {
+ return SUCCESS;
+ }
+
+ DBG1(DBG_PTS, "could not insert component measurement into database");
+ return FAILED;
+}
+
+METHOD(pts_database_t, delete_comp_measurements, int,
+ private_pts_database_t *this, int cid, int aik_id)
+{
+ return this->db->execute(this->db, NULL,
+ "DELETE FROM component_hashes "
+ "WHERE component = ? AND key = ?",
+ DB_INT, cid, DB_INT, aik_id);
+}
+
+METHOD(pts_database_t, get_comp_measurement_count, status_t,
+ private_pts_database_t *this, pts_comp_func_name_t *comp_name,
+ int aik_id, pts_meas_algorithms_t algo, int *cid, int *count)
+{
+ enumerator_t *e;
+ status_t status = SUCCESS;
+
+ /* Initialize count */
+ *count = 0;
+
+ /* Get the primary key of the Component Functional Name */
+ e = this->db->query(this->db,
+ "SELECT id FROM components "
+ " WHERE vendor_id = ? AND name = ? AND qualifier = ?",
+ DB_INT, comp_name->get_vendor_id(comp_name),
+ DB_INT, comp_name->get_name(comp_name),
+ DB_INT, comp_name->get_qualifier(comp_name),
+ DB_INT);
+ if (!e)
+ {
+ DBG1(DBG_PTS, "no database query enumerator returned");
+ return FAILED;
+ }
+ if (!e->enumerate(e, cid))
+ {
+ DBG1(DBG_PTS, "component functional name not found in database");
+ e->destroy(e);
+ return FAILED;
+ }
+ e->destroy(e);
+
+ /* Get the number of stored measurements for a given AIK and component */
+ e = this->db->query(this->db,
+ "SELECT COUNT(*) FROM component_hashes AS ch "
+ "WHERE component = ? AND key = ? AND algo = ?",
+ DB_INT, *cid, DB_INT, aik_id, DB_INT, algo, DB_INT);
+ if (!e)
+ {
+ DBG1(DBG_PTS, "no database query enumerator returned");
+ return FAILED;
+ }
+ if (!e->enumerate(e, count))
+ {
+ DBG1(DBG_PTS, "no component measurement count returned from database");
+ status = FAILED;
+ }
+ e->destroy(e);
+
+ return status;
+}
+
+METHOD(pts_database_t, destroy, void,
+ private_pts_database_t *this)
+{
+ free(this);
+}
+
+/**
+ * See header
+ */
+pts_database_t *pts_database_create(imv_database_t *imv_db)
+{
+ private_pts_database_t *this;
+
+ if (!imv_db)
+ {
+ return NULL;
+ }
+
+ INIT(this,
+ .public = {
+ .get_pathname = _get_pathname,
+ .create_file_hash_enumerator = _create_file_hash_enumerator,
+ .add_file_measurement = _add_file_measurement,
+ .create_file_meas_enumerator = _create_file_meas_enumerator,
+ .check_comp_measurement = _check_comp_measurement,
+ .insert_comp_measurement = _insert_comp_measurement,
+ .delete_comp_measurements = _delete_comp_measurements,
+ .get_comp_measurement_count = _get_comp_measurement_count,
+ .destroy = _destroy,
+ },
+ .db = imv_db->get_database(imv_db),
+ );
+
+ return &this->public;
+}
diff --git a/src/libimcv/pts/pts_database.h b/src/libimcv/pts/pts_database.h
new file mode 100644
index 000000000..a6c9fb3b6
--- /dev/null
+++ b/src/libimcv/pts/pts_database.h
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2011-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts_database pts_database
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_DATABASE_H_
+#define PTS_DATABASE_H_
+
+typedef struct pts_database_t pts_database_t;
+
+#include "pts_meas_algo.h"
+#include "components/pts_comp_func_name.h"
+
+#include <imv/imv_database.h>
+#include <library.h>
+
+/**
+ * Class implementing the PTS File Measurement database
+ *
+ */
+struct pts_database_t {
+
+ /**
+ * Get absolute pathname for file or directory measurement
+ *
+ * @param is_dir TRUE if dir, FALSE if file
+ * @param id Primary key into directories or files table
+ * @return Absolute pathname as a text string
+ */
+ char* (*get_pathname)(pts_database_t *this, bool is_dir, int id);
+
+ /**
+ * Get stored measurement hash for single file or directory entries
+ *
+ * @param pid Primary key of software product in database
+ * @param algo Hash algorithm used for measurement
+ * @param is_dir TRUE if directory was measured
+ * @param id Primary key of measured file/directory
+ * @return Enumerator over all matching measurement hashes
+ */
+ enumerator_t* (*create_file_hash_enumerator)(pts_database_t *this,
+ int pid, pts_meas_algorithms_t algo,
+ bool is_dir, int id);
+
+ /**
+ * Add PTS file measurement reference value
+ *
+ * @param pid Primary key of software product in database
+ * @param algo File measurement hash algorithm used
+ * @param measurement File measurement hash
+ * @param filename Optional name of the file to be checked
+ * @param is_dir TRUE if part of directory measurement
+ * @param id Primary key into direcories/files table
+ * @return Status
+ */
+ status_t (*add_file_measurement)(pts_database_t *this, int pid,
+ pts_meas_algorithms_t algo,
+ chunk_t measurement, char *filename,
+ bool is_dir, int id);
+
+ /**
+ * Get PTS measurement[s] for a given filename stored in database
+ *
+ * @param pid Primary key of software product in database
+ * @param algo File measurement hash algorithm used
+ * @param filename Name of the file to be checked
+ * @return Enumerator over all matching measurement hashes
+ */
+ enumerator_t* (*create_file_meas_enumerator)(pts_database_t *this, int pid,
+ pts_meas_algorithms_t algo,
+ char *filename);
+
+ /**
+ * Check a functional component measurement against value stored in database
+ *
+ * @param measurement measurement hash
+ * @param cid Primary key of Component Functional Name entry
+ * @param aik_id Primary key of AIK entry in database
+ * @param seq_no Measurement sequence number
+ * @param prc Number of the PCR the measurement was extended into
+ * @param algo Hash algorithm used for measurement
+ * @return SUCCESS if check was successful
+ */
+ status_t (*check_comp_measurement)(pts_database_t *this, chunk_t measurement,
+ int cid, int aik_id, int seq_no, int pcr,
+ pts_meas_algorithms_t algo);
+
+ /**
+ * Insert a functional component measurement into the database
+ *
+ * @param measurement Measurement hash
+ * @param cid Primary key of Component Functional Name entry
+ * @param aik_id Primary key of AIK entry in database
+ * @param seq_no Measurement sequence number
+ * @param prc Number of the PCR the measurement was extended into
+ * @param algo Hash algorithm used for measurement
+ * @return SUCCESS if INSERT was successful
+ */
+ status_t (*insert_comp_measurement)(pts_database_t *this, chunk_t measurement,
+ int cid, int aik_id, int seq_no, int pcr,
+ pts_meas_algorithms_t algo);
+
+ /**
+ * Delete functional component measurements from the database
+ *
+ * @param cid Primary key of Component Functional Name entry
+ * @param aik_id Primary key of AIK entry in database
+ * @return number of deleted measurement entries
+ */
+ int (*delete_comp_measurements)(pts_database_t *this, int cid, int aik_id);
+
+ /**
+ * Get the number of measurements for a functional component and AIK
+ *
+ * @param comp_name Component Functional Name
+ * @param aik_id Primary key of AIK entry in database
+ * @param algo Hash algorithm used for measurement
+ * @param cid Primary key of Component Functional Name entry
+ * @param count measurement count
+ * @return SUCCESS if COUNT was successful
+ */
+ status_t (*get_comp_measurement_count)(pts_database_t *this,
+ pts_comp_func_name_t *comp_name, int aik_id,
+ pts_meas_algorithms_t algo, int *cid, int *count);
+
+ /**
+ * Destroys a pts_database_t object.
+ */
+ void (*destroy)(pts_database_t *this);
+
+};
+
+/**
+ * Creates an pts_database_t object
+ *
+ * @param imv_db Already attached IMV database
+ */
+pts_database_t* pts_database_create(imv_database_t *imv_db);
+
+#endif /** PTS_DATABASE_H_ @}*/
diff --git a/src/libimcv/pts/pts_dh_group.c b/src/libimcv/pts/pts_dh_group.c
new file mode 100644
index 000000000..305b4ec4f
--- /dev/null
+++ b/src/libimcv/pts/pts_dh_group.c
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pts_dh_group.h"
+
+#include <utils/debug.h>
+
+/**
+ * Described in header.
+ */
+bool pts_dh_group_probe(pts_dh_group_t *dh_groups, bool mandatory_dh_groups)
+{
+ enumerator_t *enumerator;
+ diffie_hellman_group_t dh_group;
+ const char *plugin_name;
+ char format1[] = " %s PTS DH group %N[%s] available";
+ char format2[] = " %s PTS DH group %N not available";
+
+ *dh_groups = PTS_DH_GROUP_NONE;
+
+ enumerator = lib->crypto->create_dh_enumerator(lib->crypto);
+ while (enumerator->enumerate(enumerator, &dh_group, &plugin_name))
+ {
+ if (dh_group == MODP_1024_BIT)
+ {
+ *dh_groups |= PTS_DH_GROUP_IKE2;
+ DBG2(DBG_PTS, format1, "optional ", diffie_hellman_group_names,
+ dh_group, plugin_name);
+ }
+ else if (dh_group == MODP_1536_BIT)
+ {
+ *dh_groups |= PTS_DH_GROUP_IKE5;
+ DBG2(DBG_PTS, format1, "optional ", diffie_hellman_group_names,
+ dh_group, plugin_name);
+ }
+ else if (dh_group == MODP_2048_BIT)
+ {
+ *dh_groups |= PTS_DH_GROUP_IKE14;
+ DBG2(DBG_PTS, format1, "optional ", diffie_hellman_group_names,
+ dh_group, plugin_name);
+ }
+ else if (dh_group == ECP_256_BIT)
+ {
+ *dh_groups |= PTS_DH_GROUP_IKE19;
+ DBG2(DBG_PTS, format1, "mandatory", diffie_hellman_group_names,
+ dh_group, plugin_name);
+ }
+ else if (dh_group == ECP_384_BIT)
+ {
+ *dh_groups |= PTS_DH_GROUP_IKE20;
+ DBG2(DBG_PTS, format1, "optional ", diffie_hellman_group_names,
+ dh_group, plugin_name);
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (*dh_groups & PTS_DH_GROUP_IKE19)
+ {
+ /* mandatory PTS DH group is available */
+ return TRUE;
+ }
+ if (*dh_groups == PTS_DH_GROUP_NONE)
+ {
+ DBG1(DBG_PTS, "no PTS DH group available");
+ return FALSE;
+ }
+ if (mandatory_dh_groups)
+ {
+ DBG1(DBG_PTS, format2, "mandatory", diffie_hellman_group_names,
+ ECP_256_BIT);
+ return FALSE;
+ }
+
+ /* at least one optional PTS DH group is available */
+ return TRUE;
+}
+
+/**
+ * Described in header.
+ */
+bool pts_dh_group_update(char *dh_group, pts_dh_group_t *dh_groups)
+{
+ if (strcaseeq(dh_group, "ecp384"))
+ {
+ /* nothing to update, all groups are supported */
+ return TRUE;
+ }
+ if (strcaseeq(dh_group, "ecp256"))
+ {
+ /* remove DH group 20 */
+ *dh_groups &= ~PTS_DH_GROUP_IKE20;
+ return TRUE;
+ }
+ if (strcaseeq(dh_group, "modp2048"))
+ {
+ /* remove DH groups 19 and 20 */
+ *dh_groups &= ~(PTS_DH_GROUP_IKE20 | PTS_DH_GROUP_IKE19);
+ return TRUE;
+ }
+ if (strcaseeq(dh_group, "modp1536"))
+ {
+ /* remove DH groups 14, 19 and 20 */
+ *dh_groups &= ~(PTS_DH_GROUP_IKE20 | PTS_DH_GROUP_IKE19 |
+ PTS_DH_GROUP_IKE14);
+ return TRUE;
+ }
+ if (strcaseeq(dh_group, "modp1024"))
+ {
+ /* remove DH groups 5, 14, 19 and 20 */
+ *dh_groups &= ~(PTS_DH_GROUP_IKE20 | PTS_DH_GROUP_IKE19 |
+ PTS_DH_GROUP_IKE14 | PTS_DH_GROUP_IKE5);
+ return TRUE;
+ }
+ DBG1(DBG_PTS, "unknown DH group '%s' configured", dh_group);
+ return FALSE;
+}
+
+/**
+ * Described in header.
+ */
+pts_dh_group_t pts_dh_group_select(pts_dh_group_t supported_dh_groups,
+ pts_dh_group_t offered_dh_groups)
+{
+ if ((supported_dh_groups & PTS_DH_GROUP_IKE20) &&
+ (offered_dh_groups & PTS_DH_GROUP_IKE20))
+ {
+ return PTS_DH_GROUP_IKE20;
+ }
+ if ((supported_dh_groups & PTS_DH_GROUP_IKE19) &&
+ (offered_dh_groups & PTS_DH_GROUP_IKE19))
+ {
+ return PTS_DH_GROUP_IKE19;
+ }
+ if ((supported_dh_groups & PTS_DH_GROUP_IKE14) &&
+ (offered_dh_groups & PTS_DH_GROUP_IKE14))
+ {
+ return PTS_DH_GROUP_IKE14;
+ }
+ if ((supported_dh_groups & PTS_DH_GROUP_IKE5) &&
+ (offered_dh_groups & PTS_DH_GROUP_IKE5))
+ {
+ return PTS_DH_GROUP_IKE5;
+ }
+ if ((supported_dh_groups & PTS_DH_GROUP_IKE2) &&
+ (offered_dh_groups & PTS_DH_GROUP_IKE2))
+ {
+ return PTS_DH_GROUP_IKE2;
+ }
+ return PTS_DH_GROUP_NONE;
+}
+
+/**
+ * Described in header.
+ */
+diffie_hellman_group_t pts_dh_group_to_ike(pts_dh_group_t dh_group)
+{
+ switch (dh_group)
+ {
+ case PTS_DH_GROUP_IKE2:
+ return MODP_1024_BIT;
+ case PTS_DH_GROUP_IKE5:
+ return MODP_1536_BIT;
+ case PTS_DH_GROUP_IKE14:
+ return MODP_2048_BIT;
+ case PTS_DH_GROUP_IKE19:
+ return ECP_256_BIT;
+ case PTS_DH_GROUP_IKE20:
+ return ECP_384_BIT;
+ default:
+ return MODP_NONE;
+ }
+}
diff --git a/src/libimcv/pts/pts_dh_group.h b/src/libimcv/pts/pts_dh_group.h
new file mode 100644
index 000000000..f5d951e9a
--- /dev/null
+++ b/src/libimcv/pts/pts_dh_group.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts_dh_group pts_dh_group
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_DH_GROUP_H_
+#define PTS_DH_GROUP_H_
+
+#include <library.h>
+#include <crypto/diffie_hellman.h>
+
+typedef enum pts_dh_group_t pts_dh_group_t;
+
+/**
+ * PTS Diffie Hellman Group Values
+ */
+enum pts_dh_group_t {
+ /** No DH Group */
+ PTS_DH_GROUP_NONE = 0,
+ /** IKE Group 2 */
+ PTS_DH_GROUP_IKE2 = (1<<15),
+ /** IKE Group 5 */
+ PTS_DH_GROUP_IKE5 = (1<<14),
+ /** IKE Group 14 */
+ PTS_DH_GROUP_IKE14 = (1<<13),
+ /** IKE Group 19 */
+ PTS_DH_GROUP_IKE19 = (1<<12),
+ /** IKE Group 20 */
+ PTS_DH_GROUP_IKE20 = (1<<11),
+};
+
+/**
+ * Diffie-Hellman Group Values
+ * see section 3.8.6 of PTS Protocol: Binding to TNC IF-M Specification
+ *
+ * 1
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |1|2|3|4|5|R|R|R|R|R|R|R|R|R|R|R|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ */
+
+/**
+ * Probe available PTS Diffie-Hellman groups
+ *
+ * @param dh_groups returns set of available DH groups
+ * @param mandatory_dh_groups if TRUE enforce mandatory PTS DH groups
+ * @return TRUE if mandatory DH groups are available
+ * or at least one optional DH group if
+ * mandatory_dh_groups is set to FALSE.
+ */
+bool pts_dh_group_probe(pts_dh_group_t *dh_groups, bool mandatory_dh_groups);
+
+/**
+ * Update supported Diffie-Hellman groups according to configuration
+ *
+ * modp1024: PTS_DH_GROUP_IKE2
+ * modp1536: PTS_DH_GROUP_IKE2 | PTS_DH_GROUP_IKE5
+ * modp2048: PTS_DH_GROUP_IKE2 | PTS_DH_GROUP_IKE5 | PTS_DH_GROUP_IKE14
+ * ecp256: PTS_DH_GROUP_IKE2 | PTS_DH_GROUP_IKE5 | PTS_DH_GROUP_IKE14 |
+ * PTS_DH_GROUP_IKE19
+ * ecp384: PTS_DH_GROUP_IKE2 | PTS_DH_GROUP_IKE5 | PTS_DH_GROUP_IKE14 |
+ * PTS_DH_GROUP_IKE19 | PTS_DH_GROUP_IKE20
+ *
+ * The PTS-IMC is expected to select the strongest supported group
+ *
+ * @param dh_group configured DH group
+ * @param dh_groups returns set of available DH groups
+ */
+bool pts_dh_group_update(char *dh_group, pts_dh_group_t *dh_groups);
+
+/**
+ * Select the strongest supported Diffie-Hellman group
+ * among a set of offered DH groups
+ *
+ * @param supported_groups set of supported DH groups
+ * @param offered_groups set of offered DH groups
+ * @return selected DH group
+ */
+pts_dh_group_t pts_dh_group_select(pts_dh_group_t supported_groups,
+ pts_dh_group_t offered_groups);
+
+/**
+ * Convert pts_dh_group_t to diffie_hellman_group_t
+ *
+ * @param dh_group PTS DH group type
+ * @return IKE DH group type
+ */
+diffie_hellman_group_t pts_dh_group_to_ike(pts_dh_group_t dh_group);
+
+#endif /** PTS_DH_GROUP_H_ @}*/
diff --git a/src/libimcv/pts/pts_error.c b/src/libimcv/pts/pts_error.c
new file mode 100644
index 000000000..1e79689f9
--- /dev/null
+++ b/src/libimcv/pts/pts_error.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pts_error.h"
+
+#include <bio/bio_writer.h>
+#include <ietf/ietf_attr_pa_tnc_error.h>
+
+ENUM(pts_error_code_names, TCG_PTS_RESERVED_ERROR, TCG_PTS_UNABLE_DET_PCR,
+ "Reserved Error",
+ "Hash Algorithm Not Supported",
+ "Invalid Path",
+ "File Not Found",
+ "Registry Not Supported",
+ "Registry Key Not Found",
+ "D-H Group Not Supported",
+ "DH-PN Nonce Not Acceptable",
+ "Invalid Functional Name Family",
+ "TPM Version Information Unavailable",
+ "Invalid File Pathname Delimiter",
+ "PTS Operation Not Supported",
+ "Unable To Update Reference Manifest",
+ "Unable To Perform Local Validation",
+ "Unable To Collect Current Evidence",
+ "Unable To Determine Transitive Trust Chain",
+ "Unable To Determine PCR"
+);
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t* pts_hash_alg_error_create(pts_meas_algorithms_t algorithms)
+{
+ bio_writer_t *writer;
+ chunk_t msg_info;
+ pa_tnc_attr_t *attr;
+ pen_type_t error_code = { PEN_TCG, TCG_PTS_HASH_ALG_NOT_SUPPORTED };
+
+ writer = bio_writer_create(4);
+ writer->write_uint16(writer, 0x0000);
+ writer->write_uint16(writer, algorithms);
+ msg_info = writer->get_buf(writer);
+ attr = ietf_attr_pa_tnc_error_create(error_code, msg_info);
+ writer->destroy(writer);
+
+ return attr;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t* pts_dh_group_error_create(pts_dh_group_t dh_groups)
+{
+ bio_writer_t *writer;
+ chunk_t msg_info;
+ pa_tnc_attr_t *attr;
+ pen_type_t error_code = { PEN_TCG, TCG_PTS_DH_GRPS_NOT_SUPPORTED };
+
+ writer = bio_writer_create(4);
+ writer->write_uint16(writer, 0x0000);
+ writer->write_uint16(writer, dh_groups);
+ msg_info = writer->get_buf(writer);
+ attr = ietf_attr_pa_tnc_error_create(error_code, msg_info);
+ writer->destroy(writer);
+
+ return attr;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t* pts_dh_nonce_error_create(int min_nonce_len, int max_nonce_len)
+{
+ bio_writer_t *writer;
+ chunk_t msg_info;
+ pa_tnc_attr_t *attr;
+ pen_type_t error_code = { PEN_TCG, TCG_PTS_BAD_NONCE_LENGTH };
+
+ writer = bio_writer_create(4);
+ writer->write_uint16(writer, min_nonce_len);
+ writer->write_uint16(writer, max_nonce_len);
+ msg_info = writer->get_buf(writer);
+ attr = ietf_attr_pa_tnc_error_create(error_code, msg_info);
+ writer->destroy(writer);
+
+ return attr;
+}
diff --git a/src/libimcv/pts/pts_error.h b/src/libimcv/pts/pts_error.h
new file mode 100644
index 000000000..9a53abd98
--- /dev/null
+++ b/src/libimcv/pts/pts_error.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts_error pts_error
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_ERROR_H_
+#define PTS_ERROR_H_
+
+typedef enum pts_error_code_t pts_error_code_t;
+
+#include "pts_meas_algo.h"
+#include "pts_dh_group.h"
+#include "pa_tnc/pa_tnc_attr.h"
+
+#include <library.h>
+
+#define PTS_MIN_NONCE_LEN 17
+#define PTS_MAX_NONCE_LEN 0xffff
+
+/**
+ * PTS Attestation Error Codes
+ * see section 3.14.2 of PTS Protocol: Binding to TNC IF-M Specification
+ */
+enum pts_error_code_t {
+ TCG_PTS_RESERVED_ERROR = 0,
+ TCG_PTS_HASH_ALG_NOT_SUPPORTED = 1,
+ TCG_PTS_INVALID_PATH = 2,
+ TCG_PTS_FILE_NOT_FOUND = 3,
+ TCG_PTS_REG_NOT_SUPPORTED = 4,
+ TCG_PTS_REG_KEY_NOT_FOUND = 5,
+ TCG_PTS_DH_GRPS_NOT_SUPPORTED = 6,
+ TCG_PTS_BAD_NONCE_LENGTH = 7,
+ TCG_PTS_INVALID_NAME_FAM = 8,
+ TCG_PTS_TPM_VERS_NOT_SUPPORTED = 9,
+ TCG_PTS_INVALID_DELIMITER = 10,
+ TCG_PTS_OPERATION_NOT_SUPPORTED = 11,
+ TCG_PTS_RM_ERROR = 12,
+ TCG_PTS_UNABLE_LOCAL_VAL = 13,
+ TCG_PTS_UNABLE_CUR_EVID = 14,
+ TCG_PTS_UNABLE_DET_TTC = 15,
+ TCG_PTS_UNABLE_DET_PCR = 16,
+};
+
+/**
+ * enum name for pts_error_code_t.
+ */
+extern enum_name_t *pts_error_code_names;
+
+/**
+ * Creates a PTS Hash Algorithm Not Supported Error Attribute
+ * see section 4.2.2 of PTS Protocol: Binding to TNC IF-M Specification
+ *
+ * @param algorithms supported measurement hash algorithms
+ */
+pa_tnc_attr_t* pts_hash_alg_error_create(pts_meas_algorithms_t algorithms);
+
+/**
+ * Creates a PTS DH Group Not Supported Error Attribute
+ * see section 4.2.4 of PTS Protocol: Binding to TNC IF-M Specification
+ *
+ * @param dh_groups supported DH groups
+ */
+pa_tnc_attr_t* pts_dh_group_error_create(pts_dh_group_t dh_groups);
+
+/**
+ * Creates a PTS DH PN Nonce Not Supported Error Attribute
+ * see section 4.2.5 of PTS Protocol: Binding to TNC IF-M Specification
+ *
+ * @param min_nonce_len minimum nonce length
+ * @param max_nonce_len maximum nonce length
+ */
+pa_tnc_attr_t* pts_dh_nonce_error_create(int min_nonce_len, int max_nonce_len);
+
+#endif /** PTS_ERROR_H_ @}*/
diff --git a/src/libimcv/pts/pts_file_meas.c b/src/libimcv/pts/pts_file_meas.c
new file mode 100644
index 000000000..478892aea
--- /dev/null
+++ b/src/libimcv/pts/pts_file_meas.c
@@ -0,0 +1,414 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pts_file_meas.h"
+
+#include <collections/linked_list.h>
+#include <utils/debug.h>
+
+#include <sys/stat.h>
+#include <libgen.h>
+#include <errno.h>
+
+typedef struct private_pts_file_meas_t private_pts_file_meas_t;
+
+/**
+ * Private data of a pts_file_meas_t object.
+ *
+ */
+struct private_pts_file_meas_t {
+
+ /**
+ * Public pts_file_meas_t interface.
+ */
+ pts_file_meas_t public;
+
+ /**
+ * ID of PTS File Measurement Request
+ */
+ u_int16_t request_id;
+
+ /**
+ * List of File Measurements
+ */
+ linked_list_t *list;
+};
+
+typedef struct entry_t entry_t;
+
+/**
+ * PTS File Measurement entry
+ */
+struct entry_t {
+ char *filename;
+ chunk_t measurement;
+};
+
+/**
+ * Free an entry_t object
+ */
+static void free_entry(entry_t *entry)
+{
+ if (entry)
+ {
+ free(entry->filename);
+ free(entry->measurement.ptr);
+ free(entry);
+ }
+}
+
+METHOD(pts_file_meas_t, get_request_id, u_int16_t,
+ private_pts_file_meas_t *this)
+{
+ return this->request_id;
+}
+
+METHOD(pts_file_meas_t, get_file_count, int,
+ private_pts_file_meas_t *this)
+{
+ return this->list->get_count(this->list);
+}
+
+METHOD(pts_file_meas_t, add, void,
+ private_pts_file_meas_t *this, char *filename, chunk_t measurement)
+{
+ entry_t *entry;
+
+ entry = malloc_thing(entry_t);
+ entry->filename = strdup(filename);
+ entry->measurement = chunk_clone(measurement);
+
+ this->list->insert_last(this->list, entry);
+}
+
+/**
+ * Enumerate file measurement entries
+ */
+static bool entry_filter(void *null, entry_t **entry, char **filename,
+ void *i2, chunk_t *measurement)
+{
+ *filename = (*entry)->filename;
+ *measurement = (*entry)->measurement;
+ return TRUE;
+}
+
+METHOD(pts_file_meas_t, create_enumerator, enumerator_t*,
+ private_pts_file_meas_t *this)
+{
+ return enumerator_create_filter(this->list->create_enumerator(this->list),
+ (void*)entry_filter, NULL, NULL);
+}
+
+METHOD(pts_file_meas_t, check, bool,
+ private_pts_file_meas_t *this, pts_database_t *pts_db, int pid,
+ pts_meas_algorithms_t algo)
+{
+ enumerator_t *enumerator, *e;
+ entry_t *entry;
+ chunk_t hash;
+ int count_ok = 0, count_not_found = 0, count_differ = 0;
+ status_t status;
+
+ enumerator = this->list->create_enumerator(this->list);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ status = NOT_FOUND;
+
+ e = pts_db->create_file_meas_enumerator(pts_db, pid, algo,
+ entry->filename);
+ if (e)
+ {
+ while (e->enumerate(e, &hash))
+ {
+ if (chunk_equals(entry->measurement, hash))
+ {
+ status = SUCCESS;
+ break;
+ }
+ else
+ {
+ status = VERIFY_ERROR;
+ }
+ }
+ e->destroy(e);
+ }
+ else
+ {
+ status = FAILED;
+ }
+
+ switch (status)
+ {
+ case SUCCESS:
+ DBG3(DBG_PTS, " %#B for '%s' is ok", &entry->measurement,
+ entry->filename);
+ count_ok++;
+ break;
+ case NOT_FOUND:
+ DBG2(DBG_PTS, " %#B for '%s' not found", &entry->measurement,
+ entry->filename);
+ count_not_found++;
+ break;
+ case VERIFY_ERROR:
+ DBG1(DBG_PTS, " %#B for '%s' differs", &entry->measurement,
+ entry->filename);
+ count_differ++;
+ break;
+ case FAILED:
+ default:
+ DBG1(DBG_PTS, " %#B for '%s' failed", &entry->measurement,
+ entry->filename);
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ DBG1(DBG_PTS, "%d measurements, %d ok, %d not found, %d differ",
+ this->list->get_count(this->list),
+ count_ok, count_not_found, count_differ);
+ return TRUE;
+}
+
+METHOD(pts_file_meas_t, verify, bool,
+ private_pts_file_meas_t *this, enumerator_t *e_hash, bool is_dir)
+{
+ int fid, fid_last = 0;
+ char *filename;
+ chunk_t measurement;
+ entry_t *entry;
+ enumerator_t *enumerator = NULL;
+ bool found = FALSE, match = FALSE, success = TRUE;
+
+ while (e_hash->enumerate(e_hash, &fid, &filename, &measurement))
+ {
+ if (fid != fid_last)
+ {
+ if (found && !match)
+ {
+ /* no matching hash value found for last filename */
+ success = FALSE;
+ DBG1(DBG_PTS, " %#B for '%s' is incorrect",
+ &entry->measurement, entry->filename);
+ enumerator->destroy(enumerator);
+ }
+
+ /* get a new filename from the database */
+ found = FALSE;
+ match = FALSE;
+ fid_last = fid;
+
+ /**
+ * check if we find an entry for this filename
+ * in the PTS measurement list
+ */
+ enumerator = this->list->create_enumerator(this->list);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (!is_dir || streq(filename, entry->filename))
+ {
+ found = TRUE;
+ break;
+ }
+ }
+
+ /* no PTS measurement returned for this filename */
+ if (!found)
+ {
+ success = FALSE;
+ DBG1(DBG_PTS, " no measurement found for '%s'", filename);
+ enumerator->destroy(enumerator);
+ }
+ }
+
+ if (found && !match)
+ {
+ if (chunk_equals(measurement, entry->measurement))
+ {
+ match = TRUE;
+ DBG2(DBG_PTS, " %#B for '%s' is ok",
+ &entry->measurement, entry->filename);
+ enumerator->destroy(enumerator);
+ }
+ }
+ }
+
+ if (found && !match)
+ {
+ /* no matching hash value found for the very last filename */
+ success = FALSE;
+ DBG1(DBG_PTS, " %#B for '%s' is incorrect",
+ &entry->measurement, entry->filename);
+ enumerator->destroy(enumerator);
+ }
+
+ return success;
+}
+
+METHOD(pts_file_meas_t, destroy, void,
+ private_pts_file_meas_t *this)
+{
+ this->list->destroy_function(this->list, (void *)free_entry);
+ free(this);
+}
+
+/**
+ * See header
+ */
+pts_file_meas_t *pts_file_meas_create(u_int16_t request_id)
+{
+ private_pts_file_meas_t *this;
+
+ INIT(this,
+ .public = {
+ .get_request_id = _get_request_id,
+ .get_file_count = _get_file_count,
+ .add = _add,
+ .create_enumerator = _create_enumerator,
+ .check = _check,
+ .verify = _verify,
+ .destroy = _destroy,
+ },
+ .request_id = request_id,
+ .list = linked_list_create(),
+ );
+
+ return &this->public;
+}
+
+/**
+ * Hash a file with a given absolute pathname
+ */
+static bool hash_file(hasher_t *hasher, char *pathname, u_char *hash)
+{
+ u_char buffer[4096];
+ size_t bytes_read;
+ bool success = TRUE;
+ FILE *file;
+
+ file = fopen(pathname, "rb");
+ if (!file)
+ {
+ DBG1(DBG_PTS," file '%s' can not be opened, %s", pathname,
+ strerror(errno));
+ return FALSE;
+ }
+ while (TRUE)
+ {
+ bytes_read = fread(buffer, 1, sizeof(buffer), file);
+ if (bytes_read > 0)
+ {
+ if (!hasher->get_hash(hasher, chunk_create(buffer, bytes_read), NULL))
+ {
+ DBG1(DBG_PTS, " hasher increment error");
+ success = FALSE;
+ break;
+ }
+ }
+ else
+ {
+ if (!hasher->get_hash(hasher, chunk_empty, hash))
+ {
+ DBG1(DBG_PTS, " hasher finalize error");
+ success = FALSE;
+ }
+ break;
+ }
+ }
+ fclose(file);
+
+ return success;
+}
+
+/**
+ * See header
+ */
+pts_file_meas_t *pts_file_meas_create_from_path(u_int16_t request_id,
+ char *pathname, bool is_dir, bool use_rel_name,
+ pts_meas_algorithms_t alg)
+{
+ private_pts_file_meas_t *this;
+ hash_algorithm_t hash_alg;
+ hasher_t *hasher;
+ u_char hash[HASH_SIZE_SHA384];
+ chunk_t measurement;
+ char* filename;
+ bool success = TRUE;
+
+ /* Create a hasher and a hash measurement buffer */
+ hash_alg = pts_meas_algo_to_hash(alg);
+ hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
+ if (!hasher)
+ {
+ DBG1(DBG_PTS, "hasher %N not available", hash_algorithm_names, hash_alg);
+ return NULL;
+ }
+ measurement = chunk_create(hash, hasher->get_hash_size(hasher));
+ this = (private_pts_file_meas_t*)pts_file_meas_create(request_id);
+
+ if (is_dir)
+ {
+ enumerator_t *enumerator;
+ char *rel_name, *abs_name;
+ struct stat st;
+
+ enumerator = enumerator_create_directory(pathname);
+ if (!enumerator)
+ {
+ DBG1(DBG_PTS, " directory '%s' can not be opened, %s", pathname,
+ strerror(errno));
+ success = FALSE;
+ goto end;
+ }
+ while (enumerator->enumerate(enumerator, &rel_name, &abs_name, &st))
+ {
+ /* measure regular files only */
+ if (S_ISREG(st.st_mode) && *rel_name != '.')
+ {
+ if (!hash_file(hasher, abs_name, hash))
+ {
+ continue;
+ }
+ filename = use_rel_name ? rel_name : abs_name;
+ DBG2(DBG_PTS, " %#B for '%s'", &measurement, filename);
+ add(this, filename, measurement);
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ else
+ {
+ if (!hash_file(hasher, pathname, hash))
+ {
+ success = FALSE;
+ goto end;
+ }
+ filename = use_rel_name ? path_basename(pathname) : strdup(pathname);
+ DBG2(DBG_PTS, " %#B for '%s'", &measurement, filename);
+ add(this, filename, measurement);
+ free(filename);
+ }
+
+end:
+ hasher->destroy(hasher);
+ if (success)
+ {
+ return &this->public;
+ }
+ else
+ {
+ destroy(this);
+ return NULL;
+ }
+}
diff --git a/src/libimcv/pts/pts_file_meas.h b/src/libimcv/pts/pts_file_meas.h
new file mode 100644
index 000000000..4bf28e280
--- /dev/null
+++ b/src/libimcv/pts/pts_file_meas.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts_file_meas pts_file_meas
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_FILE_MEAS_H_
+#define PTS_FILE_MEAS_H_
+
+#include "pts/pts_database.h"
+
+#include <library.h>
+
+typedef struct pts_file_meas_t pts_file_meas_t;
+
+/**
+ * Class storing PTS File Measurements
+ */
+struct pts_file_meas_t {
+
+ /**
+ * Get the ID of the PTS File Measurement Request
+ *
+ * @return ID of PTS File Measurement Request
+ */
+ u_int16_t (*get_request_id)(pts_file_meas_t *this);
+
+ /**
+ * Get the number of measured files
+ *
+ * @return Number of measured files
+ */
+ int (*get_file_count)(pts_file_meas_t *this);
+
+ /**
+ * Add a PTS File Measurement
+ *
+ * @param filename Name of measured file or directory
+ * @param measurement PTS Measurement hash
+ */
+ void (*add)(pts_file_meas_t *this, char *filename, chunk_t measurement);
+
+ /**
+ * Create a PTS File Measurement enumerator
+ *
+ * @return Enumerator returning filename and measurement
+ */
+ enumerator_t* (*create_enumerator)(pts_file_meas_t *this);
+
+ /**
+ * Check PTS File Measurements against reference value in the database
+ *
+ * @param db PTS Measurement database
+ * @param pid Primary key of software product in database
+ * @param algo PTS Measurement algorithm used
+ * @return TRUE if all measurements agreed
+ */
+ bool (*check)(pts_file_meas_t *this, pts_database_t *db, int pid,
+ pts_meas_algorithms_t algo);
+
+ /**
+ * Verify stored hashes against PTS File Measurements
+ *
+ * @param e_hash Hash enumerator
+ * @param is_dir TRUE for directory contents hashes
+ * @return TRUE if all hashes match a measurement
+ */
+ bool (*verify)(pts_file_meas_t *this, enumerator_t *e_hash, bool is_dir);
+
+ /**
+ * Destroys a pts_file_meas_t object.
+ */
+ void (*destroy)(pts_file_meas_t *this);
+
+};
+
+/**
+ * Creates a pts_file_meas_t object
+ *
+ * @param request_id ID of PTS File Measurement Request
+ */
+pts_file_meas_t* pts_file_meas_create(u_int16_t request_id);
+
+/**
+ * Creates a pts_file_meas_t object measuring a file/directory
+ *
+ * @param request_id ID of PTS File Measurement Request
+ * @param pathname Absolute file or directory pathname
+ * @param is_dir TRUE if directory path
+ * @param use_rel_name TRUE if relative filenames are to be used
+ * @param alg PTS hash measurement algorithm to be used
+ */
+pts_file_meas_t* pts_file_meas_create_from_path(u_int16_t request_id,
+ char* pathname, bool is_dir, bool use_rel_name,
+ pts_meas_algorithms_t alg);
+
+#endif /** PTS_FILE_MEAS_H_ @}*/
diff --git a/src/libimcv/pts/pts_file_meta.c b/src/libimcv/pts/pts_file_meta.c
new file mode 100644
index 000000000..9cca0a5a5
--- /dev/null
+++ b/src/libimcv/pts/pts_file_meta.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pts_file_meta.h"
+
+#include <collections/linked_list.h>
+#include <utils/debug.h>
+
+typedef struct private_pts_file_meta_t private_pts_file_meta_t;
+
+/**
+ * Private data of a pts_file_meta_t object.
+ *
+ */
+struct private_pts_file_meta_t {
+
+ /**
+ * Public pts_file_meta_t interface.
+ */
+ pts_file_meta_t public;
+
+ /**
+ * List of File Metadata
+ */
+ linked_list_t *list;
+};
+
+/**
+ * Free an pts_file_metadata_t object
+ */
+static void free_entry(pts_file_metadata_t *entry)
+{
+ if (entry)
+ {
+ free(entry->filename);
+ free(entry);
+ }
+}
+
+METHOD(pts_file_meta_t, get_file_count, int,
+ private_pts_file_meta_t *this)
+{
+ return this->list->get_count(this->list);
+}
+
+METHOD(pts_file_meta_t, add, void,
+ private_pts_file_meta_t *this, pts_file_metadata_t *metadata)
+{
+ this->list->insert_last(this->list, metadata);
+}
+
+METHOD(pts_file_meta_t, create_enumerator, enumerator_t*,
+ private_pts_file_meta_t *this)
+{
+ return this->list->create_enumerator(this->list);
+}
+
+METHOD(pts_file_meta_t, destroy, void,
+ private_pts_file_meta_t *this)
+{
+ this->list->destroy_function(this->list, (void *)free_entry);
+ free(this);
+}
+
+/**
+ * See header
+ */
+pts_file_meta_t *pts_file_meta_create()
+{
+ private_pts_file_meta_t *this;
+
+ INIT(this,
+ .public = {
+ .get_file_count = _get_file_count,
+ .add = _add,
+ .create_enumerator = _create_enumerator,
+ .destroy = _destroy,
+ },
+ .list = linked_list_create(),
+ );
+
+ return &this->public;
+}
+
diff --git a/src/libimcv/pts/pts_file_meta.h b/src/libimcv/pts/pts_file_meta.h
new file mode 100644
index 000000000..3f1813306
--- /dev/null
+++ b/src/libimcv/pts/pts_file_meta.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts_file_meta pts_file_meta
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_FILE_META_H_
+#define PTS_FILE_META_H_
+
+#include "pts_file_type.h"
+
+#include <time.h>
+#include <library.h>
+
+typedef struct pts_file_meta_t pts_file_meta_t;
+typedef struct pts_file_metadata_t pts_file_metadata_t;
+
+/**
+ * Structure holding file metadata
+ */
+struct pts_file_metadata_t {
+ pts_file_type_t type;
+ u_int64_t filesize;
+ u_int64_t created;
+ u_int64_t modified;
+ u_int64_t accessed;
+ u_int64_t owner;
+ u_int64_t group;
+ char *filename;
+};
+
+/**
+ * Class storing PTS File Metadata
+ */
+struct pts_file_meta_t {
+
+ /**
+ * Get the number of files
+ *
+ * @return Number of files
+ */
+ int (*get_file_count)(pts_file_meta_t *this);
+
+ /**
+ * Add PTS File Metadata
+ *
+ * @param filename Name of measured file or directory
+ * @param metadata File metadata
+ */
+ void (*add)(pts_file_meta_t *this, pts_file_metadata_t *metadata);
+
+ /**
+ * Create a PTS File Metadata enumerator
+ *
+ * @return Enumerator returning file metadata
+ */
+ enumerator_t* (*create_enumerator)(pts_file_meta_t *this);
+
+ /**
+ * Destroys a pts_file_meta_t object.
+ */
+ void (*destroy)(pts_file_meta_t *this);
+
+};
+
+/**
+ * Creates a pts_file_meta_t object
+ */
+pts_file_meta_t* pts_file_meta_create();
+
+#endif /** PTS_FILE_MEAS_H_ @}*/
diff --git a/src/libimcv/pts/pts_file_type.c b/src/libimcv/pts/pts_file_type.c
new file mode 100644
index 000000000..fe849dea4
--- /dev/null
+++ b/src/libimcv/pts/pts_file_type.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2011 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pts_file_type.h"
+
+ENUM(pts_file_type_names, PTS_FILE_OTHER, PTS_FILE_SOCKET,
+ "Other",
+ "FIFO",
+ "Character-Special",
+ "Reserved-3",
+ "Directory",
+ "Reserved-5",
+ "Block-Special",
+ "Reserved-7",
+ "Regular",
+ "Reserved-9",
+ "Symbolic-Link",
+ "Reserved-11",
+ "Socket"
+);
+
diff --git a/src/libimcv/pts/pts_file_type.h b/src/libimcv/pts/pts_file_type.h
new file mode 100644
index 000000000..c1d236888
--- /dev/null
+++ b/src/libimcv/pts/pts_file_type.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts_file_type pts_file_type
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_FILE_TYPE_H_
+#define PTS_FILE_TYPE_H_
+
+#include <library.h>
+
+typedef enum pts_file_type_t pts_file_type_t;
+
+/**
+ * PTS File Type
+ * see section 3.17.3 of PTS Protocol: Binding to TNC IF-M Specification
+ */
+enum pts_file_type_t {
+ /** Either unknown or different from standardized types */
+ PTS_FILE_OTHER = 0x0000,
+ /** Pipe communication file */
+ PTS_FILE_FIFO = 0x0001,
+ /** Character special file */
+ PTS_FILE_CHAR_SPEC = 0x0002,
+ /** Reserved */
+ PTS_FILE_RESERVED_3 = 0x0003,
+ /** Directory */
+ PTS_FILE_DIRECTORY = 0x0004,
+ /** Reserved */
+ PTS_FILE_RESERVED_5 = 0x0005,
+ /** Block special file */
+ PTS_FILE_BLOCK_SPEC = 0x0006,
+ /** Reserved */
+ PTS_FILE_RESERVED_7 = 0x0007,
+ /** Regular file */
+ PTS_FILE_REGULAR = 0x0008,
+ /** Reserved */
+ PTS_FILE_RESERVED_9 = 0x0009,
+ /** Symbolic link */
+ PTS_FILE_SYM_LINK = 0x000A,
+ /** Reserved */
+ PTS_FILE_RESERVED_11 = 0x000B,
+ /** Socket communication special file */
+ PTS_FILE_SOCKET = 0x000C,
+};
+
+extern enum_name_t *pts_file_type_names;
+
+#endif /** PTS_FILE_TYPE_H_ @}*/
diff --git a/src/libimcv/pts/pts_ima_bios_list.c b/src/libimcv/pts/pts_ima_bios_list.c
new file mode 100644
index 000000000..5051b6c2d
--- /dev/null
+++ b/src/libimcv/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/libimcv/pts/pts_ima_bios_list.h b/src/libimcv/pts/pts_ima_bios_list.h
new file mode 100644
index 000000000..ad162e15a
--- /dev/null
+++ b/src/libimcv/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/libimcv/pts/pts_ima_event_list.c b/src/libimcv/pts/pts_ima_event_list.c
new file mode 100644
index 000000000..9bff4654b
--- /dev/null
+++ b/src/libimcv/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/libimcv/pts/pts_ima_event_list.h b/src/libimcv/pts/pts_ima_event_list.h
new file mode 100644
index 000000000..bf5478a51
--- /dev/null
+++ b/src/libimcv/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/libimcv/pts/pts_meas_algo.c b/src/libimcv/pts/pts_meas_algo.c
new file mode 100644
index 000000000..c06371123
--- /dev/null
+++ b/src/libimcv/pts/pts_meas_algo.c
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2011-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pts_meas_algo.h"
+
+#include <utils/debug.h>
+
+ENUM_BEGIN(pts_meas_algorithm_names, PTS_MEAS_ALGO_NONE, PTS_MEAS_ALGO_NONE,
+ "None");
+ENUM_NEXT(pts_meas_algorithm_names, PTS_MEAS_ALGO_SHA384, PTS_MEAS_ALGO_SHA384,
+ PTS_MEAS_ALGO_NONE,
+ "SHA384");
+ENUM_NEXT(pts_meas_algorithm_names, PTS_MEAS_ALGO_SHA256, PTS_MEAS_ALGO_SHA256,
+ PTS_MEAS_ALGO_SHA384,
+ "SHA256");
+ENUM_NEXT(pts_meas_algorithm_names, PTS_MEAS_ALGO_SHA1, PTS_MEAS_ALGO_SHA1,
+ PTS_MEAS_ALGO_SHA256,
+ "SHA1");
+ENUM_END(pts_meas_algorithm_names, PTS_MEAS_ALGO_SHA1);
+
+/**
+ * Described in header.
+ */
+bool pts_meas_algo_probe(pts_meas_algorithms_t *algorithms)
+{
+ enumerator_t *enumerator;
+ hash_algorithm_t hash_alg;
+ const char *plugin_name;
+ char format1[] = " %s PTS measurement algorithm %N[%s] available";
+ char format2[] = " %s PTS measurement algorithm %N not available";
+
+ *algorithms = 0;
+
+ enumerator = lib->crypto->create_hasher_enumerator(lib->crypto);
+ while (enumerator->enumerate(enumerator, &hash_alg, &plugin_name))
+ {
+ if (hash_alg == HASH_SHA1)
+ {
+ *algorithms |= PTS_MEAS_ALGO_SHA1;
+ DBG2(DBG_PTS, format1, "mandatory", hash_algorithm_names, hash_alg,
+ plugin_name);
+ }
+ else if (hash_alg == HASH_SHA256)
+ {
+ *algorithms |= PTS_MEAS_ALGO_SHA256;
+ DBG2(DBG_PTS, format1, "mandatory", hash_algorithm_names, hash_alg,
+ plugin_name);
+ }
+ else if (hash_alg == HASH_SHA384)
+ {
+ *algorithms |= PTS_MEAS_ALGO_SHA384;
+ DBG2(DBG_PTS, format1, "optional ", hash_algorithm_names, hash_alg,
+ plugin_name);
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (!(*algorithms & PTS_MEAS_ALGO_SHA384))
+ {
+ DBG1(DBG_PTS, format2, "optional ", hash_algorithm_names, HASH_SHA384);
+ }
+ if ((*algorithms & PTS_MEAS_ALGO_SHA1) &&
+ (*algorithms & PTS_MEAS_ALGO_SHA256))
+ {
+ return TRUE;
+ }
+ if (!(*algorithms & PTS_MEAS_ALGO_SHA1))
+ {
+ DBG1(DBG_PTS, format2, "mandatory", hash_algorithm_names, HASH_SHA1);
+ }
+ if (!(*algorithms & PTS_MEAS_ALGO_SHA256))
+ {
+ DBG1(DBG_PTS, format2, "mandatory", hash_algorithm_names, HASH_SHA256);
+ }
+ return FALSE;
+}
+
+/**
+ * Described in header.
+ */
+bool pts_meas_algo_update(char *hash_alg, pts_meas_algorithms_t *algorithms)
+{
+ if (strcaseeq(hash_alg, "sha384") || strcaseeq(hash_alg, "sha2_384"))
+ {
+ /* nothing to update, all algorithms are supported */
+ return TRUE;
+ }
+ if (strcaseeq(hash_alg, "sha256") || strcaseeq(hash_alg, "sha2_256"))
+ {
+ /* remove SHA384algorithm */
+ *algorithms &= ~PTS_MEAS_ALGO_SHA384;
+ return TRUE;
+ }
+ if (strcaseeq(hash_alg, "sha1"))
+ {
+ /* remove SHA384 and SHA256 algorithms */
+ *algorithms &= ~(PTS_MEAS_ALGO_SHA384 | PTS_MEAS_ALGO_SHA256);
+ return TRUE;
+ }
+ DBG1(DBG_PTS, "unknown hash algorithm '%s' configured", hash_alg);
+ return FALSE;
+}
+
+/**
+ * Described in header.
+ */
+pts_meas_algorithms_t pts_meas_algo_select(pts_meas_algorithms_t supported_algos,
+ pts_meas_algorithms_t offered_algos)
+{
+ if ((supported_algos & PTS_MEAS_ALGO_SHA384) &&
+ (offered_algos & PTS_MEAS_ALGO_SHA384))
+ {
+ return PTS_MEAS_ALGO_SHA384;
+ }
+ if ((supported_algos & PTS_MEAS_ALGO_SHA256) &&
+ (offered_algos & PTS_MEAS_ALGO_SHA256))
+ {
+ return PTS_MEAS_ALGO_SHA256;
+ }
+ if ((supported_algos & PTS_MEAS_ALGO_SHA1) &&
+ (offered_algos & PTS_MEAS_ALGO_SHA1))
+ {
+ return PTS_MEAS_ALGO_SHA1;
+ }
+ return PTS_MEAS_ALGO_NONE;
+}
+
+/**
+ * Described in header.
+ */
+hash_algorithm_t pts_meas_algo_to_hash(pts_meas_algorithms_t algorithm)
+{
+ switch (algorithm)
+ {
+ case PTS_MEAS_ALGO_SHA1:
+ return HASH_SHA1;
+ case PTS_MEAS_ALGO_SHA256:
+ return HASH_SHA256;
+ case PTS_MEAS_ALGO_SHA384:
+ return HASH_SHA384;
+ default:
+ return HASH_UNKNOWN;
+ }
+}
+
+/**
+ * Described in header.
+ */
+size_t pts_meas_algo_hash_size(pts_meas_algorithms_t algorithm)
+{
+ switch (algorithm)
+ {
+ case PTS_MEAS_ALGO_SHA1:
+ return HASH_SIZE_SHA1;
+ case PTS_MEAS_ALGO_SHA256:
+ return HASH_SIZE_SHA256;
+ case PTS_MEAS_ALGO_SHA384:
+ return HASH_SIZE_SHA384;
+ case PTS_MEAS_ALGO_NONE:
+ default:
+ return 0;
+ }
+}
+
diff --git a/src/libimcv/pts/pts_meas_algo.h b/src/libimcv/pts/pts_meas_algo.h
new file mode 100644
index 000000000..eec7e7981
--- /dev/null
+++ b/src/libimcv/pts/pts_meas_algo.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2011-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts_meas_algo pts_meas_algo
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_MEAS_ALGO_H_
+#define PTS_MEAS_ALGO_H_
+
+#include <library.h>
+#include <crypto/hashers/hasher.h>
+
+typedef enum pts_meas_algorithms_t pts_meas_algorithms_t;
+
+/**
+ * PTS Measurement Algorithms
+ */
+enum pts_meas_algorithms_t {
+ PTS_MEAS_ALGO_NONE = 0,
+ PTS_MEAS_ALGO_SHA384 = (1<<13),
+ PTS_MEAS_ALGO_SHA256 = (1<<14),
+ PTS_MEAS_ALGO_SHA1 = (1<<15)
+};
+
+/**
+ * enum name for pts_meas_algorithms_t.
+ */
+extern enum_name_t *pts_meas_algorithm_names;
+
+/**
+ * Diffie-Hellman Hash Algorithm Values
+ * see section 3.8.5 of PTS Protocol: Binding to TNC IF-M Specification
+ *
+ * 1
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |1|2|3|R|R|R|R|R|R|R|R|R|R|R|R|R|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ */
+
+/**
+ * Probe available PTS measurement algorithms
+ *
+ * @param algorithms set of available algorithms
+ * @return TRUE if mandatory algorithms are available
+ */
+bool pts_meas_algo_probe(pts_meas_algorithms_t *algorithms);
+
+/**
+ * Update supported PTS measurement algorithms according to configuration
+ *
+ * sha1 : PTS_MEAS_ALGO_SHA1
+ * sha256: PTS_MEAS_ALGO_SHA1 | PTS_MEAS_ALGO_SHA256
+ * sha384: PTS_MEAS_ALGO_SHA1 | PTS_MEAS_ALGO_SHA256 | PTS_MEAS_ALGO_SHA384
+ *
+ * The PTS-IMC is expected to select the strongest supported algorithm
+ *
+ * @param hash_alg configured hash algorithm
+ * @param algorithms returns set of available PTS measurement algorithms
+ */
+bool pts_meas_algo_update(char *hash_alg, pts_meas_algorithms_t *algorithms);
+
+/**
+ * Select the strongest PTS measurement algorithm
+ * among a set of offered PTS measurement algorithms
+ *
+ * @param supported_algos set of supported PTS measurement algorithms
+ * @param offered_algos set of offered PTS measurements algorithms
+ * @return selected algorithm
+ */
+pts_meas_algorithms_t pts_meas_algo_select(pts_meas_algorithms_t supported_algos,
+ pts_meas_algorithms_t offered_algos);
+
+/**
+ * Convert pts_meas_algorithms_t to hash_algorithm_t
+ *
+ * @param algorithm PTS measurement algorithm type
+ * @return libstrongswan hash algorithm type
+ */
+hash_algorithm_t pts_meas_algo_to_hash(pts_meas_algorithms_t algorithm);
+
+/**
+ * Return the hash size of a pts_meas_algorithm
+ *
+ * @param algorithm PTS measurement algorithm type
+ * @return hash size in bytes
+ */
+size_t pts_meas_algo_hash_size(pts_meas_algorithms_t algorithm);
+
+#endif /** PTS_MEAS_ALGO_H_ @}*/
diff --git a/src/libimcv/pts/pts_pcr.c b/src/libimcv/pts/pts_pcr.c
new file mode 100644
index 000000000..0af93b608
--- /dev/null
+++ b/src/libimcv/pts/pts_pcr.c
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2012 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pts_pcr.h"
+
+#include <utils/debug.h>
+
+#include <stdarg.h>
+
+typedef struct private_pts_pcr_t private_pts_pcr_t;
+
+/**
+ * Private data of a pts_pcr_t object.
+ *
+ */
+struct private_pts_pcr_t {
+
+ /**
+ * Public pts_pcr_t interface.
+ */
+ pts_pcr_t public;
+
+ /**
+ * Shadow PCR registers
+ */
+ chunk_t pcrs[PTS_PCR_MAX_NUM];
+
+ /**
+ * Number of extended PCR registers
+ */
+ u_int32_t pcr_count;
+
+ /**
+ * Highest extended PCR register
+ */
+ u_int32_t pcr_max;
+
+ /**
+ * Bitmap of extended PCR registers
+ */
+ u_int8_t pcr_select[PTS_PCR_MAX_NUM / 8];
+
+ /**
+ * Hasher used to extend shadow PCRs
+ */
+ hasher_t *hasher;
+
+};
+
+METHOD(pts_pcr_t, get_count, u_int32_t,
+ private_pts_pcr_t *this)
+{
+ return this->pcr_count;
+}
+
+METHOD(pts_pcr_t, select_pcr, bool,
+ private_pts_pcr_t *this, u_int32_t pcr)
+{
+ u_int32_t i, f;
+
+ if (pcr >= PTS_PCR_MAX_NUM)
+ {
+ DBG1(DBG_PTS, "PCR %2u: number is larger than maximum of %u",
+ pcr, PTS_PCR_MAX_NUM-1);
+ return FALSE;
+ }
+
+ /* Determine PCR selection flag */
+ i = pcr / 8;
+ f = 1 << (pcr - 8*i);
+
+ /* Has this PCR already been selected? */
+ if (!(this->pcr_select[i] & f))
+ {
+ this->pcr_select[i] |= f;
+ this->pcr_max = max(this->pcr_max, pcr);
+ this->pcr_count++;
+ }
+ return TRUE;
+}
+
+METHOD(pts_pcr_t, get_selection_size, size_t,
+ private_pts_pcr_t *this)
+{
+
+ /**
+ * A TPM v1.2 has 24 PCR Registers so the bitmask field length
+ * used by TrouSerS is at least 3 bytes
+ */
+ return PTS_PCR_MAX_NUM / 8;
+}
+
+typedef struct {
+ /** implements enumerator_t */
+ enumerator_t public;
+ /** current PCR */
+ u_int32_t pcr;
+ /** back reference to parent */
+ private_pts_pcr_t *pcrs;
+} pcr_enumerator_t;
+
+/**
+ * Implementation of enumerator.enumerate
+ */
+static bool pcr_enumerator_enumerate(pcr_enumerator_t *this, ...)
+{
+ u_int32_t *pcr, i, f;
+ va_list args;
+
+ va_start(args, this);
+ pcr = va_arg(args, u_int32_t*);
+ va_end(args);
+
+ while (this->pcr <= this->pcrs->pcr_max)
+ {
+ /* Determine PCR selection flag */
+ i = this->pcr / 8;
+ f = 1 << (this->pcr - 8*i);
+
+ /* Assign current PCR to output argument and increase */
+ *pcr = this->pcr++;
+
+ /* return if PCR is selected */
+ if (this->pcrs->pcr_select[i] & f)
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+METHOD(pts_pcr_t, create_enumerator, enumerator_t*,
+ private_pts_pcr_t *this)
+{
+ pcr_enumerator_t *enumerator;
+
+ INIT(enumerator,
+ .public = {
+ .enumerate = (void*)pcr_enumerator_enumerate,
+ .destroy = (void*)free,
+ },
+ .pcrs = this,
+ );
+
+ return (enumerator_t*)enumerator;
+}
+
+METHOD(pts_pcr_t, get, chunk_t,
+ private_pts_pcr_t *this, u_int32_t pcr)
+{
+ return (pcr < PTS_PCR_MAX_NUM) ? this->pcrs[pcr] : chunk_empty;
+}
+
+METHOD(pts_pcr_t, set, bool,
+ private_pts_pcr_t *this, u_int32_t pcr, chunk_t value)
+{
+ if (value.len != PTS_PCR_LEN)
+ {
+ DBG1(DBG_PTS, "PCR %2u: value does not fit", pcr);
+ return FALSE;
+ }
+ if (select_pcr(this, pcr))
+ {
+ memcpy(this->pcrs[pcr].ptr, value.ptr, PTS_PCR_LEN);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+METHOD(pts_pcr_t, extend, chunk_t,
+ private_pts_pcr_t *this, u_int32_t pcr, chunk_t measurement)
+{
+ if (measurement.len != PTS_PCR_LEN)
+ {
+ DBG1(DBG_PTS, "PCR %2u: measurement does not fit", pcr);
+ return chunk_empty;
+ }
+ if (!select_pcr(this, pcr))
+ {
+ return chunk_empty;
+ }
+ if (!this->hasher->get_hash(this->hasher, this->pcrs[pcr] , NULL) ||
+ !this->hasher->get_hash(this->hasher, measurement, this->pcrs[pcr].ptr))
+ {
+ DBG1(DBG_PTS, "PCR %2u: not extended due to hasher problem", pcr);
+ return chunk_empty;
+ }
+ return this->pcrs[pcr];
+}
+
+METHOD(pts_pcr_t, get_composite, chunk_t,
+ private_pts_pcr_t *this)
+{
+ chunk_t composite;
+ enumerator_t *enumerator;
+ u_int16_t selection_size;
+ u_int32_t pcr_field_size, pcr;
+ u_char *pos;
+
+ selection_size = get_selection_size(this);
+ pcr_field_size = this->pcr_count * PTS_PCR_LEN;
+
+ composite = chunk_alloc(2 + selection_size + 4 + pcr_field_size);
+ pos = composite.ptr;
+ htoun16(pos, selection_size);
+ pos += 2;
+ memcpy(pos, this->pcr_select, selection_size);
+ pos += selection_size;
+ htoun32(pos, pcr_field_size);
+ pos += 4;
+
+ enumerator = create_enumerator(this);
+ while (enumerator->enumerate(enumerator, &pcr))
+ {
+ memcpy(pos, this->pcrs[pcr].ptr, PTS_PCR_LEN);
+ pos += PTS_PCR_LEN;
+ }
+ enumerator->destroy(enumerator);
+
+ DBG3(DBG_PTS, "constructed PCR Composite: %B", &composite);
+ return composite;
+}
+
+METHOD(pts_pcr_t, destroy, void,
+ private_pts_pcr_t *this)
+{
+ u_int32_t i;
+
+ for (i = 0; i < PTS_PCR_MAX_NUM; i++)
+ {
+ free(this->pcrs[i].ptr);
+ }
+ this->hasher->destroy(this->hasher);
+ free(this);
+}
+
+/**
+ * See header
+ */
+pts_pcr_t *pts_pcr_create(void)
+{
+ private_pts_pcr_t *this;
+ hasher_t *hasher;
+ u_int32_t i;
+
+ hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
+ if (!hasher)
+ {
+ DBG1(DBG_PTS, "%N hasher could not be created",
+ hash_algorithm_short_names, HASH_SHA1);
+ return NULL;
+ }
+
+ INIT(this,
+ .public = {
+ .get_count = _get_count,
+ .select_pcr = _select_pcr,
+ .get_selection_size = _get_selection_size,
+ .create_enumerator = _create_enumerator,
+ .get = _get,
+ .set = _set,
+ .extend = _extend,
+ .get_composite = _get_composite,
+ .destroy = _destroy,
+ },
+ .hasher = hasher,
+ );
+
+ for (i = 0; i < PTS_PCR_MAX_NUM; i++)
+ {
+ this->pcrs[i] = chunk_alloc(PTS_PCR_LEN);
+ memset(this->pcrs[i].ptr, 0x00, PTS_PCR_LEN);
+ }
+
+ return &this->public;
+}
+
diff --git a/src/libimcv/pts/pts_pcr.h b/src/libimcv/pts/pts_pcr.h
new file mode 100644
index 000000000..f638b5ee4
--- /dev/null
+++ b/src/libimcv/pts/pts_pcr.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2012 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts_pcr pts_pcr
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_PCR_H_
+#define PTS_PCR_H_
+
+typedef struct pts_pcr_t pts_pcr_t;
+
+#include <library.h>
+
+/**
+ * Maximum number of PCR's of TPM, TPM Spec 1.2
+ */
+#define PTS_PCR_MAX_NUM 24
+
+/**
+ * Number of bytes that can be saved in a PCR of TPM, TPM Spec 1.2
+ */
+#define PTS_PCR_LEN 20
+
+/**
+ * Class implementing a shadow PCR register set
+ */
+struct pts_pcr_t {
+
+ /**
+ * Get the number of selected PCRs
+ *
+ * @return number of selected PCRs
+ */
+ u_int32_t (*get_count)(pts_pcr_t *this);
+
+ /**
+ * Mark a PCR as selected
+ *
+ * @param pcr index of PCR
+ * @return TRUE if PCR index exists
+ */
+ bool (*select_pcr)(pts_pcr_t *this, u_int32_t pcr);
+
+ /**
+ * Get the size of the selection field in bytes
+ *
+ * @return number of bytes written
+ */
+ size_t (*get_selection_size)(pts_pcr_t *this);
+
+ /**
+ * Create an enumerator over all selected PCR indexes
+ *
+ * @return enumerator
+ */
+ enumerator_t* (*create_enumerator)(pts_pcr_t *this);
+
+ /**
+ * Get the current content of a PCR
+ *
+ * @param pcr index of PCR
+ * @return content of PCR
+ */
+ chunk_t (*get)(pts_pcr_t *this, u_int32_t pcr);
+
+ /**
+ * Set the content of a PCR
+ *
+ * @param pcr index of PCR
+ * @param value new value of PCR
+ * @return TRUE if value could be set
+ */
+ bool (*set)(pts_pcr_t *this, u_int32_t pcr, chunk_t value);
+
+ /**
+ * Extend the content of a PCR
+ *
+ * @param pcr index of PCR
+ * @param measurement measurment value to be extended into PCR
+ * @return new content of PCR
+ */
+ chunk_t (*extend)(pts_pcr_t *this, u_int32_t pcr, chunk_t measurement);
+
+ /**
+ * Create a PCR Composite object over all selected PCRs
+ *
+ * @return PCR Composite object (must be freed)
+ */
+ chunk_t (*get_composite)(pts_pcr_t *this);
+
+ /**
+
+ * Destroys a pts_pcr_t object.
+ */
+ void (*destroy)(pts_pcr_t *this);
+
+};
+
+/**
+ * Creates an pts_pcr_t object
+ */
+pts_pcr_t* pts_pcr_create(void);
+
+#endif /** PTS_PCR_H_ @}*/
diff --git a/src/libimcv/pts/pts_proto_caps.h b/src/libimcv/pts/pts_proto_caps.h
new file mode 100644
index 000000000..4346d9b79
--- /dev/null
+++ b/src/libimcv/pts/pts_proto_caps.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts_proto_caps pts_proto_caps
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_PROTO_CAPS_H_
+#define PTS_PROTO_CAPS_H_
+
+typedef enum pts_proto_caps_flag_t pts_proto_caps_flag_t;
+
+#include <library.h>
+
+/**
+ * PTS Protocol Capabilities Flags
+ */
+enum pts_proto_caps_flag_t {
+ /** XML based Evidence Support flag */
+ PTS_PROTO_CAPS_X = (1<<0),
+ /** Trusted Platform Evidence flag */
+ PTS_PROTO_CAPS_T = (1<<1),
+ /** DH Nonce Negotiation Support flag */
+ PTS_PROTO_CAPS_D = (1<<2),
+ /** Verification Support flag */
+ PTS_PROTO_CAPS_V = (1<<3),
+ /** Current (In-Memory) Evidence Support flag */
+ PTS_PROTO_CAPS_C = (1<<4),
+};
+
+#endif /** PTS_PROTO_CAPS_H_ @}*/
diff --git a/src/libimcv/pts/pts_req_func_comp_evid.h b/src/libimcv/pts/pts_req_func_comp_evid.h
new file mode 100644
index 000000000..bbf5bbf5b
--- /dev/null
+++ b/src/libimcv/pts/pts_req_func_comp_evid.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts_req_func_comp_evid pts_req_func_comp_evid
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_REQ_FUNC_COMP_EVID_H_
+#define PTS_REQ_FUNC_COMP_EVID_H_
+
+typedef enum pts_req_func_comp_evid_t pts_req_func_comp_evid_t;
+
+#include <library.h>
+
+/**
+ * PTS Request Functional Component Evidence Flags
+ */
+enum pts_req_func_comp_evid_t {
+ /** Transitive Trust Chain flag */
+ PTS_REQ_FUNC_COMP_EVID_TTC = (1<<7),
+ /** Verify Component flag */
+ PTS_REQ_FUNC_COMP_EVID_VER = (1<<6),
+ /** Current Evidence flag */
+ PTS_REQ_FUNC_COMP_EVID_CURR = (1<<5),
+ /** PCR Information flag */
+ PTS_REQ_FUNC_COMP_EVID_PCR = (1<<4),
+};
+
+#endif /** PTS_FUNCT_COMP_EVID_REQ_H_ @}*/
diff --git a/src/libimcv/pts/pts_simple_evid_final.h b/src/libimcv/pts/pts_simple_evid_final.h
new file mode 100644
index 000000000..0c8dea0cc
--- /dev/null
+++ b/src/libimcv/pts/pts_simple_evid_final.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts_simple_evid_final pts_rsimple_evid_final
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_SIMPLE_EVID_FINAL_H_
+#define PTS_SIMPLE_EVID_FINAL_H_
+
+typedef enum pts_simple_evid_final_flag_t pts_simple_evid_final_flag_t;
+
+#include <library.h>
+
+/**
+ * PTS Simple Evidence Final Flags
+ */
+enum pts_simple_evid_final_flag_t {
+ /** TPM PCR Composite and TPM Quote Signature not included */
+ PTS_SIMPLE_EVID_FINAL_NO = 0x00,
+ /** TPM PCR Composite and TPM Quote Signature included
+ * using TPM_QUOTE_INFO */
+ PTS_SIMPLE_EVID_FINAL_QUOTE_INFO = 0x40,
+ /** TPM PCR Composite and TPM Quote Signature included
+ * using TPM_QUOTE_INFO2, TPM_CAP_VERSION_INFO not appended */
+ PTS_SIMPLE_EVID_FINAL_QUOTE_INFO2 = 0x80,
+ /** TPM PCR Composite and TPM Quote Signature included
+ * using TPM_QUOTE_INFO2, TPM_CAP_VERSION_INFO appended */
+ PTS_SIMPLE_EVID_FINAL_QUOTE_INFO2_CAP_VER = 0xC0,
+ /** Evidence Signature included */
+ PTS_SIMPLE_EVID_FINAL_EVID_SIG = 0x20,
+};
+
+#endif /** PTS_SIMPLE_EVID_FINAL_H_ @}*/
diff --git a/src/libimcv/seg/seg_contract.c b/src/libimcv/seg/seg_contract.c
new file mode 100644
index 000000000..7db702a08
--- /dev/null
+++ b/src/libimcv/seg/seg_contract.c
@@ -0,0 +1,479 @@
+/*
+ * Copyright (C) 2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "seg_contract.h"
+#include "seg_env.h"
+#include "ietf/ietf_attr_pa_tnc_error.h"
+#include "tcg/seg/tcg_seg_attr_seg_env.h"
+
+#include <utils/debug.h>
+#include <bio/bio_writer.h>
+
+#include <tncif_pa_subtypes.h>
+
+typedef struct private_seg_contract_t private_seg_contract_t;
+
+/**
+ * Private data of a seg_contract_t object.
+ */
+struct private_seg_contract_t {
+
+ /**
+ * Public seg_contract_t interface.
+ */
+ seg_contract_t public;
+
+ /**
+ * PA-TNC message type
+ */
+ pen_type_t msg_type;
+
+ /**
+ * Maximum PA-TNC attribute size
+ */
+ uint32_t max_attr_size;
+
+ /**
+ * Maximum PA-TNC attribute segment size
+ */
+ uint32_t max_seg_size;
+
+ /**
+ * Maximum PA-TNC attribute segment size
+ */
+ uint32_t last_base_attr_id;
+
+ /**
+ * List of attribute segment envelopes
+ */
+
+ linked_list_t *seg_envs;
+
+ /**
+ * Is this a null contract?
+ */
+ bool is_null;
+
+ /**
+ * Contract role
+ */
+ bool is_issuer;
+
+ /**
+ * Issuer ID (either IMV or IMC ID)
+ */
+ TNC_UInt32 issuer_id;
+
+ /**
+ * Responder ID (either IMC or IMV ID)
+ */
+ TNC_UInt32 responder_id;
+
+ /**
+ * IMC/IMV role
+ */
+ bool is_imc;
+
+};
+
+METHOD(seg_contract_t, get_msg_type, pen_type_t,
+ private_seg_contract_t *this)
+{
+ return this->msg_type;
+}
+
+METHOD(seg_contract_t, set_max_size, void,
+ private_seg_contract_t *this, uint32_t max_attr_size, uint32_t max_seg_size)
+{
+ this->max_attr_size = max_attr_size;
+ this->max_seg_size = max_seg_size;
+ this->is_null = max_attr_size == SEG_CONTRACT_MAX_SIZE_VALUE &&
+ max_seg_size == SEG_CONTRACT_MAX_SIZE_VALUE;
+}
+
+METHOD(seg_contract_t, get_max_size, void,
+ private_seg_contract_t *this, uint32_t *max_attr_size, uint32_t *max_seg_size)
+{
+ if (max_attr_size)
+ {
+ *max_attr_size = this->max_attr_size;
+ }
+ if (max_seg_size)
+ {
+ *max_seg_size = this->max_seg_size;
+ }
+}
+
+METHOD(seg_contract_t, check_size, bool,
+ private_seg_contract_t *this, pa_tnc_attr_t *attr, bool *oversize)
+{
+ chunk_t attr_value;
+ size_t attr_len;
+
+ *oversize = FALSE;
+
+ if (this->is_null)
+ {
+ /* null segmentation contract */
+ return FALSE;
+ }
+ attr->build(attr);
+ attr_value = attr->get_value(attr);
+ attr_len = PA_TNC_ATTR_HEADER_SIZE + attr_value.len;
+
+ if (attr_len > this->max_attr_size)
+ {
+ /* oversize attribute */
+ *oversize = TRUE;
+ return FALSE;
+ }
+ if (this->max_seg_size == SEG_CONTRACT_NO_FRAGMENTATION)
+ {
+ /* no fragmentation wanted */
+ return FALSE;
+ }
+ return attr_value.len > this->max_seg_size + TCG_SEG_ATTR_SEG_ENV_HEADER;
+}
+
+METHOD(seg_contract_t, first_segment, pa_tnc_attr_t*,
+ private_seg_contract_t *this, pa_tnc_attr_t *attr)
+{
+ seg_env_t *seg_env;
+
+ seg_env = seg_env_create(++this->last_base_attr_id, attr,
+ this->max_seg_size);
+ if (!seg_env)
+ {
+ return NULL;
+ }
+ this->seg_envs->insert_last(this->seg_envs, seg_env);
+
+ return seg_env->first_segment(seg_env);
+}
+
+METHOD(seg_contract_t, next_segment, pa_tnc_attr_t*,
+ private_seg_contract_t *this, uint32_t base_attr_id)
+{
+ pa_tnc_attr_t *seg_env_attr = NULL;
+ seg_env_t *seg_env;
+ bool last_segment = FALSE;
+ enumerator_t *enumerator;
+
+ enumerator = this->seg_envs->create_enumerator(this->seg_envs);
+ while (enumerator->enumerate(enumerator, &seg_env))
+ {
+ if (seg_env->get_base_attr_id(seg_env) == base_attr_id)
+ {
+ seg_env_attr = seg_env->next_segment(seg_env, &last_segment);
+ if (!seg_env_attr)
+ {
+ break;
+ }
+ if (last_segment)
+ {
+ this->seg_envs->remove_at(this->seg_envs, enumerator);
+ seg_env->destroy(seg_env);
+ }
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ return seg_env_attr;
+}
+
+METHOD(seg_contract_t, add_segment, pa_tnc_attr_t*,
+ private_seg_contract_t *this, pa_tnc_attr_t *attr, pa_tnc_attr_t **error,
+ bool *more)
+{
+ tcg_seg_attr_seg_env_t *seg_env_attr;
+ seg_env_t *current, *seg_env = NULL;
+ pa_tnc_attr_t *base_attr;
+ pen_type_t error_code;
+ uint32_t base_attr_id;
+ uint8_t flags;
+ chunk_t segment_data, msg_info;
+ enumerator_t *enumerator;
+
+ seg_env_attr = (tcg_seg_attr_seg_env_t*)attr;
+ base_attr_id = seg_env_attr->get_base_attr_id(seg_env_attr);
+ segment_data = seg_env_attr->get_segment(seg_env_attr, &flags);
+ *more = flags & SEG_ENV_FLAG_MORE;
+ *error = NULL;
+
+ enumerator = this->seg_envs->create_enumerator(this->seg_envs);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (current->get_base_attr_id(current) == base_attr_id)
+ {
+ seg_env = current;
+ this->seg_envs->remove_at(this->seg_envs, enumerator);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (flags & SEG_ENV_FLAG_START)
+ {
+ if (seg_env)
+ {
+ DBG1(DBG_TNC, "base attribute ID %d is already in use",
+ base_attr_id);
+ this->seg_envs->insert_last(this->seg_envs, seg_env);
+ return NULL;
+ }
+ DBG2(DBG_TNC, "received first segment for base attribute ID %d "
+ "(%d bytes)", base_attr_id, segment_data.len);
+ seg_env = seg_env_create_from_data(base_attr_id, segment_data,
+ this->max_seg_size, error);
+ if (!seg_env)
+ {
+ return NULL;
+ }
+ }
+ else
+ {
+ if (!seg_env)
+ {
+ DBG1(DBG_TNC, "base attribute ID %d not found", base_attr_id);
+ return NULL;
+ }
+ DBG2(DBG_TNC, "received %s segment for base attribute ID %d "
+ "(%d bytes)", (*more) ? "next" : "last", base_attr_id,
+ segment_data.len);
+ if (!seg_env->add_segment(seg_env, segment_data, error))
+ {
+ seg_env->destroy(seg_env);
+ return NULL;
+ }
+ }
+ base_attr = seg_env->get_base_attr(seg_env);
+
+ if (*more)
+ {
+ /* reinsert into list since more segments are to come */
+ this->seg_envs->insert_last(this->seg_envs, seg_env);
+ }
+ else
+ {
+ /* added the last segment */
+ if (!base_attr)
+ {
+ /* base attribute waits for more data */
+ DBG1(DBG_TNC, "insufficient bytes for PA-TNC attribute value");
+ msg_info = seg_env->get_base_attr_info(seg_env);
+ error_code = pen_type_create(PEN_IETF, PA_ERROR_INVALID_PARAMETER);
+ *error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
+ msg_info, PA_TNC_ATTR_INFO_SIZE);
+ }
+ seg_env->destroy(seg_env);
+ }
+ return base_attr;
+}
+
+METHOD(seg_contract_t, is_issuer, bool,
+ private_seg_contract_t *this)
+{
+ return this->is_issuer;
+}
+
+METHOD(seg_contract_t, is_null, bool,
+ private_seg_contract_t *this)
+{
+ return this->is_null;
+}
+
+METHOD(seg_contract_t, set_responder, void,
+ private_seg_contract_t *this, TNC_UInt32 responder_id)
+{
+ this->responder_id = responder_id;
+}
+
+METHOD(seg_contract_t, get_responder, TNC_UInt32,
+ private_seg_contract_t *this)
+{
+ return this->responder_id;
+}
+
+METHOD(seg_contract_t, get_issuer, TNC_UInt32,
+ private_seg_contract_t *this)
+{
+ return this->issuer_id;
+}
+
+METHOD(seg_contract_t, clone_, seg_contract_t*,
+ private_seg_contract_t *this)
+{
+ private_seg_contract_t *clone;
+
+ clone = malloc_thing(private_seg_contract_t);
+ memcpy(clone, this, sizeof(private_seg_contract_t));
+ clone->seg_envs = linked_list_create();
+
+ return &clone->public;
+}
+
+METHOD(seg_contract_t, get_info_string, void,
+ private_seg_contract_t *this, char *buf, size_t len, bool request)
+{
+ enum_name_t *pa_subtype_names;
+ uint32_t msg_vid, msg_subtype;
+ char *pos = buf;
+ int written;
+
+ /* nul-terminate the string buffer */
+ buf[--len] = '\0';
+
+ if (this->is_issuer && request)
+ {
+ written = snprintf(pos, len, "%s %d requests",
+ this->is_imc ? "IMC" : "IMV", this->issuer_id);
+ }
+ else
+ {
+ written = snprintf(pos, len, "%s %d received",
+ this->is_imc ? "IMC" : "IMV",
+ this->is_issuer ? this->issuer_id :
+ this->responder_id);
+ }
+ if (written < 0 || written > len)
+ {
+ return;
+ }
+ pos += written;
+ len -= written;
+
+ written = snprintf(pos, len, " a %ssegmentation contract%s ",
+ this->is_null ? "null" : "", request ?
+ (this->is_issuer ? "" : " request") : " response");
+ if (written < 0 || written > len)
+ {
+ return;
+ }
+ pos += written;
+ len -= written;
+
+ if ((!this->is_issuer && this->issuer_id != TNC_IMVID_ANY) ||
+ ( this->is_issuer && this->responder_id != TNC_IMVID_ANY))
+ {
+ written = snprintf(pos, len, "from %s %d ",
+ this->is_imc ? "IMV" : "IMC",
+ this->is_issuer ? this->responder_id :
+ this->issuer_id);
+ if (written < 0 || written > len)
+ {
+ return;
+ }
+ pos += written;
+ len -= written;
+ }
+
+ msg_vid = this->msg_type.vendor_id;
+ msg_subtype = this->msg_type.type;
+ pa_subtype_names = get_pa_subtype_names(msg_vid);
+ if (pa_subtype_names)
+ {
+ written = snprintf(pos, len, "for PA message type '%N/%N' "
+ "0x%06x/0x%08x", pen_names, msg_vid,
+ pa_subtype_names, msg_subtype, msg_vid,
+ msg_subtype);
+ }
+ else
+ {
+ written = snprintf(pos, len, "for PA message type '%N' "
+ "0x%06x/0x%08x", pen_names, msg_vid,
+ msg_vid, msg_subtype);
+ }
+ if (written < 0 || written > len)
+ {
+ return;
+ }
+ pos += written;
+ len -= written;
+
+ if (!this->is_null)
+ {
+ written = snprintf(pos, len, "\n maximum attribute size of %u bytes "
+ "with ", this->max_attr_size);
+ if (written < 0 || written > len)
+ {
+ return;
+ }
+ pos += written;
+ len -= written;
+
+ if (this->max_seg_size == SEG_CONTRACT_MAX_SIZE_VALUE)
+ {
+ written = snprintf(pos, len, "no segmentation");
+ }
+ else
+ {
+ written = snprintf(pos, len, "maximum segment size of %u bytes",
+ this->max_seg_size);
+ }
+ }
+}
+
+METHOD(seg_contract_t, destroy, void,
+ private_seg_contract_t *this)
+{
+ this->seg_envs->destroy_offset(this->seg_envs, offsetof(seg_env_t, destroy));
+ free(this);
+}
+
+/**
+ * See header
+ */
+seg_contract_t *seg_contract_create(pen_type_t msg_type,
+ uint32_t max_attr_size,
+ uint32_t max_seg_size,
+ bool is_issuer, TNC_UInt32 issuer_id,
+ bool is_imc)
+{
+ private_seg_contract_t *this;
+
+ INIT(this,
+ .public = {
+ .get_msg_type = _get_msg_type,
+ .set_max_size = _set_max_size,
+ .get_max_size = _get_max_size,
+ .check_size = _check_size,
+ .first_segment = _first_segment,
+ .next_segment = _next_segment,
+ .add_segment = _add_segment,
+ .is_issuer = _is_issuer,
+ .is_null = _is_null,
+ .set_responder = _set_responder,
+ .get_responder = _get_responder,
+ .get_issuer = _get_issuer,
+ .clone = _clone_,
+ .get_info_string = _get_info_string,
+ .destroy = _destroy,
+ },
+ .msg_type = msg_type,
+ .max_attr_size = max_attr_size,
+ .max_seg_size = max_seg_size,
+ .seg_envs = linked_list_create(),
+ .is_issuer = is_issuer,
+ .issuer_id = issuer_id,
+ .responder_id = is_imc ? TNC_IMVID_ANY : TNC_IMCID_ANY,
+ .is_imc = is_imc,
+ .is_null = max_attr_size == SEG_CONTRACT_MAX_SIZE_VALUE &&
+ max_seg_size == SEG_CONTRACT_MAX_SIZE_VALUE,
+ );
+
+ return &this->public;
+}
+
diff --git a/src/libimcv/seg/seg_contract.h b/src/libimcv/seg/seg_contract.h
new file mode 100644
index 000000000..23676a9f4
--- /dev/null
+++ b/src/libimcv/seg/seg_contract.h
@@ -0,0 +1,180 @@
+/*
+ * 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 seg_contract seg_contract
+ * @{ @ingroup libimcv_seg
+ */
+
+#ifndef SEG_CONTRACT_H_
+#define SEG_CONTRACT_H_
+
+typedef struct seg_contract_t seg_contract_t;
+
+#include "pa_tnc/pa_tnc_attr.h"
+
+#include <library.h>
+#include <pen/pen.h>
+
+#include <tncif.h>
+
+#define SEG_CONTRACT_MAX_SIZE_VALUE 0xffffffff
+#define SEG_CONTRACT_NO_FRAGMENTATION SEG_CONTRACT_MAX_SIZE_VALUE
+
+/**
+ * Interface for a PA-TNC attribute segmentation contract
+ *
+ */
+struct seg_contract_t {
+
+ /**
+ * Get the PA-TNC message type.
+ *
+ * @return PA-TNC Message type
+ */
+ pen_type_t (*get_msg_type)(seg_contract_t *this);
+
+ /**
+ * Set maximum PA-TNC attribute and segment size in octets
+ *
+ * @param max_attr_size Maximum PA-TNC attribute size in octets
+ * @param max_seg_size Maximum PA-TNC attribute segment size in octets
+ */
+ void (*set_max_size)(seg_contract_t *this, uint32_t max_attr_size,
+ uint32_t max_seg_size);
+
+ /**
+ * Get maximum PA-TNC attribute and segment size in octets
+ *
+ * @param max_attr_size Maximum PA-TNC attribute size in octets
+ * @param max_seg_size Maximum PA-TNC attribute segment size in octets
+ */
+ void (*get_max_size)(seg_contract_t *this, uint32_t *max_attr_size,
+ uint32_t *max_seg_size);
+
+ /**
+ * Check if a PA-TNC attribute must be segmented or is oversized
+ *
+ * @param attr PA-TNC attribute to be checked
+ * @param oversize PA-TNC attribute is larger than maximum size
+ * @return TRUE if PA-TNC attribute must be segmented
+ */
+ bool (*check_size)(seg_contract_t *this, pa_tnc_attr_t *attr,
+ bool *oversize);
+
+ /**
+ * Generate first segment of a PA-TNC attribute according to the contract
+ *
+ * @param attr PA-TNC attribute to be segmented
+ * @return First segment envelope attribute
+ */
+ pa_tnc_attr_t* (*first_segment)(seg_contract_t *this, pa_tnc_attr_t *attr);
+
+ /**
+ * Generate next segment of a PA-TNC attribute according to the contract
+ *
+ * @param base_attr_id Base Attribute ID
+ * @return Next segment envelope attribute
+ */
+ pa_tnc_attr_t* (*next_segment)(seg_contract_t *this, uint32_t base_attr_id);
+
+ /**
+ * Add an attribute segments until the PA-TNC attribute is reconstructed
+ *
+ * @param attr Segment envelope attribute
+ * @param error Error attribute if an error occurred or NULL
+ * @param more Need more segments
+ * @return Completed PA-TNC attribute or NULL
+ */
+ pa_tnc_attr_t* (*add_segment)(seg_contract_t *this,
+ pa_tnc_attr_t *attr, pa_tnc_attr_t **error,
+ bool *more);
+
+ /**
+ * Get contract role
+ *
+ * @return TRUE: contracting party (issuer),
+ * FALSE: contracted party
+ */
+ bool (*is_issuer)(seg_contract_t *this);
+
+ /**
+ * Is this a null contract ?
+ *
+ * @return TRUE if null contract
+ */
+ bool (*is_null)(seg_contract_t *this);
+
+ /**
+ * Set the responder ID
+ *
+ * @param responder IMC or IMV ID of responder
+ */
+ void (*set_responder)(seg_contract_t *this, TNC_UInt32 responder);
+
+ /**
+ * Get the responder ID
+ *
+ * @return IMC or IMV ID of responder
+ */
+ TNC_UInt32 (*get_responder)(seg_contract_t *this);
+
+ /**
+ * Get the issuer ID
+ *
+ * @return IMC or IMV ID of issuer
+ */
+ TNC_UInt32 (*get_issuer)(seg_contract_t *this);
+
+ /**
+ * Clone a contract
+ *
+ * @return Cloned contract
+ */
+ seg_contract_t* (*clone)(seg_contract_t *this);
+
+ /**
+ * Get an info string about the contract
+ *
+ * @param buf String buffer of at least size len
+ * @param len Size of string buffer
+ * @param request TRUE if contract request, FALSE if response
+ */
+ void (*get_info_string)(seg_contract_t *this, char *buf, size_t len,
+ bool request);
+
+ /**
+ * Destroys a seg_contract_t object.
+ */
+ void (*destroy)(seg_contract_t *this);
+};
+
+/**
+ * Create a PA-TNC attribute segmentation contract
+ *
+ * @param msg_type PA-TNC message type
+ * @param max_attr_size Maximum PA-TNC attribute size in octets
+ * @param max_seg_size Maximum PA-TNC attribute segment size in octets
+ * @param is_issuer TRUE if issuer of the contract
+ * @param issuer_id IMC or IMV ID of issuer
+ * @param is_imc TRUE if IMC, FALSE if IMV
+ */
+seg_contract_t* seg_contract_create(pen_type_t msg_type,
+ uint32_t max_attr_size,
+ uint32_t max_seg_size,
+ bool is_issuer, TNC_UInt32 issuer_id,
+ bool is_imc);
+
+#endif /** SEG_CONTRACT_H_ @}*/
diff --git a/src/libimcv/seg/seg_contract_manager.c b/src/libimcv/seg/seg_contract_manager.c
new file mode 100644
index 000000000..604c51134
--- /dev/null
+++ b/src/libimcv/seg/seg_contract_manager.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "seg_contract_manager.h"
+
+typedef struct private_seg_contract_manager_t private_seg_contract_manager_t;
+
+/**
+ * Private data of a seg_contract_manager_t object.
+ *
+ */
+struct private_seg_contract_manager_t {
+
+ /**
+ * Public seg_contract_manager_t interface.
+ */
+ seg_contract_manager_t public;
+
+ /**
+ * List of PA-TNC segmentation contracts
+ */
+ linked_list_t *contracts;
+
+};
+
+METHOD(seg_contract_manager_t, add_contract, void,
+ private_seg_contract_manager_t *this, seg_contract_t *contract)
+{
+ this->contracts->insert_last(this->contracts, contract);
+}
+
+METHOD(seg_contract_manager_t, get_contract, seg_contract_t*,
+ private_seg_contract_manager_t *this, pen_type_t msg_type, bool is_issuer,
+ TNC_UInt32 id)
+{
+ enumerator_t *enumerator;
+ seg_contract_t *contract, *found = NULL;
+
+ enumerator = this->contracts->create_enumerator(this->contracts);
+ while (enumerator->enumerate(enumerator, &contract))
+ {
+ if (contract->is_issuer(contract) == is_issuer &&
+ pen_type_equals(contract->get_msg_type(contract), msg_type) &&
+ id == (is_issuer ? contract->get_responder(contract) :
+ contract->get_issuer(contract)))
+ {
+ found = contract;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ return found;
+}
+
+METHOD(seg_contract_manager_t, destroy, void,
+ private_seg_contract_manager_t *this)
+{
+ this->contracts->destroy_offset(this->contracts,
+ offsetof(seg_contract_t, destroy));
+ free(this);
+}
+
+/**
+ * See header
+ */
+seg_contract_manager_t *seg_contract_manager_create(void)
+{
+ private_seg_contract_manager_t *this;
+
+ INIT(this,
+ .public = {
+ .add_contract = _add_contract,
+ .get_contract = _get_contract,
+ .destroy = _destroy,
+ },
+ .contracts = linked_list_create(),
+ );
+
+ return &this->public;
+}
+
diff --git a/src/libimcv/seg/seg_contract_manager.h b/src/libimcv/seg/seg_contract_manager.h
new file mode 100644
index 000000000..fa9d23c0f
--- /dev/null
+++ b/src/libimcv/seg/seg_contract_manager.h
@@ -0,0 +1,63 @@
+/*
+ * 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 seg_contract_manager seg_contract_manager
+ * @{ @ingroup libimcv_seg
+ */
+
+#ifndef SEG_CONTRACT_MANAGER_H_
+#define SEG_CONTRACT_MANAGER_H_
+
+typedef struct seg_contract_manager_t seg_contract_manager_t;
+
+#include "seg_contract.h"
+
+/**
+ * Interface for a PA-TNC attribute segmentation contract manager
+ *
+ */
+struct seg_contract_manager_t {
+
+ /**
+ * Add segmentation contract
+ *
+ * @param contract Segmentation contract to be added
+ */
+ void (*add_contract)(seg_contract_manager_t *this, seg_contract_t *contract);
+
+ /**
+ * Get segmentation contract
+ *
+ * @param msg_type PA-TNC message type governed by contract
+ * @param is_issuer If TRUE get only issuer contracts
+ * @param id Match either issuer or responder ID
+ */
+ seg_contract_t* (*get_contract)(seg_contract_manager_t *this,
+ pen_type_t msg_type, bool is_issuer,
+ TNC_UInt32 id);
+
+ /**
+ * Destroys a seg_contract_manager_t object.
+ */
+ void (*destroy)(seg_contract_manager_t *this);
+};
+
+/**
+ * Create a PA-TNC attribute segmentation contract manager
+ */
+seg_contract_manager_t* seg_contract_manager_create();
+
+#endif /** SEG_CONTRACT_MANAGER_H_ @}*/
diff --git a/src/libimcv/seg/seg_env.c b/src/libimcv/seg/seg_env.c
new file mode 100644
index 000000000..c47ce2934
--- /dev/null
+++ b/src/libimcv/seg/seg_env.c
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "seg_env.h"
+
+#include "imcv.h"
+#include "pa_tnc/pa_tnc_msg.h"
+#include "ietf/ietf_attr_pa_tnc_error.h"
+#include "tcg/seg/tcg_seg_attr_seg_env.h"
+
+#include <utils/debug.h>
+#include <bio/bio_reader.h>
+#include <bio/bio_writer.h>
+
+#define BASE_ATTR_ID_PREFIX 0xFF
+
+typedef struct private_seg_env_t private_seg_env_t;
+
+/**
+ * Private data of a seg_env_t object.
+ */
+struct private_seg_env_t {
+
+ /**
+ * Public seg_env_t interface.
+ */
+ seg_env_t public;
+
+ /**
+ * Base Attribute ID
+ */
+ uint32_t base_attr_id;
+
+ /**
+ * Base Attribute
+ */
+ pa_tnc_attr_t *base_attr;
+
+ /**
+ * Base Attribute Info to be used for PA-TNC error messages
+ */
+ u_char base_attr_info[8];
+
+ /**
+ * Base Attribute needs more segment data
+ */
+ bool need_more;
+
+ /**
+ * Pointer to remaining attribute data to be sent
+ */
+ chunk_t data;
+
+ /**
+ * Maximum PA-TNC attribute segment size
+ */
+ uint32_t max_seg_size;
+
+};
+
+METHOD(seg_env_t, get_base_attr_id, uint32_t,
+ private_seg_env_t *this)
+{
+ return this->base_attr_id;
+}
+
+METHOD(seg_env_t, get_base_attr, pa_tnc_attr_t*,
+ private_seg_env_t *this)
+{
+ return this->need_more ? NULL : this->base_attr->get_ref(this->base_attr);
+}
+
+METHOD(seg_env_t, get_base_attr_info, chunk_t,
+ private_seg_env_t *this)
+{
+ return chunk_create(this->base_attr_info, 8);
+}
+
+METHOD(seg_env_t, first_segment, pa_tnc_attr_t*,
+ private_seg_env_t *this)
+{
+ pa_tnc_attr_t *seg_env_attr;
+ bio_writer_t *writer;
+ pen_type_t type;
+ chunk_t segment_data, value;
+ uint8_t flags, seg_env_flags;
+
+ /* get components of base attribute header and data */
+ flags = this->base_attr->get_noskip_flag(this->base_attr) ?
+ PA_TNC_ATTR_FLAG_NOSKIP : PA_TNC_ATTR_FLAG_NONE;
+ type = this->base_attr->get_type(this->base_attr);
+
+ /* attribute data going into the first segment */
+ segment_data = this->data;
+ segment_data.len = this->max_seg_size - PA_TNC_ATTR_HEADER_SIZE;
+
+ /* build encoding of the base attribute header and first segment data */
+ writer = bio_writer_create(this->max_seg_size);
+ writer->write_uint8 (writer, flags);
+ writer->write_uint24(writer, type.vendor_id);
+ writer->write_uint32(writer, type.type);
+ writer->write_uint32(writer, PA_TNC_ATTR_HEADER_SIZE + this->data.len);
+ writer->write_data (writer, segment_data);
+ value = writer->extract_buf(writer);
+ writer->destroy(writer);
+ this->data = chunk_skip(this->data, segment_data.len);
+
+ DBG2(DBG_TNC, "creating first segment for base attribute ID %d (%d bytes)",
+ this->base_attr_id, this->max_seg_size);
+
+ seg_env_flags = SEG_ENV_FLAG_START | SEG_ENV_FLAG_MORE;
+ seg_env_attr = tcg_seg_attr_seg_env_create(value, seg_env_flags,
+ this->base_attr_id);
+ chunk_free(&value);
+
+ return seg_env_attr;
+}
+
+METHOD(seg_env_t, next_segment, pa_tnc_attr_t*,
+ private_seg_env_t *this, bool *last)
+{
+ pa_tnc_attr_t *seg_env_attr;
+ chunk_t segment_data;
+ uint8_t seg_env_flags;
+ bool is_last_segment;
+
+ if (this->data.len == 0)
+ {
+ /* no more attribute data to segment available */
+ return NULL;
+ }
+
+ /* attribute data going into the next segment */
+ segment_data = this->data;
+ segment_data.len = min(this->max_seg_size, this->data.len);
+ this->data = chunk_skip(this->data, segment_data.len);
+
+ is_last_segment = (this->data.len == 0);
+ if (last)
+ {
+ *last = is_last_segment;
+ }
+ DBG2(DBG_TNC, "creating %s segment for base attribute ID %d (%d bytes)",
+ is_last_segment ? "last" : "next", this->base_attr_id,
+ segment_data.len);
+
+ seg_env_flags = is_last_segment ? SEG_ENV_FLAG_NONE : SEG_ENV_FLAG_MORE;
+ seg_env_attr = tcg_seg_attr_seg_env_create(segment_data, seg_env_flags,
+ this->base_attr_id);
+
+ return seg_env_attr;
+}
+
+METHOD(seg_env_t, add_segment, bool,
+ private_seg_env_t *this, chunk_t segment, pa_tnc_attr_t **error)
+{
+ pen_type_t type, error_code;
+ uint32_t attr_offset;
+ chunk_t msg_info;
+ status_t status;
+
+ this->base_attr->add_segment(this->base_attr, segment);
+ status = this->base_attr->process(this->base_attr, &attr_offset);
+
+ if (status != SUCCESS && status != NEED_MORE)
+ {
+ type = this->base_attr->get_type(this->base_attr);
+ if (type.vendor_id == PEN_IETF && type.type == IETF_ATTR_PA_TNC_ERROR)
+ {
+ /* error while processing a PA-TNC error attribute - abort */
+ return FALSE;
+ }
+ error_code = pen_type_create(PEN_IETF, PA_ERROR_INVALID_PARAMETER);
+ msg_info = get_base_attr_info(this);
+ *error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
+ msg_info, PA_TNC_ATTR_HEADER_SIZE + attr_offset);
+ return FALSE;
+ }
+ this->need_more = (status == NEED_MORE);
+
+ return TRUE;
+}
+
+METHOD(seg_env_t, destroy, void,
+ private_seg_env_t *this)
+{
+ DESTROY_IF(this->base_attr);
+ free(this);
+}
+
+/**
+ * See header
+ */
+seg_env_t *seg_env_create(uint32_t base_attr_id, pa_tnc_attr_t *base_attr,
+ uint32_t max_seg_size)
+{
+ private_seg_env_t *this;
+ chunk_t value;
+
+ base_attr->build(base_attr);
+ value = base_attr->get_value(base_attr);
+
+ /**
+ * The PA-TNC attribute header must not be segmented and
+ * there must be at least a first and one next segment
+ */
+ if (max_seg_size < PA_TNC_ATTR_HEADER_SIZE ||
+ max_seg_size >= PA_TNC_ATTR_HEADER_SIZE + value.len)
+ {
+ return NULL;
+ }
+
+ INIT(this,
+ .public = {
+ .get_base_attr_id = _get_base_attr_id,
+ .get_base_attr = _get_base_attr,
+ .get_base_attr_info = _get_base_attr_info,
+ .first_segment = _first_segment,
+ .next_segment = _next_segment,
+ .add_segment = _add_segment,
+ .destroy = _destroy,
+ },
+ .base_attr_id = base_attr_id,
+ .base_attr = base_attr->get_ref(base_attr),
+ .max_seg_size = max_seg_size,
+ .data = base_attr->get_value(base_attr),
+ );
+
+ return &this->public;
+}
+
+/**
+ * See header
+ */
+seg_env_t *seg_env_create_from_data(uint32_t base_attr_id, chunk_t data,
+ uint32_t max_seg_size, pa_tnc_attr_t** error)
+{
+ private_seg_env_t *this;
+ pen_type_t type, error_code;
+ bio_reader_t *reader;
+ chunk_t msg_info;
+ uint32_t offset = 0, attr_offset;
+ status_t status;
+
+ INIT(this,
+ .public = {
+ .get_base_attr_id = _get_base_attr_id,
+ .get_base_attr = _get_base_attr,
+ .get_base_attr_info = _get_base_attr_info,
+ .first_segment = _first_segment,
+ .next_segment = _next_segment,
+ .add_segment = _add_segment,
+ .destroy = _destroy,
+ },
+ .base_attr_id = base_attr_id,
+ .max_seg_size = max_seg_size,
+ );
+
+ /* create info field to be used by PA-TNC error messages */
+ memset(this->base_attr_info, 0xff, 4);
+ htoun32(this->base_attr_info + 4, base_attr_id);
+ msg_info = get_base_attr_info(this);
+
+ /* extract from base attribute segment from data */
+ reader = bio_reader_create(data);
+ this->base_attr = imcv_pa_tnc_attributes->create(imcv_pa_tnc_attributes,
+ reader, TRUE, &offset, msg_info, error);
+ reader->destroy(reader);
+
+ if (!this->base_attr)
+ {
+ destroy(this);
+ return NULL;
+ }
+ status = this->base_attr->process(this->base_attr, &attr_offset);
+
+ if (status != SUCCESS && status != NEED_MORE)
+ {
+ type = this->base_attr->get_type(this->base_attr);
+ if (!(type.vendor_id == PEN_IETF &&
+ type.type == IETF_ATTR_PA_TNC_ERROR))
+ {
+ error_code = pen_type_create(PEN_IETF, PA_ERROR_INVALID_PARAMETER);
+ *error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
+ msg_info, PA_TNC_ATTR_HEADER_SIZE + attr_offset);
+ }
+ destroy(this);
+ return NULL;
+ }
+ this->need_more = (status == NEED_MORE);
+
+ return &this->public;
+}
+
diff --git a/src/libimcv/seg/seg_env.h b/src/libimcv/seg/seg_env.h
new file mode 100644
index 000000000..08d33d752
--- /dev/null
+++ b/src/libimcv/seg/seg_env.h
@@ -0,0 +1,119 @@
+/*
+ * 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 seg_env seg_env
+ * @{ @ingroup libimcv_seg
+ */
+
+#ifndef SEG_ENV_H_
+#define SEG_ENV_H_
+
+typedef struct seg_env_t seg_env_t;
+typedef enum seg_env_flags_t seg_env_flags_t;
+
+#include <library.h>
+
+#include <pa_tnc/pa_tnc_attr.h>
+
+/**
+ * Segment Envelope flags
+ */
+enum seg_env_flags_t {
+ SEG_ENV_FLAG_NONE = 0,
+ SEG_ENV_FLAG_MORE = (1<<7),
+ SEG_ENV_FLAG_START = (1<<6)
+};
+
+/**
+ * Interface for a PA-TNC attribute segment envelope object
+ */
+struct seg_env_t {
+
+ /**
+ * Get Base Attribute ID
+ *
+ * @return Base Attribute ID
+ */
+ uint32_t (*get_base_attr_id)(seg_env_t *this);
+
+ /**
+ * Get Base Attribute if it contains processed [incremental] data
+ *
+ * @return Base Attribute (must be destroyed) or NULL
+ */
+ pa_tnc_attr_t* (*get_base_attr)(seg_env_t *this);
+
+ /**
+ * Base Attribute Info to be used by PA-TNC error messages
+ *
+ * @return Message info string
+ */
+ chunk_t (*get_base_attr_info)(seg_env_t *this);
+
+ /**
+ * Generate the first segment envelope of the base attribute
+ *
+ * @return First attribute segment envelope
+ */
+ pa_tnc_attr_t* (*first_segment)(seg_env_t *this);
+
+ /**
+ * Generate the next segment envelope of the base attribute
+ *
+ * @param last TRUE if last segment
+ * @return Next attribute segment envelope
+ */
+ pa_tnc_attr_t* (*next_segment)(seg_env_t *this, bool *last);
+
+ /**
+ * Generate the first segment envelope of the base attribute
+ *
+ * @param segment Attribute segment to be added
+ * @param error Error attribute if a parsing error occurred
+ * return TRUE if segment was successfully added
+ */
+ bool (*add_segment)(seg_env_t *this, chunk_t segment,
+ pa_tnc_attr_t** error);
+
+ /**
+ * Destroys a seg_env_t object.
+ */
+ void (*destroy)(seg_env_t *this);
+};
+
+/**
+ * Create a PA-TNC attribute segment envelope object
+ *
+ * @param base_attr_id Base Attribute ID
+ * @param base_attr Base Attribute to be segmented
+ * @param max_seg_size Maximum segment size
+ */
+seg_env_t* seg_env_create(uint32_t base_attr_id, pa_tnc_attr_t *base_attr,
+ uint32_t max_seg_size);
+
+/**
+ * Create a PA-TNC attribute segment envelope object
+ *
+ * @param base_attr_id Base Attribute ID
+ * @param data First attribute segment
+ * @param max_seg_size Maximum segment size
+ * @param error Error attribute if a parsing error occurred
+ */
+seg_env_t* seg_env_create_from_data(uint32_t base_attr_id, chunk_t data,
+ uint32_t max_seg_size,
+ pa_tnc_attr_t** error);
+
+#endif /** SEG_ENV_H_ @}*/
diff --git a/src/libimcv/suites/test_imcv_seg.c b/src/libimcv/suites/test_imcv_seg.c
new file mode 100644
index 000000000..469b1110d
--- /dev/null
+++ b/src/libimcv/suites/test_imcv_seg.c
@@ -0,0 +1,738 @@
+/*
+ * Copyright (C) 2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "test_suite.h"
+
+#include <imcv.h>
+#include <pa_tnc/pa_tnc_attr.h>
+#include <seg/seg_env.h>
+#include <seg/seg_contract.h>
+#include <seg/seg_contract_manager.h>
+#include <ietf/ietf_attr_pa_tnc_error.h>
+#include <ita/ita_attr.h>
+#include <ita/ita_attr_command.h>
+#include <ita/ita_attr_dummy.h>
+#include <tcg/seg/tcg_seg_attr_seg_env.h>
+
+#include <tncif_pa_subtypes.h>
+
+static struct {
+ uint32_t max_seg_size, next_segs, last_seg_size;
+} seg_env_tests[] = {
+ { 0, 0, 0 },
+ { 11, 0, 0 },
+ { 12, 3, 12 },
+ { 13, 3, 9 },
+ { 15, 3, 3 },
+ { 16, 2, 16 },
+ { 17, 2, 14 },
+ { 23, 2, 2 },
+ { 24, 1, 24 },
+ { 25, 1, 23 },
+ { 47, 1, 1 },
+ { 48, 0, 0 },
+};
+
+static char command[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+static uint32_t id = 0x123456;
+
+START_TEST(test_imcv_seg_env)
+{
+ pa_tnc_attr_t *attr, *attr1, *base_attr, *base_attr1, *error;
+ tcg_seg_attr_seg_env_t *seg_env_attr;
+ ita_attr_command_t *ita_attr;
+ seg_env_t *seg_env, *seg_env1;
+ pen_type_t type;
+ uint32_t base_attr_id, max_seg_size, last_seg_size, seg_size, offset;
+ uint8_t flags;
+ bool last, last_seg;
+ chunk_t value, segment, seg;
+ int n;
+
+ libimcv_init(FALSE);
+ max_seg_size = seg_env_tests[_i].max_seg_size;
+ last_seg_size = seg_env_tests[_i].last_seg_size;
+ base_attr = ita_attr_command_create(command);
+ base_attr->build(base_attr);
+
+ seg_env = seg_env_create(id, base_attr, max_seg_size);
+ if (seg_env_tests[_i].next_segs == 0)
+ {
+ ck_assert(seg_env == NULL);
+ }
+ else
+ {
+ ck_assert(seg_env->get_base_attr_id(seg_env) == id);
+ base_attr1 = seg_env->get_base_attr(seg_env);
+ ck_assert(base_attr == base_attr1);
+ base_attr1->destroy(base_attr1);
+
+ for (n = 0; n <= seg_env_tests[_i].next_segs; n++)
+ {
+ last_seg = (n == seg_env_tests[_i].next_segs);
+ seg_size = (last_seg) ? last_seg_size : max_seg_size;
+ if (n == 0)
+ {
+ /* create first segment */
+ attr = seg_env->first_segment(seg_env);
+
+ seg_env_attr = (tcg_seg_attr_seg_env_t*)attr;
+ segment = seg_env_attr->get_segment(seg_env_attr, &flags);
+ if (max_seg_size > 12)
+ {
+ seg = chunk_create(command, seg_size - 12);
+ ck_assert(chunk_equals(seg, chunk_skip(segment, 12)));
+ }
+ ck_assert(flags == (SEG_ENV_FLAG_MORE | SEG_ENV_FLAG_START));
+ }
+ else
+ {
+ /* create next segments */
+ attr = seg_env->next_segment(seg_env, &last);
+ ck_assert(last == last_seg);
+
+ seg_env_attr = (tcg_seg_attr_seg_env_t*)attr;
+ segment = seg_env_attr->get_segment(seg_env_attr, &flags);
+ seg = chunk_create(command + n * max_seg_size - 12, seg_size);
+ ck_assert(chunk_equals(seg, segment));
+ ck_assert(flags == last_seg ? SEG_ENV_FLAG_NONE :
+ SEG_ENV_FLAG_MORE);
+ }
+
+ /* check built segment envelope attribute */
+ value = attr->get_value(attr);
+ ck_assert(value.len == 4 + seg_size);
+ ck_assert(segment.len == seg_size);
+ ck_assert(seg_env_attr->get_base_attr_id(seg_env_attr) == id);
+
+ /* create parse segment envelope attribute from data */
+ attr1 = tcg_seg_attr_seg_env_create_from_data(value.len, value);
+ ck_assert(attr1->process(attr1, &offset) == SUCCESS);
+ attr->destroy(attr);
+
+ seg_env_attr = (tcg_seg_attr_seg_env_t*)attr1;
+ segment = seg_env_attr->get_segment(seg_env_attr, &flags);
+ base_attr_id = seg_env_attr->get_base_attr_id(seg_env_attr);
+ ck_assert(base_attr_id == id);
+
+ /* create and update seg_env object on the receiving side */
+ if (n == 0)
+ {
+ ck_assert(flags == (SEG_ENV_FLAG_MORE | SEG_ENV_FLAG_START));
+ seg_env1 = seg_env_create_from_data(base_attr_id, segment,
+ max_seg_size, &error);
+ }
+ else
+ {
+ ck_assert(flags == last_seg ? SEG_ENV_FLAG_NONE :
+ SEG_ENV_FLAG_MORE);
+ seg_env1->add_segment(seg_env1, segment, &error);
+ }
+ attr1->destroy(attr1);
+ }
+
+ /* check reconstructed base attribute */
+ base_attr1 = seg_env1->get_base_attr(seg_env1);
+ ck_assert(base_attr1);
+ type = base_attr1->get_type(base_attr1);
+ ck_assert(type.vendor_id == PEN_ITA);
+ ck_assert(type.type == ITA_ATTR_COMMAND);
+ ita_attr = (ita_attr_command_t*)base_attr1;
+ ck_assert(streq(ita_attr->get_command(ita_attr), command));
+
+ seg_env->destroy(seg_env);
+ seg_env1->destroy(seg_env1);
+ base_attr1->destroy(base_attr1);
+ }
+ base_attr->destroy(base_attr);
+ libimcv_deinit();
+}
+END_TEST
+
+START_TEST(test_imcv_seg_env_special)
+{
+ pa_tnc_attr_t *attr, *attr1, *base_attr;
+ tcg_seg_attr_seg_env_t *seg_env_attr;
+ pen_type_t type;
+ seg_env_t *seg_env;
+ chunk_t segment, value;
+ uint32_t max_seg_size = 47;
+ uint32_t last_seg_size = 1;
+ uint32_t offset = 12;
+
+ base_attr = ita_attr_command_create(command);
+ base_attr->build(base_attr);
+
+ /* set noskip flag in base attribute */
+ base_attr->set_noskip_flag(base_attr, TRUE);
+
+ seg_env = seg_env_create(id, base_attr, max_seg_size);
+ attr = seg_env->first_segment(seg_env);
+ attr->destroy(attr);
+
+ /* don't return last segment indicator */
+ attr = seg_env->next_segment(seg_env, NULL);
+
+ /* build attribute */
+ attr->build(attr);
+
+ /* don't return flags */
+ seg_env_attr = (tcg_seg_attr_seg_env_t*)attr;
+ segment = seg_env_attr->get_segment(seg_env_attr, NULL);
+ ck_assert(segment.len == last_seg_size);
+
+ /* get segment envelope attribute reference and destroy it */
+ attr1 = attr->get_ref(attr);
+ attr1->destroy(attr1);
+
+ /* check some standard methods */
+ type = attr->get_type(attr);
+ ck_assert(type.vendor_id == PEN_TCG);
+ ck_assert(type.type == TCG_SEG_ATTR_SEG_ENV);
+ ck_assert(attr->get_noskip_flag(attr) == FALSE);
+ attr->set_noskip_flag(attr, TRUE);
+ ck_assert(attr->get_noskip_flag(attr) == TRUE);
+
+ /* request next segment which does not exist */
+ ck_assert(seg_env->next_segment(seg_env, NULL) == NULL);
+
+ /* create and parse a too short segment envelope attribute */
+ attr1 = tcg_seg_attr_seg_env_create_from_data(0, chunk_empty);
+ ck_assert(attr1->process(attr1, &offset) == FAILED);
+ ck_assert(offset == 0);
+ attr1->destroy(attr1);
+
+ /* create and parse correct segment envelope attribute */
+ value = attr->get_value(attr);
+ attr1 = tcg_seg_attr_seg_env_create_from_data(value.len, value);
+ ck_assert(attr1->process(attr1, &offset) == SUCCESS);
+ type = attr1->get_type(attr1);
+ ck_assert(type.vendor_id == PEN_TCG);
+ ck_assert(type.type == TCG_SEG_ATTR_SEG_ENV);
+ attr1->destroy(attr1);
+
+ /* cleanup */
+ attr->destroy(attr);
+ seg_env->destroy(seg_env);
+ base_attr->destroy(base_attr);
+}
+END_TEST
+
+static struct {
+ pa_tnc_error_code_t error_code;
+ chunk_t segment;
+} env_invalid_tests[] = {
+ { PA_ERROR_INVALID_PARAMETER, { NULL, 0 } },
+ { PA_ERROR_INVALID_PARAMETER, chunk_from_chars(
+ 0x00, 0xff, 0xff, 0xf0, 0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x0a)
+ },
+ { PA_ERROR_INVALID_PARAMETER, chunk_from_chars(
+ 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c)
+ },
+ { PA_ERROR_INVALID_PARAMETER, chunk_from_chars(
+ 0x00, 0x00, 0x90, 0x2a, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x0c)
+ },
+ { PA_ERROR_ATTR_TYPE_NOT_SUPPORTED, chunk_from_chars(
+ 0x80, 0x00, 0x90, 0x2a, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x0c)
+ },
+ { PA_ERROR_RESERVED, chunk_from_chars(
+ 0x00, 0x00, 0x90, 0x2a, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x0c)
+ },
+ { PA_ERROR_RESERVED, chunk_from_chars(
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0c)
+ },
+ { PA_ERROR_INVALID_PARAMETER, chunk_from_chars(
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c)
+ }
+};
+
+START_TEST(test_imcv_seg_env_invalid)
+{
+ seg_env_t *seg_env;
+ pen_type_t error_code;
+ pa_tnc_attr_t*error;
+ ietf_attr_pa_tnc_error_t *error_attr;
+
+ libimcv_init(FALSE);
+ seg_env = seg_env_create_from_data(id, env_invalid_tests[_i].segment, 20,
+ &error);
+ ck_assert(seg_env == NULL);
+ if (env_invalid_tests[_i].error_code == PA_ERROR_RESERVED)
+ {
+ ck_assert(error == NULL);
+ }
+ else
+ {
+ ck_assert(error);
+ error->build(error);
+ error_attr = (ietf_attr_pa_tnc_error_t*)error;
+ error_code = error_attr->get_error_code(error_attr);
+ ck_assert(error_code.vendor_id == PEN_IETF);
+ ck_assert(error_code.type == env_invalid_tests[_i].error_code);
+ error->destroy(error);
+ }
+ libimcv_deinit();
+}
+END_TEST
+
+START_TEST(test_imcv_seg_contract)
+{
+ seg_contract_t *contract_i, *contract_r;
+ tcg_seg_attr_seg_env_t *seg_env_attr;
+ ita_attr_command_t *ita_attr;
+ pa_tnc_attr_t *attr, *base_attr_i, *base_attr_r, *error;
+ pen_type_t type, msg_type = { PEN_ITA, PA_SUBTYPE_ITA_TEST };
+ uint32_t max_seg_size, max_attr_size = 1000, issuer_id = 1;
+ uint32_t base_attr_id;
+ bool more;
+
+ libimcv_init(FALSE);
+ max_seg_size = seg_env_tests[_i].max_seg_size;
+ base_attr_r = ita_attr_command_create(command);
+ base_attr_r->build(base_attr_r);
+ contract_i = seg_contract_create(msg_type, max_attr_size, max_seg_size,
+ TRUE, issuer_id, FALSE);
+ contract_r = seg_contract_create(msg_type, max_attr_size, max_seg_size,
+ FALSE, issuer_id, TRUE);
+ attr = contract_r->first_segment(contract_r, base_attr_r);
+
+ if (seg_env_tests[_i].next_segs == 0)
+ {
+ ck_assert(attr == NULL);
+ }
+ else
+ {
+ ck_assert(attr);
+ seg_env_attr = (tcg_seg_attr_seg_env_t*)attr;
+ base_attr_id = seg_env_attr->get_base_attr_id(seg_env_attr);
+ ck_assert(base_attr_id == 1);
+ base_attr_i = contract_i->add_segment(contract_i, attr, &error, &more);
+ ck_assert(base_attr_i == NULL);
+ attr->destroy(attr);
+ ck_assert(more);
+ while (more)
+ {
+ attr = contract_r->next_segment(contract_r, base_attr_id);
+ ck_assert(attr);
+ seg_env_attr = (tcg_seg_attr_seg_env_t*)attr;
+ base_attr_id = seg_env_attr->get_base_attr_id(seg_env_attr);
+ ck_assert(base_attr_id == 1);
+ base_attr_i = contract_i->add_segment(contract_i, attr, &error,
+ &more);
+ attr->destroy(attr);
+ }
+ ck_assert(base_attr_i);
+ ck_assert(error == NULL);
+ type = base_attr_i->get_type(base_attr_i);
+ ck_assert(pen_type_equals(type, base_attr_r->get_type(base_attr_r)));
+ ita_attr = (ita_attr_command_t*)base_attr_i;
+ ck_assert(streq(ita_attr->get_command(ita_attr), command));
+ base_attr_i->destroy(base_attr_i);
+ }
+ contract_i->destroy(contract_i);
+ contract_r->destroy(contract_r);
+ base_attr_r->destroy(base_attr_r);
+ libimcv_deinit();
+}
+END_TEST
+
+START_TEST(test_imcv_seg_contract_special)
+{
+ seg_contract_t *contract_i, *contract_r;
+ tcg_seg_attr_seg_env_t *seg_env_attr1, *seg_env_attr2;
+ ita_attr_command_t *ita_attr;
+ pa_tnc_attr_t *base_attr1_i, *base_attr2_i, *base_attr1_r, *base_attr2_r;
+ pa_tnc_attr_t *attr1_f, *attr2_f, *attr1_n, *attr2_n, *attr3, *error;
+ pen_type_t type, msg_type = { PEN_ITA, PA_SUBTYPE_ITA_TEST };
+ uint32_t max_seg_size, max_attr_size, issuer_id = 1;
+ uint32_t base_attr1_id, base_attr2_id;
+ char info[512];
+ bool oversize, more;
+
+ libimcv_init(FALSE);
+
+ /* create two base attributes to be segmented */
+ base_attr1_r = ita_attr_command_create(command);
+ base_attr2_r = ita_attr_dummy_create(129);
+ base_attr1_r->build(base_attr1_r);
+ base_attr2_r->build(base_attr2_r);
+
+ /* create an issuer contract*/
+ contract_i = seg_contract_create(msg_type, 1000, 47,
+ TRUE, issuer_id, FALSE);
+ ck_assert(pen_type_equals(contract_i->get_msg_type(contract_i), msg_type));
+ ck_assert(contract_i->is_issuer(contract_i));
+ ck_assert(!contract_i->is_null(contract_i));
+
+ /* set null contract */
+ contract_i->set_max_size(contract_i, SEG_CONTRACT_MAX_SIZE_VALUE,
+ SEG_CONTRACT_MAX_SIZE_VALUE);
+ ck_assert(contract_i->is_null(contract_i));
+
+ /* set and get maximum attribute and segment sizes */
+ contract_i->set_max_size(contract_i, 1000, 47);
+ contract_i->get_max_size(contract_i, NULL, NULL);
+ contract_i->get_max_size(contract_i, &max_attr_size, &max_seg_size);
+ contract_i->get_info_string(contract_i, info, sizeof(info), TRUE);
+ ck_assert(max_attr_size == 1000 && max_seg_size == 47);
+ ck_assert(!contract_i->is_null(contract_i));
+
+ /* create a null responder contract*/
+ contract_r = seg_contract_create(msg_type, SEG_CONTRACT_MAX_SIZE_VALUE,
+ SEG_CONTRACT_MAX_SIZE_VALUE,
+ FALSE, issuer_id, TRUE);
+ ck_assert(!contract_r->is_issuer(contract_r));
+ ck_assert(!contract_r->check_size(contract_r, base_attr2_r, &oversize));
+ ck_assert(!oversize);
+
+ /* allow no fragmentation */
+ contract_r->set_max_size(contract_r, 1000, SEG_CONTRACT_MAX_SIZE_VALUE);
+ ck_assert(!contract_r->is_null(contract_r));
+ ck_assert(!contract_r->check_size(contract_r, base_attr2_r, &oversize));
+ ck_assert(!oversize);
+
+ /* no maximum size limit and no fragmentation needed */
+ contract_r->set_max_size(contract_r, SEG_CONTRACT_MAX_SIZE_VALUE, 141);
+ ck_assert(!contract_r->is_null(contract_r));
+ ck_assert(!contract_r->check_size(contract_r, base_attr2_r, &oversize));
+ ck_assert(!oversize);
+
+ /* oversize base attribute */
+ contract_r->set_max_size(contract_r, 140, 47);
+ ck_assert(!contract_r->is_null(contract_r));
+ ck_assert(!contract_r->check_size(contract_r, base_attr2_r, &oversize));
+ ck_assert(oversize);
+
+ /* set final maximum attribute and segment sizes */
+ contract_r->set_max_size(contract_r, 141, 47);
+ contract_r->get_info_string(contract_r, info, sizeof(info), TRUE);
+ ck_assert(contract_r->check_size(contract_r, base_attr2_r, &oversize));
+ ck_assert(!oversize);
+
+ /* get first segment of each base attribute */
+ attr1_f = contract_r->first_segment(contract_r, base_attr1_r);
+ attr2_f = contract_r->first_segment(contract_r, base_attr2_r);
+ ck_assert(attr1_f);
+ ck_assert(attr2_f);
+ seg_env_attr1 = (tcg_seg_attr_seg_env_t*)attr1_f;
+ seg_env_attr2 = (tcg_seg_attr_seg_env_t*)attr2_f;
+ base_attr1_id = seg_env_attr1->get_base_attr_id(seg_env_attr1);
+ base_attr2_id = seg_env_attr2->get_base_attr_id(seg_env_attr2);
+ ck_assert(base_attr1_id == 1);
+ ck_assert(base_attr2_id == 2);
+
+ /* get second segment of each base attribute */
+ attr1_n = contract_r->next_segment(contract_r, 1);
+ attr2_n = contract_r->next_segment(contract_r, 2);
+ ck_assert(attr1_n);
+ ck_assert(attr2_n);
+
+ /* process first segment of first base attribute */
+ base_attr1_i = contract_i->add_segment(contract_i, attr1_f, &error, &more);
+ ck_assert(base_attr1_i == NULL);
+ ck_assert(error == NULL);
+ ck_assert(more);
+
+ /* reapply first segment of first base attribute */
+ base_attr1_i = contract_i->add_segment(contract_i, attr1_f, &error, &more);
+ ck_assert(base_attr1_i == NULL);
+ ck_assert(error == NULL);
+ ck_assert(more);
+
+ /* process stray second segment of second attribute */
+ base_attr2_i = contract_i->add_segment(contract_i, attr2_n, &error, &more);
+ ck_assert(base_attr2_i == NULL);
+ ck_assert(error == NULL);
+ ck_assert(more);
+
+ /* process first segment of second base attribute */
+ base_attr2_i = contract_i->add_segment(contract_i, attr2_f, &error, &more);
+ ck_assert(base_attr2_i == NULL);
+ ck_assert(error == NULL);
+ ck_assert(more);
+
+ /* try to get a segment of a non-existing base-attribute */
+ attr3 = contract_r->next_segment(contract_r, 3);
+ ck_assert(attr3 == NULL);
+
+ /* process second segment of first base attribute */
+ base_attr1_i = contract_i->add_segment(contract_i, attr1_n, &error, &more);
+ ck_assert(base_attr1_i);
+ ck_assert(error == NULL);
+ ck_assert(!more);
+
+ /* process second segment of second base attribute */
+ base_attr2_i = contract_i->add_segment(contract_i, attr2_n, &error, &more);
+ ck_assert(base_attr2_i == NULL);
+ ck_assert(error == NULL);
+ ck_assert(more);
+
+ /* destroy first and second segments */
+ attr1_f->destroy(attr1_f);
+ attr2_f->destroy(attr2_f);
+ attr1_n->destroy(attr1_n);
+ attr2_n->destroy(attr2_n);
+
+ /* request surplus segment of first base attribute */
+ attr1_n = contract_r->next_segment(contract_r, 1);
+ ck_assert(attr1_n == NULL);
+
+ /* get last segment of second base attribute */
+ attr2_n = contract_r->next_segment(contract_r, 2);
+ ck_assert(attr2_n);
+
+ /* process last segment of second base attribute */
+ base_attr2_i = contract_i->add_segment(contract_i, attr2_n, &error, &more);
+ attr2_n->destroy(attr2_n);
+ ck_assert(base_attr2_i);
+ ck_assert(error == NULL);
+ ck_assert(!more);
+
+ /* request surplus segment of second base attribute */
+ attr2_n = contract_r->next_segment(contract_r, 2);
+ ck_assert(attr2_n == NULL);
+
+ /* compare original with reconstructed base attributes */
+ type = base_attr1_i->get_type(base_attr1_i);
+ ck_assert(pen_type_equals(type, base_attr1_r->get_type(base_attr1_r)));
+ ita_attr = (ita_attr_command_t*)base_attr1_i;
+ ck_assert(streq(ita_attr->get_command(ita_attr), command));
+
+ type = base_attr2_i->get_type(base_attr2_i);
+ ck_assert(pen_type_equals(type, base_attr2_r->get_type(base_attr2_r)));
+ ck_assert(chunk_equals(base_attr2_i->get_value(base_attr2_i),
+ base_attr2_r->get_value(base_attr2_r)));
+
+ /* cleanup */
+ base_attr1_r->destroy(base_attr1_r);
+ base_attr2_r->destroy(base_attr2_r);
+ base_attr1_i->destroy(base_attr1_i);
+ base_attr2_i->destroy(base_attr2_i);
+ contract_i->destroy(contract_i);
+ contract_r->destroy(contract_r);
+ libimcv_deinit();
+}
+END_TEST
+
+static struct {
+ bool err_f;
+ chunk_t frag_f;
+ bool err_n;
+ bool base_attr;
+ chunk_t frag_n;
+} contract_invalid_tests[] = {
+ { FALSE, chunk_from_chars(
+ 0xc0, 0x00, 0x00, 0x01, 0x00, 0x00, 0x90, 0x2a, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x0d),
+ FALSE, TRUE, chunk_from_chars(
+ 0x00, 0x00, 0x00, 0x01, 0x01 )
+ },
+ { FALSE, chunk_from_chars(
+ 0xc0, 0x00, 0x00, 0x02, 0x00, 0x00, 0x90, 0x2a, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x0e),
+ TRUE, FALSE, chunk_from_chars(
+ 0x00, 0x00, 0x00, 0x02, 0x01 )
+ },
+ { TRUE, chunk_from_chars(
+ 0xc0, 0x00, 0x00, 0x03, 0x00, 0x00, 0x55, 0x97, 0x00, 0x00, 0x00, 0x23,
+ 0x00, 0x00, 0x00, 0x0d),
+ FALSE, FALSE, chunk_from_chars(
+ 0x00, 0x00, 0x00, 0x03, 0x01 )
+ },
+ { FALSE, chunk_from_chars(
+ 0xc0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+ 0x00, 0x00, 0x00, 0x14),
+ FALSE, FALSE, chunk_from_chars(
+ 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 )
+ },
+ { FALSE, chunk_from_chars(
+ 0xc0, 0x00, 0x00, 0x05, 0x00, 0x00, 0x90, 0x2a, 0x00, 0x00, 0x00, 0x03,
+ 0x00, 0x00, 0x00, 0x0f),
+ TRUE, FALSE, chunk_from_chars(
+ 0x00, 0x00, 0x00, 0x05, 0x00, 0x02, 0x01 )
+ },
+ { FALSE, chunk_from_chars(
+ 0xc0, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x00, 0x00, 0x00, 0x11),
+ TRUE, FALSE, chunk_from_chars(
+ 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0xff )
+ }
+};
+
+START_TEST(test_imcv_seg_contract_invalid)
+{
+ uint32_t max_seg_size = 12, max_attr_size = 100, issuer_id = 1;
+ pen_type_t msg_type = { PEN_ITA, PA_SUBTYPE_ITA_TEST };
+ pa_tnc_attr_t *attr_f, *attr_n, *base_attr, *error;
+ chunk_t value_f, value_n;
+ seg_contract_t *contract;
+ uint32_t offset;
+ bool more;
+
+ libimcv_init(FALSE);
+ value_f = contract_invalid_tests[_i].frag_f;
+ value_n = contract_invalid_tests[_i].frag_n;
+ attr_f = tcg_seg_attr_seg_env_create_from_data(value_f.len, value_f);
+ attr_n = tcg_seg_attr_seg_env_create_from_data(value_n.len, value_n);
+ ck_assert(attr_f->process(attr_f, &offset) == SUCCESS);
+ ck_assert(attr_n->process(attr_n, &offset) == SUCCESS);
+
+ contract = seg_contract_create(msg_type, max_attr_size, max_seg_size,
+ TRUE, issuer_id, FALSE);
+ base_attr = contract->add_segment(contract, attr_f, &error, &more);
+ ck_assert(base_attr == NULL);
+
+ if (contract_invalid_tests[_i].err_f)
+ {
+ ck_assert(error);
+ error->destroy(error);
+ }
+ else
+ {
+ ck_assert(error == NULL);
+ ck_assert(more);
+ base_attr = contract->add_segment(contract, attr_n, &error, &more);
+ if (contract_invalid_tests[_i].err_n)
+ {
+ ck_assert(error);
+ error->destroy(error);
+ }
+ else
+ {
+ ck_assert(error == NULL);
+ }
+ if (contract_invalid_tests[_i].base_attr)
+ {
+ ck_assert(base_attr);
+ base_attr->destroy(base_attr);
+ }
+ }
+
+ /* cleanup */
+ attr_f->destroy(attr_f);
+ attr_n->destroy(attr_n);
+ contract->destroy(contract);
+ libimcv_deinit();
+}
+END_TEST
+
+START_TEST(test_imcv_seg_contract_mgr)
+{
+ char buf[BUF_LEN];
+ uint32_t max_seg_size = 12, max_attr_size = 100;
+ pen_type_t msg_type1 = { PEN_ITA, PA_SUBTYPE_ITA_TEST };
+ pen_type_t msg_type2 = { PEN_IETF, PA_SUBTYPE_IETF_OPERATING_SYSTEM };
+ seg_contract_manager_t *contracts;
+ seg_contract_t *cx, *c1, *c2, *c3, *c4;
+
+ contracts = seg_contract_manager_create();
+
+ /* add contract template as issuer */
+ c1 = seg_contract_create(msg_type1, max_attr_size, max_seg_size,
+ TRUE, 1, FALSE);
+ c1->get_info_string(c1, buf, BUF_LEN, TRUE);
+
+ contracts->add_contract(contracts, c1);
+
+ /* received contract request for msg_type1 as responder */
+ cx = contracts->get_contract(contracts, msg_type1, FALSE, 2);
+ ck_assert(cx == NULL);
+
+ /* add directed contract as responder */
+ c2 = seg_contract_create(msg_type1, max_attr_size, max_seg_size,
+ FALSE, 2, FALSE);
+ c2->set_responder(c2, 1);
+ c2->get_info_string(c2, buf, BUF_LEN, TRUE);
+ contracts->add_contract(contracts, c2);
+
+ /* retrieve this contract */
+ cx = contracts->get_contract(contracts, msg_type1, FALSE, 2);
+ ck_assert(cx == c2);
+
+ /* received directed contract response as issuer */
+ cx = contracts->get_contract(contracts, msg_type1, TRUE, 3);
+ ck_assert(cx == NULL);
+
+ /* get contract template */
+ cx = contracts->get_contract(contracts, msg_type1, TRUE, TNC_IMCID_ANY);
+ ck_assert(cx == c1);
+
+ /* clone the contract template and as it as a directed contract */
+ c3 = cx->clone(cx);
+ c3->set_responder(c3, 3);
+ c3->get_info_string(c3, buf, BUF_LEN, FALSE);
+ contracts->add_contract(contracts, c3);
+
+ /* retrieve this contract */
+ cx = contracts->get_contract(contracts, msg_type1, TRUE, 3);
+ ck_assert(cx == c3);
+
+ /* received contract request for msg_type2 as responder */
+ cx = contracts->get_contract(contracts, msg_type2, FALSE, 2);
+ ck_assert(cx == NULL);
+
+ /* add directed contract as responder */
+ c4 = seg_contract_create(msg_type2, max_attr_size, max_seg_size,
+ FALSE, 2, FALSE);
+ c4->set_responder(c4, 1);
+ contracts->add_contract(contracts, c4);
+
+ /* retrieve this contract */
+ cx = contracts->get_contract(contracts, msg_type2, FALSE, 2);
+ ck_assert(cx == c4);
+
+ contracts->destroy(contracts);
+}
+END_TEST
+
+Suite *imcv_seg_suite_create()
+{
+ Suite *s;
+ TCase *tc;
+
+ s = suite_create("imcv_seg");
+
+ tc = tcase_create("env");
+ tcase_add_loop_test(tc, test_imcv_seg_env, 0, countof(seg_env_tests));
+ suite_add_tcase(s, tc);
+
+ tc = tcase_create("env_special");
+ tcase_add_test(tc, test_imcv_seg_env_special);
+ suite_add_tcase(s, tc);
+
+ tc = tcase_create("env_invalid");
+ tcase_add_loop_test(tc, test_imcv_seg_env_invalid, 0,
+ countof(env_invalid_tests));
+ suite_add_tcase(s, tc);
+
+ tc = tcase_create("contract");
+ tcase_add_loop_test(tc, test_imcv_seg_contract, 0, countof(seg_env_tests));
+ suite_add_tcase(s, tc);
+
+ tc = tcase_create("contract_special");
+ tcase_add_test(tc, test_imcv_seg_contract_special);
+ suite_add_tcase(s, tc);
+
+ tc = tcase_create("contract_invalid");
+ tcase_add_loop_test(tc, test_imcv_seg_contract_invalid, 0,
+ countof(contract_invalid_tests));
+ suite_add_tcase(s, tc);
+
+ tc = tcase_create("contract_mgr");
+ tcase_add_test(tc, test_imcv_seg_contract_mgr);
+ suite_add_tcase(s, tc);
+
+ return s;
+}
diff --git a/src/libimcv/swid/swid_error.c b/src/libimcv/swid/swid_error.c
new file mode 100644
index 000000000..7f3c34476
--- /dev/null
+++ b/src/libimcv/swid/swid_error.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "swid_error.h"
+
+#include <bio/bio_writer.h>
+#include <ietf/ietf_attr_pa_tnc_error.h>
+
+ENUM(swid_error_code_names, TCG_SWID_ERROR, TCG_SWID_RESPONSE_TOO_LARGE,
+ "SWID Error",
+ "SWID Subscription Denied",
+ "SWID Response Too Large"
+);
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t* swid_error_create(swid_error_code_t code, u_int32_t request_id,
+ u_int32_t max_attr_size, char *description)
+{
+ bio_writer_t *writer;
+ chunk_t msg_info;
+ pa_tnc_attr_t *attr;
+ pen_type_t error_code;
+
+ error_code = pen_type_create( PEN_TCG, code);
+ writer = bio_writer_create(4);
+ writer->write_uint32(writer, request_id);
+ if (code == TCG_SWID_RESPONSE_TOO_LARGE)
+ {
+ writer->write_uint32(writer, max_attr_size);
+ }
+ if (description)
+ {
+ writer->write_data(writer, chunk_from_str(description));
+ }
+ msg_info = writer->get_buf(writer);
+ attr = ietf_attr_pa_tnc_error_create(error_code, msg_info);
+ writer->destroy(writer);
+
+ return attr;
+}
+
diff --git a/src/libimcv/swid/swid_error.h b/src/libimcv/swid/swid_error.h
new file mode 100644
index 000000000..b459ba686
--- /dev/null
+++ b/src/libimcv/swid/swid_error.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2013 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup swid_error swid_error
+ * @{ @ingroup libimcv_swid
+ */
+
+#ifndef SWID_ERROR_H_
+#define SWID_ERROR_H_
+
+typedef enum swid_error_code_t swid_error_code_t;
+
+#include "pa_tnc/pa_tnc_attr.h"
+
+#include <library.h>
+
+
+/**
+ * SWID Error Codes
+ * see section 3.14.2 of PTS Protocol: Binding to TNC IF-M Specification
+ */
+enum swid_error_code_t {
+ TCG_SWID_ERROR = 0x20,
+ TCG_SWID_SUBSCRIPTION_DENIED = 0x21,
+ TCG_SWID_RESPONSE_TOO_LARGE = 0x22
+};
+
+/**
+ * enum name for swid_error_code_t.
+ */
+extern enum_name_t *swid_error_code_names;
+
+/**
+ * Creates a SWID Error Attribute
+ * see section 4.12 of TNC SWID Message and Attributes for IF-M
+ *
+ * @param code SWID error code
+ * @param request SWID request ID
+ * @param max_attr_size Maximum IF-M attribute size (if applicable)
+ * @param description Optional description string or NULL
+ */
+pa_tnc_attr_t* swid_error_create(swid_error_code_t code, u_int32_t request,
+ u_int32_t max_attr_size, char *description);
+
+#endif /** SWID_ERROR_H_ @}*/
diff --git a/src/libimcv/swid/swid_inventory.c b/src/libimcv/swid/swid_inventory.c
new file mode 100644
index 000000000..a49286954
--- /dev/null
+++ b/src/libimcv/swid/swid_inventory.c
@@ -0,0 +1,454 @@
+/*
+ * Copyright (C) 2013-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "swid_inventory.h"
+#include "swid_tag.h"
+#include "swid_tag_id.h"
+
+#include <collections/linked_list.h>
+#include <bio/bio_writer.h>
+#include <utils/debug.h>
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <libgen.h>
+#include <errno.h>
+
+typedef struct private_swid_inventory_t private_swid_inventory_t;
+
+/**
+ * Private data of a swid_inventory_t object.
+ *
+ */
+struct private_swid_inventory_t {
+
+ /**
+ * Public swid_inventory_t interface.
+ */
+ swid_inventory_t public;
+
+ /**
+ * Full SWID tags or just SWID tag IDs
+ */
+ bool full_tags;
+
+ /**
+ * List of SWID tags or tag IDs
+ */
+ linked_list_t *list;
+};
+
+/**
+ * Read SWID tags issued by the swid_generator tool
+ */
+static status_t read_swid_tags(private_swid_inventory_t *this, FILE *file)
+{
+ swid_tag_t *tag;
+ bio_writer_t *writer;
+ chunk_t tag_encoding, tag_file_path = chunk_empty;
+ bool more_tags = TRUE, last_newline;
+ char line[8192];
+ size_t len;
+
+ while (more_tags)
+ {
+ last_newline = TRUE;
+ writer = bio_writer_create(512);
+ while (TRUE)
+ {
+ if (!fgets(line, sizeof(line), file))
+ {
+ more_tags = FALSE;
+ break;
+ }
+ len = strlen(line);
+
+ if (last_newline && line[0] == '\n')
+ {
+ break;
+ }
+ else
+ {
+ last_newline = (line[len-1] == '\n');
+ writer->write_data(writer, chunk_create(line, len));
+ }
+ }
+
+ tag_encoding = writer->get_buf(writer);
+
+ if (tag_encoding.len > 1)
+ {
+ /* remove trailing newline if present */
+ if (tag_encoding.ptr[tag_encoding.len - 1] == '\n')
+ {
+ tag_encoding.len--;
+ }
+ DBG3(DBG_IMC, " %.*s", tag_encoding.len, tag_encoding.ptr);
+
+ tag = swid_tag_create(tag_encoding, tag_file_path);
+ this->list->insert_last(this->list, tag);
+ }
+ writer->destroy(writer);
+ }
+
+ return SUCCESS;
+}
+
+/**
+ * Read SWID tag or software IDs issued by the swid_generator tool
+ */
+static status_t read_swid_tag_ids(private_swid_inventory_t *this, FILE *file)
+{
+ swid_tag_id_t *tag_id;
+ chunk_t tag_creator, unique_sw_id, tag_file_path = chunk_empty;
+ char line[BUF_LEN];
+
+ while (TRUE)
+ {
+ char *separator;
+ size_t len;
+
+ if (!fgets(line, sizeof(line), file))
+ {
+ return SUCCESS;
+ }
+ len = strlen(line);
+
+ /* remove trailing newline if present */
+ if (len > 0 && line[len - 1] == '\n')
+ {
+ len--;
+ }
+ DBG3(DBG_IMC, " %.*s", len, line);
+
+ separator = strchr(line, '_');
+ if (!separator)
+ {
+ DBG1(DBG_IMC, "separation of regid from unique software ID failed");
+ return FAILED;
+ }
+ tag_creator = chunk_create(line, separator - line);
+ separator++;
+
+ unique_sw_id = chunk_create(separator, len - (separator - line));
+ tag_id = swid_tag_id_create(tag_creator, unique_sw_id, tag_file_path);
+ this->list->insert_last(this->list, tag_id);
+ }
+}
+
+static status_t generate_tags(private_swid_inventory_t *this, char *generator,
+ swid_inventory_t *targets, bool pretty, bool full)
+{
+ FILE *file;
+ char command[BUF_LEN];
+ char doc_separator[] = "'\n\n'";
+
+ status_t status = SUCCESS;
+
+ if (targets->get_count(targets) == 0)
+ {
+ /* Assemble the SWID generator command */
+ if (this->full_tags)
+ {
+ snprintf(command, BUF_LEN, "%s swid --doc-separator %s%s%s",
+ generator, doc_separator, pretty ? " --pretty" : "",
+ full ? " --full" : "");
+ }
+ else
+ {
+ snprintf(command, BUF_LEN, "%s software-id", generator);
+ }
+
+ /* Open a pipe stream for reading the SWID generator output */
+ file = popen(command, "r");
+ if (!file)
+ {
+ DBG1(DBG_IMC, "failed to run swid_generator command");
+ return NOT_SUPPORTED;
+ }
+
+ if (this->full_tags)
+ {
+ DBG2(DBG_IMC, "SWID tag generation by package manager");
+ status = read_swid_tags(this, file);
+ }
+ else
+ {
+ DBG2(DBG_IMC, "SWID tag ID generation by package manager");
+ status = read_swid_tag_ids(this, file);
+ }
+ pclose(file);
+ }
+ else if (this->full_tags)
+ {
+ swid_tag_id_t *tag_id;
+ enumerator_t *enumerator;
+
+ enumerator = targets->create_enumerator(targets);
+ while (enumerator->enumerate(enumerator, &tag_id))
+ {
+ char software_id[BUF_LEN];
+ chunk_t tag_creator, unique_sw_id;
+
+ tag_creator = tag_id->get_tag_creator(tag_id);
+ unique_sw_id = tag_id->get_unique_sw_id(tag_id, NULL);
+ snprintf(software_id, BUF_LEN, "%.*s_%.*s",
+ tag_creator.len, tag_creator.ptr,
+ unique_sw_id.len, unique_sw_id.ptr);
+
+ /* Assemble the SWID generator command */
+ snprintf(command, BUF_LEN, "%s swid --software-id %s%s%s",
+ generator, software_id, pretty ? " --pretty" : "",
+ full ? " --full" : "");
+
+ /* Open a pipe stream for reading the SWID generator output */
+ file = popen(command, "r");
+ if (!file)
+ {
+ DBG1(DBG_IMC, "failed to run swid_generator command");
+ return NOT_SUPPORTED;
+ }
+ status = read_swid_tags(this, file);
+ pclose(file);
+
+ if (status != SUCCESS)
+ {
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+
+ return status;
+}
+
+static bool collect_tags(private_swid_inventory_t *this, char *pathname,
+ swid_inventory_t *targets)
+{
+ char *rel_name, *abs_name;
+ struct stat st;
+ bool success = FALSE;
+ enumerator_t *enumerator;
+
+ enumerator = enumerator_create_directory(pathname);
+ if (!enumerator)
+ {
+ DBG1(DBG_IMC, "directory '%s' can not be opened, %s",
+ pathname, strerror(errno));
+ return FALSE;
+ }
+ DBG2(DBG_IMC, "entering %s", pathname);
+
+ while (enumerator->enumerate(enumerator, &rel_name, &abs_name, &st))
+ {
+ char * start, *stop;
+ chunk_t tag_creator;
+ chunk_t unique_sw_id = chunk_empty, tag_file_path = chunk_empty;
+
+ if (!strstr(rel_name, "regid."))
+ {
+ continue;
+ }
+ if (S_ISDIR(st.st_mode))
+ {
+ /* In case of a targeted request */
+ if (targets->get_count(targets))
+ {
+ enumerator_t *target_enumerator;
+ swid_tag_id_t *tag_id;
+ bool match = FALSE;
+
+ target_enumerator = targets->create_enumerator(targets);
+ while (target_enumerator->enumerate(target_enumerator, &tag_id))
+ {
+ if (chunk_equals(tag_id->get_tag_creator(tag_id),
+ chunk_from_str(rel_name)))
+ {
+ match = TRUE;
+ break;
+ }
+ }
+ target_enumerator->destroy(target_enumerator);
+
+ if (!match)
+ {
+ continue;
+ }
+ }
+
+ if (!collect_tags(this, abs_name, targets))
+ {
+ goto end;
+ }
+ continue;
+ }
+
+ /* parse the regid filename into its components */
+ start = rel_name;
+ stop = strchr(start, '_');
+ if (!stop)
+ {
+ DBG1(DBG_IMC, " %s", rel_name);
+ DBG1(DBG_IMC, " '_' separator not found");
+ goto end;
+ }
+ tag_creator = chunk_create(start, stop-start);
+ start = stop + 1;
+
+ stop = strstr(start, ".swidtag");
+ if (!stop)
+ {
+ DBG1(DBG_IMC, " %s", rel_name);
+ DBG1(DBG_IMC, " swidtag postfix not found");
+ goto end;
+ }
+ unique_sw_id = chunk_create(start, stop-start);
+ tag_file_path = chunk_from_str(abs_name);
+
+ /* In case of a targeted request */
+ if (targets->get_count(targets))
+ {
+ chunk_t target_unique_sw_id, target_tag_creator;
+ enumerator_t *target_enumerator;
+ swid_tag_id_t *tag_id;
+ bool match = FALSE;
+
+ target_enumerator = targets->create_enumerator(targets);
+ while (target_enumerator->enumerate(target_enumerator, &tag_id))
+ {
+ target_unique_sw_id = tag_id->get_unique_sw_id(tag_id, NULL);
+ target_tag_creator = tag_id->get_tag_creator(tag_id);
+
+ if (chunk_equals(target_unique_sw_id, unique_sw_id) &&
+ chunk_equals(target_tag_creator, tag_creator))
+ {
+ match = TRUE;
+ break;
+ }
+ }
+ target_enumerator->destroy(target_enumerator);
+
+ if (!match)
+ {
+ continue;
+ }
+ }
+ DBG2(DBG_IMC, " %s", rel_name);
+
+ if (this->full_tags)
+ {
+ swid_tag_t *tag;
+ chunk_t *xml_tag;
+
+ xml_tag = chunk_map(abs_name, FALSE);
+ if (!xml_tag)
+ {
+ DBG1(DBG_IMC, " opening '%s' failed: %s", abs_name,
+ strerror(errno));
+ goto end;
+ }
+
+ tag = swid_tag_create(*xml_tag, tag_file_path);
+ this->list->insert_last(this->list, tag);
+ chunk_unmap(xml_tag);
+ }
+ else
+ {
+ swid_tag_id_t *tag_id;
+
+ tag_id = swid_tag_id_create(tag_creator, unique_sw_id, tag_file_path);
+ this->list->insert_last(this->list, tag_id);
+ }
+ }
+ success = TRUE;
+
+end:
+ enumerator->destroy(enumerator);
+ DBG2(DBG_IMC, "leaving %s", pathname);
+
+ return success;
+}
+
+METHOD(swid_inventory_t, collect, bool,
+ private_swid_inventory_t *this, char *directory, char *generator,
+ swid_inventory_t *targets, bool pretty, bool full)
+{
+ /**
+ * Tags are generated by a package manager
+ */
+ generate_tags(this, generator, targets, pretty, full);
+
+ /**
+ * Collect swidtag files by iteratively entering all directories in
+ * the tree under the "directory" path.
+ */
+ return collect_tags(this, directory, targets);
+}
+
+METHOD(swid_inventory_t, add, void,
+ private_swid_inventory_t *this, void *item)
+{
+ this->list->insert_last(this->list, item);
+}
+
+METHOD(swid_inventory_t, get_count, int,
+ private_swid_inventory_t *this)
+{
+ return this->list->get_count(this->list);
+}
+
+METHOD(swid_inventory_t, create_enumerator, enumerator_t*,
+ private_swid_inventory_t *this)
+{
+ return this->list->create_enumerator(this->list);
+}
+
+METHOD(swid_inventory_t, destroy, void,
+ private_swid_inventory_t *this)
+{
+ if (this->full_tags)
+ {
+ this->list->destroy_offset(this->list, offsetof(swid_tag_t, destroy));
+ }
+ else
+ {
+ this->list->destroy_offset(this->list, offsetof(swid_tag_id_t, destroy));
+ }
+ free(this);
+}
+
+/**
+ * See header
+ */
+swid_inventory_t *swid_inventory_create(bool full_tags)
+{
+ private_swid_inventory_t *this;
+
+ INIT(this,
+ .public = {
+ .collect = _collect,
+ .add = _add,
+ .get_count = _get_count,
+ .create_enumerator = _create_enumerator,
+ .destroy = _destroy,
+ },
+ .full_tags = full_tags,
+ .list = linked_list_create(),
+ );
+
+ return &this->public;
+}
diff --git a/src/libimcv/swid/swid_inventory.h b/src/libimcv/swid/swid_inventory.h
new file mode 100644
index 000000000..04029070e
--- /dev/null
+++ b/src/libimcv/swid/swid_inventory.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2013-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup swid_inventory swid_inventory
+ * @{ @ingroup libimcv_swid
+ */
+
+#ifndef SWID_INVENTORY_H_
+#define SWID_INVENTORY_H_
+
+#include <library.h>
+
+/* Maximum size of a SWID Tag Inventory: 100 MB */
+#define SWID_MAX_ATTR_SIZE 100000000
+
+typedef struct swid_inventory_t swid_inventory_t;
+
+/**
+ * Class managing SWID tag inventory
+ */
+struct swid_inventory_t {
+
+ /**
+ * Collect the SWID tags stored on the endpoint
+ *
+ * @param directory SWID directory path
+ * @param generator Path to SWID generator
+ * @param targets List of target tag IDs
+ * @param pretty Generate indented XML SWID tags
+ * @param full Include file information in SWID tags
+ * @return TRUE if successful
+ */
+ bool (*collect)(swid_inventory_t *this, char *directory, char *generator,
+ swid_inventory_t *targets, bool pretty, bool full);
+
+ /**
+ * Collect the SWID tags stored on the endpoint
+ *
+ * @param item SWID tag or tag ID to be added
+ */
+ void (*add)(swid_inventory_t *this, void *item);
+
+ /**
+ * Get the number of collected SWID tags
+ *
+ * @return Number of collected SWID tags
+ */
+ int (*get_count)(swid_inventory_t *this);
+
+ /**
+ * Create a SWID tag inventory enumerator
+ *
+ * @return Enumerator returning either tag ID or full tag
+ */
+ enumerator_t* (*create_enumerator)(swid_inventory_t *this);
+
+ /**
+ * Destroys a swid_inventory_t object.
+ */
+ void (*destroy)(swid_inventory_t *this);
+
+};
+
+/**
+ * Creates a swid_inventory_t object
+ *
+ * @param full_tags TRUE if full tags, FALSE if tag IDs only
+ */
+swid_inventory_t* swid_inventory_create(bool full_tags);
+
+#endif /** SWID_INVENTORY_H_ @}*/
diff --git a/src/libimcv/swid/swid_tag.c b/src/libimcv/swid/swid_tag.c
new file mode 100644
index 000000000..c77c75700
--- /dev/null
+++ b/src/libimcv/swid/swid_tag.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2013-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "swid_tag.h"
+
+typedef struct private_swid_tag_t private_swid_tag_t;
+
+/**
+ * Private data of a swid_tag_t object.
+ *
+ */
+struct private_swid_tag_t {
+
+ /**
+ * Public swid_tag_t interface.
+ */
+ swid_tag_t public;
+
+ /**
+ * UTF-8 XML encoding of SWID tag
+ */
+ chunk_t encoding;
+
+ /**
+ * Optional Tag Identifier Instance ID
+ */
+ chunk_t instance_id;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+};
+
+METHOD(swid_tag_t, get_encoding, chunk_t,
+ private_swid_tag_t *this)
+{
+ return this->encoding;
+}
+
+METHOD(swid_tag_t, get_instance_id, chunk_t,
+ private_swid_tag_t *this)
+{
+ return this->instance_id;
+}
+
+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)
+{
+ if (ref_put(&this->ref))
+ {
+ free(this->encoding.ptr);
+ free(this->instance_id.ptr);
+ free(this);
+ }
+}
+
+/**
+ * See header
+ */
+swid_tag_t *swid_tag_create(chunk_t encoding, chunk_t instance_id)
+{
+ private_swid_tag_t *this;
+
+ INIT(this,
+ .public = {
+ .get_encoding = _get_encoding,
+ .get_instance_id = _get_instance_id,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .encoding = chunk_clone(encoding),
+ .ref = 1,
+ );
+
+ if (instance_id.len > 0)
+ {
+ this->instance_id = chunk_clone(instance_id);
+ }
+
+ return &this->public;
+}
+
diff --git a/src/libimcv/swid/swid_tag.h b/src/libimcv/swid/swid_tag.h
new file mode 100644
index 000000000..22c14b1aa
--- /dev/null
+++ b/src/libimcv/swid/swid_tag.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2013-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup swid_tag swid_tag
+ * @{ @ingroup libimcv_swid
+ */
+
+#ifndef SWID_TAG_H_
+#define SWID_TAG_H_
+
+#include <library.h>
+
+typedef struct swid_tag_t swid_tag_t;
+
+
+/**
+ * Class storing a SWID Tag
+ */
+struct swid_tag_t {
+
+ /**
+ * Get UTF-8 XML encoding of SWID tag
+ *
+ * @return XML encoding of SWID tag
+ */
+ chunk_t (*get_encoding)(swid_tag_t *this);
+
+ /**
+ * Get the optional Tag Identifier Instance ID
+ *
+ * @return Optional Tag Identifier Instance ID
+ */
+ chunk_t (*get_instance_id)(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.
+ */
+ void (*destroy)(swid_tag_t *this);
+
+};
+
+/**
+ * Creates a swid_tag_t object
+ *
+ * @param encoding XML encoding of SWID tag
+ * @param instance_id Tag Identifier Instance ID or empty chunk
+ */
+swid_tag_t* swid_tag_create(chunk_t encoding, chunk_t instance_id);
+
+#endif /** SWID_TAG_H_ @}*/
diff --git a/src/libimcv/swid/swid_tag_id.c b/src/libimcv/swid/swid_tag_id.c
new file mode 100644
index 000000000..2dc6e3141
--- /dev/null
+++ b/src/libimcv/swid/swid_tag_id.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2013-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "swid_tag_id.h"
+
+typedef struct private_swid_tag_id_t private_swid_tag_id_t;
+
+/**
+ * Private data of a swid_tag_id_t object.
+ *
+ */
+struct private_swid_tag_id_t {
+
+ /**
+ * Public swid_tag_id_t interface.
+ */
+ swid_tag_id_t public;
+
+ /**
+ * Tag Creator
+ */
+ chunk_t tag_creator;
+
+ /**
+ * Unique Software ID
+ */
+ chunk_t unique_sw_id;
+
+ /**
+ * Optional Tag Identifier Instance ID
+ */
+ chunk_t instance_id;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+};
+
+METHOD(swid_tag_id_t, get_tag_creator, chunk_t,
+ private_swid_tag_id_t *this)
+{
+ return this->tag_creator;
+}
+
+METHOD(swid_tag_id_t, get_unique_sw_id, chunk_t,
+ private_swid_tag_id_t *this, chunk_t *instance_id)
+{
+ if (instance_id)
+ {
+ *instance_id = this->instance_id;
+ }
+ 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)
+{
+ if (ref_put(&this->ref))
+ {
+ free(this->tag_creator.ptr);
+ free(this->unique_sw_id.ptr);
+ free(this->instance_id.ptr);
+ free(this);
+ }
+}
+
+/**
+ * See header
+ */
+swid_tag_id_t *swid_tag_id_create(chunk_t tag_creator, chunk_t unique_sw_id,
+ chunk_t instance_id)
+{
+ private_swid_tag_id_t *this;
+
+ INIT(this,
+ .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 (instance_id.len > 0)
+ {
+ this->instance_id = chunk_clone(instance_id);
+ }
+
+ return &this->public;
+}
+
diff --git a/src/libimcv/swid/swid_tag_id.h b/src/libimcv/swid/swid_tag_id.h
new file mode 100644
index 000000000..a2be290ae
--- /dev/null
+++ b/src/libimcv/swid/swid_tag_id.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2013-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup swid_tag_id swid_tag_id
+ * @{ @ingroup libimcv_swid
+ */
+
+#ifndef SWID_TAG_ID_H_
+#define SWID_TAG_ID_H_
+
+#include <library.h>
+
+typedef struct swid_tag_id_t swid_tag_id_t;
+
+
+/**
+ * Class storing a SWID Tag ID
+ */
+struct swid_tag_id_t {
+
+ /**
+ * Get the Tag Creator
+ *
+ * @return Tag Creator
+ */
+ chunk_t (*get_tag_creator)(swid_tag_id_t *this);
+
+ /**
+ * Get the Unique Software ID and optional Tag File Path
+ *
+ * @param instance_id Optional Tag Identifier Instance ID
+ * @return Unique Software ID
+ */
+ chunk_t (*get_unique_sw_id)(swid_tag_id_t *this, chunk_t *instance_id);
+
+ /**
+ * 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.
+ */
+ void (*destroy)(swid_tag_id_t *this);
+
+};
+
+/**
+ * Creates a swid_tag_id_t object
+ *
+ * @param tag_creator Tag Creator
+ * @param unique_sw_id Unique Software ID
+ * @param instance_id Tag Identifier Instance ID or empty chunk
+ */
+swid_tag_id_t* swid_tag_id_create(chunk_t tag_creator, chunk_t unique_sw_id,
+ chunk_t instance_id);
+
+#endif /** SWID_TAG_ID_H_ @}*/
diff --git a/src/libimcv/tcg/pts/tcg_pts_attr_aik.c b/src/libimcv/tcg/pts/tcg_pts_attr_aik.c
new file mode 100644
index 000000000..194cf1b68
--- /dev/null
+++ b/src/libimcv/tcg/pts/tcg_pts_attr_aik.c
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2011-2012 Sansar Choinyambuu
+ * Copyright (C) 2011-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tcg_pts_attr_aik.h"
+
+#include <pa_tnc/pa_tnc_msg.h>
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <utils/debug.h>
+
+typedef struct private_tcg_pts_attr_aik_t private_tcg_pts_attr_aik_t;
+
+/**
+ * Attestation Identity Key
+ * see section 3.13 of PTS Protocol: Binding to TNC IF-M Specification
+ *
+ * 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Flags | Attestation Identity Key (Variable Length) ~
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Attestation Identity Key (Variable Length) ~
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+#define PTS_AIK_SIZE 4
+#define PTS_AIK_FLAGS_NONE 0
+#define PTS_AIK_FLAGS_NAKED_KEY (1<<7)
+/**
+ * Private data of an tcg_pts_attr_aik_t object.
+ */
+struct private_tcg_pts_attr_aik_t {
+
+ /**
+ * Public members of tcg_pts_attr_aik_t
+ */
+ tcg_pts_attr_aik_t public;
+
+ /**
+ * Vendor-specific attribute type
+ */
+ pen_type_t type;
+
+ /**
+ * Length of attribute value
+ */
+ size_t length;
+
+ /**
+ * Attribute value or segment
+ */
+ chunk_t value;
+
+ /**
+ * Noskip flag
+ */
+ bool noskip_flag;
+
+ /**
+ * AIK Certificate or Public Key
+ */
+ certificate_t *aik;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+};
+
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
+ private_tcg_pts_attr_aik_t *this)
+{
+ return this->type;
+}
+
+METHOD(pa_tnc_attr_t, get_value, chunk_t,
+ private_tcg_pts_attr_aik_t *this)
+{
+ return this->value;
+}
+
+METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
+ private_tcg_pts_attr_aik_t *this)
+{
+ return this->noskip_flag;
+}
+
+METHOD(pa_tnc_attr_t, set_noskip_flag,void,
+ private_tcg_pts_attr_aik_t *this, bool noskip)
+{
+ this->noskip_flag = noskip;
+}
+
+METHOD(pa_tnc_attr_t, build, void,
+ private_tcg_pts_attr_aik_t *this)
+{
+ bio_writer_t *writer;
+ u_int8_t flags = PTS_AIK_FLAGS_NONE;
+ cred_encoding_type_t encoding_type = CERT_ASN1_DER;
+ chunk_t aik_blob;
+
+ if (this->value.ptr)
+ {
+ return;
+ }
+ if (this->aik->get_type(this->aik) == CERT_TRUSTED_PUBKEY)
+ {
+ flags |= PTS_AIK_FLAGS_NAKED_KEY;
+ encoding_type = PUBKEY_SPKI_ASN1_DER;
+ }
+ if (!this->aik->get_encoding(this->aik, encoding_type, &aik_blob))
+ {
+ DBG1(DBG_TNC, "encoding of Attestation Identity Key failed");
+ aik_blob = chunk_empty;
+ }
+ writer = bio_writer_create(PTS_AIK_SIZE);
+ writer->write_uint8(writer, flags);
+ writer->write_data (writer, aik_blob);
+ this->value = writer->extract_buf(writer);
+ this->length = this->value.len;
+ writer->destroy(writer);
+ free(aik_blob.ptr);
+}
+
+METHOD(pa_tnc_attr_t, process, status_t,
+ private_tcg_pts_attr_aik_t *this, u_int32_t *offset)
+{
+ bio_reader_t *reader;
+ u_int8_t flags;
+ certificate_type_t type;
+ chunk_t aik_blob;
+
+ *offset = 0;
+
+ if (this->value.len < this->length)
+ {
+ return NEED_MORE;
+ }
+ if (this->value.len < PTS_AIK_SIZE)
+ {
+ DBG1(DBG_TNC, "insufficient data for Attestation Identity Key");
+ return FAILED;
+ }
+ reader = bio_reader_create(this->value);
+ reader->read_uint8(reader, &flags);
+ reader->read_data (reader, reader->remaining(reader), &aik_blob);
+
+ type = (flags & PTS_AIK_FLAGS_NAKED_KEY) ? CERT_TRUSTED_PUBKEY : CERT_X509;
+
+ this->aik = lib->creds->create(lib->creds, CRED_CERTIFICATE, type,
+ BUILD_BLOB_PEM, aik_blob, BUILD_END);
+ reader->destroy(reader);
+
+ if (!this->aik)
+ {
+ DBG1(DBG_TNC, "parsing of Attestation Identity Key failed");
+ *offset = 0;
+ return FAILED;
+ }
+ return SUCCESS;
+}
+
+METHOD(pa_tnc_attr_t, add_segment, void,
+ private_tcg_pts_attr_aik_t *this, chunk_t segment)
+{
+ this->value = chunk_cat("mc", this->value, segment);
+}
+
+METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
+ private_tcg_pts_attr_aik_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.pa_tnc_attribute;
+}
+
+METHOD(pa_tnc_attr_t, destroy, void,
+ private_tcg_pts_attr_aik_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ DESTROY_IF(this->aik);
+ free(this->value.ptr);
+ free(this);
+ }
+}
+
+METHOD(tcg_pts_attr_aik_t, get_aik, certificate_t*,
+ private_tcg_pts_attr_aik_t *this)
+{
+ return this->aik;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *tcg_pts_attr_aik_create(certificate_t *aik)
+{
+ private_tcg_pts_attr_aik_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_aik = _get_aik,
+ },
+ .type = { PEN_TCG, TCG_PTS_AIK },
+ .aik = aik->get_ref(aik),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *tcg_pts_attr_aik_create_from_data(size_t length, chunk_t data)
+{
+ private_tcg_pts_attr_aik_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_aik = _get_aik,
+ },
+ .type = { PEN_TCG, TCG_PTS_AIK },
+ .length = length,
+ .value = chunk_clone(data),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
diff --git a/src/libimcv/tcg/pts/tcg_pts_attr_aik.h b/src/libimcv/tcg/pts/tcg_pts_attr_aik.h
new file mode 100644
index 000000000..b524ff321
--- /dev/null
+++ b/src/libimcv/tcg/pts/tcg_pts_attr_aik.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup tcg_pts_attr_aik tcg_pts_attr_aik
+ * @{ @ingroup tcg_attr
+ */
+
+#ifndef TCG_PTS_ATTR_AIK_H_
+#define TCG_PTS_ATTR_AIK_H_
+
+typedef struct tcg_pts_attr_aik_t tcg_pts_attr_aik_t;
+
+#include "tcg/tcg_attr.h"
+#include "pa_tnc/pa_tnc_attr.h"
+
+#include <credentials/certificates/certificate.h>
+
+/**
+ * Class implementing the TCG PTS Attestation Identity Key attribute
+ *
+ */
+struct tcg_pts_attr_aik_t {
+
+ /**
+ * Public PA-TNC attribute interface
+ */
+ pa_tnc_attr_t pa_tnc_attribute;
+
+ /**
+ * Get AIK
+ *
+ * @return AIK Certificate or Public Key
+ */
+ certificate_t* (*get_aik)(tcg_pts_attr_aik_t *this);
+
+};
+
+/**
+ * Creates an tcg_pts_attr_aik_t object
+ *
+ * @param aik Attestation Identity Key
+ */
+pa_tnc_attr_t* tcg_pts_attr_aik_create(certificate_t *aik);
+
+/**
+ * Creates an tcg_pts_attr_aik_t object from received data
+ *
+ * @param length Total length of attribute value
+ * @param value Unparsed attribute value (might be a segment)
+ */
+pa_tnc_attr_t* tcg_pts_attr_aik_create_from_data(size_t length, chunk_t value);
+
+#endif /** TCG_PTS_ATTR_AIK_H_ @}*/
diff --git a/src/libimcv/tcg/pts/tcg_pts_attr_dh_nonce_finish.c b/src/libimcv/tcg/pts/tcg_pts_attr_dh_nonce_finish.c
new file mode 100644
index 000000000..2a1506898
--- /dev/null
+++ b/src/libimcv/tcg/pts/tcg_pts_attr_dh_nonce_finish.c
@@ -0,0 +1,287 @@
+/*
+ * Copyright (C) 2011-2012 Sansar Choinyambuu
+ * Copyright (C) 2011-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tcg_pts_attr_dh_nonce_finish.h"
+
+#include <pa_tnc/pa_tnc_msg.h>
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <utils/debug.h>
+
+typedef struct private_tcg_pts_attr_dh_nonce_finish_t
+ private_tcg_pts_attr_dh_nonce_finish_t;
+
+/**
+ * PTS DH Nonce Finish
+ * see section 3.8.3 of PTS Protocol: Binding to TNC IF-M Specification
+ *
+ * 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Reserved | Nonce Len | Selected Hash Algorithm |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | D-H Initiator Public Value ... |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | D-H Initiator Nonce ... |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ */
+
+#define PTS_DH_NONCE_FINISH_SIZE 12
+#define PTS_DH_NONCE_FINISH_RESERVED 0x00
+
+/**
+ * Private data of an tcg_pts_attr_dh_nonce_finish_t object.
+ */
+struct private_tcg_pts_attr_dh_nonce_finish_t {
+
+ /**
+ * Public members of tcg_pts_attr_dh_nonce_finish_t
+ */
+ tcg_pts_attr_dh_nonce_finish_t public;
+
+ /**
+ * Vendor-specific attribute type
+ */
+ pen_type_t type;
+
+ /**
+ * Length of attribute value
+ */
+ size_t length;
+
+ /**
+ * Attribute value or segment
+ */
+ chunk_t value;
+
+ /**
+ * Noskip flag
+ */
+ bool noskip_flag;
+
+ /**
+ * Selected Hashing Algorithm
+ */
+ pts_meas_algorithms_t hash_algo;
+
+ /**
+ * DH Initiator Public Value
+ */
+ chunk_t initiator_value;
+
+ /**
+ * DH Initiator Nonce
+ */
+ chunk_t initiator_nonce;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+};
+
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
+ private_tcg_pts_attr_dh_nonce_finish_t *this)
+{
+ return this->type;
+}
+
+METHOD(pa_tnc_attr_t, get_value, chunk_t,
+ private_tcg_pts_attr_dh_nonce_finish_t *this)
+{
+ return this->value;
+}
+
+METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
+ private_tcg_pts_attr_dh_nonce_finish_t *this)
+{
+ return this->noskip_flag;
+}
+
+METHOD(pa_tnc_attr_t, set_noskip_flag,void,
+ private_tcg_pts_attr_dh_nonce_finish_t *this, bool noskip)
+{
+ this->noskip_flag = noskip;
+}
+
+METHOD(pa_tnc_attr_t, build, void,
+ private_tcg_pts_attr_dh_nonce_finish_t *this)
+{
+ bio_writer_t *writer;
+
+ if (this->value.ptr)
+ {
+ return;
+ }
+ writer = bio_writer_create(PTS_DH_NONCE_FINISH_SIZE);
+ writer->write_uint8 (writer, PTS_DH_NONCE_FINISH_RESERVED);
+ writer->write_uint8 (writer, this->initiator_nonce.len);
+ writer->write_uint16(writer, this->hash_algo);
+ writer->write_data (writer, this->initiator_value);
+ writer->write_data (writer, this->initiator_nonce);
+
+ this->value = writer->extract_buf(writer);
+ this->length = this->value.len;
+ writer->destroy(writer);
+}
+
+METHOD(pa_tnc_attr_t, process, status_t,
+ private_tcg_pts_attr_dh_nonce_finish_t *this, u_int32_t *offset)
+{
+ bio_reader_t *reader;
+ u_int8_t reserved, nonce_len;
+ u_int16_t hash_algo;
+
+ *offset = 0;
+
+ if (this->value.len < this->length)
+ {
+ return NEED_MORE;
+ }
+ if (this->value.len < PTS_DH_NONCE_FINISH_SIZE)
+ {
+ DBG1(DBG_TNC, "insufficient data for PTS DH Nonce Finish");
+ return FAILED;
+ }
+ reader = bio_reader_create(this->value);
+ reader->read_uint8 (reader, &reserved);
+ reader->read_uint8 (reader, &nonce_len);
+ reader->read_uint16(reader, &hash_algo);
+ reader->read_data(reader, reader->remaining(reader) - nonce_len,
+ &this->initiator_value);
+ reader->read_data(reader, nonce_len, &this->initiator_nonce);
+ this->hash_algo = hash_algo;
+ this->initiator_value = chunk_clone(this->initiator_value);
+ this->initiator_nonce = chunk_clone(this->initiator_nonce);
+ reader->destroy(reader);
+
+ return SUCCESS;
+}
+
+METHOD(pa_tnc_attr_t, add_segment, void,
+ private_tcg_pts_attr_dh_nonce_finish_t *this, chunk_t segment)
+{
+ this->value = chunk_cat("mc", this->value, segment);
+}
+
+METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
+ private_tcg_pts_attr_dh_nonce_finish_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.pa_tnc_attribute;
+}
+
+METHOD(pa_tnc_attr_t, destroy, void,
+ private_tcg_pts_attr_dh_nonce_finish_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ free(this->value.ptr);
+ free(this->initiator_value.ptr);
+ free(this->initiator_nonce.ptr);
+ free(this);
+ }
+}
+
+METHOD(tcg_pts_attr_dh_nonce_finish_t, get_hash_algo, pts_meas_algorithms_t,
+ private_tcg_pts_attr_dh_nonce_finish_t *this)
+{
+ return this->hash_algo;
+}
+
+METHOD(tcg_pts_attr_dh_nonce_finish_t, get_initiator_value, chunk_t,
+ private_tcg_pts_attr_dh_nonce_finish_t *this)
+{
+ return this->initiator_value;
+}
+
+METHOD(tcg_pts_attr_dh_nonce_finish_t, get_initiator_nonce, chunk_t,
+ private_tcg_pts_attr_dh_nonce_finish_t *this)
+{
+ return this->initiator_nonce;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *tcg_pts_attr_dh_nonce_finish_create(
+ pts_meas_algorithms_t hash_algo,
+ chunk_t initiator_value,
+ chunk_t initiator_nonce)
+{
+ private_tcg_pts_attr_dh_nonce_finish_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_hash_algo = _get_hash_algo,
+ .get_initiator_nonce = _get_initiator_nonce,
+ .get_initiator_value = _get_initiator_value,
+ },
+ .type = { PEN_TCG, TCG_PTS_DH_NONCE_FINISH },
+ .hash_algo = hash_algo,
+ .initiator_value = initiator_value,
+ .initiator_nonce = chunk_clone(initiator_nonce),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *tcg_pts_attr_dh_nonce_finish_create_from_data(size_t length,
+ chunk_t value)
+{
+ private_tcg_pts_attr_dh_nonce_finish_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_hash_algo = _get_hash_algo,
+ .get_initiator_nonce = _get_initiator_nonce,
+ .get_initiator_value = _get_initiator_value,
+ },
+ .type = { PEN_TCG, TCG_PTS_DH_NONCE_FINISH },
+ .length = length,
+ .value = chunk_clone(value),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
diff --git a/src/libimcv/tcg/pts/tcg_pts_attr_dh_nonce_finish.h b/src/libimcv/tcg/pts/tcg_pts_attr_dh_nonce_finish.h
new file mode 100644
index 000000000..78b5025bc
--- /dev/null
+++ b/src/libimcv/tcg/pts/tcg_pts_attr_dh_nonce_finish.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup tcg_pts_attr_dh_nonce_finish tcg_pts_attr_dh_nonce_finish
+ * @{ @ingroup tcg_attr
+ */
+
+#ifndef TCG_PTS_ATTR_DH_NONCE_FINISH_H_
+#define TCG_PTS_ATTR_DH_NONCE_FINISH_H_
+
+typedef struct tcg_pts_attr_dh_nonce_finish_t tcg_pts_attr_dh_nonce_finish_t;
+
+#include "tcg/tcg_attr.h"
+#include "pa_tnc/pa_tnc_attr.h"
+#include "pts/pts_meas_algo.h"
+
+/**
+ * Class implementing the TCG PTS DH Nonce Finish Attribute
+ */
+struct tcg_pts_attr_dh_nonce_finish_t {
+
+ /**
+ * Public PA-TNC attribute interface
+ */
+ pa_tnc_attr_t pa_tnc_attribute;
+
+ /**
+ * Get nonce length
+ *
+ * @return Length of nonce
+ */
+ u_int8_t (*get_nonce_len)(tcg_pts_attr_dh_nonce_finish_t *this);
+
+ /**
+ * Get selected hash algorithm
+ *
+ * @return Selected hash algorithm
+ */
+ pts_meas_algorithms_t (*get_hash_algo)(tcg_pts_attr_dh_nonce_finish_t *this);
+
+ /**
+ * Get DH Initiator Public Value
+ *
+ * @return DH Initiator Public Value
+ */
+ chunk_t (*get_initiator_value)(tcg_pts_attr_dh_nonce_finish_t *this);
+
+ /**
+ * Get DH Initiator Nonce
+ *
+ * @return DH Initiator Nonce
+ */
+ chunk_t (*get_initiator_nonce)(tcg_pts_attr_dh_nonce_finish_t *this);
+
+};
+
+/**
+ * Creates an tcg_pts_attr_dh_nonce_finish_t object
+ *
+ * @param hash_algo Selected hash algorithm
+ * @param initiator_value DH Initiator Public Value
+ * @param initiator_nonce DH Initiator Nonce
+ */
+pa_tnc_attr_t* tcg_pts_attr_dh_nonce_finish_create(
+ pts_meas_algorithms_t hash_algo,
+ chunk_t initiator_value,
+ chunk_t initiator_nonce);
+
+/**
+ * Creates an tcg_pts_attr_dh_nonce_finish_t object from received data
+ *
+ * @param length Total length of attribute value
+ * @param value Unparsed attribute value (might be a segment)
+ */
+pa_tnc_attr_t* tcg_pts_attr_dh_nonce_finish_create_from_data(size_t length,
+ chunk_t value);
+
+#endif /** TCG_PTS_ATTR_DH_NONCE_FINISH_H_ @}*/
diff --git a/src/libimcv/tcg/pts/tcg_pts_attr_dh_nonce_params_req.c b/src/libimcv/tcg/pts/tcg_pts_attr_dh_nonce_params_req.c
new file mode 100644
index 000000000..0349ce53e
--- /dev/null
+++ b/src/libimcv/tcg/pts/tcg_pts_attr_dh_nonce_params_req.c
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2011-2012 Sansar Choinyambuu
+ * Copyright (C) 2011-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tcg_pts_attr_dh_nonce_params_req.h"
+
+#include <pa_tnc/pa_tnc_msg.h>
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <utils/debug.h>
+
+typedef struct private_tcg_pts_attr_dh_nonce_params_req_t
+ private_tcg_pts_attr_dh_nonce_params_req_t;
+
+/**
+ * PTS DH Nonce Parameters Request
+ * see section 3.8.1 of PTS Protocol: Binding to TNC IF-M Specification
+ *
+ * 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Reserved | Min. Nonce Len | D-H Group Set |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ */
+
+#define PTS_DH_NONCE_PARAMS_REQ_SIZE 4
+#define PTS_DH_NONCE_PARAMS_REQ_RESERVED 0x00
+
+/**
+ * Private data of an tcg_pts_attr_dh_nonce_params_req_t object.
+ */
+struct private_tcg_pts_attr_dh_nonce_params_req_t {
+
+ /**
+ * Public members of tcg_pts_attr_dh_nonce_params_req_t
+ */
+ tcg_pts_attr_dh_nonce_params_req_t public;
+
+ /**
+ * Vendor-specific attribute type
+ */
+ pen_type_t type;
+
+ /**
+ * Length of attribute value
+ */
+ size_t length;
+
+ /**
+ * Attribute value or segment
+ */
+ chunk_t value;
+
+ /**
+ * Noskip flag
+ */
+ bool noskip_flag;
+
+ /**
+ * Minimum acceptable length of nonce
+ */
+ u_int8_t min_nonce_len;
+
+ /**
+ * Diffie Hellman group set
+ */
+ pts_dh_group_t dh_groups;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+};
+
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
+ private_tcg_pts_attr_dh_nonce_params_req_t *this)
+{
+ return this->type;
+}
+
+METHOD(pa_tnc_attr_t, get_value, chunk_t,
+ private_tcg_pts_attr_dh_nonce_params_req_t *this)
+{
+ return this->value;
+}
+
+METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
+ private_tcg_pts_attr_dh_nonce_params_req_t *this)
+{
+ return this->noskip_flag;
+}
+
+METHOD(pa_tnc_attr_t, set_noskip_flag,void,
+ private_tcg_pts_attr_dh_nonce_params_req_t *this, bool noskip)
+{
+ this->noskip_flag = noskip;
+}
+
+METHOD(pa_tnc_attr_t, build, void,
+ private_tcg_pts_attr_dh_nonce_params_req_t *this)
+{
+ bio_writer_t *writer;
+
+ if (this->value.ptr)
+ {
+ return;
+ }
+ writer = bio_writer_create(PTS_DH_NONCE_PARAMS_REQ_SIZE);
+ writer->write_uint8 (writer, PTS_DH_NONCE_PARAMS_REQ_RESERVED);
+ writer->write_uint8 (writer, this->min_nonce_len);
+ writer->write_uint16(writer, this->dh_groups);
+
+ this->value = writer->extract_buf(writer);
+ this->length = this->value.len;
+ writer->destroy(writer);
+}
+
+METHOD(pa_tnc_attr_t, process, status_t,
+ private_tcg_pts_attr_dh_nonce_params_req_t *this, u_int32_t *offset)
+{
+ bio_reader_t *reader;
+ u_int8_t reserved;
+ u_int16_t dh_groups;
+
+ *offset = 0;
+
+ if (this->value.len < this->length)
+ {
+ return NEED_MORE;
+ }
+ if (this->value.len < PTS_DH_NONCE_PARAMS_REQ_SIZE)
+ {
+ DBG1(DBG_TNC, "insufficient data for PTS DH Nonce Parameters Request");
+ return FAILED;
+ }
+ reader = bio_reader_create(this->value);
+ reader->read_uint8(reader, &reserved);
+ reader->read_uint8(reader, &this->min_nonce_len);
+ reader->read_uint16(reader, &dh_groups);
+ this->dh_groups = dh_groups;
+ reader->destroy(reader);
+
+ return SUCCESS;
+}
+
+METHOD(pa_tnc_attr_t, add_segment, void,
+ private_tcg_pts_attr_dh_nonce_params_req_t *this, chunk_t segment)
+{
+ this->value = chunk_cat("mc", this->value, segment);
+}
+
+METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
+ private_tcg_pts_attr_dh_nonce_params_req_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.pa_tnc_attribute;
+}
+
+METHOD(pa_tnc_attr_t, destroy, void,
+ private_tcg_pts_attr_dh_nonce_params_req_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ free(this->value.ptr);
+ free(this);
+ }
+}
+
+METHOD(tcg_pts_attr_dh_nonce_params_req_t, get_min_nonce_len, u_int8_t,
+ private_tcg_pts_attr_dh_nonce_params_req_t *this)
+{
+ return this->min_nonce_len;
+}
+
+METHOD(tcg_pts_attr_dh_nonce_params_req_t, get_dh_groups, pts_dh_group_t,
+ private_tcg_pts_attr_dh_nonce_params_req_t *this)
+{
+ return this->dh_groups;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *tcg_pts_attr_dh_nonce_params_req_create(u_int8_t min_nonce_len,
+ pts_dh_group_t dh_groups)
+{
+ private_tcg_pts_attr_dh_nonce_params_req_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_min_nonce_len = _get_min_nonce_len,
+ .get_dh_groups = _get_dh_groups,
+ },
+ .type = { PEN_TCG, TCG_PTS_DH_NONCE_PARAMS_REQ },
+ .min_nonce_len = min_nonce_len,
+ .dh_groups = dh_groups,
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *tcg_pts_attr_dh_nonce_params_req_create_from_data(size_t length,
+ chunk_t value)
+{
+ private_tcg_pts_attr_dh_nonce_params_req_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_min_nonce_len = _get_min_nonce_len,
+ .get_dh_groups = _get_dh_groups,
+ },
+ .type = { PEN_TCG, TCG_PTS_DH_NONCE_PARAMS_REQ },
+ .length = length,
+ .value = chunk_clone(value),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
diff --git a/src/libimcv/tcg/pts/tcg_pts_attr_dh_nonce_params_req.h b/src/libimcv/tcg/pts/tcg_pts_attr_dh_nonce_params_req.h
new file mode 100644
index 000000000..4396bf687
--- /dev/null
+++ b/src/libimcv/tcg/pts/tcg_pts_attr_dh_nonce_params_req.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup tcg_pts_attr_dh_nonce_params_req tcg_pts_attr_dh_nonce_params_req
+ * @{ @ingroup tcg_attr
+ */
+
+#ifndef TCG_PTS_ATTR_DH_NONCE_PARAMS_REQ_H_
+#define TCG_PTS_ATTR_DH_NONCE_PARAMS_REQ_H_
+
+typedef struct tcg_pts_attr_dh_nonce_params_req_t
+ tcg_pts_attr_dh_nonce_params_req_t;
+
+#include "tcg/tcg_attr.h"
+#include "pa_tnc/pa_tnc_attr.h"
+#include "pts/pts_dh_group.h"
+
+/**
+ * Class implementing the TCG PTS DH Nonce Parameters Request Attribute
+ */
+struct tcg_pts_attr_dh_nonce_params_req_t {
+
+ /**
+ * Public PA-TNC attribute interface
+ */
+ pa_tnc_attr_t pa_tnc_attribute;
+
+ /**
+ * Get Minimum nonce length
+ *
+ * @return Minimum acceptable length of nonce
+ */
+ u_int8_t (*get_min_nonce_len)(tcg_pts_attr_dh_nonce_params_req_t *this);
+
+ /**
+ * Get supported Diffie Hellman Groups
+ *
+ * @return Supported Diffie Hellman Groups
+ */
+ pts_dh_group_t (*get_dh_groups)(tcg_pts_attr_dh_nonce_params_req_t *this);
+};
+
+/**
+ * Creates an tcg_pts_attr_dh_nonce_params_req_t object
+ *
+ * @param min_nonce_len Minimum acceptable length of nonce
+ * @param dh_groups Initiator's supported DH groups
+ */
+pa_tnc_attr_t* tcg_pts_attr_dh_nonce_params_req_create(u_int8_t min_nonce_len,
+ pts_dh_group_t dh_groups);
+
+/**
+ * Creates an tcg_pts_attr_dh_nonce_params_req_t object from received data
+ *
+ * @param length Total length of attribute value
+ * @param value Unparsed attribute value (might be a segment)
+ */
+pa_tnc_attr_t* tcg_pts_attr_dh_nonce_params_req_create_from_data(size_t length,
+ chunk_t value);
+
+#endif /** TCG_PTS_ATTR_DH_NONCE_PARAMS_REQ_H_ @}*/
diff --git a/src/libimcv/tcg/pts/tcg_pts_attr_dh_nonce_params_resp.c b/src/libimcv/tcg/pts/tcg_pts_attr_dh_nonce_params_resp.c
new file mode 100644
index 000000000..fa1dbdd3a
--- /dev/null
+++ b/src/libimcv/tcg/pts/tcg_pts_attr_dh_nonce_params_resp.c
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2011-2012 Sansar Choinyambuu
+ * Copyright (C) 2011-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tcg_pts_attr_dh_nonce_params_resp.h"
+
+#include <pa_tnc/pa_tnc_msg.h>
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <utils/debug.h>
+
+typedef struct private_tcg_pts_attr_dh_nonce_params_resp_t
+ private_tcg_pts_attr_dh_nonce_params_resp_t;
+
+/**
+ * PTS DH Nonce Parameters Response
+ * see section 3.8.2 of PTS Protocol: Binding to TNC IF-M Specification
+ *
+ * 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Reserved | Nonce Len |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Selected D-H Group | Hash Algorithm Set |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | D-H Responder Nonce ... |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | D-H Responder Public Value ... |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ */
+
+#define PTS_DH_NONCE_PARAMS_RESP_SIZE 16
+#define PTS_DH_NONCE_PARAMS_RESP_RESERVED 0x0000
+
+/**
+ * Private data of an tcg_pts_attr_dh_nonce_params_resp_t object.
+ */
+struct private_tcg_pts_attr_dh_nonce_params_resp_t {
+
+ /**
+ * Public members of tcg_pts_attr_dh_nonce_params_resp_t
+ */
+ tcg_pts_attr_dh_nonce_params_resp_t public;
+
+ /**
+ * Vendor-specific attribute type
+ */
+ pen_type_t type;
+
+ /**
+ * Length of attribute value
+ */
+ size_t length;
+
+ /**
+ * Attribute value or segment
+ */
+ chunk_t value;
+
+ /**
+ * Noskip flag
+ */
+ bool noskip_flag;
+
+ /**
+ * Selected Diffie Hellman group
+ */
+ pts_dh_group_t dh_group;
+
+ /**
+ * Supported Hashing Algorithms
+ */
+ pts_meas_algorithms_t hash_algo_set;
+
+ /**
+ * DH Responder Nonce
+ */
+ chunk_t responder_nonce;
+
+ /**
+ * DH Responder Public Value
+ */
+ chunk_t responder_value;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+};
+
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
+ private_tcg_pts_attr_dh_nonce_params_resp_t *this)
+{
+ return this->type;
+}
+
+METHOD(pa_tnc_attr_t, get_value, chunk_t,
+ private_tcg_pts_attr_dh_nonce_params_resp_t *this)
+{
+ return this->value;
+}
+
+METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
+ private_tcg_pts_attr_dh_nonce_params_resp_t *this)
+{
+ return this->noskip_flag;
+}
+
+METHOD(pa_tnc_attr_t, set_noskip_flag,void,
+ private_tcg_pts_attr_dh_nonce_params_resp_t *this, bool noskip)
+{
+ this->noskip_flag = noskip;
+}
+
+METHOD(pa_tnc_attr_t, build, void,
+ private_tcg_pts_attr_dh_nonce_params_resp_t *this)
+{
+ bio_writer_t *writer;
+
+ if (this->value.ptr)
+ {
+ return;
+ }
+ writer = bio_writer_create(PTS_DH_NONCE_PARAMS_RESP_SIZE);
+ writer->write_uint24(writer, PTS_DH_NONCE_PARAMS_RESP_RESERVED);
+ writer->write_uint8 (writer, this->responder_nonce.len);
+ writer->write_uint16(writer, this->dh_group);
+ writer->write_uint16(writer, this->hash_algo_set);
+ writer->write_data (writer, this->responder_nonce);
+ writer->write_data (writer, this->responder_value);
+
+ this->value = writer->extract_buf(writer);
+ this->length = this->value.len;
+ writer->destroy(writer);
+}
+
+METHOD(pa_tnc_attr_t, process, status_t,
+ private_tcg_pts_attr_dh_nonce_params_resp_t *this, u_int32_t *offset)
+{
+ bio_reader_t *reader;
+ u_int32_t reserved;
+ u_int8_t nonce_len;
+ u_int16_t dh_group, hash_algo_set;
+
+ *offset = 0;
+
+ if (this->value.len < this->length)
+ {
+ return NEED_MORE;
+ }
+ if (this->value.len < PTS_DH_NONCE_PARAMS_RESP_SIZE)
+ {
+ DBG1(DBG_TNC, "insufficient data for PTS DH Nonce Parameters Response");
+ return FAILED;
+ }
+ reader = bio_reader_create(this->value);
+ reader->read_uint24(reader, &reserved);
+ reader->read_uint8 (reader, &nonce_len);
+ reader->read_uint16(reader, &dh_group);
+ reader->read_uint16(reader, &hash_algo_set);
+ reader->read_data(reader, nonce_len, &this->responder_nonce);
+ reader->read_data(reader, reader->remaining(reader), &this->responder_value);
+ this->dh_group = dh_group;
+ this->hash_algo_set = hash_algo_set;
+ this->responder_nonce = chunk_clone(this->responder_nonce);
+ this->responder_value = chunk_clone(this->responder_value);
+ reader->destroy(reader);
+
+ return SUCCESS;
+}
+
+METHOD(pa_tnc_attr_t, add_segment, void,
+ private_tcg_pts_attr_dh_nonce_params_resp_t *this, chunk_t segment)
+{
+ this->value = chunk_cat("mc", this->value, segment);
+}
+
+METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
+ private_tcg_pts_attr_dh_nonce_params_resp_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.pa_tnc_attribute;
+}
+
+METHOD(pa_tnc_attr_t, destroy, void,
+ private_tcg_pts_attr_dh_nonce_params_resp_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ free(this->value.ptr);
+ free(this->responder_nonce.ptr);
+ free(this->responder_value.ptr);
+ free(this);
+ }
+}
+
+METHOD(tcg_pts_attr_dh_nonce_params_resp_t, get_dh_group, pts_dh_group_t,
+ private_tcg_pts_attr_dh_nonce_params_resp_t *this)
+{
+ return this->dh_group;
+}
+
+METHOD(tcg_pts_attr_dh_nonce_params_resp_t, get_hash_algo_set,
+ pts_meas_algorithms_t, private_tcg_pts_attr_dh_nonce_params_resp_t *this)
+{
+ return this->hash_algo_set;
+}
+
+METHOD(tcg_pts_attr_dh_nonce_params_resp_t, get_responder_nonce, chunk_t,
+ private_tcg_pts_attr_dh_nonce_params_resp_t *this)
+{
+ return this->responder_nonce;
+}
+
+METHOD(tcg_pts_attr_dh_nonce_params_resp_t, get_responder_value, chunk_t,
+ private_tcg_pts_attr_dh_nonce_params_resp_t *this)
+{
+ return this->responder_value;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *tcg_pts_attr_dh_nonce_params_resp_create(pts_dh_group_t dh_group,
+ pts_meas_algorithms_t hash_algo_set,
+ chunk_t responder_nonce,
+ chunk_t responder_value)
+{
+ private_tcg_pts_attr_dh_nonce_params_resp_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_dh_group = _get_dh_group,
+ .get_hash_algo_set = _get_hash_algo_set,
+ .get_responder_nonce = _get_responder_nonce,
+ .get_responder_value = _get_responder_value,
+ },
+ .type = { PEN_TCG, TCG_PTS_DH_NONCE_PARAMS_RESP },
+ .dh_group = dh_group,
+ .hash_algo_set = hash_algo_set,
+ .responder_nonce = chunk_clone(responder_nonce),
+ .responder_value = responder_value,
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *tcg_pts_attr_dh_nonce_params_resp_create_from_data(size_t length,
+ chunk_t value)
+{
+ private_tcg_pts_attr_dh_nonce_params_resp_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_dh_group = _get_dh_group,
+ .get_hash_algo_set = _get_hash_algo_set,
+ .get_responder_nonce = _get_responder_nonce,
+ .get_responder_value = _get_responder_value,
+ },
+ .type = { PEN_TCG, TCG_PTS_DH_NONCE_PARAMS_RESP },
+ .length = length,
+ .value = chunk_clone(value),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
diff --git a/src/libimcv/tcg/pts/tcg_pts_attr_dh_nonce_params_resp.h b/src/libimcv/tcg/pts/tcg_pts_attr_dh_nonce_params_resp.h
new file mode 100644
index 000000000..b548a81f0
--- /dev/null
+++ b/src/libimcv/tcg/pts/tcg_pts_attr_dh_nonce_params_resp.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup tcg_pts_attr_dh_nonce_params_resp tcg_pts_attr_dh_nonce_params_resp
+ * @{ @ingroup tcg_attr
+ */
+
+#ifndef TCG_PTS_ATTR_DH_NONCE_PARAMS_RESP_H_
+#define TCG_PTS_ATTR_DH_NONCE_PARAMS_RESP_H_
+
+typedef struct tcg_pts_attr_dh_nonce_params_resp_t
+ tcg_pts_attr_dh_nonce_params_resp_t;
+
+#include "tcg/tcg_attr.h"
+#include "pa_tnc/pa_tnc_attr.h"
+#include "pts/pts_dh_group.h"
+#include "pts/pts_meas_algo.h"
+
+/**
+ * Class implementing the TCG PTS DH Nonce Parameters Response Attribute
+ */
+struct tcg_pts_attr_dh_nonce_params_resp_t {
+
+ /**
+ * Public PA-TNC attribute interface
+ */
+ pa_tnc_attr_t pa_tnc_attribute;
+
+ /**
+ * Get selected Diffie Hellman Group
+ *
+ * @return Selected Diffie Hellman Group
+ */
+ pts_dh_group_t (*get_dh_group)(tcg_pts_attr_dh_nonce_params_resp_t *this);
+
+ /**
+ * Get supported hash algorithms
+ *
+ * @return Hash algorithm set
+ */
+ pts_meas_algorithms_t (*get_hash_algo_set)(
+ tcg_pts_attr_dh_nonce_params_resp_t *this);
+
+ /**
+ * Get DH Responder Nonce
+ *
+ * @return DH Responder Nonce
+ */
+ chunk_t (*get_responder_nonce)(tcg_pts_attr_dh_nonce_params_resp_t *this);
+
+ /**
+ * Get DH Responder Public Value
+ *
+ * @return DH Responder Public Value
+ */
+ chunk_t (*get_responder_value)(tcg_pts_attr_dh_nonce_params_resp_t *this);
+
+};
+
+/**
+ * Creates an tcg_pts_attr_dh_nonce_params_resp_t object
+ *
+ * @param dh_group Selected DH group
+ * @param hash_algo_set Set of supported hash algorithms
+ * @param responder_nonce DH Responder Nonce
+ * @param responder_value DH Responder Public value
+ */
+pa_tnc_attr_t* tcg_pts_attr_dh_nonce_params_resp_create(pts_dh_group_t dh_group,
+ pts_meas_algorithms_t hash_algo_set,
+ chunk_t responder_nonce,
+ chunk_t responder_value);
+
+/**
+ * Creates an tcg_pts_attr_dh_nonce_params_resp_t object from received data
+ *
+ * @param length Total length of attribute value
+ * @param value Unparsed attribute value (might be a segment)
+ */
+pa_tnc_attr_t* tcg_pts_attr_dh_nonce_params_resp_create_from_data(size_t length,
+ chunk_t value);
+
+#endif /** TCG_PTS_ATTR_DH_NONCE_PARAMS_RESP_H_ @}*/
diff --git a/src/libimcv/tcg/pts/tcg_pts_attr_file_meas.c b/src/libimcv/tcg/pts/tcg_pts_attr_file_meas.c
new file mode 100644
index 000000000..5b4cc273b
--- /dev/null
+++ b/src/libimcv/tcg/pts/tcg_pts_attr_file_meas.c
@@ -0,0 +1,356 @@
+/*
+ * Copyright (C) 2011-2012 Sansar Choinyambuu
+ * Copyright (C) 2011-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tcg_pts_attr_file_meas.h"
+
+#include <pa_tnc/pa_tnc_msg.h>
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <collections/linked_list.h>
+#include <utils/debug.h>
+
+typedef struct private_tcg_pts_attr_file_meas_t private_tcg_pts_attr_file_meas_t;
+
+/**
+ * File Measurement
+ * see section 3.19.2 of PTS Protocol: Binding to TNC IF-M Specification
+ *
+ * 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Number of Files included |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Number of Files included |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Request ID | Measurement Length |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Measurement #1 (Variable Length) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Filename Length | Filename (Variable Length) ~
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * ~ Filename (Variable Length) ~
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Measurement #2 (Variable Length) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Filename Length | Filename (Variable Length) ~
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * ~ Filename (Variable Length) ~
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * ...........................
+ */
+
+#define PTS_FILE_MEAS_SIZE 12
+
+/**
+ * Private data of an tcg_pts_attr_file_meas_t object.
+ */
+struct private_tcg_pts_attr_file_meas_t {
+
+ /**
+ * Public members of tcg_pts_attr_file_meas_t
+ */
+ tcg_pts_attr_file_meas_t public;
+
+ /**
+ * Vendor-specific attribute type
+ */
+ pen_type_t type;
+
+ /**
+ * Length of attribute value
+ */
+ size_t length;
+
+ /**
+ * Offset up to which attribute value has been processed
+ */
+ size_t offset;
+
+ /**
+ * Current position of attribute value pointer
+ */
+ chunk_t value;
+
+ /**
+ * Contains complete attribute or current segment
+ */
+ chunk_t segment;
+
+ /**
+ * Noskip flag
+ */
+ bool noskip_flag;
+
+ /**
+ * Request ID
+ */
+ uint16_t request_id;
+
+ /**
+ * Measurement Length
+ */
+ uint16_t meas_len;
+
+ /**
+ * Number of Files in attribute
+ */
+ uint64_t count;
+
+ /**
+ * PTS File Measurements
+ */
+ pts_file_meas_t *measurements;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+};
+
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
+ private_tcg_pts_attr_file_meas_t *this)
+{
+ return this->type;
+}
+
+METHOD(pa_tnc_attr_t, get_value, chunk_t,
+ private_tcg_pts_attr_file_meas_t *this)
+{
+ return this->value;
+}
+
+METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
+ private_tcg_pts_attr_file_meas_t *this)
+{
+ return this->noskip_flag;
+}
+
+METHOD(pa_tnc_attr_t, set_noskip_flag,void,
+ private_tcg_pts_attr_file_meas_t *this, bool noskip)
+{
+ this->noskip_flag = noskip;
+}
+
+METHOD(pa_tnc_attr_t, build, void,
+ private_tcg_pts_attr_file_meas_t *this)
+{
+ bio_writer_t *writer;
+ enumerator_t *enumerator;
+ u_int64_t count;
+ u_int16_t request_id;
+ char *filename;
+ chunk_t measurement;
+ bool first = TRUE;
+
+ if (this->value.ptr)
+ {
+ return;
+ }
+ count = this->measurements->get_file_count(this->measurements);
+ request_id = this->measurements->get_request_id(this->measurements);
+
+ writer = bio_writer_create(PTS_FILE_MEAS_SIZE);
+ writer->write_uint64(writer, count);
+ writer->write_uint16(writer, request_id);
+
+ enumerator = this->measurements->create_enumerator(this->measurements);
+ while (enumerator->enumerate(enumerator, &filename, &measurement))
+ {
+ if (first)
+ {
+ writer->write_uint16(writer, measurement.len);
+ first = FALSE;
+ }
+ writer->write_data (writer, measurement);
+ writer->write_data16(writer, chunk_create(filename, strlen(filename)));
+ }
+ enumerator->destroy(enumerator);
+
+ if (first)
+ {
+ /* no attached measurements */
+ writer->write_uint16(writer, 0);
+ }
+
+ this->value = writer->extract_buf(writer);
+ this->segment = this->value;
+ this->length = this->value.len;
+ writer->destroy(writer);
+}
+
+METHOD(pa_tnc_attr_t, process, status_t,
+ private_tcg_pts_attr_file_meas_t *this, u_int32_t *offset)
+{
+ bio_reader_t *reader;
+ chunk_t measurement, filename;
+ status_t status = NEED_MORE;
+ char buf[BUF_LEN];
+ size_t len;
+
+ if (this->offset == 0)
+ {
+ if (this->length < PTS_FILE_MEAS_SIZE)
+ {
+ DBG1(DBG_TNC, "insufficient data for %N/%N", pen_names, PEN_TCG,
+ tcg_attr_names, this->type.type);
+ *offset = this->offset;
+ return FAILED;
+ }
+ if (this->value.len < PTS_FILE_MEAS_SIZE)
+ {
+ return NEED_MORE;
+ }
+ reader = bio_reader_create(this->value);
+ reader->read_uint64(reader, &this->count);
+ reader->read_uint16(reader, &this->request_id);
+ reader->read_uint16(reader, &this->meas_len);
+ this->offset = PTS_FILE_MEAS_SIZE;
+ this->value = reader->peek(reader);
+ reader->destroy(reader);
+ }
+
+ this->measurements = pts_file_meas_create(this->request_id);
+ reader = bio_reader_create(this->value);
+
+ while (this->count)
+ {
+ if (!reader->read_data(reader, this->meas_len, &measurement) ||
+ !reader->read_data16(reader, &filename))
+ {
+ goto end;
+ }
+ this->offset += this->value.len - reader->remaining(reader);
+ this->value = reader->peek(reader);
+
+ len = min(filename.len, BUF_LEN-1);
+ memcpy(buf, filename.ptr, len);
+ buf[len] = '\0';
+ this->measurements->add(this->measurements, buf, measurement);
+ this->count--;
+ }
+
+ if (this->length != this->offset)
+ {
+ DBG1(DBG_TNC, "inconsistent length for %N/%N", pen_names, PEN_TCG,
+ tcg_attr_names, this->type.type);
+ *offset = this->offset;
+ status = FAILED;
+ }
+ status = SUCCESS;
+
+end:
+ reader->destroy(reader);
+ return status;
+}
+
+METHOD(pa_tnc_attr_t, add_segment, void,
+ private_tcg_pts_attr_file_meas_t *this, chunk_t segment)
+{
+ this->value = chunk_cat("cc", this->value, segment);
+ chunk_free(&this->segment);
+ this->segment = this->value;
+}
+
+METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
+ private_tcg_pts_attr_file_meas_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.pa_tnc_attribute;
+}
+METHOD(pa_tnc_attr_t, destroy, void,
+ private_tcg_pts_attr_file_meas_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ DESTROY_IF(this->measurements);
+ free(this->segment.ptr);
+ free(this);
+ }
+}
+
+METHOD(tcg_pts_attr_file_meas_t, get_measurements, pts_file_meas_t*,
+ private_tcg_pts_attr_file_meas_t *this)
+{
+ return this->measurements;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *tcg_pts_attr_file_meas_create(pts_file_meas_t *measurements)
+{
+ private_tcg_pts_attr_file_meas_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_measurements = _get_measurements,
+ },
+ .type = { PEN_TCG, TCG_PTS_FILE_MEAS },
+ .request_id = measurements->get_request_id(measurements),
+ .count = measurements->get_file_count(measurements),
+ .measurements = measurements,
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *tcg_pts_attr_file_meas_create_from_data(size_t length,
+ chunk_t data)
+{
+ private_tcg_pts_attr_file_meas_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_measurements = _get_measurements,
+ },
+ .type = { PEN_TCG, TCG_PTS_FILE_MEAS },
+ .length = length,
+ .segment = chunk_clone(data),
+ .ref = 1,
+ );
+
+ /* received either complete attribute value or first segment */
+ this->value = this->segment;
+
+ return &this->public.pa_tnc_attribute;
+}
diff --git a/src/libimcv/tcg/pts/tcg_pts_attr_file_meas.h b/src/libimcv/tcg/pts/tcg_pts_attr_file_meas.h
new file mode 100644
index 000000000..d399fecbb
--- /dev/null
+++ b/src/libimcv/tcg/pts/tcg_pts_attr_file_meas.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup tcg_pts_attr_file_meas tcg_pts_attr_file_meas
+ * @{ @ingroup tcg_attr
+ */
+
+#ifndef TCG_PTS_ATTR_FILE_MEAS_H_
+#define TCG_PTS_ATTR_FILE_MEAS_H_
+
+typedef struct tcg_pts_attr_file_meas_t tcg_pts_attr_file_meas_t;
+
+#include "tcg/tcg_attr.h"
+#include "pa_tnc/pa_tnc_attr.h"
+#include "pts/pts.h"
+#include "pts/pts_file_meas.h"
+
+/**
+ * Class implementing the TCG PTS File Measurement attribute
+ *
+ */
+struct tcg_pts_attr_file_meas_t {
+
+ /**
+ * Public PA-TNC attribute interface
+ */
+ pa_tnc_attr_t pa_tnc_attribute;
+
+ /**
+ * Get PTS File Measurements
+ *
+ * @return PTS File Measurements
+ */
+ pts_file_meas_t* (*get_measurements)(tcg_pts_attr_file_meas_t *this);
+
+};
+
+/**
+ * Creates an tcg_pts_attr_file_meas_t object
+ *
+ * @param measurements PTS File Measurements
+ */
+pa_tnc_attr_t* tcg_pts_attr_file_meas_create(pts_file_meas_t *measurements);
+
+/**
+ * Creates an tcg_pts_attr_file_meas_t object from received data
+ *
+ * @param length Total length of attribute value
+ * @param value Unparsed attribute value (might be a segment)
+ */
+pa_tnc_attr_t* tcg_pts_attr_file_meas_create_from_data(size_t length,
+ chunk_t value);
+
+#endif /** TCG_PTS_ATTR_FILE_MEAS_H_ @}*/
diff --git a/src/libimcv/tcg/pts/tcg_pts_attr_gen_attest_evid.c b/src/libimcv/tcg/pts/tcg_pts_attr_gen_attest_evid.c
new file mode 100644
index 000000000..b7b4d7e3f
--- /dev/null
+++ b/src/libimcv/tcg/pts/tcg_pts_attr_gen_attest_evid.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2011-2012 Sansar Choinyambuu
+ * Copyright (C) 2011-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tcg_pts_attr_gen_attest_evid.h"
+
+#include <pa_tnc/pa_tnc_msg.h>
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <utils/debug.h>
+
+typedef struct private_tcg_pts_attr_gen_attest_evid_t
+ private_tcg_pts_attr_gen_attest_evid_t;
+
+/**
+ * Generate Attestation Evidence
+ * see section 3.14.2 of PTS Protocol: Binding to TNC IF-M Specification
+ *
+ * 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ *
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Reserved |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ */
+
+#define PTS_GEN_ATTEST_EVID_SIZE 4
+#define PTS_GEN_ATTEST_EVID_RESERVED 0x00
+
+/**
+ * Private data of an tcg_pts_attr_gen_attest_evid_t object.
+ */
+struct private_tcg_pts_attr_gen_attest_evid_t {
+
+ /**
+ * Public members of tcg_pts_attr_gen_attest_evid_t
+ */
+ tcg_pts_attr_gen_attest_evid_t public;
+
+ /**
+ * Vendor-specific attribute type
+ */
+ pen_type_t type;
+
+ /**
+ * Length of attribute value
+ */
+ size_t length;
+
+ /**
+ * Attribute value or segment
+ */
+ chunk_t value;
+
+ /**
+ * Noskip flag
+ */
+ bool noskip_flag;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+};
+
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
+ private_tcg_pts_attr_gen_attest_evid_t *this)
+{
+ return this->type;
+}
+
+METHOD(pa_tnc_attr_t, get_value, chunk_t,
+ private_tcg_pts_attr_gen_attest_evid_t *this)
+{
+ return this->value;
+}
+
+METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
+ private_tcg_pts_attr_gen_attest_evid_t *this)
+{
+ return this->noskip_flag;
+}
+
+METHOD(pa_tnc_attr_t, set_noskip_flag,void,
+ private_tcg_pts_attr_gen_attest_evid_t *this, bool noskip)
+{
+ this->noskip_flag = noskip;
+}
+
+METHOD(pa_tnc_attr_t, build, void,
+ private_tcg_pts_attr_gen_attest_evid_t *this)
+{
+ bio_writer_t *writer;
+
+ if (this->value.ptr)
+ {
+ return;
+ }
+ writer = bio_writer_create(PTS_GEN_ATTEST_EVID_SIZE);
+ writer->write_uint32 (writer, PTS_GEN_ATTEST_EVID_RESERVED);
+
+ this->value = writer->extract_buf(writer);
+ this->length = this->value.len;
+ writer->destroy(writer);
+}
+
+METHOD(pa_tnc_attr_t, process, status_t,
+ private_tcg_pts_attr_gen_attest_evid_t *this, u_int32_t *offset)
+{
+ bio_reader_t *reader;
+ u_int32_t reserved;
+
+ *offset = 0;
+
+ if (this->value.len < this->length)
+ {
+ return NEED_MORE;
+ }
+ if (this->value.len < PTS_GEN_ATTEST_EVID_SIZE)
+ {
+ DBG1(DBG_TNC, "insufficient data for Generate Attestation Evidence");
+ return FAILED;
+ }
+ reader = bio_reader_create(this->value);
+ reader->read_uint32 (reader, &reserved);
+ reader->destroy(reader);
+
+ return SUCCESS;
+}
+
+METHOD(pa_tnc_attr_t, add_segment, void,
+ private_tcg_pts_attr_gen_attest_evid_t *this, chunk_t segment)
+{
+ this->value = chunk_cat("mc", this->value, segment);
+}
+
+METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
+ private_tcg_pts_attr_gen_attest_evid_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.pa_tnc_attribute;
+}
+
+METHOD(pa_tnc_attr_t, destroy, void,
+ private_tcg_pts_attr_gen_attest_evid_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ free(this->value.ptr);
+ free(this);
+ }
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *tcg_pts_attr_gen_attest_evid_create()
+{
+ private_tcg_pts_attr_gen_attest_evid_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ },
+ .type = { PEN_TCG, TCG_PTS_GEN_ATTEST_EVID },
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *tcg_pts_attr_gen_attest_evid_create_from_data(size_t length,
+ chunk_t data)
+{
+ private_tcg_pts_attr_gen_attest_evid_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ },
+ .type = { PEN_TCG, TCG_PTS_GEN_ATTEST_EVID },
+ .length = length,
+ .value = chunk_clone(data),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
diff --git a/src/libimcv/tcg/pts/tcg_pts_attr_gen_attest_evid.h b/src/libimcv/tcg/pts/tcg_pts_attr_gen_attest_evid.h
new file mode 100644
index 000000000..971abd2a3
--- /dev/null
+++ b/src/libimcv/tcg/pts/tcg_pts_attr_gen_attest_evid.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup tcg_pts_attr_gen_attest_evid tcg_pts_attr_gen_attest_evid
+ * @{ @ingroup tcg_attr
+ */
+
+#ifndef TCG_PTS_ATTR_GEN_ATTEST_EVID_H_
+#define TCG_PTS_ATTR_GEN_ATTEST_EVID_H_
+
+typedef struct tcg_pts_attr_gen_attest_evid_t tcg_pts_attr_gen_attest_evid_t;
+
+#include "tcg/tcg_attr.h"
+#include "pa_tnc/pa_tnc_attr.h"
+
+/**
+ * Class implementing the TCG PTS Generate Attestation Evidence Attribute
+ *
+ */
+struct tcg_pts_attr_gen_attest_evid_t {
+
+ /**
+ * Public PA-TNC attribute interface
+ */
+ pa_tnc_attr_t pa_tnc_attribute;
+};
+
+/**
+ * Creates an tcg_pts_attr_gen_attest_evid_t object
+ */
+pa_tnc_attr_t* tcg_pts_attr_gen_attest_evid_create();
+
+/**
+ * Creates an tcg_pts_attr_gen_attest_evid_t object from received data
+ *
+ * @param length Total length of attribute value
+ * @param value Unparsed attribute value (might be a segment)
+ */
+pa_tnc_attr_t* tcg_pts_attr_gen_attest_evid_create_from_data(size_t length,
+ chunk_t value);
+
+#endif /** TCG_PTS_ATTR_GEN_ATTEST_EVID_H_ @}*/
diff --git a/src/libimcv/tcg/pts/tcg_pts_attr_get_aik.c b/src/libimcv/tcg/pts/tcg_pts_attr_get_aik.c
new file mode 100644
index 000000000..8fda2b1f5
--- /dev/null
+++ b/src/libimcv/tcg/pts/tcg_pts_attr_get_aik.c
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2011-2012 Sansar Choinyambuu
+ * Copyright (C) 2011-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tcg_pts_attr_get_aik.h"
+
+#include <pa_tnc/pa_tnc_msg.h>
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <utils/debug.h>
+
+typedef struct private_tcg_pts_attr_get_aik_t private_tcg_pts_attr_get_aik_t;
+
+/**
+ * Get Attestation Identity Key
+ * see section 3.12 of PTS Protocol: Binding to TNC IF-M Specification
+ *
+ * 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Reserved |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+#define PTS_GET_AIK_SIZE 4
+#define PTS_GET_AIK_RESERVED 0x00000000
+
+/**
+ * Private data of an tcg_pts_attr_get_aik_t object.
+ */
+struct private_tcg_pts_attr_get_aik_t {
+
+ /**
+ * Public members of tcg_pts_attr_get_aik_t
+ */
+ tcg_pts_attr_get_aik_t public;
+
+ /**
+ * Vendor-specific attribute type
+ */
+ pen_type_t type;
+
+ /**
+ * Length of attribute value
+ */
+ size_t length;
+
+ /**
+ * Attribute value or segment
+ */
+ chunk_t value;
+
+ /**
+ * Noskip flag
+ */
+ bool noskip_flag;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+};
+
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
+ private_tcg_pts_attr_get_aik_t *this)
+{
+ return this->type;
+}
+
+METHOD(pa_tnc_attr_t, get_value, chunk_t,
+ private_tcg_pts_attr_get_aik_t *this)
+{
+ return this->value;
+}
+
+METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
+ private_tcg_pts_attr_get_aik_t *this)
+{
+ return this->noskip_flag;
+}
+
+METHOD(pa_tnc_attr_t, set_noskip_flag,void,
+ private_tcg_pts_attr_get_aik_t *this, bool noskip)
+{
+ this->noskip_flag = noskip;
+}
+
+METHOD(pa_tnc_attr_t, build, void,
+ private_tcg_pts_attr_get_aik_t *this)
+{
+ bio_writer_t *writer;
+
+ if (this->value.ptr)
+ {
+ return;
+ }
+ writer = bio_writer_create(PTS_GET_AIK_SIZE);
+ writer->write_uint32 (writer, PTS_GET_AIK_RESERVED);
+
+ this->value = writer->extract_buf(writer);
+ this->length = this->value.len;
+ writer->destroy(writer);
+}
+
+METHOD(pa_tnc_attr_t, add_segment, void,
+ private_tcg_pts_attr_get_aik_t *this, chunk_t segment)
+{
+ this->value = chunk_cat("mc", this->value, segment);
+}
+
+METHOD(pa_tnc_attr_t, process, status_t,
+ private_tcg_pts_attr_get_aik_t *this, u_int32_t *offset)
+{
+ bio_reader_t *reader;
+ u_int32_t reserved;
+
+ *offset = 0;
+
+ if (this->value.len < this->length)
+ {
+ return NEED_MORE;
+ }
+ if (this->value.len < PTS_GET_AIK_SIZE)
+ {
+ DBG1(DBG_TNC, "insufficient data for Get AIK");
+ return FAILED;
+ }
+ reader = bio_reader_create(this->value);
+ reader->read_uint32 (reader, &reserved);
+ reader->destroy(reader);
+
+ return SUCCESS;
+}
+
+METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
+ private_tcg_pts_attr_get_aik_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.pa_tnc_attribute;
+}
+
+METHOD(pa_tnc_attr_t, destroy, void,
+ private_tcg_pts_attr_get_aik_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ free(this->value.ptr);
+ free(this);
+ }
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *tcg_pts_attr_get_aik_create()
+{
+ private_tcg_pts_attr_get_aik_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ },
+ .type = { PEN_TCG, TCG_PTS_GET_AIK },
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *tcg_pts_attr_get_aik_create_from_data(size_t length,
+ chunk_t data)
+{
+ private_tcg_pts_attr_get_aik_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ },
+ .type = { PEN_TCG, TCG_PTS_GET_AIK },
+ .length = length,
+ .value = chunk_clone(data),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
diff --git a/src/libimcv/tcg/pts/tcg_pts_attr_get_aik.h b/src/libimcv/tcg/pts/tcg_pts_attr_get_aik.h
new file mode 100644
index 000000000..923fd039f
--- /dev/null
+++ b/src/libimcv/tcg/pts/tcg_pts_attr_get_aik.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup tcg_pts_attr_get_aik tcg_pts_attr_get_aik
+ * @{ @ingroup tcg_attr
+ */
+
+#ifndef TCG_PTS_ATTR_GET_AIK_H_
+#define TCG_PTS_ATTR_GET_AIK_H_
+
+typedef struct tcg_pts_attr_get_aik_t tcg_pts_attr_get_aik_t;
+
+#include "tcg/tcg_attr.h"
+#include "pa_tnc/pa_tnc_attr.h"
+
+/**
+ * Class implementing the TCG PTS Get Attestation Identity Key Attribute
+ *
+ */
+struct tcg_pts_attr_get_aik_t {
+
+ /**
+ * Public PA-TNC attribute interface
+ */
+ pa_tnc_attr_t pa_tnc_attribute;
+};
+
+/**
+ * Creates an tcg_pts_attr_get_aik_t object
+ */
+pa_tnc_attr_t* tcg_pts_attr_get_aik_create();
+
+/**
+ * Creates an tcg_pts_attr_get_aik_t object from received data
+ *
+ * @param length Total length of attribute value
+ * @param value Unparsed attribute value (might be a segment)
+ */
+pa_tnc_attr_t* tcg_pts_attr_get_aik_create_from_data(size_t length,
+ chunk_t value);
+
+#endif /** TCG_PTS_ATTR_GET_AIK_H_ @}*/
diff --git a/src/libimcv/tcg/pts/tcg_pts_attr_get_tpm_version_info.c b/src/libimcv/tcg/pts/tcg_pts_attr_get_tpm_version_info.c
new file mode 100644
index 000000000..a4c9dba87
--- /dev/null
+++ b/src/libimcv/tcg/pts/tcg_pts_attr_get_tpm_version_info.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2011-2012 Sansar Choinyambuu
+ * Copyright (C) 2011-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tcg_pts_attr_get_tpm_version_info.h"
+
+#include <pa_tnc/pa_tnc_msg.h>
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <utils/debug.h>
+
+typedef struct private_tcg_pts_attr_get_tpm_version_info_t
+ private_tcg_pts_attr_get_tpm_version_info_t;
+
+/**
+ * Get TPM Version Information
+ * see section 3.10 of PTS Protocol: Binding to TNC IF-M Specification
+ *
+ * 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ *
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Reserved |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ */
+
+#define PTS_GET_TPM_VER_INFO_SIZE 4
+#define PTS_GET_TPM_VER_INFO_RESERVED 0x00
+
+/**
+ * Private data of an tcg_pts_attr_get_tpm_version_info_t object.
+ */
+struct private_tcg_pts_attr_get_tpm_version_info_t {
+
+ /**
+ * Public members of tcg_pts_attr_get_tpm_version_info_t
+ */
+ tcg_pts_attr_get_tpm_version_info_t public;
+
+ /**
+ * Vendor-specific attribute type
+ */
+ pen_type_t type;
+
+ /**
+ * Length of attribute value
+ */
+ size_t length;
+
+ /**
+ * Attribute value or segment
+ */
+ chunk_t value;
+
+ /**
+ * Noskip flag
+ */
+ bool noskip_flag;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+};
+
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
+ private_tcg_pts_attr_get_tpm_version_info_t *this)
+{
+ return this->type;
+}
+
+METHOD(pa_tnc_attr_t, get_value, chunk_t,
+ private_tcg_pts_attr_get_tpm_version_info_t *this)
+{
+ return this->value;
+}
+
+METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
+ private_tcg_pts_attr_get_tpm_version_info_t *this)
+{
+ return this->noskip_flag;
+}
+
+METHOD(pa_tnc_attr_t, set_noskip_flag,void,
+ private_tcg_pts_attr_get_tpm_version_info_t *this, bool noskip)
+{
+ this->noskip_flag = noskip;
+}
+
+METHOD(pa_tnc_attr_t, build, void,
+ private_tcg_pts_attr_get_tpm_version_info_t *this)
+{
+ bio_writer_t *writer;
+
+ if (this->value.ptr)
+ {
+ return;
+ }
+ writer = bio_writer_create(PTS_GET_TPM_VER_INFO_SIZE);
+ writer->write_uint32 (writer, PTS_GET_TPM_VER_INFO_RESERVED);
+
+ this->value = writer->extract_buf(writer);
+ this->length = this->value.len;
+ writer->destroy(writer);
+}
+
+METHOD(pa_tnc_attr_t, process, status_t,
+ private_tcg_pts_attr_get_tpm_version_info_t *this, u_int32_t *offset)
+{
+ bio_reader_t *reader;
+ u_int32_t reserved;
+
+ *offset = 0;
+
+ if (this->value.len < this->length)
+ {
+ return NEED_MORE;
+ }
+ if (this->value.len < PTS_GET_TPM_VER_INFO_SIZE)
+ {
+ DBG1(DBG_TNC, "insufficient data for Get TPM Version Information");
+ return FAILED;
+ }
+ reader = bio_reader_create(this->value);
+ reader->read_uint32 (reader, &reserved);
+ reader->destroy(reader);
+
+ return SUCCESS;
+}
+
+METHOD(pa_tnc_attr_t, add_segment, void,
+ private_tcg_pts_attr_get_tpm_version_info_t *this, chunk_t segment)
+{
+ this->value = chunk_cat("mc", this->value, segment);
+}
+
+METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
+ private_tcg_pts_attr_get_tpm_version_info_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.pa_tnc_attribute;
+}
+
+METHOD(pa_tnc_attr_t, destroy, void,
+ private_tcg_pts_attr_get_tpm_version_info_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ free(this->value.ptr);
+ free(this);
+ }
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *tcg_pts_attr_get_tpm_version_info_create()
+{
+ private_tcg_pts_attr_get_tpm_version_info_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ },
+ .type = { PEN_TCG, TCG_PTS_GET_TPM_VERSION_INFO },
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *tcg_pts_attr_get_tpm_version_info_create_from_data(size_t length,
+ chunk_t data)
+{
+ private_tcg_pts_attr_get_tpm_version_info_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ },
+ .type = { PEN_TCG, TCG_PTS_GET_TPM_VERSION_INFO },
+ .length = length,
+ .value = chunk_clone(data),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
diff --git a/src/libimcv/tcg/pts/tcg_pts_attr_get_tpm_version_info.h b/src/libimcv/tcg/pts/tcg_pts_attr_get_tpm_version_info.h
new file mode 100644
index 000000000..19fb5a4e8
--- /dev/null
+++ b/src/libimcv/tcg/pts/tcg_pts_attr_get_tpm_version_info.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup tcg_pts_attr_get_tpm_version_info tcg_pts_attr_get_tpm_version_info
+ * @{ @ingroup tcg_attr
+ */
+
+#ifndef TCG_PTS_ATTR_GET_TPM_VERSION_INFO_H_
+#define TCG_PTS_ATTR_GET_TPM_VERSION_INFO_H_
+
+typedef struct tcg_pts_attr_get_tpm_version_info_t
+ tcg_pts_attr_get_tpm_version_info_t;
+
+#include "tcg/tcg_attr.h"
+#include "pa_tnc/pa_tnc_attr.h"
+
+/**
+ * Class implementing the TCG PTS Get TPM Version Info Attribute
+ *
+ */
+struct tcg_pts_attr_get_tpm_version_info_t {
+
+ /**
+ * Public PA-TNC attribute interface
+ */
+ pa_tnc_attr_t pa_tnc_attribute;
+};
+
+/**
+ * Creates an tcg_pts_attr_get_tpm_version_info_t object
+ */
+pa_tnc_attr_t* tcg_pts_attr_get_tpm_version_info_create();
+
+/**
+ * Creates an tcg_pts_attr_get_tpm_version_info_t object from received data
+ *
+ * @param length Total length of attribute value
+ * @param value Unparsed attribute value (might be a segment)
+ */
+pa_tnc_attr_t* tcg_pts_attr_get_tpm_version_info_create_from_data(size_t length,
+ chunk_t value);
+
+#endif /** TCG_PTS_ATTR_GET_TPM_VERSION_INFO_H_ @}*/
diff --git a/src/libimcv/tcg/pts/tcg_pts_attr_meas_algo.c b/src/libimcv/tcg/pts/tcg_pts_attr_meas_algo.c
new file mode 100644
index 000000000..8b0502a91
--- /dev/null
+++ b/src/libimcv/tcg/pts/tcg_pts_attr_meas_algo.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2011-2012 Sansar Choinyambuu
+ * Copyright (C) 2011-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tcg_pts_attr_meas_algo.h"
+
+#include <pa_tnc/pa_tnc_msg.h>
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <utils/debug.h>
+
+typedef struct private_tcg_pts_attr_meas_algo_t private_tcg_pts_attr_meas_algo_t;
+
+/**
+ * PTS Measurement Algorithm
+ * see section 3.9.1 of PTS Protocol: Binding to TNC IF-M Specification
+ *
+ * 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Reserved | Hash Algorithm Set |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ */
+
+#define PTS_MEAS_ALGO_SIZE 4
+#define PTS_MEAS_ALGO_RESERVED 0x0000
+
+/**
+ * Private data of an tcg_pts_attr_meas_algo_t object.
+ */
+struct private_tcg_pts_attr_meas_algo_t {
+
+ /**
+ * Public members of tcg_pts_attr_meas_algo_t
+ */
+ tcg_pts_attr_meas_algo_t public;
+
+ /**
+ * Vendor-specific attribute type
+ */
+ pen_type_t type;
+
+ /**
+ * Length of attribute value
+ */
+ size_t length;
+
+ /**
+ * Attribute value or segment
+ */
+ chunk_t value;
+
+ /**
+ * Noskip flag
+ */
+ bool noskip_flag;
+
+ /**
+ * Set of algorithms
+ */
+ pts_meas_algorithms_t algorithms;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+};
+
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
+ private_tcg_pts_attr_meas_algo_t *this)
+{
+ return this->type;
+}
+
+METHOD(pa_tnc_attr_t, get_value, chunk_t,
+ private_tcg_pts_attr_meas_algo_t *this)
+{
+ return this->value;
+}
+
+METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
+ private_tcg_pts_attr_meas_algo_t *this)
+{
+ return this->noskip_flag;
+}
+
+METHOD(pa_tnc_attr_t, set_noskip_flag,void,
+ private_tcg_pts_attr_meas_algo_t *this, bool noskip)
+{
+ this->noskip_flag = noskip;
+}
+
+METHOD(pa_tnc_attr_t, build, void,
+ private_tcg_pts_attr_meas_algo_t *this)
+{
+ bio_writer_t *writer;
+
+ if (this->value.ptr)
+ {
+ return;
+ }
+ writer = bio_writer_create(PTS_MEAS_ALGO_SIZE);
+ writer->write_uint16(writer, PTS_MEAS_ALGO_RESERVED);
+ writer->write_uint16(writer, this->algorithms);
+ this->value = writer->extract_buf(writer);
+ this->length = this->value.len;
+ writer->destroy(writer);
+}
+
+METHOD(pa_tnc_attr_t, process, status_t,
+ private_tcg_pts_attr_meas_algo_t *this, u_int32_t *offset)
+{
+ bio_reader_t *reader;
+ u_int16_t reserved, algorithms;
+
+ *offset = 0;
+
+ if (this->value.len < this->length)
+ {
+ return NEED_MORE;
+ }
+ if (this->value.len < PTS_MEAS_ALGO_SIZE)
+ {
+ DBG1(DBG_TNC, "insufficient data for PTS Measurement Algorithm");
+ return FAILED;
+ }
+ reader = bio_reader_create(this->value);
+ reader->read_uint16(reader, &reserved);
+ reader->read_uint16(reader, &algorithms);
+ this->algorithms = algorithms;
+ reader->destroy(reader);
+
+ return SUCCESS;
+}
+
+METHOD(pa_tnc_attr_t, add_segment, void,
+ private_tcg_pts_attr_meas_algo_t *this, chunk_t segment)
+{
+ this->value = chunk_cat("mc", this->value, segment);
+}
+
+METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
+ private_tcg_pts_attr_meas_algo_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.pa_tnc_attribute;
+}
+
+METHOD(pa_tnc_attr_t, destroy, void,
+ private_tcg_pts_attr_meas_algo_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ free(this->value.ptr);
+ free(this);
+ }
+}
+
+METHOD(tcg_pts_attr_meas_algo_t, get_algorithms, pts_meas_algorithms_t,
+ private_tcg_pts_attr_meas_algo_t *this)
+{
+ return this->algorithms;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *tcg_pts_attr_meas_algo_create(pts_meas_algorithms_t algorithms,
+ bool selection)
+{
+ private_tcg_pts_attr_meas_algo_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_algorithms = _get_algorithms,
+ },
+ .type = { PEN_TCG,
+ selection ? TCG_PTS_MEAS_ALGO_SELECTION : TCG_PTS_MEAS_ALGO },
+ .algorithms = algorithms,
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *tcg_pts_attr_meas_algo_create_from_data(size_t length,
+ chunk_t data,
+ bool selection)
+{
+ private_tcg_pts_attr_meas_algo_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_algorithms = _get_algorithms,
+ },
+ .type = { PEN_TCG,
+ selection ? TCG_PTS_MEAS_ALGO_SELECTION : TCG_PTS_MEAS_ALGO },
+ .length = length,
+ .value = chunk_clone(data),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
diff --git a/src/libimcv/tcg/pts/tcg_pts_attr_meas_algo.h b/src/libimcv/tcg/pts/tcg_pts_attr_meas_algo.h
new file mode 100644
index 000000000..bc15a9bb4
--- /dev/null
+++ b/src/libimcv/tcg/pts/tcg_pts_attr_meas_algo.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup tcg_pts_attr_meas_algo tcg_pts_attr_meas_algo
+ * @{ @ingroup tcg_attr
+ */
+
+#ifndef TCG_PTS_ATTR_MEAS_ALGO_H_
+#define TCG_PTS_ATTR_MEAS_ALGO_H_
+
+typedef struct tcg_pts_attr_meas_algo_t tcg_pts_attr_meas_algo_t;
+
+#include "tcg/tcg_attr.h"
+#include "pts/pts_meas_algo.h"
+#include "pa_tnc/pa_tnc_attr.h"
+
+/**
+ * Class implementing the TCG Measurement Algorithm Attribute
+ *
+ */
+struct tcg_pts_attr_meas_algo_t {
+
+ /**
+ * Public PA-TNC attribute interface
+ */
+ pa_tnc_attr_t pa_tnc_attribute;
+
+ /**
+ * Get PTS Measurement Algorithm Set
+ *
+ * @return set of algorithms
+ */
+ pts_meas_algorithms_t (*get_algorithms)(tcg_pts_attr_meas_algo_t *this);
+
+};
+
+/**
+ * Creates an tcg_pts_attr_meas_algo_t object
+ *
+ * @param algorithms set of algorithms
+ * @param selection TRUE if a selection
+ */
+pa_tnc_attr_t* tcg_pts_attr_meas_algo_create(pts_meas_algorithms_t algorithms,
+ bool selection);
+
+/**
+ * Creates an tcg_pts_attr_meas_algo_t object from received data
+ *
+ * @param length Total length of attribute value
+ * @param value Unparsed attribute value (might be a segment)
+ * @param selection TRUE if a selection
+ */
+pa_tnc_attr_t* tcg_pts_attr_meas_algo_create_from_data(size_t length,
+ chunk_t value,
+ bool selection);
+
+#endif /** TCG_PTS_ATTR_MEAS_ALGO_H_ @}*/
diff --git a/src/libimcv/tcg/pts/tcg_pts_attr_proto_caps.c b/src/libimcv/tcg/pts/tcg_pts_attr_proto_caps.c
new file mode 100644
index 000000000..0a562c0bc
--- /dev/null
+++ b/src/libimcv/tcg/pts/tcg_pts_attr_proto_caps.c
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2011-2012 Sansar Choinyambuu
+ * Copyright (C) 2011-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tcg_pts_attr_proto_caps.h"
+
+#include <pa_tnc/pa_tnc_msg.h>
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <utils/debug.h>
+
+typedef struct private_tcg_pts_attr_proto_caps_t private_tcg_pts_attr_proto_caps_t;
+
+/**
+ * PTS Protocol Capabilities
+ * see section 3.7 of PTS Protocol: Binding to TNC IF-M Specification
+ *
+ * 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Reserved |C|V|D|T|X|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ */
+
+#define PTS_PROTO_CAPS_SIZE 4
+#define PTS_PROTO_CAPS_RESERVED 0x0000
+
+/**
+ * Private data of an tcg_pts_attr_proto_caps_t object.
+ */
+struct private_tcg_pts_attr_proto_caps_t {
+
+ /**
+ * Public members of tcg_pts_attr_proto_caps_t
+ */
+ tcg_pts_attr_proto_caps_t public;
+
+ /**
+ * Vendor-specific attribute type
+ */
+ pen_type_t type;
+
+
+ /**
+ * Length of attribute value
+ */
+ size_t length;
+
+ /**
+ * Attribute value or segment
+ */
+ chunk_t value;
+
+ /**
+ * Noskip flag
+ */
+ bool noskip_flag;
+
+ /**
+ * Set of flags
+ */
+ pts_proto_caps_flag_t flags;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+};
+
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
+ private_tcg_pts_attr_proto_caps_t *this)
+{
+ return this->type;
+}
+
+METHOD(pa_tnc_attr_t, get_value, chunk_t,
+ private_tcg_pts_attr_proto_caps_t *this)
+{
+ return this->value;
+}
+
+METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
+ private_tcg_pts_attr_proto_caps_t *this)
+{
+ return this->noskip_flag;
+}
+
+METHOD(pa_tnc_attr_t, set_noskip_flag,void,
+ private_tcg_pts_attr_proto_caps_t *this, bool noskip)
+{
+ this->noskip_flag = noskip;
+}
+
+METHOD(pa_tnc_attr_t, build, void,
+ private_tcg_pts_attr_proto_caps_t *this)
+{
+ bio_writer_t *writer;
+
+ if (this->value.ptr)
+ {
+ return;
+ }
+ writer = bio_writer_create(PTS_PROTO_CAPS_SIZE);
+ writer->write_uint16(writer, PTS_PROTO_CAPS_RESERVED);
+ writer->write_uint16(writer, this->flags);
+
+ this->value = writer->extract_buf(writer);
+ this->length = this->value.len;
+ writer->destroy(writer);
+}
+
+METHOD(pa_tnc_attr_t, process, status_t,
+ private_tcg_pts_attr_proto_caps_t *this, u_int32_t *offset)
+{
+ bio_reader_t *reader;
+ u_int16_t reserved, flags;
+
+ *offset = 0;
+
+ if (this->value.len < this->length)
+ {
+ return NEED_MORE;
+ }
+ if (this->value.len < PTS_PROTO_CAPS_SIZE)
+ {
+ DBG1(DBG_TNC, "insufficient data for PTS Protocol Capabilities");
+ return FAILED;
+ }
+ reader = bio_reader_create(this->value);
+ reader->read_uint16(reader, &reserved);
+ reader->read_uint16(reader, &flags);
+ this->flags = flags;
+ reader->destroy(reader);
+
+ return SUCCESS;
+}
+
+METHOD(pa_tnc_attr_t, add_segment, void,
+ private_tcg_pts_attr_proto_caps_t *this, chunk_t segment)
+{
+ this->value = chunk_cat("mc", this->value, segment);
+}
+
+METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
+ private_tcg_pts_attr_proto_caps_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.pa_tnc_attribute;
+}
+
+METHOD(pa_tnc_attr_t, destroy, void,
+ private_tcg_pts_attr_proto_caps_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ free(this->value.ptr);
+ free(this);
+ }
+}
+
+METHOD(tcg_pts_attr_proto_caps_t, get_flags, pts_proto_caps_flag_t,
+ private_tcg_pts_attr_proto_caps_t *this)
+{
+ return this->flags;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *tcg_pts_attr_proto_caps_create(pts_proto_caps_flag_t flags,
+ bool request)
+{
+ private_tcg_pts_attr_proto_caps_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_flags = _get_flags,
+ },
+ .type = { PEN_TCG,
+ request ? TCG_PTS_REQ_PROTO_CAPS : TCG_PTS_PROTO_CAPS },
+ .flags = flags,
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *tcg_pts_attr_proto_caps_create_from_data(size_t length,
+ chunk_t data,
+ bool request)
+{
+ private_tcg_pts_attr_proto_caps_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_flags = _get_flags,
+ },
+ .type = { PEN_TCG,
+ request ? TCG_PTS_REQ_PROTO_CAPS : TCG_PTS_PROTO_CAPS },
+ .length = length,
+ .value = chunk_clone(data),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
diff --git a/src/libimcv/tcg/pts/tcg_pts_attr_proto_caps.h b/src/libimcv/tcg/pts/tcg_pts_attr_proto_caps.h
new file mode 100644
index 000000000..11ed22810
--- /dev/null
+++ b/src/libimcv/tcg/pts/tcg_pts_attr_proto_caps.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup tcg_pts_attr_proto_caps tcg_pts_attr_proto_caps
+ * @{ @ingroup tcg_attr
+ */
+
+#ifndef TCG_PTS_ATTR_PROTO_CAPS_H_
+#define TCG_PTS_ATTR_PROTO_CAPS_H_
+
+typedef struct tcg_pts_attr_proto_caps_t tcg_pts_attr_proto_caps_t;
+
+#include "tcg/tcg_attr.h"
+#include "pa_tnc/pa_tnc_attr.h"
+#include "pts/pts_proto_caps.h"
+
+/**
+ * Class implementing the TCG PTS Protocol Capabilities Attribute
+ */
+struct tcg_pts_attr_proto_caps_t {
+
+ /**
+ * Public PA-TNC attribute interface
+ */
+ pa_tnc_attr_t pa_tnc_attribute;
+
+ /**
+ * Get PTS procol capabilities flags
+ *
+ * @return set of flags
+ */
+ pts_proto_caps_flag_t (*get_flags)(tcg_pts_attr_proto_caps_t *this);
+
+};
+
+/**
+ * Creates an tcg_pts_attr_proto_caps_t object
+ *
+ * @param flags set of flags
+ * @param request TRUE for a PTS protocol capabilities request
+ */
+pa_tnc_attr_t* tcg_pts_attr_proto_caps_create(pts_proto_caps_flag_t flags,
+ bool request);
+
+/**
+ * Creates an tcg_pts_attr_proto_caps_t object from received data
+ *
+ * @param length Total length of attribute value
+ * @param value Unparsed attribute value (might be a segment)
+ * @param request TRUE for a PTS protocol capabilities request
+ */
+pa_tnc_attr_t* tcg_pts_attr_proto_caps_create_from_data(size_t length,
+ chunk_t value,
+ bool request);
+
+#endif /** TCG_PTS_ATTR_PROTO_CAPS_H_ @}*/
diff --git a/src/libimcv/tcg/pts/tcg_pts_attr_req_file_meas.c b/src/libimcv/tcg/pts/tcg_pts_attr_req_file_meas.c
new file mode 100644
index 000000000..a3c3ce56e
--- /dev/null
+++ b/src/libimcv/tcg/pts/tcg_pts_attr_req_file_meas.c
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2011-2012 Sansar Choinyambuu
+ * Copyright (C) 2011-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#define _GNU_SOURCE /* for stdndup() */
+#include <string.h>
+
+#include "tcg_pts_attr_req_file_meas.h"
+
+#include <pa_tnc/pa_tnc_msg.h>
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <utils/debug.h>
+
+typedef struct private_tcg_pts_attr_req_file_meas_t private_tcg_pts_attr_req_file_meas_t;
+
+/**
+ * Request File Measurement
+ * see section 3.19.1 of PTS Protocol: Binding to TNC IF-M Specification
+ *
+ * 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Flags | Reserved | Request ID |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Delimiter |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * ~ Fully Qualified File Pathname (Variable Length) ~
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+#define PTS_REQ_FILE_MEAS_SIZE 8
+#define PTS_REQ_FILE_MEAS_RESERVED 0x00
+#define PTS_REQ_FILE_MEAS_NO_FLAGS 0x00
+
+#define DIRECTORY_CONTENTS_FLAG (1<<7)
+
+/**
+ * Private data of an tcg_pts_attr_req_file_meas_t object.
+ */
+struct private_tcg_pts_attr_req_file_meas_t {
+
+ /**
+ * Public members of tcg_pts_attr_req_file_meas_t
+ */
+ tcg_pts_attr_req_file_meas_t public;
+
+ /**
+ * Vendor-specific attribute type
+ */
+ pen_type_t type;
+
+ /**
+ * Length of attribute value
+ */
+ size_t length;
+
+ /**
+ * Attribute value or segment
+ */
+ chunk_t value;
+
+ /**
+ * Noskip flag
+ */
+ bool noskip_flag;
+
+ /**
+ * Directory Contents flag
+ */
+ bool directory_flag;
+
+ /**
+ * Request ID
+ */
+ u_int16_t request_id;
+
+ /**
+ * UTF8 Encoding of Delimiter Character
+ */
+ u_int32_t delimiter;
+
+ /**
+ * Fully Qualified File Pathname
+ */
+ char *pathname;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+};
+
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
+ private_tcg_pts_attr_req_file_meas_t *this)
+{
+ return this->type;
+}
+
+METHOD(pa_tnc_attr_t, get_value, chunk_t,
+ private_tcg_pts_attr_req_file_meas_t *this)
+{
+ return this->value;
+}
+
+METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
+ private_tcg_pts_attr_req_file_meas_t *this)
+{
+ return this->noskip_flag;
+}
+
+METHOD(pa_tnc_attr_t, set_noskip_flag,void,
+ private_tcg_pts_attr_req_file_meas_t *this, bool noskip)
+{
+ this->noskip_flag = noskip;
+}
+
+METHOD(pa_tnc_attr_t, build, void,
+ private_tcg_pts_attr_req_file_meas_t *this)
+{
+ u_int8_t flags = PTS_REQ_FILE_MEAS_NO_FLAGS;
+ chunk_t pathname;
+ bio_writer_t *writer;
+
+ if (this->value.ptr)
+ {
+ return;
+ }
+ if (this->directory_flag)
+ {
+ flags |= DIRECTORY_CONTENTS_FLAG;
+ }
+ pathname = chunk_create(this->pathname, strlen(this->pathname));
+
+ writer = bio_writer_create(PTS_REQ_FILE_MEAS_SIZE);
+ writer->write_uint8 (writer, flags);
+ writer->write_uint8 (writer, PTS_REQ_FILE_MEAS_RESERVED);
+ writer->write_uint16(writer, this->request_id);
+ writer->write_uint32(writer, this->delimiter);
+ writer->write_data (writer, pathname);
+ this->value = writer->extract_buf(writer);
+ this->length = this->value.len;
+ writer->destroy(writer);
+}
+
+METHOD(pa_tnc_attr_t, process, status_t,
+ private_tcg_pts_attr_req_file_meas_t *this, u_int32_t *offset)
+{
+ bio_reader_t *reader;
+ u_int8_t flags;
+ u_int8_t reserved;
+ chunk_t pathname;
+
+ *offset = 0;
+
+ if (this->value.len < this->length)
+ {
+ return NEED_MORE;
+ }
+ if (this->value.len < PTS_REQ_FILE_MEAS_SIZE)
+ {
+ DBG1(DBG_TNC, "insufficient data for Request File Measurement");
+ return FAILED;
+ }
+
+ reader = bio_reader_create(this->value);
+ reader->read_uint8 (reader, &flags);
+ reader->read_uint8 (reader, &reserved);
+ reader->read_uint16(reader, &this->request_id);
+ reader->read_uint32(reader, &this->delimiter);
+ reader->read_data (reader, reader->remaining(reader), &pathname);
+
+ this->directory_flag = (flags & DIRECTORY_CONTENTS_FLAG) !=
+ PTS_REQ_FILE_MEAS_NO_FLAGS;
+ this->pathname = strndup(pathname.ptr, pathname.len);
+
+ reader->destroy(reader);
+ return SUCCESS;
+}
+
+METHOD(pa_tnc_attr_t, add_segment, void,
+ private_tcg_pts_attr_req_file_meas_t *this, chunk_t segment)
+{
+ this->value = chunk_cat("mc", this->value, segment);
+}
+
+METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
+ private_tcg_pts_attr_req_file_meas_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.pa_tnc_attribute;
+}
+
+METHOD(pa_tnc_attr_t, destroy, void,
+ private_tcg_pts_attr_req_file_meas_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ free(this->pathname);
+ free(this->value.ptr);
+ free(this);
+ }
+}
+
+METHOD(tcg_pts_attr_req_file_meas_t, get_directory_flag, bool,
+ private_tcg_pts_attr_req_file_meas_t *this)
+{
+ return this->directory_flag;
+}
+
+METHOD(tcg_pts_attr_req_file_meas_t, get_request_id, u_int16_t,
+ private_tcg_pts_attr_req_file_meas_t *this)
+{
+ return this->request_id;
+}
+
+METHOD(tcg_pts_attr_req_file_meas_t, get_delimiter, u_int32_t,
+ private_tcg_pts_attr_req_file_meas_t *this)
+{
+ return this->delimiter;
+}
+
+METHOD(tcg_pts_attr_req_file_meas_t, get_pathname, char*,
+ private_tcg_pts_attr_req_file_meas_t *this)
+{
+ return this->pathname;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *tcg_pts_attr_req_file_meas_create(bool directory_flag,
+ u_int16_t request_id,
+ u_int32_t delimiter,
+ char *pathname)
+{
+ private_tcg_pts_attr_req_file_meas_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_directory_flag = _get_directory_flag,
+ .get_request_id = _get_request_id,
+ .get_delimiter = _get_delimiter,
+ .get_pathname = _get_pathname,
+ },
+ .type = { PEN_TCG, TCG_PTS_REQ_FILE_MEAS },
+ .directory_flag = directory_flag,
+ .request_id = request_id,
+ .delimiter = delimiter,
+ .pathname = strdup(pathname),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *tcg_pts_attr_req_file_meas_create_from_data(size_t length,
+ chunk_t data)
+{
+ private_tcg_pts_attr_req_file_meas_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_directory_flag = _get_directory_flag,
+ .get_request_id = _get_request_id,
+ .get_delimiter = _get_delimiter,
+ .get_pathname = _get_pathname,
+ },
+ .type = { PEN_TCG, TCG_PTS_REQ_FILE_MEAS },
+ .length = length,
+ .value = chunk_clone(data),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
diff --git a/src/libimcv/tcg/pts/tcg_pts_attr_req_file_meas.h b/src/libimcv/tcg/pts/tcg_pts_attr_req_file_meas.h
new file mode 100644
index 000000000..20a54dfaf
--- /dev/null
+++ b/src/libimcv/tcg/pts/tcg_pts_attr_req_file_meas.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup tcg_pts_attr_req_file_meas tcg_pts_attr_req_file_meas
+ * @{ @ingroup tcg_attr
+ */
+
+#ifndef TCG_PTS_ATTR_REQ_FILE_MEAS_H_
+#define TCG_PTS_ATTR_REQ_FILE_MEAS_H_
+
+typedef struct tcg_pts_attr_req_file_meas_t tcg_pts_attr_req_file_meas_t;
+
+#include "tcg/tcg_attr.h"
+#include "pa_tnc/pa_tnc_attr.h"
+
+/**
+ * Class implementing the TCG PTS Request File Measurement attribute
+ *
+ */
+struct tcg_pts_attr_req_file_meas_t {
+
+ /**
+ * Public PA-TNC attribute interface
+ */
+ pa_tnc_attr_t pa_tnc_attribute;
+
+ /**
+ * Get flag for PTS Request File Measurement
+ *
+ * @return Directory Contents flag
+ */
+ bool (*get_directory_flag)(tcg_pts_attr_req_file_meas_t *this);
+
+ /**
+ * Get Request ID
+ *
+ * @return Request ID
+ */
+ u_int16_t (*get_request_id)(tcg_pts_attr_req_file_meas_t *this);
+
+ /**
+ * Get Delimiter
+ *
+ * @return UTF-8 encoding of a Delimiter Character
+ */
+ u_int32_t (*get_delimiter)(tcg_pts_attr_req_file_meas_t *this);
+
+ /**
+ * Get Fully Qualified File Pathname
+ *
+ * @return Pathname
+ */
+ char* (*get_pathname)(tcg_pts_attr_req_file_meas_t *this);
+
+};
+
+/**
+ * Creates an tcg_pts_attr_req_file_meas_t object
+ *
+ * @param directory_flag Directory Contents Flag
+ * @param request_id Request ID
+ * @param delimiter Delimiter Character
+ * @param pathname File Pathname
+ */
+pa_tnc_attr_t* tcg_pts_attr_req_file_meas_create(bool directory_flag,
+ u_int16_t request_id,
+ u_int32_t delimiter,
+ char *pathname);
+
+/**
+ * Creates an tcg_pts_attr_req_file_meas_t object from received data
+ *
+ * @param length Total length of attribute value
+ * @param value Unparsed attribute value (might be a segment)
+ */
+pa_tnc_attr_t* tcg_pts_attr_req_file_meas_create_from_data(size_t length,
+ chunk_t value);
+
+#endif /** TCG_PTS_ATTR_REQ_FILE_MEAS_H_ @}*/
diff --git a/src/libimcv/tcg/pts/tcg_pts_attr_req_file_meta.c b/src/libimcv/tcg/pts/tcg_pts_attr_req_file_meta.c
new file mode 100644
index 000000000..f6befa8b9
--- /dev/null
+++ b/src/libimcv/tcg/pts/tcg_pts_attr_req_file_meta.c
@@ -0,0 +1,296 @@
+/*
+ * Copyright (C) 2011-2012 Sansar Choinyambuu
+ * Copyright (C) 2011-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#define _GNU_SOURCE /* for stdndup() */
+#include <string.h>
+
+#include "tcg_pts_attr_req_file_meta.h"
+
+#include <pa_tnc/pa_tnc_msg.h>
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <utils/debug.h>
+
+typedef struct private_tcg_pts_attr_req_file_meta_t private_tcg_pts_attr_req_file_meta_t;
+
+/**
+ * Request File Metadata
+ * see section 3.17.1 of PTS Protocol: Binding to TNC IF-M Specification
+ *
+ * 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Flags | Delimiter | Reserved |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * ~ Fully Qualified File Pathname (Variable Length) ~
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+#define PTS_REQ_FILE_META_SIZE 4
+#define PTS_REQ_FILE_META_RESERVED 0x00
+#define PTS_REQ_FILE_META_NO_FLAGS 0x00
+
+#define DIRECTORY_CONTENTS_FLAG (1<<7)
+
+/**
+ * Private data of an tcg_pts_attr_req_file_meta_t object.
+ */
+struct private_tcg_pts_attr_req_file_meta_t {
+
+ /**
+ * Public members of tcg_pts_attr_req_file_meta_t
+ */
+ tcg_pts_attr_req_file_meta_t public;
+
+ /**
+ * Vendor-specific attribute type
+ */
+ pen_type_t type;
+
+ /**
+ * Length of attribute value
+ */
+ size_t length;
+
+ /**
+ * Attribute value or segment
+ */
+ chunk_t value;
+
+ /**
+ * Noskip flag
+ */
+ bool noskip_flag;
+
+ /**
+ * Directory Contents flag
+ */
+ bool directory_flag;
+
+ /**
+ * UTF8 Encoding of Delimiter Character
+ */
+ u_int8_t delimiter;
+
+ /**
+ * Fully Qualified File Pathname
+ */
+ char *pathname;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+};
+
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
+ private_tcg_pts_attr_req_file_meta_t *this)
+{
+ return this->type;
+}
+
+METHOD(pa_tnc_attr_t, get_value, chunk_t,
+ private_tcg_pts_attr_req_file_meta_t *this)
+{
+ return this->value;
+}
+
+METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
+ private_tcg_pts_attr_req_file_meta_t *this)
+{
+ return this->noskip_flag;
+}
+
+METHOD(pa_tnc_attr_t, set_noskip_flag,void,
+ private_tcg_pts_attr_req_file_meta_t *this, bool noskip)
+{
+ this->noskip_flag = noskip;
+}
+
+METHOD(pa_tnc_attr_t, build, void,
+ private_tcg_pts_attr_req_file_meta_t *this)
+{
+ u_int8_t flags = PTS_REQ_FILE_META_NO_FLAGS;
+ chunk_t pathname;
+ bio_writer_t *writer;
+
+ if (this->value.ptr)
+ {
+ return;
+ }
+ if (this->directory_flag)
+ {
+ flags |= DIRECTORY_CONTENTS_FLAG;
+ }
+ pathname = chunk_create(this->pathname, strlen(this->pathname));
+
+ writer = bio_writer_create(PTS_REQ_FILE_META_SIZE);
+ writer->write_uint8 (writer, flags);
+ writer->write_uint8 (writer, this->delimiter);
+ writer->write_uint16(writer, PTS_REQ_FILE_META_RESERVED);
+
+ writer->write_data (writer, pathname);
+ this->value = writer->extract_buf(writer);
+ this->length = this->value.len;
+ writer->destroy(writer);
+}
+
+METHOD(pa_tnc_attr_t, process, status_t,
+ private_tcg_pts_attr_req_file_meta_t *this, u_int32_t *offset)
+{
+ bio_reader_t *reader;
+ u_int8_t flags;
+ u_int16_t reserved;
+ chunk_t pathname;
+
+ *offset = 0;
+
+ if (this->value.len < this->length)
+ {
+ return NEED_MORE;
+ }
+ if (this->value.len < PTS_REQ_FILE_META_SIZE)
+ {
+ DBG1(DBG_TNC, "insufficient data for Request File Metadata");
+ }
+
+ reader = bio_reader_create(this->value);
+ reader->read_uint8 (reader, &flags);
+ reader->read_uint8 (reader, &this->delimiter);
+ reader->read_uint16(reader, &reserved);
+
+ reader->read_data (reader, reader->remaining(reader), &pathname);
+
+ this->directory_flag = (flags & DIRECTORY_CONTENTS_FLAG) !=
+ PTS_REQ_FILE_META_NO_FLAGS;
+ this->pathname = strndup(pathname.ptr, pathname.len);
+
+ reader->destroy(reader);
+ return SUCCESS;
+}
+
+METHOD(pa_tnc_attr_t, add_segment, void,
+ private_tcg_pts_attr_req_file_meta_t *this, chunk_t segment)
+{
+ this->value = chunk_cat("mc", this->value, segment);
+}
+
+METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
+ private_tcg_pts_attr_req_file_meta_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.pa_tnc_attribute;
+}
+
+METHOD(pa_tnc_attr_t, destroy, void,
+ private_tcg_pts_attr_req_file_meta_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ free(this->pathname);
+ free(this->value.ptr);
+ free(this);
+ }
+}
+
+METHOD(tcg_pts_attr_req_file_meta_t, get_directory_flag, bool,
+ private_tcg_pts_attr_req_file_meta_t *this)
+{
+ return this->directory_flag;
+}
+
+METHOD(tcg_pts_attr_req_file_meta_t, get_delimiter, u_int8_t,
+ private_tcg_pts_attr_req_file_meta_t *this)
+{
+ return this->delimiter;
+}
+
+METHOD(tcg_pts_attr_req_file_meta_t, get_pathname, char*,
+ private_tcg_pts_attr_req_file_meta_t *this)
+{
+ return this->pathname;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *tcg_pts_attr_req_file_meta_create(bool directory_flag,
+ u_int8_t delimiter,
+ char *pathname)
+{
+ private_tcg_pts_attr_req_file_meta_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_directory_flag = _get_directory_flag,
+ .get_delimiter = _get_delimiter,
+ .get_pathname = _get_pathname,
+ },
+ .type = { PEN_TCG, TCG_PTS_REQ_FILE_META },
+ .directory_flag = directory_flag,
+ .delimiter = delimiter,
+ .pathname = strdup(pathname),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *tcg_pts_attr_req_file_meta_create_from_data(size_t length,
+ chunk_t data)
+{
+ private_tcg_pts_attr_req_file_meta_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_directory_flag = _get_directory_flag,
+ .get_delimiter = _get_delimiter,
+ .get_pathname = _get_pathname,
+ },
+ .type = { PEN_TCG, TCG_PTS_REQ_FILE_META },
+ .length = length,
+ .value = chunk_clone(data),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
diff --git a/src/libimcv/tcg/pts/tcg_pts_attr_req_file_meta.h b/src/libimcv/tcg/pts/tcg_pts_attr_req_file_meta.h
new file mode 100644
index 000000000..c2f1cca74
--- /dev/null
+++ b/src/libimcv/tcg/pts/tcg_pts_attr_req_file_meta.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup tcg_pts_attr_req_file_meta tcg_pts_attr_req_file_meta
+ * @{ @ingroup tcg_attr
+ */
+
+#ifndef TCG_PTS_ATTR_REQ_FILE_META_H_
+#define TCG_PTS_ATTR_REQ_FILE_META_H_
+
+typedef struct tcg_pts_attr_req_file_meta_t tcg_pts_attr_req_file_meta_t;
+
+#include "tcg/tcg_attr.h"
+#include "pa_tnc/pa_tnc_attr.h"
+
+/**
+ * Class implementing the TCG PTS Request File Metadata attribute
+ *
+ */
+struct tcg_pts_attr_req_file_meta_t {
+
+ /**
+ * Public PA-TNC attribute interface
+ */
+ pa_tnc_attr_t pa_tnc_attribute;
+
+ /**
+ * Get directory flag for PTS Request File Metadata
+ *
+ * @return Directory Contents flag
+ */
+ bool (*get_directory_flag)(tcg_pts_attr_req_file_meta_t *this);
+
+ /**
+ * Get Delimiter
+ *
+ * @return UTF-8 encoding of a Delimiter Character
+ */
+ u_int8_t (*get_delimiter)(tcg_pts_attr_req_file_meta_t *this);
+
+ /**
+ * Get Fully Qualified File Pathname
+ *
+ * @return Pathname
+ */
+ char* (*get_pathname)(tcg_pts_attr_req_file_meta_t *this);
+
+};
+
+/**
+ * Creates an tcg_pts_attr_req_file_meta_t object
+ *
+ * @param directory_flag Directory Contents Flag
+ * @param delimiter Delimiter Character
+ * @param pathname File Pathname
+ */
+pa_tnc_attr_t* tcg_pts_attr_req_file_meta_create(bool directory_flag,
+ u_int8_t delimiter,
+ char *pathname);
+
+/**
+ * Creates an tcg_pts_attr_req_file_meta_t object from received data
+ *
+ * @param length Total length of attribute value
+ * @param value Unparsed attribute value (might be a segment)
+ */
+pa_tnc_attr_t* tcg_pts_attr_req_file_meta_create_from_data(size_t length,
+ chunk_t value);
+
+#endif /** TCG_PTS_ATTR_REQ_FILE_META_H_ @}*/
diff --git a/src/libimcv/tcg/pts/tcg_pts_attr_req_func_comp_evid.c b/src/libimcv/tcg/pts/tcg_pts_attr_req_func_comp_evid.c
new file mode 100644
index 000000000..03891104c
--- /dev/null
+++ b/src/libimcv/tcg/pts/tcg_pts_attr_req_func_comp_evid.c
@@ -0,0 +1,389 @@
+/*
+ * Copyright (C) 2011-2012 Sansar Choinyambuu
+ * Copyright (C) 2011-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tcg_pts_attr_req_func_comp_evid.h"
+
+#include <pa_tnc/pa_tnc_msg.h>
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <collections/linked_list.h>
+#include <utils/debug.h>
+
+typedef struct private_tcg_pts_attr_req_func_comp_evid_t private_tcg_pts_attr_req_func_comp_evid_t;
+
+/**
+ * Request Functional Component Evidence
+ * see section 3.14.1 of PTS Protocol: Binding to TNC IF-M Specification
+ *
+ * 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Flags | Sub-component Depth (for Component #1) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Component Functional Name #1 |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Component Functional Name #1 |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | ........ |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Flags | Sub-component Depth (for Component #N) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Component Functional Name #N |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Component Functional Name #N |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+/**
+ * Component Functional Name Structure
+ * (see section 5.1 of PTS Protocol: Binding to TNC IF-M Specification)
+ *
+ * 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Component Functional Name Vendor ID |Fam| Qualifier |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Component Functional Name |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+#define PTS_REQ_FUNC_COMP_EVID_SIZE 12
+#define PTS_REQ_FUNC_COMP_FAMILY_MASK 0xC0
+
+/**
+ * Private data of an tcg_pts_attr_req_func_comp_evid_t object.
+ */
+struct private_tcg_pts_attr_req_func_comp_evid_t {
+
+ /**
+ * Public members of tcg_pts_attr_req_func_comp_evid_t
+ */
+ tcg_pts_attr_req_func_comp_evid_t public;
+
+ /**
+ * Vendor-specific attribute type
+ */
+ pen_type_t type;
+
+ /**
+ * Length of attribute value
+ */
+ size_t length;
+
+ /**
+ * Attribute value or segment
+ */
+ chunk_t value;
+
+ /**
+ * Noskip flag
+ */
+ bool noskip_flag;
+
+ /**
+ * List of Functional Components
+ */
+ linked_list_t *list;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+};
+
+typedef struct entry_t entry_t;
+
+/**
+ * Functional component entry
+ */
+struct entry_t {
+ u_int8_t flags;
+ u_int32_t depth;
+ pts_comp_func_name_t *name;
+};
+
+/**
+ * Enumerate functional component entries
+ */
+static bool entry_filter(void *null, entry_t **entry, u_int8_t *flags,
+ void *i2, u_int32_t *depth, void *i3,
+ pts_comp_func_name_t **name)
+{
+ *flags = (*entry)->flags;
+ *depth = (*entry)->depth;
+ *name = (*entry)->name;
+
+ return TRUE;
+}
+
+/**
+ * Free an entry_t object
+ */
+static void free_entry(entry_t *this)
+{
+ if (this)
+ {
+ this->name->destroy(this->name);
+ free(this);
+ }
+}
+
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
+ private_tcg_pts_attr_req_func_comp_evid_t *this)
+{
+ return this->type;
+}
+
+METHOD(pa_tnc_attr_t, get_value, chunk_t,
+ private_tcg_pts_attr_req_func_comp_evid_t *this)
+{
+ return this->value;
+}
+
+METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
+ private_tcg_pts_attr_req_func_comp_evid_t *this)
+{
+ return this->noskip_flag;
+}
+
+METHOD(pa_tnc_attr_t, set_noskip_flag,void,
+ private_tcg_pts_attr_req_func_comp_evid_t *this, bool noskip)
+{
+ this->noskip_flag = noskip;
+}
+
+METHOD(pa_tnc_attr_t, build, void,
+ private_tcg_pts_attr_req_func_comp_evid_t *this)
+{
+ bio_writer_t *writer;
+ enumerator_t *enumerator;
+ entry_t *entry;
+
+ if (this->value.ptr)
+ {
+ return;
+ }
+ writer = bio_writer_create(PTS_REQ_FUNC_COMP_EVID_SIZE);
+
+ enumerator = this->list->create_enumerator(this->list);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ writer->write_uint8 (writer, entry->flags);
+ writer->write_uint24(writer, entry->depth);
+ writer->write_uint24(writer, entry->name->get_vendor_id(entry->name));
+ writer->write_uint8 (writer, entry->name->get_qualifier(entry->name));
+ writer->write_uint32(writer, entry->name->get_name(entry->name));
+ }
+ enumerator->destroy(enumerator);
+
+ this->value = writer->extract_buf(writer);
+ this->length = this->value.len;
+ writer->destroy(writer);
+}
+
+METHOD(pa_tnc_attr_t, process, status_t,
+ private_tcg_pts_attr_req_func_comp_evid_t *this, u_int32_t *offset)
+{
+ bio_reader_t *reader;
+ u_int32_t depth, vendor_id, name;
+ u_int8_t flags, fam_and_qualifier, qualifier;
+ status_t status = FAILED;
+ entry_t *entry = NULL;
+
+ *offset = 0;
+
+ if (this->value.len < this->length)
+ {
+ return NEED_MORE;
+ }
+ if (this->value.len < PTS_REQ_FUNC_COMP_EVID_SIZE)
+ {
+ DBG1(DBG_TNC, "insufficient data for Request Functional "
+ "Component Evidence");
+ return FAILED;
+ }
+ reader = bio_reader_create(this->value);
+
+ while (reader->remaining(reader))
+ {
+ if (!reader->read_uint8(reader, &flags))
+ {
+ DBG1(DBG_TNC, "insufficient data for PTS Request Functional "
+ "Component Evidence Flags");
+ goto end;
+ }
+ if (!reader->read_uint24(reader, &depth))
+ {
+ DBG1(DBG_TNC, "insufficient data for PTS Request Functional "
+ "Component Evidence Sub Component Depth");
+ goto end;
+ }
+ if (!reader->read_uint24(reader, &vendor_id))
+ {
+ DBG1(DBG_TNC, "insufficient data for PTS Request Functional "
+ "Component Evidence Component Name Vendor ID");
+ goto end;
+ }
+ if (!reader->read_uint8(reader, &fam_and_qualifier))
+ {
+ DBG1(DBG_TNC, "insufficient data for PTS Request Functional "
+ "Component Evidence Family and Qualifier");
+ goto end;
+ }
+ if (fam_and_qualifier & PTS_REQ_FUNC_COMP_FAMILY_MASK)
+ {
+ DBG1(DBG_TNC, "the Functional Name Encoding Family "
+ "is not Binary Enumeration");
+ goto end;
+ }
+ if (!reader->read_uint32(reader, &name))
+ {
+ DBG1(DBG_TNC, "insufficient data for PTS Request Functional "
+ "Component Evidence Component Functional Name");
+ goto end;
+ }
+ qualifier = fam_and_qualifier & ~PTS_REQ_FUNC_COMP_FAMILY_MASK;
+
+ entry = malloc_thing(entry_t);
+ entry->flags = flags;
+ entry->depth = depth;
+ entry->name = pts_comp_func_name_create(vendor_id, name, qualifier);
+
+ this->list->insert_last(this->list, entry);
+ }
+ status = SUCCESS;
+
+end:
+ reader->destroy(reader);
+ return status;
+}
+
+METHOD(pa_tnc_attr_t, add_segment, void,
+ private_tcg_pts_attr_req_func_comp_evid_t *this, chunk_t segment)
+{
+ this->value = chunk_cat("mc", this->value, segment);
+}
+
+METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
+ private_tcg_pts_attr_req_func_comp_evid_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.pa_tnc_attribute;
+}
+
+METHOD(pa_tnc_attr_t, destroy, void,
+ private_tcg_pts_attr_req_func_comp_evid_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ this->list->destroy_function(this->list, (void *)free_entry);
+ free(this->value.ptr);
+ free(this);
+ }
+}
+
+METHOD(tcg_pts_attr_req_func_comp_evid_t, add_component, void,
+ private_tcg_pts_attr_req_func_comp_evid_t *this, u_int8_t flags,
+ u_int32_t depth, pts_comp_func_name_t *name)
+{
+ entry_t *entry;
+
+ entry = malloc_thing(entry_t);
+ entry->flags = flags;
+ entry->depth = depth;
+ entry->name = name->clone(name);
+ this->list->insert_last(this->list, entry);
+}
+
+METHOD(tcg_pts_attr_req_func_comp_evid_t, get_count, int,
+ private_tcg_pts_attr_req_func_comp_evid_t *this)
+{
+ return this->list->get_count(this->list);
+}
+
+METHOD(tcg_pts_attr_req_func_comp_evid_t, create_enumerator, enumerator_t*,
+ private_tcg_pts_attr_req_func_comp_evid_t *this)
+{
+ return enumerator_create_filter(this->list->create_enumerator(this->list),
+ (void*)entry_filter, NULL, NULL);
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *tcg_pts_attr_req_func_comp_evid_create(void)
+{
+ private_tcg_pts_attr_req_func_comp_evid_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .add_component = _add_component,
+ .get_count = _get_count,
+ .create_enumerator = _create_enumerator,
+ },
+ .type = { PEN_TCG, TCG_PTS_REQ_FUNC_COMP_EVID },
+ .list = linked_list_create(),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *tcg_pts_attr_req_func_comp_evid_create_from_data(size_t length,
+ chunk_t data)
+{
+ private_tcg_pts_attr_req_func_comp_evid_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .add_component = _add_component,
+ .get_count = _get_count,
+ .create_enumerator = _create_enumerator,
+ },
+ .type = { PEN_TCG, TCG_PTS_REQ_FUNC_COMP_EVID },
+ .length = length,
+ .list = linked_list_create(),
+ .value = chunk_clone(data),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
diff --git a/src/libimcv/tcg/pts/tcg_pts_attr_req_func_comp_evid.h b/src/libimcv/tcg/pts/tcg_pts_attr_req_func_comp_evid.h
new file mode 100644
index 000000000..2f8657ed2
--- /dev/null
+++ b/src/libimcv/tcg/pts/tcg_pts_attr_req_func_comp_evid.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup tcg_pts_attr_req_func_comp_evid tcg_pts_attr_req_func_comp_evid
+ * @{ @ingroup tcg_attr
+ */
+
+#ifndef TCG_PTS_ATTR_REQ_FUNC_COMP_EVID_H_
+#define TCG_PTS_ATTR_REQ_FUNC_COMP_EVID_H_
+
+typedef struct tcg_pts_attr_req_func_comp_evid_t tcg_pts_attr_req_func_comp_evid_t;
+
+#include "tcg/tcg_attr.h"
+#include "pts/components/pts_comp_func_name.h"
+#include "pa_tnc/pa_tnc_attr.h"
+
+/**
+ * Class implementing the TCG PTS Request Functional Component Evidence attribute
+ *
+ */
+struct tcg_pts_attr_req_func_comp_evid_t {
+
+ /**
+ * Public PA-TNC attribute interface
+ */
+ pa_tnc_attr_t pa_tnc_attribute;
+
+ /**
+ * Add a component to the Functional Component Evidence Request
+ *
+ * @param flags Component Evidence Request Flags
+ * @param depth Sub-component Depth
+ * @param name Functional Component Name
+ */
+ void (*add_component)(tcg_pts_attr_req_func_comp_evid_t *this,
+ u_int8_t flags, u_int32_t depth,
+ pts_comp_func_name_t *name);
+
+ /**
+ * Returns the number of Functional Component entries
+ *
+ * @return Number of entries
+ */
+ int (*get_count)(tcg_pts_attr_req_func_comp_evid_t *this);
+
+ /**
+ * Enumerator over Functional Component entries
+ *
+ * @return Entry enumerator
+ */
+ enumerator_t* (*create_enumerator)(tcg_pts_attr_req_func_comp_evid_t *this);
+
+};
+
+/**
+ * Creates a tcg_pts_attr_req_func_comp_evid_t object
+ */
+pa_tnc_attr_t* tcg_pts_attr_req_func_comp_evid_create(void);
+
+/**
+ * Creates a tcg_pts_attr_req_func_comp_evid_t object from received data
+ *
+ * @param length Total length of attribute value
+ * @param value Unparsed attribute value (might be a segment)
+ */
+pa_tnc_attr_t* tcg_pts_attr_req_func_comp_evid_create_from_data(size_t length,
+ chunk_t value);
+
+#endif /** TCG_PTS_ATTR_REQ_FUNC_COMP_EVID_H_ @}*/
diff --git a/src/libimcv/tcg/pts/tcg_pts_attr_simple_comp_evid.c b/src/libimcv/tcg/pts/tcg_pts_attr_simple_comp_evid.c
new file mode 100644
index 000000000..d94ee89a5
--- /dev/null
+++ b/src/libimcv/tcg/pts/tcg_pts_attr_simple_comp_evid.c
@@ -0,0 +1,532 @@
+/*
+ * Copyright (C) 2011-2012 Sansar Choinyambuu
+ * Copyright (C) 2011-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tcg_pts_attr_simple_comp_evid.h"
+
+#include <pa_tnc/pa_tnc_msg.h>
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <utils/debug.h>
+
+#include <time.h>
+
+typedef struct private_tcg_pts_attr_simple_comp_evid_t private_tcg_pts_attr_simple_comp_evid_t;
+
+/**
+ * Simple Component Evidence
+ * see section 3.15.1 of PTS Protocol: Binding to TNC IF-M Specification
+ *
+ * 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Flags | Sub-Component Depth |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Specific Functional Component |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Specific Functional Component |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Measure. Type | Extended into PCR |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Hash Algorithm | PCR Transform | Reserved |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Measurement Date/Time |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Measurement Date/Time |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Measurement Date/Time |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Measurement Date/Time |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Measurement Date/Time |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Optional Policy URI Length | Opt. Verification Policy URI ~
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * ~ Optional Verification Policy URI ~
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Optional PCR Length | Optional PCR Before Value ~
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * ~ Optional PCR Before Value (Variable Length) ~
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * ~ Optional PCR After Value (Variable Length) ~
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * ~ Component Measurement (Variable Length) ~
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+/**
+ * Specific Functional Component -> Component Functional Name Structure
+ * see section 5.1 of PTS Protocol: Binding to TNC IF-M Specification
+ *
+ * 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Component Functional Name Vendor ID |Fam| Qualifier |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Component Functional Name |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ */
+
+#define PTS_SIMPLE_COMP_EVID_SIZE 40
+#define PTS_SIMPLE_COMP_EVID_MEAS_TIME_SIZE 20
+#define PTS_SIMPLE_COMP_EVID_RESERVED 0x00
+#define PTS_SIMPLE_COMP_EVID_FAMILY_MASK 0xC0
+#define PTS_SIMPLE_COMP_EVID_VALIDATION_MASK 0x60
+#define PTS_SIMPLE_COMP_EVID_MEAS_TYPE (1<<7)
+#define PTS_SIMPLE_COMP_EVID_FLAG_PCR (1<<7)
+
+static char *utc_undefined_time_str = "0000-00-00T00:00:00Z";
+
+/**
+ * Private data of an tcg_pts_attr_simple_comp_evid_t object.
+ */
+struct private_tcg_pts_attr_simple_comp_evid_t {
+
+ /**
+ * Public members of tcg_pts_attr_simple_comp_evid_t
+ */
+ tcg_pts_attr_simple_comp_evid_t public;
+
+ /**
+ * Vendor-specific attribute type
+ */
+ pen_type_t type;
+
+ /**
+ * Length of attribute value
+ */
+ size_t length;
+
+ /**
+ * Attribute value or segment
+ */
+ chunk_t value;
+
+ /**
+ * Noskip flag
+ */
+ bool noskip_flag;
+
+ /**
+ * PTS Component Evidence
+ */
+ pts_comp_evidence_t *evidence;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+};
+
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
+ private_tcg_pts_attr_simple_comp_evid_t *this)
+{
+ return this->type;
+}
+
+METHOD(pa_tnc_attr_t, get_value, chunk_t,
+ private_tcg_pts_attr_simple_comp_evid_t *this)
+{
+ return this->value;
+}
+
+METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
+ private_tcg_pts_attr_simple_comp_evid_t *this)
+{
+ return this->noskip_flag;
+}
+
+METHOD(pa_tnc_attr_t, set_noskip_flag,void,
+ private_tcg_pts_attr_simple_comp_evid_t *this, bool noskip)
+{
+ this->noskip_flag = noskip;
+}
+
+/**
+ * Convert time_t to Simple Component Evidence UTS string format
+ */
+void measurement_time_to_utc(time_t measurement_time, chunk_t *utc_time)
+{
+ struct tm t;
+
+ if (measurement_time == UNDEFINED_TIME)
+ {
+ utc_time->ptr = utc_undefined_time_str;
+ }
+ else
+ {
+ gmtime_r(&measurement_time, &t);
+ sprintf(utc_time->ptr, "%04d-%02d-%02dT%02d:%02d:%02dZ",
+ t.tm_year + 1900, t.tm_mon + 1, t.tm_mday,
+ t.tm_hour, t.tm_min, t.tm_sec);
+ }
+}
+
+METHOD(pa_tnc_attr_t, build, void,
+ private_tcg_pts_attr_simple_comp_evid_t *this)
+{
+ bio_writer_t *writer;
+ bool has_pcr_info;
+ char utc_time_buf[25], *policy_uri;
+ u_int8_t flags;
+ u_int16_t len;
+ u_int32_t depth, extended_pcr;
+ pts_comp_func_name_t *name;
+ pts_meas_algorithms_t hash_algorithm;
+ pts_pcr_transform_t transform;
+ pts_comp_evid_validation_t validation;
+ time_t measurement_time;
+ chunk_t measurement, utc_time, pcr_before, pcr_after;
+
+ if (this->value.ptr)
+ {
+ return;
+ }
+
+ /* Extract parameters from comp_evidence_t object */
+ name = this->evidence->get_comp_func_name(this->evidence,
+ &depth);
+ measurement = this->evidence->get_measurement(this->evidence,
+ &extended_pcr, &hash_algorithm, &transform,
+ &measurement_time);
+ has_pcr_info = this->evidence->get_pcr_info(this->evidence,
+ &pcr_before, &pcr_after);
+ validation = this->evidence->get_validation(this->evidence,
+ &policy_uri);
+
+ /* Determine the flags to set*/
+ flags = validation;
+ if (has_pcr_info)
+ {
+ flags |= PTS_SIMPLE_COMP_EVID_FLAG_PCR;
+ }
+
+ utc_time = chunk_create(utc_time_buf, PTS_SIMPLE_COMP_EVID_MEAS_TIME_SIZE);
+ measurement_time_to_utc(measurement_time, &utc_time);
+
+ writer = bio_writer_create(PTS_SIMPLE_COMP_EVID_SIZE);
+
+ writer->write_uint8 (writer, flags);
+ writer->write_uint24(writer, depth);
+ writer->write_uint24(writer, name->get_vendor_id(name));
+ writer->write_uint8 (writer, name->get_qualifier(name));
+ writer->write_uint32(writer, name->get_name(name));
+ writer->write_uint8 (writer, PTS_SIMPLE_COMP_EVID_MEAS_TYPE);
+ writer->write_uint24(writer, extended_pcr);
+ writer->write_uint16(writer, hash_algorithm);
+ writer->write_uint8 (writer, transform);
+ writer->write_uint8 (writer, PTS_SIMPLE_COMP_EVID_RESERVED);
+ writer->write_data (writer, utc_time);
+
+ /* Optional fields */
+ if (validation == PTS_COMP_EVID_VALIDATION_FAILED ||
+ validation == PTS_COMP_EVID_VALIDATION_PASSED)
+ {
+ len = strlen(policy_uri);
+ writer->write_uint16(writer, len);
+ writer->write_data (writer, chunk_create(policy_uri, len));
+ }
+ if (has_pcr_info)
+ {
+ writer->write_uint16(writer, pcr_before.len);
+ writer->write_data (writer, pcr_before);
+ writer->write_data (writer, pcr_after);
+ }
+
+ writer->write_data(writer, measurement);
+
+ this->value = writer->extract_buf(writer);
+ this->length = this->value.len;
+ writer->destroy(writer);
+}
+
+static const int days[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
+static const int tm_leap_1970 = 477;
+
+/**
+ * Convert Simple Component Evidence UTS string format to time_t
+ */
+bool measurement_time_from_utc(time_t *measurement_time, chunk_t utc_time)
+{
+ int tm_year, tm_mon, tm_day, tm_days, tm_hour, tm_min, tm_sec, tm_secs;
+ int tm_leap_4, tm_leap_100, tm_leap_400, tm_leap;
+
+ if (memeq(utc_undefined_time_str, utc_time.ptr, utc_time.len))
+ {
+ *measurement_time = 0;
+ return TRUE;
+ }
+ if (sscanf(utc_time.ptr, "%4d-%2d-%2dT%2d:%2d:%2dZ",
+ &tm_year, &tm_mon, &tm_day, &tm_hour, &tm_min, &tm_sec) != 6)
+ {
+ return FALSE;
+ }
+
+ /* representation of months as 0..11 */
+ tm_mon--;
+
+ /* representation of days as 0..30 */
+ tm_day--;
+
+ /* number of leap years between last year and 1970? */
+ tm_leap_4 = (tm_year - 1) / 4;
+ tm_leap_100 = tm_leap_4 / 25;
+ tm_leap_400 = tm_leap_100 / 4;
+ tm_leap = tm_leap_4 - tm_leap_100 + tm_leap_400 - tm_leap_1970;
+
+ /* if date later then February, is the current year a leap year? */
+ if (tm_mon > 1 && (tm_year % 4 == 0) &&
+ (tm_year % 100 != 0 || tm_year % 400 == 0))
+ {
+ tm_leap++;
+ }
+ tm_days = 365 * (tm_year - 1970) + days[tm_mon] + tm_day + tm_leap;
+ tm_secs = 60 * (60 * (24 * tm_days + tm_hour) + tm_min) + tm_sec;
+
+ *measurement_time = tm_secs;
+ return TRUE;
+}
+
+METHOD(pa_tnc_attr_t, process, status_t,
+ private_tcg_pts_attr_simple_comp_evid_t *this, u_int32_t *offset)
+{
+ bio_reader_t *reader;
+ pts_comp_func_name_t *name;
+ u_int8_t flags, fam_and_qualifier, qualifier, reserved;
+ u_int8_t measurement_type, transform, validation;
+ u_int16_t hash_algorithm, len;
+ u_int32_t depth, vendor_id, comp_name, extended_pcr;
+ chunk_t measurement, utc_time, policy_uri, pcr_before, pcr_after;
+ time_t measurement_time;
+ bool has_pcr_info = FALSE, has_validation = FALSE;
+ status_t status = FAILED;
+
+ *offset = 0;
+
+ if (this->value.len < this->length)
+ {
+ return NEED_MORE;
+ }
+ if (this->value.len < PTS_SIMPLE_COMP_EVID_SIZE)
+ {
+ DBG1(DBG_TNC, "insufficient data for Simple Component Evidence");
+ }
+ reader = bio_reader_create(this->value);
+
+ reader->read_uint8 (reader, &flags);
+ reader->read_uint24(reader, &depth);
+ reader->read_uint24(reader, &vendor_id);
+ reader->read_uint8 (reader, &fam_and_qualifier);
+ reader->read_uint32(reader, &comp_name);
+ reader->read_uint8 (reader, &measurement_type);
+ reader->read_uint24(reader, &extended_pcr);
+ reader->read_uint16(reader, &hash_algorithm);
+ reader->read_uint8 (reader, &transform);
+ reader->read_uint8 (reader, &reserved);
+ reader->read_data (reader, PTS_SIMPLE_COMP_EVID_MEAS_TIME_SIZE, &utc_time);
+
+ if (measurement_type != PTS_SIMPLE_COMP_EVID_MEAS_TYPE)
+ {
+ DBG1(DBG_TNC, "unsupported Measurement Type in "
+ "Simple Component Evidence");
+ *offset = 12;
+ reader->destroy(reader);
+ return FAILED;
+ }
+ if (!measurement_time_from_utc(&measurement_time, utc_time))
+ {
+ DBG1(DBG_TNC, "invalid Measurement Time field in "
+ "Simple Component Evidence");
+ *offset = 20;
+ reader->destroy(reader);
+ return FAILED;
+ }
+ validation = flags & PTS_SIMPLE_COMP_EVID_VALIDATION_MASK;
+ qualifier = fam_and_qualifier & ~PTS_SIMPLE_COMP_EVID_FAMILY_MASK;
+
+ /* Is optional Policy URI field included? */
+ if (validation == PTS_COMP_EVID_VALIDATION_FAILED ||
+ validation == PTS_COMP_EVID_VALIDATION_PASSED)
+ {
+ if (!reader->read_uint16(reader, &len))
+ {
+ DBG1(DBG_TNC, "insufficient data for PTS Simple Component Evidence "
+ "Verification Policy URI Length");
+ goto end;
+ }
+ if (!reader->read_data(reader, len, &policy_uri))
+ {
+ DBG1(DBG_TNC, "insufficient data for PTS Simple Component Evidence "
+ "Verification Policy URI");
+ goto end;
+ }
+ has_validation = TRUE;
+ }
+
+ /* Are optional PCR value fields included? */
+ if (flags & PTS_SIMPLE_COMP_EVID_FLAG_PCR)
+ {
+ if (!reader->read_uint16(reader, &len))
+ {
+ DBG1(DBG_TNC, "insufficient data for PTS Simple Component Evidence "
+ "PCR Value length");
+ goto end;
+ }
+ if (!reader->read_data(reader, len, &pcr_before))
+ {
+ DBG1(DBG_TNC, "insufficient data for PTS Simple Component Evidence "
+ "PCR Before Value");
+ goto end;
+ }
+ if (!reader->read_data(reader, len, &pcr_after))
+ {
+ DBG1(DBG_TNC, "insufficient data for PTS Simple Component Evidence "
+ "PCR After Value");
+ goto end;
+ }
+ has_pcr_info = TRUE;
+ }
+
+ /* Measurement field comes at the very end */
+ reader->read_data(reader,reader->remaining(reader), &measurement);
+ reader->destroy(reader);
+
+ /* Create Component Functional Name object */
+ name = pts_comp_func_name_create(vendor_id, comp_name, qualifier);
+
+ /* Create Component Evidence object */
+ measurement = chunk_clone(measurement);
+ this->evidence = pts_comp_evidence_create(name, depth, extended_pcr,
+ hash_algorithm, transform,
+ measurement_time, measurement);
+
+ /* Add options */
+ if (has_validation)
+ {
+ char buf[BUF_LEN];
+ size_t len;
+
+ len = min(policy_uri.len, BUF_LEN-1);
+ memcpy(buf, policy_uri.ptr, len);
+ buf[len] = '\0';
+ this->evidence->set_validation(this->evidence, validation, buf);
+ }
+ if (has_pcr_info)
+ {
+ pcr_before = chunk_clone(pcr_before);
+ pcr_after = chunk_clone(pcr_after);
+ this->evidence->set_pcr_info(this->evidence, pcr_before, pcr_after);
+ }
+
+ return SUCCESS;
+
+end:
+ reader->destroy(reader);
+ return status;
+}
+
+METHOD(pa_tnc_attr_t, add_segment, void,
+ private_tcg_pts_attr_simple_comp_evid_t *this, chunk_t segment)
+{
+ this->value = chunk_cat("mc", this->value, segment);
+}
+
+METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
+ private_tcg_pts_attr_simple_comp_evid_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.pa_tnc_attribute;
+}
+
+METHOD(pa_tnc_attr_t, destroy, void,
+ private_tcg_pts_attr_simple_comp_evid_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ DESTROY_IF(this->evidence);
+ free(this->value.ptr);
+ free(this);
+ }
+}
+
+METHOD(tcg_pts_attr_simple_comp_evid_t, get_comp_evidence, pts_comp_evidence_t*,
+ private_tcg_pts_attr_simple_comp_evid_t *this)
+{
+ return this->evidence;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *tcg_pts_attr_simple_comp_evid_create(pts_comp_evidence_t *evid)
+{
+ private_tcg_pts_attr_simple_comp_evid_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_comp_evidence = _get_comp_evidence,
+ },
+ .type = { PEN_TCG, TCG_PTS_SIMPLE_COMP_EVID },
+ .evidence = evid,
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *tcg_pts_attr_simple_comp_evid_create_from_data(size_t length,
+ chunk_t data)
+{
+ private_tcg_pts_attr_simple_comp_evid_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_comp_evidence = _get_comp_evidence,
+ },
+ .type = { PEN_TCG, TCG_PTS_SIMPLE_COMP_EVID },
+ .length = length,
+ .value = chunk_clone(data),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
diff --git a/src/libimcv/tcg/pts/tcg_pts_attr_simple_comp_evid.h b/src/libimcv/tcg/pts/tcg_pts_attr_simple_comp_evid.h
new file mode 100644
index 000000000..c08adb8c9
--- /dev/null
+++ b/src/libimcv/tcg/pts/tcg_pts_attr_simple_comp_evid.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup tcg_pts_attr_simple_comp_evid tcg_pts_attr_simple_comp_evid
+ * @{ @ingroup tcg_attr
+ */
+
+#ifndef TCG_PTS_ATTR_SIMPLE_COMP_EVID_H_
+#define TCG_PTS_ATTR_SIMPLE_COMP_EVID_H_
+
+typedef struct tcg_pts_attr_simple_comp_evid_t tcg_pts_attr_simple_comp_evid_t;
+
+#include "tcg/tcg_attr.h"
+#include "pts/components/pts_comp_evidence.h"
+#include "pa_tnc/pa_tnc_attr.h"
+
+/**
+ * Class implementing the TCG PTS Simple Component Evidence attribute
+ *
+ */
+struct tcg_pts_attr_simple_comp_evid_t {
+
+ /**
+ * Public PA-TNC attribute interface
+ */
+ pa_tnc_attr_t pa_tnc_attribute;
+
+ /**
+ * Get Component Evidence
+ *
+ * @return Component Evidence
+ */
+ pts_comp_evidence_t* (*get_comp_evidence)(tcg_pts_attr_simple_comp_evid_t *this);
+
+};
+
+/**
+ * Creates an tcg_pts_attr_simple_comp_evid_t object
+ *
+ * @param evid Component Evidence
+ */
+pa_tnc_attr_t* tcg_pts_attr_simple_comp_evid_create(pts_comp_evidence_t *evid);
+
+/**
+ * Creates an tcg_pts_attr_simple_comp_evid_t object from received data
+ *
+ * @param length Total length of attribute value
+ * @param value Unparsed attribute value (might be a segment)
+ */
+pa_tnc_attr_t* tcg_pts_attr_simple_comp_evid_create_from_data(size_t length,
+ chunk_t value);
+
+#endif /** TCG_PTS_ATTR_SIMPLE_COMP_EVID_H_ @}*/
diff --git a/src/libimcv/tcg/pts/tcg_pts_attr_simple_evid_final.c b/src/libimcv/tcg/pts/tcg_pts_attr_simple_evid_final.c
new file mode 100644
index 000000000..cfeaec6e9
--- /dev/null
+++ b/src/libimcv/tcg/pts/tcg_pts_attr_simple_evid_final.c
@@ -0,0 +1,405 @@
+/*
+ * Copyright (C) 2011-2012 Sansar Choinyambuu
+ * Copyright (C) 2011-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tcg_pts_attr_simple_evid_final.h"
+#include "pts/pts_simple_evid_final.h"
+
+#include <pa_tnc/pa_tnc_msg.h>
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <utils/debug.h>
+
+typedef struct private_tcg_pts_attr_simple_evid_final_t private_tcg_pts_attr_simple_evid_final_t;
+
+/**
+ * Simple Evidence Final
+ * see section 3.15.2 of PTS Protocol: Binding to TNC IF-M Specification
+ *
+ * 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Flags | Reserved | Optional Composite Hash Alg |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Optional TPM PCR Composite Length |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * ~ Optional TPM PCR Composite (Variable Length) ~
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Optional TPM Quote Signature Length |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * ~ Optional TPM Quote Signature (Variable Length) ~
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * ~ Optional Evidence Signature (Variable Length) ~
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+#define PTS_SIMPLE_EVID_FINAL_SIZE 2
+#define PTS_SIMPLE_EVID_FINAL_RESERVED 0x00
+#define PTS_SIMPLE_EVID_FINAL_FLAG_MASK 0xC0
+/**
+ * Private data of an tcg_pts_attr_simple_evid_final_t object.
+ */
+struct private_tcg_pts_attr_simple_evid_final_t {
+
+ /**
+ * Public members of tcg_pts_attr_simple_evid_final_t
+ */
+ tcg_pts_attr_simple_evid_final_t public;
+
+ /**
+ * Vendor-specific attribute type
+ */
+ pen_type_t type;
+
+ /**
+ * Length of attribute value
+ */
+ size_t length;
+
+ /**
+ * Attribute value or segment
+ */
+ chunk_t value;
+
+ /**
+ * Noskip flag
+ */
+ bool noskip_flag;
+
+ /**
+ * Set of flags for Simple Evidence Final
+ */
+ u_int8_t flags;
+
+ /**
+ * Optional Composite Hash Algorithm
+ */
+ pts_meas_algorithms_t comp_hash_algorithm;
+
+ /**
+ * Optional TPM PCR Composite
+ */
+ chunk_t pcr_comp;
+
+ /**
+ * Optional TPM Quote Signature
+ */
+ chunk_t tpm_quote_sig;
+
+ /**
+ * Is Evidence Signature included?
+ */
+ bool has_evid_sig;
+
+ /**
+ * Optional Evidence Signature
+ */
+ chunk_t evid_sig;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+};
+
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
+ private_tcg_pts_attr_simple_evid_final_t *this)
+{
+ return this->type;
+}
+
+METHOD(pa_tnc_attr_t, get_value, chunk_t,
+ private_tcg_pts_attr_simple_evid_final_t *this)
+{
+ return this->value;
+}
+
+METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
+ private_tcg_pts_attr_simple_evid_final_t *this)
+{
+ return this->noskip_flag;
+}
+
+METHOD(pa_tnc_attr_t, add_segment, void,
+ private_tcg_pts_attr_simple_evid_final_t *this, chunk_t segment)
+{
+ this->value = chunk_cat("mc", this->value, segment);
+}
+
+METHOD(pa_tnc_attr_t, set_noskip_flag,void,
+ private_tcg_pts_attr_simple_evid_final_t *this, bool noskip)
+{
+ this->noskip_flag = noskip;
+}
+
+METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
+ private_tcg_pts_attr_simple_evid_final_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.pa_tnc_attribute;
+}
+
+METHOD(pa_tnc_attr_t, destroy, void,
+ private_tcg_pts_attr_simple_evid_final_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ free(this->value.ptr);
+ free(this->pcr_comp.ptr);
+ free(this->tpm_quote_sig.ptr);
+ free(this->evid_sig.ptr);
+ free(this);
+ }
+}
+
+METHOD(pa_tnc_attr_t, build, void,
+ private_tcg_pts_attr_simple_evid_final_t *this)
+{
+ bio_writer_t *writer;
+ u_int8_t flags;
+
+ if (this->value.ptr)
+ {
+ return;
+ }
+ flags = this->flags & PTS_SIMPLE_EVID_FINAL_FLAG_MASK;
+
+ if (this->has_evid_sig)
+ {
+ flags |= PTS_SIMPLE_EVID_FINAL_EVID_SIG;
+ }
+
+ writer = bio_writer_create(PTS_SIMPLE_EVID_FINAL_SIZE);
+ writer->write_uint8 (writer, flags);
+ writer->write_uint8 (writer, PTS_SIMPLE_EVID_FINAL_RESERVED);
+
+ /** Optional Composite Hash Algorithm field is always present
+ * Field has value of all zeroes if not used.
+ * Implemented adhering the suggestion of Paul Sangster 28.Oct.2011
+ */
+ writer->write_uint16(writer, this->comp_hash_algorithm);
+
+ /* Optional fields */
+ if (this->flags != PTS_SIMPLE_EVID_FINAL_NO)
+ {
+ writer->write_uint32 (writer, this->pcr_comp.len);
+ writer->write_data (writer, this->pcr_comp);
+
+ writer->write_uint32 (writer, this->tpm_quote_sig.len);
+ writer->write_data (writer, this->tpm_quote_sig);
+ }
+
+ if (this->has_evid_sig)
+ {
+ writer->write_data (writer, this->evid_sig);
+ }
+
+ this->value = writer->extract_buf(writer);
+ this->length = this->value.len;
+ writer->destroy(writer);
+}
+
+METHOD(pa_tnc_attr_t, process, status_t,
+ private_tcg_pts_attr_simple_evid_final_t *this, u_int32_t *offset)
+{
+ bio_reader_t *reader;
+ u_int8_t flags, reserved;
+ u_int16_t algorithm;
+ u_int32_t pcr_comp_len, tpm_quote_sig_len, evid_sig_len;
+ status_t status = FAILED;
+
+ *offset = 0;
+
+ if (this->value.len < this->length)
+ {
+ return NEED_MORE;
+ }
+ if (this->value.len < PTS_SIMPLE_EVID_FINAL_SIZE)
+ {
+ DBG1(DBG_TNC, "insufficient data for Simple Evidence Final");
+ return FAILED;
+ }
+ reader = bio_reader_create(this->value);
+
+ reader->read_uint8(reader, &flags);
+ reader->read_uint8(reader, &reserved);
+
+ this->flags = flags & PTS_SIMPLE_EVID_FINAL_FLAG_MASK;
+
+ this->has_evid_sig = (flags & PTS_SIMPLE_EVID_FINAL_EVID_SIG) != 0;
+
+ /** Optional Composite Hash Algorithm field is always present
+ * Field has value of all zeroes if not used.
+ * Implemented adhering the suggestion of Paul Sangster 28.Oct.2011
+ */
+
+ reader->read_uint16(reader, &algorithm);
+ this->comp_hash_algorithm = algorithm;
+
+ /* Optional Composite Hash Algorithm and TPM PCR Composite fields */
+ if (this->flags != PTS_SIMPLE_EVID_FINAL_NO)
+ {
+ if (!reader->read_uint32(reader, &pcr_comp_len))
+ {
+ DBG1(DBG_TNC, "insufficient data for PTS Simple Evidence Final "
+ "PCR Composite Length");
+ goto end;
+ }
+ if (!reader->read_data(reader, pcr_comp_len, &this->pcr_comp))
+ {
+ DBG1(DBG_TNC, "insufficient data for PTS Simple Evidence Final "
+ "PCR Composite");
+ goto end;
+ }
+ this->pcr_comp = chunk_clone(this->pcr_comp);
+
+ if (!reader->read_uint32(reader, &tpm_quote_sig_len))
+ {
+ DBG1(DBG_TNC, "insufficient data for PTS Simple Evidence Final "
+ "TPM Quote Singature Length");
+ goto end;
+ }
+ if (!reader->read_data(reader, tpm_quote_sig_len, &this->tpm_quote_sig))
+ {
+ DBG1(DBG_TNC, "insufficient data for PTS Simple Evidence Final "
+ "TPM Quote Singature");
+ goto end;
+ }
+ this->tpm_quote_sig = chunk_clone(this->tpm_quote_sig);
+ }
+
+ /* Optional Evidence Signature field */
+ if (this->has_evid_sig)
+ {
+ evid_sig_len = reader->remaining(reader);
+ reader->read_data(reader, evid_sig_len, &this->evid_sig);
+ this->evid_sig = chunk_clone(this->evid_sig);
+ }
+
+ reader->destroy(reader);
+ return SUCCESS;
+
+end:
+ reader->destroy(reader);
+ return status;
+}
+
+METHOD(tcg_pts_attr_simple_evid_final_t, get_quote_info, u_int8_t,
+ private_tcg_pts_attr_simple_evid_final_t *this,
+ pts_meas_algorithms_t *comp_hash_algo, chunk_t *pcr_comp, chunk_t *tpm_quote_sig)
+{
+ if (comp_hash_algo)
+ {
+ *comp_hash_algo = this->comp_hash_algorithm;
+ }
+ if (pcr_comp)
+ {
+ *pcr_comp = this->pcr_comp;
+ }
+ if (tpm_quote_sig)
+ {
+ *tpm_quote_sig = this->tpm_quote_sig;
+ }
+ return this->flags;
+}
+
+METHOD(tcg_pts_attr_simple_evid_final_t, get_evid_sig, bool,
+ private_tcg_pts_attr_simple_evid_final_t *this, chunk_t *evid_sig)
+{
+ if (evid_sig)
+ {
+ *evid_sig = this->evid_sig;
+ }
+ return this->has_evid_sig;
+}
+
+METHOD(tcg_pts_attr_simple_evid_final_t, set_evid_sig, void,
+ private_tcg_pts_attr_simple_evid_final_t *this, chunk_t evid_sig)
+{
+ this->evid_sig = evid_sig;
+ this->has_evid_sig = TRUE;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *tcg_pts_attr_simple_evid_final_create(u_int8_t flags,
+ pts_meas_algorithms_t comp_hash_algorithm,
+ chunk_t pcr_comp, chunk_t tpm_quote_sig)
+{
+ private_tcg_pts_attr_simple_evid_final_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_quote_info = _get_quote_info,
+ .get_evid_sig = _get_evid_sig,
+ .set_evid_sig = _set_evid_sig,
+ },
+ .type = { PEN_TCG, TCG_PTS_SIMPLE_EVID_FINAL },
+ .flags = flags,
+ .comp_hash_algorithm = comp_hash_algorithm,
+ .pcr_comp = pcr_comp,
+ .tpm_quote_sig = tpm_quote_sig,
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *tcg_pts_attr_simple_evid_final_create_from_data(size_t length,
+ chunk_t data)
+{
+ private_tcg_pts_attr_simple_evid_final_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_quote_info = _get_quote_info,
+ .get_evid_sig = _get_evid_sig,
+ .set_evid_sig = _set_evid_sig,
+ },
+ .type = { PEN_TCG, TCG_PTS_SIMPLE_EVID_FINAL },
+ .length = length,
+ .value = chunk_clone(data),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
diff --git a/src/libimcv/tcg/pts/tcg_pts_attr_simple_evid_final.h b/src/libimcv/tcg/pts/tcg_pts_attr_simple_evid_final.h
new file mode 100644
index 000000000..8343b5b30
--- /dev/null
+++ b/src/libimcv/tcg/pts/tcg_pts_attr_simple_evid_final.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup tcg_pts_attr_simple_evid_final tcg_pts_attr_simple_evid_final
+ * @{ @ingroup tcg_attr
+ */
+
+#ifndef TCG_PTS_ATTR_SIMPLE_EVID_FINAL_H_
+#define TCG_PTS_ATTR_SIMPLE_EVID_FINAL_H_
+
+typedef struct tcg_pts_attr_simple_evid_final_t tcg_pts_attr_simple_evid_final_t;
+
+#include "tcg/tcg_attr.h"
+#include "tcg_pts_attr_meas_algo.h"
+#include "pa_tnc/pa_tnc_attr.h"
+
+/**
+ * Class implementing the TCG PTS Simple Evidence Final attribute
+ *
+ */
+struct tcg_pts_attr_simple_evid_final_t {
+
+ /**
+ * Public PA-TNC attribute interface
+ */
+ pa_tnc_attr_t pa_tnc_attribute;
+
+ /**
+ * Get Optional PCR Composite and TPM Quote Signature
+ *
+ * @param comp_hash_algo Optional Composite Hash Algorithm
+ * @param pcr_comp Optional PCR Composite
+ * @param tpm_quote sig Optional TPM Quote Signature
+ * @return PTS_SIMPLE_EVID_FINAL flags
+ */
+ u_int8_t (*get_quote_info)(tcg_pts_attr_simple_evid_final_t *this,
+ pts_meas_algorithms_t *comp_hash_algo,
+ chunk_t *pcr_comp, chunk_t *tpm_quote_sig);
+
+ /**
+ * Get Optional Evidence Signature
+ *
+ * @param evid_sig Optional Evidence Signature
+ * @return TRUE if Evidence Signature is available
+ */
+ bool (*get_evid_sig)(tcg_pts_attr_simple_evid_final_t *this,
+ chunk_t *evid_sig);
+
+ /**
+ * Set Optional Evidence Signature
+ *
+ * @param vid_sig Optional Evidence Signature
+ */
+ void (*set_evid_sig)(tcg_pts_attr_simple_evid_final_t *this,
+ chunk_t evid_sig);
+
+};
+
+/**
+ * Creates an tcg_pts_attr_simple_evid_final_t object
+ *
+ * @param flags Set of flags
+ * @param comp_hash_algorithm Composite Hash Algorithm
+ * @param pcr_comp Optional TPM PCR Composite
+ * @param tpm_quote_sign Optional TPM Quote Signature
+ */
+pa_tnc_attr_t* tcg_pts_attr_simple_evid_final_create(
+ u_int8_t flags,
+ pts_meas_algorithms_t comp_hash_algorithm,
+ chunk_t pcr_comp,
+ chunk_t tpm_quote_sign);
+
+/**
+ * Creates an tcg_pts_attr_simple_evid_final_t object from received data
+ *
+ * @param length Total length of attribute value
+ * @param value Unparsed attribute value (might be a segment)
+ */
+pa_tnc_attr_t* tcg_pts_attr_simple_evid_final_create_from_data(size_t length,
+ chunk_t value);
+
+#endif /** TCG_PTS_ATTR_SIMPLE_EVID_FINAL_H_ @}*/
diff --git a/src/libimcv/tcg/pts/tcg_pts_attr_tpm_version_info.c b/src/libimcv/tcg/pts/tcg_pts_attr_tpm_version_info.c
new file mode 100644
index 000000000..db877e9c5
--- /dev/null
+++ b/src/libimcv/tcg/pts/tcg_pts_attr_tpm_version_info.c
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) 2011-2012 Sansar Choinyambuu
+ * Copyright (C) 2011-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tcg_pts_attr_tpm_version_info.h"
+
+#include <pa_tnc/pa_tnc_msg.h>
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <utils/debug.h>
+
+typedef struct private_tcg_pts_attr_tpm_version_info_t private_tcg_pts_attr_tpm_version_info_t;
+
+/**
+ * TPM Version Information
+ * see section 3.11 of PTS Protocol: Binding to TNC IF-M Specification
+ *
+ * 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ *
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | TPM Version Information (Variable Length) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * see TPM Structure Specification Part 2, section 21.6: TPM_CAP_VERSION_INFO
+ */
+
+#define PTS_TPM_VER_INFO_SIZE 4
+
+/**
+ * Private data of an tcg_pts_attr_tpm_version_info_t object.
+ */
+struct private_tcg_pts_attr_tpm_version_info_t {
+
+ /**
+ * Public members of tcg_pts_attr_tpm_version_info_t
+ */
+ tcg_pts_attr_tpm_version_info_t public;
+
+ /**
+ * Vendor-specific attribute type
+ */
+ pen_type_t type;
+
+ /**
+ * Length of attribute value
+ */
+ size_t length;
+
+ /**
+ * Attribute value or segment
+ */
+ chunk_t value;
+
+ /**
+ * Noskip flag
+ */
+ bool noskip_flag;
+
+ /**
+ * TPM Version Information
+ */
+ chunk_t tpm_version_info;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+};
+
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
+ private_tcg_pts_attr_tpm_version_info_t *this)
+{
+ return this->type;
+}
+
+METHOD(pa_tnc_attr_t, get_value, chunk_t,
+ private_tcg_pts_attr_tpm_version_info_t *this)
+{
+ return this->value;
+}
+
+METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
+ private_tcg_pts_attr_tpm_version_info_t *this)
+{
+ return this->noskip_flag;
+}
+
+METHOD(pa_tnc_attr_t, set_noskip_flag,void,
+ private_tcg_pts_attr_tpm_version_info_t *this, bool noskip)
+{
+ this->noskip_flag = noskip;
+}
+
+METHOD(pa_tnc_attr_t, build, void,
+ private_tcg_pts_attr_tpm_version_info_t *this)
+{
+ bio_writer_t *writer;
+
+ if (this->value.ptr)
+ {
+ return;
+ }
+ writer = bio_writer_create(PTS_TPM_VER_INFO_SIZE);
+ writer->write_data(writer, this->tpm_version_info);
+
+ this->value = writer->extract_buf(writer);
+ this->length = this->value.len;
+ writer->destroy(writer);
+}
+
+METHOD(pa_tnc_attr_t, process, status_t,
+ private_tcg_pts_attr_tpm_version_info_t *this, u_int32_t *offset)
+{
+ bio_reader_t *reader;
+
+ *offset = 0;
+
+ if (this->value.len < this->length)
+ {
+ return NEED_MORE;
+ }
+ if (this->value.len < PTS_TPM_VER_INFO_SIZE)
+ {
+ DBG1(DBG_TNC, "insufficient data for TPM Version Information");
+ return FAILED;
+ }
+ reader = bio_reader_create(this->value);
+ reader->read_data (reader, this->value.len, &this->tpm_version_info);
+ this->tpm_version_info = chunk_clone(this->tpm_version_info);
+ reader->destroy(reader);
+
+ return SUCCESS;
+}
+
+METHOD(pa_tnc_attr_t, add_segment, void,
+ private_tcg_pts_attr_tpm_version_info_t *this, chunk_t segment)
+{
+ this->value = chunk_cat("mc", this->value, segment);
+}
+
+METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
+ private_tcg_pts_attr_tpm_version_info_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.pa_tnc_attribute;
+}
+
+METHOD(pa_tnc_attr_t, destroy, void,
+ private_tcg_pts_attr_tpm_version_info_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ free(this->value.ptr);
+ free(this->tpm_version_info.ptr);
+ free(this);
+ }
+}
+
+METHOD(tcg_pts_attr_tpm_version_info_t, get_tpm_version_info, chunk_t,
+ private_tcg_pts_attr_tpm_version_info_t *this)
+{
+ return this->tpm_version_info;
+}
+
+METHOD(tcg_pts_attr_tpm_version_info_t, set_tpm_version_info, void,
+ private_tcg_pts_attr_tpm_version_info_t *this,
+ chunk_t tpm_version_info)
+{
+ this->tpm_version_info = tpm_version_info;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *tcg_pts_attr_tpm_version_info_create(chunk_t tpm_version_info)
+{
+ private_tcg_pts_attr_tpm_version_info_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_tpm_version_info = _get_tpm_version_info,
+ .set_tpm_version_info = _set_tpm_version_info,
+ },
+ .type = { PEN_TCG, TCG_PTS_TPM_VERSION_INFO },
+ .tpm_version_info = chunk_clone(tpm_version_info),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *tcg_pts_attr_tpm_version_info_create_from_data(size_t length,
+ chunk_t data)
+{
+ private_tcg_pts_attr_tpm_version_info_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_tpm_version_info = _get_tpm_version_info,
+ .set_tpm_version_info = _set_tpm_version_info,
+ },
+ .type = { PEN_TCG, TCG_PTS_TPM_VERSION_INFO },
+ .length = length,
+ .value = chunk_clone(data),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
diff --git a/src/libimcv/tcg/pts/tcg_pts_attr_tpm_version_info.h b/src/libimcv/tcg/pts/tcg_pts_attr_tpm_version_info.h
new file mode 100644
index 000000000..d87d72b22
--- /dev/null
+++ b/src/libimcv/tcg/pts/tcg_pts_attr_tpm_version_info.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup tcg_pts_attr_tpm_version_info tcg_pts_attr_tpm_version_info
+ * @{ @ingroup tcg_attr
+ */
+
+#ifndef TCG_PTS_ATTR_TPM_VERSION_INFO_H_
+#define TCG_PTS_ATTR_TPM_VERSION_INFO_H_
+
+typedef struct tcg_pts_attr_tpm_version_info_t tcg_pts_attr_tpm_version_info_t;
+
+#include "tcg/tcg_attr.h"
+#include "pa_tnc/pa_tnc_attr.h"
+
+/**
+ * Class implementing the TCG PTS TPM Version Info Attribute
+ *
+ */
+struct tcg_pts_attr_tpm_version_info_t {
+
+ /**
+ * Public PA-TNC attribute interface
+ */
+ pa_tnc_attr_t pa_tnc_attribute;
+
+ /**
+ * Get TPM Version Info
+ *
+ * @return TPM version info
+ */
+ chunk_t (*get_tpm_version_info)(tcg_pts_attr_tpm_version_info_t *this);
+
+ /**
+ * Set TPM Version Info
+ *
+ * @param tpm_version_info TPM version info
+ */
+ void (*set_tpm_version_info)(tcg_pts_attr_tpm_version_info_t *this,
+ chunk_t tpm_version_info);
+};
+
+/**
+ * Creates an tcg_pts_attr_tpm_version_info_t object
+ *
+ * @param tpm_version_info TPM version info
+ */
+pa_tnc_attr_t* tcg_pts_attr_tpm_version_info_create(chunk_t tpm_version_info);
+
+/**
+ * Creates an tcg_pts_attr_tpm_version_info_t object from received data
+ *
+ * @param length Total length of attribute value
+ * @param value Unparsed attribute value (might be a segment)
+ */
+pa_tnc_attr_t* tcg_pts_attr_tpm_version_info_create_from_data(size_t length,
+ chunk_t value);
+
+#endif /** TCG_PTS_ATTR_TPM_VERSION_INFO_H_ @}*/
diff --git a/src/libimcv/tcg/pts/tcg_pts_attr_unix_file_meta.c b/src/libimcv/tcg/pts/tcg_pts_attr_unix_file_meta.c
new file mode 100644
index 000000000..7c176fdf6
--- /dev/null
+++ b/src/libimcv/tcg/pts/tcg_pts_attr_unix_file_meta.c
@@ -0,0 +1,372 @@
+/*
+ * Copyright (C) 2011-2012 Sansar Choinyambuu
+ * Copyright (C) 2011-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#define _GNU_SOURCE /* for stdndup() */
+#include <string.h>
+
+#include "tcg_pts_attr_unix_file_meta.h"
+
+#include <pa_tnc/pa_tnc_msg.h>
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <collections/linked_list.h>
+#include <utils/debug.h>
+
+typedef struct private_tcg_pts_attr_file_meta_t private_tcg_pts_attr_file_meta_t;
+
+/**
+ * Unix-Style File Metadata
+ * see section 3.17.3 of PTS Protocol: Binding to TNC IF-M Specification
+ *
+ * 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Number of Files included |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Number of Files included |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | File metadata Length | Type | Reserved |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | File Size |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | File Size |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | File Create Time |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | File Create Time |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Last Modify Time |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Last Modify Time |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Last Access Time |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Last Access Time |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | File Owner ID |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | File Owner ID |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | File Group ID |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | File Group ID |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * ~ Filename (Variable Length) ~
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * ...........................
+ */
+
+#define PTS_FILE_META_SIZE 8
+#define PTS_FILE_MEAS_RESERVED 0x00
+#define PTS_FILE_METADATA_SIZE 52
+
+/**
+ * Private data of an tcg_pts_attr_file_meta_t object.
+ */
+struct private_tcg_pts_attr_file_meta_t {
+
+ /**
+ * Public members of tcg_pts_attr_file_meta_t
+ */
+ tcg_pts_attr_file_meta_t public;
+
+ /**
+ * Vendor-specific attribute type
+ */
+ pen_type_t type;
+
+ /**
+ * Length of attribute value
+ */
+ size_t length;
+
+ /**
+ * Attribute value or segment
+ */
+ chunk_t value;
+
+ /**
+ * Noskip flag
+ */
+ bool noskip_flag;
+
+ /**
+ * PTS File Metadata
+ */
+ pts_file_meta_t *metadata;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+};
+
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
+ private_tcg_pts_attr_file_meta_t *this)
+{
+ return this->type;
+}
+
+METHOD(pa_tnc_attr_t, get_value, chunk_t,
+ private_tcg_pts_attr_file_meta_t *this)
+{
+ return this->value;
+}
+
+METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
+ private_tcg_pts_attr_file_meta_t *this)
+{
+ return this->noskip_flag;
+}
+
+METHOD(pa_tnc_attr_t, set_noskip_flag,void,
+ private_tcg_pts_attr_file_meta_t *this, bool noskip)
+{
+ this->noskip_flag = noskip;
+}
+
+METHOD(pa_tnc_attr_t, build, void,
+ private_tcg_pts_attr_file_meta_t *this)
+{
+ bio_writer_t *writer;
+ enumerator_t *enumerator;
+ pts_file_metadata_t *entry;
+ u_int64_t number_of_files;
+
+ if (this->value.ptr)
+ {
+ return;
+ }
+ number_of_files = this->metadata->get_file_count(this->metadata);
+ writer = bio_writer_create(PTS_FILE_META_SIZE);
+
+ writer->write_uint64(writer, number_of_files);
+
+ enumerator = this->metadata->create_enumerator(this->metadata);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ writer->write_uint16(writer, PTS_FILE_METADATA_SIZE +
+ strlen(entry->filename));
+ writer->write_uint8 (writer, entry->type);
+ writer->write_uint8 (writer, PTS_FILE_MEAS_RESERVED);
+ writer->write_uint64(writer, entry->filesize);
+ writer->write_uint64(writer, entry->created);
+ writer->write_uint64(writer, entry->modified);
+ writer->write_uint64(writer, entry->accessed);
+ writer->write_uint64(writer, entry->owner);
+ writer->write_uint64(writer, entry->group);
+ writer->write_data (writer, chunk_create(entry->filename,
+ strlen(entry->filename)));
+ }
+ enumerator->destroy(enumerator);
+
+ this->value = writer->extract_buf(writer);
+ this->length = this->value.len;
+ writer->destroy(writer);
+}
+
+METHOD(pa_tnc_attr_t, process, status_t,
+ private_tcg_pts_attr_file_meta_t *this, u_int32_t *offset)
+{
+ bio_reader_t *reader;
+ pts_file_metadata_t *entry;
+ u_int8_t type, reserved;
+ u_int16_t len;
+ u_int64_t number_of_files, filesize, created, modified, accessed;
+ u_int64_t owner, group;
+ chunk_t filename;
+ status_t status = FAILED;
+
+ *offset = 0;
+
+ if (this->value.len < this->length)
+ {
+ return NEED_MORE;
+ }
+ if (this->value.len < PTS_FILE_META_SIZE)
+ {
+ DBG1(DBG_TNC, "insufficient data for PTS Unix-Style file metadata header");
+ return FAILED;
+ }
+ reader = bio_reader_create(this->value);
+ reader->read_uint64(reader, &number_of_files);
+
+ this->metadata = pts_file_meta_create();
+
+ while (number_of_files--)
+ {
+ if (!reader->read_uint16(reader, &len))
+ {
+ DBG1(DBG_TNC, "insufficient data for PTS file metadata length");
+ goto end;
+ }
+ if (!reader->read_uint8(reader, &type))
+ {
+ DBG1(DBG_TNC, "insufficient data for file type");
+ goto end;
+ }
+ if (!reader->read_uint8(reader, &reserved))
+ {
+ DBG1(DBG_TNC, "insufficient data for reserved field");
+ goto end;
+ }
+ if (!reader->read_uint64(reader, &filesize))
+ {
+ DBG1(DBG_TNC, "insufficient data for file size");
+ goto end;
+ }
+ if (!reader->read_uint64(reader, &created))
+ {
+ DBG1(DBG_TNC, "insufficient data for file create time");
+ goto end;
+ }
+ if (!reader->read_uint64(reader, &modified))
+ {
+ DBG1(DBG_TNC, "insufficient data for last modify time");
+ goto end;
+ }
+ if (!reader->read_uint64(reader, &accessed))
+ {
+ DBG1(DBG_TNC, "insufficient data for last access time");
+ goto end;
+ }
+ if (!reader->read_uint64(reader, &owner))
+ {
+ DBG1(DBG_TNC, "insufficient data for owner id");
+ goto end;
+ }
+ if (!reader->read_uint64(reader, &group))
+ {
+ DBG1(DBG_TNC, "insufficient data for group id");
+ goto end;
+ }
+ if (!reader->read_data(reader, len - PTS_FILE_METADATA_SIZE, &filename))
+ {
+ DBG1(DBG_TNC, "insufficient data for filename");
+ goto end;
+ }
+
+ entry = malloc_thing(pts_file_metadata_t);
+ entry->type = type;
+ entry->filesize = filesize;
+ entry->created = created;
+ entry->modified = modified;
+ entry->accessed = accessed;
+ entry->owner = owner;
+ entry->group = group;
+ entry->filename = strndup(filename.ptr, filename.len);
+
+ this->metadata->add(this->metadata, entry);
+ }
+ status = SUCCESS;
+
+end:
+ reader->destroy(reader);
+ return status;
+}
+
+METHOD(pa_tnc_attr_t, add_segment, void,
+ private_tcg_pts_attr_file_meta_t *this, chunk_t segment)
+{
+ this->value = chunk_cat("mc", this->value, segment);
+}
+
+METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
+ private_tcg_pts_attr_file_meta_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.pa_tnc_attribute;
+}
+
+METHOD(pa_tnc_attr_t, destroy, void,
+ private_tcg_pts_attr_file_meta_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ DESTROY_IF(this->metadata);
+ free(this->value.ptr);
+ free(this);
+ }
+}
+
+METHOD(tcg_pts_attr_file_meta_t, get_metadata, pts_file_meta_t*,
+ private_tcg_pts_attr_file_meta_t *this)
+{
+ return this->metadata;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *tcg_pts_attr_unix_file_meta_create(pts_file_meta_t *metadata)
+{
+ private_tcg_pts_attr_file_meta_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_metadata = _get_metadata,
+ },
+ .type = { PEN_TCG, TCG_PTS_UNIX_FILE_META },
+ .metadata = metadata,
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *tcg_pts_attr_unix_file_meta_create_from_data(size_t length,
+ chunk_t data)
+{
+ private_tcg_pts_attr_file_meta_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_metadata = _get_metadata,
+ },
+ .type = { PEN_TCG, TCG_PTS_UNIX_FILE_META },
+ .length = length,
+ .value = chunk_clone(data),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
diff --git a/src/libimcv/tcg/pts/tcg_pts_attr_unix_file_meta.h b/src/libimcv/tcg/pts/tcg_pts_attr_unix_file_meta.h
new file mode 100644
index 000000000..d08261cc9
--- /dev/null
+++ b/src/libimcv/tcg/pts/tcg_pts_attr_unix_file_meta.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup tcg_pts_attr_unix_file_meta tcg_pts_attr_unix_file_meta
+ * @{ @ingroup tcg_attr
+ */
+
+#ifndef TCG_PTS_ATTR_UNIX_FILE_META_H_
+#define TCG_PTS_ATTR_UNIX_FILE_META_H_
+
+typedef struct tcg_pts_attr_file_meta_t tcg_pts_attr_file_meta_t;
+
+#include "tcg/tcg_attr.h"
+#include "pa_tnc/pa_tnc_attr.h"
+#include "pts/pts.h"
+#include "pts/pts_file_meta.h"
+
+/**
+ * Class implementing the TCG PTS File Measurement attribute
+ *
+ */
+struct tcg_pts_attr_file_meta_t {
+
+ /**
+ * Public PA-TNC attribute interface
+ */
+ pa_tnc_attr_t pa_tnc_attribute;
+
+ /**
+ * Get PTS File Metadata
+ *
+ * @return PTS File Metadata
+ */
+ pts_file_meta_t* (*get_metadata)(tcg_pts_attr_file_meta_t *this);
+
+};
+
+/**
+ * Creates an tcg_pts_attr_file_meta_t object
+ *
+ * @param metadata PTS File Metadata
+ */
+pa_tnc_attr_t* tcg_pts_attr_unix_file_meta_create(pts_file_meta_t *metadata);
+
+/**
+ * Creates an tcg_pts_attr_file_meta_t object from received data
+ *
+ * @param length Total length of attribute value
+ * @param value Unparsed attribute value (might be a segment)
+ */
+pa_tnc_attr_t* tcg_pts_attr_unix_file_meta_create_from_data(size_t length,
+ chunk_t value);
+
+#endif /** TCG_PTS_ATTR_UNIX_FILE_META_H_ @}*/
diff --git a/src/libimcv/tcg/seg/tcg_seg_attr_max_size.c b/src/libimcv/tcg/seg/tcg_seg_attr_max_size.c
new file mode 100644
index 000000000..010eaf83d
--- /dev/null
+++ b/src/libimcv/tcg/seg/tcg_seg_attr_max_size.c
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tcg_seg_attr_max_size.h"
+
+#include <pa_tnc/pa_tnc_msg.h>
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <utils/debug.h>
+
+typedef struct private_tcg_seg_attr_max_size_t private_tcg_seg_attr_max_size_t;
+
+/**
+ * Maximum Attribute Size Request/Response
+ * see TCG IF-M Segmentation Specification
+ *
+ * 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Max Attribute Size |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Max Segment Size |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+/**
+ * Private data of an tcg_seg_attr_max_size_t object.
+ */
+struct private_tcg_seg_attr_max_size_t {
+
+ /**
+ * Public members of tcg_seg_attr_max_size_t
+ */
+ tcg_seg_attr_max_size_t public;
+
+ /**
+ * Vendor-specific attribute type
+ */
+ pen_type_t type;
+
+ /**
+ * Length of attribute value
+ */
+ size_t length;
+
+ /**
+ * Attribute value or segment
+ */
+ chunk_t value;
+
+ /**
+ * Noskip flag
+ */
+ bool noskip_flag;
+
+ /**
+ * Maximum IF-M attribute size in octets
+ */
+ uint32_t max_attr_size;
+
+ /**
+ * Maximum IF-M attribute segment size in octets
+ */
+ uint32_t max_seg_size;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+};
+
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
+ private_tcg_seg_attr_max_size_t *this)
+{
+ return this->type;
+}
+
+METHOD(pa_tnc_attr_t, get_value, chunk_t,
+ private_tcg_seg_attr_max_size_t *this)
+{
+ return this->value;
+}
+
+METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
+ private_tcg_seg_attr_max_size_t *this)
+{
+ return this->noskip_flag;
+}
+
+METHOD(pa_tnc_attr_t, set_noskip_flag,void,
+ private_tcg_seg_attr_max_size_t *this, bool noskip)
+{
+ this->noskip_flag = noskip;
+}
+
+METHOD(pa_tnc_attr_t, build, void,
+ private_tcg_seg_attr_max_size_t *this)
+{
+ bio_writer_t *writer;
+
+ if (this->value.ptr)
+ {
+ return;
+ }
+ writer = bio_writer_create(TCG_SEG_ATTR_MAX_SIZE_SIZE);
+ writer->write_uint32(writer, this->max_attr_size);
+ writer->write_uint32(writer, this->max_seg_size);
+
+ this->value = writer->extract_buf(writer);
+ this->length = this->value.len;
+ writer->destroy(writer);
+}
+
+METHOD(pa_tnc_attr_t, process, status_t,
+ private_tcg_seg_attr_max_size_t *this, u_int32_t *offset)
+{
+ bio_reader_t *reader;
+
+ *offset = 0;
+
+ if (this->value.len < this->length)
+ {
+ return NEED_MORE;
+ }
+ if (this->value.len < TCG_SEG_ATTR_MAX_SIZE_SIZE)
+ {
+ DBG1(DBG_TNC, "insufficient data for %N", tcg_attr_names,
+ this->type.type);
+ return FAILED;
+ }
+ reader = bio_reader_create(this->value);
+ reader->read_uint32(reader, &this->max_attr_size);
+ reader->read_uint32(reader, &this->max_seg_size);
+ reader->destroy(reader);
+
+ return SUCCESS;
+}
+
+METHOD(pa_tnc_attr_t, add_segment, void,
+ private_tcg_seg_attr_max_size_t *this, chunk_t segment)
+{
+ this->value = chunk_cat("mc", this->value, segment);
+}
+
+METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
+ private_tcg_seg_attr_max_size_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.pa_tnc_attribute;
+}
+
+METHOD(pa_tnc_attr_t, destroy, void,
+ private_tcg_seg_attr_max_size_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ free(this->value.ptr);
+ free(this);
+ }
+}
+
+METHOD(tcg_seg_attr_max_size_t, get_attr_size, void,
+ private_tcg_seg_attr_max_size_t *this, uint32_t *max_attr_size,
+ uint32_t *max_seg_size)
+{
+ if (max_attr_size)
+ {
+ *max_attr_size = this->max_attr_size;
+ }
+ if (max_seg_size)
+ {
+ *max_seg_size = this->max_seg_size;
+ }
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t* tcg_seg_attr_max_size_create(uint32_t max_attr_size,
+ uint32_t max_seg_size,
+ bool request)
+{
+ private_tcg_seg_attr_max_size_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_attr_size = _get_attr_size,
+ },
+ .type = { PEN_TCG, request ? TCG_SEG_MAX_ATTR_SIZE_REQ :
+ TCG_SEG_MAX_ATTR_SIZE_RESP },
+ .max_attr_size = max_attr_size,
+ .max_seg_size = max_seg_size,
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *tcg_seg_attr_max_size_create_from_data(size_t length,
+ chunk_t data,
+ bool request)
+{
+ private_tcg_seg_attr_max_size_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_attr_size = _get_attr_size,
+ },
+ .type = { PEN_TCG, request ? TCG_SEG_MAX_ATTR_SIZE_REQ :
+ TCG_SEG_MAX_ATTR_SIZE_RESP },
+ .length = length,
+ .value = chunk_clone(data),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
diff --git a/src/libimcv/tcg/seg/tcg_seg_attr_max_size.h b/src/libimcv/tcg/seg/tcg_seg_attr_max_size.h
new file mode 100644
index 000000000..72660acd5
--- /dev/null
+++ b/src/libimcv/tcg/seg/tcg_seg_attr_max_size.h
@@ -0,0 +1,73 @@
+/*
+ * 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 tcg_seg_attr_max_size tcg_seg_attr_max_size
+ * @{ @ingroup tcg_attr
+ */
+
+#ifndef TCG_SEG_ATTR_MAX_SIZE_H_
+#define TCG_SEG_ATTR_MAX_SIZE_H_
+
+typedef struct tcg_seg_attr_max_size_t tcg_seg_attr_max_size_t;
+
+#include "tcg/tcg_attr.h"
+
+#define TCG_SEG_ATTR_MAX_SIZE_SIZE 8
+
+/**
+ * Class implementing the TCG Segmentation Maximum Attribute Size Attribute
+ */
+struct tcg_seg_attr_max_size_t {
+
+ /**
+ * Public PA-TNC attribute interface
+ */
+ pa_tnc_attr_t pa_tnc_attribute;
+
+ /**
+ * Get maximum IF-M attribute and segment size in octets
+ *
+ * @param max_attr_size Maximum IF-M attribute size in octets
+ * @param max_seg_size Maximum IF-M attribute segment size in octets
+ */
+ void (*get_attr_size)(tcg_seg_attr_max_size_t *this,
+ uint32_t *max_attr_size, uint32_t *max_seg_size);
+
+};
+
+/**
+ * Creates an tcg_seg_attr_max_size_t object
+ *
+ * @param max_attr_size Maximum IF-M attribute size in octets
+ * @param max_seg_size Maximum IF-M attribute segment size in octets
+ * @param request TRUE for a request, FALSE for a response
+ */
+pa_tnc_attr_t* tcg_seg_attr_max_size_create(uint32_t max_attr_size,
+ uint32_t max_seg_size,
+ bool request);
+
+/**
+ * Creates an tcg_seg_attr_max_size_t object from received data
+ *
+ * @param length Total length of attribute value
+ * @param value Unparsed attribute value (might be a segment)
+ * @param request TRUE for a request, FALSE for a response
+ */
+pa_tnc_attr_t* tcg_seg_attr_max_size_create_from_data(size_t length,
+ chunk_t value,
+ bool request);
+
+#endif /** TCG_SEG_ATTR_MAX_SIZE_H_ @}*/
diff --git a/src/libimcv/tcg/seg/tcg_seg_attr_next_seg.c b/src/libimcv/tcg/seg/tcg_seg_attr_next_seg.c
new file mode 100644
index 000000000..995f64cad
--- /dev/null
+++ b/src/libimcv/tcg/seg/tcg_seg_attr_next_seg.c
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tcg_seg_attr_next_seg.h"
+
+#include <pa_tnc/pa_tnc_msg.h>
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <utils/debug.h>
+
+typedef struct private_tcg_seg_attr_next_seg_t private_tcg_seg_attr_next_seg_t;
+
+typedef enum {
+ NEXT_SEG_FLAG_NONE = 0,
+ NEXT_SEG_FLAG_CANCEL = 1
+} next_seg_flags_t;
+
+/**
+ * Next Segment
+ * see TCG IF-M Segmentation Specification
+ *
+ * 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |C| Reserved | Base Attribute ID |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+/**
+ * Private data of an tcg_seg_attr_next_seg_t object.
+ */
+struct private_tcg_seg_attr_next_seg_t {
+
+ /**
+ * Public members of tcg_seg_attr_next_seg_t
+ */
+ tcg_seg_attr_next_seg_t public;
+
+ /**
+ * Vendor-specific attribute type
+ */
+ pen_type_t type;
+
+ /**
+ * Length of attribute value
+ */
+ size_t length;
+
+ /**
+ * Attribute value or segment
+ */
+ chunk_t value;
+
+ /**
+ * Noskip flag
+ */
+ bool noskip_flag;
+
+ /**
+ * Cancel flag
+ */
+ bool cancel_flag;
+
+ /**
+ * Base Attribute ID
+ */
+ uint32_t base_attr_id;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+};
+
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
+ private_tcg_seg_attr_next_seg_t *this)
+{
+ return this->type;
+}
+
+METHOD(pa_tnc_attr_t, get_value, chunk_t,
+ private_tcg_seg_attr_next_seg_t *this)
+{
+ return this->value;
+}
+
+METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
+ private_tcg_seg_attr_next_seg_t *this)
+{
+ return this->noskip_flag;
+}
+
+METHOD(pa_tnc_attr_t, set_noskip_flag,void,
+ private_tcg_seg_attr_next_seg_t *this, bool noskip)
+{
+ this->noskip_flag = noskip;
+}
+
+METHOD(pa_tnc_attr_t, build, void,
+ private_tcg_seg_attr_next_seg_t *this)
+{
+ bio_writer_t *writer;
+
+ if (this->value.ptr)
+ {
+ return;
+ }
+ writer = bio_writer_create(TCG_SEG_ATTR_NEXT_SEG_SIZE);
+ writer->write_uint8 (writer, this->cancel_flag ? NEXT_SEG_FLAG_CANCEL :
+ NEXT_SEG_FLAG_NONE);
+ writer->write_uint24(writer, this->base_attr_id);
+
+ this->value = writer->extract_buf(writer);
+ this->length = this->value.len;
+ writer->destroy(writer);
+}
+
+METHOD(pa_tnc_attr_t, process, status_t,
+ private_tcg_seg_attr_next_seg_t *this, u_int32_t *offset)
+{
+ bio_reader_t *reader;
+ uint8_t flags;
+
+ *offset = 0;
+
+ if (this->value.len < this->length)
+ {
+ DBG1(DBG_TNC, "segmentation not allowed for %N", tcg_attr_names,
+ this->type.type);
+ return FAILED;
+ }
+ if (this->value.len < TCG_SEG_ATTR_NEXT_SEG_SIZE)
+ {
+ DBG1(DBG_TNC, "insufficient data for %N", tcg_attr_names,
+ this->type.type);
+ return FAILED;
+ }
+ reader = bio_reader_create(this->value);
+ reader->read_uint8 (reader, &flags);
+ reader->read_uint24(reader, &this->base_attr_id);
+ reader->destroy(reader);
+
+ this->cancel_flag = (flags & NEXT_SEG_FLAG_CANCEL);
+
+ return SUCCESS;
+}
+
+METHOD(pa_tnc_attr_t, add_segment, void,
+ private_tcg_seg_attr_next_seg_t *this, chunk_t segment)
+{
+ this->value = chunk_cat("mc", this->value, segment);
+}
+
+METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
+ private_tcg_seg_attr_next_seg_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.pa_tnc_attribute;
+}
+
+METHOD(pa_tnc_attr_t, destroy, void,
+ private_tcg_seg_attr_next_seg_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ free(this->value.ptr);
+ free(this);
+ }
+}
+
+METHOD(tcg_seg_attr_next_seg_t, get_base_attr_id, uint32_t,
+ private_tcg_seg_attr_next_seg_t *this)
+{
+ return this->base_attr_id;
+}
+
+METHOD(tcg_seg_attr_next_seg_t, get_cancel_flag, bool,
+ private_tcg_seg_attr_next_seg_t *this)
+{
+ return this->cancel_flag;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t* tcg_seg_attr_next_seg_create(uint32_t base_attr_id, bool cancel)
+{
+ private_tcg_seg_attr_next_seg_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_base_attr_id = _get_base_attr_id,
+ .get_cancel_flag = _get_cancel_flag,
+ },
+ .type = { PEN_TCG, TCG_SEG_NEXT_SEG_REQ },
+ .base_attr_id = base_attr_id,
+ .cancel_flag = cancel,
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *tcg_seg_attr_next_seg_create_from_data(size_t length,
+ chunk_t data)
+{
+ private_tcg_seg_attr_next_seg_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_base_attr_id = _get_base_attr_id,
+ .get_cancel_flag = _get_cancel_flag,
+ },
+ .type = { PEN_TCG, TCG_SEG_NEXT_SEG_REQ },
+ .length = length,
+ .value = chunk_clone(data),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
diff --git a/src/libimcv/tcg/seg/tcg_seg_attr_next_seg.h b/src/libimcv/tcg/seg/tcg_seg_attr_next_seg.h
new file mode 100644
index 000000000..49a4d3666
--- /dev/null
+++ b/src/libimcv/tcg/seg/tcg_seg_attr_next_seg.h
@@ -0,0 +1,73 @@
+/*
+ * 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 tcg_seg_attr_next_seg tcg_seg_attr_next_seg
+ * @{ @ingroup tcg_attr
+ */
+
+#ifndef TCG_SEG_ATTR_NEXT_SEG_H_
+#define TCG_SEG_ATTR_NEXT_SEG_H_
+
+typedef struct tcg_seg_attr_next_seg_t tcg_seg_attr_next_seg_t;
+
+#include "tcg/tcg_attr.h"
+
+#define TCG_SEG_ATTR_NEXT_SEG_SIZE 4
+
+/**
+ * Class implementing the TCG Segmentation Next Segment Attribute
+ */
+struct tcg_seg_attr_next_seg_t {
+
+ /**
+ * Public PA-TNC attribute interface
+ */
+ pa_tnc_attr_t pa_tnc_attribute;
+
+ /**
+ * Get Base Attribute ID
+ *
+ * @return Base Attribute ID
+ */
+ uint32_t (*get_base_attr_id)(tcg_seg_attr_next_seg_t *this);
+
+ /**
+ * Get the Cancel flag
+ *
+ * @return Cancel flag
+ */
+ bool (*get_cancel_flag)(tcg_seg_attr_next_seg_t *this);
+
+};
+
+/**
+ * Creates an tcg_seg_attr_next_seg_t object
+ *
+ * @param base_attr_id Base Attribute ID
+ * @param cancel If TRUE set Cancel flag
+ */
+pa_tnc_attr_t* tcg_seg_attr_next_seg_create(uint32_t base_attr_id, bool cancel);
+
+/**
+ * Creates an tcg_seg_attr_next_seg_t object from received data
+ *
+ * @param length Total length of attribute value
+ * @param value Unparsed attribute value (might be a segment)
+ */
+pa_tnc_attr_t* tcg_seg_attr_next_seg_create_from_data(size_t length,
+ chunk_t value);
+
+#endif /** TCG_SEG_ATTR_NEXT_SEG_H_ @}*/
diff --git a/src/libimcv/tcg/seg/tcg_seg_attr_seg_env.c b/src/libimcv/tcg/seg/tcg_seg_attr_seg_env.c
new file mode 100644
index 000000000..4f767539c
--- /dev/null
+++ b/src/libimcv/tcg/seg/tcg_seg_attr_seg_env.c
@@ -0,0 +1,257 @@
+/*
+ * Copyright (C) 2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tcg_seg_attr_seg_env.h"
+
+#include <pa_tnc/pa_tnc_msg.h>
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <utils/debug.h>
+
+typedef struct private_tcg_seg_attr_seg_env_t private_tcg_seg_attr_seg_env_t;
+
+/**
+ * Attribute Segment Envelope
+ * see TCG IF-M Segmentation Specification
+ *
+ * 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |M|S| Reserved | Base Attribute ID |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Segment Value (Variable Length) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+/**
+ * Private data of an tcg_seg_attr_seg_env_t object.
+ */
+struct private_tcg_seg_attr_seg_env_t {
+
+ /**
+ * Public members of tcg_seg_attr_seg_env_t
+ */
+ tcg_seg_attr_seg_env_t public;
+
+ /**
+ * Vendor-specific attribute type
+ */
+ pen_type_t type;
+
+ /**
+ * Length of attribute value
+ */
+ size_t length;
+
+ /**
+ * Attribute value or segment
+ */
+ chunk_t value;
+
+ /**
+ * Noskip flag
+ */
+ bool noskip_flag;
+
+ /**
+ * PA-TNC segmentation flags
+ */
+ uint8_t flags;
+
+ /**
+ * Base Attribute ID
+ */
+ uint32_t base_attr_id;
+
+ /**
+ * Attribute value
+ */
+ chunk_t segment;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+};
+
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
+ private_tcg_seg_attr_seg_env_t *this)
+{
+ return this->type;
+}
+
+METHOD(pa_tnc_attr_t, get_value, chunk_t,
+ private_tcg_seg_attr_seg_env_t *this)
+{
+ return this->value;
+}
+
+METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
+ private_tcg_seg_attr_seg_env_t *this)
+{
+ return this->noskip_flag;
+}
+
+METHOD(pa_tnc_attr_t, set_noskip_flag,void,
+ private_tcg_seg_attr_seg_env_t *this, bool noskip)
+{
+ this->noskip_flag = noskip;
+}
+
+METHOD(pa_tnc_attr_t, build, void,
+ private_tcg_seg_attr_seg_env_t *this)
+{
+ /* constructor already allocated and built value */
+ this->length = this->value.len;
+ return;
+}
+
+METHOD(pa_tnc_attr_t, process, status_t,
+ private_tcg_seg_attr_seg_env_t *this, u_int32_t *offset)
+{
+ bio_reader_t *reader;
+
+ *offset = 0;
+
+ if (this->value.len < this->length)
+ {
+ DBG1(DBG_TNC, "segmentation not allowed for %N/%N", pen_names, PEN_TCG,
+ tcg_attr_names, this->type.type);
+ return FAILED;
+ }
+ if (this->value.len < TCG_SEG_ATTR_SEG_ENV_HEADER)
+ {
+ DBG1(DBG_TNC, "insufficient data for %N/%N", pen_names, PEN_TCG,
+ tcg_attr_names, this->type.type);
+ return FAILED;
+ }
+ reader = bio_reader_create(this->value);
+ reader->read_uint8 (reader, &this->flags);
+ reader->read_uint24(reader, &this->base_attr_id);
+ reader->destroy(reader);
+
+ return SUCCESS;
+}
+
+METHOD(pa_tnc_attr_t, add_segment, void,
+ private_tcg_seg_attr_seg_env_t *this, chunk_t segment)
+{
+ /* no segments are expected */
+}
+
+METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
+ private_tcg_seg_attr_seg_env_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.pa_tnc_attribute;
+}
+
+METHOD(pa_tnc_attr_t, destroy, void,
+ private_tcg_seg_attr_seg_env_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ free(this->value.ptr);
+ free(this);
+ }
+}
+
+METHOD(tcg_seg_attr_seg_env_t, get_segment, chunk_t,
+ private_tcg_seg_attr_seg_env_t *this, uint8_t *flags)
+{
+ if (flags)
+ {
+ *flags = this->flags;
+ }
+ return chunk_skip(this->value, TCG_SEG_ATTR_SEG_ENV_HEADER);
+}
+
+METHOD(tcg_seg_attr_seg_env_t, get_base_attr_id, uint32_t,
+ private_tcg_seg_attr_seg_env_t *this)
+{
+ return this->base_attr_id;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t* tcg_seg_attr_seg_env_create(chunk_t segment, uint8_t flags,
+ uint32_t base_attr_id)
+{
+ private_tcg_seg_attr_seg_env_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_base_attr_id = _get_base_attr_id,
+ .get_segment = _get_segment,
+ },
+ .type = { PEN_TCG, TCG_SEG_ATTR_SEG_ENV },
+ .flags = flags,
+ .base_attr_id = base_attr_id,
+ .value = chunk_alloc(TCG_SEG_ATTR_SEG_ENV_HEADER + segment.len),
+ .ref = 1,
+ );
+
+ htoun32(this->value.ptr, base_attr_id);
+ *this->value.ptr = flags;
+ memcpy(this->value.ptr + TCG_SEG_ATTR_SEG_ENV_HEADER,
+ segment.ptr, segment.len);
+
+ return &this->public.pa_tnc_attribute;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *tcg_seg_attr_seg_env_create_from_data(size_t length,
+ chunk_t data)
+{
+ private_tcg_seg_attr_seg_env_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_base_attr_id = _get_base_attr_id,
+ .get_segment = _get_segment,
+ },
+ .type = { PEN_TCG, TCG_SEG_ATTR_SEG_ENV },
+ .length = length,
+ .value = chunk_clone(data),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
diff --git a/src/libimcv/tcg/seg/tcg_seg_attr_seg_env.h b/src/libimcv/tcg/seg/tcg_seg_attr_seg_env.h
new file mode 100644
index 000000000..a8b3d7c34
--- /dev/null
+++ b/src/libimcv/tcg/seg/tcg_seg_attr_seg_env.h
@@ -0,0 +1,76 @@
+/*
+ * 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 tcg_seg_attr_seg_env tcg_seg_attr_seg_env
+ * @{ @ingroup tcg_attr
+ */
+
+#ifndef TCG_SEG_ATTR_SEG_ENV_H_
+#define TCG_SEG_ATTR_SEG_ENV_H_
+
+typedef struct tcg_seg_attr_seg_env_t tcg_seg_attr_seg_env_t;
+
+#include "tcg/tcg_attr.h"
+
+#define TCG_SEG_ATTR_SEG_ENV_HEADER 4
+
+/**
+ * Class implementing the TCG Segmentation Envelope Attribute
+ */
+struct tcg_seg_attr_seg_env_t {
+
+ /**
+ * Public PA-TNC attribute interface
+ */
+ pa_tnc_attr_t pa_tnc_attribute;
+
+ /**
+ * Get enveloped attribute segment
+ *
+ * @param flags Segmentation flags
+ * @return Segment
+ */
+ chunk_t (*get_segment)(tcg_seg_attr_seg_env_t *this, uint8_t *flags);
+
+ /**
+ * Get Base Attribute ID
+ *
+ * @return Base Attribute ID
+ */
+ uint32_t (*get_base_attr_id)(tcg_seg_attr_seg_env_t *this);
+
+};
+
+/**
+ * Creates an tcg_seg_attr_seg_env_t object
+ *
+ * @param segment Attribute segment
+ * @param flags Segmentation flags
+ * @param base_attr_id Base Attribute ID
+ */
+pa_tnc_attr_t* tcg_seg_attr_seg_env_create(chunk_t segment, uint8_t flags,
+ uint32_t base_attr_id);
+
+/**
+ * Creates an tcg_seg_attr_seg_env_t object from received data
+ *
+ * @param length Total length of attribute value
+ * @param value Unparsed attribute value (might be a segment)
+ */
+pa_tnc_attr_t* tcg_seg_attr_seg_env_create_from_data(size_t length,
+ chunk_t value);
+
+#endif /** TCG_SEG_ATTR_SEG_ENV_H_ @}*/
diff --git a/src/libimcv/tcg/swid/tcg_swid_attr_req.c b/src/libimcv/tcg/swid/tcg_swid_attr_req.c
new file mode 100644
index 000000000..561242758
--- /dev/null
+++ b/src/libimcv/tcg/swid/tcg_swid_attr_req.c
@@ -0,0 +1,349 @@
+/*
+ * Copyright (C) 2013-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tcg_swid_attr_req.h"
+
+#include "swid/swid_tag_id.h"
+
+#include <pa_tnc/pa_tnc_msg.h>
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <utils/debug.h>
+#include <collections/linked_list.h>
+
+typedef struct private_tcg_swid_attr_req_t private_tcg_swid_attr_req_t;
+
+/**
+ * SWID Request
+ * see section 4.7 of TCG TNC SWID Message and Attributes for IF-M
+ *
+ * 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |R|S|C| Reserved| Tag ID Count |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Request ID |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Earliest EID |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Tag Creator Length | Tag Creator (variable length) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Unique Software ID Length |Unique Software ID (var length)|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+#define SWID_REQ_RESERVED_MASK 0xE0
+
+/**
+ * Private data of an tcg_swid_attr_req_t object.
+ */
+struct private_tcg_swid_attr_req_t {
+
+ /**
+ * Public members of tcg_swid_attr_req_t
+ */
+ tcg_swid_attr_req_t public;
+
+ /**
+ * Vendor-specific attribute type
+ */
+ pen_type_t type;
+
+ /**
+ * Length of attribute value
+ */
+ size_t length;
+
+
+ /**
+ * Attribute value or segment
+ */
+ chunk_t value;
+
+ /**
+ * Noskip flag
+ */
+ bool noskip_flag;
+
+ /**
+ * SWID request flags
+ */
+ u_int8_t flags;
+
+ /**
+ * Request ID
+ */
+ u_int32_t request_id;
+
+ /**
+ * Earliest EID
+ */
+ u_int32_t earliest_eid;
+
+ /**
+ * List of Target Tag Identifiers
+ */
+ swid_inventory_t *targets;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+};
+
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
+ private_tcg_swid_attr_req_t *this)
+{
+ return this->type;
+}
+
+METHOD(pa_tnc_attr_t, get_value, chunk_t,
+ private_tcg_swid_attr_req_t *this)
+{
+ return this->value;
+}
+
+METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
+ private_tcg_swid_attr_req_t *this)
+{
+ return this->noskip_flag;
+}
+
+METHOD(pa_tnc_attr_t, set_noskip_flag,void,
+ private_tcg_swid_attr_req_t *this, bool noskip)
+{
+ this->noskip_flag = noskip;
+}
+
+METHOD(pa_tnc_attr_t, build, void,
+ private_tcg_swid_attr_req_t *this)
+{
+ bio_writer_t *writer;
+ chunk_t tag_creator, unique_sw_id;
+ swid_tag_id_t *tag_id;
+ enumerator_t *enumerator;
+
+ if (this->value.ptr)
+ {
+ return;
+ }
+
+ 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);
+ writer->write_uint32(writer, this->earliest_eid);
+
+ enumerator = this->targets->create_enumerator(this->targets);
+ 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, NULL);
+ writer->write_data16(writer, tag_creator);
+ writer->write_data16(writer, unique_sw_id);
+ }
+ enumerator->destroy(enumerator);
+
+ this->value = writer->extract_buf(writer);
+ this->length = this->value.len;
+ writer->destroy(writer);
+}
+
+METHOD(pa_tnc_attr_t, process, status_t,
+ private_tcg_swid_attr_req_t *this, u_int32_t *offset)
+{
+ bio_reader_t *reader;
+ u_int32_t tag_id_count;
+ chunk_t tag_creator, unique_sw_id;
+ swid_tag_id_t *tag_id;
+
+ *offset = 0;
+
+ if (this->value.len < this->length)
+ {
+ return NEED_MORE;
+ }
+ if (this->value.len < TCG_SWID_REQ_MIN_SIZE)
+ {
+ DBG1(DBG_TNC, "insufficient data for SWID Request");
+ return FAILED;
+ }
+
+ reader = bio_reader_create(this->value);
+ reader->read_uint8 (reader, &this->flags);
+ reader->read_uint24(reader, &tag_id_count);
+ reader->read_uint32(reader, &this->request_id);
+ reader->read_uint32(reader, &this->earliest_eid);
+
+ if (this->request_id == 0)
+ {
+ *offset = 4;
+ return FAILED;
+ }
+ *offset = TCG_SWID_REQ_MIN_SIZE;
+
+ this->flags &= SWID_REQ_RESERVED_MASK;
+
+ while (tag_id_count--)
+ {
+ if (!reader->read_data16(reader, &tag_creator))
+ {
+ DBG1(DBG_TNC, "insufficient data for Tag Creator field");
+ return FAILED;
+ }
+ *offset += 2 + tag_creator.len;
+
+ if (!reader->read_data16(reader, &unique_sw_id))
+ {
+ DBG1(DBG_TNC, "insufficient data for Unique Software ID");
+ return FAILED;
+ }
+ *offset += 2 + unique_sw_id.len;
+
+ tag_id = swid_tag_id_create(tag_creator, unique_sw_id, chunk_empty);
+ this->targets->add(this->targets, tag_id);
+ }
+ reader->destroy(reader);
+
+ return SUCCESS;
+}
+
+METHOD(pa_tnc_attr_t, add_segment, void,
+ private_tcg_swid_attr_req_t *this, chunk_t segment)
+{
+ this->value = chunk_cat("mc", this->value, segment);
+}
+
+METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
+ private_tcg_swid_attr_req_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.pa_tnc_attribute;
+}
+
+METHOD(pa_tnc_attr_t, destroy, void,
+ private_tcg_swid_attr_req_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ this->targets->destroy(this->targets);
+ free(this->value.ptr);
+ free(this);
+ }
+}
+
+METHOD(tcg_swid_attr_req_t, get_flags, u_int8_t,
+ private_tcg_swid_attr_req_t *this)
+{
+ return this->flags;
+}
+
+METHOD(tcg_swid_attr_req_t, get_request_id, u_int32_t,
+ private_tcg_swid_attr_req_t *this)
+{
+ return this->request_id;
+}
+
+METHOD(tcg_swid_attr_req_t, get_earliest_eid, u_int32_t,
+ private_tcg_swid_attr_req_t *this)
+{
+ return this->earliest_eid;
+}
+
+METHOD(tcg_swid_attr_req_t, add_target, void,
+ private_tcg_swid_attr_req_t *this, swid_tag_id_t *tag_id)
+{
+ this->targets->add(this->targets, tag_id);
+}
+
+METHOD(tcg_swid_attr_req_t, get_targets, swid_inventory_t*,
+ private_tcg_swid_attr_req_t *this)
+{
+ return this->targets;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *tcg_swid_attr_req_create(u_int8_t flags, u_int32_t request_id,
+ u_int32_t eid)
+{
+ private_tcg_swid_attr_req_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_flags = _get_flags,
+ .get_request_id = _get_request_id,
+ .get_earliest_eid = _get_earliest_eid,
+ .add_target = _add_target,
+ .get_targets = _get_targets,
+ },
+ .type = { PEN_TCG, TCG_SWID_REQUEST },
+ .flags = flags & SWID_REQ_RESERVED_MASK,
+ .request_id = request_id,
+ .earliest_eid = eid,
+ .targets = swid_inventory_create(FALSE),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *tcg_swid_attr_req_create_from_data(size_t length, chunk_t data)
+{
+ private_tcg_swid_attr_req_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_flags = _get_flags,
+ .get_request_id = _get_request_id,
+ .get_earliest_eid = _get_earliest_eid,
+ .add_target = _add_target,
+ .get_targets = _get_targets,
+ },
+ .type = { PEN_TCG, TCG_SWID_REQUEST },
+ .length = length,
+ .value = chunk_clone(data),
+ .targets = swid_inventory_create(FALSE),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
diff --git a/src/libimcv/tcg/swid/tcg_swid_attr_req.h b/src/libimcv/tcg/swid/tcg_swid_attr_req.h
new file mode 100644
index 000000000..fd2ccdc4f
--- /dev/null
+++ b/src/libimcv/tcg/swid/tcg_swid_attr_req.h
@@ -0,0 +1,106 @@
+/*
+ * 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 tcg_swid_attr_req tcg_swid_attr_req
+ * @{ @ingroup tcg_attr
+ */
+
+#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;
+
+enum tcg_swid_attr_req_flag_t {
+ TCG_SWID_ATTR_REQ_FLAG_NONE = 0,
+ TCG_SWID_ATTR_REQ_FLAG_R = (1 << 7),
+ TCG_SWID_ATTR_REQ_FLAG_S = (1 << 6),
+ TCG_SWID_ATTR_REQ_FLAG_C = (1 << 5)
+};
+
+#include "tcg/tcg_attr.h"
+#include "swid/swid_tag_id.h"
+#include "swid/swid_inventory.h"
+#include "pa_tnc/pa_tnc_attr.h"
+
+/**
+ * Class implementing the TCG SWID Request attribute
+ */
+struct tcg_swid_attr_req_t {
+
+ /**
+ * Public PA-TNC attribute interface
+ */
+ pa_tnc_attr_t pa_tnc_attribute;
+
+ /**
+ * Get SWID request flags
+ *
+ * @return Flags
+ */
+ u_int8_t (*get_flags)(tcg_swid_attr_req_t *this);
+
+ /**
+ * Get Request ID
+ *
+ * @return Request ID
+ */
+ u_int32_t (*get_request_id)(tcg_swid_attr_req_t *this);
+
+ /**
+ * Get Earliest EID
+ *
+ * @return Event ID
+ */
+ u_int32_t (*get_earliest_eid)(tcg_swid_attr_req_t *this);
+
+ /**
+ * Add Tag ID
+ *
+ * @param tag_id SWID Tag ID (is not cloned by constructor!)
+ */
+ void (*add_target)(tcg_swid_attr_req_t *this, swid_tag_id_t *tag_id);
+
+ /**
+ * Create Tag ID enumerator
+ *
+ * @return Get a list of target tag IDs
+ */
+ swid_inventory_t* (*get_targets)(tcg_swid_attr_req_t *this);
+
+};
+
+/**
+ * Creates an tcg_swid_attr_req_t object
+ *
+ * @param flags Sets the C|S|R flags
+ * @param request_id Request ID
+ * @param eid Earliest Event ID
+ */
+pa_tnc_attr_t* tcg_swid_attr_req_create(u_int8_t flags, u_int32_t request_id,
+ u_int32_t eid);
+
+/**
+ * Creates an tcg_swid_attr_req_t object from received data
+ *
+ * @param length Total length of attribute value
+ * @param value Unparsed attribute value (might be a segment)
+ */
+pa_tnc_attr_t* tcg_swid_attr_req_create_from_data(size_t length, chunk_t value);
+
+#endif /** TCG_SWID_ATTR_REQ_H_ @}*/
diff --git a/src/libimcv/tcg/swid/tcg_swid_attr_tag_id_inv.c b/src/libimcv/tcg/swid/tcg_swid_attr_tag_id_inv.c
new file mode 100644
index 000000000..560d5878f
--- /dev/null
+++ b/src/libimcv/tcg/swid/tcg_swid_attr_tag_id_inv.c
@@ -0,0 +1,396 @@
+/*
+ * Copyright (C) 2013-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tcg_swid_attr_tag_id_inv.h"
+
+#include <pa_tnc/pa_tnc_msg.h>
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <utils/debug.h>
+
+
+typedef struct private_tcg_swid_attr_tag_id_inv_t private_tcg_swid_attr_tag_id_inv_t;
+
+/**
+ * SWID Tag Identifier Inventory
+ * see section 4.8 of TCG TNC SWID Message and Attributes for IF-M
+ *
+ * 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Reserved | Tag ID Count |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Request ID Copy |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | EID Epoch |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Last EID |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Tag Creator Length | Tag Creator (variable length) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Unique Software ID Length |Unique Software ID (var length)|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Instance ID Length | Instance ID (variable length) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+#define TCG_SWID_TAG_ID_INV_RESERVED 0x00
+
+/**
+ * Private data of an tcg_swid_attr_tag_id_inv_t object.
+ */
+struct private_tcg_swid_attr_tag_id_inv_t {
+
+ /**
+ * Public members of tcg_swid_attr_tag_id_inv_t
+ */
+ tcg_swid_attr_tag_id_inv_t public;
+
+ /**
+ * Vendor-specific attribute type
+ */
+ pen_type_t type;
+
+ /**
+ * Length of attribute value
+ */
+ size_t length;
+
+ /**
+ * Offset up to which attribute value has been processed
+ */
+ size_t offset;
+
+ /**
+ * Current position of attribute value pointer
+ */
+ chunk_t value;
+
+ /**
+ * Contains complete attribute or current segment
+ */
+ chunk_t segment;
+
+ /**
+ * Noskip flag
+ */
+ bool noskip_flag;
+
+ /**
+ * Request ID
+ */
+ uint32_t request_id;
+
+ /**
+ * Event ID Epoch
+ */
+ uint32_t eid_epoch;
+
+ /**
+ * Last Event ID
+ */
+ uint32_t last_eid;
+
+ /**
+ * Number of SWID Tag IDs in attribute
+ */
+ uint32_t tag_id_count;
+
+ /**
+ * SWID Tag ID Inventory
+ */
+ swid_inventory_t *inventory;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+};
+
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
+ private_tcg_swid_attr_tag_id_inv_t *this)
+{
+ return this->type;
+}
+
+METHOD(pa_tnc_attr_t, get_value, chunk_t,
+ private_tcg_swid_attr_tag_id_inv_t *this)
+{
+ return this->value;
+}
+
+METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
+ private_tcg_swid_attr_tag_id_inv_t *this)
+{
+ return this->noskip_flag;
+}
+
+METHOD(pa_tnc_attr_t, set_noskip_flag,void,
+ private_tcg_swid_attr_tag_id_inv_t *this, bool noskip)
+{
+ this->noskip_flag = noskip;
+}
+
+METHOD(pa_tnc_attr_t, build, void,
+ private_tcg_swid_attr_tag_id_inv_t *this)
+{
+ bio_writer_t *writer;
+ swid_tag_id_t *tag_id;
+ chunk_t tag_creator, unique_sw_id, instance_id;
+ enumerator_t *enumerator;
+
+ if (this->value.ptr)
+ {
+ return;
+ }
+
+ 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);
+ writer->write_uint32(writer, this->last_eid);
+
+ enumerator = this->inventory->create_enumerator(this->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, &instance_id);
+ writer->write_data16(writer, tag_creator);
+ writer->write_data16(writer, unique_sw_id);
+ writer->write_data16(writer, instance_id);
+ }
+ enumerator->destroy(enumerator);
+
+ this->value = writer->extract_buf(writer);
+ this->segment = this->value;
+ this->length = this->value.len;
+ writer->destroy(writer);
+}
+
+METHOD(pa_tnc_attr_t, process, status_t,
+ private_tcg_swid_attr_tag_id_inv_t *this, uint32_t *offset)
+{
+ bio_reader_t *reader;
+ uint8_t reserved;
+ chunk_t tag_creator, unique_sw_id, instance_id;
+ swid_tag_id_t *tag_id;
+ status_t status = NEED_MORE;
+
+ if (this->offset == 0)
+ {
+ if (this->length < TCG_SWID_TAG_ID_INV_MIN_SIZE)
+ {
+ DBG1(DBG_TNC, "insufficient data for %N/%N", pen_names, PEN_TCG,
+ tcg_attr_names, this->type.type);
+ *offset = this->offset;
+ return FAILED;
+ }
+ if (this->value.len < TCG_SWID_TAG_ID_INV_MIN_SIZE)
+ {
+ return NEED_MORE;
+ }
+ reader = bio_reader_create(this->value);
+ reader->read_uint8 (reader, &reserved);
+ reader->read_uint24(reader, &this->tag_id_count);
+ reader->read_uint32(reader, &this->request_id);
+ reader->read_uint32(reader, &this->eid_epoch);
+ reader->read_uint32(reader, &this->last_eid);
+ this->offset = TCG_SWID_TAG_ID_INV_MIN_SIZE;
+ this->value = reader->peek(reader);
+ reader->destroy(reader);
+ }
+
+ reader = bio_reader_create(this->value);
+
+ while (this->tag_id_count)
+ {
+ if (!reader->read_data16(reader, &tag_creator) ||
+ !reader->read_data16(reader, &unique_sw_id) ||
+ !reader->read_data16(reader, &instance_id))
+ {
+ goto end;
+ }
+ tag_id = swid_tag_id_create(tag_creator, unique_sw_id, instance_id);
+ this->inventory->add(this->inventory, tag_id);
+ this->offset += this->value.len - reader->remaining(reader);
+ this->value = reader->peek(reader);
+
+ /* at least one tag ID was processed */
+ status = SUCCESS;
+ this->tag_id_count--;
+ }
+
+ if (this->length != this->offset)
+ {
+ DBG1(DBG_TNC, "inconsistent length for %N/%N", pen_names, PEN_TCG,
+ tcg_attr_names, this->type.type);
+ *offset = this->offset;
+ status = FAILED;
+ }
+
+end:
+ reader->destroy(reader);
+ return status;
+}
+
+METHOD(pa_tnc_attr_t, add_segment, void,
+ private_tcg_swid_attr_tag_id_inv_t *this, chunk_t segment)
+{
+ this->value = chunk_cat("cc", this->value, segment);
+ chunk_free(&this->segment);
+ this->segment = this->value;
+}
+
+METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
+ private_tcg_swid_attr_tag_id_inv_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.pa_tnc_attribute;
+}
+
+METHOD(pa_tnc_attr_t, destroy, void,
+ private_tcg_swid_attr_tag_id_inv_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ this->inventory->destroy(this->inventory);
+ free(this->segment.ptr);
+ free(this);
+ }
+}
+
+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, uint32_t,
+ private_tcg_swid_attr_tag_id_inv_t *this, uint32_t *eid_epoch)
+{
+ if (eid_epoch)
+ {
+ *eid_epoch = this->eid_epoch;
+ }
+ return this->last_eid;
+}
+
+METHOD(tcg_swid_attr_tag_id_inv_t, get_tag_id_count, uint32_t,
+ private_tcg_swid_attr_tag_id_inv_t *this)
+{
+ return this->tag_id_count;
+}
+
+METHOD(tcg_swid_attr_tag_id_inv_t, get_inventory, swid_inventory_t*,
+ private_tcg_swid_attr_tag_id_inv_t *this)
+{
+ return this->inventory;
+}
+
+METHOD(tcg_swid_attr_tag_id_inv_t, clear_inventory, void,
+ private_tcg_swid_attr_tag_id_inv_t *this)
+{
+ this->inventory->destroy(this->inventory);
+ this->inventory = swid_inventory_create(FALSE);
+}
+
+/**
+ * Described in header.
+ */
+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;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .add = _add,
+ .get_request_id = _get_request_id,
+ .get_last_eid = _get_last_eid,
+ .get_tag_id_count = _get_tag_id_count,
+ .get_inventory = _get_inventory,
+ .clear_inventory = _clear_inventory,
+ },
+ .type = { PEN_TCG, TCG_SWID_TAG_ID_INVENTORY },
+ .request_id = request_id,
+ .eid_epoch = eid_epoch,
+ .last_eid = eid,
+ .inventory = swid_inventory_create(FALSE),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *tcg_swid_attr_tag_id_inv_create_from_data(size_t length,
+ chunk_t data)
+{
+ private_tcg_swid_attr_tag_id_inv_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .add = _add,
+ .get_request_id = _get_request_id,
+ .get_last_eid = _get_last_eid,
+ .get_tag_id_count = _get_tag_id_count,
+ .get_inventory = _get_inventory,
+ .clear_inventory = _clear_inventory,
+ },
+ .type = { PEN_TCG, TCG_SWID_TAG_ID_INVENTORY },
+ .length = length,
+ .segment = chunk_clone(data),
+ .inventory = swid_inventory_create(FALSE),
+ .ref = 1,
+ );
+
+ /* received either complete attribute value or first segment */
+ this->value = this->segment;
+
+ return &this->public.pa_tnc_attribute;
+}
diff --git a/src/libimcv/tcg/swid/tcg_swid_attr_tag_id_inv.h b/src/libimcv/tcg/swid/tcg_swid_attr_tag_id_inv.h
new file mode 100644
index 000000000..e9db9b3c6
--- /dev/null
+++ b/src/libimcv/tcg/swid/tcg_swid_attr_tag_id_inv.h
@@ -0,0 +1,109 @@
+/*
+ * 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 tcg_swid_attr_tag_id_inv tcg_swid_attr_tag_id_inv
+ * @{ @ingroup tcg_attr
+ */
+
+#ifndef TCG_SWID_ATTR_TAG_ID_INV_H_
+#define TCG_SWID_ATTR_TAG_ID_INV_H_
+
+typedef struct tcg_swid_attr_tag_id_inv_t tcg_swid_attr_tag_id_inv_t;
+
+#include "tcg/tcg_attr.h"
+#include "swid/swid_tag_id.h"
+#include "swid/swid_inventory.h"
+
+#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
+ *
+ */
+struct tcg_swid_attr_tag_id_inv_t {
+
+ /**
+ * Public PA-TNC attribute interface
+ */
+ 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
+ */
+ uint32_t (*get_request_id)(tcg_swid_attr_tag_id_inv_t *this);
+
+ /**
+ * Get Last Event ID
+ *
+ * @param eid_epoch Event ID Epoch
+ * @return Last Event ID
+ */
+ uint32_t (*get_last_eid)(tcg_swid_attr_tag_id_inv_t *this,
+ uint32_t *eid_epoch);
+
+ /**
+ * Get count of remaining SWID tag IDs
+ *
+ * @return SWID Tag ID count
+ */
+ uint32_t (*get_tag_id_count)(tcg_swid_attr_tag_id_inv_t *this);
+
+ /**
+ * Get Inventory of SWID tag IDs
+ *
+ * @result SWID Tag ID Inventory
+ */
+ swid_inventory_t* (*get_inventory)(tcg_swid_attr_tag_id_inv_t *this);
+
+ /**
+ * Remove all SWID Tag IDs from the Inventory
+ */
+ void (*clear_inventory)(tcg_swid_attr_tag_id_inv_t *this);
+
+};
+
+/**
+ * Creates an tcg_swid_attr_tag_id_inv_t object
+ *
+ * @param request_id Copy of the Request ID
+ * @param eid_epoch Event ID Epoch
+ * @param eid Last Event ID
+ */
+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
+ *
+ * @param length Total length of attribute value
+ * @param value Unparsed attribute value (might be a segment)
+ */
+pa_tnc_attr_t* tcg_swid_attr_tag_id_inv_create_from_data(size_t length,
+ chunk_t value);
+
+#endif /** TCG_SWID_ATTR_TAG_ID_INV_H_ @}*/
diff --git a/src/libimcv/tcg/swid/tcg_swid_attr_tag_inv.c b/src/libimcv/tcg/swid/tcg_swid_attr_tag_inv.c
new file mode 100644
index 000000000..013482441
--- /dev/null
+++ b/src/libimcv/tcg/swid/tcg_swid_attr_tag_inv.c
@@ -0,0 +1,389 @@
+/*
+ * Copyright (C) 2013-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tcg_swid_attr_tag_inv.h"
+
+#include <pa_tnc/pa_tnc_msg.h>
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <utils/debug.h>
+
+
+typedef struct private_tcg_swid_attr_tag_inv_t private_tcg_swid_attr_tag_inv_t;
+
+/**
+ * SWID Tag Inventory
+ * see section 4.10 of TCG TNC SWID Message and Attributes for IF-M
+ *
+ * 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Reserved | Tag ID Count |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Request ID Copy |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | EID Epoch |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Last EID |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Instance ID Length | Instance ID (var. length) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Tag Length |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Tag (Variable) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+#define TCG_SWID_TAG_INV_RESERVED 0x00
+
+/**
+ * Private data of an tcg_swid_attr_tag_inv_t object.
+ */
+struct private_tcg_swid_attr_tag_inv_t {
+
+ /**
+ * Public members of tcg_swid_attr_tag_inv_t
+ */
+ tcg_swid_attr_tag_inv_t public;
+
+ /**
+ * Vendor-specific attribute type
+ */
+ pen_type_t type;
+
+ /**
+ * Length of attribute value
+ */
+ size_t length;
+
+ /**
+ * Offset up to which attribute value has been processed
+ */
+ size_t offset;
+
+ /**
+ * Current position of attribute value pointer
+ */
+ chunk_t value;
+
+ /**
+ * Contains complete attribute or current segment
+ */
+ chunk_t segment;
+
+ /**
+ * Noskip flag
+ */
+ bool noskip_flag;
+
+ /**
+ * Request ID
+ */
+ uint32_t request_id;
+
+ /**
+ * Event ID Epoch
+ */
+ uint32_t eid_epoch;
+
+ /**
+ * Last Event ID
+ */
+ uint32_t last_eid;
+
+ /**
+ * Number of SWID Tags in attribute
+ */
+ uint32_t tag_count;
+
+ /**
+ * SWID Tag Inventory
+ */
+ swid_inventory_t *inventory;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+};
+
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
+ private_tcg_swid_attr_tag_inv_t *this)
+{
+ return this->type;
+}
+
+METHOD(pa_tnc_attr_t, get_value, chunk_t,
+ private_tcg_swid_attr_tag_inv_t *this)
+{
+ return this->value;
+}
+
+METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
+ private_tcg_swid_attr_tag_inv_t *this)
+{
+ return this->noskip_flag;
+}
+
+METHOD(pa_tnc_attr_t, set_noskip_flag,void,
+ private_tcg_swid_attr_tag_inv_t *this, bool noskip)
+{
+ this->noskip_flag = noskip;
+}
+
+METHOD(pa_tnc_attr_t, build, void,
+ private_tcg_swid_attr_tag_inv_t *this)
+{
+ bio_writer_t *writer;
+ swid_tag_t *tag;
+ enumerator_t *enumerator;
+
+ if (this->value.ptr)
+ {
+ return;
+ }
+
+ 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);
+ writer->write_uint32(writer, this->last_eid);
+
+ enumerator = this->inventory->create_enumerator(this->inventory);
+ while (enumerator->enumerate(enumerator, &tag))
+ {
+ writer->write_data16(writer, tag->get_instance_id(tag));
+ writer->write_data32(writer, tag->get_encoding(tag));
+ }
+ enumerator->destroy(enumerator);
+
+ this->value = writer->extract_buf(writer);
+ this->segment = this->value;
+ this->length = this->value.len;
+ writer->destroy(writer);
+}
+
+METHOD(pa_tnc_attr_t, process, status_t,
+ private_tcg_swid_attr_tag_inv_t *this, uint32_t *offset)
+{
+ bio_reader_t *reader;
+ uint8_t reserved;
+ chunk_t tag_encoding, instance_id;
+ swid_tag_t *tag;
+ status_t status = NEED_MORE;
+
+ if (this->offset == 0)
+ {
+ if (this->length < TCG_SWID_TAG_INV_MIN_SIZE)
+ {
+ DBG1(DBG_TNC, "insufficient data for %N/%N", pen_names, PEN_TCG,
+ tcg_attr_names, this->type.type);
+ *offset = this->offset;
+ return FAILED;
+ }
+ if (this->value.len < TCG_SWID_TAG_INV_MIN_SIZE)
+ {
+ return NEED_MORE;
+ }
+ reader = bio_reader_create(this->value);
+ reader->read_uint8 (reader, &reserved);
+ reader->read_uint24(reader, &this->tag_count);
+ reader->read_uint32(reader, &this->request_id);
+ reader->read_uint32(reader, &this->eid_epoch);
+ reader->read_uint32(reader, &this->last_eid);
+ this->offset = TCG_SWID_TAG_INV_MIN_SIZE;
+ this->value = reader->peek(reader);
+ reader->destroy(reader);
+ }
+
+ reader = bio_reader_create(this->value);
+
+ while (this->tag_count)
+ {
+ if (!reader->read_data16(reader, &instance_id) ||
+ !reader->read_data32(reader, &tag_encoding))
+ {
+ goto end;
+ }
+ tag = swid_tag_create(tag_encoding, instance_id);
+ this->inventory->add(this->inventory, tag);
+ this->offset += this->value.len - reader->remaining(reader);
+ this->value = reader->peek(reader);
+
+ /* at least one tag was processed */
+ status = SUCCESS;
+ this->tag_count--;
+ }
+
+ if (this->length != this->offset)
+ {
+ DBG1(DBG_TNC, "inconsistent length for %N/%N", pen_names, PEN_TCG,
+ tcg_attr_names, this->type.type);
+ *offset = this->offset;
+ status = FAILED;
+ }
+
+end:
+ reader->destroy(reader);
+ return status;
+}
+
+METHOD(pa_tnc_attr_t, add_segment, void,
+ private_tcg_swid_attr_tag_inv_t *this, chunk_t segment)
+{
+ this->value = chunk_cat("cc", this->value, segment);
+ chunk_free(&this->segment);
+ this->segment = this->value;
+}
+
+METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
+ private_tcg_swid_attr_tag_inv_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.pa_tnc_attribute;
+}
+
+METHOD(pa_tnc_attr_t, destroy, void,
+ private_tcg_swid_attr_tag_inv_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ this->inventory->destroy(this->inventory);
+ free(this->segment.ptr);
+ free(this);
+ }
+}
+
+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, uint32_t,
+ private_tcg_swid_attr_tag_inv_t *this, uint32_t *eid_epoch)
+{
+ if (eid_epoch)
+ {
+ *eid_epoch = this->eid_epoch;
+ }
+ return this->last_eid;
+}
+
+METHOD(tcg_swid_attr_tag_inv_t, get_tag_count, uint32_t,
+ private_tcg_swid_attr_tag_inv_t *this)
+{
+ return this->tag_count;
+}
+
+METHOD(tcg_swid_attr_tag_inv_t, get_inventory, swid_inventory_t*,
+ private_tcg_swid_attr_tag_inv_t *this)
+{
+ return this->inventory;
+}
+
+METHOD(tcg_swid_attr_tag_inv_t, clear_inventory, void,
+ private_tcg_swid_attr_tag_inv_t *this)
+{
+ this->inventory->destroy(this->inventory);
+ this->inventory = swid_inventory_create(TRUE);
+}
+
+/**
+ * Described in header.
+ */
+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;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .add = _add,
+ .get_request_id = _get_request_id,
+ .get_last_eid = _get_last_eid,
+ .get_tag_count = _get_tag_count,
+ .get_inventory = _get_inventory,
+ .clear_inventory = _clear_inventory,
+ },
+ .type = { PEN_TCG, TCG_SWID_TAG_INVENTORY },
+ .request_id = request_id,
+ .eid_epoch = eid_epoch,
+ .last_eid = eid,
+ .inventory = swid_inventory_create(TRUE),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *tcg_swid_attr_tag_inv_create_from_data(size_t length,
+ chunk_t data)
+{
+ private_tcg_swid_attr_tag_inv_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .add = _add,
+ .get_request_id = _get_request_id,
+ .get_last_eid = _get_last_eid,
+ .get_tag_count = _get_tag_count,
+ .get_inventory = _get_inventory,
+ .clear_inventory = _clear_inventory,
+ },
+ .type = { PEN_TCG, TCG_SWID_TAG_INVENTORY },
+ .length = length,
+ .segment = chunk_clone(data),
+ .inventory = swid_inventory_create(TRUE),
+ .ref = 1,
+ );
+
+ /* received either complete attribute value or first segment */
+ this->value = this->segment;
+
+ return &this->public.pa_tnc_attribute;
+}
diff --git a/src/libimcv/tcg/swid/tcg_swid_attr_tag_inv.h b/src/libimcv/tcg/swid/tcg_swid_attr_tag_inv.h
new file mode 100644
index 000000000..43ebd9e2a
--- /dev/null
+++ b/src/libimcv/tcg/swid/tcg_swid_attr_tag_inv.h
@@ -0,0 +1,108 @@
+/*
+ * 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 tcg_swid_attr_tag_inv tcg_swid_attr_tag_inv
+ * @{ @ingroup tcg_attr
+ */
+
+#ifndef TCG_SWID_ATTR_TAG_INV_H_
+#define TCG_SWID_ATTR_TAG_INV_H_
+
+typedef struct tcg_swid_attr_tag_inv_t tcg_swid_attr_tag_inv_t;
+
+#include "tcg/tcg_attr.h"
+#include "swid/swid_tag.h"
+#include "swid/swid_inventory.h"
+
+#include <pa_tnc/pa_tnc_attr.h>
+
+#define TCG_SWID_TAG_INV_MIN_SIZE 16
+
+/**
+ * Class implementing the TCG SWID Tag Inventory attribute
+ *
+ */
+struct tcg_swid_attr_tag_inv_t {
+
+ /**
+ * Public PA-TNC attribute interface
+ */
+ 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
+ */
+ uint32_t (*get_request_id)(tcg_swid_attr_tag_inv_t *this);
+
+ /**
+ * Get Last Event ID
+ *
+ * @param eid_epoch Event ID Epoch
+ * @return Last Event ID
+ */
+ uint32_t (*get_last_eid)(tcg_swid_attr_tag_inv_t *this,
+ uint32_t *eid_epoch);
+
+ /**
+ * Get count of remaining SWID tags
+ *
+ * @return SWID Tag count
+ */
+ uint32_t (*get_tag_count)(tcg_swid_attr_tag_inv_t *this);
+
+ /**
+ * Get Inventory of SWID tags
+ *
+ * @result SWID Tag Inventory
+ */
+ swid_inventory_t* (*get_inventory)(tcg_swid_attr_tag_inv_t *this);
+
+ /**
+ * Remove all SWID Tags from the Inventory
+ */
+ void (*clear_inventory)(tcg_swid_attr_tag_inv_t *this);
+
+};
+
+/**
+ * Creates an tcg_swid_attr_tag_inv_t object
+ *
+ * @param request_id Copy of the Request ID
+ * @param eid_epoch Event ID Epoch
+ * @param eid Last Event ID
+ */
+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
+ *
+ * @param length Total length of attribute value
+ * @param value Unparsed attribute value (might be a segment)
+ */
+pa_tnc_attr_t* tcg_swid_attr_tag_inv_create_from_data(size_t length,
+ chunk_t value);
+
+#endif /** TCG_SWID_ATTR_TAG_INV_H_ @}*/
diff --git a/src/libimcv/tcg/tcg_attr.c b/src/libimcv/tcg/tcg_attr.c
new file mode 100644
index 000000000..79492913b
--- /dev/null
+++ b/src/libimcv/tcg/tcg_attr.c
@@ -0,0 +1,270 @@
+/*
+ * 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 "tcg_attr.h"
+#include "tcg/pts/tcg_pts_attr_proto_caps.h"
+#include "tcg/pts/tcg_pts_attr_dh_nonce_params_req.h"
+#include "tcg/pts/tcg_pts_attr_dh_nonce_params_resp.h"
+#include "tcg/pts/tcg_pts_attr_dh_nonce_finish.h"
+#include "tcg/pts/tcg_pts_attr_meas_algo.h"
+#include "tcg/pts/tcg_pts_attr_get_tpm_version_info.h"
+#include "tcg/pts/tcg_pts_attr_tpm_version_info.h"
+#include "tcg/pts/tcg_pts_attr_get_aik.h"
+#include "tcg/pts/tcg_pts_attr_aik.h"
+#include "tcg/pts/tcg_pts_attr_req_func_comp_evid.h"
+#include "tcg/pts/tcg_pts_attr_gen_attest_evid.h"
+#include "tcg/pts/tcg_pts_attr_simple_comp_evid.h"
+#include "tcg/pts/tcg_pts_attr_simple_evid_final.h"
+#include "tcg/pts/tcg_pts_attr_req_file_meas.h"
+#include "tcg/pts/tcg_pts_attr_file_meas.h"
+#include "tcg/pts/tcg_pts_attr_req_file_meta.h"
+#include "tcg/pts/tcg_pts_attr_unix_file_meta.h"
+#include "tcg/swid/tcg_swid_attr_req.h"
+#include "tcg/swid/tcg_swid_attr_tag_id_inv.h"
+#include "tcg/swid/tcg_swid_attr_tag_inv.h"
+#include "tcg/seg/tcg_seg_attr_max_size.h"
+#include "tcg/seg/tcg_seg_attr_seg_env.h"
+#include "tcg/seg/tcg_seg_attr_next_seg.h"
+
+ENUM_BEGIN(tcg_attr_names, TCG_SCAP_REFERENCES,
+ TCG_SCAP_SUMMARY_RESULTS,
+ "SCAP References",
+ "SCAP Capabilities and Inventory",
+ "SCAP Content",
+ "SCAP Assessment",
+ "SCAP Results",
+ "SCAP Summary Results");
+ENUM_NEXT(tcg_attr_names, TCG_SWID_REQUEST,
+ TCG_SWID_TAG_EVENTS,
+ TCG_SCAP_SUMMARY_RESULTS,
+ "SWID Request",
+ "SWID Tag Identifier Inventory",
+ "SWID Tag Identifier Events",
+ "SWID Tag Inventory",
+ "SWID Tag Events");
+ENUM_NEXT(tcg_attr_names, TCG_SEG_MAX_ATTR_SIZE_REQ,
+ TCG_SEG_CANCEL_SEG_EXCH,
+ TCG_SWID_TAG_EVENTS,
+ "Max Attribute Size Request",
+ "Max Attribute Size Response",
+ "Attribute Segment Envelope",
+ "Next Segment Request",
+ "Cancel Segment Exchange");
+ENUM_NEXT(tcg_attr_names, TCG_PTS_REQ_FUNC_COMP_EVID,
+ TCG_PTS_REQ_FUNC_COMP_EVID,
+ TCG_SEG_CANCEL_SEG_EXCH,
+ "Request Functional Component Evidence");
+ENUM_NEXT(tcg_attr_names, TCG_PTS_GEN_ATTEST_EVID,
+ TCG_PTS_GEN_ATTEST_EVID,
+ TCG_PTS_REQ_FUNC_COMP_EVID,
+ "Generate Attestation Evidence");
+ENUM_NEXT(tcg_attr_names, TCG_PTS_SIMPLE_COMP_EVID,
+ TCG_PTS_SIMPLE_COMP_EVID,
+ TCG_PTS_GEN_ATTEST_EVID,
+ "Simple Component Evidence");
+ENUM_NEXT(tcg_attr_names, TCG_PTS_SIMPLE_EVID_FINAL,
+ TCG_PTS_SIMPLE_EVID_FINAL,
+ TCG_PTS_SIMPLE_COMP_EVID,
+ "Simple Evidence Final");
+ENUM_NEXT(tcg_attr_names, TCG_PTS_VERIFICATION_RESULT,
+ TCG_PTS_VERIFICATION_RESULT,
+ TCG_PTS_SIMPLE_EVID_FINAL,
+ "Verification Result");
+ENUM_NEXT(tcg_attr_names, TCG_PTS_INTEG_REPORT,
+ TCG_PTS_INTEG_REPORT,
+ TCG_PTS_VERIFICATION_RESULT,
+ "Integrity Report");
+ENUM_NEXT(tcg_attr_names, TCG_PTS_REQ_FILE_META,
+ TCG_PTS_REQ_FILE_META,
+ TCG_PTS_INTEG_REPORT,
+ "Request File Metadata");
+ENUM_NEXT(tcg_attr_names, TCG_PTS_WIN_FILE_META,
+ TCG_PTS_WIN_FILE_META,
+ TCG_PTS_REQ_FILE_META,
+ "Windows-Style File Metadata");
+ENUM_NEXT(tcg_attr_names, TCG_PTS_UNIX_FILE_META,
+ TCG_PTS_UNIX_FILE_META,
+ TCG_PTS_WIN_FILE_META,
+ "Unix-Style File Metadata");
+ENUM_NEXT(tcg_attr_names, TCG_PTS_REQ_REGISTRY_VALUE,
+ TCG_PTS_REQ_REGISTRY_VALUE,
+ TCG_PTS_UNIX_FILE_META,
+ "Request Registry Value");
+ENUM_NEXT(tcg_attr_names, TCG_PTS_REGISTRY_VALUE,
+ TCG_PTS_REGISTRY_VALUE,
+ TCG_PTS_REQ_REGISTRY_VALUE,
+ "Registry Value");
+ENUM_NEXT(tcg_attr_names, TCG_PTS_REQ_FILE_MEAS,
+ TCG_PTS_REQ_FILE_MEAS,
+ TCG_PTS_REGISTRY_VALUE,
+ "Request File Measurement");
+ENUM_NEXT(tcg_attr_names, TCG_PTS_FILE_MEAS,
+ TCG_PTS_FILE_MEAS,
+ TCG_PTS_REQ_FILE_MEAS,
+ "File Measurement");
+ENUM_NEXT(tcg_attr_names, TCG_PTS_REQ_INTEG_MEAS_LOG,
+ TCG_PTS_REQ_INTEG_MEAS_LOG,
+ TCG_PTS_FILE_MEAS,
+ "Request Integrity Measurement Log");
+ENUM_NEXT(tcg_attr_names, TCG_PTS_INTEG_MEAS_LOG,
+ TCG_PTS_INTEG_MEAS_LOG,
+ TCG_PTS_REQ_INTEG_MEAS_LOG,
+ "Integrity Measurement Log");
+ENUM_NEXT(tcg_attr_names, TCG_PTS_REQ_PROTO_CAPS,
+ TCG_PTS_REQ_PROTO_CAPS,
+ TCG_PTS_INTEG_MEAS_LOG,
+ "Request PTS Protocol Capabilities");
+ENUM_NEXT(tcg_attr_names, TCG_PTS_PROTO_CAPS,
+ TCG_PTS_PROTO_CAPS,
+ TCG_PTS_REQ_PROTO_CAPS,
+ "PTS Protocol Capabilities");
+ENUM_NEXT(tcg_attr_names, TCG_PTS_DH_NONCE_PARAMS_REQ,
+ TCG_PTS_DH_NONCE_PARAMS_REQ,
+ TCG_PTS_PROTO_CAPS,
+ "DH Nonce Parameters Request");
+ENUM_NEXT(tcg_attr_names, TCG_PTS_DH_NONCE_PARAMS_RESP,
+ TCG_PTS_DH_NONCE_PARAMS_RESP,
+ TCG_PTS_DH_NONCE_PARAMS_REQ,
+ "DH Nonce Parameters Response");
+ENUM_NEXT(tcg_attr_names, TCG_PTS_DH_NONCE_FINISH,
+ TCG_PTS_DH_NONCE_FINISH,
+ TCG_PTS_DH_NONCE_PARAMS_RESP,
+ "DH Nonce Finish");
+ENUM_NEXT(tcg_attr_names, TCG_PTS_MEAS_ALGO,
+ TCG_PTS_MEAS_ALGO,
+ TCG_PTS_DH_NONCE_FINISH,
+ "PTS Measurement Algorithm Request");
+ENUM_NEXT(tcg_attr_names, TCG_PTS_MEAS_ALGO_SELECTION,
+ TCG_PTS_MEAS_ALGO_SELECTION,
+ TCG_PTS_MEAS_ALGO,
+ "PTS Measurement Algorithm");
+ENUM_NEXT(tcg_attr_names, TCG_PTS_GET_TPM_VERSION_INFO,
+ TCG_PTS_GET_TPM_VERSION_INFO,
+ TCG_PTS_MEAS_ALGO_SELECTION,
+ "Get TPM Version Information");
+ENUM_NEXT(tcg_attr_names, TCG_PTS_TPM_VERSION_INFO,
+ TCG_PTS_TPM_VERSION_INFO,
+ TCG_PTS_GET_TPM_VERSION_INFO,
+ "TPM Version Information");
+ENUM_NEXT(tcg_attr_names, TCG_PTS_REQ_TEMPL_REF_MANI_SET_META,
+ TCG_PTS_REQ_TEMPL_REF_MANI_SET_META,
+ TCG_PTS_TPM_VERSION_INFO,
+ "Request Template Reference Manifest Set Metadata");
+ENUM_NEXT(tcg_attr_names, TCG_PTS_TEMPL_REF_MANI_SET_META,
+ TCG_PTS_TEMPL_REF_MANI_SET_META,
+ TCG_PTS_REQ_TEMPL_REF_MANI_SET_META,
+ "Template Reference Manifest Set Metadata");
+ENUM_NEXT(tcg_attr_names, TCG_PTS_UPDATE_TEMPL_REF_MANI,
+ TCG_PTS_UPDATE_TEMPL_REF_MANI,
+ TCG_PTS_TEMPL_REF_MANI_SET_META,
+ "Update Template Reference Manifest");
+ENUM_NEXT(tcg_attr_names, TCG_PTS_GET_AIK,
+ TCG_PTS_GET_AIK,
+ TCG_PTS_UPDATE_TEMPL_REF_MANI,
+ "Get Attestation Identity Key");
+ENUM_NEXT(tcg_attr_names, TCG_PTS_AIK,
+ TCG_PTS_AIK,
+ TCG_PTS_GET_AIK,
+ "Attestation Identity Key");
+ENUM_END(tcg_attr_names, TCG_PTS_AIK);
+
+/**
+ * See header
+ */
+pa_tnc_attr_t* tcg_attr_create_from_data(u_int32_t type, size_t length, chunk_t value)
+{
+ switch (type)
+ {
+ case TCG_SWID_REQUEST:
+ return tcg_swid_attr_req_create_from_data(length, value);
+ case TCG_SWID_TAG_ID_INVENTORY:
+ return tcg_swid_attr_tag_id_inv_create_from_data(length, value);
+ case TCG_SWID_TAG_INVENTORY:
+ return tcg_swid_attr_tag_inv_create_from_data(length, value);
+ case TCG_SEG_MAX_ATTR_SIZE_REQ:
+ return tcg_seg_attr_max_size_create_from_data(length, value, TRUE);
+ case TCG_SEG_MAX_ATTR_SIZE_RESP:
+ return tcg_seg_attr_max_size_create_from_data(length, value, FALSE);
+ case TCG_SEG_ATTR_SEG_ENV:
+ return tcg_seg_attr_seg_env_create_from_data(length, value);
+ case TCG_SEG_NEXT_SEG_REQ:
+ return tcg_seg_attr_next_seg_create_from_data(length, value);
+ case TCG_PTS_REQ_PROTO_CAPS:
+ return tcg_pts_attr_proto_caps_create_from_data(length, value,
+ TRUE);
+ case TCG_PTS_PROTO_CAPS:
+ return tcg_pts_attr_proto_caps_create_from_data(length, value,
+ FALSE);
+ case TCG_PTS_DH_NONCE_PARAMS_REQ:
+ return tcg_pts_attr_dh_nonce_params_req_create_from_data(length,
+ value);
+ case TCG_PTS_DH_NONCE_PARAMS_RESP:
+ return tcg_pts_attr_dh_nonce_params_resp_create_from_data(length,
+ value);
+ case TCG_PTS_DH_NONCE_FINISH:
+ return tcg_pts_attr_dh_nonce_finish_create_from_data(length, value);
+ case TCG_PTS_MEAS_ALGO:
+ return tcg_pts_attr_meas_algo_create_from_data(length, value,
+ FALSE);
+ case TCG_PTS_MEAS_ALGO_SELECTION:
+ return tcg_pts_attr_meas_algo_create_from_data(length, value,
+ TRUE);
+ case TCG_PTS_GET_TPM_VERSION_INFO:
+ return tcg_pts_attr_get_tpm_version_info_create_from_data(length,
+ value);
+ case TCG_PTS_TPM_VERSION_INFO:
+ return tcg_pts_attr_tpm_version_info_create_from_data(length,
+ value);
+ case TCG_PTS_GET_AIK:
+ return tcg_pts_attr_get_aik_create_from_data(length, value);
+ case TCG_PTS_AIK:
+ return tcg_pts_attr_aik_create_from_data(length, value);
+ case TCG_PTS_REQ_FUNC_COMP_EVID:
+ return tcg_pts_attr_req_func_comp_evid_create_from_data(length,
+ value);
+ case TCG_PTS_GEN_ATTEST_EVID:
+ return tcg_pts_attr_gen_attest_evid_create_from_data(length, value);
+ case TCG_PTS_SIMPLE_COMP_EVID:
+ return tcg_pts_attr_simple_comp_evid_create_from_data(length,
+ value);
+ case TCG_PTS_SIMPLE_EVID_FINAL:
+ return tcg_pts_attr_simple_evid_final_create_from_data(length,
+ value);
+ case TCG_PTS_REQ_FILE_MEAS:
+ return tcg_pts_attr_req_file_meas_create_from_data(length, value);
+ case TCG_PTS_FILE_MEAS:
+ return tcg_pts_attr_file_meas_create_from_data(length, value);
+ case TCG_PTS_REQ_FILE_META:
+ return tcg_pts_attr_req_file_meta_create_from_data(length, value);
+ case TCG_PTS_UNIX_FILE_META:
+ return tcg_pts_attr_unix_file_meta_create_from_data(length, value);
+ /* unsupported TCG/SWID attributes */
+ case TCG_SWID_TAG_ID_EVENTS:
+ case TCG_SWID_TAG_EVENTS:
+ /* unsupported TCG/PTS attributes */
+ case TCG_PTS_REQ_TEMPL_REF_MANI_SET_META:
+ case TCG_PTS_TEMPL_REF_MANI_SET_META:
+ case TCG_PTS_UPDATE_TEMPL_REF_MANI:
+ case TCG_PTS_VERIFICATION_RESULT:
+ case TCG_PTS_INTEG_REPORT:
+ case TCG_PTS_WIN_FILE_META:
+ case TCG_PTS_REQ_REGISTRY_VALUE:
+ case TCG_PTS_REGISTRY_VALUE:
+ case TCG_PTS_REQ_INTEG_MEAS_LOG:
+ case TCG_PTS_INTEG_MEAS_LOG:
+ default:
+ return NULL;
+ }
+}
diff --git a/src/libimcv/tcg/tcg_attr.h b/src/libimcv/tcg/tcg_attr.h
new file mode 100644
index 000000000..9523f8e18
--- /dev/null
+++ b/src/libimcv/tcg/tcg_attr.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2011-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup tcg_attr tcg_attr
+ * @{ @ingroup libimcv
+ */
+
+#ifndef TCG_ATTR_H_
+#define TCG_ATTR_H_
+
+#include <pa_tnc/pa_tnc_attr.h>
+#include <library.h>
+
+typedef enum tcg_attr_t tcg_attr_t;
+
+/**
+ * TCG PTS IF-M Attributes (section 4 of PTS PROTO: Binding to TNC IF-M)
+ */
+enum tcg_attr_t {
+
+ /* SCAP Attributes */
+ TCG_SCAP_REFERENCES = 0x00000001,
+ TCG_SCAP_CAPS_AND_INVENTORY = 0x00000002,
+ TCG_SCAP_CONTENT = 0x00000003,
+ TCG_SCAP_ASSESSMENT = 0x00000004,
+ TCG_SCAP_RESULTS = 0x00000005,
+ TCG_SCAP_SUMMARY_RESULTS = 0x00000006,
+
+ /* SWID Attributes */
+ TCG_SWID_REQUEST = 0x00000011,
+ TCG_SWID_TAG_ID_INVENTORY = 0x00000012,
+ TCG_SWID_TAG_ID_EVENTS = 0x00000013,
+ TCG_SWID_TAG_INVENTORY = 0x00000014,
+ TCG_SWID_TAG_EVENTS = 0x00000015,
+
+ /* IF-M Attribute Segmentation */
+ TCG_SEG_MAX_ATTR_SIZE_REQ = 0x00000021,
+ TCG_SEG_MAX_ATTR_SIZE_RESP = 0x00000022,
+ TCG_SEG_ATTR_SEG_ENV = 0x00000023,
+ TCG_SEG_NEXT_SEG_REQ = 0x00000024,
+ TCG_SEG_CANCEL_SEG_EXCH = 0x00000025,
+
+ /* PTS Protocol Negotiations */
+ TCG_PTS_REQ_PROTO_CAPS = 0x01000000,
+ TCG_PTS_PROTO_CAPS = 0x02000000,
+ TCG_PTS_DH_NONCE_PARAMS_REQ = 0x03000000,
+ TCG_PTS_DH_NONCE_PARAMS_RESP = 0x04000000,
+ TCG_PTS_DH_NONCE_FINISH = 0x05000000,
+ TCG_PTS_MEAS_ALGO = 0x06000000,
+ TCG_PTS_MEAS_ALGO_SELECTION = 0x07000000,
+ TCG_PTS_GET_TPM_VERSION_INFO = 0x08000000,
+ TCG_PTS_TPM_VERSION_INFO = 0x09000000,
+ TCG_PTS_REQ_TEMPL_REF_MANI_SET_META = 0x0A000000,
+ TCG_PTS_TEMPL_REF_MANI_SET_META = 0x0B000000,
+ TCG_PTS_UPDATE_TEMPL_REF_MANI = 0x0C000000,
+ TCG_PTS_GET_AIK = 0x0D000000,
+ TCG_PTS_AIK = 0x0E000000,
+
+ /* PTS-based Attestation Evidence */
+ TCG_PTS_REQ_FUNC_COMP_EVID = 0x00100000,
+ TCG_PTS_GEN_ATTEST_EVID = 0x00200000,
+ TCG_PTS_SIMPLE_COMP_EVID = 0x00300000,
+ TCG_PTS_SIMPLE_EVID_FINAL = 0x00400000,
+ TCG_PTS_VERIFICATION_RESULT = 0x00500000,
+ TCG_PTS_INTEG_REPORT = 0x00600000,
+ TCG_PTS_REQ_FILE_META = 0x00700000,
+ TCG_PTS_WIN_FILE_META = 0x00800000,
+ TCG_PTS_UNIX_FILE_META = 0x00900000,
+ TCG_PTS_REQ_REGISTRY_VALUE = 0x00A00000,
+ TCG_PTS_REGISTRY_VALUE = 0x00B00000,
+ TCG_PTS_REQ_FILE_MEAS = 0x00C00000,
+ TCG_PTS_FILE_MEAS = 0x00D00000,
+ TCG_PTS_REQ_INTEG_MEAS_LOG = 0x00E00000,
+ TCG_PTS_INTEG_MEAS_LOG = 0x00F00000,
+};
+
+/**
+ * enum name for tcg_attr_t.
+ */
+extern enum_name_t *tcg_attr_names;
+
+/**
+ * Create a TCG PA-TNC attribute from data
+ *
+ * @param type attribute type
+ * @param length attribute length
+ * @param value attribute value or segment
+ */
+pa_tnc_attr_t* tcg_attr_create_from_data(u_int32_t type, size_t length,
+ chunk_t value);
+
+#endif /** TCG_ATTR_H_ @}*/