static int manifest_flash_verify_v2()

in core/manifest/manifest_flash.c [319:493]


static int manifest_flash_verify_v2 (const struct manifest_flash *manifest,
	const struct hash_engine *hash, const struct signature_verification *verification,
	enum hash_type sig_hash, uint8_t *hash_out)
{
	struct manifest_toc_header *toc_header;
	struct manifest_toc_entry entry;
	struct manifest_platform_id plat_id_header;
	uint32_t next_addr;
	uint32_t toc_end;
	uint32_t sig_addr =
		manifest->addr + manifest->state->header.length - manifest->state->header.sig_length;
	int i;
	int status;

	/* Hash the header data that has already been read in. */
	status = hash_start_new_hash (hash, sig_hash);
	if (status != 0) {
		return status;
	}

	status = hash->update (hash, (uint8_t*) &manifest->state->header,
		sizeof (manifest->state->header));
	if (status != 0) {
		goto error;
	}

	/* Read and hash the table of contents header. */
	toc_header = &manifest->state->toc_header;

	next_addr = manifest->addr + sizeof (manifest->state->header);
	status = manifest->flash->read (manifest->flash, next_addr, (uint8_t*) toc_header,
		sizeof (*toc_header));
	if (status != 0) {
		goto error;
	}

	switch (toc_header->hash_type) {
		case MANIFEST_HASH_SHA256:
			manifest->state->toc_hash_type = HASH_TYPE_SHA256;
			manifest->state->toc_hash_length = SHA256_HASH_LENGTH;
			break;

#ifdef HASH_ENABLE_SHA384
		case MANIFEST_HASH_SHA384:
			manifest->state->toc_hash_type = HASH_TYPE_SHA384;
			manifest->state->toc_hash_length = SHA384_HASH_LENGTH;
			break;
#endif

#ifdef HASH_ENABLE_SHA512
		case MANIFEST_HASH_SHA512:
			manifest->state->toc_hash_type = HASH_TYPE_SHA512;
			manifest->state->toc_hash_length = SHA512_HASH_LENGTH;
			break;
#endif

		default:
			status = MANIFEST_TOC_UNKNOWN_HASH_TYPE;
			goto error;
	}

	status = hash->update (hash, (uint8_t*) toc_header, sizeof (*toc_header));
	if (status != 0) {
		goto error;
	}

	/* Find the platform ID element, hashing each entry as it is read in. */
	next_addr += sizeof (*toc_header);
	i = 0;
	do {
		status = manifest->flash->read (manifest->flash, next_addr, (uint8_t*) &entry,
			sizeof (entry));
		if (status != 0) {
			goto error;
		}

		status = hash->update (hash, (uint8_t*) &entry, sizeof (entry));
		if (status != 0) {
			goto error;
		}

		next_addr += sizeof (entry);
		i++;
	} while ((entry.type_id != MANIFEST_PLATFORM_ID) && (i < toc_header->entry_count));

	if (entry.type_id != MANIFEST_PLATFORM_ID) {
		status = MANIFEST_NO_PLATFORM_ID;
		goto error;
	}

	/* Hash the flash contents for the rest of the table of contents. */
	toc_end = manifest->addr + sizeof (manifest->state->header) + sizeof (*toc_header) +
		(toc_header->entry_count * sizeof (entry)) +
		(toc_header->hash_count * manifest->state->toc_hash_length);
	status = flash_hash_update_contents (manifest->flash, next_addr, toc_end - next_addr, hash);
	if (status != 0) {
		goto error;
	}

	/* Read and hash the table of contents hash. */
	next_addr = toc_end;
	status = manifest->flash->read (manifest->flash, next_addr, manifest->state->toc_hash,
		manifest->state->toc_hash_length);
	if (status != 0) {
		goto error;
	}

	status = hash->update (hash, manifest->state->toc_hash, manifest->state->toc_hash_length);
	if (status != 0) {
		goto error;
	}

	/* Hash the flash contents until the platform ID element. */
	next_addr += manifest->state->toc_hash_length;
	status = flash_hash_update_contents (manifest->flash, next_addr,
		manifest->addr + entry.offset - next_addr, hash);
	if (status != 0) {
		goto error;
	}

	/* Read and hash the platform ID element header. */
	next_addr = manifest->addr + entry.offset;
	status = manifest->flash->read (manifest->flash, next_addr, (uint8_t*) &plat_id_header,
		sizeof (plat_id_header));
	if (status != 0) {
		goto error;
	}

	if (plat_id_header.id_length > manifest->max_platform_id) {
		status = MANIFEST_PLAT_ID_BUFFER_TOO_SMALL;
		goto error;
	}

	status = hash->update (hash, (uint8_t*) &plat_id_header, sizeof (plat_id_header));
	if (status != 0) {
		goto error;
	}

	/* Read and hash the platform ID string. */
	next_addr += sizeof (plat_id_header);
	status = manifest->flash->read (manifest->flash, next_addr, (uint8_t*) manifest->platform_id,
		plat_id_header.id_length);
	if (status != 0) {
		goto error;
	}

	manifest->platform_id[plat_id_header.id_length] = '\0';
	status = hash->update (hash, (uint8_t*) manifest->platform_id, plat_id_header.id_length);
	if (status != 0) {
		goto error;
	}

	/* Hash the remaining manifest flash contents. */
	next_addr += plat_id_header.id_length;
	status = flash_hash_update_contents (manifest->flash, next_addr, sig_addr - next_addr, hash);
	if (status != 0) {
		goto error;
	}

	/* Verify the signature of the overall manifest data. */
	status = signature_verification_verify_hash_and_finish_save_digest (verification, hash, NULL, 0,
		manifest->signature, manifest->state->header.sig_length, manifest->state->hash_cache,
		sizeof (manifest->state->hash_cache), &manifest->state->cache_valid);

	if (manifest->state->cache_valid && hash_out) {
		memcpy (hash_out, manifest->state->hash_cache, manifest->state->hash_length);
	}

	return status;

error:
	hash->cancel (hash);

	return status;
}