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