]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
libimcv: Evaluate IMA SHA-256 measurements
authorAndreas Steffen <andreas.steffen@strongswan.org>
Thu, 17 Dec 2020 11:14:23 +0000 (12:14 +0100)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Fri, 8 Jan 2021 10:00:15 +0000 (11:00 +0100)
conf/plugins/imc-attestation.opt
src/libimcv/pts/components/ita/ita_comp_ima.c
src/libimcv/pts/pts_ima_event_list.c
src/libimcv/pts/pts_ima_event_list.h

index 25435ac535c782693de0dfe00f18a8a4f0a01192..34fec0a7eaf3b3d9f64b4c37020693060d30055d 100644 (file)
@@ -47,3 +47,7 @@ libimcv.plugins.imc-attestation.pcr18_meas =
 
 libimcv.plugins.imc-attestation.pcr18_after =
        PCR18 value after measurement.
+
+libimcv.plugins.imc-attestation.pcr_padding = no
+       Whether to pad IMA SHA1 measurements values when extending into
+       SHA256 PCR bank.
index 703d2e16a362033ee3462b125fd70d94ca4d0ed2..752aa267ddce18fc0edc8c77e9de3473fadb69be 100644 (file)
@@ -29,7 +29,6 @@
 #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_FILENAME_LEN_MAX           255
 
 typedef struct pts_ita_comp_ima_t pts_ita_comp_ima_t;
 typedef enum ima_state_t ima_state_t;
@@ -118,6 +117,11 @@ struct pts_ita_comp_ima_t {
         */
        bool pcr_info;
 
+       /**
+        * Whether to pad PCR measurements if matching hash is not available
+        */
+       bool pcr_padding;
+
        /**
         * Creation time of measurement
         */
@@ -165,16 +169,15 @@ struct pts_ita_comp_ima_t {
  */
 static pts_comp_evidence_t* extend_pcr(pts_ita_comp_ima_t* this,
                                                                           uint8_t qualifier, pts_pcr_t *pcrs,
-                                                                          uint32_t pcr, chunk_t measurement)
+                                                                          uint32_t pcr, chunk_t measurement,
+                                                                          pts_pcr_transform_t pcr_transform)
 {
-       pts_pcr_transform_t pcr_transform;
        pts_meas_algorithms_t pcr_algo;
        pts_comp_func_name_t *name;
        pts_comp_evidence_t *evidence;
        chunk_t pcr_before = chunk_empty, pcr_after = chunk_empty;
 
        pcr_algo = pcrs->get_pcr_algo(pcrs);
-       pcr_transform = PTS_PCR_TRANSFORM_MATCH;
 
        if (this->pcr_info)
        {
@@ -199,115 +202,71 @@ static pts_comp_evidence_t* extend_pcr(pts_ita_comp_ima_t* this,
 }
 
 /**
- * Generate an IMA or IMA-NG hash from an event digest and event name
- *
- * @param digest               event digest
- * @param ima_algo             hash algorithm string ("sha1:", "sha256:", etc.)
- * @param ima_name             event name
- * @param little_endian        endianness of client platform
- * @param algo                 hash algorithm used by TPM
- * @param hash_buf             hash value to be compared with TPM measurement
+ * Compute and check boot aggregate value by hashing PCR0 to PCR7
  */
-static bool ima_hash(chunk_t digest, char *ima_algo, char *ima_name,
-                                        bool little_endian, pts_meas_algorithms_t algo,
-                                        char *hash_buf)
+static bool check_boot_aggregate(pts_pcr_t *pcrs, char *algo, bool pcr_padding,
+                                                                chunk_t boot_aggregate, chunk_t measurement)
+
 {
+       chunk_t ba_measurement;
+       uint8_t meas_buffer[HASH_SIZE_SHA512];
+       size_t hash_size;
+       pts_meas_algorithms_t pcr_algo;
        hash_algorithm_t hash_alg;
        hasher_t *hasher;
-       bool success;
-
-       hash_alg = pts_meas_algo_to_hash(algo);
-       hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
-       if (!hasher)
-       {
-               DBG1(DBG_PTS, "%N hasher could not be created",
-                        hash_algorithm_short_names, hash_alg);
-               return FALSE;
-       }
+       uint32_t i, pcr_max;
+       bool success, pcr_ok = TRUE;
 
-       if (ima_algo)
-       {
-               uint32_t d_len, n_len;
-               chunk_t algo_name, event_name, digest_len, name_len;
-
-               /* IMA-NG hash */
-               algo_name  = chunk_create(ima_algo, strlen(ima_algo) + 1);
-               event_name = chunk_create(ima_name, strlen(ima_name) + 1);
-
-               d_len = algo_name.len + digest.len;
-               digest_len = chunk_create((uint8_t*)&d_len, sizeof(d_len));
-               /* TODO handle endianness of both client and server platforms */
-
-               n_len = event_name.len;
-               name_len = chunk_create((uint8_t*)&n_len, sizeof(n_len));
-               /* TODO handle endianness of both client and server platforms */
-
-               success = hasher->get_hash(hasher, digest_len, NULL) &&
-                                 hasher->get_hash(hasher, algo_name, NULL) &&
-                                 hasher->get_hash(hasher, digest, NULL) &&
-                                 hasher->get_hash(hasher, name_len, NULL) &&
-                                 hasher->get_hash(hasher, event_name, hash_buf);
-       }
-       else
+       /* determine PCR hash algorithm and the need for PCR padding */
+       pcr_algo = pcrs->get_pcr_algo(pcrs);
+       if (pcr_algo == PTS_MEAS_ALGO_SHA1)
        {
-               u_char filename_buffer[IMA_FILENAME_LEN_MAX + 1];
-               chunk_t file_name;
-
-               /* IMA legacy hash */
-               memset(filename_buffer, 0, sizeof(filename_buffer));
-               strncpy(filename_buffer, ima_name, IMA_FILENAME_LEN_MAX);
-               file_name = chunk_create (filename_buffer, sizeof(filename_buffer));
-
-               success = hasher->get_hash(hasher, digest, NULL) &&
-                                 hasher->get_hash(hasher, file_name, hash_buf);
+               pcr_padding = FALSE;
        }
-       hasher->destroy(hasher);
-
-       return success;
-}
 
-/**
- * Compute and check boot aggregate value by hashing PCR0 to PCR7
- */
-static bool check_boot_aggregate(pts_pcr_t *pcrs, chunk_t measurement,
-                                                                char *algo)
-{
-       u_char pcr_buffer[HASH_SIZE_SHA1];
-       chunk_t boot_aggregate;
-       hasher_t *hasher;
-       uint32_t i;
-       bool success, pcr_ok = TRUE;
 
-       hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
+       /* create hasher for boot aggregate computation */
+       hash_alg = pts_meas_algo_to_hash(pcr_algo);
+       hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
        if (!hasher)
        {
                DBG1(DBG_PTS, "%N hasher could not be created",
-                        hash_algorithm_short_names, HASH_SHA1);
+                        hash_algorithm_short_names, hash_alg);
                return FALSE;
        }
-       for (i = 0; i < 8 && pcr_ok; i++)
+       hash_size = hasher->get_hash_size(hasher);
+
+       /* Include PCR8 and PCR9 in boot aggregate with unpadded non-SHA1 hashes */
+       pcr_max = (pcr_algo == PTS_MEAS_ALGO_SHA1 || pcr_padding) ? 7 : 9;
+
+       /* the boot aggregate hash is computed over PCR0 .. PCR7/PCR9 */
+       for (i = 0; i <= pcr_max && pcr_ok; i++)
        {
                pcr_ok = hasher->get_hash(hasher, pcrs->get(pcrs, i), NULL);
        }
        if (pcr_ok)
        {
-               pcr_ok = hasher->get_hash(hasher, chunk_empty, pcr_buffer);
+               pcr_ok = hasher->get_hash(hasher, chunk_empty, boot_aggregate.ptr);
        }
        hasher->destroy(hasher);
 
+
        if (pcr_ok)
        {
-               boot_aggregate = chunk_create(pcr_buffer, sizeof(pcr_buffer));
-
-               /* TODO handle endianness of client platform */
-               pcr_ok = ima_hash(boot_aggregate, algo, "boot_aggregate",
-                                                 TRUE, PTS_MEAS_ALGO_SHA1, pcr_buffer);
+               ba_measurement = chunk_create(meas_buffer, hash_size);
+               if (pcr_padding)
+               {
+                       memset(meas_buffer, 0x00, hash_size);
+                       pcr_algo = PTS_MEAS_ALGO_SHA1;
+               }
+               pcr_ok = pts_ima_event_hash(boot_aggregate, algo, "boot_aggregate",
+                                                                       pcr_algo, meas_buffer);
        }
        if (pcr_ok)
        {
-               success = chunk_equals_const(boot_aggregate, measurement);
-               DBG1(DBG_PTS, "boot aggregate value is %scorrect",
-                                          success ? "":"in");
+               success = chunk_equals_const(ba_measurement, measurement);
+               DBG1(DBG_PTS, "boot aggregate computed over PCR0..PCR%d is %scorrect",
+                                          pcr_max, success ? "":"in");
                return success;
        }
        else
@@ -340,9 +299,11 @@ METHOD(pts_component_t, measure, status_t,
        pts_comp_evidence_t **evidence)
 {
        pts_pcr_t *pcrs;
+       pts_meas_algorithms_t pcr_algo;
        pts_comp_evidence_t *evid = NULL;
-       size_t algo_len, name_len;
-       chunk_t measurement;
+       size_t algo_len, name_len, pcr_size;
+       chunk_t measurement, boot_aggregate;
+       uint8_t pcr_buffer[HASH_SIZE_SHA512];
        char *uri, *algo, *name;
        uint32_t pcr;
        status_t status;
@@ -352,6 +313,8 @@ METHOD(pts_component_t, measure, status_t,
        {
                return FAILED;
        }
+       pcr_algo = pcrs->get_pcr_algo(pcrs);
+       pcr_size = pts_meas_algo_hash_size(pcr_algo);
 
        if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
                                          PTS_ITA_QUALIFIER_TYPE_TRUSTED))
@@ -360,8 +323,7 @@ METHOD(pts_component_t, measure, status_t,
                {
                        case IMA_STATE_INIT:
                                this->bios_list = pts_ima_bios_list_create(pts->get_tpm(pts),
-                                                                                                       IMA_BIOS_MEASUREMENTS,
-                                                                                                       pcrs->get_pcr_algo(pcrs));
+                                                                                       IMA_BIOS_MEASUREMENTS, pcr_algo);
                                if (!this->bios_list)
                                {
                                        return FAILED;
@@ -378,7 +340,8 @@ METHOD(pts_component_t, measure, status_t,
                                        DBG1(DBG_PTS, "could not retrieve bios measurement entry");
                                        return status;
                                }
-                               evid = extend_pcr(this, qualifier, pcrs, pcr, measurement);
+                               evid = extend_pcr(this, qualifier, pcrs, pcr, measurement,
+                                                                               PTS_PCR_TRANSFORM_MATCH);
 
                                this->state = this->bios_list->get_count(this->bios_list) ?
                                                                                IMA_STATE_BIOS : IMA_STATE_INIT;
@@ -393,8 +356,16 @@ METHOD(pts_component_t, measure, status_t,
                switch (this->state)
                {
                        case IMA_STATE_INIT:
+
+                               /* disable padding for SHA1 legacy hash */
+                               if (pcr_algo == PTS_MEAS_ALGO_SHA1)
+                               {
+                                       this->pcr_padding = FALSE;
+                               }
+
                                this->ima_list = pts_ima_event_list_create(
-                                                                                               IMA_RUNTIME_MEASUREMENTS);
+                                                                               IMA_RUNTIME_MEASUREMENTS,
+                                                                               pcr_algo, this->pcr_padding);
                                if (!this->ima_list)
                                {
                                        return FAILED;
@@ -414,13 +385,17 @@ METHOD(pts_component_t, measure, status_t,
                                }
                                if (this->state == IMA_STATE_BOOT_AGGREGATE && this->bios_count)
                                {
-                                       if (!check_boot_aggregate(pcrs, measurement, algo))
+                                       boot_aggregate = chunk_create(pcr_buffer, pcr_size);
+                                       if (!check_boot_aggregate(pcrs, algo, this->pcr_padding,
+                                                                                         boot_aggregate, measurement))
                                        {
                                                return FAILED;
                                        }
                                }
-                               evid = extend_pcr(this, qualifier, pcrs, IMA_PCR,
-                                                                 measurement);
+
+                               evid = extend_pcr(this, qualifier, pcrs, IMA_PCR, measurement,
+                                                                 this->pcr_padding ? PTS_PCR_TRANSFORM_SHORT :
+                                                                                                         PTS_PCR_TRANSFORM_MATCH);
                                if (evid)
                                {
                                        if (algo)
@@ -528,7 +503,8 @@ METHOD(pts_component_t, verify, status_t,
 {
        bool has_pcr_info;
        uint32_t pcr;
-       pts_meas_algorithms_t algo;
+       size_t pcr_size;
+       pts_meas_algorithms_t algo, pcr_algo;
        pts_pcr_transform_t transform;
        pts_pcr_t *pcrs;
        time_t creation_time;
@@ -536,13 +512,25 @@ METHOD(pts_component_t, verify, status_t,
        status_t status = NOT_FOUND;
 
        this->aik_id = pts->get_aik_id(pts);
+
+
        pcrs = pts->get_pcrs(pts);
        if (!pcrs)
        {
                return FAILED;
        }
+       pcr_algo = pcrs->get_pcr_algo(pcrs);
+       pcr_size = pts_meas_algo_hash_size(pcr_algo);
+
        measurement = evidence->get_measurement(evidence, &pcr, &algo, &transform,
                                                                                        &creation_time);
+       if (algo != pcr_algo)
+       {
+               DBG1(DBG_PTS, "received %N measurement hash but PCR bank is %N",
+                        pts_meas_algorithm_names, algo, pts_meas_algorithm_names, algo);
+               return FAILED;
+       }
+       this->pcr_padding = (transform == PTS_PCR_TRANSFORM_SHORT);
 
        if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
                                          PTS_ITA_QUALIFIER_TYPE_TRUSTED))
@@ -606,6 +594,8 @@ METHOD(pts_component_t, verify, status_t,
                int ima_count;
                char *ima_algo, *ima_name;
                char algo_buf[IMA_ALGO_LEN_MAX];
+               uint8_t pcr_buffer[HASH_SIZE_SHA512];
+               chunk_t boot_aggregate;
                pts_meas_algorithms_t hash_algo;
 
                hash_algo = parse_validation_uri(evidence, &ima_name, &ima_algo,
@@ -622,15 +612,17 @@ METHOD(pts_component_t, verify, status_t,
                                                                  "but is '%s'", ima_name);
                                        return FAILED;
                                }
-                               if (hash_algo != PTS_MEAS_ALGO_SHA1)
+                               if (hash_algo != pcr_algo)
                                {
                                        DBG1(DBG_PTS, "ima: boot_aggregate algorithm must be %N "
                                                                  "but is %N",
-                                                                  pts_meas_algorithm_names, PTS_MEAS_ALGO_SHA1,
+                                                                  pts_meas_algorithm_names, pcr_algo,
                                                                   pts_meas_algorithm_names, hash_algo);
                                        return FAILED;
                                }
-                               if (!check_boot_aggregate(pcrs, measurement, ima_algo))
+                               boot_aggregate = chunk_create(pcr_buffer, pcr_size);
+                               if (!check_boot_aggregate(pcrs, ima_algo, this->pcr_padding,
+                                                                                 boot_aggregate, measurement))
                                {
                                        return FAILED;
                                }
@@ -652,8 +644,8 @@ METHOD(pts_component_t, verify, status_t,
                                        DBG1(DBG_PTS, "checking boot aggregate evidence "
                                                                  "measurement");
                                        status = this->pts_db->check_comp_measurement(this->pts_db,
-                                                                                                       measurement, this->ima_cid,
-                                                                                                       this->aik_id, 1, pcr, algo);
+                                                                                               boot_aggregate, this->ima_cid,
+                                                                                               this->aik_id, 1, pcr, algo);
                                }
                                else
                                {
@@ -661,8 +653,8 @@ METHOD(pts_component_t, verify, status_t,
                                                                  "measurement");
                                        this->is_ima_registering = TRUE;
                                        status = this->pts_db->insert_comp_measurement(this->pts_db,
-                                                                                                       measurement, this->ima_cid,
-                                                                                                       this->aik_id, 1, pcr, algo);
+                                                                                               boot_aggregate, this->ima_cid,
+                                                                                               this->aik_id, 1, pcr, algo);
                                }
                                this->state = IMA_STATE_RUNTIME;
 
@@ -673,20 +665,33 @@ METHOD(pts_component_t, verify, status_t,
                                break;
                        case IMA_STATE_RUNTIME:
                        {
-                               uint8_t hash_buf[HASH_SIZE_SHA512];
-                               uint8_t digest_buf[HASH_SIZE_SHA512], *hex_digest_buf;
                                chunk_t hex_digest, digest, hash;
+                               uint8_t digest_buf[HASH_SIZE_SHA512], *hex_digest_buf;
+                               uint8_t hash_buf[HASH_SIZE_SHA512];
+                               size_t hash_size;
+                               pts_meas_algorithms_t meas_algo;
                                enumerator_t *e;
 
                                this->count++;
                                if (evidence->get_validation(evidence, NULL) !=
-                                       PTS_COMP_EVID_VALIDATION_PASSED)
+                                                       PTS_COMP_EVID_VALIDATION_PASSED)
                                {
                                        DBG1(DBG_PTS, "evidence validation failed");
                                        this->count_failed++;
                                        return FAILED;
                                }
-                               hash = chunk_create(hash_buf, pts_meas_algo_hash_size(algo));
+                               hash_size = pts_meas_algo_hash_size(algo);
+                               hash = chunk_create(hash_buf, hash_size);
+
+                               if (this->pcr_padding)
+                               {
+                                       memset(hash_buf, 0x00, hash_size);
+                                       meas_algo = PTS_MEAS_ALGO_SHA1;
+                               }
+                               else
+                               {
+                                       meas_algo = algo;
+                               }
 
                                e = this->pts_db->create_file_meas_enumerator(this->pts_db,
                                                                                                pts->get_platform_id(pts),
@@ -697,8 +702,9 @@ METHOD(pts_component_t, verify, status_t,
                                        {
                                                hex_digest = chunk_from_str(hex_digest_buf);
                                                digest = chunk_from_hex(hex_digest, digest_buf);
-                                               if (!ima_hash(digest, ima_algo, ima_name,
-                                                                         FALSE, algo, hash_buf))
+
+                                               if (!pts_ima_event_hash(digest, ima_algo, ima_name,
+                                                                                               meas_algo, hash_buf))
                                                {
                                                        status = FAILED;
                                                        break;
@@ -916,6 +922,8 @@ pts_component_t *pts_ita_comp_ima_create(uint32_t depth,
                .pts_db = pts_db,
                .pcr_info = lib->settings->get_bool(lib->settings,
                                                "%s.plugins.imc-attestation.pcr_info", FALSE, lib->ns),
+               .pcr_padding = lib->settings->get_bool(lib->settings,
+                                               "%s.plugins.imc-attestation.pcr_padding", FALSE, lib->ns),
                .ref = 1,
        );
 
index 9bff4654b8fe35dc257476dc0cfd262260b51fb4..f361f2f94d31e70f86c1be2122ec145552cd2cb3 100644 (file)
@@ -31,6 +31,9 @@ typedef struct event_entry_t event_entry_t;
 #define IMA_NG_TYPE_LEN                                6
 #define IMA_TYPE_LEN_MAX                       10
 #define IMA_ALGO_DIGEST_LEN_MAX                IMA_ALGO_LEN_MAX + HASH_SIZE_SHA512
+#define IMA_FILENAME_LEN_MAX           255
+
+
 
 /**
  * Private data of a pts_ima_event_list_t object.
@@ -61,7 +64,7 @@ struct private_pts_ima_event_list_t {
 struct event_entry_t {
 
        /**
-        * SHA1 measurement hash
+        * Special IMA measurement hash
         */
        chunk_t measurement;
 
@@ -125,11 +128,14 @@ METHOD(pts_ima_event_list_t, destroy, void,
 /**
  * See header
  */
-pts_ima_event_list_t* pts_ima_event_list_create(char *file)
+pts_ima_event_list_t* pts_ima_event_list_create(char *file,
+                                                       pts_meas_algorithms_t pcr_algo, bool pcr_padding)
 {
        private_pts_ima_event_list_t *this;
        event_entry_t *entry;
+       chunk_t digest;
        uint32_t pcr, type_len, name_len, eventdata_len, algo_digest_len, algo_len;
+       size_t hash_size;
        char type[IMA_TYPE_LEN_MAX];
        char algo_digest[IMA_ALGO_DIGEST_LEN_MAX];
        char *pos, *error = "";
@@ -164,6 +170,8 @@ pts_ima_event_list_t* pts_ima_event_list_create(char *file)
                .list = linked_list_create(),
        );
 
+       hash_size = pts_meas_algo_hash_size(pcr_algo);
+
        while (TRUE)
        {
                /* read 32 bit PCR number in host order */
@@ -175,12 +183,13 @@ pts_ima_event_list_t* pts_ima_event_list_create(char *file)
                        DBG2(DBG_PTS, "loaded ima measurements '%s' (%d entries)",
                                 file, this->list->get_count(this->list));
                        close(fd);
+
                        return &this->public;
                }
 
                /* create and initialize new IMA entry */
                entry = malloc_thing(event_entry_t);
-               entry->measurement = chunk_alloc(HASH_SIZE_SHA1);
+               entry->measurement = chunk_alloc(hash_size);
                entry->algo = NULL;
                entry->name = NULL;
 
@@ -190,7 +199,12 @@ pts_ima_event_list_t* pts_ima_event_list_create(char *file)
                        break;
                }
 
-               /* read 20 byte SHA-1 measurement digest */
+               if (pcr_padding)
+               {
+                       memset(entry->measurement.ptr, 0x00, hash_size);
+               }
+
+               /* read 20 byte SHA-1 IMA measurement digest */
                if (read(fd, entry->measurement.ptr, HASH_SIZE_SHA1) != HASH_SIZE_SHA1)
                {
                        error = "invalid SHA-1 digest field";
@@ -271,6 +285,9 @@ pts_ima_event_list_t* pts_ima_event_list_create(char *file)
                        entry->algo = malloc(algo_len);
                        memcpy(entry->algo, algo_digest, algo_len);
 
+                       /* extract the digest */
+                       digest = chunk_create(pos + 1, algo_digest_len - algo_len);
+
                        /* read the 32 bit length of the event name in host order */
                        if (read(fd, &name_len, 4) != 4 ||
                                eventdata_len != 4 + algo_digest_len + 4 + name_len)
@@ -288,6 +305,17 @@ pts_ima_event_list_t* pts_ima_event_list_create(char *file)
                                error = "invalid filename field";
                                break;
                        }
+
+                       /* re-compute IMA measurement digest for non-SHA1 hash algorithms */
+                       if (pcr_algo != PTS_MEAS_ALGO_SHA1 && !pcr_padding)
+                       {
+                               if (!pts_ima_event_hash(digest, entry->algo, entry->name,
+                                                                               pcr_algo, entry->measurement.ptr))
+                               {
+                                       break;
+                               }
+
+                       }
                }
                else
                {
@@ -328,3 +356,61 @@ pts_ima_event_list_t* pts_ima_event_list_create(char *file)
 
        return NULL;
 }
+
+/**
+ * See header
+ */
+bool pts_ima_event_hash(chunk_t digest, char *ima_algo, char *ima_name,
+                                               pts_meas_algorithms_t pcr_algo, char *hash_buf)
+{
+       hash_algorithm_t hash_alg;
+       hasher_t *hasher;
+       bool success;
+
+       hash_alg = pts_meas_algo_to_hash(pcr_algo);
+       hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
+       if (!hasher)
+       {
+               DBG1(DBG_PTS, "%N hasher could not be created",
+                        hash_algorithm_short_names, hash_alg);
+               return FALSE;
+       }
+
+       if (ima_algo)
+       {
+               uint32_t ad_len, n_len;
+               chunk_t algo_name, event_name, algo_digest_len, name_len;
+
+               /* IMA-NG hash */
+               algo_name  = chunk_create(ima_algo, strlen(ima_algo) + 1);
+               event_name = chunk_create(ima_name, strlen(ima_name) + 1);
+
+               ad_len = htole32(algo_name.len + digest.len);
+               algo_digest_len = chunk_create((uint8_t*)&ad_len, sizeof(ad_len));
+
+               n_len = htole32(event_name.len);
+               name_len = chunk_create((uint8_t*)&n_len, sizeof(n_len));
+
+               success = hasher->get_hash(hasher, algo_digest_len, NULL) &&
+                                 hasher->get_hash(hasher, algo_name, NULL) &&
+                                 hasher->get_hash(hasher, digest, NULL) &&
+                                 hasher->get_hash(hasher, name_len, NULL) &&
+                                 hasher->get_hash(hasher, event_name, hash_buf);
+       }
+       else
+       {
+               u_char filename_buffer[IMA_FILENAME_LEN_MAX + 1];
+               chunk_t file_name;
+
+               /* IMA legacy hash */
+               memset(filename_buffer, 0, sizeof(filename_buffer));
+               strncpy(filename_buffer, ima_name, IMA_FILENAME_LEN_MAX);
+               file_name = chunk_create (filename_buffer, sizeof(filename_buffer));
+
+               success = hasher->get_hash(hasher, digest, NULL) &&
+                                 hasher->get_hash(hasher, file_name, hash_buf);
+       }
+       hasher->destroy(hasher);
+
+       return success;
+}
index bab2e958622d4d1d2f57065bd3d4ccc9d102d71c..e793c63e26e39e52a9fb76bbd68ec394db3e47f6 100644 (file)
@@ -21,6 +21,8 @@
 #ifndef PTS_IMA_EVENT_LIST_H_
 #define PTS_IMA_EVENT_LIST_H_
 
+#include "pts_meas_algo.h"
+
 #include <time.h>
 
 #include <library.h>
@@ -56,7 +58,7 @@ struct pts_ima_event_list_t {
         * Get the next file measurement and remove it from the list
         *
         * @param measurement   Measurement hash
-        * @param algo                  Algorithm used to hash files
+        * @param algo                  Algorithm used to compute file digests
         " @param name                  Event name (absolute filename or boot_aggregate)
         * @return                              Return code
         */
@@ -74,7 +76,23 @@ struct pts_ima_event_list_t {
  * Create a PTS IMA runtime file measurement object
  *
  * @param file                         Pathname pointing to the IMA runtime measurements
+ * @param pcr_algo                     PCR hash measurement algorithm to be used
+ * @param pcr_padding          Apply PCR hash padding if hash algorithm is lacking
+ */
+pts_ima_event_list_t* pts_ima_event_list_create(char *file,
+                                                       pts_meas_algorithms_t pcr_algo, bool pcr_padding);
+
+/**
+ * Generate an IMA or IMA-NG hash from an event digest and event name
+ *
+ * @param digest               event digest
+ * @param ima_algo             event digest algorithm string ("sha1:", "sha256:", etc.)
+ * @param ima_name             event name
+ * @param pcr_algo             hash algorithm used by TPM PCR extension
+ * @param hash_buf             hash value to be compared with TPM measurement
+ * @return                             TRUE if computation successful
  */
-pts_ima_event_list_t* pts_ima_event_list_create(char *file);
+bool pts_ima_event_hash(chunk_t digest, char *ima_algo, char *ima_name,
+                                               pts_meas_algorithms_t pcr_algo, char *hash_buf);
 
 #endif /** PTS_IMA_EVENT_LIST_H_ @}*/