From d2f49c3dc4228e2fc628b668ec631164d46d064a Mon Sep 17 00:00:00 2001 From: Andreas Steffen Date: Thu, 1 Sep 2011 15:42:35 +0200 Subject: [PATCH] finished refactoring of file measurements --- src/libimcv/Makefile.am | 1 + .../plugins/imc_attestation/imc_attestation.c | 88 ++----- .../plugins/imv_attestation/imv_attestation.c | 223 ++++++++-------- .../imv_attestation/imv_attestation_state.c | 8 + src/libimcv/tcg/pts/pts.c | 242 +++++++++++------- src/libimcv/tcg/pts/pts.h | 48 ++-- src/libimcv/tcg/pts/pts_file_meas.c | 137 ++++++++++ src/libimcv/tcg/pts/pts_file_meas.h | 76 ++++++ src/libimcv/tcg/tcg_pts_attr_file_meas.c | 222 ++++++---------- src/libimcv/tcg/tcg_pts_attr_file_meas.h | 71 +---- 10 files changed, 613 insertions(+), 503 deletions(-) create mode 100644 src/libimcv/tcg/pts/pts_file_meas.c create mode 100644 src/libimcv/tcg/pts/pts_file_meas.h diff --git a/src/libimcv/Makefile.am b/src/libimcv/Makefile.am index 133e82462..12bb2ef11 100644 --- a/src/libimcv/Makefile.am +++ b/src/libimcv/Makefile.am @@ -33,6 +33,7 @@ libimcv_la_SOURCES = \ tcg/pts/pts_error.h tcg/pts/pts_error.c \ tcg/pts/pts_proto_caps.h tcg/pts/pts_funct_comp_name.h \ tcg/pts/pts_database.h tcg/pts/pts_database.c \ + tcg/pts/pts_file_meas.h tcg/pts/pts_file_meas.c \ tcg/pts/pts_meas_algo.h tcg/pts/pts_meas_algo.c # CFLAGS = -Wall -Werror diff --git a/src/libimcv/plugins/imc_attestation/imc_attestation.c b/src/libimcv/plugins/imc_attestation/imc_attestation.c index 937a7ecc0..cc91bcf4f 100644 --- a/src/libimcv/plugins/imc_attestation/imc_attestation.c +++ b/src/libimcv/plugins/imc_attestation/imc_attestation.c @@ -292,9 +292,8 @@ TNC_Result TNC_IMC_ReceiveMessage(TNC_IMCID imc_id, } /* Send AIK attribute */ - attr_to_send = tcg_pts_attr_aik_create(is_naked_key, aik); - attr_to_send = (pa_tnc_attr_t*)attr_to_send; - attr_list->insert_last(attr_list,attr_to_send); + attr = tcg_pts_attr_aik_create(is_naked_key, aik); + attr_list->insert_last(attr_list, attr); break; } @@ -306,80 +305,29 @@ TNC_Result TNC_IMC_ReceiveMessage(TNC_IMCID imc_id, case TCG_PTS_REQ_FILE_MEAS: { tcg_pts_attr_req_file_meas_t *attr_cast; - tcg_pts_attr_file_meas_t *attr_out; char *pathname; - u_int16_t request_id, meas_len; - pts_meas_algorithms_t selected_algorithm; - chunk_t file_hash; - bool directory_flag; - linked_list_t *file_measurements; + u_int16_t request_id; + bool is_directory; + pts_file_meas_t *measurements; attr_cast = (tcg_pts_attr_req_file_meas_t*)attr; - directory_flag = attr_cast->get_directory_flag(attr_cast); + is_directory = attr_cast->get_directory_flag(attr_cast); request_id = attr_cast->get_request_id(attr_cast); pathname = attr_cast->get_pathname(attr_cast); - - DBG2(DBG_IMC, "%s to be measured: '%s'", - directory_flag ? "directory" : "file", pathname); - - /* Send File Measurement attribute */ - selected_algorithm = pts->get_meas_algorithm(pts); - meas_len = HASH_SIZE_SHA1; - if(selected_algorithm & PTS_MEAS_ALGO_SHA384) - { - meas_len = HASH_SIZE_SHA384; - } - else if (selected_algorithm & PTS_MEAS_ALGO_SHA256) - { - meas_len = HASH_SIZE_SHA256; - } - /** - * Hash the file or directory and add them as attribute - */ - - attr = directory_flag ? - tcg_pts_attr_file_meas_create(0, request_id, meas_len) : - tcg_pts_attr_file_meas_create(1, request_id, meas_len); + /* 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->do_measurements(pts, request_id, + pathname, is_directory); + if (!measurements) + { + /* TODO handle error codes from measurements */ + return TNC_RESULT_FATAL; + } + attr = tcg_pts_attr_file_meas_create(measurements); attr->set_noskip_flag(attr, TRUE); - attr_out = (tcg_pts_attr_file_meas_t*)attr; - - if (!directory_flag) - { - if (!pts->hash_file(pts, pathname, &file_hash)) - { - DBG1(DBG_IMC, "Hashing the given file has failed"); - return TNC_RESULT_FATAL; - } - attr_out->add_file_meas(attr_out, file_hash, pathname); - } - else - { - enumerator_t *meas_enumerator; - file_meas_entry_t *meas_entry; - u_int64_t num_of_files = 0 ; - - if (!pts->hash_directory(pts, pathname, &file_measurements)) - { - DBG1(DBG_IMC, "Hashing the files in a given directory has failed"); - return TNC_RESULT_FATAL; - } - - meas_enumerator = file_measurements->create_enumerator(file_measurements); - while (meas_enumerator->enumerate(meas_enumerator, &meas_entry)) - { - num_of_files++; - attr_out->add_file_meas(attr_out, - meas_entry->measurement, - meas_entry->filename); - } - - attr_out->set_number_of_files(attr_out, num_of_files); - meas_enumerator->destroy(meas_enumerator); - file_measurements->destroy(file_measurements); - - } - attr_list->insert_last(attr_list, attr); break; } diff --git a/src/libimcv/plugins/imv_attestation/imv_attestation.c b/src/libimcv/plugins/imv_attestation/imv_attestation.c index ead325186..619c97c2e 100644 --- a/src/libimcv/plugins/imv_attestation/imv_attestation.c +++ b/src/libimcv/plugins/imv_attestation/imv_attestation.c @@ -168,11 +168,12 @@ TNC_Result TNC_IMV_NotifyConnectionChange(TNC_IMVID imv_id, static TNC_Result send_message(TNC_ConnectionID connection_id) { pa_tnc_msg_t *msg; - TNC_Result result; + pa_tnc_attr_t *attr; pts_t *pts; imv_state_t *state; imv_attestation_state_t *attestation_state; imv_attestation_handshake_state_t handshake_state; + TNC_Result result; if (!imv_attestation->get_state(imv_attestation, connection_id, &state)) { @@ -190,91 +191,89 @@ static TNC_Result send_message(TNC_ConnectionID connection_id) { case IMV_ATTESTATION_STATE_INIT: { - pa_tnc_attr_t *attr_req_proto_cap, *attr_meas_algo; pts_proto_caps_flag_t flags; /* Send Request Protocol Capabilities attribute */ flags = pts->get_proto_caps(pts); - attr_req_proto_cap = tcg_pts_attr_proto_caps_create(flags, TRUE); - attr_req_proto_cap->set_noskip_flag(attr_req_proto_cap, TRUE); - msg->add_attribute(msg, attr_req_proto_cap); + attr = tcg_pts_attr_proto_caps_create(flags, TRUE); + attr->set_noskip_flag(attr, TRUE); + msg->add_attribute(msg, attr); /* Send Measurement Algorithms attribute */ - attr_meas_algo = tcg_pts_attr_meas_algo_create(supported_algorithms, FALSE); - attr_meas_algo->set_noskip_flag(attr_meas_algo, TRUE); - msg->add_attribute(msg, attr_meas_algo); + attr = tcg_pts_attr_meas_algo_create(supported_algorithms, FALSE); + attr->set_noskip_flag(attr, TRUE); + msg->add_attribute(msg, attr); break; } case IMV_ATTESTATION_STATE_MEAS: { - pa_tnc_attr_t *attr_req_file_meas; enumerator_t *enumerator; - pts_meas_algorithms_t communicated_caps; u_int32_t delimiter = SOLIDUS_UTF; + char *platform_info, *pathname; int id, type; - char *product, *path; - - /* Send Get TPM Version Information attribute */ - communicated_caps = pts->get_proto_caps(pts); - if (communicated_caps & PTS_PROTO_CAPS_T) + bool is_directory; + + /* Does the PTS-IMC have TPM support? */ + if (pts->get_proto_caps(pts) & PTS_PROTO_CAPS_T) { - pa_tnc_attr_t *attr_get_tpm_version, *attr_get_aik; - /* Send Get TPM Version attribute */ - attr_get_tpm_version = tcg_pts_attr_get_tpm_version_info_create(); - attr_get_tpm_version->set_noskip_flag(attr_get_tpm_version, TRUE); - msg->add_attribute(msg, attr_get_tpm_version); + attr = tcg_pts_attr_get_tpm_version_info_create(); + attr->set_noskip_flag(attr, TRUE); + msg->add_attribute(msg, attr); /* Send Get AIK attribute */ - attr_get_aik = tcg_pts_attr_get_aik_create(); - attr_get_aik->set_noskip_flag(attr_get_aik, TRUE); - msg->add_attribute(msg, attr_get_aik); + attr = tcg_pts_attr_get_aik_create(); + attr->set_noskip_flag(attr, TRUE); + msg->add_attribute(msg, attr); } - /* Send Request File Measurement attribute */ - /** - * Add files to measure to PTS Request File Measurement attribute - */ - product = "Ubuntu 11.4 i686"; + /* Get Platform and OS of the PTS-IMC */ + platform_info = pts->get_platform_info(pts); - if (!pts_db) + if (!pts_db || !platform_info) { + DBG1(DBG_IMV, "%s%s%s not available", + (pts_db) ? "" : "pts database", + (!pts_db && !platform_info) ? "and" : "", + (platform_info) ? "" : "platform info"); break; } - enumerator = pts_db->create_file_enumerator(pts_db, product); + DBG1(DBG_IMV, "platform is '%s'", platform_info); + + /* Send Request File Measurement attribute */ + enumerator = pts_db->create_file_enumerator(pts_db, platform_info); if (!enumerator) { break; } - while (enumerator->enumerate(enumerator, &id, &type, &path)) + while (enumerator->enumerate(enumerator, &id, &type, &pathname)) { - bool is_directory; - - DBG2(DBG_IMV, "id = %d, type = %d, path = '%s'", id, type, path); - - is_directory = (type != 0) ? TRUE : FALSE; - attr_req_file_meas = tcg_pts_attr_req_file_meas_create(is_directory, - id, delimiter, path); - attr_req_file_meas->set_noskip_flag(attr_req_file_meas, TRUE); - msg->add_attribute(msg, attr_req_file_meas); + is_directory = (type != 0); + DBG2(DBG_IMV, "measurement request %d for %s '%s'", + id, is_directory ? "directory" : "file", pathname); + attr = tcg_pts_attr_req_file_meas_create(is_directory, id, + delimiter, pathname); + attr->set_noskip_flag(attr, TRUE); + msg->add_attribute(msg, attr); } enumerator->destroy(enumerator); - break; } case IMV_ATTESTATION_STATE_COMP_EVID: case IMV_ATTESTATION_STATE_IML: - DBG1(DBG_IMV, "Attestation IMV has nothing to send: \"%s\"", handshake_state); + DBG1(DBG_IMV, "Attestation IMV has nothing to send: \"%s\"", + handshake_state); return TNC_RESULT_FATAL; default: - DBG1(DBG_IMV, "Attestation IMV is in unknown state: \"%s\"", handshake_state); + DBG1(DBG_IMV, "Attestation IMV is in unknown state: \"%s\"", + handshake_state); return TNC_RESULT_FATAL; } msg->build(msg); result = imv_attestation->send_message(imv_attestation, connection_id, - msg->get_encoding(msg)); + msg->get_encoding(msg)); msg->destroy(msg); return result; @@ -297,7 +296,7 @@ TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id, enumerator_t *enumerator; TNC_Result result; bool fatal_error = FALSE; - bool comparisons_succeeded = TRUE; + bool measurement_error = FALSE; if (!imv_attestation) { @@ -359,7 +358,7 @@ TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id, } else if (attr->get_vendor_id(attr) == PEN_TCG) { - switch(attr->get_type(attr)) + switch (attr->get_type(attr)) { case TCG_PTS_PROTO_CAPS: { @@ -424,63 +423,62 @@ TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id, case TCG_PTS_FILE_MEAS: { tcg_pts_attr_file_meas_t *attr_cast; - u_int64_t num_of_files; u_int16_t request_id; - u_int16_t meas_len; - enumerator_t *meas_enumerator; - file_meas_entry_t *meas_entry; - - attr_cast = (tcg_pts_attr_file_meas_t*)attr; - num_of_files = attr_cast->get_number_of_files(attr_cast); - request_id = attr_cast->get_request_id(attr_cast); - meas_len = attr_cast->get_meas_len(attr_cast); - - meas_enumerator = attr_cast->create_file_meas_enumerator(attr_cast); - while (meas_enumerator->enumerate(meas_enumerator, &meas_entry)) + pts_meas_algorithms_t algo; + pts_file_meas_t *measurements; + chunk_t measurement; + char *platform_info, *filename; + enumerator_t *e_meas; + + platform_info = pts->get_platform_info(pts); + if (!pts_db || !platform_info) { - enumerator_t *hash_enumerator; - pts_meas_algorithms_t selected_algorithm; - char *product = "Ubuntu 11.4 i686"; - chunk_t db_measurement; - - DBG3(DBG_IMV, "Received measurement: %B", &meas_entry->measurement); - - if (!pts_db) - { - break; - } - selected_algorithm = pts->get_meas_algorithm(pts); - - hash_enumerator = pts_db->create_meas_enumerator(pts_db, product, request_id, selected_algorithm); - if (!hash_enumerator) - { - break; - } - while (hash_enumerator->enumerate(hash_enumerator, &db_measurement)) - { - DBG3(DBG_IMV, "Expected measurement: %B", &db_measurement); - - /* Compare the received hash measurement with one saved in db */ - if(chunk_equals(db_measurement, meas_entry->measurement)) - { - DBG1(DBG_IMV, "Measurement comparison succeeded for: %s", - meas_entry->filename); - } - else - { - DBG1(DBG_IMV, "Measurement comparison failed for: %s", - meas_entry->filename); - comparisons_succeeded = FALSE; - } - } - hash_enumerator->destroy(hash_enumerator); - + break; } - - meas_enumerator->destroy(meas_enumerator); + + attr_cast = (tcg_pts_attr_file_meas_t*)attr; + measurements = attr_cast->get_measurements(attr_cast); + algo = pts->get_meas_algorithm(pts); + request_id = measurements->get_request_id(measurements); + + DBG1(DBG_IMV, "file measurement request %d:", request_id); + + e_meas = measurements->create_enumerator(measurements); + while (e_meas->enumerate(e_meas, &filename, &measurement)) + { + enumerator_t *e; + chunk_t db_measurement; + + e = pts_db->create_meas_enumerator(pts_db, + platform_info, request_id, algo); + if (!e) + { + DBG1(DBG_IMV, " database enumerator failed"); + break; + } + if (!e->enumerate(e, &db_measurement)) + { + DBG1(DBG_IMV, " measurement for '%s' not found" + " in database", filename); + e->destroy(e); + break; + } + if (chunk_equals(db_measurement, measurement)) + { + DBG2(DBG_IMV, " %#B for '%s' is ok", + &measurement, filename); + } + else + { + DBG1(DBG_IMV, " %#B for '%s' does not match %#B", + &measurement, filename, &db_measurement); + measurement_error = TRUE; + } + e->destroy(e); + } + e_meas->destroy(e_meas); attestation_state->set_handshake_state(attestation_state, IMV_ATTESTATION_STATE_END); - break; } @@ -526,22 +524,27 @@ TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id, state->set_recommendation(state, TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION, TNC_IMV_EVALUATION_RESULT_ERROR); - return imv_attestation->provide_recommendation(imv_attestation, connection_id); + return imv_attestation->provide_recommendation(imv_attestation, + connection_id); } - - - if(attestation_state->get_handshake_state(attestation_state) & IMV_ATTESTATION_STATE_END) + + if (attestation_state->get_handshake_state(attestation_state) & + IMV_ATTESTATION_STATE_END) { - (comparisons_succeeded) ? + if (measurement_error) + { state->set_recommendation(state, - TNC_IMV_ACTION_RECOMMENDATION_ALLOW, - TNC_IMV_EVALUATION_RESULT_COMPLIANT) : + TNC_IMV_ACTION_RECOMMENDATION_ISOLATE, + TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR); + } + else + { state->set_recommendation(state, - TNC_IMV_ACTION_RECOMMENDATION_ISOLATE, - TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR); - - return imv_attestation->provide_recommendation(imv_attestation, connection_id); - + TNC_IMV_ACTION_RECOMMENDATION_ALLOW, + TNC_IMV_EVALUATION_RESULT_COMPLIANT); + } + return imv_attestation->provide_recommendation(imv_attestation, + connection_id); } return send_message(connection_id); diff --git a/src/libimcv/plugins/imv_attestation/imv_attestation_state.c b/src/libimcv/plugins/imv_attestation/imv_attestation_state.c index cb343a143..bf21c0f97 100644 --- a/src/libimcv/plugins/imv_attestation/imv_attestation_state.c +++ b/src/libimcv/plugins/imv_attestation/imv_attestation_state.c @@ -184,6 +184,7 @@ METHOD(imv_attestation_state_t, get_pts, pts_t*, imv_state_t *imv_attestation_state_create(TNC_ConnectionID connection_id) { private_imv_attestation_state_t *this; + char *platform_info; INIT(this, .public = { @@ -206,6 +207,13 @@ imv_state_t *imv_attestation_state_create(TNC_ConnectionID connection_id) .eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW, .pts = pts_create(FALSE), ); + + platform_info = lib->settings->get_str(lib->settings, + "libimcv.plugins.imv-attestation.platform_info", NULL); + if (platform_info) + { + this->pts->set_platform_info(this->pts, platform_info); + } return &this->public.interface; } diff --git a/src/libimcv/tcg/pts/pts.c b/src/libimcv/tcg/pts/pts.c index 5a15b3a01..bd3892214 100644 --- a/src/libimcv/tcg/pts/pts.c +++ b/src/libimcv/tcg/pts/pts.c @@ -26,12 +26,11 @@ #include #include -#include +#include #include -#include "fake_ek_cert.h" -#define PTS_BUF_SIZE 32768 +#define PTS_BUF_SIZE 4096 /* Size of endorsement key in bytes */ #define EKSIZE (2048/8) @@ -66,6 +65,11 @@ struct private_pts_t { */ pts_meas_algorithms_t algorithm; + /** + * Platform and OS Info + */ + char *platform_info; + /** * Do we have an activated TPM */ @@ -153,6 +157,19 @@ static void print_tpm_version_info(private_pts_t *this) } } +METHOD(pts_t, get_platform_info, char*, + private_pts_t *this) +{ + return this->platform_info; +} + +METHOD(pts_t, set_platform_info, void, + private_pts_t *this, char *info) +{ + free(this->platform_info); + this->platform_info = strdup(info); +} + METHOD(pts_t, get_tpm_version_info, bool, private_pts_t *this, chunk_t *info) { @@ -186,7 +203,7 @@ static TSS_RESULT makeEKCert(TSS_HCONTEXT hContext, TSS_HTPM hTPM, UINT32 *pCert result = Tspi_TPM_GetPubEndorsementKey (hTPM, TRUE, NULL, &hPubek); if (result != TSS_SUCCESS) { - DBG1(DBG_IMC, "Error in: Tspi_TPM_GetPubEndorsementKey\n"); + DBG1(DBG_IMC, "Error in: Tspi_TPM_GetPubEndorsementKey"); return result; } result = Tspi_GetAttribData (hPubek, TSS_TSPATTRIB_RSAKEY_INFO, @@ -194,18 +211,20 @@ static TSS_RESULT makeEKCert(TSS_HCONTEXT hContext, TSS_HTPM hTPM, UINT32 *pCert Tspi_Context_CloseObject (hContext, hPubek); if (result != TSS_SUCCESS) { - DBG1(DBG_IMC, "Error in: Tspi_Context_CloseObject\n"); + DBG1(DBG_IMC, "Error in: Tspi_Context_CloseObject"); return result; } if (modulusLen != 256) { - DBG1(DBG_IMC, "Tspi_GetAttribData modulusLen != 256\n"); + DBG1(DBG_IMC, "Tspi_GetAttribData modulusLen != 256"); Tspi_Context_FreeMemory (hContext, modulus); return result; } + /* TODO define fakeEKCert *pCertLen = sizeof(fakeEKCert); *pCert = malloc (*pCertLen); memcpy (*pCert, fakeEKCert, *pCertLen); memcpy (*pCert + 0xc6, modulus, modulusLen); + */ Tspi_Context_FreeMemory (hContext, modulus); return TSS_SUCCESS; @@ -230,7 +249,7 @@ static X509* readPCAcert (int level) curl_easy_setopt(hCurl, CURLOPT_WRITEDATA, (BYTE **)f_tmp); if ((result = curl_easy_perform(hCurl))) { - DBG1(DBG_IMC, "Unable to connect to Privacy CA, curl library result code %d\n", result); + DBG1(DBG_IMC, "Unable to connect to Privacy CA, curl library result code %d", result); fclose(f_tmp); return NULL; } @@ -288,7 +307,7 @@ static bool obtain_aik(private_pts_t *this) curl_global_init (CURL_GLOBAL_ALL); - DBG3(DBG_IMC, "Retrieving PCA certificate...\n"); + DBG3(DBG_IMC, "Retrieving PCA certificate..."); /* TPM has EK Certificate */ if(REALEK) @@ -297,56 +316,56 @@ static bool obtain_aik(private_pts_t *this) } x509 = readPCAcert (level); if (x509 == NULL) { - DBG1(DBG_IMC, "Error reading PCA key\n"); + DBG1(DBG_IMC, "Error reading PCA key"); goto err; } pcaKey = X509_get_pubkey(x509); rsa = EVP_PKEY_get1_RSA(pcaKey); if (rsa == NULL) { - DBG1(DBG_IMC, "Error reading RSA key from PCA\n"); + DBG1(DBG_IMC, "Error reading RSA key from PCA"); goto err; } X509_free (x509); result = Tspi_Context_Create(&hContext); if (result != TSS_SUCCESS) { - DBG1(DBG_IMC, "Error 0x%x on Tspi_Context_Create\n", result); + DBG1(DBG_IMC, "Error 0x%x on Tspi_Context_Create", result); goto err; } result = Tspi_Context_Connect(hContext, NULL); if (result != TSS_SUCCESS) { - DBG1(DBG_IMC, "Error 0x%x on Tspi_Context_Connect\n", result); + DBG1(DBG_IMC, "Error 0x%x on Tspi_Context_Connect", result); goto err; } result = Tspi_Context_GetTpmObject (hContext, &hTPM); if (result != TSS_SUCCESS) { - DBG1(DBG_IMC, "Error 0x%x on Tspi_Context_GetTpmObject\n", result); + DBG1(DBG_IMC, "Error 0x%x on Tspi_Context_GetTpmObject", result); goto err; } result = Tspi_Context_LoadKeyByUUID(hContext, TSS_PS_TYPE_SYSTEM, SRK_UUID, &hSRK); if (result != TSS_SUCCESS) { - DBG1(DBG_IMC, "Error 0x%x on Tspi_Context_LoadKeyByUUID for SRK\n", result); + DBG1(DBG_IMC, "Error 0x%x on Tspi_Context_LoadKeyByUUID for SRK", result); goto err; } result = Tspi_GetPolicyObject(hSRK, TSS_POLICY_USAGE, &hSrkPolicy); if (result != TSS_SUCCESS) { - DBG1(DBG_IMC, "Error 0x%x on Tspi_GetPolicyObject for SRK\n", result); + DBG1(DBG_IMC, "Error 0x%x on Tspi_GetPolicyObject for SRK", result); goto err; } result = Tspi_Policy_SetSecret(hSrkPolicy, TSS_SECRET_MODE_SHA1, 20, secret); if (result != TSS_SUCCESS) { - DBG1(DBG_IMC, "Error 0x%x on Tspi_Policy_SetSecret for SRK\n", result); + DBG1(DBG_IMC, "Error 0x%x on Tspi_Policy_SetSecret for SRK", result); goto err; } result = Tspi_GetPolicyObject(hTPM, TSS_POLICY_USAGE, &hTPMPolicy); if (result != TSS_SUCCESS) { - DBG1(DBG_IMC, "Error 0x%x on Tspi_GetPolicyObject for TPM\n", result); + DBG1(DBG_IMC, "Error 0x%x on Tspi_GetPolicyObject for TPM", result); goto err; } result = Tspi_Policy_SetSecret(hTPMPolicy, TSS_SECRET_MODE_SHA1, 20, secret); if (result != TSS_SUCCESS) { - DBG1(DBG_IMC, "Error 0x%x on Tspi_Policy_SetSecret for TPM\n", result); + DBG1(DBG_IMC, "Error 0x%x on Tspi_Policy_SetSecret for TPM", result); goto err; } @@ -354,7 +373,7 @@ static bool obtain_aik(private_pts_t *this) TSS_OBJECT_TYPE_RSAKEY, initFlags, &hIdentKey); if (result != TSS_SUCCESS) { - DBG1(DBG_IMC, "Error 0x%x on Tspi_Context_CreateObject for key\n", result); + DBG1(DBG_IMC, "Error 0x%x on Tspi_Context_CreateObject for key", result); goto err; } @@ -373,14 +392,14 @@ static bool obtain_aik(private_pts_t *this) result = Tspi_SetAttribData (hPCAKey, TSS_TSPATTRIB_RSAKEY_INFO, TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, size_n, n); if (result != TSS_SUCCESS) { - DBG1(DBG_IMC, "Error 0x%x on Tspi_SetAttribData for PCA modulus\n", result); + DBG1(DBG_IMC, "Error 0x%x on Tspi_SetAttribData for PCA modulus", result); goto err; } result = Tspi_SetAttribUint32(hPCAKey, TSS_TSPATTRIB_KEY_INFO, TSS_TSPATTRIB_KEYINFO_ENCSCHEME, TSS_ES_RSAESPKCSV15); if (result != TSS_SUCCESS) { - DBG1(DBG_IMC, "Error 0x%x on Tspi_SetAttribUint32 for PCA encscheme\n", result); + DBG1(DBG_IMC, "Error 0x%x on Tspi_SetAttribUint32 for PCA encscheme", result); goto err; } @@ -395,22 +414,22 @@ static bool obtain_aik(private_pts_t *this) result = Tspi_SetAttribData(hTPM, TSS_TSPATTRIB_TPM_CREDENTIAL, TSS_TPMATTRIB_EKCERT, ekCertLen, ekCert); if (result != TSS_SUCCESS) { - DBG1(DBG_IMC, "Error 0x%x on SetAttribData for EKCert\n", result); + DBG1(DBG_IMC, "Error 0x%x on SetAttribData for EKCert", result); goto err; } } - DBG3(DBG_IMC, "Generating attestation identity key...\n"); + DBG3(DBG_IMC, "Generating attestation identity key..."); result = Tspi_TPM_CollateIdentityRequest(hTPM, hSRK, hPCAKey, 0, NULL, hIdentKey, TSS_ALG_AES, &ulTCPAIdentityReqLength, &rgbTCPAIdentityReq); if (result != TSS_SUCCESS){ - DBG1(DBG_IMC, "Error 0x%x on Tspi_TPM_CollateIdentityRequest\n", result); + DBG1(DBG_IMC, "Error 0x%x on Tspi_TPM_CollateIdentityRequest", result); goto err; } - DBG3(DBG_IMC, "Sending request to PrivacyCA.com...\n"); + DBG3(DBG_IMC, "Sending request to PrivacyCA.com..."); /* Send to server */ f_tmp = tmpfile(); @@ -425,12 +444,12 @@ static bool obtain_aik(private_pts_t *this) slist = curl_slist_append (slist, "Content-Transfer-Encoding: binary"); curl_easy_setopt (hCurl, CURLOPT_HTTPHEADER, slist); if ((result = curl_easy_perform(hCurl))) { - DBG1(DBG_IMC, "Unable to connect to Privacy CA, curl library result code %d\n", result); + DBG1(DBG_IMC, "Unable to connect to Privacy CA, curl library result code %d", result); exit (result); } curl_slist_free_all(slist); - DBG3(DBG_IMC, "Processing response from PrivacyCA...\n"); + DBG3(DBG_IMC, "Processing response from PrivacyCA..."); fflush (f_tmp); symBufSize = ftell(f_tmp); @@ -438,7 +457,7 @@ static bool obtain_aik(private_pts_t *this) rewind(f_tmp); if(!fread (symBuf, 1, symBufSize, f_tmp)) { - DBG1(DBG_IMC, "Failed to read buffer\n"); + DBG1(DBG_IMC, "Failed to read buffer"); goto err; } @@ -447,7 +466,7 @@ static bool obtain_aik(private_pts_t *this) asymBufSize = sizeof(asymBuf); if (symBufSize <= asymBufSize) { - DBG1(DBG_IMC, "Bad response from PrivacyCA.com: %s\n", symBuf); + DBG1(DBG_IMC, "Bad response from PrivacyCA.com: %s", symBuf); goto err; } @@ -457,7 +476,7 @@ static bool obtain_aik(private_pts_t *this) result = Tspi_Key_LoadKey (hIdentKey, hSRK); if (result != TSS_SUCCESS) { - DBG1(DBG_IMC, "Error 0x%x on Tspi_Key_LoadKey for AIK\n", result); + DBG1(DBG_IMC, "Error 0x%x on Tspi_Key_LoadKey for AIK", result); goto err; } @@ -465,7 +484,7 @@ static bool obtain_aik(private_pts_t *this) symBufSize, symBuf, &credBufSize, &credBuf); if (result != TSS_SUCCESS) { - DBG1(DBG_IMC, "Error 0x%x on Tspi_TPM_ActivateIdentity\n", result); + DBG1(DBG_IMC, "Error 0x%x on Tspi_TPM_ActivateIdentity", result); goto err; } @@ -473,11 +492,11 @@ static bool obtain_aik(private_pts_t *this) tbuf = credBuf; x509 = d2i_X509(NULL, (const BYTE **)&tbuf, credBufSize); if (x509 == NULL) { - DBG1(DBG_IMC, "Unable to parse returned credential\n"); + DBG1(DBG_IMC, "Unable to parse returned credential"); goto err; } if (tbuf-credBuf != credBufSize) { - DBG1(DBG_IMC, "Note, not all data from privacy ca was parsed correctly\n"); + DBG1(DBG_IMC, "Note, not all data from privacy ca was parsed correctly"); } if(x509) @@ -504,11 +523,11 @@ static bool obtain_aik(private_pts_t *this) } else { - DBG1(DBG_IMC, "Neither AIK Key blob, nor AIK Certificate is available\n"); + DBG1(DBG_IMC, "Neither AIK Key blob, nor AIK Certificate is available"); goto err; } - DBG3(DBG_IMC, "Succeeded at obtaining AIK Certificate from Privacy CA!\n"); + DBG3(DBG_IMC, "Succeeded at obtaining AIK Certificate from Privacy CA!"); return TRUE; err: @@ -536,30 +555,20 @@ METHOD(pts_t, set_aik, void, this->is_naked_key = is_naked_key; } -METHOD(pts_t, hash_file, bool, - private_pts_t *this, char *pathname, chunk_t *out) +/** + * Compute a hash over a file + */ +static bool hash_file(hasher_t *hasher, char *pathname, u_char *hash) { - char buffer[PTS_BUF_SIZE]; - chunk_t path_chunk; + u_char buffer[PTS_BUF_SIZE]; FILE *file; int bytes_read; - hasher_t *hasher; - hash_algorithm_t hash_alg; - - /* Create a hasher */ - hash_alg = pts_meas_to_hash_algorithm(this->algorithm); - hasher = lib->crypto->create_hasher(lib->crypto, hash_alg); - if (!hasher) - { - DBG1(DBG_IMC, "hasher %N not available", hash_algorithm_names, hash_alg); - return FALSE; - } file = fopen(pathname, "rb"); if (!file) { - DBG1(DBG_IMC,"file '%s' can not be opened, %s", pathname, strerror(errno)); - hasher->destroy(hasher); + DBG1(DBG_IMC," file '%s' can not be opened, %s", pathname, + strerror(errno)); return FALSE; } while (TRUE) @@ -567,66 +576,116 @@ METHOD(pts_t, hash_file, bool, bytes_read = fread(buffer, 1, sizeof(buffer), file); if (bytes_read > 0) { - hasher->allocate_hash(hasher, chunk_create(buffer, bytes_read), NULL); + hasher->get_hash(hasher, chunk_create(buffer, bytes_read), NULL); } else { - hasher->allocate_hash(hasher, chunk_empty, out); + hasher->get_hash(hasher, chunk_empty, hash); break; } } - fclose(file); - hasher->destroy(hasher); return TRUE; +} + +/** + * Get the relative filename of a fully qualified file pathname + */ +static char* get_filename(char *pathname) +{ + char *pos, *filename; + + pos = filename = pathname; + while (pos && *(++pos) != '\0') + { + filename = pos; + pos = strchr(filename, '/'); + } + return filename; } -METHOD(pts_t, hash_directory, bool, - private_pts_t *this, char *pathname, linked_list_t **file_measurements) +METHOD(pts_t, do_measurements, pts_file_meas_t*, + private_pts_t *this, u_int16_t request_id, char *pathname, + bool directory_flag) { - DIR *dir; - struct dirent *ent; - chunk_t path_chunk; - file_meas_entry_t *entry; - linked_list_t *list = *file_measurements; - char filename[BUF_LEN]; - - list = linked_list_create(); - entry = malloc_thing(file_meas_entry_t); - - dir = opendir(pathname); - if (dir == NULL) + hasher_t *hasher; + hash_algorithm_t hash_alg; + u_char hash[HASH_SIZE_SHA384]; + chunk_t measurement; + pts_file_meas_t *measurements; + + /* Create a hasher */ + hash_alg = pts_meas_to_hash_algorithm(this->algorithm); + hasher = lib->crypto->create_hasher(lib->crypto, hash_alg); + if (!hasher) { - DBG1(DBG_IMC, "opening directory '%s' failed: %s", pathname, strerror(errno)); - return FALSE; + DBG1(DBG_IMC, " hasher %N not available", hash_algorithm_names, hash_alg); + return NULL; } - while ((ent = readdir(dir))) + + /* Create a measurement object */ + measurements = pts_file_meas_create(request_id); + + /* Link the hash to the measurement and set the measurement length */ + measurement = chunk_create(hash, hasher->get_hash_size(hasher)); + + if (directory_flag) { - if (*ent->d_name == '.') - { /* skip ".", ".." and hidden files (such as ".svn") */ - continue; - } - snprintf(filename, BUF_LEN, "%s/%s", pathname, ent->d_name); - entry->filename = strdup(filename); - - if (!hash_file(this, filename, &entry->measurement)) + enumerator_t *enumerator; + char *rel_name, *abs_name; + struct stat st; + + enumerator = enumerator_create_directory(pathname); + if (!enumerator) { - DBG1(DBG_IMC, "Hashing the given file has failed"); - return FALSE; + DBG1(DBG_IMC," directory '%s' can not be opened, %s", pathname, + strerror(errno)); + hasher->destroy(hasher); + measurements->destroy(measurements); + return NULL; } - list->insert_last(list, entry); + while (enumerator->enumerate(enumerator, &rel_name, &abs_name, &st)) + { + if (S_ISDIR(st.st_mode) && *rel_name != '.') + { + if (!hash_file(hasher, abs_name, hash)) + { + enumerator->destroy(enumerator); + hasher->destroy(hasher); + measurements->destroy(measurements); + return NULL; + } + DBG2(DBG_IMC, " %#B for '%s'", + &measurement, rel_name); + measurements->add(measurements, rel_name, measurement); + } + } + enumerator->destroy(enumerator); } - - closedir(dir); - - *file_measurements = list; - return TRUE; + else + { + char *filename; + + if (!hash_file(hasher, pathname, hash)) + { + hasher->destroy(hasher); + measurements->destroy(measurements); + return NULL; + } + filename = get_filename(pathname); + DBG2(DBG_IMC, " %#B for '%s'", &measurement, filename); + measurements->add(measurements, filename, measurement); + } + hasher->destroy(hasher); + + return measurements; } METHOD(pts_t, destroy, void, private_pts_t *this) { + free(this->platform_info); free(this->tpm_version_info.ptr); free(this); } @@ -683,12 +742,13 @@ pts_t *pts_create(bool is_imc) .set_proto_caps = _set_proto_caps, .get_meas_algorithm = _get_meas_algorithm, .set_meas_algorithm = _set_meas_algorithm, + .get_platform_info = _get_platform_info, + .set_platform_info = _set_platform_info, .get_tpm_version_info = _get_tpm_version_info, .set_tpm_version_info = _set_tpm_version_info, .get_aik = _get_aik, .set_aik = _set_aik, - .hash_file = _hash_file, - .hash_directory = _hash_directory, + .do_measurements = _do_measurements, .destroy = _destroy, }, .proto_caps = PTS_PROTO_CAPS_V, diff --git a/src/libimcv/tcg/pts/pts.h b/src/libimcv/tcg/pts/pts.h index f76ee8eb1..6b5d0c1a2 100644 --- a/src/libimcv/tcg/pts/pts.h +++ b/src/libimcv/tcg/pts/pts.h @@ -25,21 +25,10 @@ typedef struct pts_t pts_t; #include "pts_proto_caps.h" #include "pts_meas_algo.h" -#include - +#include "pts_file_meas.h" #include -typedef struct file_meas_entry_t file_meas_entry_t; - -/** - * File Measurement entry - */ -struct file_meas_entry_t { - char *filename; - chunk_t measurement; -}; - /** * Class implementing the TCG Platform Trust System (PTS) * @@ -74,6 +63,20 @@ struct pts_t { */ void (*set_meas_algorithm)(pts_t *this, pts_meas_algorithms_t algorithm); + /** + * Get Platform and OS Info + * + * @return platform and OS info + */ + char* (*get_platform_info)(pts_t *this); + + /** + * Set Platform and OS Info + * + * @param info platform and OS info + */ + void (*set_platform_info)(pts_t *this, char *info); + /** * Get TPM 1.2 Version Info * @@ -107,23 +110,16 @@ struct pts_t { void (*set_aik)(pts_t *this, chunk_t aik, bool is_naked_key); /** - * Hash the given file + * Do PTS File Measurements * - * @param pathname absolute path to file to be hashed - * @param out hash output value of a given file - * @return TRUE if hashing file was successful + * @param request_id ID of PTS File Measurement Request + * @param pathname Absolute pathname of file to be measured + * @param is_directory if TRUE directory contents are measured + * @return PTS File Measurements of NULL if FAILED */ - bool (*hash_file)(pts_t *this, char *pathname, chunk_t *out); + pts_file_meas_t* (*do_measurements)(pts_t *this, u_int16_t request_id, + char *pathname, bool is_directory); - /** - * Hash the given directory - * - * @param pathname absolute path to directory to be hashed - * @param file_measurements list of hash output values of files in a given folder - * @return TRUE if hashing directory was successful - */ - bool (*hash_directory)(pts_t *this, char *pathname, linked_list_t **file_measurements); - /** * Destroys a pts_t object. */ diff --git a/src/libimcv/tcg/pts/pts_file_meas.c b/src/libimcv/tcg/pts/pts_file_meas.c new file mode 100644 index 000000000..cfd47cb12 --- /dev/null +++ b/src/libimcv/tcg/pts/pts_file_meas.c @@ -0,0 +1,137 @@ +/* + * 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "pts_file_meas.h" + +#include + +typedef struct private_pts_file_meas_t private_pts_file_meas_t; + +/** + * Private data of a pts_file_meas_t object. + * + */ +struct private_pts_file_meas_t { + + /** + * Public pts_file_meas_t interface. + */ + pts_file_meas_t public; + + /** + * ID of PTS File Measurement Request + */ + u_int16_t request_id; + + /** + * List of File Measurements + */ + linked_list_t *list; +}; + +typedef struct entry_t entry_t; + +/** + * PTS File Measurement entry + */ +struct entry_t { + char *filename; + chunk_t measurement; +}; + +/** + * Free an entry_t object + */ +static void free_entry(entry_t *entry) +{ + if (entry) + { + free(entry->filename); + free(entry->measurement.ptr); + free(entry); + } +} + +METHOD(pts_file_meas_t, get_request_id, u_int16_t, + private_pts_file_meas_t *this) +{ + return this->request_id; +} + +METHOD(pts_file_meas_t, get_file_count, int, + private_pts_file_meas_t *this) +{ + return this->list->get_count(this->list); +} + +METHOD(pts_file_meas_t, add, void, + private_pts_file_meas_t *this, char *filename, chunk_t measurement) +{ + entry_t *entry; + + entry = malloc_thing(entry_t); + entry->filename = strdup(filename); + entry->measurement = chunk_clone(measurement); + + this->list->insert_last(this->list, entry); +} + +/** + * Enumerate file measurement entries + */ +static bool entry_filter(void *null, entry_t **entry, char **filename, + void *i2, chunk_t *measurement) +{ + *filename = (*entry)->filename; + *measurement = (*entry)->measurement; + return TRUE; +} + +METHOD(pts_file_meas_t, create_enumerator, enumerator_t*, + private_pts_file_meas_t *this) +{ + return enumerator_create_filter(this->list->create_enumerator(this->list), + (void*)entry_filter, NULL, NULL); +} + +METHOD(pts_file_meas_t, destroy, void, + private_pts_file_meas_t *this) +{ + this->list->destroy_function(this->list, (void *)free_entry); + free(this); +} + +/** + * See header + */ +pts_file_meas_t *pts_file_meas_create(u_int16_t request_id) +{ + private_pts_file_meas_t *this; + + INIT(this, + .public = { + .get_request_id = _get_request_id, + .get_file_count = _get_file_count, + .add = _add, + .create_enumerator = _create_enumerator, + .destroy = _destroy, + }, + .request_id = request_id, + .list = linked_list_create(), + ); + + return &this->public; +} + diff --git a/src/libimcv/tcg/pts/pts_file_meas.h b/src/libimcv/tcg/pts/pts_file_meas.h new file mode 100644 index 000000000..63507b96b --- /dev/null +++ b/src/libimcv/tcg/pts/pts_file_meas.h @@ -0,0 +1,76 @@ +/* + * 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 . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup pts_file_meas pts_file_meas + * @{ @ingroup pts + */ + +#ifndef PTS_FILE_MEAS_H_ +#define PTS_FILE_MEAS_H_ + +#include + +typedef struct pts_file_meas_t pts_file_meas_t; + +/** + * Class storing PTS File Measurements + */ +struct pts_file_meas_t { + + /** + * Get the ID of the PTS File Measurement Request + * + * @return ID of PTS File Measurement Request + */ + u_int16_t (*get_request_id)(pts_file_meas_t *this); + + /** + * Get the number of measured files + * + * @return Number of measured files + */ + int (*get_file_count)(pts_file_meas_t *this); + + /** + * Add a PTS File Measurement + * + * @param filename Name of measured file or directory + * @param measurement PTS Measurement hash + */ + void (*add)(pts_file_meas_t *this, char *filename, chunk_t measurement); + + /** + * Create a PTS File Measurement enumerator + * + * @return Enumerator returning filename and measurement + */ + enumerator_t* (*create_enumerator)(pts_file_meas_t *this); + + /** + * Destroys a pts_file_meas_t object. + */ + void (*destroy)(pts_file_meas_t *this); + +}; + +/** + * Creates a pts_file_meas_t object + * + * @param request_id ID of PTS File Measurement Request + */ +pts_file_meas_t* pts_file_meas_create(u_int16_t request_id); + +#endif /** PTS_FILE_MEAS_H_ @}*/ diff --git a/src/libimcv/tcg/tcg_pts_attr_file_meas.c b/src/libimcv/tcg/tcg_pts_attr_file_meas.c index efeed7e17..d2fcb548f 100644 --- a/src/libimcv/tcg/tcg_pts_attr_file_meas.c +++ b/src/libimcv/tcg/tcg_pts_attr_file_meas.c @@ -31,25 +31,24 @@ typedef struct private_tcg_pts_attr_file_meas_t private_tcg_pts_attr_file_meas_t * * 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Number of Files included | + * | Number of Files included | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Number of Files included | + * | Number of Files included | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Request ID | Measurement Length | + * | Request ID | Measurement Length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Measurement #1 (Variable Length) | + * | Measurement #1 (Variable Length) | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Filename Length | Filename (Variable Length) ~ + * | Filename Length | Filename (Variable Length) ~ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * ~ Filename (Variable Length) ~ + * ~ Filename (Variable Length) ~ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Measurement #2 (Variable Length) | + * | Measurement #2 (Variable Length) | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Filename Length | Filename (Variable Length) ~ + * | Filename Length | Filename (Variable Length) ~ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * ~ Filename (Variable Length) ~ + * ~ Filename (Variable Length) ~ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * ........................... */ @@ -87,24 +86,9 @@ struct private_tcg_pts_attr_file_meas_t { bool noskip_flag; /** - * Number of files included + * PTS File Measurements */ - u_int64_t number_of_files; - - /** - * Request ID - */ - u_int16_t request_id; - - /** - * Measurement Length - */ - u_int16_t meas_len; - - /** - * List of File Measurement entries - */ - linked_list_t *measurements; + pts_file_meas_t *measurements; }; @@ -143,24 +127,32 @@ METHOD(pa_tnc_attr_t, build, void, { bio_writer_t *writer; enumerator_t *enumerator; - file_meas_entry_t *entry; - chunk_t filename; + u_int64_t number_of_files; + u_int16_t request_id; + char *filename; + chunk_t measurement; + bool first = TRUE; + number_of_files = this->measurements->get_file_count(this->measurements); + request_id = this->measurements->get_request_id(this->measurements); writer = bio_writer_create(PTS_FILE_MEAS_SIZE); - /* Write the 64 bit integer as 2 parts, first 32 bit and second */ - writer->write_uint32 (writer, (this->number_of_files >> 32)); - writer->write_uint32 (writer, (this->number_of_files & (int)(pow(2,32) - 1))); - writer->write_uint16(writer, this->request_id); - writer->write_uint16(writer, this->meas_len); + /* Write the 64 bit integer as two 32 bit parts */ + writer->write_uint32(writer, number_of_files >> 32); + writer->write_uint32(writer, number_of_files & 0xffffffff); + writer->write_uint16(writer, request_id); enumerator = this->measurements->create_enumerator(this->measurements); - while (enumerator->enumerate(enumerator, &entry)) + while (enumerator->enumerate(enumerator, &filename, &measurement)) { - filename = chunk_create(entry->filename, strlen(entry->filename)); - writer->write_data (writer, entry->measurement); - writer->write_uint16(writer, strlen(entry->filename)); - writer->write_data (writer, filename); + if (first) + { + writer->write_uint16(writer, measurement.len); + first = FALSE; + } + writer->write_data (writer, measurement); + writer->write_uint16(writer, strlen(filename)); + writer->write_data (writer, chunk_create(filename, strlen(filename))); } enumerator->destroy(enumerator); @@ -172,113 +164,79 @@ METHOD(pa_tnc_attr_t, process, status_t, private_tcg_pts_attr_file_meas_t *this, u_int32_t *offset) { bio_reader_t *reader; + int count; u_int32_t number_of_files; - u_int16_t filename_length; - chunk_t filename; - file_meas_entry_t *entry; + u_int16_t request_id, meas_len, filename_len; + size_t len; + chunk_t measurement, filename; + char buf[BUF_LEN]; + status_t status = FAILED; if (this->value.len < PTS_FILE_MEAS_SIZE) { - DBG1(DBG_TNC, "insufficient data for File Measurement"); + DBG1(DBG_TNC, "insufficient data for PTS file measurement header"); *offset = 0; return FAILED; } reader = bio_reader_create(this->value); - - reader->read_uint32(reader, &number_of_files); - this->number_of_files = (u_int64_t)number_of_files << 32; - reader->read_uint32(reader, &number_of_files); - this->number_of_files += number_of_files; - reader->read_uint16(reader, &this->request_id); - reader->read_uint16(reader, &this->meas_len); - - while (reader->remaining(reader)) - { - entry = malloc_thing(file_meas_entry_t); - - reader->read_data (reader, this->meas_len, &entry->measurement); - entry->measurement = chunk_clone(entry->measurement); - reader->read_uint16 (reader, &filename_length); - reader->read_data(reader, filename_length, &filename); - entry->filename = malloc(filename.len + 1); - memcpy(entry->filename, filename.ptr, filename.len); - entry->filename[filename.len] = '\0'; - - this->measurements->insert_last(this->measurements, entry); - } + reader->read_uint32(reader, &number_of_files); + count = (sizeof(count) > 4) ? number_of_files << 32 : 0; + reader->read_uint32(reader, &number_of_files); + count += number_of_files; + reader->read_uint16(reader, &request_id); + reader->read_uint16(reader, &meas_len); + + this->measurements = pts_file_meas_create(request_id); + + while (count--) + { + if (!reader->read_data(reader, meas_len, &measurement)) + { + DBG1(DBG_TNC, "insufficient data for PTS file measurement"); + goto end; + } + if (!reader->read_uint16(reader, &filename_len)) + { + DBG1(DBG_TNC, "insufficient data for filename length"); + goto end; + } + if (!reader->read_data(reader, filename_len, &filename)) + { + DBG1(DBG_TNC, "insufficient data for filename"); + goto end; + } + + len = min(filename.len, BUF_LEN-1); + memcpy(buf, filename.ptr, len); + buf[len] = '\0'; + this->measurements->add(this->measurements, buf, measurement); + } + status = SUCCESS; + +end: reader->destroy(reader); - return SUCCESS; + return status; } METHOD(pa_tnc_attr_t, destroy, void, private_tcg_pts_attr_file_meas_t *this) { + this->measurements->destroy(this->measurements); free(this->value.ptr); - this->measurements->destroy_function(this->measurements, free); free(this); } -METHOD(tcg_pts_attr_file_meas_t, get_number_of_files, u_int64_t, +METHOD(tcg_pts_attr_file_meas_t, get_measurements, pts_file_meas_t*, private_tcg_pts_attr_file_meas_t *this) { - return this->number_of_files; -} - -METHOD(tcg_pts_attr_file_meas_t, set_number_of_files, void, - private_tcg_pts_attr_file_meas_t *this, u_int64_t number_of_files) -{ - this->number_of_files = number_of_files; -} - -METHOD(tcg_pts_attr_file_meas_t, get_request_id, u_int16_t, - private_tcg_pts_attr_file_meas_t *this) -{ - return this->request_id; -} - -METHOD(tcg_pts_attr_file_meas_t, set_request_id, void, - private_tcg_pts_attr_file_meas_t *this, u_int16_t request_id) -{ - this->request_id = request_id; -} - -METHOD(tcg_pts_attr_file_meas_t, get_meas_len, u_int16_t, - private_tcg_pts_attr_file_meas_t *this) -{ - return this->meas_len; -} - -METHOD(tcg_pts_attr_file_meas_t, set_meas_len, void, - private_tcg_pts_attr_file_meas_t *this, u_int16_t meas_len) -{ - this->meas_len = meas_len; -} - -METHOD(tcg_pts_attr_file_meas_t, add_file_meas, void, - private_tcg_pts_attr_file_meas_t *this, chunk_t measurement, char *filename) -{ - file_meas_entry_t *entry; - - entry = malloc_thing(file_meas_entry_t); - entry->measurement = measurement; - entry->filename = strdup(filename); - this->measurements->insert_last(this->measurements, entry); -} - -METHOD(tcg_pts_attr_file_meas_t, create_file_meas_enumerator, enumerator_t*, - private_tcg_pts_attr_file_meas_t *this) -{ - return this->measurements->create_enumerator(this->measurements); + return this->measurements; } /** * Described in header. */ -pa_tnc_attr_t *tcg_pts_attr_file_meas_create( - u_int64_t number_of_files, - u_int16_t request_id, - u_int16_t meas_len) +pa_tnc_attr_t *tcg_pts_attr_file_meas_create(pts_file_meas_t *measurements) { private_tcg_pts_attr_file_meas_t *this; @@ -294,21 +252,11 @@ pa_tnc_attr_t *tcg_pts_attr_file_meas_create( .process = _process, .destroy = _destroy, }, - .get_number_of_files= _get_number_of_files, - .set_number_of_files= _set_number_of_files, - .get_request_id = _get_request_id, - .set_request_id = _set_request_id, - .get_meas_len = _get_meas_len, - .set_meas_len = _set_meas_len, - .add_file_meas = _add_file_meas, - .create_file_meas_enumerator = _create_file_meas_enumerator, + .get_measurements = _get_measurements, }, .vendor_id = PEN_TCG, .type = TCG_PTS_FILE_MEAS, - .number_of_files = number_of_files, - .request_id = request_id, - .meas_len = meas_len, - .measurements = linked_list_create(), + .measurements = measurements, ); return &this->public.pa_tnc_attribute; @@ -334,19 +282,11 @@ pa_tnc_attr_t *tcg_pts_attr_file_meas_create_from_data(chunk_t data) .process = _process, .destroy = _destroy, }, - .get_number_of_files= _get_number_of_files, - .set_number_of_files= _set_number_of_files, - .get_request_id = _get_request_id, - .set_request_id = _set_request_id, - .get_meas_len = _get_meas_len, - .set_meas_len = _set_meas_len, - .add_file_meas = _add_file_meas, - .create_file_meas_enumerator = _create_file_meas_enumerator, + .get_measurements = _get_measurements, }, .vendor_id = PEN_TCG, .type = TCG_PTS_FILE_MEAS, .value = chunk_clone(data), - .measurements = linked_list_create(), ); return &this->public.pa_tnc_attribute; diff --git a/src/libimcv/tcg/tcg_pts_attr_file_meas.h b/src/libimcv/tcg/tcg_pts_attr_file_meas.h index 90b671385..a28e9c1a9 100644 --- a/src/libimcv/tcg/tcg_pts_attr_file_meas.h +++ b/src/libimcv/tcg/tcg_pts_attr_file_meas.h @@ -25,8 +25,8 @@ typedef struct tcg_pts_attr_file_meas_t tcg_pts_attr_file_meas_t; #include "tcg_attr.h" #include "pa_tnc/pa_tnc_attr.h" -/* TODO: for struct file_meas_entry_t */ #include "pts/pts.h" +#include "pts/pts_file_meas.h" /** * Class implementing the TCG PTS File Measurement attribute @@ -40,79 +40,20 @@ struct tcg_pts_attr_file_meas_t { pa_tnc_attr_t pa_tnc_attribute; /** - * Get Number of Files included + * Get PTS File Measurements * - * @return Number of Files included + * @return PTS File Measurements */ - u_int64_t (*get_number_of_files)(tcg_pts_attr_file_meas_t *this); + pts_file_meas_t* (*get_measurements)(tcg_pts_attr_file_meas_t *this); - /** - * Set Number of Files included - * - * @param num_files Number of Files included - */ - void (*set_number_of_files)(tcg_pts_attr_file_meas_t *this, - u_int64_t num_files); - - /** - * Get Request ID - * - * @return Request ID - */ - u_int16_t (*get_request_id)(tcg_pts_attr_file_meas_t *this); - - /** - * Set Request ID - * - * @param request_id Request ID - */ - void (*set_request_id)(tcg_pts_attr_file_meas_t *this, - u_int16_t request_id); - - /** - * Get Measurement Length - * - * @return Measurement Length - */ - u_int16_t (*get_meas_len)(tcg_pts_attr_file_meas_t *this); - - /** - * Set Measurement Length - * - * @param meas_len Measurement Length - */ - void (*set_meas_len)(tcg_pts_attr_file_meas_t *this, - u_int16_t meas_len); - - /** - * Add a file measurement entry - * - * @param measurement Measurement value - * @param filename Filename - */ - void (*add_file_meas)(tcg_pts_attr_file_meas_t *this, chunk_t measurement, - char *filename); - - /** - * Enumerates over all file measurements - * Format: chunk_t *measurement, chunk_t *file_name - * - * @return enumerator - */ - enumerator_t* (*create_file_meas_enumerator)(tcg_pts_attr_file_meas_t *this); }; /** * Creates an tcg_pts_attr_file_meas_t object * - * @param directory_flag Directory Contents Flag - * @param request_id Request ID - * @param delimiter Delimiter Character - * @param path File Path + * @param measurements PTS File Measurements */ -pa_tnc_attr_t* tcg_pts_attr_file_meas_create(u_int64_t number_of_files, - u_int16_t request_id, - u_int16_t meas_len); +pa_tnc_attr_t* tcg_pts_attr_file_meas_create(pts_file_meas_t *measurements); /** * Creates an tcg_pts_attr_file_meas_t object from received data