aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/libimcv/Makefile.am5
-rw-r--r--src/libimcv/imc/imc_msg.c212
-rw-r--r--src/libimcv/imc/imc_state.h2
-rw-r--r--src/libimcv/imv/imv_msg.c235
-rw-r--r--src/libimcv/imv/imv_state.h2
-rw-r--r--src/libimcv/pa_tnc/pa_tnc_attr.h3
-rw-r--r--src/libimcv/pa_tnc/pa_tnc_attr_manager.c133
-rw-r--r--src/libimcv/pa_tnc/pa_tnc_attr_manager.h17
-rw-r--r--src/libimcv/pa_tnc/pa_tnc_msg.c161
-rw-r--r--src/libimcv/pa_tnc/pa_tnc_msg.h3
-rw-r--r--src/libimcv/seg/seg_contract.c (renamed from src/libimcv/seg_contract/seg_contract.c)170
-rw-r--r--src/libimcv/seg/seg_contract.h (renamed from src/libimcv/seg_contract/seg_contract.h)62
-rw-r--r--src/libimcv/seg/seg_contract_manager.c (renamed from src/libimcv/seg_contract/seg_contract_manager.c)0
-rw-r--r--src/libimcv/seg/seg_contract_manager.h (renamed from src/libimcv/seg_contract/seg_contract_manager.h)0
-rw-r--r--src/libimcv/seg/seg_env.c261
-rw-r--r--src/libimcv/seg/seg_env.h108
-rw-r--r--src/libpts/Makefile.am3
-rw-r--r--src/libpts/plugins/imc_swid/imc_swid.c30
-rwxr-xr-xsrc/libpts/plugins/imv_attestation/build-database.sh2
-rw-r--r--src/libpts/tcg/seg/tcg_seg_attr_next_seg.c235
-rw-r--r--src/libpts/tcg/seg/tcg_seg_attr_next_seg.h71
-rw-r--r--src/libpts/tcg/seg/tcg_seg_attr_seg_env.c234
-rw-r--r--src/libpts/tcg/seg/tcg_seg_attr_seg_env.h25
-rw-r--r--src/libpts/tcg/tcg_attr.c6
24 files changed, 1660 insertions, 320 deletions
diff --git a/src/libimcv/Makefile.am b/src/libimcv/Makefile.am
index 8b3ca5daa..37041d2b2 100644
--- a/src/libimcv/Makefile.am
+++ b/src/libimcv/Makefile.am
@@ -56,8 +56,9 @@ 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 \
- seg_contract/seg_contract.h seg_contract/seg_contract.c \
- seg_contract/seg_contract_manager.h seg_contract/seg_contract_manager.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
ipsec_SCRIPTS = imv/_imv_policy
EXTRA_DIST = imv/_imv_policy Android.mk
diff --git a/src/libimcv/imc/imc_msg.c b/src/libimcv/imc/imc_msg.c
index 9b9aeca23..3f2d7aed5 100644
--- a/src/libimcv/imc/imc_msg.c
+++ b/src/libimcv/imc/imc_msg.c
@@ -24,6 +24,7 @@
#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>
@@ -108,11 +109,17 @@ METHOD(imc_msg_t, send_, TNC_Result,
pa_tnc_attr_t *attr;
TNC_UInt32 msg_flags;
TNC_MessageType msg_type;
- bool attr_added;
+ bool attr_added, oversize;
chunk_t msg;
+ seg_contract_t *contract;
+ seg_contract_manager_t *contracts;
enumerator_t *enumerator;
TNC_Result result = TNC_RESULT_SUCCESS;
+ /* Get IF-M segmentation contract for this subtype if any */
+ contracts = this->state->get_contracts(this->state);
+ contract = contracts->get_contract(contracts, this->msg_type, FALSE);
+
while (this->attr_list->get_count(this->attr_list))
{
pa_tnc_msg = pa_tnc_msg_create(this->state->get_max_msg_len(this->state));
@@ -121,6 +128,17 @@ METHOD(imc_msg_t, send_, TNC_Result,
enumerator = this->attr_list->create_enumerator(this->attr_list);
while (enumerator->enumerate(enumerator, &attr))
{
+ if (contract && contract->check_size(contract, attr, &oversize))
+ {
+ if (oversize)
+ {
+ /* TODO generate SWID error msg */
+ }
+ else
+ {
+ attr = contract->first_segment(contract, attr);
+ }
+ }
if (pa_tnc_msg->add_attribute(pa_tnc_msg, attr))
{
attr_added = TRUE;
@@ -274,7 +292,6 @@ METHOD(imc_msg_t, receive, TNC_Result,
enumerator = this->pa_msg->create_attribute_enumerator(this->pa_msg);
while (enumerator->enumerate(enumerator, &attr))
{
- tcg_seg_attr_max_size_t *attr_cast;
uint32_t max_attr_size, max_seg_size, my_max_attr_size, my_max_seg_size;
seg_contract_t *contract;
seg_contract_manager_t *contracts;
@@ -283,79 +300,160 @@ METHOD(imc_msg_t, receive, TNC_Result,
type = attr->get_type(attr);
+ contracts = this->state->get_contracts(this->state);
+
if (type.vendor_id != PEN_TCG)
{
continue;
}
- if (type.type == TCG_SEG_MAX_ATTR_SIZE_REQ)
+ switch (type.type)
{
- attr_cast = (tcg_seg_attr_max_size_t*)attr;
- attr_cast->get_attr_size(attr_cast, &max_attr_size, &max_seg_size);
-
- contracts = this->state->get_contracts(this->state);
- contract = contracts->get_contract(contracts, this->msg_type, FALSE);
- if (contract)
- {
- contract->set_max_size(contract, max_attr_size, max_seg_size);
- }
- else
+ case TCG_SEG_MAX_ATTR_SIZE_REQ:
{
- contract = seg_contract_create(this->msg_type, max_attr_size,
+ tcg_seg_attr_max_size_t *attr_cast;
+
+ attr_cast = (tcg_seg_attr_max_size_t*)attr;
+ attr_cast->get_attr_size(attr_cast, &max_attr_size,
+ &max_seg_size);
+ contract = contracts->get_contract(contracts, this->msg_type,
+ FALSE);
+ if (contract)
+ {
+ contract->set_max_size(contract, max_attr_size,
+ max_seg_size);
+ }
+ else
+ {
+ contract = seg_contract_create(this->msg_type, max_attr_size,
max_seg_size, FALSE, this->src_id, TRUE);
- contracts->add_contract(contracts, contract);
+ contracts->add_contract(contracts, contract);
+ }
+ contract->get_info_string(contract, buf, BUF_LEN, TRUE);
+ DBG2(DBG_IMC, "%s", buf);
+
+ /* Determine maximum PA-TNC attribute segment size */
+ my_max_seg_size = this->state->get_max_msg_len(this->state)
+ - PA_TNC_HEADER_SIZE
+ - PA_TNC_ATTR_HEADER_SIZE
+ - TCG_SEG_ATTR_SEG_ENV_HEADER
+ - PA_TNC_ATTR_HEADER_SIZE
+ - TCG_SEG_ATTR_MAX_SIZE_SIZE;
+
+ /* If segmentation is possible select lower segment size */
+ if (max_seg_size != SEG_CONTRACT_NO_FRAGMENTATION &&
+ max_seg_size > my_max_seg_size)
+ {
+ max_seg_size = my_max_seg_size;
+ contract->set_max_size(contract, max_attr_size,
+ max_seg_size);
+ DBG2(DBG_IMC, " lowered maximum segment size to %u bytes",
+ max_seg_size);
+ }
+
+ /* Add Maximum Attribute Size Response attribute */
+ attr = tcg_seg_attr_max_size_create(max_attr_size,
+ max_seg_size, FALSE);
+ out_msg->add_attribute(out_msg, attr);
+ break;
}
- contract->get_info_string(contract, buf, BUF_LEN, TRUE);
- DBG2(DBG_IMC, "%s", buf);
-
- /* Determine maximum PA-TNC attribute segment size */
- my_max_seg_size = this->state->get_max_msg_len(this->state)
- - PA_TNC_HEADER_SIZE
- - PA_TNC_ATTR_HEADER_SIZE
- - TCG_SEG_ATTR_SEG_ENV_HEADER
- - PA_TNC_ATTR_HEADER_SIZE
- - TCG_SEG_ATTR_MAX_SIZE_SIZE;
-
- /* If segmentation is not prohibited select lower segment size */
- if (max_seg_size != SEG_CONTRACT_NO_FRAGMENTATION &&
- max_seg_size > my_max_seg_size)
+ case TCG_SEG_MAX_ATTR_SIZE_RESP:
{
- max_seg_size = my_max_seg_size;
- contract->set_max_size(contract, max_attr_size, max_seg_size);
- DBG2(DBG_IMC, " lowered maximum segment size to %u bytes",
- max_seg_size);
+ tcg_seg_attr_max_size_t *attr_cast;
+
+ attr_cast = (tcg_seg_attr_max_size_t*)attr;
+ attr_cast->get_attr_size(attr_cast, &max_attr_size,
+ &max_seg_size);
+ contract = contracts->get_contract(contracts, this->msg_type,
+ TRUE);
+ if (contract)
+ {
+ contract->get_max_size(contract, &my_max_attr_size,
+ &my_max_seg_size);
+ if (my_max_seg_size != SEG_CONTRACT_NO_FRAGMENTATION &&
+ my_max_seg_size > max_seg_size)
+ {
+ my_max_seg_size = max_seg_size;
+ contract->set_max_size(contract, my_max_attr_size,
+ my_max_seg_size);
+ }
+ contract->get_info_string(contract, buf, BUF_LEN, FALSE);
+ DBG2(DBG_IMC, "%s", buf);
+ }
+ else
+ {
+ /* TODO no request pending */
+ DBG1(DBG_IMC, "no contract for this PA message type found");
+ }
+ break;
}
+ case TCG_SEG_ATTR_SEG_ENV:
+ {
+ tcg_seg_attr_seg_env_t *seg_env_attr;
+ pa_tnc_attr_t *error;
+ uint32_t base_attr_id;
+ bool more;
- /* Add Maximum Attribute Size Response attribute */
- attr = tcg_seg_attr_max_size_create(max_attr_size,
- max_seg_size, FALSE);
- out_msg->add_attribute(out_msg, attr);
- }
- else if (type.type == TCG_SEG_MAX_ATTR_SIZE_RESP)
- {
- attr_cast = (tcg_seg_attr_max_size_t*)attr;
- attr_cast->get_attr_size(attr_cast, &max_attr_size, &max_seg_size);
+ seg_env_attr = (tcg_seg_attr_seg_env_t*)attr;
+ base_attr_id = seg_env_attr->get_base_attr_id(seg_env_attr);
- contracts = this->state->get_contracts(this->state);
- contract = contracts->get_contract(contracts, this->msg_type, TRUE);
- if (contract)
- {
- contract->get_max_size(contract, &my_max_attr_size,
- &my_max_seg_size);
- if (my_max_seg_size != SEG_CONTRACT_NO_FRAGMENTATION &&
- my_max_seg_size > max_seg_size)
+ contract = contracts->get_contract(contracts, this->msg_type,
+ TRUE);
+ if (!contract)
{
- my_max_seg_size = max_seg_size;
- contract->set_max_size(contract, my_max_attr_size,
- my_max_seg_size);
- contract->get_info_string(contract, buf, BUF_LEN, FALSE);
- DBG2(DBG_IMC, "%s", buf);
+ DBG2(DBG_IMC, "no contract for received attribute segment "
+ "with base attribute ID %u", base_attr_id);
+ continue;
+ }
+ attr = contract->add_segment(contract, attr, &error, &more);
+ if (error)
+ {
+ out_msg->add_attribute(out_msg, error);
+ }
+ if (attr)
+ {
+ this->pa_msg->add_attribute(this->pa_msg, attr);
}
+ if (more)
+ {
+ /* Send Next Segment Request */
+ attr = tcg_seg_attr_next_seg_create(base_attr_id, FALSE);
+ out_msg->add_attribute(out_msg, attr);
+ }
+ break;
}
- else
+ case TCG_SEG_NEXT_SEG_REQ:
{
- /* TODO no request pending */
+ tcg_seg_attr_next_seg_t *attr_cast;
+ uint32_t base_attr_id;
+
+ attr_cast = (tcg_seg_attr_next_seg_t*)attr;
+ base_attr_id = attr_cast->get_base_attr_id(attr_cast);
+
+ contract = contracts->get_contract(contracts, this->msg_type,
+ FALSE);
+ if (!contract)
+ {
+ /* TODO no contract - generate error message */
+ DBG2(DBG_IMC, "no contract for received next segment "
+ "request with base attribute ID %u", base_attr_id);
+ continue;
+ }
+ attr = contract->next_segment(contract, base_attr_id);
+ if (attr)
+ {
+ out_msg->add_attribute(out_msg, attr);
+ }
+ else
+ {
+ /* TODO no more segments - generate error message */
+ DBG1(DBG_IMC, "no more segments found for "
+ "base attribute ID %u", base_attr_id);
+ }
+ break;
}
+ default:
+ break;
}
}
enumerator->destroy(enumerator);
diff --git a/src/libimcv/imc/imc_state.h b/src/libimcv/imc/imc_state.h
index e3e83a3b9..efcf567f0 100644
--- a/src/libimcv/imc/imc_state.h
+++ b/src/libimcv/imc/imc_state.h
@@ -22,7 +22,7 @@
#ifndef IMC_STATE_H_
#define IMC_STATE_H_
-#include "seg_contract/seg_contract_manager.h"
+#include "seg/seg_contract_manager.h"
#include <tncif.h>
#include <tncifimv.h>
diff --git a/src/libimcv/imv/imv_msg.c b/src/libimcv/imv/imv_msg.c
index 35209dc18..b32b01c06 100644
--- a/src/libimcv/imv/imv_msg.c
+++ b/src/libimcv/imv/imv_msg.c
@@ -24,6 +24,7 @@
#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>
@@ -125,11 +126,17 @@ METHOD(imv_msg_t, send_, TNC_Result,
pa_tnc_attr_t *attr;
TNC_UInt32 msg_flags;
TNC_MessageType msg_type;
- bool attr_added;
+ bool attr_added, oversize;
chunk_t msg;
+ seg_contract_t *contract;
+ seg_contract_manager_t *contracts;
enumerator_t *enumerator;
TNC_Result result = TNC_RESULT_SUCCESS;
+ /* Get IF-M segmentation contract for this subtype if any */
+ contracts = this->state->get_contracts(this->state);
+ contract = contracts->get_contract(contracts, this->msg_type, FALSE);
+
while (this->attr_list->get_count(this->attr_list))
{
pa_tnc_msg = pa_tnc_msg_create(this->state->get_max_msg_len(this->state));
@@ -138,6 +145,17 @@ METHOD(imv_msg_t, send_, TNC_Result,
enumerator = this->attr_list->create_enumerator(this->attr_list);
while (enumerator->enumerate(enumerator, &attr))
{
+ if (contract && contract->check_size(contract, attr, &oversize))
+ {
+ if (oversize)
+ {
+ /* TODO generate SWID error msg */
+ }
+ else
+ {
+ attr = contract->first_segment(contract, attr);
+ }
+ }
if (pa_tnc_msg->add_attribute(pa_tnc_msg, attr))
{
attr_added = TRUE;
@@ -317,15 +335,14 @@ METHOD(imv_msg_t, receive, TNC_Result,
return TNC_RESULT_FATAL;
}
- /* process any IF-M segmentation contracts */
+ /* process IF-M segmentation attributes */
enumerator = this->pa_msg->create_attribute_enumerator(this->pa_msg);
while (enumerator->enumerate(enumerator, &attr))
{
uint32_t max_attr_size, max_seg_size, my_max_attr_size, my_max_seg_size;
- tcg_seg_attr_max_size_t *attr_cast;
imv_msg_t *out_msg;
- seg_contract_t *contract;
seg_contract_manager_t *contracts;
+ seg_contract_t *contract;
char buf[BUF_LEN];
pen_type_t type;
@@ -336,81 +353,169 @@ METHOD(imv_msg_t, receive, TNC_Result,
continue;
}
- if (type.type == TCG_SEG_MAX_ATTR_SIZE_REQ)
- {
- attr_cast = (tcg_seg_attr_max_size_t*)attr;
- attr_cast->get_attr_size(attr_cast, &max_attr_size, &max_seg_size);
+ contracts = this->state->get_contracts(this->state);
- contracts = this->state->get_contracts(this->state);
- contract = contracts->get_contract(contracts, this->msg_type, FALSE);
- if (contract)
- {
- contract->set_max_size(contract, max_attr_size, max_seg_size);
- }
- else
+ switch (type.type)
+ {
+ case TCG_SEG_MAX_ATTR_SIZE_REQ:
{
- contract = seg_contract_create(this->msg_type, max_attr_size,
+ tcg_seg_attr_max_size_t *attr_cast;
+
+ attr_cast = (tcg_seg_attr_max_size_t*)attr;
+ attr_cast->get_attr_size(attr_cast, &max_attr_size,
+ &max_seg_size);
+ contract = contracts->get_contract(contracts, this->msg_type,
+ FALSE);
+ if (contract)
+ {
+ contract->set_max_size(contract, max_attr_size,
+ max_seg_size);
+ }
+ else
+ {
+ contract = seg_contract_create(this->msg_type, max_attr_size,
max_seg_size, FALSE, this->src_id, FALSE);
- contracts->add_contract(contracts, contract);
- }
- contract->get_info_string(contract, buf, BUF_LEN, TRUE);
- DBG2(DBG_IMV, "%s", buf);
-
- /* Determine maximum PA-TNC attribute segment size */
- my_max_seg_size = this->state->get_max_msg_len(this->state)
- - PA_TNC_HEADER_SIZE
- - PA_TNC_ATTR_HEADER_SIZE
- - TCG_SEG_ATTR_SEG_ENV_HEADER
- - PA_TNC_ATTR_HEADER_SIZE
- - TCG_SEG_ATTR_MAX_SIZE_SIZE;
-
- /* If segmentation is not prohibited select lower segment size */
- if (max_seg_size != SEG_CONTRACT_NO_FRAGMENTATION &&
- max_seg_size > my_max_seg_size)
- {
- max_seg_size = my_max_seg_size;
- contract->set_max_size(contract, max_attr_size, max_seg_size);
- DBG2(DBG_IMV, " lowered maximum segment size to %u bytes",
- max_seg_size);
- }
+ contracts->add_contract(contracts, contract);
+ }
+ contract->get_info_string(contract, buf, BUF_LEN, TRUE);
+ DBG2(DBG_IMV, "%s", buf);
+
+ /* Determine maximum PA-TNC attribute segment size */
+ my_max_seg_size = this->state->get_max_msg_len(this->state)
+ - PA_TNC_HEADER_SIZE
+ - PA_TNC_ATTR_HEADER_SIZE
+ - TCG_SEG_ATTR_SEG_ENV_HEADER
+ - PA_TNC_ATTR_HEADER_SIZE
+ - TCG_SEG_ATTR_MAX_SIZE_SIZE;
+
+ /* If segmentation is possible select lower segment size */
+ if (max_seg_size != SEG_CONTRACT_NO_FRAGMENTATION &&
+ max_seg_size > my_max_seg_size)
+ {
+ max_seg_size = my_max_seg_size;
+ contract->set_max_size(contract, max_attr_size,
+ max_seg_size);
+ DBG2(DBG_IMV, " lowered maximum segment size to %u bytes",
+ max_seg_size);
+ }
- /* Send Maximum Attribute Size Response */
- out_msg = imv_msg_create_as_reply(&this->public);
- attr = tcg_seg_attr_max_size_create(max_attr_size,
- max_seg_size, FALSE);
- out_msg->add_attribute(out_msg, attr);
- result = out_msg->send(out_msg, TRUE);
- out_msg->destroy(out_msg);
- if (result != TNC_RESULT_SUCCESS)
- {
+ /* Send Maximum Attribute Size Response */
+ out_msg = imv_msg_create_as_reply(&this->public);
+ attr = tcg_seg_attr_max_size_create(max_attr_size,
+ max_seg_size, FALSE);
+ out_msg->add_attribute(out_msg, attr);
+ result = out_msg->send(out_msg, TRUE);
+ out_msg->destroy(out_msg);
+ if (result != TNC_RESULT_SUCCESS)
+ {
+ break;
+ }
break;
}
- }
- else if (type.type == TCG_SEG_MAX_ATTR_SIZE_RESP)
- {
- attr_cast = (tcg_seg_attr_max_size_t*)attr;
- attr_cast->get_attr_size(attr_cast, &max_attr_size, &max_seg_size);
-
- contracts = this->state->get_contracts(this->state);
- contract = contracts->get_contract(contracts, this->msg_type, TRUE);
- if (contract)
+ case TCG_SEG_MAX_ATTR_SIZE_RESP:
{
- contract->get_max_size(contract, &my_max_attr_size,
- &my_max_seg_size);
- if (my_max_seg_size != SEG_CONTRACT_NO_FRAGMENTATION &&
- my_max_seg_size > max_seg_size)
+ tcg_seg_attr_max_size_t *attr_cast;
+
+ attr_cast = (tcg_seg_attr_max_size_t*)attr;
+ attr_cast->get_attr_size(attr_cast, &max_attr_size,
+ &max_seg_size);
+ contract = contracts->get_contract(contracts, this->msg_type,
+ TRUE);
+ if (contract)
{
- my_max_seg_size = max_seg_size;
- contract->set_max_size(contract, my_max_attr_size,
- my_max_seg_size);
+ contract->get_max_size(contract, &my_max_attr_size,
+ &my_max_seg_size);
+ if (my_max_seg_size != SEG_CONTRACT_NO_FRAGMENTATION &&
+ my_max_seg_size > max_seg_size)
+ {
+ my_max_seg_size = max_seg_size;
+ contract->set_max_size(contract, my_max_attr_size,
+ my_max_seg_size);
+ }
contract->get_info_string(contract, buf, BUF_LEN, FALSE);
DBG2(DBG_IMV, "%s", buf);
}
+ else
+ {
+ /* TODO no request pending */
+ DBG1(DBG_IMV, "no contract for this PA message type found");
+ }
+ break;
}
- else
+ case TCG_SEG_ATTR_SEG_ENV:
+ {
+ tcg_seg_attr_seg_env_t *seg_env_attr;
+ pa_tnc_attr_t *error;
+ uint32_t base_attr_id;
+ bool more;
+
+ seg_env_attr = (tcg_seg_attr_seg_env_t*)attr;
+ base_attr_id = seg_env_attr->get_base_attr_id(seg_env_attr);
+
+ contract = contracts->get_contract(contracts, this->msg_type,
+ TRUE);
+ if (!contract)
+ {
+ DBG2(DBG_IMV, "no contract for received attribute segment "
+ "with base attribute ID %u", base_attr_id);
+ continue;
+ }
+ attr = contract->add_segment(contract, attr, &error, &more);
+ if (error)
+ {
+ out_msg = imv_msg_create_as_reply(&this->public);
+ out_msg->add_attribute(out_msg, error);
+ result = out_msg->send(out_msg, TRUE);
+ out_msg->destroy(out_msg);
+ }
+ if (attr)
+ {
+ this->pa_msg->add_attribute(this->pa_msg, attr);
+ }
+ if (more)
+ {
+ /* Send Next Segment Request */
+ out_msg = imv_msg_create_as_reply(&this->public);
+ attr = tcg_seg_attr_next_seg_create(base_attr_id, FALSE);
+ out_msg->add_attribute(out_msg, attr);
+ result = out_msg->send(out_msg, TRUE);
+ out_msg->destroy(out_msg);
+ }
+ break;
+ }
+ case TCG_SEG_NEXT_SEG_REQ:
{
- /* TODO no request pending */
+ tcg_seg_attr_next_seg_t *attr_cast;
+ uint32_t base_attr_id;
+
+ attr_cast = (tcg_seg_attr_next_seg_t*)attr;
+ base_attr_id = attr_cast->get_base_attr_id(attr_cast);
+
+ contract = contracts->get_contract(contracts, this->msg_type,
+ FALSE);
+ if (!contract)
+ {
+ /* TODO no contract - generate error message */
+ DBG2(DBG_IMV, "no contract for received next segment "
+ "request with base attribute ID %u", base_attr_id);
+ continue;
+ }
+ attr = contract->next_segment(contract, base_attr_id);
+ if (attr)
+ {
+ out_msg = imv_msg_create_as_reply(&this->public);
+ out_msg->add_attribute(out_msg, attr);
+ result = out_msg->send(out_msg, TRUE);
+ out_msg->destroy(out_msg);
+ }
+ else
+ {
+ /* TODO no more segments - generate error message */
+ }
+ break;
}
+ default:
+ break;
}
}
enumerator->destroy(enumerator);
diff --git a/src/libimcv/imv/imv_state.h b/src/libimcv/imv/imv_state.h
index 3a93a5f95..30ed612b3 100644
--- a/src/libimcv/imv/imv_state.h
+++ b/src/libimcv/imv/imv_state.h
@@ -23,7 +23,7 @@
#define IMV_STATE_H_
#include "imv_session.h"
-#include "seg_contract/seg_contract_manager.h"
+#include "seg/seg_contract_manager.h"
#include <tncifimv.h>
diff --git a/src/libimcv/pa_tnc/pa_tnc_attr.h b/src/libimcv/pa_tnc/pa_tnc_attr.h
index 1e0c339c9..a5296692c 100644
--- a/src/libimcv/pa_tnc/pa_tnc_attr.h
+++ b/src/libimcv/pa_tnc/pa_tnc_attr.h
@@ -28,6 +28,9 @@ typedef struct pa_tnc_attr_t pa_tnc_attr_t;
#define PA_TNC_ATTR_HEADER_SIZE 12
+#define PA_TNC_ATTR_FLAG_NONE 0x00
+#define PA_TNC_ATTR_FLAG_NOSKIP (1<<7)
+
/**
* Interface for an RFC 5792 PA-TNC Posture Attribute.
*
diff --git a/src/libimcv/pa_tnc/pa_tnc_attr_manager.c b/src/libimcv/pa_tnc/pa_tnc_attr_manager.c
index 900a55716..7fae9a9dd 100644
--- a/src/libimcv/pa_tnc/pa_tnc_attr_manager.c
+++ b/src/libimcv/pa_tnc/pa_tnc_attr_manager.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Andreas Steffen
+ * Copyright (C) 2011-2014 Andreas Steffen
*
* HSR Hochschule fuer Technik Rapperswil
*
@@ -16,6 +16,10 @@
#include "pa_tnc_attr_manager.h"
+#include "imcv.h"
+#include "pa_tnc_attr.h"
+#include "ietf/ietf_attr_pa_tnc_error.h"
+
#include <collections/linked_list.h>
#include <utils/debug.h>
@@ -100,14 +104,102 @@ METHOD(pa_tnc_attr_manager_t, get_names, enum_name_t*,
return attr_names;
}
+/**
+ * PA-TNC attribute
+ *
+ * 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Flags | PA-TNC Attribute Vendor ID |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | PA-TNC Attribute Type |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | PA-TNC Attribute Length |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Attribute Value (Variable Length) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+#define PA_TNC_ATTR_INFO_SIZE 8
+
METHOD(pa_tnc_attr_manager_t, create, pa_tnc_attr_t*,
- private_pa_tnc_attr_manager_t *this, pen_t vendor_id, u_int32_t type,
- chunk_t value)
+ private_pa_tnc_attr_manager_t *this, bio_reader_t *reader, uint32_t *offset,
+ chunk_t msg_info, pa_tnc_attr_t **error)
{
+ uint8_t flags;
+ uint32_t type, length, attr_offset;
+ chunk_t value;
+ ietf_attr_pa_tnc_error_t *error_attr;
+ pen_t vendor_id;
+ pen_type_t unsupported_type;
+ pen_type_t error_code = { PEN_IETF, PA_ERROR_INVALID_PARAMETER };
+ enum_name_t *pa_attr_names;
+ pa_tnc_attr_t *attr = NULL;
enumerator_t *enumerator;
entry_t *entry;
- pa_tnc_attr_t *attr = NULL;
+ /* properly initialize error return argument in case of no error */
+ *error = NULL;
+
+ if (reader->remaining(reader) < PA_TNC_ATTR_HEADER_SIZE)
+ {
+ DBG1(DBG_TNC, "insufficient bytes for PA-TNC attribute header");
+ *error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
+ msg_info, *offset);
+ return NULL;
+ }
+ reader->read_uint8 (reader, &flags);
+ reader->read_uint24(reader, &vendor_id);
+ reader->read_uint32(reader, &type);
+ reader->read_uint32(reader, &length);
+
+ pa_attr_names = imcv_pa_tnc_attributes->get_names(imcv_pa_tnc_attributes,
+ vendor_id);
+ if (pa_attr_names)
+ {
+ DBG2(DBG_TNC, "processing PA-TNC attribute type '%N/%N' "
+ "0x%06x/0x%08x", pen_names, vendor_id,
+ pa_attr_names, type, vendor_id, type);
+ }
+ else
+ {
+ DBG2(DBG_TNC, "processing PA-TNC attribute type '%N' "
+ "0x%06x/0x%08x", pen_names, vendor_id,
+ vendor_id, type);
+ }
+
+ if (length < PA_TNC_ATTR_HEADER_SIZE)
+ {
+ DBG1(DBG_TNC, "%u bytes too small for PA-TNC attribute length",
+ length);
+ *error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
+ msg_info, *offset + PA_TNC_ATTR_INFO_SIZE);
+ return NULL;
+ }
+
+ if (!reader->read_data(reader, length - PA_TNC_ATTR_HEADER_SIZE, &value))
+ {
+ DBG1(DBG_TNC, "insufficient bytes for PA-TNC attribute value");
+ *error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
+ msg_info, *offset + PA_TNC_ATTR_INFO_SIZE);
+ return NULL;
+ }
+ DBG3(DBG_TNC, "%B", &value);
+
+ if (vendor_id == PEN_RESERVED)
+ {
+ *error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
+ msg_info, *offset + 1);
+ return NULL;
+ }
+ if (type == IETF_ATTR_RESERVED)
+ {
+ *error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
+ msg_info, *offset + 4);
+ return NULL;
+ }
+
+ /* check if the attribute type is registered */
enumerator = this->list->create_enumerator(this->list);
while (enumerator->enumerate(enumerator, &entry))
{
@@ -122,6 +214,39 @@ METHOD(pa_tnc_attr_manager_t, create, pa_tnc_attr_t*,
}
enumerator->destroy(enumerator);
+ if (!attr)
+ {
+ if (!(flags & PA_TNC_ATTR_FLAG_NOSKIP))
+ {
+ DBG1(DBG_TNC, "skipping unsupported PA-TNC attribute");
+ offset += length;
+ return NULL;
+ }
+
+ DBG1(DBG_TNC, "unsupported PA-TNC attribute with NOSKIP flag");
+ unsupported_type = pen_type_create(vendor_id, type);
+ error_code = pen_type_create(PEN_IETF, PA_ERROR_ATTR_TYPE_NOT_SUPPORTED);
+ *error = ietf_attr_pa_tnc_error_create(error_code, msg_info);
+ error_attr = (ietf_attr_pa_tnc_error_t*)(*error);
+ error_attr->set_unsupported_attr(error_attr, flags, unsupported_type);
+ return NULL;
+ }
+ if (attr->process(attr, &attr_offset) != SUCCESS)
+ {
+ attr->destroy(attr);
+ attr = NULL;
+ if (vendor_id == PEN_IETF && type == IETF_ATTR_PA_TNC_ERROR)
+ {
+ /* error while processing a PA-TNC error attribute - abort */
+ return NULL;
+ }
+ error_code = pen_type_create(PEN_IETF, PA_ERROR_INVALID_PARAMETER);
+ *error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
+ msg_info, *offset + PA_TNC_ATTR_HEADER_SIZE + attr_offset);
+ return NULL;
+ }
+ (*offset) += length;
+
return attr;
}
diff --git a/src/libimcv/pa_tnc/pa_tnc_attr_manager.h b/src/libimcv/pa_tnc/pa_tnc_attr_manager.h
index 121be7f90..0709c5b22 100644
--- a/src/libimcv/pa_tnc/pa_tnc_attr_manager.h
+++ b/src/libimcv/pa_tnc/pa_tnc_attr_manager.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Andreas Steffen
+ * Copyright (C) 2011-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@ typedef struct pa_tnc_attr_manager_t pa_tnc_attr_manager_t;
#include "pa_tnc_attr.h"
#include <library.h>
+#include <bio/bio_reader.h>
typedef pa_tnc_attr_t* (*pa_tnc_attr_create_t)(u_int32_t type, chunk_t value);
@@ -61,15 +62,17 @@ struct pa_tnc_attr_manager_t {
enum_name_t* (*get_names)(pa_tnc_attr_manager_t *this, pen_t vendor_id);
/**
- * Create a PA-TNC attribute object from data for a given vendor ID and type
+ * Create and pre-parse a PA-TNC attribute object from data
*
- * @param vendor_id Private Enterprise Number (PEN)
- * @param type PA-TNC attribute type
- * @param value PA-TNC attribute value as encoded data
+ * @param reader PA-TNC attribute as encoded data
+ * @param offset Offset in bytes where an error has been found
+ * @param msg_info Message info added to an error attribute
+ * @param error Error attribute if an error occurred
* @return PA-TNC attribute object if supported, NULL else
*/
- pa_tnc_attr_t* (*create)(pa_tnc_attr_manager_t *this, pen_t vendor_id,
- u_int32_t type, chunk_t value);
+ pa_tnc_attr_t* (*create)(pa_tnc_attr_manager_t *this, bio_reader_t *reader,
+ uint32_t *offset, chunk_t msg_info,
+ pa_tnc_attr_t **error);
/**
* Destroys a pa_tnc_attr_manager_t object.
diff --git a/src/libimcv/pa_tnc/pa_tnc_msg.c b/src/libimcv/pa_tnc/pa_tnc_msg.c
index 4cfb9bdd0..5a0afcdc0 100644
--- a/src/libimcv/pa_tnc/pa_tnc_msg.c
+++ b/src/libimcv/pa_tnc/pa_tnc_msg.c
@@ -37,28 +37,6 @@ typedef struct private_pa_tnc_msg_t private_pa_tnc_msg_t;
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
-#define PA_TNC_RESERVED 0x000000
-
-/**
- * PA-TNC attribute
- *
- * 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Flags | PA-TNC Attribute Vendor ID |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | PA-TNC Attribute Type |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | PA-TNC Attribute Length |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Attribute Value (Variable Length) |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-
-#define PA_TNC_ATTR_FLAG_NONE 0x00
-#define PA_TNC_ATTR_FLAG_NOSKIP (1<<7)
-#define PA_TNC_ATTR_INFO_SIZE 8
-
/**
* Private data of a pa_tnc_msg_t object.
*
@@ -96,6 +74,11 @@ struct private_pa_tnc_msg_t {
size_t max_msg_len;
/**
+ * TRUE if attribute was extracted from data
+ */
+ bool from_data;
+
+ /**
* Encoded message
*/
chunk_t encoding;
@@ -113,17 +96,19 @@ METHOD(pa_tnc_msg_t, add_attribute, bool,
chunk_t attr_value;
size_t attr_len;
- attr->build(attr);
- attr_value = attr->get_value(attr);
- attr_len = PA_TNC_ATTR_HEADER_SIZE + attr_value.len;
-
- if (this->max_msg_len && this->msg_len + attr_len > this->max_msg_len)
+ if (!this->from_data)
{
- /* attribute just does not fit into this message */
- return FALSE;
- }
- this->msg_len += attr_len;
+ attr->build(attr);
+ attr_value = attr->get_value(attr);
+ attr_len = PA_TNC_ATTR_HEADER_SIZE + attr_value.len;
+ if (this->max_msg_len && this->msg_len + attr_len > this->max_msg_len)
+ {
+ /* attribute just does not fit into this message */
+ return FALSE;
+ }
+ this->msg_len += attr_len;
+ }
this->attributes->insert_last(this->attributes, attr);
return TRUE;
}
@@ -201,9 +186,9 @@ METHOD(pa_tnc_msg_t, process, status_t,
private_pa_tnc_msg_t *this)
{
bio_reader_t *reader;
- pa_tnc_attr_t *error;
+ pa_tnc_attr_t *attr, *error;
uint8_t version;
- uint32_t reserved, offset, attr_offset;
+ uint32_t reserved, offset;
pen_type_t error_code = { PEN_IETF, PA_ERROR_INVALID_PARAMETER };
/* process message header */
@@ -231,116 +216,21 @@ METHOD(pa_tnc_msg_t, process, status_t,
offset = PA_TNC_HEADER_SIZE;
/* pre-process PA-TNC attributes */
- while (reader->remaining(reader) >= PA_TNC_ATTR_HEADER_SIZE)
+ while (reader->remaining(reader) > 0)
{
- pen_t vendor_id;
- uint8_t flags;
- uint32_t type, length;
- chunk_t value;
- pa_tnc_attr_t *attr;
- enum_name_t *pa_attr_names;
- ietf_attr_pa_tnc_error_t *error_attr;
- pen_type_t unsupported_type;
-
- reader->read_uint8 (reader, &flags);
- reader->read_uint24(reader, &vendor_id);
- reader->read_uint32(reader, &type);
- reader->read_uint32(reader, &length);
-
- pa_attr_names = imcv_pa_tnc_attributes->get_names(imcv_pa_tnc_attributes,
- vendor_id);
- if (pa_attr_names)
- {
- DBG2(DBG_TNC, "processing PA-TNC attribute type '%N/%N' "
- "0x%06x/0x%08x", pen_names, vendor_id,
- pa_attr_names, type, vendor_id, type);
- }
- else
- {
- DBG2(DBG_TNC, "processing PA-TNC attribute type '%N' "
- "0x%06x/0x%08x", pen_names, vendor_id,
- vendor_id, type);
- }
-
- if (length < PA_TNC_ATTR_HEADER_SIZE)
- {
- DBG1(DBG_TNC, "%u bytes too small for PA-TNC attribute length",
- length);
- error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
- this->encoding, offset + PA_TNC_ATTR_INFO_SIZE);
- goto err;
- }
-
- if (!reader->read_data(reader, length - PA_TNC_ATTR_HEADER_SIZE, &value))
- {
- DBG1(DBG_TNC, "insufficient bytes for PA-TNC attribute value");
- error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
- this->encoding, offset + PA_TNC_ATTR_INFO_SIZE);
- goto err;
- }
- DBG3(DBG_TNC, "%B", &value);
-
- if (vendor_id == PEN_RESERVED)
- {
- error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
- this->encoding, offset + 1);
- goto err;
- }
- if (type == IETF_ATTR_RESERVED)
- {
- error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
- this->encoding, offset + 4);
- goto err;
- }
attr = imcv_pa_tnc_attributes->create(imcv_pa_tnc_attributes,
- vendor_id, type, value);
- if (!attr)
+ reader, &offset, this->encoding, &error);
+ if (error)
{
- if (!(flags & PA_TNC_ATTR_FLAG_NOSKIP))
- {
- DBG1(DBG_TNC, "skipping unsupported PA-TNC attribute");
- offset += length;
- continue;
- }
-
- DBG1(DBG_TNC, "unsupported PA-TNC attribute with NOSKIP flag");
- unsupported_type = pen_type_create(vendor_id, type);
- error_code = pen_type_create(PEN_IETF,
- PA_ERROR_ATTR_TYPE_NOT_SUPPORTED);
- error = ietf_attr_pa_tnc_error_create(error_code, this->encoding);
- error_attr = (ietf_attr_pa_tnc_error_t*)error;
- error_attr->set_unsupported_attr(error_attr, flags, unsupported_type);
goto err;
}
-
- if (attr->process(attr, &attr_offset) != SUCCESS)
+ if (attr)
{
- attr->destroy(attr);
- if (vendor_id == PEN_IETF && type == IETF_ATTR_PA_TNC_ERROR)
- {
- /* error while processing a PA-TNC error attribute - abort */
- reader->destroy(reader);
- return FAILED;
- }
- error_code = pen_type_create(PEN_IETF,
- PA_ERROR_INVALID_PARAMETER);
- error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
- this->encoding,
- offset + PA_TNC_ATTR_HEADER_SIZE + attr_offset);
- goto err;
+ this->attributes->insert_last(this->attributes, attr);
}
- this->attributes->insert_last(this->attributes, attr);
- offset += length;
}
-
- if (reader->remaining(reader) == 0)
- {
- reader->destroy(reader);
- return SUCCESS;
- }
- DBG1(DBG_TNC, "insufficient bytes for PA-TNC attribute header");
- error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
- this->encoding, offset);
+ reader->destroy(reader);
+ return SUCCESS;
err:
reader->destroy(reader);
@@ -509,6 +399,7 @@ pa_tnc_msg_t *pa_tnc_msg_create_from_data(chunk_t data)
.encoding = chunk_clone(data),
.attributes = linked_list_create(),
.errors = linked_list_create(),
+ .from_data = TRUE,
);
return &this->public;
diff --git a/src/libimcv/pa_tnc/pa_tnc_msg.h b/src/libimcv/pa_tnc/pa_tnc_msg.h
index 57ff1a04c..a33690890 100644
--- a/src/libimcv/pa_tnc/pa_tnc_msg.h
+++ b/src/libimcv/pa_tnc/pa_tnc_msg.h
@@ -25,6 +25,9 @@ typedef struct pa_tnc_msg_t pa_tnc_msg_t;
#define PA_TNC_VERSION 0x01
#define PA_TNC_HEADER_SIZE 8
+#define PA_TNC_RESERVED 0x000000
+
+
#include "pa_tnc_attr.h"
diff --git a/src/libimcv/seg_contract/seg_contract.c b/src/libimcv/seg/seg_contract.c
index dab2c239f..589d6d1cd 100644
--- a/src/libimcv/seg_contract/seg_contract.c
+++ b/src/libimcv/seg/seg_contract.c
@@ -14,16 +14,19 @@
*/
#include "seg_contract.h"
+#include "seg_env.h"
#include <utils/debug.h>
+#include <bio/bio_writer.h>
#include <tncif_pa_subtypes.h>
+#include <tcg/seg/tcg_seg_attr_seg_env.h>
+
typedef struct private_seg_contract_t private_seg_contract_t;
/**
* Private data of a seg_contract_t object.
- *
*/
struct private_seg_contract_t {
@@ -48,6 +51,17 @@ struct private_seg_contract_t {
uint32_t max_seg_size;
/**
+ * Maximum PA-TNC attribute segment size
+ */
+ uint32_t last_base_attr_id;
+
+ /**
+ * List of attribute segment envelopes
+ */
+
+ linked_list_t *seg_envs;
+
+ /**
* Is this a null contract?
*/
bool is_null;
@@ -97,6 +111,154 @@ METHOD(seg_contract_t, get_max_size, void,
}
}
+METHOD(seg_contract_t, check_size, bool,
+ private_seg_contract_t *this, pa_tnc_attr_t *attr, bool *oversize)
+{
+ chunk_t attr_value;
+ size_t attr_len;
+
+ *oversize = FALSE;
+
+ if (this->is_null)
+ {
+ /* null segmentation contract */
+ return FALSE;
+ }
+ attr->build(attr);
+ attr_value = attr->get_value(attr);
+ attr_len = PA_TNC_ATTR_HEADER_SIZE + attr_value.len;
+
+ if (attr_len > this->max_attr_size)
+ {
+ /* oversize attribute */
+ *oversize = TRUE;
+ return FALSE;
+ }
+ if (this->max_seg_size == SEG_CONTRACT_NO_FRAGMENTATION)
+ {
+ /* no fragmentation wanted */
+ return FALSE;
+ }
+ return attr_value.len > this->max_seg_size + TCG_SEG_ATTR_SEG_ENV_HEADER;
+}
+
+METHOD(seg_contract_t, first_segment, pa_tnc_attr_t*,
+ private_seg_contract_t *this, pa_tnc_attr_t *attr)
+{
+ seg_env_t *seg_env;
+
+ seg_env = seg_env_create(++this->last_base_attr_id, attr,
+ this->max_seg_size);
+ if (!seg_env)
+ {
+ return NULL;
+ }
+ this->seg_envs->insert_last(this->seg_envs, seg_env);
+
+ return seg_env->first_segment(seg_env);
+}
+
+METHOD(seg_contract_t, next_segment, pa_tnc_attr_t*,
+ private_seg_contract_t *this, uint32_t base_attr_id)
+{
+ pa_tnc_attr_t *seg_env_attr = NULL;
+ seg_env_t *seg_env;
+ bool last_segment = FALSE;
+ enumerator_t *enumerator;
+
+ enumerator = this->seg_envs->create_enumerator(this->seg_envs);
+ while (enumerator->enumerate(enumerator, &seg_env))
+ {
+ if (seg_env->get_base_attr_id(seg_env) == base_attr_id)
+ {
+ seg_env_attr = seg_env->next_segment(seg_env, &last_segment);
+ if (!seg_env_attr)
+ {
+ break;
+ }
+ if (last_segment)
+ {
+ this->seg_envs->remove_at(this->seg_envs, enumerator);
+ seg_env->destroy(seg_env);
+ }
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ return seg_env_attr;
+}
+
+METHOD(seg_contract_t, add_segment, pa_tnc_attr_t*,
+ private_seg_contract_t *this, pa_tnc_attr_t *attr, pa_tnc_attr_t **error,
+ bool *more)
+{
+ tcg_seg_attr_seg_env_t *seg_env_attr;
+ seg_env_t *current, *seg_env = NULL;
+ pa_tnc_attr_t *base_attr;
+ uint32_t base_attr_id;
+ uint8_t flags;
+ chunk_t segment_data;
+ enumerator_t *enumerator;
+
+ seg_env_attr = (tcg_seg_attr_seg_env_t*)attr;
+ base_attr_id = seg_env_attr->get_base_attr_id(seg_env_attr);
+ segment_data = seg_env_attr->get_segment(seg_env_attr, &flags);
+ *more = flags & SEG_ENV_FLAG_MORE;
+ *error = NULL;
+
+ enumerator = this->seg_envs->create_enumerator(this->seg_envs);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (current->get_base_attr_id(current) == base_attr_id)
+ {
+ seg_env = current;
+ if (!(*more))
+ {
+ this->seg_envs->remove_at(this->seg_envs, enumerator);
+ }
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (flags & SEG_ENV_FLAG_START)
+ {
+ if (seg_env)
+ {
+ DBG1(DBG_TNC, "base attribute ID %d is already in use",
+ base_attr_id);
+ return NULL;
+ }
+ DBG2(DBG_TNC, "received first segment for base attribute ID %d "
+ "(%d bytes)", base_attr_id, segment_data.len);
+ seg_env = seg_env_create_from_data(base_attr_id, segment_data,
+ this->max_seg_size);
+ this->seg_envs->insert_last(this->seg_envs, seg_env);
+ }
+ else
+ {
+ if (!seg_env)
+ {
+ DBG1(DBG_TNC, "base attribute ID %d not found", base_attr_id);
+ return NULL;
+ }
+ DBG2(DBG_TNC, "received %s segment for base attribute ID %d "
+ "(%d bytes)", (*more) ? "next" : "last", base_attr_id,
+ segment_data.len);
+ seg_env->add_segment(seg_env, segment_data);
+ }
+ if (*more)
+ {
+ return NULL;
+ }
+ base_attr = seg_env->get_base_attr(seg_env, error);
+ seg_env->destroy(seg_env);
+
+ return base_attr;
+}
+
+
METHOD(seg_contract_t, is_issuer, bool,
private_seg_contract_t *this)
{
@@ -206,6 +368,7 @@ METHOD(seg_contract_t, get_info_string, void,
METHOD(seg_contract_t, destroy, void,
private_seg_contract_t *this)
{
+ this->seg_envs->destroy_offset(this->seg_envs, offsetof(seg_env_t, destroy));
free(this);
}
@@ -225,6 +388,10 @@ seg_contract_t *seg_contract_create(pen_type_t msg_type,
.get_msg_type = _get_msg_type,
.set_max_size = _set_max_size,
.get_max_size = _get_max_size,
+ .check_size = _check_size,
+ .first_segment = _first_segment,
+ .next_segment = _next_segment,
+ .add_segment = _add_segment,
.is_issuer = _is_issuer,
.is_null = _is_null,
.get_info_string = _get_info_string,
@@ -233,6 +400,7 @@ seg_contract_t *seg_contract_create(pen_type_t msg_type,
.msg_type = msg_type,
.max_attr_size = max_attr_size,
.max_seg_size = max_seg_size,
+ .seg_envs = linked_list_create(),
.is_issuer = is_issuer,
.issuer_id = issuer_id,
.is_imc = is_imc,
diff --git a/src/libimcv/seg_contract/seg_contract.h b/src/libimcv/seg/seg_contract.h
index 26f55c9ce..48828c472 100644
--- a/src/libimcv/seg_contract/seg_contract.h
+++ b/src/libimcv/seg/seg_contract.h
@@ -23,6 +23,8 @@
typedef struct seg_contract_t seg_contract_t;
+#include "pa_tnc/pa_tnc_attr.h"
+
#include <library.h>
#include <pen/pen.h>
@@ -47,8 +49,8 @@ struct seg_contract_t {
/**
* Set maximum PA-TNC attribute and segment size in octets
*
- * @param max_attr_size Maximum PA-TNC attribute size in octets
- * @param max_seg_size Maximum PA-TNC attribute segment size in octets
+ * @param max_attr_size Maximum PA-TNC attribute size in octets
+ * @param max_seg_size Maximum PA-TNC attribute segment size in octets
*/
void (*set_max_size)(seg_contract_t *this, uint32_t max_attr_size,
uint32_t max_seg_size);
@@ -56,33 +58,71 @@ struct seg_contract_t {
/**
* Get maximum PA-TNC attribute and segment size in octets
*
- * @param max_attr_size Maximum PA-TNC attribute size in octets
- * @param max_seg_size Maximum PA-TNC attribute segment size in octets
+ * @param max_attr_size Maximum PA-TNC attribute size in octets
+ * @param max_seg_size Maximum PA-TNC attribute segment size in octets
*/
void (*get_max_size)(seg_contract_t *this, uint32_t *max_attr_size,
uint32_t *max_seg_size);
/**
+ * Check if a PA-TNC attribute must be segmented or is oversized
+ *
+ * @param attr PA-TNC attribute to be checked
+ * @param oversize PA-TNC attribute is larger than maximum size
+ * @return TRUE if PA-TNC attribute must be segmented
+ */
+ bool (*check_size)(seg_contract_t *this, pa_tnc_attr_t *attr,
+ bool *oversize);
+
+ /**
+ * Generate first segment of a PA-TNC attribute according to the contract
+ *
+ * @param attr PA-TNC attribute to be segmented
+ * @return First segment envelope attribute
+ */
+ pa_tnc_attr_t* (*first_segment)(seg_contract_t *this, pa_tnc_attr_t *attr);
+
+ /**
+ * Generate next segment of a PA-TNC attribute according to the contract
+ *
+ * @param base_attr_id Base Attribute ID
+ * @return Next segment envelope attribute
+ */
+ pa_tnc_attr_t* (*next_segment)(seg_contract_t *this, uint32_t base_attr_id);
+
+ /**
+ * Add an attribute segments until the PA-TNC attribute is reconstructed
+ *
+ * @param attr Segment envelope attribute
+ * @param error Error attribute if an error occurred or NULL
+ * @param more Need more segments
+ * @return Completed PA-TNC attribute or NULL
+ */
+ pa_tnc_attr_t* (*add_segment)(seg_contract_t *this,
+ pa_tnc_attr_t *attr, pa_tnc_attr_t **error,
+ bool *more);
+
+ /**
* Get contract role
*
- * @return TRUE: contracting party (issuer),
- * FALSE: contracted party
+ * @return TRUE: contracting party (issuer),
+ * FALSE: contracted party
*/
bool (*is_issuer)(seg_contract_t *this);
/**
* Is this a null contract ?
*
- * @return TRUE if null contract
+ * @return TRUE if null contract
*/
bool (*is_null)(seg_contract_t *this);
/**
* Get an info string about the contract
*
- * @param buf String buffer of at least size len
- * @param len Size of string buffer
- * @param request TRUE if contract request, FALSE if response
+ * @param buf String buffer of at least size len
+ * @param len Size of string buffer
+ * @param request TRUE if contract request, FALSE if response
*/
void (*get_info_string)(seg_contract_t *this, char *buf, size_t len,
bool request);
@@ -96,7 +136,7 @@ struct seg_contract_t {
/**
* Create a PA-TNC attribute segmentation contract
*
- * @param msg_type PA-TNC message type
+ * @param msg_type PA-TNC message type
* @param max_attr_size Maximum PA-TNC attribute size in octets
* @param max_seg_size Maximum PA-TNC attribute segment size in octets
* @param is_issuer TRUE if issuer of the contract
diff --git a/src/libimcv/seg_contract/seg_contract_manager.c b/src/libimcv/seg/seg_contract_manager.c
index d099436fc..d099436fc 100644
--- a/src/libimcv/seg_contract/seg_contract_manager.c
+++ b/src/libimcv/seg/seg_contract_manager.c
diff --git a/src/libimcv/seg_contract/seg_contract_manager.h b/src/libimcv/seg/seg_contract_manager.h
index 355822d99..355822d99 100644
--- a/src/libimcv/seg_contract/seg_contract_manager.h
+++ b/src/libimcv/seg/seg_contract_manager.h
diff --git a/src/libimcv/seg/seg_env.c b/src/libimcv/seg/seg_env.c
new file mode 100644
index 000000000..1f4cfc53f
--- /dev/null
+++ b/src/libimcv/seg/seg_env.c
@@ -0,0 +1,261 @@
+/*
+ * Copyright (C) 2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "seg_env.h"
+
+#include "imcv.h"
+#include "pa_tnc/pa_tnc_msg.h"
+
+#include <utils/debug.h>
+#include <bio/bio_reader.h>
+#include <bio/bio_writer.h>
+
+#include <tcg/seg/tcg_seg_attr_seg_env.h>
+
+#define BASE_ATTR_ID_PREFIX 0xFF
+
+typedef struct private_seg_env_t private_seg_env_t;
+
+/**
+ * Private data of a seg_env_t object.
+ */
+struct private_seg_env_t {
+
+ /**
+ * Public seg_env_t interface.
+ */
+ seg_env_t public;
+
+ /**
+ * Base Attribute ID
+ */
+ uint32_t base_attr_id;
+
+ /**
+ * Base Attribute
+ */
+ pa_tnc_attr_t *base_attr;
+
+ /**
+ * Maximum PA-TNC attribute segment size
+ */
+ uint32_t max_seg_size;
+
+ /**
+ * TRUE if attribute is assembled from data
+ */
+ bool from_data;
+
+ /**
+ * Remaining attribute data to be sent or received data being accumulated
+ */
+ chunk_t data;
+
+};
+
+METHOD(seg_env_t, get_base_attr_id, uint32_t,
+ private_seg_env_t *this)
+{
+ return this->base_attr_id;
+}
+
+METHOD(seg_env_t, get_base_attr, pa_tnc_attr_t*,
+ private_seg_env_t *this, pa_tnc_attr_t** error)
+{
+ *error = NULL;
+
+ if (!this->base_attr)
+ {
+ bio_writer_t *writer;
+ bio_reader_t *reader;
+ chunk_t msg_info;
+ uint32_t offset = 0;
+
+ writer = bio_writer_create(8);
+ writer->write_uint8 (writer, PA_TNC_VERSION);
+ writer->write_uint24(writer, PA_TNC_RESERVED);
+ writer->write_uint8 (writer, BASE_ATTR_ID_PREFIX);
+ writer->write_uint24(writer, this->base_attr_id);
+ msg_info = writer->extract_buf(writer);
+ writer->destroy(writer);
+
+ reader = bio_reader_create(this->data);
+ this->base_attr = imcv_pa_tnc_attributes->create(imcv_pa_tnc_attributes,
+ reader, &offset, msg_info, error);
+ chunk_free(&msg_info);
+ reader->destroy(reader);
+ }
+
+ return this->base_attr ? this->base_attr->get_ref(this->base_attr) : NULL;
+}
+
+METHOD(seg_env_t, first_segment, pa_tnc_attr_t*,
+ private_seg_env_t *this)
+{
+ pa_tnc_attr_t *seg_env_attr;
+ bio_writer_t *writer;
+ pen_type_t type;
+ chunk_t segment_data, value;
+ uint8_t flags, seg_env_flags;
+
+ /* get components of base attribute header and data */
+ flags = this->base_attr->get_noskip_flag(this->base_attr) ?
+ PA_TNC_ATTR_FLAG_NOSKIP : PA_TNC_ATTR_FLAG_NONE;
+ type = this->base_attr->get_type(this->base_attr);
+
+ /* attribute data going into the first segment */
+ segment_data = this->data;
+ segment_data.len = this->max_seg_size - PA_TNC_ATTR_HEADER_SIZE;
+
+ /* build encoding of the base attribute header and first segment data */
+ writer = bio_writer_create(this->max_seg_size);
+ writer->write_uint8 (writer, flags);
+ writer->write_uint24(writer, type.vendor_id);
+ writer->write_uint32(writer, type.type);
+ writer->write_uint32(writer, PA_TNC_ATTR_HEADER_SIZE + this->data.len);
+ writer->write_data (writer, segment_data);
+ value = writer->extract_buf(writer);
+ writer->destroy(writer);
+ this->data = chunk_skip(this->data, segment_data.len);
+
+ DBG2(DBG_TNC, "creating first segment for base attribute ID %d (%d bytes)",
+ this->base_attr_id, this->max_seg_size);
+
+ seg_env_flags = SEG_ENV_FLAG_START | SEG_ENV_FLAG_MORE;
+ seg_env_attr = tcg_seg_attr_seg_env_create(value, seg_env_flags,
+ this->base_attr_id);
+ chunk_free(&value);
+
+ return seg_env_attr;
+}
+
+METHOD(seg_env_t, next_segment, pa_tnc_attr_t*,
+ private_seg_env_t *this, bool *last)
+{
+ pa_tnc_attr_t *seg_env_attr;
+ chunk_t segment_data;
+ uint8_t seg_env_flags;
+ bool is_last_segment;
+
+ if (this->data.len == 0)
+ {
+ /* no more attribute data to segment available */
+ return NULL;
+ }
+
+ /* attribute data going into the next segment */
+ segment_data = this->data;
+ segment_data.len = min(this->max_seg_size, this->data.len);
+ this->data = chunk_skip(this->data, segment_data.len);
+
+ is_last_segment = (this->data.len == 0);
+ if (last)
+ {
+ *last = is_last_segment;
+ }
+ DBG2(DBG_TNC, "creating %s segment for base attribute ID %d (%d bytes)",
+ is_last_segment ? "last" : "next", this->base_attr_id,
+ segment_data.len);
+
+ seg_env_flags = is_last_segment ? SEG_ENV_FLAG_NONE : SEG_ENV_FLAG_MORE;
+ seg_env_attr = tcg_seg_attr_seg_env_create(segment_data, seg_env_flags,
+ this->base_attr_id);
+
+ return seg_env_attr;
+}
+
+METHOD(seg_env_t, add_segment, void,
+ private_seg_env_t *this, chunk_t segment_data)
+{
+ this->data = chunk_cat("mc", this->data, segment_data);
+}
+
+METHOD(seg_env_t, destroy, void,
+ private_seg_env_t *this)
+{
+ if (this->from_data)
+ {
+ chunk_free(&this->data);
+ }
+ DESTROY_IF(this->base_attr);
+ free(this);
+}
+
+/**
+ * See header
+ */
+seg_env_t *seg_env_create(uint32_t base_attr_id, pa_tnc_attr_t *base_attr,
+ uint32_t max_seg_size)
+{
+ private_seg_env_t *this;
+ chunk_t value;
+
+ base_attr->build(base_attr);
+ value = base_attr->get_value(base_attr);
+
+ /**
+ * The PA-TNC attribute header must not be segmented and
+ * there must be at least a first and one next segment
+ */
+ if (max_seg_size < PA_TNC_ATTR_HEADER_SIZE ||
+ max_seg_size >= PA_TNC_ATTR_HEADER_SIZE + value.len)
+ {
+ return NULL;
+ }
+
+ INIT(this,
+ .public = {
+ .get_base_attr_id = _get_base_attr_id,
+ .get_base_attr = _get_base_attr,
+ .first_segment = _first_segment,
+ .next_segment = _next_segment,
+ .add_segment = _add_segment,
+ .destroy = _destroy,
+ },
+ .base_attr_id = base_attr_id,
+ .base_attr = base_attr->get_ref(base_attr),
+ .max_seg_size = max_seg_size,
+ .data = base_attr->get_value(base_attr),
+ );
+
+ return &this->public;
+}
+
+/**
+ * See header
+ */
+seg_env_t *seg_env_create_from_data(uint32_t base_attr_id, chunk_t data,
+ uint32_t max_seg_size)
+{
+ private_seg_env_t *this;
+
+ INIT(this,
+ .public = {
+ .get_base_attr_id = _get_base_attr_id,
+ .get_base_attr = _get_base_attr,
+ .first_segment = _first_segment,
+ .next_segment = _next_segment,
+ .add_segment = _add_segment,
+ .destroy = _destroy,
+ },
+ .base_attr_id = base_attr_id,
+ .max_seg_size = max_seg_size,
+ .data = chunk_clone(data),
+ .from_data = TRUE,
+ );
+
+ return &this->public;
+}
+
diff --git a/src/libimcv/seg/seg_env.h b/src/libimcv/seg/seg_env.h
new file mode 100644
index 000000000..0dcefdde8
--- /dev/null
+++ b/src/libimcv/seg/seg_env.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup seg_env seg_env
+ * @{ @ingroup libimcv
+ */
+
+#ifndef SEG_ENV_H_
+#define SEG_ENV_H_
+
+typedef struct seg_env_t seg_env_t;
+typedef enum seg_env_flags_t seg_env_flags_t;
+
+#include <library.h>
+
+#include <pa_tnc/pa_tnc_attr.h>
+
+/**
+ * Segment Envelope flags
+ */
+enum seg_env_flags_t {
+ SEG_ENV_FLAG_NONE = 0,
+ SEG_ENV_FLAG_MORE = (1<<7),
+ SEG_ENV_FLAG_START = (1<<6)
+};
+
+/**
+ * Interface for a PA-TNC attribute segment envelope object
+ */
+struct seg_env_t {
+
+ /**
+ * Get Base Attribute ID
+ *
+ * @return Base Attribute ID
+ */
+ uint32_t (*get_base_attr_id)(seg_env_t *this);
+
+ /**
+ * Get Base Attribute
+ *
+ * @param error Error attribute if an error occurred or NULL
+ * @return Base Attribute (must be destroyed) or NULL
+ */
+ pa_tnc_attr_t* (*get_base_attr)(seg_env_t *this, pa_tnc_attr_t **error);
+
+ /**
+ * Generate the first segment envelope of the base attribute
+ *
+ * @return First attribute segment envelope
+ */
+ pa_tnc_attr_t* (*first_segment)(seg_env_t *this);
+
+ /**
+ * Generate the next segment envelope of the base attribute
+ *
+ * @param last TRUE if last segment
+ * @return Next attribute segment envelope
+ */
+ pa_tnc_attr_t* (*next_segment)(seg_env_t *this, bool *last);
+
+ /**
+ * Generate the first segment envelope of the base attribute
+ *
+ * @param segment Attribute segment to be added
+ */
+ void (*add_segment)(seg_env_t *this, chunk_t segment);
+
+ /**
+ * Destroys a seg_env_t object.
+ */
+ void (*destroy)(seg_env_t *this);
+};
+
+/**
+ * Create a PA-TNC attribute segment envelope object
+ *
+ * @param base_attr_id Base Attribute ID
+ * @param base_attr Base Attribute to be segmented
+ * @param max_seg_size Maximum segment size
+ */
+seg_env_t* seg_env_create(uint32_t base_attr_id, pa_tnc_attr_t *base_attr,
+ uint32_t max_seg_size);
+
+/**
+ * Create a PA-TNC attribute segment envelope object
+ *
+ * @param base_attr_id Base Attribute ID
+ * @param data First attribute segment
+ * @param max_seg_size Maximum segment size
+ */
+seg_env_t* seg_env_create_from_data(uint32_t base_attr_id, chunk_t data,
+ uint32_t max_seg_size);
+
+#endif /** SEG_ENV_H_ @}*/
diff --git a/src/libpts/Makefile.am b/src/libpts/Makefile.am
index be5c26c50..f047b5233 100644
--- a/src/libpts/Makefile.am
+++ b/src/libpts/Makefile.am
@@ -70,7 +70,8 @@ libpts_la_SOURCES = \
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.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
diff --git a/src/libpts/plugins/imc_swid/imc_swid.c b/src/libpts/plugins/imc_swid/imc_swid.c
index 5da367bd1..3763731a0 100644
--- a/src/libpts/plugins/imc_swid/imc_swid.c
+++ b/src/libpts/plugins/imc_swid/imc_swid.c
@@ -241,43 +241,15 @@ static bool add_swid_inventory(imc_state_t *state, imc_msg_t *msg,
{
tcg_swid_attr_tag_id_inv_t *swid_id_attr;
swid_tag_id_t *tag_id;
- chunk_t tag_creator, unique_sw_id, instance_id;
- /* At least one TCG Tag ID Inventory attribute is sent */
- attr_size = PA_TNC_ATTR_HEADER_SIZE + TCG_SWID_TAG_ID_INV_MIN_SIZE;
+ /* 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))
{
- tag_creator = tag_id->get_tag_creator(tag_id);
- unique_sw_id = tag_id->get_unique_sw_id(tag_id, &instance_id);
- entry_size = 2 + tag_creator.len + 2 + unique_sw_id.len +
- 2 + instance_id.len;
-
- if (attr_size + entry_size > max_attr_size)
- {
- if (first)
- {
- /**
- * Send an ITA Start Angel attribute to the IMV signalling
- * that multiple TGC SWID Tag ID Inventory attributes follow
- */
- attr_angel = ita_attr_angel_create(TRUE);
- msg->add_attribute(msg, attr_angel);
- first = FALSE;
- }
- msg->add_attribute(msg, attr);
-
- /* create the next TCG SWID Tag ID Inventory attribute */
- attr_size = PA_TNC_ATTR_HEADER_SIZE +
- TCG_SWID_TAG_ID_INV_MIN_SIZE;
- attr = tcg_swid_attr_tag_id_inv_create(request_id, eid_epoch, 1);
- }
- swid_id_attr = (tcg_swid_attr_tag_id_inv_t*)attr;
swid_id_attr->add(swid_id_attr, tag_id->get_ref(tag_id));
- attr_size += entry_size;
}
enumerator->destroy(enumerator);
}
diff --git a/src/libpts/plugins/imv_attestation/build-database.sh b/src/libpts/plugins/imv_attestation/build-database.sh
index b8d5037b1..980de47ff 100755
--- a/src/libpts/plugins/imv_attestation/build-database.sh
+++ b/src/libpts/plugins/imv_attestation/build-database.sh
@@ -2,7 +2,7 @@
p="Ubuntu 14.04 x86_64"
a="x86_64-linux-gnu"
-k="3.13.0-32-generic"
+k="3.13.0-34-generic"
for hash in sha1 sha256
do
diff --git a/src/libpts/tcg/seg/tcg_seg_attr_next_seg.c b/src/libpts/tcg/seg/tcg_seg_attr_next_seg.c
new file mode 100644
index 000000000..22934cc1f
--- /dev/null
+++ b/src/libpts/tcg/seg/tcg_seg_attr_next_seg.c
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tcg_seg_attr_next_seg.h"
+
+#include <pa_tnc/pa_tnc_msg.h>
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <utils/debug.h>
+
+typedef struct private_tcg_seg_attr_next_seg_t private_tcg_seg_attr_next_seg_t;
+
+typedef enum {
+ NEXT_SEG_FLAG_NONE = 0,
+ NEXT_SEG_FLAG_CANCEL = 1
+} next_seg_flags_t;
+
+/**
+ * Next Segment
+ * see TCG IF-M Segmentation Specification
+ *
+ * 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |C| Reserved | Base Attribute ID |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+/**
+ * Private data of an tcg_seg_attr_next_seg_t object.
+ */
+struct private_tcg_seg_attr_next_seg_t {
+
+ /**
+ * Public members of tcg_seg_attr_next_seg_t
+ */
+ tcg_seg_attr_next_seg_t public;
+
+ /**
+ * Vendor-specific attribute type
+ */
+ pen_type_t type;
+
+ /**
+ * Attribute value
+ */
+ chunk_t value;
+
+ /**
+ * Noskip flag
+ */
+ bool noskip_flag;
+
+ /**
+ * Cancel flag
+ */
+ bool cancel_flag;
+
+ /**
+ * Base Attribute ID
+ */
+ uint32_t base_attr_id;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+};
+
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
+ private_tcg_seg_attr_next_seg_t *this)
+{
+ return this->type;
+}
+
+METHOD(pa_tnc_attr_t, get_value, chunk_t,
+ private_tcg_seg_attr_next_seg_t *this)
+{
+ return this->value;
+}
+
+METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
+ private_tcg_seg_attr_next_seg_t *this)
+{
+ return this->noskip_flag;
+}
+
+METHOD(pa_tnc_attr_t, set_noskip_flag,void,
+ private_tcg_seg_attr_next_seg_t *this, bool noskip)
+{
+ this->noskip_flag = noskip;
+}
+
+METHOD(pa_tnc_attr_t, build, void,
+ private_tcg_seg_attr_next_seg_t *this)
+{
+ bio_writer_t *writer;
+
+ if (this->value.ptr)
+ {
+ return;
+ }
+ writer = bio_writer_create(TCG_SEG_ATTR_NEXT_SEG_SIZE);
+ writer->write_uint8 (writer, this->cancel_flag ? NEXT_SEG_FLAG_CANCEL :
+ NEXT_SEG_FLAG_NONE);
+ writer->write_uint24(writer, this->base_attr_id);
+
+ this->value = writer->extract_buf(writer);
+ writer->destroy(writer);
+}
+
+METHOD(pa_tnc_attr_t, process, status_t,
+ private_tcg_seg_attr_next_seg_t *this, u_int32_t *offset)
+{
+ bio_reader_t *reader;
+ uint8_t flags;
+
+ if (this->value.len < TCG_SEG_ATTR_NEXT_SEG_SIZE)
+ {
+ DBG1(DBG_TNC, "insufficient data for %N", tcg_attr_names,
+ this->type.type);
+ *offset = 0;
+ return FAILED;
+ }
+ reader = bio_reader_create(this->value);
+ reader->read_uint8 (reader, &flags);
+ reader->read_uint24(reader, &this->base_attr_id);
+ reader->destroy(reader);
+
+ this->cancel_flag = (flags & NEXT_SEG_FLAG_CANCEL);
+
+ return SUCCESS;
+}
+
+METHOD(pa_tnc_attr_t, destroy, void,
+ private_tcg_seg_attr_next_seg_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ free(this->value.ptr);
+ free(this);
+ }
+}
+
+METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
+ private_tcg_seg_attr_next_seg_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.pa_tnc_attribute;
+}
+
+METHOD(tcg_seg_attr_next_seg_t, get_base_attr_id, uint32_t,
+ private_tcg_seg_attr_next_seg_t *this)
+{
+ return this->base_attr_id;
+}
+
+METHOD(tcg_seg_attr_next_seg_t, get_cancel_flag, bool,
+ private_tcg_seg_attr_next_seg_t *this)
+{
+ return this->cancel_flag;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t* tcg_seg_attr_next_seg_create(uint32_t base_attr_id, bool cancel)
+{
+ private_tcg_seg_attr_next_seg_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_base_attr_id = _get_base_attr_id,
+ .get_cancel_flag = _get_cancel_flag,
+ },
+ .type = { PEN_TCG, TCG_SEG_NEXT_SEG_REQ },
+ .base_attr_id = base_attr_id,
+ .cancel_flag = cancel,
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *tcg_seg_attr_next_seg_create_from_data(chunk_t data)
+{
+ private_tcg_seg_attr_next_seg_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_base_attr_id = _get_base_attr_id,
+ .get_cancel_flag = _get_cancel_flag,
+ },
+ .type = { PEN_TCG, TCG_SEG_NEXT_SEG_REQ },
+ .value = chunk_clone(data),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
diff --git a/src/libpts/tcg/seg/tcg_seg_attr_next_seg.h b/src/libpts/tcg/seg/tcg_seg_attr_next_seg.h
new file mode 100644
index 000000000..c9f53f853
--- /dev/null
+++ b/src/libpts/tcg/seg/tcg_seg_attr_next_seg.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup tcg_seg_attr_next_seg tcg_seg_attr_next_seg
+ * @{ @ingroup tcg_attr
+ */
+
+#ifndef TCG_SEG_ATTR_NEXT_SEG_H_
+#define TCG_SEG_ATTR_NEXT_SEG_H_
+
+typedef struct tcg_seg_attr_next_seg_t tcg_seg_attr_next_seg_t;
+
+#include "tcg/tcg_attr.h"
+
+#define TCG_SEG_ATTR_NEXT_SEG_SIZE 4
+
+/**
+ * Class implementing the TCG Segmentation Next Segment Attribute
+ */
+struct tcg_seg_attr_next_seg_t {
+
+ /**
+ * Public PA-TNC attribute interface
+ */
+ pa_tnc_attr_t pa_tnc_attribute;
+
+ /**
+ * Get Base Attribute ID
+ *
+ * @return Base Attribute ID
+ */
+ uint32_t (*get_base_attr_id)(tcg_seg_attr_next_seg_t *this);
+
+ /**
+ * Get the Cancel flag
+ *
+ * @return Cancel flag
+ */
+ bool (*get_cancel_flag)(tcg_seg_attr_next_seg_t *this);
+
+};
+
+/**
+ * Creates an tcg_seg_attr_next_seg_t object
+ *
+ * @param base_attr_id Base Attribute ID
+ * @param cancel If TRUE set Cancel flag
+ */
+pa_tnc_attr_t* tcg_seg_attr_next_seg_create(uint32_t base_attr_id, bool cancel);
+
+/**
+ * Creates an tcg_seg_attr_next_seg_t object from received data
+ *
+ * @param value unparsed attribute value
+ */
+pa_tnc_attr_t* tcg_seg_attr_next_seg_create_from_data(chunk_t value);
+
+#endif /** TCG_SEG_ATTR_NEXT_SEG_H_ @}*/
diff --git a/src/libpts/tcg/seg/tcg_seg_attr_seg_env.c b/src/libpts/tcg/seg/tcg_seg_attr_seg_env.c
new file mode 100644
index 000000000..833111f8f
--- /dev/null
+++ b/src/libpts/tcg/seg/tcg_seg_attr_seg_env.c
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tcg_seg_attr_seg_env.h"
+
+#include <pa_tnc/pa_tnc_msg.h>
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <utils/debug.h>
+
+typedef struct private_tcg_seg_attr_seg_env_t private_tcg_seg_attr_seg_env_t;
+
+/**
+ * Attribute Segment Envelope
+ * see TCG IF-M Segmentation Specification
+ *
+ * 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |M|S| Reserved | Base Attribute ID |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Segment Value (Variable Length) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+/**
+ * Private data of an tcg_seg_attr_seg_env_t object.
+ */
+struct private_tcg_seg_attr_seg_env_t {
+
+ /**
+ * Public members of tcg_seg_attr_seg_env_t
+ */
+ tcg_seg_attr_seg_env_t public;
+
+ /**
+ * Vendor-specific attribute type
+ */
+ pen_type_t type;
+
+ /**
+ * Attribute value
+ */
+ chunk_t value;
+
+ /**
+ * Noskip flag
+ */
+ bool noskip_flag;
+
+ /**
+ * PA-TNC segmentation flags
+ */
+ uint8_t flags;
+
+ /**
+ * Base Attribute ID
+ */
+ uint32_t base_attr_id;
+
+ /**
+ * Attribute value
+ */
+ chunk_t segment;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+};
+
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
+ private_tcg_seg_attr_seg_env_t *this)
+{
+ return this->type;
+}
+
+METHOD(pa_tnc_attr_t, get_value, chunk_t,
+ private_tcg_seg_attr_seg_env_t *this)
+{
+ return this->value;
+}
+
+METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
+ private_tcg_seg_attr_seg_env_t *this)
+{
+ return this->noskip_flag;
+}
+
+METHOD(pa_tnc_attr_t, set_noskip_flag,void,
+ private_tcg_seg_attr_seg_env_t *this, bool noskip)
+{
+ this->noskip_flag = noskip;
+}
+
+METHOD(pa_tnc_attr_t, build, void,
+ private_tcg_seg_attr_seg_env_t *this)
+{
+ /* constructor already allocated and built value */
+ return;
+}
+
+METHOD(pa_tnc_attr_t, process, status_t,
+ private_tcg_seg_attr_seg_env_t *this, u_int32_t *offset)
+{
+ bio_reader_t *reader;
+
+ if (this->value.len < TCG_SEG_ATTR_SEG_ENV_HEADER)
+ {
+ DBG1(DBG_TNC, "insufficient data for %N", tcg_attr_names,
+ this->type.type);
+ *offset = 0;
+ return FAILED;
+ }
+ reader = bio_reader_create(this->value);
+ reader->read_uint8 (reader, &this->flags);
+ reader->read_uint24(reader, &this->base_attr_id);
+ reader->destroy(reader);
+
+ return SUCCESS;
+}
+
+METHOD(pa_tnc_attr_t, destroy, void,
+ private_tcg_seg_attr_seg_env_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ free(this->value.ptr);
+ free(this);
+ }
+}
+
+METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
+ private_tcg_seg_attr_seg_env_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.pa_tnc_attribute;
+}
+
+METHOD(tcg_seg_attr_seg_env_t, get_segment, chunk_t,
+ private_tcg_seg_attr_seg_env_t *this, uint8_t *flags)
+{
+ if (flags)
+ {
+ *flags = this->flags;
+ }
+ return chunk_skip(this->value, TCG_SEG_ATTR_SEG_ENV_HEADER);
+}
+
+METHOD(tcg_seg_attr_seg_env_t, get_base_attr_id, uint32_t,
+ private_tcg_seg_attr_seg_env_t *this)
+{
+ return this->base_attr_id;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t* tcg_seg_attr_seg_env_create(chunk_t segment, uint8_t flags,
+ uint32_t base_attr_id)
+{
+ private_tcg_seg_attr_seg_env_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_base_attr_id = _get_base_attr_id,
+ .get_segment = _get_segment,
+ },
+ .type = { PEN_TCG, TCG_SEG_ATTR_SEG_ENV },
+ .flags = flags,
+ .base_attr_id = base_attr_id,
+ .value = chunk_alloc(TCG_SEG_ATTR_SEG_ENV_HEADER + segment.len),
+ .ref = 1,
+ );
+
+ htoun32(this->value.ptr, base_attr_id);
+ *this->value.ptr = flags;
+ memcpy(this->value.ptr + TCG_SEG_ATTR_SEG_ENV_HEADER,
+ segment.ptr, segment.len);
+
+ return &this->public.pa_tnc_attribute;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *tcg_seg_attr_seg_env_create_from_data(chunk_t data)
+{
+ private_tcg_seg_attr_seg_env_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_base_attr_id = _get_base_attr_id,
+ .get_segment = _get_segment,
+ },
+ .type = { PEN_TCG, TCG_SEG_ATTR_SEG_ENV },
+ .value = chunk_clone(data),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
diff --git a/src/libpts/tcg/seg/tcg_seg_attr_seg_env.h b/src/libpts/tcg/seg/tcg_seg_attr_seg_env.h
index 84cac8c36..19184392b 100644
--- a/src/libpts/tcg/seg/tcg_seg_attr_seg_env.h
+++ b/src/libpts/tcg/seg/tcg_seg_attr_seg_env.h
@@ -37,22 +37,37 @@ struct tcg_seg_attr_seg_env_t {
*/
pa_tnc_attr_t pa_tnc_attribute;
+ /**
+ * Get enveloped attribute segment
+ *
+ * @param flags Segmentation flags
+ * @return Segment
+ */
+ chunk_t (*get_segment)(tcg_seg_attr_seg_env_t *this, uint8_t *flags);
+
+ /**
+ * Get Base Attribute ID
+ *
+ * @return Base Attribute ID
+ */
+ uint32_t (*get_base_attr_id)(tcg_seg_attr_seg_env_t *this);
+
};
/**
* Creates an tcg_seg_attr_seg_env_t object
*
- * @param max_attr_size Maximum IF-M attribute size in octets
- * @param max_seg_size Maximum IF-M attribute segment size in octets
- * @param request TRUE for a request, FALSE for a response
+ * @param segment Attribute segment
+ * @param flags Segmentation flags
+ * @param base_attr_id Base Attribute ID
*/
-pa_tnc_attr_t* tcg_seg_attr_seg_env_create(chunk_t segment, uint8_t flags);
+pa_tnc_attr_t* tcg_seg_attr_seg_env_create(chunk_t segment, uint8_t flags,
+ uint32_t base_attr_id);
/**
* Creates an tcg_seg_attr_seg_env_t object from received data
*
* @param value unparsed attribute value
- * @param request TRUE for a request, FALSE for a response
*/
pa_tnc_attr_t* tcg_seg_attr_seg_env_create_from_data(chunk_t value);
diff --git a/src/libpts/tcg/tcg_attr.c b/src/libpts/tcg/tcg_attr.c
index 064b0ebc9..d4ae1da67 100644
--- a/src/libpts/tcg/tcg_attr.c
+++ b/src/libpts/tcg/tcg_attr.c
@@ -35,6 +35,8 @@
#include "tcg/swid/tcg_swid_attr_tag_id_inv.h"
#include "tcg/swid/tcg_swid_attr_tag_inv.h"
#include "tcg/seg/tcg_seg_attr_max_size.h"
+#include "tcg/seg/tcg_seg_attr_seg_env.h"
+#include "tcg/seg/tcg_seg_attr_next_seg.h"
ENUM_BEGIN(tcg_attr_names, TCG_SCAP_REFERENCES,
TCG_SCAP_SUMMARY_RESULTS,
@@ -195,6 +197,10 @@ pa_tnc_attr_t* tcg_attr_create_from_data(u_int32_t type, chunk_t value)
return tcg_seg_attr_max_size_create_from_data(value, TRUE);
case TCG_SEG_MAX_ATTR_SIZE_RESP:
return tcg_seg_attr_max_size_create_from_data(value, FALSE);
+ case TCG_SEG_ATTR_SEG_ENV:
+ return tcg_seg_attr_seg_env_create_from_data(value);
+ case TCG_SEG_NEXT_SEG_REQ:
+ return tcg_seg_attr_next_seg_create_from_data(value);
case TCG_PTS_REQ_PROTO_CAPS:
return tcg_pts_attr_proto_caps_create_from_data(value, TRUE);
case TCG_PTS_PROTO_CAPS: