diff options
-rw-r--r-- | src/libpts/pts/components/ita/ita_comp_ima.c | 175 |
1 files changed, 111 insertions, 64 deletions
diff --git a/src/libpts/pts/components/ita/ita_comp_ima.c b/src/libpts/pts/components/ita/ita_comp_ima.c index e9c6b9dd0..2af276d2b 100644 --- a/src/libpts/pts/components/ita/ita_comp_ima.c +++ b/src/libpts/pts/components/ita/ita_comp_ima.c @@ -32,6 +32,7 @@ #define SECURITY_DIR "/sys/kernel/security/" #define IMA_BIOS_MEASUREMENTS SECURITY_DIR "tpm0/binary_bios_measurements" #define IMA_RUNTIME_MEASUREMENTS SECURITY_DIR "ima/binary_runtime_measurements" +#define IMA_EVENT_NAME_LEN_MAX 255 #define IMA_PCR 10 #define IMA_PCR_MAX 16 #define IMA_TYPE_LEN 3 @@ -44,7 +45,7 @@ typedef enum ima_state_t ima_state_t; enum ima_state_t { IMA_STATE_INIT, IMA_STATE_BIOS, - IMA_STATE_BIOS_AGGREGATE, + IMA_STATE_BOOT_AGGREGATE, IMA_STATE_RUNTIME, IMA_STATE_END }; @@ -355,14 +356,16 @@ static bool load_runtime_measurements(char *file, linked_list_t *list, * Extend measurement into PCR an create evidence */ pts_comp_evidence_t* extend_pcr(pts_ita_comp_ima_t* this, u_int32_t pcr, - size_t pcr_len, chunk_t measurement) + chunk_t measurement) { + size_t pcr_len; pts_pcr_transform_t pcr_transform; pts_meas_algorithms_t hash_algo; pts_comp_evidence_t *evidence; chunk_t pcr_before, pcr_after; hash_algo = PTS_MEAS_ALGO_SHA1; + pcr_len = HASH_SIZE_SHA1; pcr_transform = pts_meas_algo_to_pcr_transform(hash_algo, pcr_len); pcr_before = chunk_clone(this->pcrs[pcr]); this->hasher->get_hash(this->hasher, pcr_before, NULL); @@ -377,6 +380,35 @@ pts_comp_evidence_t* extend_pcr(pts_ita_comp_ima_t* this, u_int32_t pcr, return evidence; } +/** + * Compute and check boot aggregate value by hashing PCR0 to PCR7 + */ +void check_boot_aggregate(pts_ita_comp_ima_t *this, chunk_t measurement) +{ + u_int32_t pcr; + u_char pcr_buffer[HASH_SIZE_SHA1]; + u_char boot_aggregate_name[] = "boot_aggregate"; + u_char filename_buffer[IMA_EVENT_NAME_LEN_MAX + 1]; + chunk_t boot_aggregate, file_name; + + /* See Linux kernel header: security/integrity/ima/ima.h */ + boot_aggregate = chunk_create(pcr_buffer, sizeof(pcr_buffer)); + memset(filename_buffer, 0, sizeof(filename_buffer)); + strcpy(filename_buffer, boot_aggregate_name); + file_name = chunk_create(filename_buffer, sizeof(filename_buffer)); + + for (pcr = 0; pcr < 8; pcr++) + { + this->hasher->get_hash(this->hasher, this->pcrs[pcr], NULL); + } + this->hasher->get_hash(this->hasher, chunk_empty, pcr_buffer); + this->hasher->get_hash(this->hasher, boot_aggregate, NULL); + this->hasher->get_hash(this->hasher, file_name, pcr_buffer); + + DBG1(DBG_PTS, "boot aggregate value is %scorrect", + chunk_equals(boot_aggregate, measurement) ? "":"in"); +} + METHOD(pts_component_t, get_comp_func_name, pts_comp_func_name_t*, pts_ita_comp_ima_t *this) { @@ -420,8 +452,8 @@ METHOD(pts_component_t, measure, status_t, DBG1(DBG_PTS, "could not retrieve bios measurement entry"); return status; } - *evidence = extend_pcr(this, bios_entry->pcr, pts->get_pcr_len(pts), - bios_entry->measurement); + *evidence = extend_pcr(this, bios_entry->pcr, + bios_entry->measurement); free(bios_entry); /* break if still some BIOS measurements are left */ @@ -438,9 +470,9 @@ METHOD(pts_component_t, measure, status_t, } this->state = this->ima_list->get_count(this->ima_list) ? - IMA_STATE_BIOS_AGGREGATE : IMA_STATE_END; + IMA_STATE_BOOT_AGGREGATE : IMA_STATE_END; break; - case IMA_STATE_BIOS_AGGREGATE: + case IMA_STATE_BOOT_AGGREGATE: case IMA_STATE_RUNTIME: status = this->ima_list->remove_first(this->ima_list, (void**)&ima_entry); @@ -449,18 +481,18 @@ METHOD(pts_component_t, measure, status_t, DBG1(DBG_PTS, "could not retrieve ima measurement entry"); return status; } - *evidence = extend_pcr(this, IMA_PCR, pts->get_pcr_len(pts), - ima_entry->measurement); + *evidence = extend_pcr(this, IMA_PCR, ima_entry->measurement); + + if (this->state == IMA_STATE_BOOT_AGGREGATE) + { + check_boot_aggregate(this, ima_entry->measurement); + } /* TODO optionally send file measurements */ chunk_free(&ima_entry->file_measurement); chunk_free(&ima_entry->filename); free(ima_entry); - if (this->state == IMA_STATE_BIOS_AGGREGATE) - { - /* TODO check BIOS aggregate value */ - } this->state = this->ima_list->get_count(this->ima_list) ? IMA_STATE_RUNTIME : IMA_STATE_END; break; @@ -487,66 +519,81 @@ METHOD(pts_component_t, verify, status_t, measurement = evidence->get_measurement(evidence, &extended_pcr, &algo, &transform, &measurement_time); - if (!this->keyid.ptr) + switch (this->state) { - if (!pts->get_aik_keyid(pts, &this->keyid)) - { - return FAILED; - } - this->keyid = chunk_clone(this->keyid); - - if (!this->pts_db) - { - DBG1(DBG_PTS, "pts database not available"); - return FAILED; - } - status = this->pts_db->get_comp_measurement_count(this->pts_db, - this->name, this->keyid, algo, - &this->cid, &this->kid, &this->count); - if (status != SUCCESS) - { - return status; - } - vid = this->name->get_vendor_id(this->name); - name = this->name->get_name(this->name); - names = pts_components->get_comp_func_names(pts_components, vid); - - if (this->count) - { - DBG1(DBG_PTS, "checking %d %N '%N' functional component evidence " - "measurements", this->count, pen_names, vid, names, name); - } - else - { - DBG1(DBG_PTS, "registering %N '%N' functional component evidence " - "measurements", pen_names, vid, names, name); - this->is_registering = TRUE; - } - } + case IMA_STATE_INIT: + if (!pts->get_aik_keyid(pts, &this->keyid)) + { + return FAILED; + } + this->keyid = chunk_clone(this->keyid); - if (extended_pcr != IMA_PCR) - { - if (this->is_registering) - { - status = this->pts_db->insert_comp_measurement(this->pts_db, - measurement, this->cid, this->kid, - ++this->seq_no, extended_pcr, algo); - if (status != SUCCESS) + if (!this->pts_db) { - return status; + DBG1(DBG_PTS, "pts database not available"); + return FAILED; } - this->count = this->seq_no + 1; - } - else - { - status = this->pts_db->check_comp_measurement(this->pts_db, - measurement, this->cid, this->kid, - ++this->seq_no, extended_pcr, algo); + status = this->pts_db->get_comp_measurement_count(this->pts_db, + this->name, this->keyid, algo, + &this->cid, &this->kid, &this->count); if (status != SUCCESS) { return status; } - } + vid = this->name->get_vendor_id(this->name); + name = this->name->get_name(this->name); + names = pts_components->get_comp_func_names(pts_components, vid); + + if (this->count) + { + DBG1(DBG_PTS, "checking %d %N '%N' functional component " + "evidence measurements", this->count, pen_names, + vid, names, name); + } + else + { + DBG1(DBG_PTS, "registering %N '%N' functional component " + "evidence measurements", pen_names, vid, names, + name); + this->is_registering = TRUE; + } + this->state = IMA_STATE_BIOS; + /* fall through to next state */ + case IMA_STATE_BIOS: + if (extended_pcr != IMA_PCR) + { + if (this->is_registering) + { + status = this->pts_db->insert_comp_measurement(this->pts_db, + measurement, this->cid, this->kid, + ++this->seq_no, extended_pcr, algo); + if (status != SUCCESS) + { + return status; + } + this->count = this->seq_no + 1; + } + else + { + status = this->pts_db->check_comp_measurement(this->pts_db, + measurement, this->cid, this->kid, + ++this->seq_no, extended_pcr, algo); + if (status != SUCCESS) + { + return status; + } + } + break; + } + this->state = IMA_STATE_BOOT_AGGREGATE; + /* fall through to next state */ + case IMA_STATE_BOOT_AGGREGATE: + this->state = IMA_STATE_RUNTIME; + break; + case IMA_STATE_RUNTIME: + break; + case IMA_STATE_END: + break; } has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after); |