moved all shadow PCR stuff to the pts_pcr class
authorAndreas Steffen <andreas.steffen@strongswan.org>
Sat, 21 Jul 2012 13:56:39 +0000 (15:56 +0200)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Sat, 21 Jul 2012 13:58:13 +0000 (15:58 +0200)
src/libpts/plugins/imc_attestation/imc_attestation_process.c
src/libpts/pts/components/ita/ita_comp_ima.c
src/libpts/pts/components/ita/ita_comp_tboot.c
src/libpts/pts/components/ita/ita_comp_tgrub.c
src/libpts/pts/pts.c
src/libpts/pts/pts.h
src/libpts/pts/pts_pcr.c
src/libpts/pts/pts_pcr.h

index edaaa57..5ba9f87 100644 (file)
@@ -420,9 +420,6 @@ bool imc_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list,
                        /* Send buffered Simple Component Evidences */
                        while (attestation_state->next_evidence(attestation_state, &evid))
                        {
-                               pts->select_pcr(pts, evid->get_extended_pcr(evid));
-
-                               /* Send Simple Component Evidence */
                                attr = tcg_pts_attr_simple_comp_evid_create(evid);
                                attr_list->insert_last(attr_list, attr);
                        }
index b687c0f..d57fe6a 100644 (file)
@@ -122,11 +122,6 @@ struct pts_ita_comp_ima_t {
        linked_list_t *ima_list;
 
        /**
-        * Shadow PCR set
-        */
-       pts_pcr_t *pcrs;
-
-       /**
         * Whether to send pcr_before and pcr_after info
         */
        bool pcr_info;
@@ -361,8 +356,8 @@ static bool load_runtime_measurements(char *file, linked_list_t *list,
 /**
  * Extend measurement into PCR an create evidence
  */
-static pts_comp_evidence_t* extend_pcr(pts_ita_comp_ima_t* this, u_int32_t pcr,
-                                                                          chunk_t measurement)
+static pts_comp_evidence_t* extend_pcr(pts_ita_comp_ima_t* this, pts_pcr_t *pcrs,
+                                                                          u_int32_t pcr, chunk_t measurement)
 {
        size_t pcr_len;
        pts_pcr_transform_t pcr_transform;
@@ -376,9 +371,9 @@ static pts_comp_evidence_t* extend_pcr(pts_ita_comp_ima_t* this, u_int32_t pcr,
 
        if (this->pcr_info)
        {
-               pcr_before = chunk_clone(this->pcrs->get(this->pcrs, pcr));
+               pcr_before = chunk_clone(pcrs->get(pcrs, pcr));
        }
-       pcr_after = this->pcrs->extend(this->pcrs, pcr, measurement);
+       pcr_after = pcrs->extend(pcrs, pcr, measurement);
        if (!pcr_after.ptr)
        {
                free(pcr_before.ptr);
@@ -389,7 +384,7 @@ static pts_comp_evidence_t* extend_pcr(pts_ita_comp_ima_t* this, u_int32_t pcr,
                                                                this->measurement_time, measurement);
        if (this->pcr_info)
        {
-               pcr_after =chunk_clone(this->pcrs->get(this->pcrs, pcr));
+               pcr_after =chunk_clone(pcrs->get(pcrs, pcr));
                evidence->set_pcr_info(evidence, pcr_before, pcr_after);
        }
        return evidence;
@@ -398,7 +393,7 @@ static pts_comp_evidence_t* extend_pcr(pts_ita_comp_ima_t* this, u_int32_t pcr,
 /**
  * Compute and check boot aggregate value by hashing PCR0 to PCR7
  */
-static void check_boot_aggregate(pts_ita_comp_ima_t *this, chunk_t measurement)
+static void check_boot_aggregate(pts_pcr_t *pcrs, chunk_t measurement)
 {
        u_int32_t i;
        u_char filename_buffer[IMA_FILENAME_LEN_MAX + 1];
@@ -415,7 +410,7 @@ static void check_boot_aggregate(pts_ita_comp_ima_t *this, chunk_t measurement)
        }
        for (i = 0; i < 8 && pcr_ok; i++)
        {
-               pcr_ok = hasher->get_hash(hasher, this->pcrs->get(this->pcrs, i), NULL);
+               pcr_ok = hasher->get_hash(hasher, pcrs->get(pcrs, i), NULL);
        }
        if (pcr_ok)
        {
@@ -468,8 +463,10 @@ METHOD(pts_component_t, measure, status_t,
        status_t status;
        int count;
        enumerator_t *e;
+       pts_pcr_t *pcrs;
        pts_file_meas_t *file_meas;
 
+       pcrs = pts->get_pcrs(pts);
        *measurements = NULL;
 
        switch (this->state)
@@ -490,8 +487,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,
-                                                                                bios_entry->measurement);
+                       *evidence = extend_pcr(this, pcrs, bios_entry->pcr,
+                                                                                          bios_entry->measurement);
                        free(bios_entry);
                        if (!evidence)
                        {
@@ -545,11 +542,11 @@ METHOD(pts_component_t, measure, status_t,
                                DBG1(DBG_PTS, "could not retrieve ima measurement entry");
                                return status;
                        }
-                       *evidence = extend_pcr(this, IMA_PCR, ima_entry->measurement);
+                       *evidence = extend_pcr(this, pcrs, IMA_PCR, ima_entry->measurement);
 
                        if (this->state == IMA_STATE_BOOT_AGGREGATE)
                        {
-                               check_boot_aggregate(this, ima_entry->measurement);
+                               check_boot_aggregate(pcrs, ima_entry->measurement);
                        }
 
                        free(ima_entry->file_measurement.ptr);
@@ -578,10 +575,12 @@ METHOD(pts_component_t, verify, status_t,
        enum_name_t *names;
        pts_meas_algorithms_t algo;
        pts_pcr_transform_t transform;
+       pts_pcr_t *pcrs;
        time_t measurement_time;
        chunk_t measurement, pcr_before, pcr_after;
        status_t status;
 
+       pcrs = pts->get_pcrs(pts);
        measurement = evidence->get_measurement(evidence, &extended_pcr,
                                                                &algo, &transform, &measurement_time);
 
@@ -665,13 +664,25 @@ METHOD(pts_component_t, verify, status_t,
        has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after);
        if (has_pcr_info)
        {
-               if (!pts->add_pcr(pts, extended_pcr, pcr_before, pcr_after))
+               if (!chunk_equals(pcr_before, pcrs->get(pcrs, extended_pcr)))
+               {
+                       DBG1(DBG_PTS, "PCR %2u: pcr_before is not equal to pcr value",
+                                                  extended_pcr);
+               }
+               if (pcrs->set(pcrs, extended_pcr, pcr_after))
                {
-                       return FAILED;
+                       return SUCCESS;
                }
        }
-
-       return SUCCESS;
+       else
+       {
+               pcr_after = pcrs->extend(pcrs, extended_pcr, measurement);
+               if (pcr_after.ptr)
+               {
+                       return SUCCESS;
+               }
+       }
+       return FAILED;
 }
 
 METHOD(pts_component_t, finalize, bool,
@@ -723,7 +734,6 @@ METHOD(pts_component_t, destroy, void,
        this->bios_list->destroy_function(this->bios_list, (void *)free_bios_entry);
        this->ima_list->destroy_function(this->ima_list, (void *)free_ima_entry);
        this->name->destroy(this->name);
-       this->pcrs->destroy(this->pcrs);
        free(this->keyid.ptr);
        free(this);
 }
@@ -735,14 +745,6 @@ pts_component_t *pts_ita_comp_ima_create(u_int8_t qualifier, u_int32_t depth,
                                                                                 pts_database_t *pts_db)
 {
        pts_ita_comp_ima_t *this;
-       pts_pcr_t *pcrs;
-
-       pcrs = pts_pcr_create();
-       if (!pcrs)
-       {
-               DBG1(DBG_PTS, "shadow PCR set could not be created");
-               return NULL;
-       }
 
        INIT(this,
                .public = {
@@ -761,7 +763,6 @@ pts_component_t *pts_ita_comp_ima_create(u_int8_t qualifier, u_int32_t depth,
                .bios_list = linked_list_create(),
                .ima_list = linked_list_create(),
                .ima_count = IMA_MEASUREMENT_BATCH_SIZE - 1,
-               .pcrs = pcrs,
                .pcr_info = lib->settings->get_bool(lib->settings,
                                                "libimcv.plugins.imc-attestation.pcr_info", TRUE),
        );
index 8ac8335..40befc3 100644 (file)
@@ -110,13 +110,14 @@ METHOD(pts_component_t, measure, status_t,
        pts_file_meas_t **measurements)
 
 {
+       size_t pcr_len;
+       pts_pcr_t *pcrs;
+       pts_pcr_transform_t pcr_transform;
+       pts_meas_algorithms_t hash_algo;
        pts_comp_evidence_t *evid;
        char *meas_hex, *pcr_before_hex, *pcr_after_hex;
        chunk_t measurement, pcr_before, pcr_after;
-       size_t hash_size, pcr_len;
        u_int32_t extended_pcr;
-       pts_pcr_transform_t pcr_transform;
-       pts_meas_algorithms_t hash_algo;
        
        switch (this->seq_no++)
        {
@@ -150,9 +151,8 @@ METHOD(pts_component_t, measure, status_t,
                return FAILED;
        }
 
-       hash_algo = pts->get_meas_algorithm(pts);
-       hash_size = pts_meas_algo_hash_size(hash_algo);
-       pcr_len = pts->get_pcr_len(pts);
+       hash_algo = PTS_MEAS_ALGO_SHA1;
+       pcr_len = HASH_SIZE_SHA1;
        pcr_transform = pts_meas_algo_to_pcr_transform(hash_algo, pcr_len);
 
        /* get and check the measurement data */
@@ -163,7 +163,7 @@ METHOD(pts_component_t, measure, status_t,
        pcr_after = chunk_from_hex(
                                        chunk_create(pcr_after_hex, strlen(pcr_after_hex)), NULL);
        if (pcr_before.len != pcr_len || pcr_after.len != pcr_len ||
-               measurement.len != hash_size)
+               measurement.len != pcr_len)
        {
                DBG1(DBG_PTS, "TBOOT measurement or pcr data have the wrong size");
                free(measurement.ptr);
@@ -172,10 +172,11 @@ METHOD(pts_component_t, measure, status_t,
                return FAILED;
        }
 
+       pcrs = pts->get_pcrs(pts);
+       pcrs->set(pcrs, extended_pcr, pcr_after);
        evid = *evidence = pts_comp_evidence_create(this->name->clone(this->name),
-                                                               this->depth, extended_pcr,
-                                                               hash_algo, pcr_transform,
-                                                               this->measurement_time, measurement);
+                                                       this->depth, extended_pcr, hash_algo, pcr_transform,
+                                                       this->measurement_time, measurement);
        evid->set_pcr_info(evid, pcr_before, pcr_after);
 
        return (this->seq_no < 2) ? NEED_MORE : SUCCESS;
@@ -189,10 +190,12 @@ METHOD(pts_component_t, verify, status_t,
        enum_name_t *names;
        pts_meas_algorithms_t algo;
        pts_pcr_transform_t transform;
+       pts_pcr_t *pcrs;
        time_t measurement_time;
        chunk_t measurement, pcr_before, pcr_after;
        status_t status;
 
+       pcrs = pts->get_pcrs(pts);
        measurement = evidence->get_measurement(evidence, &extended_pcr,
                                                                &algo, &transform, &measurement_time);
 
@@ -258,9 +261,14 @@ METHOD(pts_component_t, verify, status_t,
        has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after);
        if (has_pcr_info)
        {
-               if (!pts->add_pcr(pts, extended_pcr, pcr_before, pcr_after))
+               if (!chunk_equals(pcr_before, pcrs->get(pcrs, extended_pcr)))
                {
-                       return FAILED;
+                       DBG1(DBG_PTS, "PCR %2u: pcr_before is not equal to pcr value",
+                                                  extended_pcr);
+               }
+               if (pcrs->set(pcrs, extended_pcr, pcr_after))
+               {
+                       return SUCCESS;
                }
        }
 
index a25f2f8..1d24b0a 100644 (file)
@@ -73,13 +73,13 @@ METHOD(pts_component_t, measure, status_t,
        pts_ita_comp_tgrub_t *this, pts_t *pts, pts_comp_evidence_t **evidence,
        pts_file_meas_t **measurements)
 {
+       size_t pcr_len;
+       pts_pcr_transform_t pcr_transform;
+       pts_meas_algorithms_t hash_algo;
        pts_comp_evidence_t *evid;
        u_int32_t extended_pcr;
        time_t measurement_time;
        chunk_t measurement, pcr_before, pcr_after;
-       pts_pcr_transform_t pcr_transform;
-       pts_meas_algorithms_t hash_algo;
-       size_t hash_size, pcr_len;
 
        /* Provisional implementation for TGRUB */
        extended_pcr = PCR_DEBUG;
@@ -91,12 +91,11 @@ METHOD(pts_component_t, measure, status_t,
                return FAILED;
        }
 
-       hash_algo = pts->get_meas_algorithm(pts);
-       hash_size = pts_meas_algo_hash_size(hash_algo);
-       pcr_len = pts->get_pcr_len(pts);
+       hash_algo = PTS_MEAS_ALGO_SHA1;
+       pcr_len = HASH_SIZE_SHA1;
        pcr_transform = pts_meas_algo_to_pcr_transform(hash_algo, pcr_len);
 
-       measurement = chunk_alloc(hash_size);
+       measurement = chunk_alloc(pcr_len);
        memset(measurement.ptr, 0x00, measurement.len);
                
        pcr_before = chunk_alloc(pcr_len);
@@ -118,9 +117,11 @@ METHOD(pts_component_t, verify, status_t,
        u_int32_t extended_pcr;
        pts_meas_algorithms_t algo;
        pts_pcr_transform_t transform;
+       pts_pcr_t *pcrs;
        time_t measurement_time;
        chunk_t measurement, pcr_before, pcr_after;
 
+       pcrs = pts->get_pcrs(pts);
        measurement = evidence->get_measurement(evidence, &extended_pcr,
                                                                &algo, &transform, &measurement_time);
        if (extended_pcr != PCR_DEBUG)
@@ -133,9 +134,13 @@ METHOD(pts_component_t, verify, status_t,
        has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after);
        if (has_pcr_info)
        {
-               if (!pts->add_pcr(pts, extended_pcr, pcr_before, pcr_after))
+               if (!chunk_equals(pcr_before, pcrs->get(pcrs, extended_pcr)))
+               {
+                       DBG1(DBG_PTS, "PCR %2u: pcr_before is not equal to pcr value");
+               }
+               if (pcrs->set(pcrs, extended_pcr, pcr_after))
                {
-                       return FAILED;
+                       return SUCCESS;
                }
        }
        
index 16047aa..769890f 100644 (file)
 #include <unistd.h>
 #include <errno.h>
 
-/**
- * Maximum number of PCR's of TPM, TPM Spec 1.2
- */
-#define PCR_MAX_NUM                            24
-
-/**
- * Number of bytes that can be saved in a PCR of TPM, TPM Spec 1.2
- */
-#define PCR_LEN                                        20
-
 typedef struct private_pts_t private_pts_t;
 
 /**
@@ -119,29 +109,9 @@ struct private_pts_t {
        certificate_t *aik;
 
        /**
-        * Table of extended PCRs with corresponding values
-        */
-       u_char* pcrs[PCR_MAX_NUM];
-
-       /**
-        * Length of PCR registers
-        */
-       size_t pcr_len;
-
-       /**
-        * Number of extended PCR registers
+        * Shadow PCR set
         */
-       u_int32_t pcr_count;
-
-       /**
-        * Highest extended PCR register
-        */
-       u_int32_t pcr_max;
-
-       /**
-        * Bitmap of extended PCR registers
-        */
-       u_int8_t pcr_select[PCR_MAX_NUM / 8];
+       pts_pcr_t *pcrs;
 
 };
 
@@ -369,12 +339,6 @@ METHOD(pts_t, set_tpm_version_info, void,
        print_tpm_version_info(this);
 }
 
-METHOD(pts_t, get_pcr_len, size_t,
-       private_pts_t *this)
-{
-       return this->pcr_len;
-}
-
 /**
  * Load an AIK Blob (TSS_TSPATTRIB_KEYBLOB_BLOB attribute)
  */
@@ -715,8 +679,8 @@ METHOD(pts_t, extend_pcr, bool,
                goto err;
        }
 
-       pcr_value = chunk_alloc(PCR_LEN);
-       result = Tspi_TPM_PcrExtend(hTPM, pcr_num, PCR_LEN, input.ptr,
+       pcr_value = chunk_alloc(PTS_PCR_LEN);
+       result = Tspi_TPM_PcrExtend(hTPM, pcr_num, PTS_PCR_LEN, input.ptr,
                                                                NULL, &pcr_length, &pcr_value.ptr);
        if (result != TSS_SUCCESS)
        {
@@ -745,22 +709,6 @@ err:
        return FALSE;
 }
 
-
-static void clear_pcrs(private_pts_t *this)
-{
-       int i;
-
-       for (i = 0; i <= this->pcr_max; i++)
-       {
-               free(this->pcrs[i]);
-               this->pcrs[i] = NULL;
-       }
-       this->pcr_count = 0;
-       this->pcr_max = 0;
-
-       memset(this->pcr_select, 0x00, sizeof(this->pcr_select));
-}
-
 METHOD(pts_t, quote_tpm, bool,
        private_pts_t *this, bool use_quote2, chunk_t *pcr_comp, chunk_t *quote_sig)
 {
@@ -776,7 +724,8 @@ METHOD(pts_t, quote_tpm, bool,
        TSS_RESULT result;
        chunk_t quote_info;
        BYTE* versionInfo;
-       u_int32_t versionInfoSize, pcr, i = 0, f = 1;
+       u_int32_t versionInfoSize, pcr;
+       enumerator_t *enumerator;
        bool success = FALSE;
 
        result = Tspi_Context_Create(&hContext);
@@ -836,25 +785,23 @@ METHOD(pts_t, quote_tpm, bool,
        }
 
        /* Select PCRs */
-       for (pcr = 0; pcr <= this->pcr_max ; pcr++)
-       {
-               if (f == 256)
-               {
-                       i++;
-                       f = 1;
-               }
-               if (this->pcr_select[i] & f)
+       enumerator = this->pcrs->create_enumerator(this->pcrs);
+       while (enumerator->enumerate(enumerator, &pcr))
+       {
+               result = use_quote2 ?
+                               Tspi_PcrComposite_SelectPcrIndexEx(hPcrComposite, pcr,
+                                                                                       TSS_PCRS_DIRECTION_RELEASE) :
+                               Tspi_PcrComposite_SelectPcrIndex(hPcrComposite, pcr);
+               if (result != TSS_SUCCESS)
                {
-                       result = use_quote2 ?
-                                       Tspi_PcrComposite_SelectPcrIndexEx(hPcrComposite, pcr,
-                                                                                               TSS_PCRS_DIRECTION_RELEASE) :
-                                       Tspi_PcrComposite_SelectPcrIndex(hPcrComposite, pcr);
-                       if (result != TSS_SUCCESS)
-                       {
-                               goto err3;
-                       }
+                       break;
                }
-               f <<= 1;
+       }
+       enumerator->destroy(enumerator);
+
+       if (result != TSS_SUCCESS)
+       {
+               goto err3;
        }
 
        /* Set the Validation Data */
@@ -914,87 +861,14 @@ err1:
        {
                DBG1(DBG_PTS, "TPM not available: tss error 0x%x", result);
        }
-       clear_pcrs(this);
 
        return success;
 }
 
-METHOD(pts_t, select_pcr, bool,
-       private_pts_t *this, u_int32_t pcr)
-{
-       u_int32_t i, f;
-
-       if (pcr >= PCR_MAX_NUM)
-       {
-               DBG1(DBG_PTS, "PCR %u: number is larger than maximum of %u",
-                                          pcr, PCR_MAX_NUM-1);
-               return FALSE;
-       }
-
-       /* Determine PCR selection flag */
-       i = pcr / 8;
-       f = 1 << (pcr - 8*i);
-
-       /* Has this PCR already been selected? */
-       if (!(this->pcr_select[i] & f))
-       {
-               this->pcr_select[i] |= f;
-               this->pcr_max = max(this->pcr_max, pcr);
-               this->pcr_count++;
-       }
-
-       return TRUE;
-}
-
-METHOD(pts_t, add_pcr, bool,
-       private_pts_t *this, u_int32_t pcr, chunk_t pcr_before, chunk_t pcr_after)
+METHOD(pts_t, get_pcrs, pts_pcr_t*,
+       private_pts_t *this)
 {
-       if (pcr >= PCR_MAX_NUM)
-       {
-               DBG1(DBG_PTS, "PCR %u: number is larger than maximum of %u",
-                                          pcr, PCR_MAX_NUM-1);
-               return FALSE;
-       }
-
-       /* Is the length of the PCR registers already set? */
-       if (this->pcr_len)
-       {
-               if (pcr_after.len != this->pcr_len)
-               {
-                       DBG1(DBG_PTS, "PCR %02u: length is %d bytes but should be %d bytes",
-                                                  pcr_after.len, this->pcr_len);
-                       return FALSE;
-               }
-       }
-       else
-       {
-               this->pcr_len = pcr_after.len;
-       }
-
-       /* Has the value of the PCR register already been assigned? */
-       if (this->pcrs[pcr])
-       {
-               if (!memeq(this->pcrs[pcr], pcr_before.ptr, this->pcr_len))
-               {
-                       DBG1(DBG_PTS, "PCR %02u: new pcr_before value does not equal "
-                                                 "old pcr_after value");
-               }
-               /* remove the old PCR value */
-               free(this->pcrs[pcr]);
-       }
-       else
-       {
-               /* add extended PCR Register */
-               this->pcr_select[pcr / 8] |= 1 << (pcr % 8);
-               this->pcr_max = max(this->pcr_max, pcr);
-               this->pcr_count++;
-       }
-
-       /* Duplicate and store current PCR value */
-       pcr_after = chunk_clone(pcr_after);
-       this->pcrs[pcr] = pcr_after.ptr;
-
-       return TRUE;
+       return this->pcrs;
 }
 
 /**
@@ -1016,13 +890,11 @@ METHOD(pts_t, get_quote_info, bool,
        pts_meas_algorithms_t comp_hash_algo,
        chunk_t *out_pcr_comp, chunk_t *out_quote_info)
 {
-       u_int8_t size_of_select;
-       int pcr_comp_len, i;
-       chunk_t pcr_comp, hash_pcr_comp;
+       chunk_t selection, pcr_comp, hash_pcr_comp;
        bio_writer_t *writer;
        hasher_t *hasher;
 
-       if (this->pcr_count == 0)
+       if (!this->pcrs->get_count(this->pcrs))
        {
                DBG1(DBG_PTS, "No extended PCR entries available, "
                                          "unable to construct TPM Quote Info");
@@ -1041,33 +913,8 @@ METHOD(pts_t, get_quote_info, bool,
                return FALSE;
        }
 
-       /**
-        * A TPM v1.2 has 24 PCR Registers
-        * so the bitmask field length used by TrouSerS is at least 3 bytes
-        */
-       size_of_select = max(PCR_MAX_NUM / 8, 1 + this->pcr_max / 8);
-       pcr_comp_len = 2 + size_of_select + 4 + this->pcr_count * this->pcr_len;
-
-       writer = bio_writer_create(pcr_comp_len);
+       pcr_comp = this->pcrs->get_composite(this->pcrs);
 
-       writer->write_uint16(writer, size_of_select);
-       for (i = 0; i < size_of_select; i++)
-       {
-               writer->write_uint8(writer, this->pcr_select[i]);
-       }
-
-       writer->write_uint32(writer, this->pcr_count * this->pcr_len);
-       for (i = 0; i < 8 * size_of_select; i++)
-       {
-               if (this->pcrs[i])
-               {
-                       writer->write_data(writer, chunk_create(this->pcrs[i], this->pcr_len));
-               }
-       }
-       pcr_comp = chunk_clone(writer->get_buf(writer));
-       DBG3(DBG_PTS, "constructed PCR Composite: %B", &pcr_comp);
-
-       writer->destroy(writer);
 
        /* Output the TPM_PCR_COMPOSITE expected from IMC */
        if (comp_hash_algo)
@@ -1117,14 +964,10 @@ METHOD(pts_t, get_quote_info, bool,
                /* Secret assessment value 20 bytes (nonce) */
                writer->write_data(writer, this->secret);
 
-               /* Length of the PCR selection field */
-               writer->write_uint16(writer, size_of_select);
-
                /* PCR selection */
-               for (i = 0; i < size_of_select ; i++)
-               {
-                       writer->write_uint8(writer, this->pcr_select[i]);
-               }
+               selection.ptr = pcr_comp.ptr;
+               selection.len = 2 + this->pcrs->get_selection_size(this->pcrs);
+               writer->write_data(writer, selection);
 
                /* TPM Locality Selection */
                writer->write_uint8(writer, TPM_LOC_ZERO);
@@ -1160,7 +1003,6 @@ METHOD(pts_t, get_quote_info, bool,
        writer->destroy(writer);
        free(pcr_comp.ptr);
        free(hash_pcr_comp.ptr);
-       clear_pcrs(this);
 
        return TRUE;
 }
@@ -1192,7 +1034,7 @@ METHOD(pts_t, verify_quote_signature, bool,
 METHOD(pts_t, destroy, void,
        private_pts_t *this)
 {
-       clear_pcrs(this);
+       DESTROY_IF(this->pcrs);
        DESTROY_IF(this->aik);
        DESTROY_IF(this->dh);
        free(this->initiator_nonce.ptr);
@@ -1374,6 +1216,14 @@ static bool has_tpm(private_pts_t *this)
 pts_t *pts_create(bool is_imc)
 {
        private_pts_t *this;
+       pts_pcr_t *pcrs;
+
+       pcrs = pts_pcr_create();
+       if (!pcrs)
+       {
+               DBG1(DBG_PTS, "shadow PCR set could not be created");
+               return NULL;
+       }
 
        INIT(this,
                .public = {
@@ -1391,7 +1241,6 @@ pts_t *pts_create(bool is_imc)
                        .set_platform_info = _set_platform_info,
                        .get_tpm_version_info = _get_tpm_version_info,
                        .set_tpm_version_info = _set_tpm_version_info,
-                       .get_pcr_len = _get_pcr_len,
                        .get_aik = _get_aik,
                        .set_aik = _set_aik,
                        .get_aik_keyid = _get_aik_keyid,
@@ -1400,8 +1249,7 @@ pts_t *pts_create(bool is_imc)
                        .read_pcr = _read_pcr,
                        .extend_pcr = _extend_pcr,
                        .quote_tpm = _quote_tpm,
-                       .select_pcr = _select_pcr,
-                       .add_pcr = _add_pcr,
+                       .get_pcrs = _get_pcrs,
                        .get_quote_info = _get_quote_info,
                        .verify_quote_signature  = _verify_quote_signature,
                        .destroy = _destroy,
@@ -1410,6 +1258,7 @@ pts_t *pts_create(bool is_imc)
                .proto_caps = PTS_PROTO_CAPS_V,
                .algorithm = PTS_MEAS_ALGO_SHA256,
                .dh_hash_algorithm = PTS_MEAS_ALGO_SHA256,
+               .pcrs = pcrs,
        );
 
        if (is_imc)
@@ -1419,7 +1268,6 @@ pts_t *pts_create(bool is_imc)
                if (has_tpm(this))
                {
                        this->has_tpm = TRUE;
-                       this->pcr_len = PCR_LEN;
                        this->proto_caps |= PTS_PROTO_CAPS_T | PTS_PROTO_CAPS_D;
                        load_aik(this);
                        load_aik_blob(this);
index c35f686..5f88cd1 100644 (file)
@@ -29,6 +29,7 @@ typedef struct pts_t pts_t;
 #include "pts_file_meas.h"
 #include "pts_file_meta.h"
 #include "pts_dh_group.h"
+#include "pts_pcr.h"
 #include "pts_req_func_comp_evid.h"
 #include "pts_simple_evid_final.h"
 #include "components/pts_comp_func_name.h"
@@ -190,13 +191,6 @@ struct pts_t {
        void (*set_tpm_version_info)(pts_t *this, chunk_t info);
 
        /**
-        * Get the length of the TPM PCR registers
-        *
-        * @return                                      Length of PCR registers in bytes, 0 if undefined
-        */
-       size_t (*get_pcr_len)(pts_t *this);
-
-       /**
         * Get Attestation Identity Certificate or Public Key
         *
         * @return                                      AIK Certificate or Public Key
@@ -273,24 +267,12 @@ struct pts_t {
         bool (*quote_tpm)(pts_t *this, bool use_quote2, chunk_t *pcr_comp,
                                                                                                         chunk_t *quote_sig);
 
-        /**
-        * Mark an extended PCR as selected
-        *
-        * @param pcr                           Number of the extended PCR
-        * @return                                      TRUE if PCR number is valid
-        */
-        bool (*select_pcr)(pts_t *this, u_int32_t pcr);
-
-        /**
-        * Add an extended PCR with its corresponding value
+       /**
+        * Get the shadow PCR set
         *
-        * @param pcr                           Number of the extended PCR
-        * @param pcr_before            PCR value before extension
-        * @param pcr_after                     PCR value after extension
-        * @return                                      TRUE if PCR number and register length is valid
+        * @return                                      shadow PCR set
         */
-       bool (*add_pcr)(pts_t *this, u_int32_t pcr, chunk_t pcr_before,
-                                                                                               chunk_t pcr_after);
+       pts_pcr_t* (*get_pcrs)(pts_t *this);
 
         /**
         * Constructs and returns TPM Quote Info structure expected from IMC
index c21e585..a7a2f5f 100644 (file)
 
 #include <debug.h>
 
-/**
- * Maximum number of PCR's of TPM, TPM Spec 1.2
- */
-#define PCR_MAX_NUM                            24
-
-/**
- * Number of bytes that can be saved in a PCR of TPM, TPM Spec 1.2
- */
-#define PCR_LEN                                        20
+#include <stdarg.h>
 
 typedef struct private_pts_pcr_t private_pts_pcr_t;
 
@@ -43,7 +35,22 @@ struct private_pts_pcr_t {
        /**
         * Shadow PCR registers
         */
-       chunk_t pcrs[PCR_MAX_NUM];
+       chunk_t pcrs[PTS_PCR_MAX_NUM];
+
+       /**
+        * Number of extended PCR registers
+        */
+       u_int32_t pcr_count;
+
+       /**
+        * Highest extended PCR register
+        */
+       u_int32_t pcr_max;
+
+       /**
+        * Bitmap of extended PCR registers
+        */
+       u_int8_t pcr_select[PTS_PCR_MAX_NUM / 8];
 
        /**
         * Hasher used to extend shadow PCRs
@@ -52,44 +59,186 @@ struct private_pts_pcr_t {
 
 };
 
+METHOD(pts_pcr_t, get_count, u_int32_t,
+       private_pts_pcr_t *this)
+{
+       return this->pcr_count;
+}
+
+METHOD(pts_pcr_t, select_pcr, bool,
+       private_pts_pcr_t *this, u_int32_t pcr)
+{
+       u_int32_t i, f;
+
+       if (pcr >= PTS_PCR_MAX_NUM)
+       {
+               DBG1(DBG_PTS, "PCR %2u: number is larger than maximum of %u",
+                                          pcr, PTS_PCR_MAX_NUM-1);
+               return FALSE;
+       }
+
+       /* Determine PCR selection flag */
+       i = pcr / 8;
+       f = 1 << (pcr - 8*i);
+
+       /* Has this PCR already been selected? */
+       if (!(this->pcr_select[i] & f))
+       {
+               this->pcr_select[i] |= f;
+               this->pcr_max = max(this->pcr_max, pcr);
+               this->pcr_count++;
+       }
+       return TRUE;
+}
+
+METHOD(pts_pcr_t, get_selection_size, size_t,
+       private_pts_pcr_t *this)
+{
+
+       /**
+        * A TPM v1.2 has 24 PCR Registers so the bitmask field length
+        * used by TrouSerS is at least 3 bytes
+        */
+       return PTS_PCR_MAX_NUM / 8;
+}
+
+typedef struct {
+       /** implements enumerator_t */
+       enumerator_t public;
+       /** current PCR */
+       u_int32_t pcr;
+       /** back reference to parent */
+       private_pts_pcr_t *pcrs;
+} pcr_enumerator_t;
+
+/**
+ * Implementation of enumerator.enumerate
+ */
+static bool pcr_enumerator_enumerate(pcr_enumerator_t *this, ...)
+{
+       u_int32_t *pcr, i, f;
+       va_list args;
+
+       va_start(args, this);
+       pcr = va_arg(args, u_int32_t*);
+       va_end(args);
+
+       while (this->pcr <= this->pcrs->pcr_max)
+       {
+               /* Determine PCR selection flag */
+               i = this->pcr / 8;
+               f = 1 << (this->pcr - 8*i);
+
+               /* Assign current PCR to output argument and increase */
+               *pcr = this->pcr++;
+
+               /* return if PCR is selected */
+               if (this->pcrs->pcr_select[i] & f)
+               {
+                       return TRUE;
+               }
+       }
+       return FALSE;
+}
+
+METHOD(pts_pcr_t, create_enumerator, enumerator_t*,
+       private_pts_pcr_t *this)
+{
+       pcr_enumerator_t *enumerator;
+
+       INIT(enumerator,
+               .public = {
+                       .enumerate = (void*)pcr_enumerator_enumerate,
+                       .destroy = (void*)free,
+               },
+               .pcrs = this,
+       );
+
+       return (enumerator_t*)enumerator;
+}
+
 METHOD(pts_pcr_t, get, chunk_t,
        private_pts_pcr_t *this, u_int32_t pcr)
 {
-       return (pcr < PCR_MAX_NUM) ? this->pcrs[pcr] : chunk_empty;
+       return (pcr < PTS_PCR_MAX_NUM) ? this->pcrs[pcr] : chunk_empty;
 }
 
-METHOD(pts_pcr_t, set, void,
+METHOD(pts_pcr_t, set, bool,
        private_pts_pcr_t *this, u_int32_t pcr, chunk_t value)
 {
-       if (pcr < PCR_MAX_NUM && value.len == PCR_LEN)
+       if (value.len != PTS_PCR_LEN)
+       {
+               DBG1(DBG_PTS, "PCR %2u: value does not fit", pcr);
+               return FALSE;
+       }
+       if (select_pcr(this, pcr))
        {
-               memcpy(this->pcrs[pcr].ptr, value.ptr, PCR_LEN);
+               memcpy(this->pcrs[pcr].ptr, value.ptr, PTS_PCR_LEN);
+               return TRUE;
        }
+       return FALSE;
 }
 
 METHOD(pts_pcr_t, extend, chunk_t,
        private_pts_pcr_t *this, u_int32_t pcr, chunk_t measurement)
 {
-       if (pcr >= PCR_MAX_NUM || measurement.len != PCR_LEN)
+       if (measurement.len != PTS_PCR_LEN)
+       {
+               DBG1(DBG_PTS, "PCR %2u: measurement does not fit", pcr);
+               return chunk_empty;
+       }
+       if (!select_pcr(this, pcr))
        {
-               DBG1(DBG_PTS, "PCR%d does not exist or has the wrong size", pcr);
                return chunk_empty;
        }
        if (!this->hasher->get_hash(this->hasher, this->pcrs[pcr] , NULL) ||
                !this->hasher->get_hash(this->hasher, measurement, this->pcrs[pcr].ptr))
        {
-               DBG1(DBG_PTS, "PCR%d was not extended due to a hasher problem", pcr);
+               DBG1(DBG_PTS, "PCR %2u: not extended due to hasher problem", pcr);
                return chunk_empty;
        }
        return this->pcrs[pcr];
 }
 
+METHOD(pts_pcr_t, get_composite, chunk_t,
+       private_pts_pcr_t *this)
+{
+       chunk_t composite;
+       enumerator_t *enumerator;
+       u_int16_t selection_size;
+       u_int32_t pcr_field_size, pcr;
+       u_char *pos;
+
+       selection_size = get_selection_size(this);
+       pcr_field_size = this->pcr_count * PTS_PCR_LEN;
+
+       composite = chunk_alloc(2 + selection_size + 4 + pcr_field_size);
+       pos = composite.ptr;
+       htoun16(pos, selection_size);
+       pos += 2;
+       memcpy(pos, this->pcr_select, selection_size);
+       pos += selection_size;
+       htoun32(pos, pcr_field_size);
+       pos += 4;
+
+       enumerator = create_enumerator(this);
+       while (enumerator->enumerate(enumerator, &pcr))
+       {
+               memcpy(pos, this->pcrs[pcr].ptr, PTS_PCR_LEN);
+               pos += PTS_PCR_LEN;
+       }
+       enumerator->destroy(enumerator);
+
+       DBG3(DBG_PTS, "constructed PCR Composite: %B", &composite);
+       return composite;
+}
+
 METHOD(pts_pcr_t, destroy, void,
        private_pts_pcr_t *this)
 {
        u_int32_t i;
 
-       for (i = 0; i < PCR_MAX_NUM; i++)
+       for (i = 0; i < PTS_PCR_MAX_NUM; i++)
        {
                free(this->pcrs[i].ptr);
        }
@@ -116,18 +265,23 @@ pts_pcr_t *pts_pcr_create(void)
 
        INIT(this,
                .public = {
+                       .get_count = _get_count,
+                       .select_pcr = _select_pcr,
+                       .get_selection_size = _get_selection_size,
+                       .create_enumerator = _create_enumerator,
                        .get = _get,
                        .set = _set,
                        .extend = _extend,
+                       .get_composite = _get_composite,
                        .destroy = _destroy,
                },
                .hasher = hasher,
        );
 
-       for (i = 0; i < PCR_MAX_NUM; i++)
+       for (i = 0; i < PTS_PCR_MAX_NUM; i++)
        {
-               this->pcrs[i] = chunk_alloc(PCR_LEN);
-               memset(this->pcrs[i].ptr, 0x00, PCR_LEN);
+               this->pcrs[i] = chunk_alloc(PTS_PCR_LEN);
+               memset(this->pcrs[i].ptr, 0x00, PTS_PCR_LEN);
        }
 
        return &this->public;
index 43a85db..f638b5e 100644 (file)
@@ -26,11 +26,50 @@ typedef struct pts_pcr_t pts_pcr_t;
 #include <library.h>
 
 /**
+ * Maximum number of PCR's of TPM, TPM Spec 1.2
+ */
+#define PTS_PCR_MAX_NUM                                24
+
+/**
+ * Number of bytes that can be saved in a PCR of TPM, TPM Spec 1.2
+ */
+#define PTS_PCR_LEN                                    20
+
+/**
  * Class implementing a shadow PCR register set
  */
 struct pts_pcr_t {
 
        /**
+        * Get the number of selected PCRs
+        *
+        * @return                              number of selected PCRs
+        */
+       u_int32_t (*get_count)(pts_pcr_t *this);
+
+       /**
+        * Mark a PCR as selected
+        *
+        * @param pcr                   index of PCR
+        * @return                              TRUE if PCR index exists
+        */
+       bool (*select_pcr)(pts_pcr_t *this, u_int32_t pcr);
+
+       /**
+        * Get the size of the selection field in bytes
+        *
+        * @return                              number of bytes written
+        */
+       size_t (*get_selection_size)(pts_pcr_t *this);
+
+       /**
+        * Create an enumerator over all selected PCR indexes
+        *
+        * @return                              enumerator
+        */
+       enumerator_t* (*create_enumerator)(pts_pcr_t *this);
+
+       /**
         * Get the current content of a PCR
         *
         * @param pcr                   index of PCR
@@ -43,8 +82,9 @@ struct pts_pcr_t {
         *
         * @param pcr                   index of PCR
         * @param value                 new value of PCR
+        * @return                              TRUE if value could be set
         */
-       void (*set)(pts_pcr_t *this, u_int32_t pcr, chunk_t value);
+       bool (*set)(pts_pcr_t *this, u_int32_t pcr, chunk_t value);
 
        /**
         * Extend the content of a PCR
@@ -56,6 +96,14 @@ struct pts_pcr_t {
        chunk_t (*extend)(pts_pcr_t *this, u_int32_t pcr, chunk_t measurement);
 
        /**
+        * Create a PCR Composite object over all selected PCRs
+        *
+        * @return                              PCR Composite object (must be freed)
+        */
+       chunk_t (*get_composite)(pts_pcr_t *this);
+
+       /**
+
         * Destroys a pts_pcr_t object.
         */
        void (*destroy)(pts_pcr_t *this);