finished refactoring of file measurements
authorAndreas Steffen <andreas.steffen@strongswan.org>
Thu, 1 Sep 2011 13:42:35 +0000 (15:42 +0200)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Thu, 8 Sep 2011 10:08:15 +0000 (12:08 +0200)
src/libimcv/Makefile.am
src/libimcv/plugins/imc_attestation/imc_attestation.c
src/libimcv/plugins/imv_attestation/imv_attestation.c
src/libimcv/plugins/imv_attestation/imv_attestation_state.c
src/libimcv/tcg/pts/pts.c
src/libimcv/tcg/pts/pts.h
src/libimcv/tcg/pts/pts_file_meas.c [new file with mode: 0644]
src/libimcv/tcg/pts/pts_file_meas.h [new file with mode: 0644]
src/libimcv/tcg/tcg_pts_attr_file_meas.c
src/libimcv/tcg/tcg_pts_attr_file_meas.h

index 133e824..12bb2ef 100644 (file)
@@ -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
index 937a7ec..cc91bcf 100644 (file)
@@ -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);
-                                       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
+                                       /* 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)
                                        {
-                                               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);
-                                               
+                                               /* 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_list->insert_last(attr_list, attr);
                                        break;
                                }
index ead3251..619c97c 100644 (file)
@@ -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;
-                                       
+                                       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)
+                                       {
+                                               break;
+                                       }
+
                                        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))
+                                       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 *hash_enumerator;
-                                               pts_meas_algorithms_t selected_algorithm;
-                                               char *product = "Ubuntu 11.4 i686";
+                                               enumerator_t *e;
                                                chunk_t db_measurement;
-                                               
-                                               DBG3(DBG_IMV, "Received measurement: %B", &meas_entry->measurement);
-                                               
-                                               if (!pts_db)
+
+                                               e = pts_db->create_meas_enumerator(pts_db,
+                                                                               platform_info, request_id, algo);
+                                               if (!e)
                                                {
+                                                       DBG1(DBG_IMV, "  database enumerator failed");
                                                        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)
+                                               if (!e->enumerate(e, &db_measurement))
                                                {
+                                                       DBG1(DBG_IMV, "  measurement for '%s' not found"
+                                                                                 " in database", filename);
+                                                       e->destroy(e);
                                                        break;
                                                }
-                                               while (hash_enumerator->enumerate(hash_enumerator, &db_measurement))
+                                               if (chunk_equals(db_measurement, measurement))
+                                               {
+                                                       DBG2(DBG_IMV, "  %#B for '%s' is ok",
+                                                                &measurement, filename);
+                                               }
+                                               else
                                                {
-                                                       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;
-                                                       }
+                                                       DBG1(DBG_IMV, " %#B for '%s' does not match %#B",
+                                                                &measurement, filename, &db_measurement);
+                                                       measurement_error = TRUE;
                                                }
-                                               hash_enumerator->destroy(hash_enumerator);
-                                               
+                                               e->destroy(e);
                                        }
-                                       
-                                       meas_enumerator->destroy(meas_enumerator);
+                                       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);
index cb343a1..bf21c0f 100644 (file)
@@ -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;
 }
index 5a15b3a..bd38922 100644 (file)
 #include <trousers/tss.h>
 #include <trousers/trousers.h>
 
-#include <dirent.h>
+#include <sys/stat.h>
 #include <errno.h>
 
-#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)
@@ -67,6 +66,11 @@ struct private_pts_t {
        pts_meas_algorithms_t algorithm;
 
        /**
+        * Platform and OS Info
+        */
+       char *platform_info;
+
+       /**
         * Do we have an activated TPM
         */
        bool has_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;
+               enumerator_t *enumerator;
+               char *rel_name, *abs_name;
+               struct stat st;
+
+               enumerator = enumerator_create_directory(pathname);
+               if (!enumerator)
+               {
+                       DBG1(DBG_IMC,"  directory '%s' can not be opened, %s", pathname,
+                                strerror(errno));
+                       hasher->destroy(hasher);
+                       measurements->destroy(measurements);
+                       return NULL;    
                }
-               snprintf(filename, BUF_LEN, "%s/%s", pathname, ent->d_name);
-               entry->filename = strdup(filename);
-                               
-               if (!hash_file(this, filename, &entry->measurement))
+               while (enumerator->enumerate(enumerator, &rel_name, &abs_name, &st))
                {
-                       DBG1(DBG_IMC, "Hashing the given file has failed");
-                       return FALSE;
+                       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);
+                       }       
                }
-               list->insert_last(list, entry);
+               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,
index f76ee8e..6b5d0c1 100644 (file)
@@ -25,21 +25,10 @@ typedef struct pts_t pts_t;
 
 #include "pts_proto_caps.h"
 #include "pts_meas_algo.h"
-#include <utils/linked_list.h>
-
+#include "pts_file_meas.h"
 
 #include <library.h>
 
-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)
  *
@@ -75,6 +64,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
         *
         * @param info                  chunk containing a TPM_CAP_VERSION_INFO struct
@@ -107,24 +110,17 @@ 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.
         */
        void (*destroy)(pts_t *this);
diff --git a/src/libimcv/tcg/pts/pts_file_meas.c b/src/libimcv/tcg/pts/pts_file_meas.c
new file mode 100644 (file)
index 0000000..cfd47cb
--- /dev/null
@@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "pts_file_meas.h"
+
+#include <utils/linked_list.h>
+
+typedef struct private_pts_file_meas_t private_pts_file_meas_t;
+
+/**
+ * Private data of a pts_file_meas_t object.
+ *
+ */
+struct private_pts_file_meas_t {
+
+       /**
+        * Public pts_file_meas_t interface.
+        */
+       pts_file_meas_t public;
+
+       /**
+        * ID of PTS File Measurement Request
+        */
+       u_int16_t request_id;
+
+       /**
+        * List of File Measurements
+        */
+       linked_list_t *list;
+};
+
+typedef struct entry_t entry_t;
+
+/**
+ * PTS File Measurement entry
+ */
+struct entry_t {
+       char    *filename;
+       chunk_t  measurement;
+};
+
+/**
+ * Free an entry_t object
+ */
+static void free_entry(entry_t *entry)
+{
+       if (entry)
+       {
+               free(entry->filename);
+               free(entry->measurement.ptr);
+               free(entry);
+       }
+}
+
+METHOD(pts_file_meas_t, get_request_id, u_int16_t,
+       private_pts_file_meas_t *this)
+{
+       return this->request_id;
+}
+
+METHOD(pts_file_meas_t, get_file_count, int,
+       private_pts_file_meas_t *this)
+{
+       return this->list->get_count(this->list);
+}
+
+METHOD(pts_file_meas_t, add, void,
+       private_pts_file_meas_t *this, char *filename, chunk_t measurement)
+{
+       entry_t *entry;
+
+       entry = malloc_thing(entry_t);
+       entry->filename = strdup(filename);
+       entry->measurement = chunk_clone(measurement);
+
+       this->list->insert_last(this->list, entry);
+}
+
+/**
+ * Enumerate file measurement entries
+ */
+static bool entry_filter(void *null, entry_t **entry, char **filename,
+                                                void *i2, chunk_t *measurement)
+{
+       *filename = (*entry)->filename;
+       *measurement = (*entry)->measurement;
+       return TRUE;
+}
+
+METHOD(pts_file_meas_t, create_enumerator, enumerator_t*,
+       private_pts_file_meas_t *this)
+{
+       return enumerator_create_filter(this->list->create_enumerator(this->list),
+                                                                  (void*)entry_filter, NULL, NULL);
+}
+
+METHOD(pts_file_meas_t, 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 (file)
index 0000000..63507b9
--- /dev/null
@@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts_file_meas pts_file_meas
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_FILE_MEAS_H_
+#define PTS_FILE_MEAS_H_
+
+#include <library.h>
+
+typedef struct pts_file_meas_t pts_file_meas_t;
+
+/**
+ * Class storing PTS File Measurements
+ */
+struct pts_file_meas_t {
+
+       /**
+        * Get the ID of the PTS File Measurement Request
+        *
+        * @return                              ID of PTS File Measurement Request
+        */
+       u_int16_t (*get_request_id)(pts_file_meas_t *this);
+
+       /**
+        * Get the number of measured files
+        *
+        * @return                              Number of measured files
+        */
+       int (*get_file_count)(pts_file_meas_t *this);
+
+       /**
+        * Add a PTS File Measurement
+        *
+        * @param filename              Name of measured file or directory
+        * @param measurement   PTS Measurement hash
+        */
+       void (*add)(pts_file_meas_t *this, char *filename, chunk_t measurement);
+
+       /**
+        * Create a PTS File Measurement enumerator
+        *
+        * @return                              Enumerator returning filename and measurement 
+        */
+       enumerator_t* (*create_enumerator)(pts_file_meas_t *this);
+
+       /**
+        * 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_ @}*/
index efeed7e..d2fcb54 100644 (file)
@@ -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
-        */
-       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
+        * PTS File Measurements
         */
-       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;
+       count = (sizeof(count) > 4) ? number_of_files << 32 : 0;
        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);
+       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 (reader->remaining(reader))
+       while (count--)
        {
-               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);
+               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,
-       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*,
+METHOD(tcg_pts_attr_file_meas_t, get_measurements, pts_file_meas_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;
index 90b6713..a28e9c1 100644 (file)
@@ -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