static int cfm_flash_get_next_measurement_data()

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;
}