From 863f59c560dd2fc921f76eec2050003a1b6c6791 Mon Sep 17 00:00:00 2001 From: Andreas Steffen Date: Wed, 7 Sep 2011 00:48:25 +0200 Subject: [PATCH] get platform info from IMC --- src/libimcv/Makefile.am | 1 + src/libimcv/ietf/ietf_attr_product_info.c | 237 ++++++++++++++++++ src/libimcv/ietf/ietf_attr_product_info.h | 67 +++++ src/libimcv/pa_tnc/pa_tnc_attr.c | 4 +- .../plugins/imc_attestation/imc_attestation.c | 33 ++- src/libimcv/plugins/imv_attestation/data.sql | 4 +- .../plugins/imv_attestation/imv_attestation.c | 103 ++++---- src/libimcv/tcg/pts/pts.c | 77 +++++- 8 files changed, 473 insertions(+), 53 deletions(-) create mode 100644 src/libimcv/ietf/ietf_attr_product_info.c create mode 100644 src/libimcv/ietf/ietf_attr_product_info.h diff --git a/src/libimcv/Makefile.am b/src/libimcv/Makefile.am index dcb341305..3e040d7a3 100644 --- a/src/libimcv/Makefile.am +++ b/src/libimcv/Makefile.am @@ -12,6 +12,7 @@ libimcv_la_SOURCES = \ ietf/ietf_attr.h ietf/ietf_attr.c \ ietf/ietf_attr_pa_tnc_error.h ietf/ietf_attr_pa_tnc_error.c \ ietf/ietf_attr_port_filter.h ietf/ietf_attr_port_filter.c \ + ietf/ietf_attr_product_info.h ietf/ietf_attr_product_info.c \ ita/ita_attr.h ita/ita_attr.c \ ita/ita_attr_command.h ita/ita_attr_command.c \ pa_tnc/pa_tnc_msg.h pa_tnc/pa_tnc_msg.c \ diff --git a/src/libimcv/ietf/ietf_attr_product_info.c b/src/libimcv/ietf/ietf_attr_product_info.c new file mode 100644 index 000000000..222fef0bf --- /dev/null +++ b/src/libimcv/ietf/ietf_attr_product_info.c @@ -0,0 +1,237 @@ +/* + * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * 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 "ietf_attr_product_info.h" + +#include +#include +#include +#include + +typedef struct private_ietf_attr_product_info_t private_ietf_attr_product_info_t; + +/** + * PA-TNC Product Information type (see section 4.2.2 of RFC 5792) + * + * 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 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Product Vendor ID | Product ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Product ID | Product Name (Variable Length) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define PRODUCT_INFO_MIN_SIZE 5 + +/** + * Private data of an ietf_attr_product_info_t object. + */ +struct private_ietf_attr_product_info_t { + + /** + * Public members of ietf_attr_product_info_t + */ + ietf_attr_product_info_t public; + + /** + * Attribute vendor ID + */ + pen_t vendor_id; + + /** + * Attribute type + */ + u_int32_t type; + + /** + * Attribute value + */ + chunk_t value; + + /** + * Noskip flag + */ + bool noskip_flag; + + /** + * Product vendor ID + */ + pen_t product_vendor_id; + + /** + * Product ID + */ + u_int16_t product_id; + + /** + * Product Name + */ + char *product_name; + +}; + +METHOD(pa_tnc_attr_t, get_vendor_id, pen_t, + private_ietf_attr_product_info_t *this) +{ + return this->vendor_id; +} + +METHOD(pa_tnc_attr_t, get_type, u_int32_t, + private_ietf_attr_product_info_t *this) +{ + return this->type; +} + +METHOD(pa_tnc_attr_t, get_value, chunk_t, + private_ietf_attr_product_info_t *this) +{ + return this->value; +} + +METHOD(pa_tnc_attr_t, get_noskip_flag, bool, + private_ietf_attr_product_info_t *this) +{ + return this->noskip_flag; +} + +METHOD(pa_tnc_attr_t, set_noskip_flag,void, + private_ietf_attr_product_info_t *this, bool noskip) +{ + this->noskip_flag = noskip; +} + +METHOD(pa_tnc_attr_t, build, void, + private_ietf_attr_product_info_t *this) +{ + bio_writer_t *writer; + chunk_t product_name; + + product_name = chunk_create(this->product_name, strlen(this->product_name)); + + writer = bio_writer_create(PRODUCT_INFO_MIN_SIZE); + writer->write_uint24(writer, this->product_vendor_id); + writer->write_uint16(writer, this->product_id); + writer->write_data (writer, product_name); + + this->value = chunk_clone(writer->get_buf(writer)); + writer->destroy(writer); +} + +METHOD(pa_tnc_attr_t, process, status_t, + private_ietf_attr_product_info_t *this, u_int32_t *offset) +{ + bio_reader_t *reader; + chunk_t product_name; + + if (this->value.len < PRODUCT_INFO_MIN_SIZE) + { + DBG1(DBG_TNC, "insufficient data for IETF product information"); + *offset = 0; + return FAILED; + } + reader = bio_reader_create(this->value); + reader->read_uint24(reader, &this->product_vendor_id); + reader->read_uint16(reader, &this->product_id); + reader->read_data (reader, reader->remaining(reader), &product_name); + reader->destroy(reader); + + this->product_name = malloc(product_name.len + 1); + memcpy(this->product_name, product_name.ptr, product_name.len); + this->product_name[product_name.len] = '\0'; + + return SUCCESS; +} + +METHOD(pa_tnc_attr_t, destroy, void, + private_ietf_attr_product_info_t *this) +{ + free(this->product_name); + free(this->value.ptr); + free(this); +} + +METHOD(ietf_attr_product_info_t, get_info, char*, + private_ietf_attr_product_info_t *this, pen_t *vendor_id, u_int16_t *id) +{ + if (vendor_id) + { + *vendor_id = this->product_vendor_id; + } + if (id) + { + *id = this->product_id; + } + return this->product_name; +} + +/** + * Described in header. + */ +pa_tnc_attr_t *ietf_attr_product_info_create(pen_t vendor_id, u_int16_t id, + char *name) +{ + private_ietf_attr_product_info_t *this; + + INIT(this, + .public = { + .pa_tnc_attribute = { + .get_vendor_id = _get_vendor_id, + .get_type = _get_type, + .get_value = _get_value, + .get_noskip_flag = _get_noskip_flag, + .set_noskip_flag = _set_noskip_flag, + .build = _build, + .process = _process, + .destroy = _destroy, + }, + .get_info = _get_info, + }, + .vendor_id = PEN_IETF, + .type = IETF_ATTR_PRODUCT_INFORMATION, + .product_vendor_id = vendor_id, + .product_id = id, + .product_name = strdup(name), + ); + + return &this->public.pa_tnc_attribute; +} + +/** + * Described in header. + */ +pa_tnc_attr_t *ietf_attr_product_info_create_from_data(chunk_t data) +{ + private_ietf_attr_product_info_t *this; + + INIT(this, + .public = { + .pa_tnc_attribute = { + .get_vendor_id = _get_vendor_id, + .get_type = _get_type, + .get_value = _get_value, + .build = _build, + .process = _process, + .destroy = _destroy, + }, + .get_info = _get_info, + }, + .vendor_id = PEN_IETF, + .type = IETF_ATTR_PRODUCT_INFORMATION, + .value = chunk_clone(data), + ); + + return &this->public.pa_tnc_attribute; +} + diff --git a/src/libimcv/ietf/ietf_attr_product_info.h b/src/libimcv/ietf/ietf_attr_product_info.h new file mode 100644 index 000000000..f1dfc3e83 --- /dev/null +++ b/src/libimcv/ietf/ietf_attr_product_info.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2011 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * 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 ietf_attr_product_infot ietf_attr_product_info + * @{ @ingroup ietf + */ + +#ifndef IETF_ATTR_PRODUCT_INFO_H_ +#define IETF_ATTR_PRODUCT_INFO_H_ + +typedef struct ietf_attr_product_info_t ietf_attr_product_info_t; + +#include "ietf_attr.h" +#include "pa_tnc/pa_tnc_attr.h" + + +/** + * Class implementing the IETF PA-TNC Product Information attribute. + * + */ +struct ietf_attr_product_info_t { + + /** + * Public PA-TNC attribute interface + */ + pa_tnc_attr_t pa_tnc_attribute; + + /** + * Gets all product info + * + * @param vendor_id Product vendor ID + * @param id Product ID + * @return Product Name + */ + char* (*get_info)(ietf_attr_product_info_t *this, + pen_t *vendor_id, u_int16_t *id); + +}; + +/** + * Creates an ietf_attr_product_info_t object + * + */ +pa_tnc_attr_t* ietf_attr_product_info_create(pen_t vendor_id, u_int16_t id, + char *name); + +/** + * Creates an ietf_attr_product_info_t object from received data + * + * @param value unparsed attribute value + */ +pa_tnc_attr_t* ietf_attr_product_info_create_from_data(chunk_t value); + +#endif /** IETF_ATTR_PRODUCT_INFO_H_ @}*/ diff --git a/src/libimcv/pa_tnc/pa_tnc_attr.c b/src/libimcv/pa_tnc/pa_tnc_attr.c index 1a1ea0762..9efbfba47 100644 --- a/src/libimcv/pa_tnc/pa_tnc_attr.c +++ b/src/libimcv/pa_tnc/pa_tnc_attr.c @@ -17,6 +17,7 @@ #include "ietf/ietf_attr.h" #include "ietf/ietf_attr_pa_tnc_error.h" #include "ietf/ietf_attr_port_filter.h" +#include "ietf/ietf_attr_product_info.h" #include "tcg/tcg_attr.h" #include "tcg/tcg_pts_attr_proto_caps.h" #include "tcg/tcg_pts_attr_meas_algo.h" @@ -48,9 +49,10 @@ pa_tnc_attr_t* pa_tnc_attr_create_from_data(pen_t vendor_id, u_int32_t type, return ietf_attr_port_filter_create_from_data(value); case IETF_ATTR_PA_TNC_ERROR: return ietf_attr_pa_tnc_error_create_from_data(value); + case IETF_ATTR_PRODUCT_INFORMATION: + return ietf_attr_product_info_create_from_data(value); case IETF_ATTR_TESTING: case IETF_ATTR_ATTRIBUTE_REQUEST: - case IETF_ATTR_PRODUCT_INFORMATION: case IETF_ATTR_NUMERIC_VERSION: case IETF_ATTR_STRING_VERSION: case IETF_ATTR_OPERATIONAL_STATUS: diff --git a/src/libimcv/plugins/imc_attestation/imc_attestation.c b/src/libimcv/plugins/imc_attestation/imc_attestation.c index 19116318d..9b60bc07c 100644 --- a/src/libimcv/plugins/imc_attestation/imc_attestation.c +++ b/src/libimcv/plugins/imc_attestation/imc_attestation.c @@ -19,6 +19,7 @@ #include #include #include +#include #include @@ -121,12 +122,42 @@ TNC_Result TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id, TNC_Result TNC_IMC_BeginHandshake(TNC_IMCID imc_id, TNC_ConnectionID connection_id) { + imc_state_t *state; + imc_attestation_state_t *attestation_state; + pts_t *pts; + char *platform_info; + TNC_Result result = TNC_RESULT_SUCCESS; + if (!imc_attestation) { DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name); return TNC_RESULT_NOT_INITIALIZED; } - return TNC_RESULT_SUCCESS; + + /* get current IMC state */ + if (!imc_attestation->get_state(imc_attestation, connection_id, &state)) + { + return TNC_RESULT_FATAL; + } + attestation_state = (imc_attestation_state_t*)state; + pts = attestation_state->get_pts(attestation_state); + + platform_info = pts->get_platform_info(pts); + if (platform_info) + { + pa_tnc_msg_t *pa_tnc_msg; + pa_tnc_attr_t *attr; + + pa_tnc_msg = pa_tnc_msg_create(); + attr = ietf_attr_product_info_create(0, 0, platform_info); + pa_tnc_msg->add_attribute(pa_tnc_msg, attr); + pa_tnc_msg->build(pa_tnc_msg); + result = imc_attestation->send_message(imc_attestation, connection_id, + pa_tnc_msg->get_encoding(pa_tnc_msg)); + pa_tnc_msg->destroy(pa_tnc_msg); + } + + return result; } /** diff --git a/src/libimcv/plugins/imv_attestation/data.sql b/src/libimcv/plugins/imv_attestation/data.sql index e16e0bf02..cfa919244 100644 --- a/src/libimcv/plugins/imv_attestation/data.sql +++ b/src/libimcv/plugins/imv_attestation/data.sql @@ -3,13 +3,13 @@ INSERT INTO products ( name ) VALUES ( - 'Ubuntu 11.4 i686' + 'Ubuntu 11.04 i686' ); INSERT INTO products ( name ) VALUES ( - 'Ubuntu 11.4 x86_64' + 'Ubuntu 11.04 x86_64' ); INSERT INTO products ( diff --git a/src/libimcv/plugins/imv_attestation/imv_attestation.c b/src/libimcv/plugins/imv_attestation/imv_attestation.c index a559e219b..7e1230e29 100644 --- a/src/libimcv/plugins/imv_attestation/imv_attestation.c +++ b/src/libimcv/plugins/imv_attestation/imv_attestation.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -220,6 +221,9 @@ static TNC_Result send_message(TNC_ConnectionID connection_id) attr = tcg_pts_attr_meas_algo_create(supported_algorithms, FALSE); attr->set_noskip_flag(attr, TRUE); msg->add_attribute(msg, attr); + + attestation_state->set_handshake_state(attestation_state, + IMV_ATTESTATION_STATE_MEAS); break; } @@ -278,6 +282,9 @@ static TNC_Result send_message(TNC_ConnectionID connection_id) requested_files->insert_last(requested_files, (void*)id); } enumerator->destroy(enumerator); + + attestation_state->set_handshake_state(attestation_state, + IMV_ATTESTATION_STATE_END); break; } case IMV_ATTESTATION_STATE_COMP_EVID: @@ -347,46 +354,60 @@ TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id, enumerator = pa_tnc_msg->create_attribute_enumerator(pa_tnc_msg); while (enumerator->enumerate(enumerator, &attr)) { - if (attr->get_vendor_id(attr) == PEN_IETF && - attr->get_type(attr) == IETF_ATTR_PA_TNC_ERROR) + if (attr->get_vendor_id(attr) == PEN_IETF) { - ietf_attr_pa_tnc_error_t *error_attr; - pen_t error_vendor_id; - pa_tnc_error_code_t error_code; - chunk_t msg_info, attr_info; - u_int32_t offset; - - error_attr = (ietf_attr_pa_tnc_error_t*)attr; - error_vendor_id = error_attr->get_vendor_id(error_attr); - error_code = error_attr->get_error_code(error_attr); - msg_info = error_attr->get_msg_info(error_attr); - - if (error_vendor_id == PEN_IETF) + if (attr->get_type(attr) == IETF_ATTR_PA_TNC_ERROR) { - DBG1(DBG_IMV, "received PA-TNC error '%N' concerning message %#B", - pa_tnc_error_code_names, error_code, &msg_info); + ietf_attr_pa_tnc_error_t *error_attr; + pen_t error_vendor_id; + pa_tnc_error_code_t error_code; + chunk_t msg_info, attr_info; + u_int32_t offset; - switch (error_code) + error_attr = (ietf_attr_pa_tnc_error_t*)attr; + error_vendor_id = error_attr->get_vendor_id(error_attr); + error_code = error_attr->get_error_code(error_attr); + msg_info = error_attr->get_msg_info(error_attr); + + if (error_vendor_id == PEN_IETF) { - case PA_ERROR_INVALID_PARAMETER: - offset = error_attr->get_offset(error_attr); - DBG1(DBG_IMV, " occurred at offset of %u bytes", offset); - break; - case PA_ERROR_ATTR_TYPE_NOT_SUPPORTED: - attr_info = error_attr->get_attr_info(error_attr); - DBG1(DBG_IMV, " unsupported attribute %#B", &attr_info); - break; - default: - break; + DBG1(DBG_IMV, "received PA-TNC error '%N' " + "concerning message %#B", + pa_tnc_error_code_names, error_code, &msg_info); + + switch (error_code) + { + case PA_ERROR_INVALID_PARAMETER: + offset = error_attr->get_offset(error_attr); + DBG1(DBG_IMV, " occurred at offset of %u bytes", + offset); + break; + case PA_ERROR_ATTR_TYPE_NOT_SUPPORTED: + attr_info = error_attr->get_attr_info(error_attr); + DBG1(DBG_IMV, " unsupported attribute %#B", + &attr_info); + break; + default: + break; + } } + else if (error_vendor_id == PEN_TCG) + { + DBG1(DBG_IMV, "received TCG-PTS error '%N'", + pts_error_code_names, error_code); + DBG1(DBG_IMV, "error information: %B", &msg_info); + } + fatal_error = TRUE; } - else if (error_vendor_id == PEN_TCG) + else if (attr->get_type(attr) == IETF_ATTR_PRODUCT_INFORMATION) { - DBG1(DBG_IMV, "received TCG-PTS error '%N'", - pts_error_code_names, error_code); - DBG1(DBG_IMV, "error information: %B", &msg_info); + ietf_attr_product_info_t *attr_cast; + char *platform_info; + + attr_cast = (ietf_attr_product_info_t*)attr; + platform_info = attr_cast->get_info(attr_cast, NULL, NULL); + pts->set_platform_info(pts, platform_info); } - fatal_error = TRUE; } else if (attr->get_vendor_id(attr) == PEN_TCG) { @@ -400,9 +421,6 @@ TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id, attr_cast = (tcg_pts_attr_proto_caps_t*)attr; flags = attr_cast->get_flags(attr_cast); pts->set_proto_caps(pts, flags); - - attestation_state->set_handshake_state(attestation_state, - IMV_ATTESTATION_STATE_MEAS); break; } case TCG_PTS_MEAS_ALGO_SELECTION: @@ -413,9 +431,6 @@ TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id, attr_cast = (tcg_pts_attr_meas_algo_t*)attr; selected_algorithm = attr_cast->get_algorithms(attr_cast); pts->set_meas_algorithm(pts, selected_algorithm); - - attestation_state->set_handshake_state(attestation_state, - IMV_ATTESTATION_STATE_MEAS); break; } case TCG_PTS_TPM_VERSION_INFO: @@ -426,9 +441,6 @@ TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id, attr_cast = (tcg_pts_attr_tpm_version_info_t*)attr; tpm_version_info = attr_cast->get_tpm_version_info(attr_cast); pts->set_tpm_version_info(pts, tpm_version_info); - - attestation_state->set_handshake_state(attestation_state, - IMV_ATTESTATION_STATE_END); break; } case TCG_PTS_AIK: @@ -444,8 +456,6 @@ TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id, break; } pts->set_aik(pts, aik); - attestation_state->set_handshake_state(attestation_state, - IMV_ATTESTATION_STATE_END); break; } @@ -543,19 +553,18 @@ TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id, if (is_directory) { files_in_dir_with_meas->remove(files_in_dir_with_meas, - filename, (bool (*)(void*,void*))strcmp); + filename, (bool (*)(void*,void*))strcmp); } e->destroy(e); } - if(is_directory && !files_in_dir_with_meas->get_count(files_in_dir_with_meas)) + if (is_directory && + !files_in_dir_with_meas->get_count(files_in_dir_with_meas)) { requested_files->remove(requested_files, (void*)request_id, NULL); } e_meas->destroy(e_meas); - attestation_state->set_handshake_state(attestation_state, - IMV_ATTESTATION_STATE_END); break; } diff --git a/src/libimcv/tcg/pts/pts.c b/src/libimcv/tcg/pts/pts.c index b774ede38..1c226afd5 100644 --- a/src/libimcv/tcg/pts/pts.c +++ b/src/libimcv/tcg/pts/pts.c @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -122,12 +123,12 @@ static void print_tpm_version_info(private_pts_t *this) this->tpm_version_info.ptr, &versionInfo); if (result != TSS_SUCCESS) { - DBG1(DBG_IMC, "could not parse tpm version info: tss error 0x%x", + DBG1(DBG_TNC, "could not parse tpm version info: tss error 0x%x", result); } else { - DBG2(DBG_IMC, "TPM 1.2 Version Info: Chip Version: %hhu.%hhu.%hhu.%hhu," + DBG2(DBG_TNC, "TPM 1.2 Version Info: Chip Version: %hhu.%hhu.%hhu.%hhu," " Spec Level: %hu, Errata Rev: %hhu, Vendor ID: %.4s", versionInfo.version.major, versionInfo.version.minor, versionInfo.version.revMajor, versionInfo.version.revMinor, @@ -354,6 +355,76 @@ METHOD(pts_t, destroy, void, free(this); } +/** + * Determine Linux distribution and hardware platform + */ +char* extract_platform_info(void) +{ + FILE *file; + const char description[] = "Description:"; + char buf[BUF_LEN], *pos, *value; + int value_len; + + /* Open a pipe stream for reading the output of the lsb_release commmand */ + file = popen("/usr/bin/lsb_release -d" , "r"); + if (!file) + { + DBG1(DBG_IMC, "Failed to run lsb_release command"); + return NULL; + } + + /* Read the output the lsb_release command */ + if (!fgets(buf, BUF_LEN-1, file)) + { + DBG1(DBG_IMC, "Failed to read output of lsb_release command"); + pclose(file); + return NULL; + } + pclose(file); + + pos = strstr(buf, description); + if (!pos) + { + DBG1(DBG_IMC, "Failed to find lsb_release description field"); + return NULL; + } + value = pos + strlen(description); + + /* eat whitespace */ + while (*value == ' ' || *value == '\t') + { + value++; + } + + /* remove newline at the end and move value to the front of the buffer */ + value_len = strlen(value) - 1; + memcpy(buf, value, value_len); + buf[value_len] = ' '; + + /* Open a pipe stream for reading the output of the uname commmand */ + file = popen("/bin/uname -p" , "r"); + if (!file) + { + DBG1(DBG_IMC, "Failed to run uname command"); + return NULL; + } + + /* Read the output the uname command */ + if (!fgets(buf + value_len + 1, BUF_LEN - value_len - 2, file)) + { + DBG1(DBG_IMC, "Failed to read output of uname command"); + pclose(file); + return NULL; + } + pclose(file); + + /* remove newline at the end */ + buf[strlen(buf)-1] = '\0'; + + DBG1(DBG_IMV, "platform is '%s'", buf); + return strdup(buf); +} + /** * Check for a TPM by querying for TPM Version Info */ @@ -421,6 +492,8 @@ pts_t *pts_create(bool is_imc) if (is_imc) { + this->platform_info = extract_platform_info(); + if (has_tpm(this)) { this->has_tpm = TRUE;