Merged libpts into libimcv
authorAndreas Steffen <andreas.steffen@strongswan.org>
Fri, 29 Aug 2014 10:18:21 +0000 (12:18 +0200)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Sun, 5 Oct 2014 10:55:37 +0000 (12:55 +0200)
303 files changed:
configure.ac
src/Makefile.am
src/checksum/Makefile.am
src/libimcv/Android.mk
src/libimcv/Makefile.am
src/libimcv/imc/imc_msg.c
src/libimcv/imcv.c
src/libimcv/imcv.h
src/libimcv/imv/imv_msg.c
src/libimcv/plugins/imc_attestation/Makefile.am [new file with mode: 0644]
src/libimcv/plugins/imc_attestation/imc_attestation.c [new file with mode: 0644]
src/libimcv/plugins/imc_attestation/imc_attestation_process.c [new file with mode: 0644]
src/libimcv/plugins/imc_attestation/imc_attestation_process.h [new file with mode: 0644]
src/libimcv/plugins/imc_attestation/imc_attestation_state.c [new file with mode: 0644]
src/libimcv/plugins/imc_attestation/imc_attestation_state.h [new file with mode: 0644]
src/libimcv/plugins/imc_swid/.gitignore [new file with mode: 0644]
src/libimcv/plugins/imc_swid/Makefile.am [new file with mode: 0644]
src/libimcv/plugins/imc_swid/imc_swid.c [new file with mode: 0644]
src/libimcv/plugins/imc_swid/imc_swid_state.c [new file with mode: 0644]
src/libimcv/plugins/imc_swid/imc_swid_state.h [new file with mode: 0644]
src/libimcv/plugins/imc_swid/regid.1999-03.org.debian/regid.1999-03.org.debian_apache-2-2-22-13.swidtag [new file with mode: 0644]
src/libimcv/plugins/imc_swid/regid.1999-03.org.debian/regid.1999-03.org.debian_bind-9-8-4-dfsg.swidtag [new file with mode: 0644]
src/libimcv/plugins/imc_swid/regid.1999-03.org.debian/regid.1999-03.org.debian_libsqlite-3-7-13-1.swidtag [new file with mode: 0644]
src/libimcv/plugins/imc_swid/regid.1999-03.org.debian/regid.1999-03.org.debian_libssl-1-0-1e-2.swidtag [new file with mode: 0644]
src/libimcv/plugins/imc_swid/regid.1999-03.org.debian/regid.1999-03.org.debian_libssl-dev-1-0-1e-2.swidtag [new file with mode: 0644]
src/libimcv/plugins/imc_swid/regid.1999-03.org.debian/regid.1999-03.org.debian_openssl-1-0-1e-2.swidtag [new file with mode: 0644]
src/libimcv/plugins/imc_swid/regid.1999-03.org.debian/regid.1999-03.org.debian_sqlite-3-7-13-1.swidtag [new file with mode: 0644]
src/libimcv/plugins/imc_swid/regid.2004-03.org.strongswan_strongSwan.swidtag.in [new file with mode: 0644]
src/libimcv/plugins/imv_attestation/.gitignore [new file with mode: 0644]
src/libimcv/plugins/imv_attestation/Makefile.am [new file with mode: 0644]
src/libimcv/plugins/imv_attestation/attest.c [new file with mode: 0644]
src/libimcv/plugins/imv_attestation/attest_db.c [new file with mode: 0644]
src/libimcv/plugins/imv_attestation/attest_db.h [new file with mode: 0644]
src/libimcv/plugins/imv_attestation/attest_usage.c [new file with mode: 0644]
src/libimcv/plugins/imv_attestation/attest_usage.h [new file with mode: 0644]
src/libimcv/plugins/imv_attestation/build-database.sh [new file with mode: 0755]
src/libimcv/plugins/imv_attestation/imv_attestation.c [new file with mode: 0644]
src/libimcv/plugins/imv_attestation/imv_attestation_agent.c [new file with mode: 0644]
src/libimcv/plugins/imv_attestation/imv_attestation_agent.h [new file with mode: 0644]
src/libimcv/plugins/imv_attestation/imv_attestation_build.c [new file with mode: 0644]
src/libimcv/plugins/imv_attestation/imv_attestation_build.h [new file with mode: 0644]
src/libimcv/plugins/imv_attestation/imv_attestation_process.c [new file with mode: 0644]
src/libimcv/plugins/imv_attestation/imv_attestation_process.h [new file with mode: 0644]
src/libimcv/plugins/imv_attestation/imv_attestation_state.c [new file with mode: 0644]
src/libimcv/plugins/imv_attestation/imv_attestation_state.h [new file with mode: 0644]
src/libimcv/plugins/imv_swid/Makefile.am [new file with mode: 0644]
src/libimcv/plugins/imv_swid/imv_swid.c [new file with mode: 0644]
src/libimcv/plugins/imv_swid/imv_swid_agent.c [new file with mode: 0644]
src/libimcv/plugins/imv_swid/imv_swid_agent.h [new file with mode: 0644]
src/libimcv/plugins/imv_swid/imv_swid_rest.c [new file with mode: 0644]
src/libimcv/plugins/imv_swid/imv_swid_rest.h [new file with mode: 0644]
src/libimcv/plugins/imv_swid/imv_swid_state.c [new file with mode: 0644]
src/libimcv/plugins/imv_swid/imv_swid_state.h [new file with mode: 0644]
src/libimcv/pts/components/ita/ita_comp_func_name.c [new file with mode: 0644]
src/libimcv/pts/components/ita/ita_comp_func_name.h [new file with mode: 0644]
src/libimcv/pts/components/ita/ita_comp_ima.c [new file with mode: 0644]
src/libimcv/pts/components/ita/ita_comp_ima.h [new file with mode: 0644]
src/libimcv/pts/components/ita/ita_comp_tboot.c [new file with mode: 0644]
src/libimcv/pts/components/ita/ita_comp_tboot.h [new file with mode: 0644]
src/libimcv/pts/components/ita/ita_comp_tgrub.c [new file with mode: 0644]
src/libimcv/pts/components/ita/ita_comp_tgrub.h [new file with mode: 0644]
src/libimcv/pts/components/pts_comp_evidence.c [new file with mode: 0644]
src/libimcv/pts/components/pts_comp_evidence.h [new file with mode: 0644]
src/libimcv/pts/components/pts_comp_func_name.c [new file with mode: 0644]
src/libimcv/pts/components/pts_comp_func_name.h [new file with mode: 0644]
src/libimcv/pts/components/pts_component.h [new file with mode: 0644]
src/libimcv/pts/components/pts_component_manager.c [new file with mode: 0644]
src/libimcv/pts/components/pts_component_manager.h [new file with mode: 0644]
src/libimcv/pts/components/tcg/tcg_comp_func_name.c [new file with mode: 0644]
src/libimcv/pts/components/tcg/tcg_comp_func_name.h [new file with mode: 0644]
src/libimcv/pts/pts.c [new file with mode: 0644]
src/libimcv/pts/pts.h [new file with mode: 0644]
src/libimcv/pts/pts_creds.c [new file with mode: 0644]
src/libimcv/pts/pts_creds.h [new file with mode: 0644]
src/libimcv/pts/pts_database.c [new file with mode: 0644]
src/libimcv/pts/pts_database.h [new file with mode: 0644]
src/libimcv/pts/pts_dh_group.c [new file with mode: 0644]
src/libimcv/pts/pts_dh_group.h [new file with mode: 0644]
src/libimcv/pts/pts_error.c [new file with mode: 0644]
src/libimcv/pts/pts_error.h [new file with mode: 0644]
src/libimcv/pts/pts_file_meas.c [new file with mode: 0644]
src/libimcv/pts/pts_file_meas.h [new file with mode: 0644]
src/libimcv/pts/pts_file_meta.c [new file with mode: 0644]
src/libimcv/pts/pts_file_meta.h [new file with mode: 0644]
src/libimcv/pts/pts_file_type.c [new file with mode: 0644]
src/libimcv/pts/pts_file_type.h [new file with mode: 0644]
src/libimcv/pts/pts_ima_bios_list.c [new file with mode: 0644]
src/libimcv/pts/pts_ima_bios_list.h [new file with mode: 0644]
src/libimcv/pts/pts_ima_event_list.c [new file with mode: 0644]
src/libimcv/pts/pts_ima_event_list.h [new file with mode: 0644]
src/libimcv/pts/pts_meas_algo.c [new file with mode: 0644]
src/libimcv/pts/pts_meas_algo.h [new file with mode: 0644]
src/libimcv/pts/pts_pcr.c [new file with mode: 0644]
src/libimcv/pts/pts_pcr.h [new file with mode: 0644]
src/libimcv/pts/pts_proto_caps.h [new file with mode: 0644]
src/libimcv/pts/pts_req_func_comp_evid.h [new file with mode: 0644]
src/libimcv/pts/pts_simple_evid_final.h [new file with mode: 0644]
src/libimcv/seg/seg_contract.c
src/libimcv/seg/seg_env.c
src/libimcv/swid/swid_error.c [new file with mode: 0644]
src/libimcv/swid/swid_error.h [new file with mode: 0644]
src/libimcv/swid/swid_inventory.c [new file with mode: 0644]
src/libimcv/swid/swid_inventory.h [new file with mode: 0644]
src/libimcv/swid/swid_tag.c [new file with mode: 0644]
src/libimcv/swid/swid_tag.h [new file with mode: 0644]
src/libimcv/swid/swid_tag_id.c [new file with mode: 0644]
src/libimcv/swid/swid_tag_id.h [new file with mode: 0644]
src/libimcv/tcg/pts/tcg_pts_attr_aik.c [new file with mode: 0644]
src/libimcv/tcg/pts/tcg_pts_attr_aik.h [new file with mode: 0644]
src/libimcv/tcg/pts/tcg_pts_attr_dh_nonce_finish.c [new file with mode: 0644]
src/libimcv/tcg/pts/tcg_pts_attr_dh_nonce_finish.h [new file with mode: 0644]
src/libimcv/tcg/pts/tcg_pts_attr_dh_nonce_params_req.c [new file with mode: 0644]
src/libimcv/tcg/pts/tcg_pts_attr_dh_nonce_params_req.h [new file with mode: 0644]
src/libimcv/tcg/pts/tcg_pts_attr_dh_nonce_params_resp.c [new file with mode: 0644]
src/libimcv/tcg/pts/tcg_pts_attr_dh_nonce_params_resp.h [new file with mode: 0644]
src/libimcv/tcg/pts/tcg_pts_attr_file_meas.c [new file with mode: 0644]
src/libimcv/tcg/pts/tcg_pts_attr_file_meas.h [new file with mode: 0644]
src/libimcv/tcg/pts/tcg_pts_attr_gen_attest_evid.c [new file with mode: 0644]
src/libimcv/tcg/pts/tcg_pts_attr_gen_attest_evid.h [new file with mode: 0644]
src/libimcv/tcg/pts/tcg_pts_attr_get_aik.c [new file with mode: 0644]
src/libimcv/tcg/pts/tcg_pts_attr_get_aik.h [new file with mode: 0644]
src/libimcv/tcg/pts/tcg_pts_attr_get_tpm_version_info.c [new file with mode: 0644]
src/libimcv/tcg/pts/tcg_pts_attr_get_tpm_version_info.h [new file with mode: 0644]
src/libimcv/tcg/pts/tcg_pts_attr_meas_algo.c [new file with mode: 0644]
src/libimcv/tcg/pts/tcg_pts_attr_meas_algo.h [new file with mode: 0644]
src/libimcv/tcg/pts/tcg_pts_attr_proto_caps.c [new file with mode: 0644]
src/libimcv/tcg/pts/tcg_pts_attr_proto_caps.h [new file with mode: 0644]
src/libimcv/tcg/pts/tcg_pts_attr_req_file_meas.c [new file with mode: 0644]
src/libimcv/tcg/pts/tcg_pts_attr_req_file_meas.h [new file with mode: 0644]
src/libimcv/tcg/pts/tcg_pts_attr_req_file_meta.c [new file with mode: 0644]
src/libimcv/tcg/pts/tcg_pts_attr_req_file_meta.h [new file with mode: 0644]
src/libimcv/tcg/pts/tcg_pts_attr_req_func_comp_evid.c [new file with mode: 0644]
src/libimcv/tcg/pts/tcg_pts_attr_req_func_comp_evid.h [new file with mode: 0644]
src/libimcv/tcg/pts/tcg_pts_attr_simple_comp_evid.c [new file with mode: 0644]
src/libimcv/tcg/pts/tcg_pts_attr_simple_comp_evid.h [new file with mode: 0644]
src/libimcv/tcg/pts/tcg_pts_attr_simple_evid_final.c [new file with mode: 0644]
src/libimcv/tcg/pts/tcg_pts_attr_simple_evid_final.h [new file with mode: 0644]
src/libimcv/tcg/pts/tcg_pts_attr_tpm_version_info.c [new file with mode: 0644]
src/libimcv/tcg/pts/tcg_pts_attr_tpm_version_info.h [new file with mode: 0644]
src/libimcv/tcg/pts/tcg_pts_attr_unix_file_meta.c [new file with mode: 0644]
src/libimcv/tcg/pts/tcg_pts_attr_unix_file_meta.h [new file with mode: 0644]
src/libimcv/tcg/seg/tcg_seg_attr_max_size.c [new file with mode: 0644]
src/libimcv/tcg/seg/tcg_seg_attr_max_size.h [new file with mode: 0644]
src/libimcv/tcg/seg/tcg_seg_attr_next_seg.c [new file with mode: 0644]
src/libimcv/tcg/seg/tcg_seg_attr_next_seg.h [new file with mode: 0644]
src/libimcv/tcg/seg/tcg_seg_attr_seg_env.c [new file with mode: 0644]
src/libimcv/tcg/seg/tcg_seg_attr_seg_env.h [new file with mode: 0644]
src/libimcv/tcg/swid/tcg_swid_attr_req.c [new file with mode: 0644]
src/libimcv/tcg/swid/tcg_swid_attr_req.h [new file with mode: 0644]
src/libimcv/tcg/swid/tcg_swid_attr_tag_id_inv.c [new file with mode: 0644]
src/libimcv/tcg/swid/tcg_swid_attr_tag_id_inv.h [new file with mode: 0644]
src/libimcv/tcg/swid/tcg_swid_attr_tag_inv.c [new file with mode: 0644]
src/libimcv/tcg/swid/tcg_swid_attr_tag_inv.h [new file with mode: 0644]
src/libimcv/tcg/tcg_attr.c [new file with mode: 0644]
src/libimcv/tcg/tcg_attr.h [new file with mode: 0644]
src/libpts/Android.mk [deleted file]
src/libpts/Makefile.am [deleted file]
src/libpts/libpts.c [deleted file]
src/libpts/libpts.h [deleted file]
src/libpts/plugins/imc_attestation/Makefile.am [deleted file]
src/libpts/plugins/imc_attestation/imc_attestation.c [deleted file]
src/libpts/plugins/imc_attestation/imc_attestation_process.c [deleted file]
src/libpts/plugins/imc_attestation/imc_attestation_process.h [deleted file]
src/libpts/plugins/imc_attestation/imc_attestation_state.c [deleted file]
src/libpts/plugins/imc_attestation/imc_attestation_state.h [deleted file]
src/libpts/plugins/imc_swid/.gitignore [deleted file]
src/libpts/plugins/imc_swid/Makefile.am [deleted file]
src/libpts/plugins/imc_swid/imc_swid.c [deleted file]
src/libpts/plugins/imc_swid/imc_swid_state.c [deleted file]
src/libpts/plugins/imc_swid/imc_swid_state.h [deleted file]
src/libpts/plugins/imc_swid/regid.1999-03.org.debian/regid.1999-03.org.debian_apache-2-2-22-13.swidtag [deleted file]
src/libpts/plugins/imc_swid/regid.1999-03.org.debian/regid.1999-03.org.debian_bind-9-8-4-dfsg.swidtag [deleted file]
src/libpts/plugins/imc_swid/regid.1999-03.org.debian/regid.1999-03.org.debian_libsqlite-3-7-13-1.swidtag [deleted file]
src/libpts/plugins/imc_swid/regid.1999-03.org.debian/regid.1999-03.org.debian_libssl-1-0-1e-2.swidtag [deleted file]
src/libpts/plugins/imc_swid/regid.1999-03.org.debian/regid.1999-03.org.debian_libssl-dev-1-0-1e-2.swidtag [deleted file]
src/libpts/plugins/imc_swid/regid.1999-03.org.debian/regid.1999-03.org.debian_openssl-1-0-1e-2.swidtag [deleted file]
src/libpts/plugins/imc_swid/regid.1999-03.org.debian/regid.1999-03.org.debian_sqlite-3-7-13-1.swidtag [deleted file]
src/libpts/plugins/imc_swid/regid.2004-03.org.strongswan_strongSwan.swidtag.in [deleted file]
src/libpts/plugins/imv_attestation/.gitignore [deleted file]
src/libpts/plugins/imv_attestation/Makefile.am [deleted file]
src/libpts/plugins/imv_attestation/attest.c [deleted file]
src/libpts/plugins/imv_attestation/attest_db.c [deleted file]
src/libpts/plugins/imv_attestation/attest_db.h [deleted file]
src/libpts/plugins/imv_attestation/attest_usage.c [deleted file]
src/libpts/plugins/imv_attestation/attest_usage.h [deleted file]
src/libpts/plugins/imv_attestation/build-database.sh [deleted file]
src/libpts/plugins/imv_attestation/imv_attestation.c [deleted file]
src/libpts/plugins/imv_attestation/imv_attestation_agent.c [deleted file]
src/libpts/plugins/imv_attestation/imv_attestation_agent.h [deleted file]
src/libpts/plugins/imv_attestation/imv_attestation_build.c [deleted file]
src/libpts/plugins/imv_attestation/imv_attestation_build.h [deleted file]
src/libpts/plugins/imv_attestation/imv_attestation_process.c [deleted file]
src/libpts/plugins/imv_attestation/imv_attestation_process.h [deleted file]
src/libpts/plugins/imv_attestation/imv_attestation_state.c [deleted file]
src/libpts/plugins/imv_attestation/imv_attestation_state.h [deleted file]
src/libpts/plugins/imv_swid/Makefile.am [deleted file]
src/libpts/plugins/imv_swid/imv_swid.c [deleted file]
src/libpts/plugins/imv_swid/imv_swid_agent.c [deleted file]
src/libpts/plugins/imv_swid/imv_swid_agent.h [deleted file]
src/libpts/plugins/imv_swid/imv_swid_rest.c [deleted file]
src/libpts/plugins/imv_swid/imv_swid_rest.h [deleted file]
src/libpts/plugins/imv_swid/imv_swid_state.c [deleted file]
src/libpts/plugins/imv_swid/imv_swid_state.h [deleted file]
src/libpts/pts/components/ita/ita_comp_func_name.c [deleted file]
src/libpts/pts/components/ita/ita_comp_func_name.h [deleted file]
src/libpts/pts/components/ita/ita_comp_ima.c [deleted file]
src/libpts/pts/components/ita/ita_comp_ima.h [deleted file]
src/libpts/pts/components/ita/ita_comp_tboot.c [deleted file]
src/libpts/pts/components/ita/ita_comp_tboot.h [deleted file]
src/libpts/pts/components/ita/ita_comp_tgrub.c [deleted file]
src/libpts/pts/components/ita/ita_comp_tgrub.h [deleted file]
src/libpts/pts/components/pts_comp_evidence.c [deleted file]
src/libpts/pts/components/pts_comp_evidence.h [deleted file]
src/libpts/pts/components/pts_comp_func_name.c [deleted file]
src/libpts/pts/components/pts_comp_func_name.h [deleted file]
src/libpts/pts/components/pts_component.h [deleted file]
src/libpts/pts/components/pts_component_manager.c [deleted file]
src/libpts/pts/components/pts_component_manager.h [deleted file]
src/libpts/pts/components/tcg/tcg_comp_func_name.c [deleted file]
src/libpts/pts/components/tcg/tcg_comp_func_name.h [deleted file]
src/libpts/pts/pts.c [deleted file]
src/libpts/pts/pts.h [deleted file]
src/libpts/pts/pts_creds.c [deleted file]
src/libpts/pts/pts_creds.h [deleted file]
src/libpts/pts/pts_database.c [deleted file]
src/libpts/pts/pts_database.h [deleted file]
src/libpts/pts/pts_dh_group.c [deleted file]
src/libpts/pts/pts_dh_group.h [deleted file]
src/libpts/pts/pts_error.c [deleted file]
src/libpts/pts/pts_error.h [deleted file]
src/libpts/pts/pts_file_meas.c [deleted file]
src/libpts/pts/pts_file_meas.h [deleted file]
src/libpts/pts/pts_file_meta.c [deleted file]
src/libpts/pts/pts_file_meta.h [deleted file]
src/libpts/pts/pts_file_type.c [deleted file]
src/libpts/pts/pts_file_type.h [deleted file]
src/libpts/pts/pts_ima_bios_list.c [deleted file]
src/libpts/pts/pts_ima_bios_list.h [deleted file]
src/libpts/pts/pts_ima_event_list.c [deleted file]
src/libpts/pts/pts_ima_event_list.h [deleted file]
src/libpts/pts/pts_meas_algo.c [deleted file]
src/libpts/pts/pts_meas_algo.h [deleted file]
src/libpts/pts/pts_pcr.c [deleted file]
src/libpts/pts/pts_pcr.h [deleted file]
src/libpts/pts/pts_proto_caps.h [deleted file]
src/libpts/pts/pts_req_func_comp_evid.h [deleted file]
src/libpts/pts/pts_simple_evid_final.h [deleted file]
src/libpts/swid/swid_error.c [deleted file]
src/libpts/swid/swid_error.h [deleted file]
src/libpts/swid/swid_inventory.c [deleted file]
src/libpts/swid/swid_inventory.h [deleted file]
src/libpts/swid/swid_tag.c [deleted file]
src/libpts/swid/swid_tag.h [deleted file]
src/libpts/swid/swid_tag_id.c [deleted file]
src/libpts/swid/swid_tag_id.h [deleted file]
src/libpts/tcg/pts/tcg_pts_attr_aik.c [deleted file]
src/libpts/tcg/pts/tcg_pts_attr_aik.h [deleted file]
src/libpts/tcg/pts/tcg_pts_attr_dh_nonce_finish.c [deleted file]
src/libpts/tcg/pts/tcg_pts_attr_dh_nonce_finish.h [deleted file]
src/libpts/tcg/pts/tcg_pts_attr_dh_nonce_params_req.c [deleted file]
src/libpts/tcg/pts/tcg_pts_attr_dh_nonce_params_req.h [deleted file]
src/libpts/tcg/pts/tcg_pts_attr_dh_nonce_params_resp.c [deleted file]
src/libpts/tcg/pts/tcg_pts_attr_dh_nonce_params_resp.h [deleted file]
src/libpts/tcg/pts/tcg_pts_attr_file_meas.c [deleted file]
src/libpts/tcg/pts/tcg_pts_attr_file_meas.h [deleted file]
src/libpts/tcg/pts/tcg_pts_attr_gen_attest_evid.c [deleted file]
src/libpts/tcg/pts/tcg_pts_attr_gen_attest_evid.h [deleted file]
src/libpts/tcg/pts/tcg_pts_attr_get_aik.c [deleted file]
src/libpts/tcg/pts/tcg_pts_attr_get_aik.h [deleted file]
src/libpts/tcg/pts/tcg_pts_attr_get_tpm_version_info.c [deleted file]
src/libpts/tcg/pts/tcg_pts_attr_get_tpm_version_info.h [deleted file]
src/libpts/tcg/pts/tcg_pts_attr_meas_algo.c [deleted file]
src/libpts/tcg/pts/tcg_pts_attr_meas_algo.h [deleted file]
src/libpts/tcg/pts/tcg_pts_attr_proto_caps.c [deleted file]
src/libpts/tcg/pts/tcg_pts_attr_proto_caps.h [deleted file]
src/libpts/tcg/pts/tcg_pts_attr_req_file_meas.c [deleted file]
src/libpts/tcg/pts/tcg_pts_attr_req_file_meas.h [deleted file]
src/libpts/tcg/pts/tcg_pts_attr_req_file_meta.c [deleted file]
src/libpts/tcg/pts/tcg_pts_attr_req_file_meta.h [deleted file]
src/libpts/tcg/pts/tcg_pts_attr_req_func_comp_evid.c [deleted file]
src/libpts/tcg/pts/tcg_pts_attr_req_func_comp_evid.h [deleted file]
src/libpts/tcg/pts/tcg_pts_attr_simple_comp_evid.c [deleted file]
src/libpts/tcg/pts/tcg_pts_attr_simple_comp_evid.h [deleted file]
src/libpts/tcg/pts/tcg_pts_attr_simple_evid_final.c [deleted file]
src/libpts/tcg/pts/tcg_pts_attr_simple_evid_final.h [deleted file]
src/libpts/tcg/pts/tcg_pts_attr_tpm_version_info.c [deleted file]
src/libpts/tcg/pts/tcg_pts_attr_tpm_version_info.h [deleted file]
src/libpts/tcg/pts/tcg_pts_attr_unix_file_meta.c [deleted file]
src/libpts/tcg/pts/tcg_pts_attr_unix_file_meta.h [deleted file]
src/libpts/tcg/seg/tcg_seg_attr_max_size.c [deleted file]
src/libpts/tcg/seg/tcg_seg_attr_max_size.h [deleted file]
src/libpts/tcg/seg/tcg_seg_attr_next_seg.c [deleted file]
src/libpts/tcg/seg/tcg_seg_attr_next_seg.h [deleted file]
src/libpts/tcg/seg/tcg_seg_attr_seg_env.c [deleted file]
src/libpts/tcg/seg/tcg_seg_attr_seg_env.h [deleted file]
src/libpts/tcg/swid/tcg_swid_attr_req.c [deleted file]
src/libpts/tcg/swid/tcg_swid_attr_req.h [deleted file]
src/libpts/tcg/swid/tcg_swid_attr_tag_id_inv.c [deleted file]
src/libpts/tcg/swid/tcg_swid_attr_tag_id_inv.h [deleted file]
src/libpts/tcg/swid/tcg_swid_attr_tag_inv.c [deleted file]
src/libpts/tcg/swid/tcg_swid_attr_tag_inv.h [deleted file]
src/libpts/tcg/tcg_attr.c [deleted file]
src/libpts/tcg/tcg_attr.h [deleted file]

index 61b99e5..85f7cb3 100644 (file)
@@ -397,10 +397,6 @@ if test x$imc_test = xtrue -o x$imv_test = xtrue -o x$imc_scanner = xtrue -o x$i
        imcv=true;
 fi
 
-if test x$imc_attestation = xtrue -o x$imv_attestation = xtrue -o x$imc_swid = xtrue -o x$imv_swid = xtrue; then
-       pts=true;
-fi
-
 if test x$fips_prf = xtrue; then
        if test x$openssl = xfalse; then
                sha1=true;
@@ -1500,7 +1496,6 @@ AM_CONDITIONAL(USE_SIMAKA, test x$simaka = xtrue)
 AM_CONDITIONAL(USE_TLS, test x$tls = xtrue)
 AM_CONDITIONAL(USE_RADIUS, test x$radius = xtrue)
 AM_CONDITIONAL(USE_IMCV, test x$imcv = xtrue)
-AM_CONDITIONAL(USE_PTS, test x$pts = xtrue)
 AM_CONDITIONAL(USE_TROUSERS, test x$tss = xtrousers -o x$aikgen = xtrue)
 AM_CONDITIONAL(MONOLITHIC, test x$monolithic = xtrue)
 AM_CONDITIONAL(USE_SILENT_RULES, test x$enable_silent_rules = xyes)
@@ -1640,11 +1635,6 @@ AC_CONFIG_FILES([
        src/libtnccs/plugins/tnccs_20/Makefile
        src/libtnccs/plugins/tnccs_dynamic/Makefile
        src/libpttls/Makefile
-       src/libpts/Makefile
-       src/libpts/plugins/imc_attestation/Makefile
-       src/libpts/plugins/imv_attestation/Makefile
-       src/libpts/plugins/imc_swid/Makefile
-       src/libpts/plugins/imv_swid/Makefile
        src/libimcv/Makefile
        src/libimcv/plugins/imc_test/Makefile
        src/libimcv/plugins/imv_test/Makefile
@@ -1652,6 +1642,10 @@ AC_CONFIG_FILES([
        src/libimcv/plugins/imv_scanner/Makefile
        src/libimcv/plugins/imc_os/Makefile
        src/libimcv/plugins/imv_os/Makefile
+       src/libimcv/plugins/imc_attestation/Makefile
+       src/libimcv/plugins/imv_attestation/Makefile
+       src/libimcv/plugins/imc_swid/Makefile
+       src/libimcv/plugins/imv_swid/Makefile
        src/charon/Makefile
        src/charon-nm/Makefile
        src/charon-tkm/Makefile
index 603c9d1..38363d4 100644 (file)
@@ -40,10 +40,6 @@ if USE_IMCV
   SUBDIRS += libimcv
 endif
 
-if USE_PTS
-  SUBDIRS += libpts
-endif
-
 if USE_LIBCHARON
   SUBDIRS += libcharon
 endif
index 821c517..b358699 100644 (file)
@@ -81,11 +81,6 @@ if USE_IMCV
   libs += $(DESTDIR)$(ipseclibdir)/libimcv.so
 endif
 
-if USE_PTS
-  deps += $(top_builddir)/src/libpts/libpts.la
-  libs += $(DESTDIR)$(ipseclibdir)/libpts.so
-endif
-
 if USE_CHARON
   deps += $(top_builddir)/src/libcharon/libcharon.la
   libs += $(DESTDIR)$(ipseclibdir)/libcharon.so
index 4253fe2..d7ea015 100644 (file)
@@ -41,7 +41,59 @@ libimcv_la_SOURCES := \
        os_info/os_info.h os_info/os_info.c \
        pa_tnc/pa_tnc_attr.h \
        pa_tnc/pa_tnc_msg.h pa_tnc/pa_tnc_msg.c \
-       pa_tnc/pa_tnc_attr_manager.h pa_tnc/pa_tnc_attr_manager.c
+       pa_tnc/pa_tnc_attr_manager.h pa_tnc/pa_tnc_attr_manager.c \
+       pts/pts.h pts/pts.c \
+       pts/pts_error.h pts/pts_error.c \
+       pts/pts_pcr.h pts/pts_pcr.c \
+       pts/pts_proto_caps.h \
+       pts/pts_req_func_comp_evid.h \
+       pts/pts_simple_evid_final.h \
+       pts/pts_creds.h pts/pts_creds.c \
+       pts/pts_database.h pts/pts_database.c \
+       pts/pts_dh_group.h pts/pts_dh_group.c \
+       pts/pts_file_meas.h pts/pts_file_meas.c \
+       pts/pts_file_meta.h pts/pts_file_meta.c \
+       pts/pts_file_type.h pts/pts_file_type.c \
+       pts/pts_ima_bios_list.h pts/pts_ima_bios_list.c \
+       pts/pts_ima_event_list.h pts/pts_ima_event_list.c \
+       pts/pts_meas_algo.h pts/pts_meas_algo.c \
+       pts/components/pts_component.h \
+       pts/components/pts_component_manager.h pts/components/pts_component_manager.c \
+       pts/components/pts_comp_evidence.h pts/components/pts_comp_evidence.c \
+       pts/components/pts_comp_func_name.h pts/components/pts_comp_func_name.c \
+       pts/components/ita/ita_comp_func_name.h pts/components/ita/ita_comp_func_name.c \
+       pts/components/ita/ita_comp_ima.h pts/components/ita/ita_comp_ima.c \
+       pts/components/ita/ita_comp_tboot.h pts/components/ita/ita_comp_tboot.c \
+       pts/components/ita/ita_comp_tgrub.h pts/components/ita/ita_comp_tgrub.c \
+       pts/components/tcg/tcg_comp_func_name.h pts/components/tcg/tcg_comp_func_name.c \
+       seg/seg_contract.h seg/seg_contract.c \
+       seg/seg_contract_manager.h seg/seg_contract_manager.c \
+       seg/seg_env.h seg/seg_env.c \
+       swid/swid_error.h swid/swid_error.c \
+       swid/swid_inventory.h swid/swid_inventory.c \
+       swid/swid_tag.h swid/swid_tag.c \
+       swid/swid_tag_id.h swid/swid_tag_id.c \
+       tcg/tcg_attr.h tcg/tcg_attr.c \
+       tcg/pts/tcg_pts_attr_proto_caps.h tcg/pts/tcg_pts_attr_proto_caps.c \
+       tcg/pts/tcg_pts_attr_dh_nonce_params_req.h tcg/pts/tcg_pts_attr_dh_nonce_params_req.c \
+       tcg/pts/tcg_pts_attr_dh_nonce_params_resp.h tcg/pts/tcg_pts_attr_dh_nonce_params_resp.c \
+       tcg/pts/tcg_pts_attr_dh_nonce_finish.h tcg/pts/tcg_pts_attr_dh_nonce_finish.c \
+       tcg/pts/tcg_pts_attr_meas_algo.h tcg/pts/tcg_pts_attr_meas_algo.c \
+       tcg/pts/tcg_pts_attr_get_tpm_version_info.h tcg/pts/tcg_pts_attr_get_tpm_version_info.c \
+       tcg/pts/tcg_pts_attr_tpm_version_info.h tcg/pts/tcg_pts_attr_tpm_version_info.c \
+       tcg/pts/tcg_pts_attr_get_aik.h tcg/pts/tcg_pts_attr_get_aik.c \
+       tcg/pts/tcg_pts_attr_aik.h tcg/pts/tcg_pts_attr_aik.c \
+       tcg/pts/tcg_pts_attr_req_func_comp_evid.h tcg/pts/tcg_pts_attr_req_func_comp_evid.c \
+       tcg/pts/tcg_pts_attr_gen_attest_evid.h tcg/pts/tcg_pts_attr_gen_attest_evid.c \
+       tcg/pts/tcg_pts_attr_simple_comp_evid.h tcg/pts/tcg_pts_attr_simple_comp_evid.c \
+       tcg/pts/tcg_pts_attr_simple_evid_final.h tcg/pts/tcg_pts_attr_simple_evid_final.c \
+       tcg/pts/tcg_pts_attr_req_file_meas.h tcg/pts/tcg_pts_attr_req_file_meas.c \
+       tcg/pts/tcg_pts_attr_file_meas.h tcg/pts/tcg_pts_attr_file_meas.c \
+       tcg/pts/tcg_pts_attr_req_file_meta.h tcg/pts/tcg_pts_attr_req_file_meta.c \
+       tcg/pts/tcg_pts_attr_unix_file_meta.h tcg/pts/tcg_pts_attr_unix_file_meta.c \
+       tcg/swid/tcg_swid_attr_req.h tcg/swid/tcg_swid_attr_req.c \
+       tcg/swid/tcg_swid_attr_tag_id_inv.h tcg/swid/tcg_swid_attr_tag_id_inv.c \
+       tcg/swid/tcg_swid_attr_tag_inv.h tcg/swid/tcg_swid_attr_tag_inv.c
 
 LOCAL_SRC_FILES := $(filter %.c,$(libimcv_la_SOURCES))
 
index 37041d2..5102938 100644 (file)
@@ -12,6 +12,10 @@ libimcv_la_LIBADD = \
        $(top_builddir)/src/libstrongswan/libstrongswan.la \
        $(top_builddir)/src/libtncif/libtncif.la
 
+if USE_TROUSERS
+  libimcv_la_LIBADD += -ltspi
+endif
+
 if USE_WINDOWS
   libimcv_la_LIBADD += -lws2_32
 endif
@@ -56,9 +60,61 @@ libimcv_la_SOURCES = \
        pa_tnc/pa_tnc_attr.h \
        pa_tnc/pa_tnc_msg.h pa_tnc/pa_tnc_msg.c \
        pa_tnc/pa_tnc_attr_manager.h pa_tnc/pa_tnc_attr_manager.c \
+       pts/pts.h pts/pts.c \
+       pts/pts_error.h pts/pts_error.c \
+       pts/pts_pcr.h pts/pts_pcr.c \
+       pts/pts_proto_caps.h \
+       pts/pts_req_func_comp_evid.h \
+       pts/pts_simple_evid_final.h \
+       pts/pts_creds.h pts/pts_creds.c \
+       pts/pts_database.h pts/pts_database.c \
+       pts/pts_dh_group.h pts/pts_dh_group.c \
+       pts/pts_file_meas.h pts/pts_file_meas.c \
+       pts/pts_file_meta.h pts/pts_file_meta.c \
+       pts/pts_file_type.h pts/pts_file_type.c \
+       pts/pts_ima_bios_list.h pts/pts_ima_bios_list.c \
+       pts/pts_ima_event_list.h pts/pts_ima_event_list.c \
+       pts/pts_meas_algo.h pts/pts_meas_algo.c \
+       pts/components/pts_component.h \
+       pts/components/pts_component_manager.h pts/components/pts_component_manager.c \
+       pts/components/pts_comp_evidence.h pts/components/pts_comp_evidence.c \
+       pts/components/pts_comp_func_name.h pts/components/pts_comp_func_name.c \
+       pts/components/ita/ita_comp_func_name.h pts/components/ita/ita_comp_func_name.c \
+       pts/components/ita/ita_comp_ima.h pts/components/ita/ita_comp_ima.c \
+       pts/components/ita/ita_comp_tboot.h pts/components/ita/ita_comp_tboot.c \
+       pts/components/ita/ita_comp_tgrub.h pts/components/ita/ita_comp_tgrub.c \
+       pts/components/tcg/tcg_comp_func_name.h pts/components/tcg/tcg_comp_func_name.c \
        seg/seg_contract.h seg/seg_contract.c \
        seg/seg_contract_manager.h seg/seg_contract_manager.c \
-       seg/seg_env.h seg/seg_env.c
+       seg/seg_env.h seg/seg_env.c \
+       swid/swid_error.h swid/swid_error.c \
+       swid/swid_inventory.h swid/swid_inventory.c \
+       swid/swid_tag.h swid/swid_tag.c \
+       swid/swid_tag_id.h swid/swid_tag_id.c \
+       tcg/tcg_attr.h tcg/tcg_attr.c \
+       tcg/pts/tcg_pts_attr_proto_caps.h tcg/pts/tcg_pts_attr_proto_caps.c \
+       tcg/pts/tcg_pts_attr_dh_nonce_params_req.h tcg/pts/tcg_pts_attr_dh_nonce_params_req.c \
+       tcg/pts/tcg_pts_attr_dh_nonce_params_resp.h tcg/pts/tcg_pts_attr_dh_nonce_params_resp.c \
+       tcg/pts/tcg_pts_attr_dh_nonce_finish.h tcg/pts/tcg_pts_attr_dh_nonce_finish.c \
+       tcg/pts/tcg_pts_attr_meas_algo.h tcg/pts/tcg_pts_attr_meas_algo.c \
+       tcg/pts/tcg_pts_attr_get_tpm_version_info.h tcg/pts/tcg_pts_attr_get_tpm_version_info.c \
+       tcg/pts/tcg_pts_attr_tpm_version_info.h tcg/pts/tcg_pts_attr_tpm_version_info.c \
+       tcg/pts/tcg_pts_attr_get_aik.h tcg/pts/tcg_pts_attr_get_aik.c \
+       tcg/pts/tcg_pts_attr_aik.h tcg/pts/tcg_pts_attr_aik.c \
+       tcg/pts/tcg_pts_attr_req_func_comp_evid.h tcg/pts/tcg_pts_attr_req_func_comp_evid.c \
+       tcg/pts/tcg_pts_attr_gen_attest_evid.h tcg/pts/tcg_pts_attr_gen_attest_evid.c \
+       tcg/pts/tcg_pts_attr_simple_comp_evid.h tcg/pts/tcg_pts_attr_simple_comp_evid.c \
+       tcg/pts/tcg_pts_attr_simple_evid_final.h tcg/pts/tcg_pts_attr_simple_evid_final.c \
+       tcg/pts/tcg_pts_attr_req_file_meas.h tcg/pts/tcg_pts_attr_req_file_meas.c \
+       tcg/pts/tcg_pts_attr_file_meas.h tcg/pts/tcg_pts_attr_file_meas.c \
+       tcg/pts/tcg_pts_attr_req_file_meta.h tcg/pts/tcg_pts_attr_req_file_meta.c \
+       tcg/pts/tcg_pts_attr_unix_file_meta.h tcg/pts/tcg_pts_attr_unix_file_meta.c \
+       tcg/seg/tcg_seg_attr_max_size.h tcg/seg/tcg_seg_attr_max_size.c \
+       tcg/seg/tcg_seg_attr_seg_env.h tcg/seg/tcg_seg_attr_seg_env.c \
+       tcg/seg/tcg_seg_attr_next_seg.h tcg/seg/tcg_seg_attr_next_seg.c \
+       tcg/swid/tcg_swid_attr_req.h tcg/swid/tcg_swid_attr_req.c \
+       tcg/swid/tcg_swid_attr_tag_id_inv.h tcg/swid/tcg_swid_attr_tag_id_inv.c \
+       tcg/swid/tcg_swid_attr_tag_inv.h tcg/swid/tcg_swid_attr_tag_inv.c
 
 ipsec_SCRIPTS = imv/_imv_policy
 EXTRA_DIST = imv/_imv_policy Android.mk
@@ -99,3 +155,19 @@ endif
 if USE_IMV_OS
   SUBDIRS += plugins/imv_os
 endif
+
+if USE_IMC_ATTESTATION
+  SUBDIRS += plugins/imc_attestation
+endif
+
+if USE_IMV_ATTESTATION
+  SUBDIRS += plugins/imv_attestation
+endif
+
+if USE_IMC_SWID
+  SUBDIRS += plugins/imc_swid
+endif
+
+if USE_IMV_SWID
+  SUBDIRS += plugins/imv_swid
+endif
index ce628e4..810a92a 100644 (file)
 #include "ietf/ietf_attr.h"
 #include "ietf/ietf_attr_assess_result.h"
 #include "ietf/ietf_attr_remediation_instr.h"
+#include "tcg/seg/tcg_seg_attr_max_size.h"
+#include "tcg/seg/tcg_seg_attr_seg_env.h"
+#include "tcg/seg/tcg_seg_attr_next_seg.h"
 
 #include <tncif_names.h>
 #include <tncif_pa_subtypes.h>
 
-#include <tcg/seg/tcg_seg_attr_max_size.h>
-#include <tcg/seg/tcg_seg_attr_seg_env.h>
-#include <tcg/seg/tcg_seg_attr_next_seg.h>
-
 #include <pen/pen.h>
 #include <collections/linked_list.h>
 #include <utils/debug.h>
index 30679a3..703da23 100644 (file)
 #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>
@@ -44,6 +52,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 +175,26 @@ bool libimcv_init(bool is_imv)
                                                        ietf_attr_create_from_data, ietf_attr_names);
                imcv_pa_tnc_attributes->add_vendor(imcv_pa_tnc_attributes, PEN_ITA,
                                                        ita_attr_create_from_data, ita_attr_names);
-
+               imcv_pa_tnc_attributes->add_vendor(imcv_pa_tnc_attributes, PEN_TCG,
+                                                       tcg_attr_create_from_data, tcg_attr_names);
+
+               imcv_pts_components = pts_component_manager_create();
+               imcv_pts_components->add_vendor(imcv_pts_components, PEN_TCG,
+                                       pts_tcg_comp_func_names, PTS_TCG_QUALIFIER_TYPE_SIZE,
+                                       pts_tcg_qualifier_flag_names, pts_tcg_qualifier_type_names);
+               imcv_pts_components->add_vendor(imcv_pts_components, PEN_ITA,
+                                       pts_ita_comp_func_names, PTS_ITA_QUALIFIER_TYPE_SIZE,
+                                       pts_ita_qualifier_flag_names, pts_ita_qualifier_type_names);
+
+               imcv_pts_components->add_component(imcv_pts_components, PEN_ITA,
+                                                                         PTS_ITA_COMP_FUNC_NAME_TGRUB,
+                                                                         pts_ita_comp_tgrub_create);
+               imcv_pts_components->add_component(imcv_pts_components, PEN_ITA,
+                                                                         PTS_ITA_COMP_FUNC_NAME_TBOOT,
+                                                                         pts_ita_comp_tboot_create);
+               imcv_pts_components->add_component(imcv_pts_components, PEN_ITA,
+                                                                         PTS_ITA_COMP_FUNC_NAME_IMA,
+                                                                         pts_ita_comp_ima_create);
                if (is_imv)
                {
                        /* instantiate global IMV session manager */
@@ -193,8 +225,13 @@ void libimcv_deinit(void)
 {
        if (ref_put(&libimcv_ref))
        {
+               imcv_pts_components->remove_vendor(imcv_pts_components, PEN_TCG);
+               imcv_pts_components->remove_vendor(imcv_pts_components, PEN_ITA);
+               imcv_pts_components->destroy(imcv_pts_components);
+
                imcv_pa_tnc_attributes->remove_vendor(imcv_pa_tnc_attributes, PEN_IETF);
                imcv_pa_tnc_attributes->remove_vendor(imcv_pa_tnc_attributes, PEN_ITA);
+               imcv_pa_tnc_attributes->remove_vendor(imcv_pa_tnc_attributes, PEN_TCG);
                DESTROY_IF(imcv_pa_tnc_attributes);
                imcv_pa_tnc_attributes = NULL;
                DESTROY_IF(imcv_db);
index 7710388..cfb1903 100644 (file)
@@ -37,6 +37,7 @@
 #include "pa_tnc/pa_tnc_attr_manager.h"
 #include "imv/imv_database.h"
 #include "imv/imv_session_manager.h"
+#include "pts/components/pts_component_manager.h"
 
 #include <library.h>
 
@@ -68,4 +69,9 @@ extern imv_database_t* imcv_db;
  */
 extern imv_session_manager_t* imcv_sessions;
 
+/**
+ * PTS Functional Component manager
+ */
+extern pts_component_manager_t* imcv_pts_components;
+
 #endif /** IMCV_H_ @}*/
index d5f86ba..6c4b998 100644 (file)
 #include "ietf/ietf_attr.h"
 #include "ietf/ietf_attr_assess_result.h"
 #include "ietf/ietf_attr_remediation_instr.h"
+#include "tcg/seg/tcg_seg_attr_max_size.h"
+#include "tcg/seg/tcg_seg_attr_seg_env.h"
+#include "tcg/seg/tcg_seg_attr_next_seg.h"
 
 #include <tncif_names.h>
 #include <tncif_pa_subtypes.h>
 
-#include <tcg/seg/tcg_seg_attr_max_size.h>
-#include <tcg/seg/tcg_seg_attr_seg_env.h>
-#include <tcg/seg/tcg_seg_attr_next_seg.h>
-
 #include <pen/pen.h>
 #include <collections/linked_list.h>
 #include <utils/debug.h>
diff --git a/src/libimcv/plugins/imc_attestation/Makefile.am b/src/libimcv/plugins/imc_attestation/Makefile.am
new file mode 100644 (file)
index 0000000..e7b1f1c
--- /dev/null
@@ -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/imc_attestation.c b/src/libimcv/plugins/imc_attestation/imc_attestation.c
new file mode 100644 (file)
index 0000000..0dd88b6
--- /dev/null
@@ -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 (file)
index 0000000..fbe81ee
--- /dev/null
@@ -0,0 +1,476 @@
+/*
+ * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+/* for isdigit */
+#include <ctype.h>
+
+#include "imc_attestation_process.h"
+
+#include <ietf/ietf_attr_pa_tnc_error.h>
+
+#include <pts/pts.h>
+
+#include <tcg/pts/tcg_pts_attr_proto_caps.h>
+#include <tcg/pts/tcg_pts_attr_meas_algo.h>
+#include <tcg/pts/tcg_pts_attr_dh_nonce_params_req.h>
+#include <tcg/pts/tcg_pts_attr_dh_nonce_params_resp.h>
+#include <tcg/pts/tcg_pts_attr_dh_nonce_finish.h>
+#include <tcg/pts/tcg_pts_attr_get_tpm_version_info.h>
+#include <tcg/pts/tcg_pts_attr_tpm_version_info.h>
+#include <tcg/pts/tcg_pts_attr_get_aik.h>
+#include <tcg/pts/tcg_pts_attr_aik.h>
+#include <tcg/pts/tcg_pts_attr_req_func_comp_evid.h>
+#include <tcg/pts/tcg_pts_attr_gen_attest_evid.h>
+#include <tcg/pts/tcg_pts_attr_simple_comp_evid.h>
+#include <tcg/pts/tcg_pts_attr_simple_evid_final.h>
+#include <tcg/pts/tcg_pts_attr_req_file_meas.h>
+#include <tcg/pts/tcg_pts_attr_file_meas.h>
+#include <tcg/pts/tcg_pts_attr_req_file_meta.h>
+#include <tcg/pts/tcg_pts_attr_unix_file_meta.h>
+
+#include <utils/debug.h>
+#include <utils/lexparser.h>
+
+#define DEFAULT_NONCE_LEN              20
+
+bool imc_attestation_process(pa_tnc_attr_t *attr, imc_msg_t *msg,
+                                                        imc_attestation_state_t *attestation_state,
+                                                        pts_meas_algorithms_t supported_algorithms,
+                                                        pts_dh_group_t supported_dh_groups)
+{
+       chunk_t attr_info;
+       pts_t *pts;
+       pts_error_code_t pts_error;
+       pen_type_t attr_type;
+       bool valid_path;
+
+       pts = attestation_state->get_pts(attestation_state);
+       attr_type = attr->get_type(attr);
+
+       switch (attr_type.type)
+       {
+               case TCG_PTS_REQ_PROTO_CAPS:
+               {
+                       tcg_pts_attr_proto_caps_t *attr_cast;
+                       pts_proto_caps_flag_t imc_caps, imv_caps;
+
+                       attr_cast = (tcg_pts_attr_proto_caps_t*)attr;
+                       imv_caps = attr_cast->get_flags(attr_cast);
+                       imc_caps = pts->get_proto_caps(pts);
+                       pts->set_proto_caps(pts, imc_caps & imv_caps);
+
+                       /* Send PTS Protocol Capabilities attribute */
+                       attr = tcg_pts_attr_proto_caps_create(imc_caps & imv_caps, FALSE);
+                       msg->add_attribute(msg, attr);
+                       break;
+               }
+               case TCG_PTS_MEAS_ALGO:
+               {
+                       tcg_pts_attr_meas_algo_t *attr_cast;
+                       pts_meas_algorithms_t offered_algorithms, selected_algorithm;
+
+                       attr_cast = (tcg_pts_attr_meas_algo_t*)attr;
+                       offered_algorithms = attr_cast->get_algorithms(attr_cast);
+                       selected_algorithm = pts_meas_algo_select(supported_algorithms,
+                                                                                                         offered_algorithms);
+                       if (selected_algorithm == PTS_MEAS_ALGO_NONE)
+                       {
+                               attr = pts_hash_alg_error_create(supported_algorithms);
+                               msg->add_attribute(msg, attr);
+                               break;
+                       }
+
+                       /* Send Measurement Algorithm Selection attribute */
+                       pts->set_meas_algorithm(pts, selected_algorithm);
+                       attr = tcg_pts_attr_meas_algo_create(selected_algorithm, TRUE);
+                       msg->add_attribute(msg, attr);
+                       break;
+               }
+               case TCG_PTS_DH_NONCE_PARAMS_REQ:
+               {
+                       tcg_pts_attr_dh_nonce_params_req_t *attr_cast;
+                       pts_dh_group_t offered_dh_groups, selected_dh_group;
+                       chunk_t responder_value, responder_nonce;
+                       int nonce_len, min_nonce_len;
+
+                       nonce_len = lib->settings->get_int(lib->settings,
+                                                               "%s.plugins.imc-attestation.nonce_len",
+                                                                DEFAULT_NONCE_LEN, lib->ns);
+
+                       attr_cast = (tcg_pts_attr_dh_nonce_params_req_t*)attr;
+                       min_nonce_len = attr_cast->get_min_nonce_len(attr_cast);
+                       if (nonce_len < PTS_MIN_NONCE_LEN ||
+                               (min_nonce_len > 0 && nonce_len < min_nonce_len))
+                       {
+                               attr = pts_dh_nonce_error_create(nonce_len, PTS_MAX_NONCE_LEN);
+                               msg->add_attribute(msg, attr);
+                               break;
+                       }
+
+                       offered_dh_groups = attr_cast->get_dh_groups(attr_cast);
+                       selected_dh_group = pts_dh_group_select(supported_dh_groups,
+                                                                                                       offered_dh_groups);
+                       if (selected_dh_group == PTS_DH_GROUP_NONE)
+                       {
+                               attr = pts_dh_group_error_create(supported_dh_groups);
+                               msg->add_attribute(msg, attr);
+                               break;
+                       }
+
+                       /* Create own DH factor and nonce */
+                       if (!pts->create_dh_nonce(pts, selected_dh_group, nonce_len))
+                       {
+                               return FALSE;
+                       }
+                       pts->get_my_public_value(pts, &responder_value, &responder_nonce);
+
+                       /* Send DH Nonce Parameters Response attribute */
+                       attr = tcg_pts_attr_dh_nonce_params_resp_create(selected_dh_group,
+                                        supported_algorithms, responder_nonce, responder_value);
+                       msg->add_attribute(msg, attr);
+                       break;
+               }
+               case TCG_PTS_DH_NONCE_FINISH:
+               {
+                       tcg_pts_attr_dh_nonce_finish_t *attr_cast;
+                       pts_meas_algorithms_t selected_algorithm;
+                       chunk_t initiator_nonce, initiator_value;
+                       int nonce_len;
+
+                       attr_cast = (tcg_pts_attr_dh_nonce_finish_t*)attr;
+                       selected_algorithm = attr_cast->get_hash_algo(attr_cast);
+                       if (!(selected_algorithm & supported_algorithms))
+                       {
+                               DBG1(DBG_IMC, "PTS-IMV selected unsupported DH hash algorithm");
+                               return FALSE;
+                       }
+                       pts->set_dh_hash_algorithm(pts, selected_algorithm);
+
+                       initiator_value = attr_cast->get_initiator_value(attr_cast);
+                       initiator_nonce = attr_cast->get_initiator_nonce(attr_cast);
+
+                       nonce_len = lib->settings->get_int(lib->settings,
+                                                               "%s.plugins.imc-attestation.nonce_len",
+                                                                DEFAULT_NONCE_LEN, lib->ns);
+                       if (nonce_len != initiator_nonce.len)
+                       {
+                               DBG1(DBG_IMC, "initiator and responder DH nonces "
+                                                         "have differing lengths");
+                               return FALSE;
+                       }
+
+                       pts->set_peer_public_value(pts, initiator_value, initiator_nonce);
+                       if (!pts->calculate_secret(pts))
+                       {
+                               return FALSE;
+                       }
+                       break;
+               }
+               case TCG_PTS_GET_TPM_VERSION_INFO:
+               {
+                       chunk_t tpm_version_info, attr_info;
+                       pen_type_t error_code = { PEN_TCG, TCG_PTS_TPM_VERS_NOT_SUPPORTED };
+
+                       if (!pts->get_tpm_version_info(pts, &tpm_version_info))
+                       {
+                               attr_info = attr->get_value(attr);
+                               attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
+                               msg->add_attribute(msg, attr);
+                               break;
+                       }
+
+                       /* Send TPM Version Info attribute */
+                       attr = tcg_pts_attr_tpm_version_info_create(tpm_version_info);
+                       msg->add_attribute(msg, attr);
+                       break;
+               }
+               case TCG_PTS_GET_AIK:
+               {
+                       certificate_t *aik;
+
+                       aik = pts->get_aik(pts);
+                       if (!aik)
+                       {
+                               DBG1(DBG_IMC, "no AIK certificate or public key available");
+                               break;
+                       }
+
+                       /* Send AIK attribute */
+                       attr = tcg_pts_attr_aik_create(aik);
+                       msg->add_attribute(msg, attr);
+                       break;
+               }
+               case TCG_PTS_REQ_FILE_MEAS:
+               {
+                       tcg_pts_attr_req_file_meas_t *attr_cast;
+                       char *pathname;
+                       u_int16_t request_id;
+                       bool is_directory;
+                       u_int32_t delimiter;
+                       pts_file_meas_t *measurements;
+                       pen_type_t error_code;
+
+                       attr_info = attr->get_value(attr);
+                       attr_cast = (tcg_pts_attr_req_file_meas_t*)attr;
+                       is_directory = attr_cast->get_directory_flag(attr_cast);
+                       request_id = attr_cast->get_request_id(attr_cast);
+                       delimiter = attr_cast->get_delimiter(attr_cast);
+                       pathname = attr_cast->get_pathname(attr_cast);
+                       valid_path = pts->is_path_valid(pts, pathname, &pts_error);
+
+                       if (valid_path && pts_error)
+                       {
+                               error_code = pen_type_create(PEN_TCG, pts_error);
+                               attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
+                               msg->add_attribute(msg, attr);
+                               break;
+                       }
+                       else if (!valid_path)
+                       {
+                               break;
+                       }
+
+                       if (delimiter != SOLIDUS_UTF && delimiter != REVERSE_SOLIDUS_UTF)
+                       {
+                               error_code = pen_type_create(PEN_TCG,
+                                                                                        TCG_PTS_INVALID_DELIMITER);
+                               attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
+                               msg->add_attribute(msg, attr);
+                               break;
+                       }
+
+                       /* Do PTS File Measurements and send them to PTS-IMV */
+                       DBG2(DBG_IMC, "measurement request %d for %s '%s'",
+                                request_id, is_directory ? "directory" : "file",
+                                pathname);
+                       measurements = pts_file_meas_create_from_path(request_id,
+                                                                               pathname, is_directory, TRUE,
+                                                                               pts->get_meas_algorithm(pts));
+                       if (!measurements)
+                       {
+                               /* TODO handle error codes from measurements */
+                               return FALSE;
+                       }
+                       attr = tcg_pts_attr_file_meas_create(measurements);
+                       attr->set_noskip_flag(attr, TRUE);
+                       msg->add_attribute(msg, attr);
+                       break;
+               }
+               case TCG_PTS_REQ_FILE_META:
+               {
+                       tcg_pts_attr_req_file_meta_t *attr_cast;
+                       char *pathname;
+                       bool is_directory;
+                       u_int8_t delimiter;
+                       pts_file_meta_t *metadata;
+                       pen_type_t error_code;
+
+                       attr_info = attr->get_value(attr);
+                       attr_cast = (tcg_pts_attr_req_file_meta_t*)attr;
+                       is_directory = attr_cast->get_directory_flag(attr_cast);
+                       delimiter = attr_cast->get_delimiter(attr_cast);
+                       pathname = attr_cast->get_pathname(attr_cast);
+
+                       valid_path = pts->is_path_valid(pts, pathname, &pts_error);
+                       if (valid_path && pts_error)
+                       {
+                               error_code = pen_type_create(PEN_TCG, pts_error);
+                               attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
+                               msg->add_attribute(msg, attr);
+                               break;
+                       }
+                       else if (!valid_path)
+                       {
+                               break;
+                       }
+                       if (delimiter != SOLIDUS_UTF && delimiter != REVERSE_SOLIDUS_UTF)
+                       {
+                               error_code = pen_type_create(PEN_TCG,
+                                                                                        TCG_PTS_INVALID_DELIMITER);
+                               attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
+                               msg->add_attribute(msg, attr);
+                               break;
+                       }
+                       /* Get File Metadata and send them to PTS-IMV */
+                       DBG2(DBG_IMC, "metadata request for %s '%s'",
+                                       is_directory ? "directory" : "file",
+                                       pathname);
+                       metadata = pts->get_metadata(pts, pathname, is_directory);
+
+                       if (!metadata)
+                       {
+                               /* TODO handle error codes from measurements */
+                               return FALSE;
+                       }
+                       attr = tcg_pts_attr_unix_file_meta_create(metadata);
+                       attr->set_noskip_flag(attr, TRUE);
+                       msg->add_attribute(msg, attr);
+                       break;
+               }
+               case TCG_PTS_REQ_FUNC_COMP_EVID:
+               {
+                       tcg_pts_attr_req_func_comp_evid_t *attr_cast;
+                       pts_proto_caps_flag_t negotiated_caps;
+                       pts_comp_func_name_t *name;
+                       pts_comp_evidence_t *evid;
+                       pts_component_t *comp;
+                       pen_type_t error_code;
+                       u_int32_t depth;
+                       u_int8_t flags;
+                       status_t status;
+                       enumerator_t *e;
+
+                       attr_info = attr->get_value(attr);
+                       attr_cast = (tcg_pts_attr_req_func_comp_evid_t*)attr;
+
+                       DBG1(DBG_IMC, "evidence requested for %d functional components",
+                                                  attr_cast->get_count(attr_cast));
+
+                       e = attr_cast->create_enumerator(attr_cast);
+                       while (e->enumerate(e, &flags, &depth, &name))
+                       {
+                               name->log(name, "* ");
+                               negotiated_caps = pts->get_proto_caps(pts);
+
+                               if (flags & PTS_REQ_FUNC_COMP_EVID_TTC)
+                               {
+                                       error_code = pen_type_create(PEN_TCG,
+                                                                                                TCG_PTS_UNABLE_DET_TTC);
+                                       attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
+                                       msg->add_attribute(msg, attr);
+                                       break;
+                               }
+                               if (flags & PTS_REQ_FUNC_COMP_EVID_VER &&
+                                       !(negotiated_caps & PTS_PROTO_CAPS_V))
+                               {
+                                       error_code = pen_type_create(PEN_TCG,
+                                                                                                TCG_PTS_UNABLE_LOCAL_VAL);
+                                       attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
+                                       msg->add_attribute(msg, attr);
+                                       break;
+                               }
+                               if (flags & PTS_REQ_FUNC_COMP_EVID_CURR &&
+                                       !(negotiated_caps & PTS_PROTO_CAPS_C))
+                               {
+                                       error_code = pen_type_create(PEN_TCG,
+                                                                                                TCG_PTS_UNABLE_CUR_EVID);
+                                       attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
+                                       msg->add_attribute(msg, attr);
+                                       break;
+                               }
+                               if (flags & PTS_REQ_FUNC_COMP_EVID_PCR &&
+                                       !(negotiated_caps & PTS_PROTO_CAPS_T))
+                               {
+                                       error_code = pen_type_create(PEN_TCG,
+                                                                                                TCG_PTS_UNABLE_DET_PCR);
+                                       attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
+                                       msg->add_attribute(msg, attr);
+                                       break;
+                               }
+                               if (depth > 0)
+                               {
+                                       DBG1(DBG_IMC, "the Attestation IMC currently does not "
+                                                                 "support sub component measurements");
+                                       return FALSE;
+                               }
+                               comp = attestation_state->create_component(attestation_state,
+                                                                                                                  name, depth);
+                               if (!comp)
+                               {
+                                       DBG2(DBG_IMC, "    not registered: no evidence provided");
+                                       continue;
+                               }
+
+                               /* do the component evidence measurement[s] and cache them */
+                               do
+                               {
+                                       status = comp->measure(comp, name->get_qualifier(name),
+                                                                                  pts, &evid);
+                                       if (status == FAILED)
+                                       {
+                                               break;
+                                       }
+                                       attestation_state->add_evidence(attestation_state, evid);
+                               }
+                               while (status == NEED_MORE);
+                       }
+                       e->destroy(e);
+                       break;
+               }
+               case TCG_PTS_GEN_ATTEST_EVID:
+               {
+                       pts_simple_evid_final_flag_t flags;
+                       pts_meas_algorithms_t comp_hash_algorithm;
+                       pts_comp_evidence_t *evid;
+                       chunk_t pcr_composite, quote_sig;
+                       bool use_quote2;
+
+                       /* Send cached Component Evidence entries */
+                       while (attestation_state->next_evidence(attestation_state, &evid))
+                       {
+                               attr = tcg_pts_attr_simple_comp_evid_create(evid);
+                               msg->add_attribute(msg, attr);
+                       }
+
+                       use_quote2 = lib->settings->get_bool(lib->settings,
+                                                       "%s.plugins.imc-attestation.use_quote2", TRUE,
+                                                       lib->ns);
+                       if (!pts->quote_tpm(pts, use_quote2, &pcr_composite, &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;
+               }
+               /* TODO: Not implemented yet */
+               case TCG_PTS_REQ_INTEG_MEAS_LOG:
+               /* Attributes using XML */
+               case TCG_PTS_REQ_TEMPL_REF_MANI_SET_META:
+               case TCG_PTS_UPDATE_TEMPL_REF_MANI:
+               /* On Windows only*/
+               case TCG_PTS_REQ_REGISTRY_VALUE:
+               /* Received on IMV side only*/
+               case TCG_PTS_PROTO_CAPS:
+               case TCG_PTS_DH_NONCE_PARAMS_RESP:
+               case TCG_PTS_MEAS_ALGO_SELECTION:
+               case TCG_PTS_TPM_VERSION_INFO:
+               case TCG_PTS_TEMPL_REF_MANI_SET_META:
+               case TCG_PTS_AIK:
+               case TCG_PTS_SIMPLE_COMP_EVID:
+               case TCG_PTS_SIMPLE_EVID_FINAL:
+               case TCG_PTS_VERIFICATION_RESULT:
+               case TCG_PTS_INTEG_REPORT:
+               case TCG_PTS_UNIX_FILE_META:
+               case TCG_PTS_FILE_MEAS:
+               case TCG_PTS_INTEG_MEAS_LOG:
+               default:
+                       DBG1(DBG_IMC, "received unsupported attribute '%N'",
+                               tcg_attr_names, attr->get_type(attr));
+                       break;
+       }
+       return TRUE;
+}
diff --git a/src/libimcv/plugins/imc_attestation/imc_attestation_process.h b/src/libimcv/plugins/imc_attestation/imc_attestation_process.h
new file mode 100644 (file)
index 0000000..a2f1b4e
--- /dev/null
@@ -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 (file)
index 0000000..0b594cb
--- /dev/null
@@ -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 (file)
index 0000000..854c882
--- /dev/null
@@ -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_swid/.gitignore b/src/libimcv/plugins/imc_swid/.gitignore
new file mode 100644 (file)
index 0000000..448ad2f
--- /dev/null
@@ -0,0 +1 @@
+regid.2004-03.org.strongswan*.swidtag
diff --git a/src/libimcv/plugins/imc_swid/Makefile.am b/src/libimcv/plugins/imc_swid/Makefile.am
new file mode 100644 (file)
index 0000000..c1cdb98
--- /dev/null
@@ -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/imc_swid.c b/src/libimcv/plugins/imc_swid/imc_swid.c
new file mode 100644 (file)
index 0000000..86e2693
--- /dev/null
@@ -0,0 +1,447 @@
+/*
+ * Copyright (C) 2013-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "imc_swid_state.h"
+
+#include <imc/imc_agent.h>
+#include <imc/imc_msg.h>
+#include <ita/ita_attr.h>
+#include <ita/ita_attr_angel.h>
+#include "tcg/swid/tcg_swid_attr_req.h"
+#include "tcg/swid/tcg_swid_attr_tag_inv.h"
+#include "tcg/swid/tcg_swid_attr_tag_id_inv.h"
+#include "swid/swid_inventory.h"
+#include "swid/swid_error.h"
+
+#include <tncif_pa_subtypes.h>
+
+#include <pen/pen.h>
+#include <utils/debug.h>
+
+#define SWID_GENERATOR "/usr/local/bin/swid_generator"
+
+/* IMC definitions */
+
+static const char imc_name[] = "SWID";
+
+static pen_type_t msg_types[] = {
+       { PEN_TCG, PA_SUBTYPE_TCG_SWID }
+};
+
+static imc_agent_t *imc_swid;
+
+/**
+ * see section 3.8.1 of TCG TNC IF-IMC Specification 1.3
+ */
+TNC_Result TNC_IMC_Initialize(TNC_IMCID imc_id,
+                                                         TNC_Version min_version,
+                                                         TNC_Version max_version,
+                                                         TNC_Version *actual_version)
+{
+       if (imc_swid)
+       {
+               DBG1(DBG_IMC, "IMC \"%s\" has already been initialized", imc_name);
+               return TNC_RESULT_ALREADY_INITIALIZED;
+       }
+       imc_swid = imc_agent_create(imc_name, msg_types, countof(msg_types),
+                                                         imc_id, actual_version);
+       if (!imc_swid)
+       {
+               return TNC_RESULT_FATAL;
+       }
+       if (min_version > TNC_IFIMC_VERSION_1 || max_version < TNC_IFIMC_VERSION_1)
+       {
+               DBG1(DBG_IMC, "no common IF-IMC version");
+               return TNC_RESULT_NO_COMMON_VERSION;
+       }
+       return TNC_RESULT_SUCCESS;
+}
+
+/**
+ * see section 3.8.2 of TCG TNC IF-IMC Specification 1.3
+ */
+TNC_Result TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id,
+                                                                                 TNC_ConnectionID connection_id,
+                                                                                 TNC_ConnectionState new_state)
+{
+       imc_state_t *state;
+
+       if (!imc_swid)
+       {
+               DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
+               return TNC_RESULT_NOT_INITIALIZED;
+       }
+       switch (new_state)
+       {
+               case TNC_CONNECTION_STATE_CREATE:
+                       state = imc_swid_state_create(connection_id);
+                       return imc_swid->create_state(imc_swid, state);
+               case TNC_CONNECTION_STATE_HANDSHAKE:
+                       if (imc_swid->change_state(imc_swid, connection_id, new_state,
+                               &state) != TNC_RESULT_SUCCESS)
+                       {
+                               return TNC_RESULT_FATAL;
+                       }
+                       state->set_result(state, imc_id,
+                                                         TNC_IMV_EVALUATION_RESULT_DONT_KNOW);
+                       return TNC_RESULT_SUCCESS;
+               case TNC_CONNECTION_STATE_DELETE:
+                       return imc_swid->delete_state(imc_swid, connection_id);
+               default:
+                       return imc_swid->change_state(imc_swid, connection_id,
+                                                                                 new_state, NULL);
+       }
+}
+
+/**
+ * see section 3.8.3 of TCG TNC IF-IMC Specification 1.3
+ */
+TNC_Result TNC_IMC_BeginHandshake(TNC_IMCID imc_id,
+                                                                 TNC_ConnectionID connection_id)
+{
+       imc_state_t *state;
+
+       if (!imc_swid)
+       {
+               DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
+               return TNC_RESULT_NOT_INITIALIZED;
+       }
+       if (!imc_swid->get_state(imc_swid, connection_id, &state))
+       {
+               return TNC_RESULT_FATAL;
+       }
+
+       return TNC_RESULT_SUCCESS;
+}
+
+/**
+ * Add one or multiple SWID Inventory attributes to the send queue
+ */
+static bool add_swid_inventory(imc_state_t *state, imc_msg_t *msg,
+                                                          uint32_t request_id, bool full_tags,
+                                                          swid_inventory_t *targets)
+{
+       pa_tnc_attr_t *attr, *attr_angel, *attr_error;
+       imc_swid_state_t *swid_state;
+       swid_inventory_t *swid_inventory;
+       char *swid_directory, *swid_generator;
+       uint32_t eid_epoch;
+       size_t max_attr_size, attr_size, entry_size;
+       bool first = TRUE, swid_pretty, swid_full;
+       enumerator_t *enumerator;
+
+       swid_directory = lib->settings->get_str(lib->settings,
+                                                               "%s.plugins.imc-swid.swid_directory",
+                                                                SWID_DIRECTORY, lib->ns);
+       swid_generator = lib->settings->get_str(lib->settings,
+                                                               "%s.plugins.imc-swid.swid_generator",
+                                                                SWID_GENERATOR, lib->ns);
+       swid_pretty = lib->settings->get_bool(lib->settings,
+                                                               "%s.plugins.imc-swid.swid_pretty",
+                                                                FALSE, lib->ns);
+       swid_full = lib->settings->get_bool(lib->settings,
+                                                               "%s.plugins.imc-swid.swid_full",
+                                                                FALSE, lib->ns);
+
+       swid_inventory = swid_inventory_create(full_tags);
+       if (!swid_inventory->collect(swid_inventory, swid_directory, swid_generator,
+                                                                targets, swid_pretty, swid_full))
+       {
+               swid_inventory->destroy(swid_inventory);
+               attr_error = swid_error_create(TCG_SWID_ERROR, request_id,
+                                                                0, "error in SWID tag collection");
+               msg->add_attribute(msg, attr_error);
+               return FALSE;
+       }
+       DBG1(DBG_IMC, "collected %d SWID tag%s%s",
+                swid_inventory->get_count(swid_inventory), full_tags ? "" : " ID",
+                swid_inventory->get_count(swid_inventory) == 1 ? "" : "s");
+
+       swid_state = (imc_swid_state_t*)state;
+       eid_epoch = swid_state->get_eid_epoch(swid_state);
+
+       /**
+        * Compute the maximum TCG SWID Tag [ID] Inventory attribute size
+        * leaving space for an additional ITA Angel attribute
+        */
+       max_attr_size = state->get_max_msg_len(state) -
+                                       PA_TNC_HEADER_SIZE - PA_TNC_ATTR_HEADER_SIZE;
+
+       if (full_tags)
+       {
+               tcg_swid_attr_tag_inv_t *swid_attr;
+               swid_tag_t *tag;
+               chunk_t encoding, instance_id;
+
+               /* At least one TCG Tag Inventory attribute is sent */
+               attr_size = PA_TNC_ATTR_HEADER_SIZE + TCG_SWID_TAG_INV_MIN_SIZE;
+               attr = tcg_swid_attr_tag_inv_create(request_id, eid_epoch, 1);
+
+               enumerator = swid_inventory->create_enumerator(swid_inventory);
+               while (enumerator->enumerate(enumerator, &tag))
+               {
+                       instance_id = tag->get_instance_id(tag);
+                       encoding = tag->get_encoding(tag);
+                       entry_size = 2 + instance_id.len + 4 + encoding.len;
+
+                       /* Check for oversize tags that cannot be transported */
+                       if (PA_TNC_ATTR_HEADER_SIZE + TCG_SWID_TAG_INV_MIN_SIZE +
+                               entry_size > max_attr_size)
+                       {
+                               attr_error = swid_error_create(TCG_SWID_RESPONSE_TOO_LARGE,
+                                                                                          request_id, max_attr_size,
+                                                                                          "oversize SWID tag omitted");
+                               msg->add_attribute(msg, attr_error);
+                               continue;
+                       }
+
+                       if (attr_size + entry_size > max_attr_size)
+                       {
+                               if (first)
+                               {
+                                       /**
+                                        * Send an ITA Start Angel attribute to the IMV signalling
+                                        * that multiple TGC SWID Tag Inventory attributes follow
+                                        */
+                                       attr_angel = ita_attr_angel_create(TRUE);
+                                       msg->add_attribute(msg, attr_angel);
+                                       first = FALSE;
+                               }
+                               msg->add_attribute(msg, attr);
+
+                               /* create the next TCG SWID Tag Inventory attribute */
+                               attr_size = PA_TNC_ATTR_HEADER_SIZE +
+                                                       TCG_SWID_TAG_INV_MIN_SIZE;
+                               attr = tcg_swid_attr_tag_inv_create(request_id, eid_epoch, 1);
+                       }
+                       swid_attr = (tcg_swid_attr_tag_inv_t*)attr;
+                       swid_attr->add(swid_attr, tag->get_ref(tag));
+                       attr_size += entry_size;
+               }
+               enumerator->destroy(enumerator);
+       }
+       else
+       {
+               tcg_swid_attr_tag_id_inv_t *swid_id_attr;
+               swid_tag_id_t *tag_id;
+
+               /* Send a TCG Tag ID Inventory attribute */
+               attr = tcg_swid_attr_tag_id_inv_create(request_id, eid_epoch, 1);
+               swid_id_attr = (tcg_swid_attr_tag_id_inv_t*)attr;
+
+               enumerator = swid_inventory->create_enumerator(swid_inventory);
+               while (enumerator->enumerate(enumerator, &tag_id))
+               {
+                       swid_id_attr->add(swid_id_attr, tag_id->get_ref(tag_id));
+               }
+               enumerator->destroy(enumerator);
+       }
+       msg->add_attribute(msg, attr);
+       swid_inventory->destroy(swid_inventory);
+
+       if (!first)
+       {
+               /**
+                * If we sent an ITA Start Angel attribute in the first place,
+                * terminate by appending a matching ITA Stop Angel attribute.
+                */
+               attr_angel = ita_attr_angel_create(FALSE);
+               msg->add_attribute(msg, attr_angel);
+       }
+
+       return TRUE;
+}
+
+static TNC_Result receive_message(imc_state_t *state, imc_msg_t *in_msg)
+{
+       imc_msg_t *out_msg;
+       pa_tnc_attr_t *attr;
+       enumerator_t *enumerator;
+       pen_type_t type;
+       TNC_Result result;
+       bool fatal_error = FALSE;
+
+       /* generate an outgoing PA-TNC message - we might need it */
+       out_msg = imc_msg_create_as_reply(in_msg);
+
+       /* parse received PA-TNC message and handle local and remote errors */
+       result = in_msg->receive(in_msg, out_msg, &fatal_error);
+       if (result != TNC_RESULT_SUCCESS)
+       {
+               out_msg->destroy(out_msg);
+               return result;
+       }
+
+       /* analyze PA-TNC attributes */
+       enumerator = in_msg->create_attribute_enumerator(in_msg);
+       while (enumerator->enumerate(enumerator, &attr))
+       {
+               tcg_swid_attr_req_t *attr_req;
+               uint8_t flags;
+               uint32_t request_id;
+               bool full_tags;
+               swid_inventory_t *targets;
+
+               type = attr->get_type(attr);
+
+               if (type.vendor_id != PEN_TCG || type.type != TCG_SWID_REQUEST)
+               {
+                       continue;
+               }
+
+               attr_req = (tcg_swid_attr_req_t*)attr;
+               flags = attr_req->get_flags(attr_req);
+               request_id = attr_req->get_request_id(attr_req);
+               targets = attr_req->get_targets(attr_req);
+
+               if (flags & (TCG_SWID_ATTR_REQ_FLAG_S | TCG_SWID_ATTR_REQ_FLAG_C))
+               {
+                       attr = swid_error_create(TCG_SWID_SUBSCRIPTION_DENIED, request_id,
+                                                                        0, "no subscription available yet");
+                       out_msg->add_attribute(out_msg, attr);
+                       break;
+               }
+               full_tags = (flags & TCG_SWID_ATTR_REQ_FLAG_R) == 0;
+
+               if (!add_swid_inventory(state, out_msg, request_id, full_tags, targets))
+               {
+                       break;
+               }
+       }
+       enumerator->destroy(enumerator);
+
+       if (fatal_error)
+       {
+               result = TNC_RESULT_FATAL;
+       }
+       else
+       {
+               /* send PA-TNC message with the EXCL flag set */
+               result = out_msg->send(out_msg, TRUE);
+       }
+       out_msg->destroy(out_msg);
+
+       return result;
+}
+
+/**
+ * see section 3.8.4 of TCG TNC IF-IMC Specification 1.3
+
+ */
+TNC_Result TNC_IMC_ReceiveMessage(TNC_IMCID imc_id,
+                                                                 TNC_ConnectionID connection_id,
+                                                                 TNC_BufferReference msg,
+                                                                 TNC_UInt32 msg_len,
+                                                                 TNC_MessageType msg_type)
+{
+       imc_state_t *state;
+       imc_msg_t *in_msg;
+       TNC_Result result;
+
+       if (!imc_swid)
+       {
+               DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
+               return TNC_RESULT_NOT_INITIALIZED;
+       }
+       if (!imc_swid->get_state(imc_swid, connection_id, &state))
+       {
+               return TNC_RESULT_FATAL;
+       }
+       in_msg = imc_msg_create_from_data(imc_swid, state, connection_id, msg_type,
+                                                                         chunk_create(msg, msg_len));
+       result = receive_message(state, in_msg);
+       in_msg->destroy(in_msg);
+
+       return result;
+}
+
+/**
+ * see section 3.8.6 of TCG TNC IF-IMV Specification 1.3
+ */
+TNC_Result TNC_IMC_ReceiveMessageLong(TNC_IMCID imc_id,
+                                                                         TNC_ConnectionID connection_id,
+                                                                         TNC_UInt32 msg_flags,
+                                                                         TNC_BufferReference msg,
+                                                                         TNC_UInt32 msg_len,
+                                                                         TNC_VendorID msg_vid,
+                                                                         TNC_MessageSubtype msg_subtype,
+                                                                         TNC_UInt32 src_imv_id,
+                                                                         TNC_UInt32 dst_imc_id)
+{
+       imc_state_t *state;
+       imc_msg_t *in_msg;
+       TNC_Result result;
+
+       if (!imc_swid)
+       {
+               DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
+               return TNC_RESULT_NOT_INITIALIZED;
+       }
+       if (!imc_swid->get_state(imc_swid, connection_id, &state))
+       {
+               return TNC_RESULT_FATAL;
+       }
+       in_msg = imc_msg_create_from_long_data(imc_swid, state, connection_id,
+                                                               src_imv_id, dst_imc_id,msg_vid, msg_subtype,
+                                                               chunk_create(msg, msg_len));
+       result =receive_message(state, in_msg);
+       in_msg->destroy(in_msg);
+
+       return result;
+}
+
+/**
+ * see section 3.8.7 of TCG TNC IF-IMC Specification 1.3
+ */
+TNC_Result TNC_IMC_BatchEnding(TNC_IMCID imc_id,
+                                                          TNC_ConnectionID connection_id)
+{
+       if (!imc_swid)
+       {
+               DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
+               return TNC_RESULT_NOT_INITIALIZED;
+       }
+       return TNC_RESULT_SUCCESS;
+}
+
+/**
+ * see section 3.8.8 of TCG TNC IF-IMC Specification 1.3
+ */
+TNC_Result TNC_IMC_Terminate(TNC_IMCID imc_id)
+{
+       if (!imc_swid)
+       {
+               DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
+               return TNC_RESULT_NOT_INITIALIZED;
+       }
+       imc_swid->destroy(imc_swid);
+       imc_swid = NULL;
+
+       return TNC_RESULT_SUCCESS;
+}
+
+/**
+ * see section 4.2.8.1 of TCG TNC IF-IMC Specification 1.3
+ */
+TNC_Result TNC_IMC_ProvideBindFunction(TNC_IMCID imc_id,
+                                                                          TNC_TNCC_BindFunctionPointer bind_function)
+{
+       if (!imc_swid)
+       {
+               DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
+               return TNC_RESULT_NOT_INITIALIZED;
+       }
+       return imc_swid->bind_functions(imc_swid, bind_function);
+}
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 (file)
index 0000000..65c279b
--- /dev/null
@@ -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 (file)
index 0000000..cb3ac45
--- /dev/null
@@ -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.1999-03.org.debian/regid.1999-03.org.debian_apache-2-2-22-13.swidtag b/src/libimcv/plugins/imc_swid/regid.1999-03.org.debian/regid.1999-03.org.debian_apache-2-2-22-13.swidtag
new file mode 100644 (file)
index 0000000..82e16d2
--- /dev/null
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<software_identification_tag xmlns="http://standards.iso.org/iso/19770/-2/2009/schema.xsd">
+  <entitlement_required_indicator>true</entitlement_required_indicator>
+  <product_title>apache2</product_title>
+  <product_version>
+    <name>2.2-22-13</name>
+    <numeric>
+      <major>2</major>
+      <minor>2</minor>
+      <build>22</build>
+      <review>13</review>
+    </numeric>
+  </product_version>
+  <software_creator>
+    <name>Apache Software Foundation</name>
+    <regid>regid.1995-04.org.apache</regid>
+  </software_creator>
+  <software_licensor>
+    <name>Debian Project</name>
+    <regid>regid.1999-03.org.debian</regid>
+  </software_licensor>
+  <software_id>
+    <unique_id>apache-2-2-22-13</unique_id>
+    <tag_creator_regid>regid.1999-03.org.debian</tag_creator_regid>
+  </software_id>
+  <tag_creator>
+    <name>Debian Project</name>
+    <regid>regid.1999-03.org.debian</regid>
+  </tag_creator>
+</software_identification_tag>
diff --git a/src/libimcv/plugins/imc_swid/regid.1999-03.org.debian/regid.1999-03.org.debian_bind-9-8-4-dfsg.swidtag b/src/libimcv/plugins/imc_swid/regid.1999-03.org.debian/regid.1999-03.org.debian_bind-9-8-4-dfsg.swidtag
new file mode 100644 (file)
index 0000000..9e856eb
--- /dev/null
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<software_identification_tag xmlns="http://standards.iso.org/iso/19770/-2/2009/schema.xsd">
+  <entitlement_required_indicator>true</entitlement_required_indicator>
+  <product_title>bind9</product_title>
+  <product_version>
+    <name>9-8-4-dfsg</name>
+    <numeric>
+      <major>9</major>
+      <minor>8</minor>
+      <build>4</build>
+      <review>dfsg</review>
+    </numeric>
+  </product_version>
+  <software_creator>
+    <name>Internet Systems Consortium</name>
+    <regid>regid.1994-04.org.isc</regid>
+  </software_creator>
+  <software_licensor>
+    <name>Debian Project</name>
+    <regid>regid.1999-03.org.debian</regid>
+  </software_licensor>
+  <software_id>
+    <unique_id>bind-9-8-4-dfsg</unique_id>
+    <tag_creator_regid>regid.1999-03.org.debian</tag_creator_regid>
+  </software_id>
+  <tag_creator>
+    <name>Debian Project</name>
+    <regid>regid.1999-03.org.debian</regid>
+  </tag_creator>
+</software_identification_tag>
diff --git a/src/libimcv/plugins/imc_swid/regid.1999-03.org.debian/regid.1999-03.org.debian_libsqlite-3-7-13-1.swidtag b/src/libimcv/plugins/imc_swid/regid.1999-03.org.debian/regid.1999-03.org.debian_libsqlite-3-7-13-1.swidtag
new file mode 100644 (file)
index 0000000..7650263
--- /dev/null
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<software_identification_tag xmlns="http://standards.iso.org/iso/19770/-2/2009/schema.xsd">
+  <entitlement_required_indicator>true</entitlement_required_indicator>
+  <product_title>libsqlite3</product_title>
+  <product_version>
+    <name>3.7.13-1</name>
+    <numeric>
+      <major>3</major>
+      <minor>7</minor>
+      <build>13</build>
+      <review>1</review>
+    </numeric>
+  </product_version>
+  <software_creator>
+    <name>SQLite Project</name>
+    <regid>regid.2002-08.org.sqlite</regid>
+  </software_creator>
+  <software_licensor>
+    <name>Debian Project</name>
+    <regid>regid.1999-03.org.debian</regid>
+  </software_licensor>
+  <software_id>
+    <unique_id>libsqlite-3-7-13-1</unique_id>
+    <tag_creator_regid>regid.1999-03.org.debian</tag_creator_regid>
+  </software_id>
+  <tag_creator>
+    <name>Debian Project</name>
+    <regid>regid.1999-03.org.debian</regid>
+  </tag_creator>
+</software_identification_tag>
diff --git a/src/libimcv/plugins/imc_swid/regid.1999-03.org.debian/regid.1999-03.org.debian_libssl-1-0-1e-2.swidtag b/src/libimcv/plugins/imc_swid/regid.1999-03.org.debian/regid.1999-03.org.debian_libssl-1-0-1e-2.swidtag
new file mode 100644 (file)
index 0000000..5a31c57
--- /dev/null
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<software_identification_tag xmlns="http://standards.iso.org/iso/19770/-2/2009/schema.xsd">
+  <entitlement_required_indicator>true</entitlement_required_indicator>
+  <product_title>libssl1.0.0</product_title>
+  <product_version>
+    <name>1.0.1e-2</name>
+    <numeric>
+      <major>1</major>
+      <minor>0</minor>
+      <build>1e</build>
+      <review>2</review>
+    </numeric>
+  </product_version>
+  <software_creator>
+    <name>OpenSSL Project</name>
+    <regid>regid.1998-12.org.openssl</regid>
+  </software_creator>
+  <software_licensor>
+    <name>Debian Project</name>
+    <regid>regid.1999-03.org.debian</regid>
+  </software_licensor>
+  <software_id>
+    <unique_id>libssl-1-0-1e-2</unique_id>
+    <tag_creator_regid>regid.1999-03.org.debian</tag_creator_regid>
+  </software_id>
+  <tag_creator>
+    <name>Debian Project</name>
+    <regid>regid.1999-03.org.debian</regid>
+  </tag_creator>
+</software_identification_tag>
diff --git a/src/libimcv/plugins/imc_swid/regid.1999-03.org.debian/regid.1999-03.org.debian_libssl-dev-1-0-1e-2.swidtag b/src/libimcv/plugins/imc_swid/regid.1999-03.org.debian/regid.1999-03.org.debian_libssl-dev-1-0-1e-2.swidtag
new file mode 100644 (file)
index 0000000..cc6888b
--- /dev/null
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<software_identification_tag xmlns="http://standards.iso.org/iso/19770/-2/2009/schema.xsd">
+  <entitlement_required_indicator>true</entitlement_required_indicator>
+  <product_title>libssl-dev</product_title>
+  <product_version>
+    <name>1.0.1e-2</name>
+    <numeric>
+      <major>1</major>
+      <minor>0</minor>
+      <build>1e</build>
+      <review>2</review>
+    </numeric>
+  </product_version>
+  <software_creator>
+    <name>OpenSSL Project</name>
+    <regid>regid.1998-12.org.openssl</regid>
+  </software_creator>
+  <software_licensor>
+    <name>Debian Project</name>
+    <regid>regid.1999-03.org.debian</regid>
+  </software_licensor>
+  <software_id>
+    <unique_id>libssl-dev-1-0-1e-2</unique_id>
+    <tag_creator_regid>regid.1999-03.org.debian</tag_creator_regid>
+  </software_id>
+  <tag_creator>
+    <name>Debian Project</name>
+    <regid>regid.1999-03.org.debian</regid>
+  </tag_creator>
+</software_identification_tag>
diff --git a/src/libimcv/plugins/imc_swid/regid.1999-03.org.debian/regid.1999-03.org.debian_openssl-1-0-1e-2.swidtag b/src/libimcv/plugins/imc_swid/regid.1999-03.org.debian/regid.1999-03.org.debian_openssl-1-0-1e-2.swidtag
new file mode 100644 (file)
index 0000000..af0a60d
--- /dev/null
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<software_identification_tag xmlns="http://standards.iso.org/iso/19770/-2/2009/schema.xsd">
+  <entitlement_required_indicator>true</entitlement_required_indicator>
+  <product_title>openssl</product_title>
+  <product_version>
+    <name>1.0.1e-2</name>
+    <numeric>
+      <major>1</major>
+      <minor>0</minor>
+      <build>1e</build>
+      <review>2</review>
+    </numeric>
+  </product_version>
+  <software_creator>
+    <name>OpenSSL Project</name>
+    <regid>regid.1998-12.org.openssl</regid>
+  </software_creator>
+  <software_licensor>
+    <name>Debian Project</name>
+    <regid>regid.1999-03.org.debian</regid>
+  </software_licensor>
+  <software_id>
+    <unique_id>openssl-1-0-1e-2</unique_id>
+    <tag_creator_regid>regid.1999-03.org.debian</tag_creator_regid>
+  </software_id>
+  <tag_creator>
+    <name>Debian Project</name>
+    <regid>regid.1999-03.org.debian</regid>
+  </tag_creator>
+</software_identification_tag>
diff --git a/src/libimcv/plugins/imc_swid/regid.1999-03.org.debian/regid.1999-03.org.debian_sqlite-3-7-13-1.swidtag b/src/libimcv/plugins/imc_swid/regid.1999-03.org.debian/regid.1999-03.org.debian_sqlite-3-7-13-1.swidtag
new file mode 100644 (file)
index 0000000..43d0fdc
--- /dev/null
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<software_identification_tag xmlns="http://standards.iso.org/iso/19770/-2/2009/schema.xsd">
+  <entitlement_required_indicator>true</entitlement_required_indicator>
+  <product_title>sqlite3</product_title>
+  <product_version>
+    <name>3.7.13-1</name>
+    <numeric>
+      <major>3</major>
+      <minor>7</minor>
+      <build>13</build>
+      <review>1</review>
+    </numeric>
+  </product_version>
+  <software_creator>
+    <name>SQLite Project</name>
+    <regid>regid.2002-08.org.sqlite</regid>
+  </software_creator>
+  <software_licensor>
+    <name>Debian Project</name>
+    <regid>regid.1999-03.org.debian</regid>
+  </software_licensor>
+  <software_id>
+    <unique_id>sqlite-3-7-13-1</unique_id>
+    <tag_creator_regid>regid.1999-03.org.debian</tag_creator_regid>
+  </software_id>
+  <tag_creator>
+    <name>Debian Project</name>
+    <regid>regid.1999-03.org.debian</regid>
+  </tag_creator>
+</software_identification_tag>
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 (file)
index 0000000..8b7b50f
--- /dev/null
@@ -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/imv_attestation/.gitignore b/src/libimcv/plugins/imv_attestation/.gitignore
new file mode 100644 (file)
index 0000000..79548eb
--- /dev/null
@@ -0,0 +1 @@
+attest
diff --git a/src/libimcv/plugins/imv_attestation/Makefile.am b/src/libimcv/plugins/imv_attestation/Makefile.am
new file mode 100644 (file)
index 0000000..6c5bf89
--- /dev/null
@@ -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/attest.c b/src/libimcv/plugins/imv_attestation/attest.c
new file mode 100644 (file)
index 0000000..1143a03
--- /dev/null
@@ -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 (file)
index 0000000..f85a02b
--- /dev/null
@@ -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 (file)
index 0000000..07e55cc
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2011-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup attest_db_t attest_db
+ * @{ @ingroup libpts
+ */
+
+#ifndef ATTEST_DB_H_
+#define ATTEST_DB_H_
+
+#include <pts/pts_meas_algo.h>
+#include <os_info/os_info.h>
+#include <library.h>
+
+typedef struct attest_db_t attest_db_t;
+
+/**
+ * Attestation database object
+ */
+struct attest_db_t {
+
+       /**
+        * Set functional component to be queried
+        *
+        * @param comp                  functional component
+        * @param create                if TRUE create database entry if it doesn't exist
+        * @return                              TRUE if successful
+        */
+       bool (*set_component)(attest_db_t *this, char *comp, bool create);
+
+       /**
+        * Set primary key of the functional component to be queried
+        *
+        * @param fid                   primary key of functional component
+        * @return                              TRUE if successful
+        */
+       bool (*set_cid)(attest_db_t *this, int fid);
+
+       /**
+        * Set directory to be queried
+        *
+        * @param dir                   directory
+        * @param create                if TRUE create database entry if it doesn't exist
+        * @return                              TRUE if successful
+        */
+       bool (*set_directory)(attest_db_t *this, char *dir, bool create);
+
+       /**
+        * Set primary key of the directory to be queried
+        *
+        * @param did                   primary key of directory
+        * @return                              TRUE if successful
+        */
+       bool (*set_did)(attest_db_t *this, int did);
+
+       /**
+        * Set measurement file to be queried
+        *
+        * @param file                  measurement file
+        * @param create                if TRUE create database entry if it doesn't exist
+        * @return                              TRUE if successful
+        */
+       bool (*set_file)(attest_db_t *this, char *file, bool create);
+
+       /**
+        * Set primary key of the measurement file to be queried
+        *
+        * @param fid                   primary key of measurement file
+        * @return                              TRUE if successful
+        */
+       bool (*set_fid)(attest_db_t *this, int fid);
+
+       /**
+        * Set path to directory where file[s] are to be measured
+        *
+        * @param meas_dir              measurement directory
+        * @return                              TRUE if successful
+        */
+       bool (*set_meas_directory)(attest_db_t *this, char *dir);
+
+       /**
+        * Set functional component to be queried
+        *
+        * @param key                   AIK
+        * @param create                if TRUE create database entry if it doesn't exist
+        * @return                              TRUE if successful
+        */
+       bool (*set_key)(attest_db_t *this, chunk_t key, bool create);
+
+       /**
+        * Set primary key of the AIK to be queried
+        *
+        * @param kid                   primary key of AIK
+        * @return                              TRUE if successful
+        */
+       bool (*set_kid)(attest_db_t *this, int kid);
+
+       /**
+        * Set software package to be queried
+        *
+        * @param product               software package
+        * @param create                if TRUE create database entry if it doesn't exist
+        * @return                              TRUE if successful
+        */
+       bool (*set_package)(attest_db_t *this, char *package, bool create);
+
+       /**
+        * Set primary key of the software package to be queried
+        *
+        * @param gid                   primary key of software package
+        * @return                              TRUE if successful
+        */
+       bool (*set_gid)(attest_db_t *this, int gid);
+
+       /**
+        * Set software product to be queried
+        *
+        * @param product               software product
+        * @param create                if TRUE create database entry if it doesn't exist
+        * @return                              TRUE if successful
+        */
+       bool (*set_product)(attest_db_t *this, char *product, bool create);
+
+       /**
+        * Set primary key of the software product to be queried
+        *
+        * @param pid                   primary key of software product
+        * @return                              TRUE if successful
+        */
+       bool (*set_pid)(attest_db_t *this, int pid);
+
+       /**
+        * Set software package version to be queried
+        *
+        * @param version               software package version
+        * @return                              TRUE if successful
+        */
+       bool (*set_version)(attest_db_t *this, char *version);
+
+       /**
+        * Set measurement hash algorithm
+        *
+        * @param algo                  hash algorithm
+        */
+       void (*set_algo)(attest_db_t *this, pts_meas_algorithms_t algo);
+
+       /**
+        * Set that the IMA-specific SHA-1 template hash be computed
+        */
+       void (*set_ima)(attest_db_t *this);
+
+       /**
+        * Set that relative filenames are to be used
+        */
+       void (*set_relative)(attest_db_t *this);
+
+       /**
+        * Set the package security or blacklist state
+        */
+       void (*set_package_state)(attest_db_t *this, os_package_state_t package_state);
+
+       /**
+        * Set the sequence number
+        */
+       void (*set_sequence)(attest_db_t *this, int seq_no);
+
+       /**
+        * Set owner [user/host] of an AIK
+        *
+        * @param owner                 user/host name
+        * @return                              TRUE if successful
+        */
+       void (*set_owner)(attest_db_t *this, char *owner);
+
+       /**
+        * Display all dates in UTC
+        */
+       void (*set_utc)(attest_db_t *this);
+
+       /**
+        * List all packages stored in the database
+        */
+       void (*list_packages)(attest_db_t *this);
+
+       /**
+        * List all products stored in the database
+        */
+       void (*list_products)(attest_db_t *this);
+
+       /**
+        * List all directories stored in the database
+        */
+       void (*list_directories)(attest_db_t *this);
+
+       /**
+        * List selected files stored in the database
+        */
+       void (*list_files)(attest_db_t *this);
+
+       /**
+        * List all components stored in the database
+        */
+       void (*list_components)(attest_db_t *this);
+
+       /**
+        * List all devices stored in the database
+        */
+       void (*list_devices)(attest_db_t *this);
+
+       /**
+        * List all AIKs stored in the database
+        */
+       void (*list_keys)(attest_db_t *this);
+
+       /**
+        * List selected measurement hashes stored in the database
+        */
+       void (*list_hashes)(attest_db_t *this);
+
+       /**
+        * List selected component measurement stored in the database
+        */
+       void (*list_measurements)(attest_db_t *this);
+
+       /**
+        * List sessions stored in the database
+        */
+       void (*list_sessions)(attest_db_t *this);
+
+       /**
+        * Add an entry to the database
+        */
+       bool (*add)(attest_db_t *this);
+
+       /**
+        * Delete an entry from the database
+        */
+       bool (*delete)(attest_db_t *this);
+
+       /**
+        * Destroy attest_db_t object
+        */
+       void (*destroy)(attest_db_t *this);
+
+};
+
+/**
+ * Create an attest_db_t instance
+ *
+ * @param uri                          database URI
+ */
+attest_db_t* attest_db_create(char *uri);
+
+#endif /** ATTEST_DB_H_ @}*/
diff --git a/src/libimcv/plugins/imv_attestation/attest_usage.c b/src/libimcv/plugins/imv_attestation/attest_usage.c
new file mode 100644 (file)
index 0000000..8f4afdb
--- /dev/null
@@ -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<