bdb.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. /* Copyright (c) 2015 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. * Boot descriptor block firmware functions
  6. */
  7. #include <string.h>
  8. #include "bdb.h"
  9. /*****************************************************************************/
  10. /**
  11. * Check if string contains a null terminator.
  12. *
  13. * Bytes after the null terminator do not need to be null.
  14. *
  15. * @param s String to check
  16. * @param size Size of string buffer in characters
  17. * @return 1 if string has a null terminator, 0 if not
  18. */
  19. int string_has_null(const char *s, size_t size)
  20. {
  21. for (; size; size--) {
  22. if (*s++ == 0)
  23. return 1;
  24. }
  25. return 0;
  26. }
  27. int bdb_check_header(const struct bdb_header *p, size_t size)
  28. {
  29. if (size < sizeof(*p) || size < p->struct_size)
  30. return BDB_ERROR_BUF_SIZE;
  31. if (p->struct_magic != BDB_HEADER_MAGIC)
  32. return BDB_ERROR_STRUCT_MAGIC;
  33. if (p->struct_major_version != BDB_HEADER_VERSION_MAJOR)
  34. return BDB_ERROR_STRUCT_VERSION;
  35. /* Note that minor version doesn't matter yet */
  36. if (p->struct_size < sizeof(*p))
  37. return BDB_ERROR_STRUCT_SIZE;
  38. if (p->oem_area_0_size & 3)
  39. return BDB_ERROR_OEM_AREA_SIZE; /* Not 32-bit aligned */
  40. /*
  41. * Make sure the BDB is at least big enough for us. At this point, all
  42. * the caller may have loaded is this header We'll check if there's
  43. * space for everything else after we load it.
  44. */
  45. if (p->bdb_size < sizeof(*p))
  46. return BDB_ERROR_BDB_SIZE;
  47. /*
  48. * The rest of the fields don't matter yet; we'll check them when we
  49. * check the BDB itself.
  50. */
  51. return BDB_SUCCESS;
  52. }
  53. int bdb_check_key(const struct bdb_key *p, size_t size)
  54. {
  55. size_t expect_key_size = 0;
  56. if (size < sizeof(*p) || size < p->struct_size)
  57. return BDB_ERROR_BUF_SIZE;
  58. if (p->struct_magic != BDB_KEY_MAGIC)
  59. return BDB_ERROR_STRUCT_MAGIC;
  60. if (p->struct_major_version != BDB_KEY_VERSION_MAJOR)
  61. return BDB_ERROR_STRUCT_VERSION;
  62. /* Note that minor version doesn't matter yet */
  63. if (!string_has_null(p->description, sizeof(p->description)))
  64. return BDB_ERROR_DESCRIPTION;
  65. /* We currently only support SHA-256 */
  66. if (p->hash_alg != BDB_HASH_ALG_SHA256)
  67. return BDB_ERROR_HASH_ALG;
  68. /* Make sure signature algorithm and size are correct */
  69. switch (p->sig_alg) {
  70. case BDB_SIG_ALG_RSA4096:
  71. expect_key_size = BDB_RSA4096_KEY_DATA_SIZE;
  72. break;
  73. case BDB_SIG_ALG_ECSDSA521:
  74. expect_key_size = BDB_ECDSA521_KEY_DATA_SIZE;
  75. break;
  76. case BDB_SIG_ALG_RSA3072B:
  77. expect_key_size = BDB_RSA3072B_KEY_DATA_SIZE;
  78. break;
  79. default:
  80. return BDB_ERROR_SIG_ALG;
  81. }
  82. if (p->struct_size < sizeof(*p) + expect_key_size)
  83. return BDB_ERROR_STRUCT_SIZE;
  84. return BDB_SUCCESS;
  85. }
  86. int bdb_check_sig(const struct bdb_sig *p, size_t size)
  87. {
  88. size_t expect_sig_size = 0;
  89. if (size < sizeof(*p) || size < p->struct_size)
  90. return BDB_ERROR_BUF_SIZE;
  91. if (p->struct_magic != BDB_SIG_MAGIC)
  92. return BDB_ERROR_STRUCT_MAGIC;
  93. if (p->struct_major_version != BDB_SIG_VERSION_MAJOR)
  94. return BDB_ERROR_STRUCT_VERSION;
  95. /* Note that minor version doesn't matter yet */
  96. if (!string_has_null(p->description, sizeof(p->description)))
  97. return BDB_ERROR_DESCRIPTION;
  98. /* We currently only support SHA-256 */
  99. if (p->hash_alg != BDB_HASH_ALG_SHA256)
  100. return BDB_ERROR_HASH_ALG;
  101. /* Make sure signature algorithm and size are correct */
  102. switch (p->sig_alg) {
  103. case BDB_SIG_ALG_RSA4096:
  104. expect_sig_size = BDB_RSA4096_SIG_SIZE;
  105. break;
  106. case BDB_SIG_ALG_ECSDSA521:
  107. expect_sig_size = BDB_ECDSA521_SIG_SIZE;
  108. break;
  109. case BDB_SIG_ALG_RSA3072B:
  110. expect_sig_size = BDB_RSA3072B_SIG_SIZE;
  111. break;
  112. default:
  113. return BDB_ERROR_SIG_ALG;
  114. }
  115. if (p->struct_size < sizeof(*p) + expect_sig_size)
  116. return BDB_ERROR_STRUCT_SIZE;
  117. return BDB_SUCCESS;
  118. }
  119. int bdb_check_data(const struct bdb_data *p, size_t size)
  120. {
  121. size_t need_size;
  122. if (size < sizeof(*p) || size < p->signed_size)
  123. return BDB_ERROR_BUF_SIZE;
  124. if (p->struct_magic != BDB_DATA_MAGIC)
  125. return BDB_ERROR_STRUCT_MAGIC;
  126. if (p->struct_major_version != BDB_DATA_VERSION_MAJOR)
  127. return BDB_ERROR_STRUCT_VERSION;
  128. /* Note that minor version doesn't matter yet */
  129. if (!string_has_null(p->description, sizeof(p->description)))
  130. return BDB_ERROR_DESCRIPTION;
  131. if (p->struct_size < sizeof(*p))
  132. return BDB_ERROR_STRUCT_SIZE;
  133. if (p->hash_entry_size < sizeof(struct bdb_hash))
  134. return BDB_ERROR_HASH_ENTRY_SIZE;
  135. /* Calculate expected size */
  136. need_size = p->struct_size + p->num_hashes * p->hash_entry_size;
  137. /* Make sure OEM area size doesn't cause wraparound */
  138. if (need_size + p->oem_area_1_size < need_size)
  139. return BDB_ERROR_OEM_AREA_SIZE;
  140. if (p->oem_area_1_size & 3)
  141. return BDB_ERROR_OEM_AREA_SIZE; /* Not 32-bit aligned */
  142. need_size += p->oem_area_1_size;
  143. if (p->signed_size < need_size)
  144. return BDB_ERROR_SIGNED_SIZE;
  145. return BDB_SUCCESS;
  146. }
  147. /*****************************************************************************/
  148. const struct bdb_header *bdb_get_header(const void *buf)
  149. {
  150. return buf;
  151. }
  152. const struct bdb_key *bdb_get_bdbkey(const void *buf)
  153. {
  154. const struct bdb_header *h = bdb_get_header(buf);
  155. const uint8_t *b8 = buf;
  156. /* BDB key follows header */
  157. return (const struct bdb_key *)(b8 + h->struct_size);
  158. }
  159. const void *bdb_get_oem_area_0(const void *buf)
  160. {
  161. const struct bdb_key *k = bdb_get_bdbkey(buf);
  162. const uint8_t *b8 = (const uint8_t *)k;
  163. /* OEM area 0 follows BDB key */
  164. return b8 + k->struct_size;
  165. }
  166. const struct bdb_key *bdb_get_subkey(const void *buf)
  167. {
  168. const struct bdb_header *h = bdb_get_header(buf);
  169. const uint8_t *b8 = bdb_get_oem_area_0(buf);
  170. /* Subkey follows OEM area 0 */
  171. return (const struct bdb_key *)(b8 + h->oem_area_0_size);
  172. }
  173. const struct bdb_sig *bdb_get_header_sig(const void *buf)
  174. {
  175. const struct bdb_header *h = bdb_get_header(buf);
  176. const uint8_t *b8 = bdb_get_oem_area_0(buf);
  177. /* Header signature starts after signed data */
  178. return (const struct bdb_sig *)(b8 + h->signed_size);
  179. }
  180. const struct bdb_data *bdb_get_data(const void *buf)
  181. {
  182. const struct bdb_sig *s = bdb_get_header_sig(buf);
  183. const uint8_t *b8 = (const uint8_t *)s;
  184. /* Data follows header signature */
  185. return (const struct bdb_data *)(b8 + s->struct_size);
  186. }
  187. const void *bdb_get_oem_area_1(const void *buf)
  188. {
  189. const struct bdb_data *p = bdb_get_data(buf);
  190. const uint8_t *b8 = (const uint8_t *)p;
  191. /* OEM area 1 follows BDB data */
  192. return b8 + p->struct_size;
  193. }
  194. const struct bdb_hash *bdb_get_hash(const void *buf, enum bdb_data_type type)
  195. {
  196. const struct bdb_data *data = bdb_get_data(buf);
  197. const uint8_t *b8 = bdb_get_oem_area_1(buf);
  198. int i;
  199. /* Hashes follow OEM area 0 */
  200. b8 += data->oem_area_1_size;
  201. /* Search for a matching hash */
  202. for (i = 0; i < data->num_hashes; i++, b8 += data->hash_entry_size) {
  203. const struct bdb_hash *h = (const struct bdb_hash *)b8;
  204. if (h->type == type)
  205. return h;
  206. }
  207. return NULL;
  208. }
  209. const struct bdb_sig *bdb_get_data_sig(const void *buf)
  210. {
  211. const struct bdb_data *data = bdb_get_data(buf);
  212. const uint8_t *b8 = (const uint8_t *)data;
  213. /* Data signature starts after signed data */
  214. return (const struct bdb_sig *)(b8 + data->signed_size);
  215. }
  216. /*****************************************************************************/
  217. int bdb_verify_sig(const struct bdb_key *key,
  218. const struct bdb_sig *sig,
  219. const uint8_t *digest)
  220. {
  221. /* Key and signature algorithms must match */
  222. if (key->sig_alg != sig->sig_alg)
  223. return BDB_ERROR_SIG_ALG;
  224. switch (key->sig_alg) {
  225. case BDB_SIG_ALG_RSA4096:
  226. if (bdb_rsa4096_verify(key->key_data, sig->sig_data, digest))
  227. return BDB_ERROR_VERIFY_SIG;
  228. break;
  229. case BDB_SIG_ALG_ECSDSA521:
  230. if (bdb_ecdsa521_verify(key->key_data, sig->sig_data, digest))
  231. return BDB_ERROR_VERIFY_SIG;
  232. break;
  233. case BDB_SIG_ALG_RSA3072B:
  234. if (bdb_rsa3072b_verify(key->key_data, sig->sig_data, digest))
  235. return BDB_ERROR_VERIFY_SIG;
  236. break;
  237. default:
  238. return BDB_ERROR_VERIFY_SIG;
  239. }
  240. return BDB_SUCCESS;
  241. }
  242. int bdb_verify(const void *buf, size_t size, const uint8_t *bdb_key_digest)
  243. {
  244. const uint8_t *end = (const uint8_t *)buf + size;
  245. const struct bdb_header *h;
  246. const struct bdb_key *bdbkey, *subkey;
  247. const struct bdb_sig *sig;
  248. const struct bdb_data *data;
  249. const void *oem;
  250. uint8_t digest[BDB_SHA256_DIGEST_SIZE];
  251. int bdb_digest_mismatch;
  252. /* Make sure buffer doesn't wrap around address space */
  253. if (end < (const uint8_t *)buf)
  254. return BDB_ERROR_BUF_SIZE;
  255. /*
  256. * Check header now that we've actually loaded it. We can't guarantee
  257. * this is the same header which was checked before.
  258. */
  259. h = bdb_get_header(buf);
  260. if (bdb_check_header(h, size))
  261. return BDB_ERROR_HEADER;
  262. /* Sanity-check BDB key */
  263. bdbkey = bdb_get_bdbkey(buf);
  264. if (bdb_check_key(bdbkey, end - (const uint8_t *)bdbkey))
  265. return BDB_ERROR_BDBKEY;
  266. /* Calculate BDB key digest and compare with expected */
  267. if (bdb_sha256(digest, bdbkey, bdbkey->struct_size))
  268. return BDB_ERROR_DIGEST;
  269. bdb_digest_mismatch = memcmp(digest, bdb_key_digest, sizeof(digest));
  270. /* Make sure OEM area 0 fits */
  271. oem = bdb_get_oem_area_0(buf);
  272. if (h->oem_area_0_size > end - (const uint8_t *)oem)
  273. return BDB_ERROR_OEM_AREA_0;
  274. /* Sanity-check subkey */
  275. subkey = bdb_get_subkey(buf);
  276. if (bdb_check_key(subkey, end - (const uint8_t *)subkey))
  277. return BDB_ERROR_SUBKEY;
  278. /* Make sure enough data was signed, and the signed data fits */
  279. if (h->oem_area_0_size + subkey->struct_size > h->signed_size ||
  280. h->signed_size > end - (const uint8_t *)oem)
  281. return BDB_ERROR_BDB_SIGNED_SIZE;
  282. /* Sanity-check header signature */
  283. sig = bdb_get_header_sig(buf);
  284. if (bdb_check_sig(sig, end - (const uint8_t *)sig))
  285. return BDB_ERROR_HEADER_SIG;
  286. /* Make sure it signed the right amount of data */
  287. if (sig->signed_size != h->signed_size)
  288. return BDB_ERROR_HEADER_SIG;
  289. /* Calculate header digest and compare with expected signature */
  290. if (bdb_sha256(digest, oem, h->signed_size))
  291. return BDB_ERROR_DIGEST;
  292. if (bdb_verify_sig(bdbkey, sig, digest))
  293. return BDB_ERROR_HEADER_SIG;
  294. /*
  295. * Sanity-check data struct. This also checks that OEM area 1 and the
  296. * hashes fit in the remaining buffer.
  297. */
  298. data = bdb_get_data(buf);
  299. if (bdb_check_data(data, end - (const uint8_t *)data))
  300. return BDB_ERROR_DATA;
  301. /* Sanity-check data signature */
  302. sig = bdb_get_data_sig(buf);
  303. if (bdb_check_sig(sig, end - (const uint8_t *)sig))
  304. return BDB_ERROR_DATA_SIG;
  305. if (sig->signed_size != data->signed_size)
  306. return BDB_ERROR_DATA_SIG;
  307. /* Calculate data digest and compare with expected signature */
  308. if (bdb_sha256(digest, data, data->signed_size))
  309. return BDB_ERROR_DIGEST;
  310. if (bdb_verify_sig(subkey, sig, digest))
  311. return BDB_ERROR_DATA_SIG;
  312. /* Return success or success-other-than-BDB-key-mismatch */
  313. return bdb_digest_mismatch ? BDB_GOOD_OTHER_THAN_KEY : BDB_SUCCESS;
  314. }