ryu_root_header.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /*
  2. * Copyright 2015 The Chromium OS Authors. All rights reserved.
  3. * Use of this source code is governed by a BSD-style license that can be
  4. * found in the LICENSE file.
  5. */
  6. #include <errno.h>
  7. #include <getopt.h>
  8. #include <inttypes.h>
  9. #include <stddef.h>
  10. #include <stdint.h>
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include <sys/stat.h>
  15. #include <sys/types.h>
  16. #include <unistd.h>
  17. #include "2sysincludes.h"
  18. #include "2common.h"
  19. #include "2sha.h"
  20. #include "futility.h"
  21. #include "gbb_header.h"
  22. #define SEARCH_STRIDE 4
  23. /**
  24. * Check if the pointer contains the magic string. We need to use a
  25. * case-swapped version, so that the actual magic string doesn't appear in the
  26. * code, to avoid falsely finding it when searching for the struct.
  27. */
  28. static int is_magic(const void *ptr)
  29. {
  30. const char magic_inv[RYU_ROOT_KEY_HASH_MAGIC_SIZE] =
  31. RYU_ROOT_KEY_HASH_MAGIC_INVCASE;
  32. const char *magic = ptr;
  33. int i;
  34. for (i = 0; i < RYU_ROOT_KEY_HASH_MAGIC_SIZE; i++) {
  35. if (magic[i] != (magic_inv[i] ^ 0x20))
  36. return 0;
  37. }
  38. return 1;
  39. }
  40. static int valid_ryu_root_header(struct vb2_ryu_root_key_hash *hash,
  41. size_t size)
  42. {
  43. if (!is_magic(hash->magic))
  44. return 0; /* Wrong magic */
  45. if (hash->header_version_major != RYU_ROOT_KEY_HASH_VERSION_MAJOR)
  46. return 0; /* Version we can't parse */
  47. if (hash->struct_size < EXPECTED_VB2_RYU_ROOT_KEY_HASH_SIZE)
  48. return 0; /* Header too small */
  49. if (hash->struct_size > size)
  50. return 0; /* Claimed size doesn't fit in buffer */
  51. return 1;
  52. }
  53. /**
  54. * Find the root key hash struct and return it or NULL if error.
  55. */
  56. static struct vb2_ryu_root_key_hash *find_ryu_root_header(uint8_t *ptr,
  57. size_t size)
  58. {
  59. size_t i;
  60. struct vb2_ryu_root_key_hash *tmp, *hash = NULL;
  61. int count = 0;
  62. /* Look for the ryu root key hash header */
  63. for (i = 0; i <= size - SEARCH_STRIDE; i += SEARCH_STRIDE) {
  64. if (!is_magic(ptr + i))
  65. continue;
  66. /* Found something. See if it's any good. */
  67. tmp = (struct vb2_ryu_root_key_hash *) (ptr + i);
  68. if (valid_ryu_root_header(tmp, size - i))
  69. if (!count++)
  70. hash = tmp;
  71. }
  72. switch (count) {
  73. case 0:
  74. return NULL;
  75. case 1:
  76. return hash;
  77. default:
  78. fprintf(stderr,
  79. "WARNING: multiple ryu root hash headers found\n");
  80. /* But hey, it's only a warning. Use the first one. */
  81. return hash;
  82. }
  83. }
  84. static void calculate_root_key_hash(uint8_t *digest, size_t digest_size,
  85. const GoogleBinaryBlockHeader *gbb)
  86. {
  87. const uint8_t *gbb_base = (const uint8_t *)gbb;
  88. vb2_digest_buffer(gbb_base + gbb->rootkey_offset,
  89. gbb->rootkey_size,
  90. VB2_HASH_SHA256,
  91. digest,
  92. digest_size);
  93. }
  94. int fill_ryu_root_header(uint8_t *ptr, size_t size,
  95. const GoogleBinaryBlockHeader *gbb)
  96. {
  97. struct vb2_ryu_root_key_hash *hash;
  98. /*
  99. * Find the ryu root header. If not found, nothing we can do, but
  100. * that's ok because most images don't have the header.
  101. */
  102. hash = find_ryu_root_header(ptr, size);
  103. if (!hash)
  104. return 0;
  105. /* Update the hash stored in the header based on the root key */
  106. calculate_root_key_hash(hash->root_key_hash_digest,
  107. sizeof(hash->root_key_hash_digest),
  108. gbb);
  109. printf(" - calculate ryu root hash: success\n");
  110. return 0;
  111. }
  112. int verify_ryu_root_header(uint8_t *ptr, size_t size,
  113. const GoogleBinaryBlockHeader *gbb)
  114. {
  115. uint8_t digest[VB2_SHA256_DIGEST_SIZE] = {0};
  116. struct vb2_ryu_root_key_hash *hash;
  117. /*
  118. * Find the ryu root header. If not found, nothing we can do, but
  119. * that's ok because most images don't have the header.
  120. */
  121. hash = find_ryu_root_header(ptr, size);
  122. if (!hash) {
  123. printf(" - ryu root hash not found\n");
  124. return 0;
  125. }
  126. /* Check for all 0's, which means hash hasn't been set */
  127. if (0 == memcmp(digest, hash->root_key_hash_digest, sizeof(digest))) {
  128. printf(" - ryu root hash is unset\n");
  129. return 0;
  130. }
  131. /* Update the hash stored in the header based on the root key */
  132. calculate_root_key_hash(digest, sizeof(digest), gbb);
  133. if (0 == memcmp(digest, hash->root_key_hash_digest, sizeof(digest))) {
  134. printf(" - ryu root hash verified\n");
  135. return 0;
  136. } else {
  137. printf(" - ryu root hash does not verify\n");
  138. return -1;
  139. }
  140. }