vboot_common.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. /* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
  2. * Use of this source code is governed by a BSD-style license that can be
  3. * found in the LICENSE file.
  4. *
  5. * Common functions between firmware and kernel verified boot.
  6. * (Firmware portion)
  7. */
  8. #include "sysincludes.h"
  9. #include "2sysincludes.h"
  10. #include "2common.h"
  11. #include "2rsa.h"
  12. #include "2sha.h"
  13. #include "vboot_api.h"
  14. #include "vboot_common.h"
  15. #include "utility.h"
  16. const char *kVbootErrors[VBOOT_ERROR_MAX] = {
  17. "Success.",
  18. "Key block invalid.",
  19. "Key block signature failed.",
  20. "Key block hash failed.",
  21. "Public key invalid.",
  22. "Preamble invalid.",
  23. "Preamble signature check failed.",
  24. "Shared data invalid."
  25. };
  26. uint64_t OffsetOf(const void *base, const void *ptr)
  27. {
  28. return (uint64_t)(size_t)ptr - (uint64_t)(size_t)base;
  29. }
  30. /* Helper functions to get data pointed to by a public key or signature. */
  31. uint8_t *GetPublicKeyData(VbPublicKey *key)
  32. {
  33. return (uint8_t *)key + key->key_offset;
  34. }
  35. const uint8_t *GetPublicKeyDataC(const VbPublicKey *key)
  36. {
  37. return (const uint8_t *)key + key->key_offset;
  38. }
  39. uint8_t *GetSignatureData(VbSignature *sig)
  40. {
  41. return (uint8_t *)sig + sig->sig_offset;
  42. }
  43. const uint8_t *GetSignatureDataC(const VbSignature *sig)
  44. {
  45. return (const uint8_t *)sig + sig->sig_offset;
  46. }
  47. /*
  48. * Helper functions to verify the data pointed to by a subfield is inside
  49. * the parent data. Returns 0 if inside, 1 if error.
  50. */
  51. int VerifyMemberInside(const void *parent, uint64_t parent_size,
  52. const void *member, uint64_t member_size,
  53. uint64_t member_data_offset,
  54. uint64_t member_data_size)
  55. {
  56. uint64_t end = OffsetOf(parent, member);
  57. if (end > parent_size)
  58. return 1;
  59. if (UINT64_MAX - end < member_size)
  60. return 1; /* Detect wraparound in integer math */
  61. if (end + member_size > parent_size)
  62. return 1;
  63. if (UINT64_MAX - end < member_data_offset)
  64. return 1;
  65. end += member_data_offset;
  66. if (end > parent_size)
  67. return 1;
  68. if (UINT64_MAX - end < member_data_size)
  69. return 1;
  70. if (end + member_data_size > parent_size)
  71. return 1;
  72. return 0;
  73. }
  74. int VerifyPublicKeyInside(const void *parent, uint64_t parent_size,
  75. const VbPublicKey *key)
  76. {
  77. return VerifyMemberInside(parent, parent_size,
  78. key, sizeof(VbPublicKey),
  79. key->key_offset, key->key_size);
  80. }
  81. int VerifySignatureInside(const void *parent, uint64_t parent_size,
  82. const VbSignature *sig)
  83. {
  84. return VerifyMemberInside(parent, parent_size,
  85. sig, sizeof(VbSignature),
  86. sig->sig_offset, sig->sig_size);
  87. }
  88. void PublicKeyInit(VbPublicKey *key, uint8_t *key_data, uint64_t key_size)
  89. {
  90. key->key_offset = OffsetOf(key, key_data);
  91. key->key_size = key_size;
  92. key->algorithm = VB2_ALG_COUNT; /* Key not present yet */
  93. key->key_version = 0;
  94. }
  95. int PublicKeyCopy(VbPublicKey *dest, const VbPublicKey *src)
  96. {
  97. if (dest->key_size < src->key_size)
  98. return 1;
  99. dest->key_size = src->key_size;
  100. dest->algorithm = src->algorithm;
  101. dest->key_version = src->key_version;
  102. memcpy(GetPublicKeyData(dest), GetPublicKeyDataC(src), src->key_size);
  103. return 0;
  104. }
  105. int VbGetKernelVmlinuzHeader(const VbKernelPreambleHeader *preamble,
  106. uint64_t *vmlinuz_header_address,
  107. uint64_t *vmlinuz_header_size)
  108. {
  109. *vmlinuz_header_address = 0;
  110. *vmlinuz_header_size = 0;
  111. if (preamble->header_version_minor > 0) {
  112. /*
  113. * Set header and size only if the preamble header version is >
  114. * 2.1 as they don't exist in version 2.0 (Note that we don't
  115. * need to check header_version_major; if that's not 2 then
  116. * VerifyKernelPreamble() would have already failed.
  117. */
  118. *vmlinuz_header_address = preamble->vmlinuz_header_address;
  119. *vmlinuz_header_size = preamble->vmlinuz_header_size;
  120. }
  121. return VBOOT_SUCCESS;
  122. }
  123. int VbKernelHasFlags(const VbKernelPreambleHeader *preamble)
  124. {
  125. if (preamble->header_version_minor > 1)
  126. return VBOOT_SUCCESS;
  127. return VBOOT_KERNEL_PREAMBLE_NO_FLAGS;
  128. }
  129. int VerifyVmlinuzInsideKBlob(uint64_t kblob, uint64_t kblob_size,
  130. uint64_t header, uint64_t header_size)
  131. {
  132. uint64_t end = header-kblob;
  133. if (end > kblob_size)
  134. return VBOOT_PREAMBLE_INVALID;
  135. if (UINT64_MAX - end < header_size)
  136. return VBOOT_PREAMBLE_INVALID;
  137. if (end + header_size > kblob_size)
  138. return VBOOT_PREAMBLE_INVALID;
  139. return VBOOT_SUCCESS;
  140. }
  141. uint64_t VbSharedDataReserve(VbSharedDataHeader *header, uint64_t size)
  142. {
  143. if (!header || size > header->data_size - header->data_used) {
  144. VB2_DEBUG("VbSharedData buffer out of space.\n");
  145. return 0; /* Not initialized, or not enough space left. */
  146. }
  147. uint64_t offs = header->data_used;
  148. VB2_DEBUG("VbSharedDataReserve %d bytes at %d\n", (int)size, (int)offs);
  149. header->data_used += size;
  150. return offs;
  151. }
  152. int VbSharedDataSetKernelKey(VbSharedDataHeader *header, const VbPublicKey *src)
  153. {
  154. VbPublicKey *kdest;
  155. if (!header)
  156. return VBOOT_SHARED_DATA_INVALID;
  157. if (!src)
  158. return VBOOT_PUBLIC_KEY_INVALID;
  159. kdest = &header->kernel_subkey;
  160. VB2_DEBUG("Saving kernel subkey to shared data: size %d, algo %d\n",
  161. vb2_rsa_sig_size(vb2_crypto_to_signature(src->algorithm)),
  162. (int)src->algorithm);
  163. /* Attempt to allocate space for key, if it hasn't been allocated yet */
  164. if (!header->kernel_subkey_data_offset) {
  165. header->kernel_subkey_data_offset =
  166. VbSharedDataReserve(header, src->key_size);
  167. if (!header->kernel_subkey_data_offset)
  168. return VBOOT_SHARED_DATA_INVALID;
  169. header->kernel_subkey_data_size = src->key_size;
  170. }
  171. /* Copy the kernel sign key blob into the destination buffer */
  172. PublicKeyInit(kdest,
  173. (uint8_t *)header + header->kernel_subkey_data_offset,
  174. header->kernel_subkey_data_size);
  175. return PublicKeyCopy(kdest, src);
  176. }