in core/manifest/cfm/cfm_flash.c [848:1030]
static int cfm_flash_get_next_measurement_data (const struct cfm *cfm,
struct cfm_measurement_data *measurement_data, uint8_t *entry)
{
const struct cfm_flash *cfm_flash = (const struct cfm_flash*) cfm;
union {
struct cfm_measurement_data_element measurement_data_element;
struct cfm_allowable_data_element allowable_data_element;
struct cfm_allowable_data_element_entry allowable_data_element_entry;
} buffer;
struct cfm_measurement_data_element *measurement_data_element_ptr =
&buffer.measurement_data_element;
struct cfm_allowable_data_element *allowable_data_element_ptr = &buffer.allowable_data_element;
struct cfm_allowable_data_element_entry *allowable_data_element_entry_ptr =
&buffer.allowable_data_element_entry;
struct cfm_allowable_data *allowable_data_ptr;
size_t measurement_data_element_len = sizeof (struct cfm_measurement_data_element);
size_t offset;
uint8_t i_allowable_data;
int num_allowable_data;
int status;
measurement_data->data_checks = NULL;
measurement_data->data_checks_count = 0;
// Get Measurement Data element
status = cfm_flash_get_next_element (cfm_flash, 0, (uint8_t**) &measurement_data_element_ptr,
&measurement_data_element_len, entry, CFM_MEASUREMENT_DATA);
if (status != 0) {
return status;
}
// Verify that an entire Measurement Data element was read
if (measurement_data_element_len < (int) (sizeof (struct cfm_measurement_data_element))) {
return CFM_MALFORMED_MEASUREMENT_DATA_ENTRY;
}
measurement_data->pmr_id = measurement_data_element_ptr->pmr_id;
measurement_data->measurement_id = measurement_data_element_ptr->measurement_id;
// Get count of Allowable Data elements
status = manifest_flash_get_child_elements_info (&cfm_flash->base_flash,
cfm_flash->base_flash.hash, *entry, CFM_MEASUREMENT_DATA, CFM_COMPONENT_DEVICE,
CFM_ALLOWABLE_DATA, NULL, &num_allowable_data, NULL);
if (status != 0) {
return status;
}
// Allocate space for Allowable Datas and set fields of measurement_data
measurement_data->data_checks_count = num_allowable_data;
measurement_data->data_checks =
platform_calloc (measurement_data->data_checks_count, sizeof (struct cfm_allowable_data));
if (measurement_data->data_checks == NULL) {
return CFM_NO_MEMORY;
}
// Read each Allowable Data element and fill in measurement_data
for (i_allowable_data = 0; i_allowable_data < num_allowable_data; ++i_allowable_data) {
// Read Allowable Data element
status = manifest_flash_read_element_data (&cfm_flash->base_flash,
cfm_flash->base_flash.hash, CFM_ALLOWABLE_DATA, *entry, CFM_MEASUREMENT_DATA, 0, NULL,
NULL, NULL, (uint8_t**) &allowable_data_element_ptr,
sizeof (struct cfm_allowable_data_element));
if (ROT_IS_ERROR (status)) {
if (status == MANIFEST_CHILD_NOT_FOUND) {
status = CFM_ENTRY_NOT_FOUND;
}
goto free_allowable_data;
}
// Verify that an entire Allowable Data element was read
if (status < (int) (sizeof (struct cfm_allowable_data_element))) {
status = CFM_MALFORMED_ALLOWABLE_DATA_ENTRY;
goto free_allowable_data;
}
allowable_data_ptr = &measurement_data->data_checks[i_allowable_data];
allowable_data_ptr->check = (enum cfm_check) allowable_data_element_ptr->check.check;
allowable_data_ptr->big_endian =
(allowable_data_element_ptr->check.endianness == CFM_MULTIBYTE_BIG_ENDIAN);
allowable_data_ptr->data_count = allowable_data_element_ptr->num_data;
allowable_data_ptr->bitmask_length = allowable_data_element_ptr->bitmask_length;
// Update offset to start of bitmask
offset = sizeof (struct cfm_allowable_data_element);
// Read bitmask, if one exists for this Allowable Data
if (allowable_data_ptr->bitmask_length) {
// Allocate space for bitmask
allowable_data_ptr->bitmask = platform_malloc (allowable_data_ptr->bitmask_length);
if (allowable_data_ptr->bitmask == NULL) {
status = CFM_NO_MEMORY;
goto free_allowable_data;
}
// Read bitmask from Allowable Data element
status = manifest_flash_read_element_data (&cfm_flash->base_flash,
cfm_flash->base_flash.hash, CFM_ALLOWABLE_DATA, *entry, CFM_MEASUREMENT_DATA,
offset, NULL, NULL, NULL, (uint8_t**) &allowable_data_ptr->bitmask,
allowable_data_ptr->bitmask_length);
if (ROT_IS_ERROR (status)) {
goto free_allowable_data;
}
// Ensure that the full bitmask was read
if (status < (int) (allowable_data_ptr->bitmask_length)) {
status = CFM_MALFORMED_ALLOWABLE_DATA_ENTRY;
goto free_allowable_data;
}
// Advance offset for 4-byte alignment
offset += (((size_t) allowable_data_ptr->bitmask_length + 3) & ~((size_t) 3));
}
// Allocate space for Data entries
allowable_data_ptr->allowable_data = platform_calloc (allowable_data_ptr->data_count,
sizeof (struct cfm_allowable_data_entry));
if (allowable_data_ptr->allowable_data == NULL) {
status = CFM_NO_MEMORY;
goto free_allowable_data;
}
// Read all Data entries of current Allowable Data element
for (uint8_t i_data = 0; i_data < allowable_data_ptr->data_count; i_data++) {
// Read Data header
status = manifest_flash_read_element_data (&cfm_flash->base_flash,
cfm_flash->base_flash.hash, CFM_ALLOWABLE_DATA, *entry, CFM_MEASUREMENT_DATA,
offset, entry, NULL, NULL, (uint8_t**) &allowable_data_element_entry_ptr,
sizeof (struct cfm_allowable_data_element_entry));
if (ROT_IS_ERROR (status)) {
goto free_allowable_data;
}
if (status < (int) (sizeof (struct cfm_allowable_data_element_entry))) {
status = CFM_MALFORMED_ALLOWABLE_DATA_ENTRY;
goto free_allowable_data;
}
allowable_data_ptr->allowable_data[i_data].version_set =
allowable_data_element_entry_ptr->version_set;
allowable_data_ptr->allowable_data[i_data].data_len =
allowable_data_element_entry_ptr->data_length;
offset += sizeof (struct cfm_allowable_data_element_entry);
allowable_data_ptr->allowable_data[i_data].data =
platform_malloc (allowable_data_ptr->allowable_data[i_data].data_len);
// Read Data
status = manifest_flash_read_element_data (&cfm_flash->base_flash,
cfm_flash->base_flash.hash, CFM_ALLOWABLE_DATA, *entry, CFM_MEASUREMENT_DATA,
offset, entry, NULL, NULL,
(uint8_t**) &allowable_data_ptr->allowable_data[i_data].data,
allowable_data_ptr->allowable_data[i_data].data_len);
if (ROT_IS_ERROR (status)) {
goto free_allowable_data;
}
if (status < (int) (allowable_data_ptr->allowable_data[i_data].data_len)) {
status = CFM_MALFORMED_ALLOWABLE_DATA_ENTRY;
goto free_allowable_data;
}
offset += (((size_t) allowable_data_ptr->allowable_data[i_data].data_len + 3) &
~((size_t) 3));
}
// Advance to next Allowable Data
*entry = *entry + 1;
}
return 0;
free_allowable_data:
cfm_flash_free_measurement_data (cfm, measurement_data);
return status;
}