diff --git a/src/libimcv/plugins/imc_attestation/imc_attestation.c b/src/libimcv/plugins/imc_attestation/imc_attestation.c index 3747f38a8..331e4d953 100644 --- a/src/libimcv/plugins/imc_attestation/imc_attestation.c +++ b/src/libimcv/plugins/imc_attestation/imc_attestation.c @@ -33,10 +33,14 @@ #include #include #include +#include +#include +#include #include #include + /* IMC definitions */ static const char imc_name[] = "Attestation"; @@ -60,7 +64,23 @@ static pts_meas_algorithms_t selected_algorithm = PTS_MEAS_ALGO_SHA256; /** * List of files and directories to measure */ -static linked_list_t *files, *directories; +static linked_list_t *file_list, *directory_list; + +/** + * List of file measurements + */ +static linked_list_t *file_measurements; + +/* TODO: Move the struct to some header file? Duplicate with imv_attestation*/ +/** + * Struct to hold file or directory name with the request ID for Request File Measurement attribute + */ +typedef struct measurement_req_entry_t measurement_req_entry_t; + +struct measurement_req_entry_t { + char *path; + u_int16_t request_id; +}; /** * see section 3.7.1 of TCG TNC IF-IMC Specification 1.2 @@ -162,7 +182,7 @@ static TSS_RESULT get_tpm_version_info(BYTE *tpm_version_info) /** * Get Hash Measurement of a file */ -static TNC_Result hash_file(char *path, unsigned char *out) +static TNC_Result hash_file(char *path, char *out) { BYTE buffer[IMC_ATTESTATION_BUF_SIZE]; FILE *file; @@ -205,6 +225,46 @@ static TNC_Result hash_file(char *path, unsigned char *out) return TNC_RESULT_SUCCESS; } +/** + * Get all the files in a directory + */ +static TNC_Result hash_directory(char *path) +{ + DIR *dir; + struct dirent *ent; + linked_list_t *file_measurements; + file_meas_entry_t *entry; + + file_measurements = linked_list_create(); + entry = malloc_thing(file_meas_entry_t); + + dir = opendir(path); + if (dir == NULL) + { + DBG1(DBG_IMC, "opening directory '%s' failed: %s", path, strerror(errno)); + return TNC_RESULT_FATAL; + } + while ((ent = readdir(dir))) + { + char *file_hash; + + if(hash_file(ent->d_name,file_hash) != TNC_RESULT_SUCCESS) + { + DBG1(DBG_IMC, "Hashing the given file has failed"); + return TNC_RESULT_FATAL; + } + + entry->measurement = chunk_create(file_hash,strlen(file_hash)); + entry->file_name_len = strlen(ent->d_name); + entry->file_name = chunk_create(ent->d_name,strlen(ent->d_name)); + + file_measurements->insert_last(file_measurements,entry); + } + closedir(dir); + + return TNC_RESULT_SUCCESS; +} + static TNC_Result send_message(TNC_ConnectionID connection_id) { pa_tnc_msg_t *msg; @@ -233,11 +293,7 @@ static TNC_Result send_message(TNC_ConnectionID connection_id) } case IMC_ATTESTATION_STATE_REQ_MEAS_ALGO: { - pts_meas_algorithms_t algorithm; - algorithm = PTS_MEAS_ALGO_SHA1; - /* Save the selected algorithm for further attributes creation */ - selected_algorithm = algorithm; - attr = tcg_pts_attr_meas_algo_create(algorithm, TRUE); + attr = tcg_pts_attr_meas_algo_create(selected_algorithm, TRUE); break; } case IMC_ATTESTATION_STATE_GET_TPM_INFO: @@ -256,34 +312,88 @@ static TNC_Result send_message(TNC_ConnectionID connection_id) strlen(tpm_version_info))); break; } - /* TODO: working on */ - /*case IMC_ATTESTATION_STATE_REQ_FILE_MEAS: + case IMC_ATTESTATION_STATE_REQ_FILE_MEAS: { - enumerator_t *enumerator; measurement_req_entry_t *entry; + enumerator_t *enumerator; + tcg_pts_attr_file_meas_t *attr_file_meas; + u_int16_t 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_SHA512; + } + + msg = pa_tnc_msg_create(); + + /** + * Hash the files and add them as attribute + */ enumerator = enumerator_create_single(file_list, NULL); while (enumerator->enumerate(enumerator, &entry)) { - attr = tcg_pts_attr_req_file_meas_create(false, - entry.request_id, delimiter, - chunk_create(entry.path,strlen(entry.path))); + char * file_hash; + + attr = tcg_pts_attr_file_meas_create(1, + entry->request_id, meas_len); attr->set_noskip_flag(attr, TRUE); + attr_file_meas = (tcg_pts_attr_file_meas_t*)attr; + + if(hash_file(entry->path,file_hash) != TNC_RESULT_SUCCESS) + { + DBG1(DBG_IMC, "Hashing the given file has failed"); + return TNC_RESULT_FATAL; + } + attr_file_meas->add_file_meas(attr_file_meas, + chunk_create(file_hash,strlen(file_hash)), + chunk_create(entry->path,strlen(entry->path))); + msg->add_attribute(msg, attr); } - enumerator = enumerator_create_single(file_list, NULL); + /** + * Hash the files in each directory and add them as attribute + */ + enumerator = enumerator_create_single(directory_list, NULL); while (enumerator->enumerate(enumerator, &entry)) { - attr = tcg_pts_attr_req_file_meas_create(false, - entry.request_id, delimiter, - chunk_create(entry.path,strlen(entry.path))); + enumerator_t *meas_enumerator; + file_meas_entry_t *meas_entry; + u_int64_t num_of_files = 0 ; + + if(hash_directory(entry->path) != TNC_RESULT_SUCCESS) + { + DBG1(DBG_IMC, "Hashing the files in a given directory has failed"); + return TNC_RESULT_FATAL; + } + + attr = tcg_pts_attr_file_meas_create(0, + entry->request_id, meas_len); attr->set_noskip_flag(attr, TRUE); + attr_file_meas = (tcg_pts_attr_file_meas_t*)attr; + + meas_enumerator = enumerator_create_single(file_measurements, NULL); + while (meas_enumerator->enumerate(meas_enumerator, &meas_entry)) + { + num_of_files++; + attr_file_meas->add_file_meas(attr_file_meas, + meas_entry->measurement, + meas_entry->file_name); + } + + attr_file_meas->set_number_of_files(attr_file_meas, + num_of_files); msg->add_attribute(msg, attr); } - break; - }*/ + enumerator->destroy(enumerator); + goto end; + } case IMC_ATTESTATION_STATE_GET_AIK: + /* TODO: Implement AIK retrieve */ case IMC_ATTESTATION_STATE_REQ_FUNCT_COMP_EVID: case IMC_ATTESTATION_STATE_GEN_ATTEST_EVID: case IMC_ATTESTATION_STATE_REQ_FILE_METADATA: @@ -300,6 +410,8 @@ static TNC_Result send_message(TNC_ConnectionID connection_id) attr->set_noskip_flag(attr, TRUE); msg = pa_tnc_msg_create(); msg->add_attribute(msg, attr); + +end: msg->build(msg); result = imc_attestation->send_message(imc_attestation, connection_id, msg->get_encoding(msg)); @@ -397,6 +509,8 @@ TNC_Result TNC_IMC_ReceiveMessage(TNC_IMCID imc_id, case TCG_PTS_REQ_PROTO_CAPS: break; case TCG_PTS_MEAS_ALGO: + /* TODO: save the selected algorithm here */ + //selected_algorithm = break; case TCG_PTS_GET_TPM_VERSION_INFO: break; diff --git a/src/libimcv/plugins/imv_attestation/imv_attestation.c b/src/libimcv/plugins/imv_attestation/imv_attestation.c index 2a375698f..884048198 100644 --- a/src/libimcv/plugins/imv_attestation/imv_attestation.c +++ b/src/libimcv/plugins/imv_attestation/imv_attestation.c @@ -68,6 +68,7 @@ static linked_list_t *file_list, *directory_list; */ static u_int16_t request_id_counter = 0; +/* TODO: Move the struct to some header file? Duplicate with imc_attestation*/ /** * Struct to hold file or directory name with the request ID for Request File Measurement attribute */ @@ -166,7 +167,8 @@ TNC_Result TNC_IMV_NotifyConnectionChange(TNC_IMVID imv_id, state->change_state(state, new_state); attestation_state = (imv_attestation_state_t*)state; - /** Get the files to measure for + /** + * Get the files to measure for * PTS Request File Measurement attribute */ @@ -187,7 +189,8 @@ TNC_Result TNC_IMV_NotifyConnectionChange(TNC_IMVID imv_id, request_id_counter ++; } - /** Get the directories to measure for + /** + * Get the directories to measure for * PTS Request File Measurement attribute */ @@ -309,8 +312,8 @@ static TNC_Result send_message(TNC_ConnectionID connection_id) return TNC_RESULT_FATAL; } - attr->set_noskip_flag(attr, TRUE); msg = pa_tnc_msg_create(); + attr->set_noskip_flag(attr, TRUE); msg->add_attribute(msg, attr); end: