123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- /*
- * Copyright 2015 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- #include <errno.h>
- #include <getopt.h>
- #include <inttypes.h>
- #include <stddef.h>
- #include <stdint.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/stat.h>
- #include <sys/types.h>
- #include <unistd.h>
- #include "2sysincludes.h"
- #include "2common.h"
- #include "2sha.h"
- #include "futility.h"
- #include "gbb_header.h"
- #define SEARCH_STRIDE 4
- /**
- * Check if the pointer contains the magic string. We need to use a
- * case-swapped version, so that the actual magic string doesn't appear in the
- * code, to avoid falsely finding it when searching for the struct.
- */
- static int is_magic(const void *ptr)
- {
- const char magic_inv[RYU_ROOT_KEY_HASH_MAGIC_SIZE] =
- RYU_ROOT_KEY_HASH_MAGIC_INVCASE;
- const char *magic = ptr;
- int i;
- for (i = 0; i < RYU_ROOT_KEY_HASH_MAGIC_SIZE; i++) {
- if (magic[i] != (magic_inv[i] ^ 0x20))
- return 0;
- }
- return 1;
- }
- static int valid_ryu_root_header(struct vb2_ryu_root_key_hash *hash,
- size_t size)
- {
- if (!is_magic(hash->magic))
- return 0; /* Wrong magic */
- if (hash->header_version_major != RYU_ROOT_KEY_HASH_VERSION_MAJOR)
- return 0; /* Version we can't parse */
- if (hash->struct_size < EXPECTED_VB2_RYU_ROOT_KEY_HASH_SIZE)
- return 0; /* Header too small */
- if (hash->struct_size > size)
- return 0; /* Claimed size doesn't fit in buffer */
- return 1;
- }
- /**
- * Find the root key hash struct and return it or NULL if error.
- */
- static struct vb2_ryu_root_key_hash *find_ryu_root_header(uint8_t *ptr,
- size_t size)
- {
- size_t i;
- struct vb2_ryu_root_key_hash *tmp, *hash = NULL;
- int count = 0;
- /* Look for the ryu root key hash header */
- for (i = 0; i <= size - SEARCH_STRIDE; i += SEARCH_STRIDE) {
- if (!is_magic(ptr + i))
- continue;
- /* Found something. See if it's any good. */
- tmp = (struct vb2_ryu_root_key_hash *) (ptr + i);
- if (valid_ryu_root_header(tmp, size - i))
- if (!count++)
- hash = tmp;
- }
- switch (count) {
- case 0:
- return NULL;
- case 1:
- return hash;
- default:
- fprintf(stderr,
- "WARNING: multiple ryu root hash headers found\n");
- /* But hey, it's only a warning. Use the first one. */
- return hash;
- }
- }
- static void calculate_root_key_hash(uint8_t *digest, size_t digest_size,
- const GoogleBinaryBlockHeader *gbb)
- {
- const uint8_t *gbb_base = (const uint8_t *)gbb;
- vb2_digest_buffer(gbb_base + gbb->rootkey_offset,
- gbb->rootkey_size,
- VB2_HASH_SHA256,
- digest,
- digest_size);
- }
- int fill_ryu_root_header(uint8_t *ptr, size_t size,
- const GoogleBinaryBlockHeader *gbb)
- {
- struct vb2_ryu_root_key_hash *hash;
- /*
- * Find the ryu root header. If not found, nothing we can do, but
- * that's ok because most images don't have the header.
- */
- hash = find_ryu_root_header(ptr, size);
- if (!hash)
- return 0;
- /* Update the hash stored in the header based on the root key */
- calculate_root_key_hash(hash->root_key_hash_digest,
- sizeof(hash->root_key_hash_digest),
- gbb);
- printf(" - calculate ryu root hash: success\n");
- return 0;
- }
- int verify_ryu_root_header(uint8_t *ptr, size_t size,
- const GoogleBinaryBlockHeader *gbb)
- {
- uint8_t digest[VB2_SHA256_DIGEST_SIZE] = {0};
- struct vb2_ryu_root_key_hash *hash;
- /*
- * Find the ryu root header. If not found, nothing we can do, but
- * that's ok because most images don't have the header.
- */
- hash = find_ryu_root_header(ptr, size);
- if (!hash) {
- printf(" - ryu root hash not found\n");
- return 0;
- }
- /* Check for all 0's, which means hash hasn't been set */
- if (0 == memcmp(digest, hash->root_key_hash_digest, sizeof(digest))) {
- printf(" - ryu root hash is unset\n");
- return 0;
- }
- /* Update the hash stored in the header based on the root key */
- calculate_root_key_hash(digest, sizeof(digest), gbb);
- if (0 == memcmp(digest, hash->root_key_hash_digest, sizeof(digest))) {
- printf(" - ryu root hash verified\n");
- return 0;
- } else {
- printf(" - ryu root hash does not verify\n");
- return -1;
- }
- }
|