bdb_test.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  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. * Unit tests
  6. */
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include "bdb.h"
  11. #include "host.h"
  12. #define TEST_EQ(got, want) test_eq(got, want, #got, #want, __LINE__)
  13. void test_eq(int got, int want, const char *gotstr, const char *wantstr,
  14. int line)
  15. {
  16. if (got == want)
  17. return;
  18. fprintf(stderr, "Fail(%d): %s != %s\n"
  19. "got: 0x%08x (%d)\n"
  20. "wanted: 0x%08x (%d)\n",
  21. line, gotstr, wantstr, got, got, want, want);
  22. exit(1);
  23. }
  24. void check_header_tests(void)
  25. {
  26. struct bdb_header sgood = {
  27. .struct_magic = BDB_HEADER_MAGIC,
  28. .struct_major_version = BDB_HEADER_VERSION_MAJOR,
  29. .struct_minor_version = BDB_HEADER_VERSION_MINOR,
  30. .struct_size = sizeof(struct bdb_header),
  31. .bdb_load_address = -1,
  32. .bdb_size = 1024,
  33. .signed_size = 512,
  34. .oem_area_0_size = 256,
  35. };
  36. const size_t ssize = sgood.struct_size;
  37. struct bdb_header s;
  38. s = sgood;
  39. TEST_EQ(bdb_check_header(&s, ssize), BDB_SUCCESS);
  40. TEST_EQ(bdb_check_header(&s, ssize - 1), BDB_ERROR_BUF_SIZE);
  41. s = sgood;
  42. s.struct_size++;
  43. TEST_EQ(bdb_check_header(&s, ssize), BDB_ERROR_BUF_SIZE);
  44. s = sgood;
  45. s.struct_size--;
  46. TEST_EQ(bdb_check_header(&s, ssize), BDB_ERROR_STRUCT_SIZE);
  47. s = sgood;
  48. s.struct_magic++;
  49. TEST_EQ(bdb_check_header(&s, ssize), BDB_ERROR_STRUCT_MAGIC);
  50. s = sgood;
  51. s.struct_major_version++;
  52. TEST_EQ(bdb_check_header(&s, ssize), BDB_ERROR_STRUCT_VERSION);
  53. s = sgood;
  54. s.oem_area_0_size++;
  55. TEST_EQ(bdb_check_header(&s, ssize), BDB_ERROR_OEM_AREA_SIZE);
  56. s = sgood;
  57. s.bdb_size = ssize - 1;
  58. TEST_EQ(bdb_check_header(&s, ssize), BDB_ERROR_BDB_SIZE);
  59. }
  60. void check_key_tests(void)
  61. {
  62. struct bdb_key sgood = {
  63. .struct_magic = BDB_KEY_MAGIC,
  64. .struct_major_version = BDB_KEY_VERSION_MAJOR,
  65. .struct_minor_version = BDB_KEY_VERSION_MINOR,
  66. .struct_size = (sizeof(struct bdb_key) +
  67. BDB_RSA4096_KEY_DATA_SIZE),
  68. .hash_alg = BDB_HASH_ALG_SHA256,
  69. .sig_alg = BDB_SIG_ALG_RSA4096,
  70. .key_version = 1,
  71. .description = "Test key",
  72. };
  73. const size_t ssize = sgood.struct_size;
  74. struct bdb_key s;
  75. s = sgood;
  76. TEST_EQ(bdb_check_key(&s, ssize), BDB_SUCCESS);
  77. TEST_EQ(bdb_check_key(&s, ssize - 1), BDB_ERROR_BUF_SIZE);
  78. s = sgood;
  79. s.struct_size++;
  80. TEST_EQ(bdb_check_key(&s, ssize), BDB_ERROR_BUF_SIZE);
  81. s = sgood;
  82. s.struct_size--;
  83. TEST_EQ(bdb_check_key(&s, ssize), BDB_ERROR_STRUCT_SIZE);
  84. s = sgood;
  85. s.struct_magic++;
  86. TEST_EQ(bdb_check_key(&s, ssize), BDB_ERROR_STRUCT_MAGIC);
  87. s = sgood;
  88. s.struct_major_version++;
  89. TEST_EQ(bdb_check_key(&s, ssize), BDB_ERROR_STRUCT_VERSION);
  90. /* Description must contain a null */
  91. s = sgood;
  92. memset(s.description, 'x', sizeof(s.description));
  93. TEST_EQ(bdb_check_key(&s, ssize), BDB_ERROR_DESCRIPTION);
  94. /* Data AFTER the null is explicitly allowed, though */
  95. s = sgood;
  96. s.description[100] = 'x';
  97. TEST_EQ(bdb_check_key(&s, ssize), BDB_SUCCESS);
  98. /* Limited algorithm choices at present */
  99. s = sgood;
  100. s.hash_alg = BDB_HASH_ALG_INVALID;
  101. TEST_EQ(bdb_check_key(&s, ssize), BDB_ERROR_HASH_ALG);
  102. /* This works because ECDSA521 signatures are smaller than RSA4096 */
  103. s = sgood;
  104. s.sig_alg = BDB_SIG_ALG_ECSDSA521;
  105. TEST_EQ(bdb_check_key(&s, ssize), BDB_SUCCESS);
  106. s = sgood;
  107. s.sig_alg = BDB_SIG_ALG_INVALID;
  108. TEST_EQ(bdb_check_key(&s, ssize), BDB_ERROR_SIG_ALG);
  109. }
  110. void check_sig_tests(void)
  111. {
  112. struct bdb_sig sgood = {
  113. .struct_magic = BDB_SIG_MAGIC,
  114. .struct_major_version = BDB_SIG_VERSION_MAJOR,
  115. .struct_minor_version = BDB_SIG_VERSION_MINOR,
  116. .struct_size = sizeof(struct bdb_sig) + BDB_RSA4096_SIG_SIZE,
  117. .hash_alg = BDB_HASH_ALG_SHA256,
  118. .sig_alg = BDB_SIG_ALG_RSA4096,
  119. .signed_size = 123,
  120. .description = "Test sig",
  121. };
  122. const size_t ssize = sgood.struct_size;
  123. struct bdb_sig s;
  124. s = sgood;
  125. TEST_EQ(bdb_check_sig(&s, ssize), BDB_SUCCESS);
  126. TEST_EQ(bdb_check_sig(&s, ssize - 1), BDB_ERROR_BUF_SIZE);
  127. s = sgood;
  128. s.struct_size++;
  129. TEST_EQ(bdb_check_sig(&s, ssize), BDB_ERROR_BUF_SIZE);
  130. s = sgood;
  131. s.struct_size--;
  132. TEST_EQ(bdb_check_sig(&s, ssize), BDB_ERROR_STRUCT_SIZE);
  133. s = sgood;
  134. s.struct_magic++;
  135. TEST_EQ(bdb_check_sig(&s, ssize), BDB_ERROR_STRUCT_MAGIC);
  136. s = sgood;
  137. s.struct_major_version++;
  138. TEST_EQ(bdb_check_sig(&s, ssize), BDB_ERROR_STRUCT_VERSION);
  139. /* Description must contain a null */
  140. s = sgood;
  141. memset(s.description, 'x', sizeof(s.description));
  142. TEST_EQ(bdb_check_sig(&s, ssize), BDB_ERROR_DESCRIPTION);
  143. /* Data AFTER the null is explicitly allowed, though */
  144. s = sgood;
  145. s.description[100] = 'x';
  146. TEST_EQ(bdb_check_sig(&s, ssize), BDB_SUCCESS);
  147. /* Limited algorithm choices at present */
  148. s = sgood;
  149. s.hash_alg = BDB_HASH_ALG_INVALID;
  150. TEST_EQ(bdb_check_sig(&s, ssize), BDB_ERROR_HASH_ALG);
  151. /* This works because ECDSA521 signatures are smaller than RSA4096 */
  152. s = sgood;
  153. s.sig_alg = BDB_SIG_ALG_ECSDSA521;
  154. TEST_EQ(bdb_check_sig(&s, ssize), BDB_SUCCESS);
  155. s = sgood;
  156. s.sig_alg = BDB_SIG_ALG_INVALID;
  157. TEST_EQ(bdb_check_sig(&s, ssize), BDB_ERROR_SIG_ALG);
  158. }
  159. void check_data_tests(void)
  160. {
  161. struct bdb_data sgood = {
  162. .struct_magic = BDB_DATA_MAGIC,
  163. .struct_major_version = BDB_DATA_VERSION_MAJOR,
  164. .struct_minor_version = BDB_DATA_VERSION_MINOR,
  165. .struct_size = sizeof(struct bdb_data),
  166. .data_version = 1,
  167. .oem_area_1_size = 256,
  168. .num_hashes = 3,
  169. .hash_entry_size = sizeof(struct bdb_hash),
  170. .signed_size = 2048,
  171. .description = "Test data",
  172. };
  173. const size_t ssize = sgood.signed_size;
  174. struct bdb_data s;
  175. s = sgood;
  176. TEST_EQ(bdb_check_data(&s, ssize), BDB_SUCCESS);
  177. TEST_EQ(bdb_check_data(&s, ssize - 1), BDB_ERROR_BUF_SIZE);
  178. s = sgood;
  179. s.struct_size--;
  180. TEST_EQ(bdb_check_data(&s, ssize), BDB_ERROR_STRUCT_SIZE);
  181. s = sgood;
  182. s.struct_magic++;
  183. TEST_EQ(bdb_check_data(&s, ssize), BDB_ERROR_STRUCT_MAGIC);
  184. s = sgood;
  185. s.struct_major_version++;
  186. TEST_EQ(bdb_check_data(&s, ssize), BDB_ERROR_STRUCT_VERSION);
  187. /* Description must contain a null */
  188. s = sgood;
  189. memset(s.description, 'x', sizeof(s.description));
  190. TEST_EQ(bdb_check_data(&s, ssize), BDB_ERROR_DESCRIPTION);
  191. /* Data AFTER the null is explicitly allowed, though */
  192. s = sgood;
  193. s.description[100] = 'x';
  194. TEST_EQ(bdb_check_data(&s, ssize), BDB_SUCCESS);
  195. s = sgood;
  196. s.hash_entry_size--;
  197. TEST_EQ(bdb_check_data(&s, ssize), BDB_ERROR_HASH_ENTRY_SIZE);
  198. s = sgood;
  199. s.oem_area_1_size++;
  200. TEST_EQ(bdb_check_data(&s, ssize), BDB_ERROR_OEM_AREA_SIZE);
  201. /* Check exact size needed */
  202. s = sgood;
  203. s.signed_size = sizeof(s) + s.num_hashes * sizeof(struct bdb_hash) +
  204. s.oem_area_1_size;
  205. TEST_EQ(bdb_check_data(&s, ssize), BDB_SUCCESS);
  206. s.signed_size--;
  207. TEST_EQ(bdb_check_data(&s, ssize), BDB_ERROR_SIGNED_SIZE);
  208. /*
  209. * TODO: Verify wraparound check works. That can only be tested on a
  210. * platform where size_t is uint32_t, because otherwise a 32-bit
  211. * oem_area_1_size can't cause wraparound.
  212. */
  213. }
  214. /**
  215. * Test bdb_verify() and bdb_create()
  216. */
  217. void check_bdb_verify(void)
  218. {
  219. uint8_t oem_area_0[32] = "Some OEM area.";
  220. uint8_t oem_area_1[64] = "Some other OEM area.";
  221. struct bdb_hash hash[2] = {
  222. {
  223. .offset = 0x10000,
  224. .size = 0x18000,
  225. .partition = 1,
  226. .type = BDB_DATA_SP_RW,
  227. .load_address = 0x100000,
  228. .digest = {0x11, 0x11, 0x11, 0x10},
  229. },
  230. {
  231. .offset = 0x28000,
  232. .size = 0x20000,
  233. .partition = 1,
  234. .type = BDB_DATA_AP_RW,
  235. .load_address = 0x200000,
  236. .digest = {0x22, 0x22, 0x22, 0x20},
  237. },
  238. };
  239. struct bdb_create_params p = {
  240. .bdb_load_address = 0x11223344,
  241. .oem_area_0 = oem_area_0,
  242. .oem_area_0_size = sizeof(oem_area_0),
  243. .oem_area_1 = oem_area_1,
  244. .oem_area_1_size = sizeof(oem_area_1),
  245. .header_sig_description = "The header sig",
  246. .data_sig_description = "The data sig",
  247. .data_description = "Test BDB data",
  248. .data_version = 3,
  249. .hash = hash,
  250. .num_hashes = 2,
  251. };
  252. uint8_t bdbkey_digest[BDB_SHA256_DIGEST_SIZE];
  253. struct bdb_header *hgood, *h;
  254. size_t hsize;
  255. /* Load keys */
  256. p.bdbkey = bdb_create_key("testkeys/bdbkey.keyb", 100, "BDB key");
  257. p.subkey = bdb_create_key("testkeys/subkey.keyb", 200, "Subkey");
  258. p.private_bdbkey = read_pem("testkeys/bdbkey.pem");
  259. p.private_subkey = read_pem("testkeys/subkey.pem");
  260. if (!p.bdbkey || !p.subkey || !p.private_bdbkey || !p.private_subkey) {
  261. fprintf(stderr, "Unable to load test keys\n");
  262. exit(2);
  263. }
  264. bdb_sha256(bdbkey_digest, p.bdbkey, p.bdbkey->struct_size);
  265. /* Create the test BDB */
  266. hgood = bdb_create(&p);
  267. if (!hgood) {
  268. fprintf(stderr, "Unable to create test BDB\n");
  269. exit(2);
  270. }
  271. hsize = hgood->bdb_size;
  272. /* Allocate a copy we can mangle */
  273. h = calloc(hsize, 1);
  274. /* As created, it should pass */
  275. memcpy(h, hgood, hsize);
  276. TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_SUCCESS);
  277. /* Mangle each component in turn */
  278. memcpy(h, hgood, hsize);
  279. h->struct_magic++;
  280. TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_HEADER);
  281. memcpy(h, hgood, hsize);
  282. ((struct bdb_key *)bdb_get_bdbkey(h))->struct_magic++;
  283. TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_BDBKEY);
  284. memcpy(h, hgood, hsize);
  285. ((struct bdb_key *)bdb_get_bdbkey(h))->key_version++;
  286. TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_GOOD_OTHER_THAN_KEY);
  287. memcpy(h, hgood, hsize);
  288. h->oem_area_0_size += hsize;
  289. TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_OEM_AREA_0);
  290. memcpy(h, hgood, hsize);
  291. ((struct bdb_key *)bdb_get_subkey(h))->struct_magic++;
  292. TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_SUBKEY);
  293. memcpy(h, hgood, hsize);
  294. ((struct bdb_key *)bdb_get_subkey(h))->struct_size += 4;
  295. TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_BDB_SIGNED_SIZE);
  296. memcpy(h, hgood, hsize);
  297. ((struct bdb_sig *)bdb_get_header_sig(h))->struct_magic++;
  298. TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_HEADER_SIG);
  299. memcpy(h, hgood, hsize);
  300. ((struct bdb_sig *)bdb_get_header_sig(h))->signed_size--;
  301. TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_HEADER_SIG);
  302. memcpy(h, hgood, hsize);
  303. ((struct bdb_sig *)bdb_get_header_sig(h))->sig_data[0] ^= 0x42;
  304. TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_HEADER_SIG);
  305. /* Also make sure the header sig really covers all the fields */
  306. memcpy(h, hgood, hsize);
  307. ((struct bdb_key *)bdb_get_subkey(h))->key_version++;
  308. TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_HEADER_SIG);
  309. memcpy(h, hgood, hsize);
  310. ((uint8_t *)bdb_get_oem_area_0(h))[0] ^= 0x42;
  311. TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_HEADER_SIG);
  312. memcpy(h, hgood, hsize);
  313. ((uint8_t *)bdb_get_oem_area_0(h))[p.oem_area_0_size - 1] ^= 0x24;
  314. TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_HEADER_SIG);
  315. /* Check data header */
  316. memcpy(h, hgood, hsize);
  317. ((struct bdb_data *)bdb_get_data(h))->struct_magic++;
  318. TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_DATA);
  319. memcpy(h, hgood, hsize);
  320. ((struct bdb_sig *)bdb_get_data_sig(h))->struct_magic++;
  321. TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_DATA_SIG);
  322. memcpy(h, hgood, hsize);
  323. ((struct bdb_sig *)bdb_get_data_sig(h))->signed_size--;
  324. TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_DATA_SIG);
  325. memcpy(h, hgood, hsize);
  326. ((struct bdb_sig *)bdb_get_data_sig(h))->sig_data[0] ^= 0x42;
  327. TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_DATA_SIG);
  328. /* Also make sure the data sig really covers all the fields */
  329. memcpy(h, hgood, hsize);
  330. ((struct bdb_data *)bdb_get_data(h))->data_version--;
  331. TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_DATA_SIG);
  332. memcpy(h, hgood, hsize);
  333. ((uint8_t *)bdb_get_oem_area_1(h))[0] ^= 0x42;
  334. TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_DATA_SIG);
  335. memcpy(h, hgood, hsize);
  336. ((uint8_t *)bdb_get_oem_area_1(h))[p.oem_area_1_size - 1] ^= 0x24;
  337. TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_DATA_SIG);
  338. memcpy(h, hgood, hsize);
  339. ((struct bdb_hash *)bdb_get_hash(h, BDB_DATA_SP_RW))->offset++;
  340. TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_DATA_SIG);
  341. memcpy(h, hgood, hsize);
  342. ((struct bdb_hash *)bdb_get_hash(h, BDB_DATA_AP_RW))->digest[0] ^= 0x96;
  343. TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_DATA_SIG);
  344. /*
  345. * This is also a convenient place to test that all the parameters we
  346. * fed into bdb_create() also worked. That also tests all the
  347. * bdb_get_*() functions.
  348. */
  349. memcpy(h, hgood, hsize);
  350. TEST_EQ(h->bdb_load_address, p.bdb_load_address);
  351. TEST_EQ(strcmp(bdb_get_bdbkey(h)->description,
  352. p.bdbkey->description), 0);
  353. TEST_EQ(bdb_get_bdbkey(h)->key_version, p.bdbkey->key_version);
  354. TEST_EQ(h->oem_area_0_size, p.oem_area_0_size);
  355. TEST_EQ(memcmp(bdb_get_oem_area_0(h), oem_area_0, sizeof(oem_area_0)),
  356. 0);
  357. TEST_EQ(strcmp(bdb_get_subkey(h)->description, p.subkey->description),
  358. 0);
  359. TEST_EQ(bdb_get_subkey(h)->key_version, p.subkey->key_version);
  360. TEST_EQ(strcmp(bdb_get_header_sig(h)->description,
  361. p.header_sig_description), 0);
  362. TEST_EQ(strcmp(bdb_get_data(h)->description, p.data_description), 0);
  363. TEST_EQ(bdb_get_data(h)->data_version, p.data_version);
  364. TEST_EQ(bdb_get_data(h)->num_hashes, p.num_hashes);
  365. TEST_EQ(bdb_get_data(h)->oem_area_1_size, p.oem_area_1_size);
  366. TEST_EQ(memcmp(bdb_get_oem_area_1(h), oem_area_1, sizeof(oem_area_1)),
  367. 0);
  368. TEST_EQ(strcmp(bdb_get_data_sig(h)->description,
  369. p.data_sig_description), 0);
  370. /* Test getting hash entries */
  371. memcpy(h, hgood, hsize);
  372. TEST_EQ(bdb_get_hash(h, BDB_DATA_SP_RW)->offset, hash[0].offset);
  373. TEST_EQ(bdb_get_hash(h, BDB_DATA_AP_RW)->offset, hash[1].offset);
  374. /* And a non-existent one */
  375. TEST_EQ(bdb_get_hash(h, BDB_DATA_MCU)!=NULL, 0);
  376. /*
  377. * TODO: Verify wraparound checks works. That can only be tested on a
  378. * platform where size_t is uint32_t, because otherwise a 32-bit
  379. * oem_area_1_size can't cause wraparound.
  380. */
  381. /* Free keys and buffers */
  382. free(p.bdbkey);
  383. free(p.subkey);
  384. RSA_free(p.private_bdbkey);
  385. RSA_free(p.private_subkey);
  386. free(hgood);
  387. free(h);
  388. }
  389. /*****************************************************************************/
  390. int main(void)
  391. {
  392. printf("Running tests...\n");
  393. check_header_tests();
  394. check_key_tests();
  395. check_sig_tests();
  396. check_data_tests();
  397. check_bdb_verify();
  398. printf("All tests passed!\n");
  399. return 0;
  400. }