cmd_bdb.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712
  1. /* Copyright 2016 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 boot flow utility
  6. */
  7. #include <getopt.h>
  8. #include <stdio.h>
  9. #include <unistd.h>
  10. #include "2sysincludes.h"
  11. #include "2common.h"
  12. #include "bdb.h"
  13. #include "bdb_struct.h"
  14. #include "futility.h"
  15. #include "host.h"
  16. static long int version;
  17. /* Command line options */
  18. enum {
  19. /* mode options */
  20. OPT_MODE_NONE,
  21. OPT_MODE_ADD,
  22. OPT_MODE_CREATE,
  23. OPT_MODE_RESIGN,
  24. OPT_MODE_VERIFY,
  25. /* file options */
  26. OPT_BDBKEY_PRI,
  27. OPT_BDBKEY_PUB,
  28. OPT_DATAKEY_PRI,
  29. OPT_DATAKEY_PUB,
  30. OPT_DATA,
  31. OPT_KEY_DIGEST,
  32. /* versions */
  33. OPT_BDBKEY_VERSION,
  34. OPT_DATAKEY_VERSION,
  35. OPT_DATA_VERSION,
  36. /* integer options */
  37. OPT_OFFSET,
  38. OPT_PARTITION,
  39. OPT_TYPE,
  40. OPT_LOAD_ADDRESS,
  41. /* Misc. options */
  42. OPT_IGNORE_KEY_DIGEST,
  43. OPT_VERSION,
  44. OPT_HELP,
  45. };
  46. static const struct option long_opts[] = {
  47. {"add", 1, 0, OPT_MODE_ADD},
  48. {"create", 1, 0, OPT_MODE_CREATE},
  49. {"resign", 1, 0, OPT_MODE_RESIGN},
  50. {"verify", 1, 0, OPT_MODE_VERIFY},
  51. {"bdbkey_pri", 1, 0, OPT_BDBKEY_PRI},
  52. {"bdbkey_pub", 1, 0, OPT_BDBKEY_PUB},
  53. {"datakey_pri", 1, 0, OPT_DATAKEY_PRI},
  54. {"datakey_pub", 1, 0, OPT_DATAKEY_PUB},
  55. {"bdbkey_version", 1, 0, OPT_BDBKEY_VERSION},
  56. {"datakey_version", 1, 0, OPT_DATAKEY_VERSION},
  57. {"data_version", 1, 0, OPT_DATA_VERSION},
  58. {"data", 1, 0, OPT_DATA},
  59. {"key_digest", 1, 0, OPT_KEY_DIGEST},
  60. {"offset", 1, 0, OPT_OFFSET},
  61. {"partition", 1, 0, OPT_PARTITION},
  62. {"type", 1, 0, OPT_TYPE},
  63. {"load_address", 1, 0, OPT_LOAD_ADDRESS},
  64. {"ignore_key_digest", 0, 0, OPT_IGNORE_KEY_DIGEST},
  65. {"version", 1, 0, OPT_VERSION},
  66. {"help", 0, 0, OPT_HELP},
  67. {NULL, 0, 0, 0}
  68. };
  69. /**
  70. * Add hash entry to BDB
  71. *
  72. * This adds a hash entry to a BDB. It does not change the signature. Hence,
  73. * the produced BDB needs to be resigned using the resign sub-command.
  74. */
  75. static int do_add(const char *bdb_filename, const char *data_filename,
  76. uint64_t offset, uint8_t partition,
  77. uint8_t type, uint64_t load_address)
  78. {
  79. uint8_t *bdb, *data, *new_bdb = NULL;
  80. uint32_t bdb_size, data_size;
  81. struct bdb_header *bdb_header;
  82. struct bdb_data *data_header;
  83. struct bdb_hash *new_hash;
  84. int rv = -1;
  85. bdb = read_file(bdb_filename, &bdb_size);
  86. data = read_file(data_filename, &data_size);
  87. if (!bdb || !data) {
  88. fprintf(stderr, "Unable to load BDB or data\n");
  89. goto exit;
  90. }
  91. /* Create a copy of BDB */
  92. new_bdb = calloc(1, bdb_size + sizeof(*new_hash));
  93. if (!new_bdb) {
  94. fprintf(stderr, "Unable to allocate memory\n");
  95. goto exit;
  96. }
  97. /* Copy up to the end of hashes. This implicitly clears the data
  98. * sig because it's not copied. */
  99. memcpy(new_bdb, bdb, vb2_offset_of(bdb, bdb_get_data_sig(bdb)));
  100. /* Update new BDB header */
  101. bdb_header = (struct bdb_header *)bdb_get_header(new_bdb);
  102. bdb_header->bdb_size += sizeof(*new_hash);
  103. data_header = (struct bdb_data *)bdb_get_data(new_bdb);
  104. /* Update new hash. We're overwriting the data signature, which
  105. * is already invalid anyway. */
  106. new_hash = (struct bdb_hash *)((uint8_t *)data_header
  107. + data_header->signed_size);
  108. new_hash->size = data_size;
  109. new_hash->type = type;
  110. new_hash->load_address = load_address;
  111. new_hash->partition = partition;
  112. new_hash->offset = offset;
  113. if (bdb_sha256(new_hash->digest, data, data_size)) {
  114. fprintf(stderr, "Unable to calculate hash\n");
  115. goto exit;
  116. }
  117. /* Update data header */
  118. data_header->num_hashes++;
  119. data_header->signed_size += sizeof(*new_hash);
  120. rv = write_file(bdb_filename, bdb_header, bdb_header->bdb_size);
  121. if (rv) {
  122. fprintf(stderr, "Unable to write BDB\n");
  123. goto exit;
  124. }
  125. fprintf(stderr, "Hash is added to BDB successfully. Resign required\n");
  126. exit:
  127. free(bdb);
  128. free(data);
  129. free(new_bdb);
  130. return rv;
  131. }
  132. /**
  133. * Create a new BDB
  134. *
  135. * This creates a new BDB using a pair of BDB keys and a pair of data keys.
  136. * A private data key is needed even with no hash entries.
  137. */
  138. static int do_create(const char *bdb_filename,
  139. const char *bdbkey_pri_filename,
  140. const char *bdbkey_pub_filename,
  141. uint32_t bdbkey_version,
  142. const char *datakey_pri_filename,
  143. const char *datakey_pub_filename,
  144. uint32_t datakey_version,
  145. uint64_t load_address)
  146. {
  147. struct bdb_key *bdbkey;
  148. struct bdb_key *datakey;
  149. struct rsa_st *bdbkey_pri;
  150. struct rsa_st *datakey_pri;
  151. struct bdb_create_params params;
  152. struct bdb_header *header;
  153. int rv = -1;
  154. /* Check arguments */
  155. if (!bdb_filename || !bdbkey_pri_filename || !bdbkey_pub_filename
  156. || !datakey_pri_filename || !datakey_pub_filename) {
  157. fprintf(stderr, "Missing filenames\n");
  158. return rv;
  159. }
  160. /* Load keys */
  161. bdbkey = bdb_create_key(bdbkey_pub_filename, bdbkey_version, NULL);
  162. bdbkey_pri = read_pem(bdbkey_pri_filename);
  163. datakey = bdb_create_key(datakey_pub_filename, datakey_version, NULL);
  164. datakey_pri = read_pem(datakey_pri_filename);
  165. if (!bdbkey || !bdbkey_pri || !datakey || !datakey_pri) {
  166. fprintf(stderr, "Unable to load keys\n");
  167. goto exit;
  168. }
  169. memset(&params, 0, sizeof(params));
  170. params.bdb_load_address = load_address;
  171. params.bdbkey = bdbkey;
  172. params.datakey = datakey;
  173. params.private_bdbkey = bdbkey_pri;
  174. params.private_datakey = datakey_pri;
  175. params.num_hashes = 0;
  176. header = bdb_create(&params);
  177. if (!header) {
  178. fprintf(stderr, "Unable to create BDB\n");
  179. goto exit;
  180. }
  181. rv = write_file(bdb_filename, header, header->bdb_size);
  182. if (rv) {
  183. fprintf(stderr, "Unable to write BDB\n");
  184. goto exit;
  185. }
  186. fprintf(stderr, "BDB is created successfully\n");
  187. exit:
  188. /* Free keys and buffers */
  189. free(bdbkey);
  190. free(datakey);
  191. RSA_free(bdbkey_pri);
  192. RSA_free(datakey_pri);
  193. return rv;
  194. }
  195. static int install_bdbkey(uint8_t **bdb, const struct bdb_key *new_key)
  196. {
  197. struct bdb_header *header;
  198. const struct bdb_key *key;
  199. uint8_t *p, *q;
  200. uint8_t *new_bdb;
  201. size_t new_size;
  202. size_t l;
  203. header = (struct bdb_header *)bdb_get_header(*bdb);
  204. key = bdb_get_bdbkey(*bdb);
  205. new_size = bdb_size_of(*bdb) + new_key->struct_size - key->struct_size;
  206. new_bdb = calloc(1, new_size);
  207. if (!new_bdb) {
  208. fprintf(stderr, "Unable to allocate memory\n");
  209. return -1;
  210. }
  211. /* copy BDB header */
  212. p = *bdb;
  213. q = new_bdb;
  214. l = header->struct_size;
  215. memcpy(q, p, l);
  216. /* copy new BDB key */
  217. p += l;
  218. q += l;
  219. memcpy(q, new_key, new_key->struct_size);
  220. /* copy the rest */
  221. p += key->struct_size;
  222. q += new_key->struct_size;
  223. l = bdb_size_of(*bdb) - vb2_offset_of(*bdb, p);
  224. memcpy(q, p, l);
  225. /* update size */
  226. header = (struct bdb_header *)bdb_get_header(new_bdb);
  227. header->bdb_size = new_size;
  228. free(*bdb);
  229. *bdb = new_bdb;
  230. return 0;
  231. }
  232. static int install_datakey(uint8_t **bdb, const struct bdb_key *new_key)
  233. {
  234. struct bdb_header *header;
  235. struct bdb_key *key;
  236. uint8_t *p, *q;
  237. uint8_t *new_bdb;
  238. size_t new_size;
  239. uint32_t l;
  240. key = (struct bdb_key *)bdb_get_datakey(*bdb);
  241. new_size = bdb_size_of(*bdb) + new_key->struct_size - key->struct_size;
  242. new_bdb = calloc(1, new_size);
  243. if (!new_bdb) {
  244. fprintf(stderr, "Unable to allocate memory\n");
  245. return -1;
  246. }
  247. /* copy the stuff up to datakey */
  248. p = *bdb;
  249. q = new_bdb;
  250. l = bdb_offset_of_datakey(*bdb);
  251. memcpy(q, p, l);
  252. /* copy new data key */
  253. p += l;
  254. q += l;
  255. memcpy(q, new_key, new_key->struct_size);
  256. /* copy the rest */
  257. p += key->struct_size;
  258. q += new_key->struct_size;
  259. l = bdb_size_of(*bdb) - vb2_offset_of(*bdb, p);
  260. memcpy(q, p, l);
  261. /* update size */
  262. header = (struct bdb_header *)bdb_get_header(new_bdb);
  263. header->bdb_size = new_size;
  264. header->signed_size = header->oem_area_0_size + new_key->struct_size;
  265. free(*bdb);
  266. *bdb = new_bdb;
  267. return 0;
  268. }
  269. /**
  270. * Resign a BDB using new keys
  271. *
  272. * It first installs given public keys to the BDB, then, runs verification.
  273. * If verification fails due to an invalid signature, it tries to 'fix' it
  274. * by resigning it using a given private key, then runs verification again.
  275. * Whether a key is required or not depends on which signature is invalid.
  276. * If a private key is required but not provided, it returns an error.
  277. */
  278. static int do_resign(const char *bdb_filename,
  279. const char *bdbkey_pri_filename,
  280. const char *bdbkey_pub_filename,
  281. uint32_t bdbkey_version,
  282. const char *datakey_pri_filename,
  283. const char *datakey_pub_filename,
  284. uint32_t datakey_version,
  285. uint32_t data_version)
  286. {
  287. uint8_t *bdb = NULL;
  288. struct rsa_st *bdbkey_pri = NULL;
  289. struct rsa_st *datakey_pri = NULL;
  290. uint32_t bdb_size;
  291. int resigned = 0;
  292. int rv = -1;
  293. if (!bdb_filename) {
  294. fprintf(stderr, "BDB file must be specified\n");
  295. goto exit;
  296. }
  297. bdb = read_file(bdb_filename, &bdb_size);
  298. if (!bdb) {
  299. fprintf(stderr, "Unable to read %s\n", bdb_filename);
  300. goto exit;
  301. }
  302. if (data_version != -1) {
  303. struct bdb_data *data = (struct bdb_data *)bdb_get_data(bdb);
  304. data->data_version = data_version;
  305. }
  306. if (bdbkey_pub_filename) {
  307. struct bdb_key *key = bdb_create_key(bdbkey_pub_filename,
  308. bdbkey_version, NULL);
  309. if (!key) {
  310. fprintf(stderr, "Unable to read BDB key\n");
  311. goto exit;
  312. }
  313. if (install_bdbkey(&bdb, key)) {
  314. fprintf(stderr, "Unable to install new BDB key\n");
  315. goto exit;
  316. }
  317. }
  318. if (datakey_pub_filename) {
  319. struct bdb_key *key = bdb_create_key(datakey_pub_filename,
  320. datakey_version, NULL);
  321. if (!key) {
  322. fprintf(stderr, "Unable to read data key\n");
  323. goto exit;
  324. }
  325. if (install_datakey(&bdb, key)) {
  326. fprintf(stderr, "Unable to install new data key\n");
  327. goto exit;
  328. }
  329. }
  330. /* Check validity for the new bdb key */
  331. rv = bdb_verify(bdb, bdb_size_of(bdb), NULL);
  332. if (rv == BDB_ERROR_HEADER_SIG) {
  333. /* This is expected failure if we installed a new BDB key.
  334. * Let's resign to fix it. */
  335. resigned = 1;
  336. fprintf(stderr, "Data key signature is invalid. Need to resign "
  337. "the key.\n");
  338. if (!bdbkey_pri_filename) {
  339. fprintf(stderr, "Private BDB key is required but not "
  340. "provided.\n");
  341. goto exit;
  342. }
  343. bdbkey_pri = read_pem(bdbkey_pri_filename);
  344. rv = bdb_sign_datakey(&bdb, bdbkey_pri);
  345. if (rv) {
  346. fprintf(stderr, "Failed to resign data key: %d\n", rv);
  347. goto exit;
  348. }
  349. fprintf(stderr, "Data key is resigned.\n");
  350. } else {
  351. fprintf(stderr, "Resigning data key is not required.\n");
  352. }
  353. /* Check validity for the new data key */
  354. rv = bdb_verify(bdb, bdb_size_of(bdb), NULL);
  355. switch (rv) {
  356. case BDB_ERROR_DATA_SIG:
  357. case BDB_ERROR_DATA_CHECK_SIG:
  358. /* This is expected failure if we installed a new data key
  359. * or sig is corrupted, which happens when a new hash is added
  360. * by 'add' sub-command. Let's resign the data */
  361. resigned = 1;
  362. fprintf(stderr,
  363. "Data signature is invalid. Need to resign data.\n");
  364. if (!datakey_pri_filename) {
  365. fprintf(stderr, "Private data key is required but not "
  366. "provided.\n");
  367. goto exit;
  368. }
  369. datakey_pri = read_pem(datakey_pri_filename);
  370. rv = bdb_sign_data(&bdb, datakey_pri);
  371. if (rv) {
  372. fprintf(stderr, "Failed to resign hashes: %d\n", rv);
  373. goto exit;
  374. }
  375. fprintf(stderr, "Data is resigned.\n");
  376. break;
  377. case BDB_GOOD_OTHER_THAN_KEY:
  378. case BDB_SUCCESS:
  379. fprintf(stderr, "Resigning the data is not required.\n");
  380. break;
  381. default:
  382. fprintf(stderr, "Verifying BDB failed unexpectedly: %d\n", rv);
  383. goto exit;
  384. }
  385. if (!resigned)
  386. goto exit;
  387. /* Check validity one last time */
  388. rv = bdb_verify(bdb, bdb_size_of(bdb), NULL);
  389. if (rv && rv != BDB_GOOD_OTHER_THAN_KEY) {
  390. /* This is not expected. We installed new keys and resigned
  391. * BDB but it's still invalid. */
  392. fprintf(stderr, "BDB is resigned but it's invalid: %d\n", rv);
  393. goto exit;
  394. }
  395. rv = write_file(bdb_filename, bdb, bdb_size_of(bdb));
  396. if (rv) {
  397. fprintf(stderr, "Unable to write BDB.\n");
  398. goto exit;
  399. }
  400. fprintf(stderr, "Successfully resigned BDB.\n");
  401. exit:
  402. free(bdb);
  403. RSA_free(bdbkey_pri);
  404. RSA_free(datakey_pri);
  405. return rv;
  406. }
  407. static int do_verify(const char *bdb_filename, const char *key_digest_filename,
  408. int ignore_key_digest)
  409. {
  410. uint8_t *bdb = NULL;
  411. uint8_t *key_digest = NULL;
  412. uint32_t bdb_size, key_digest_size;
  413. int rv = -1;
  414. bdb = read_file(bdb_filename, &bdb_size);
  415. if (!bdb) {
  416. fprintf(stderr, "Unable to load BDB\n");
  417. goto exit;
  418. }
  419. if (key_digest_filename) {
  420. key_digest = read_file(key_digest_filename, &key_digest_size);
  421. if (!key_digest) {
  422. fprintf(stderr, "Unable to read key digest\n");
  423. goto exit;
  424. }
  425. if (key_digest_size != BDB_SHA256_DIGEST_SIZE) {
  426. fprintf(stderr,
  427. "Invalid digest size: %d\n", key_digest_size);
  428. goto exit;
  429. }
  430. }
  431. rv = bdb_verify(bdb, bdb_size, key_digest);
  432. switch (rv) {
  433. case BDB_SUCCESS:
  434. fprintf(stderr, "BDB is successfully verified.\n");
  435. break;
  436. case BDB_GOOD_OTHER_THAN_KEY:
  437. fprintf(stderr, "BDB is valid.");
  438. if (ignore_key_digest) {
  439. rv = BDB_SUCCESS;
  440. fprintf(stderr,
  441. " Key digest doesn't match but ignored.\n");
  442. } else {
  443. fprintf(stderr,
  444. " Key digest doesn't match.\n");
  445. }
  446. break;
  447. default:
  448. /* TODO: Probably nice to print translation of the error code */
  449. fprintf(stderr, "BDB is invalid: %d.\n", rv);
  450. }
  451. exit:
  452. free(bdb);
  453. free(key_digest);
  454. return rv;
  455. }
  456. /* Print help and return error */
  457. static void print_help(int argc, char *argv[])
  458. {
  459. printf("\nUsage: " MYNAME " %s <--create|--add|--resign|--verify>\n"
  460. "\n"
  461. "Utility for managing boot descriptor blocks (BDBs).\n"
  462. "\n"
  463. "For '--add <bdb_file> [OPTIONS]', required OPTIONS are:\n"
  464. " --data <file> Data to be added\n"
  465. " --offset <offset> Offset\n"
  466. " --partition <number> Partition number\n"
  467. " --type <number> Data type\n"
  468. " --load_address <number> Data load address\n"
  469. "\n"
  470. "For '--create <bdb_file> [OPTIONS]', required OPTIONS are:\n"
  471. " --bdbkey_pri <file> BDB key in .pem format\n"
  472. " --bdbkey_pub <file> BDB key in .keyb format\n"
  473. " --datakey_pri <file> Data key in .pem format\n"
  474. " --datakey_pub <file> Data key in .keyb format\n"
  475. " --load_address <number> BDB load address\n"
  476. "\n"
  477. "For '--resign <bdb_file> [OPTIONS]', optional OPTIONS are:\n"
  478. " --bdbkey_pri <file> New BDB key in .pem format\n"
  479. " --bdbkey_pub <file> New BDB key in .keyb format\n"
  480. " --datakey_pri <file> New data key in .pem format\n"
  481. " --datakey_pub <file> New data key in .keyb format\n"
  482. " --data_version <number> Data version\n"
  483. "\n"
  484. "For '--verify <bdb_file> [OPTIONS]', optional OPTIONS are:\n"
  485. " --key_digest <file> BDB key digest\n"
  486. " --ignore_key_digest Ignore key digest mismatch\n"
  487. "\n",
  488. argv[0]);
  489. }
  490. static int do_bdb(int argc, char *argv[])
  491. {
  492. int mode = 0;
  493. const char *bdb_filename = NULL;
  494. const char *bdbkey_pri_filename = NULL;
  495. const char *bdbkey_pub_filename = NULL;
  496. const char *datakey_pri_filename = NULL;
  497. const char *datakey_pub_filename = NULL;
  498. const char *data_filename = NULL;
  499. const char *key_digest_filename = NULL;
  500. uint32_t bdbkey_version = 0;
  501. uint32_t datakey_version = 0;
  502. uint32_t data_version = -1;
  503. uint64_t offset = 0;
  504. uint8_t partition = 0;
  505. uint8_t type = 0;
  506. uint64_t load_address = -1;
  507. int ignore_key_digest = 0;
  508. int parse_error = 0;
  509. char *e;
  510. int i;
  511. while ((i = getopt_long(argc, argv, "", long_opts, NULL)) != -1) {
  512. switch (i) {
  513. case '?':
  514. /* Unhandled option */
  515. fprintf(stderr, "Unknown option or missing value\n");
  516. parse_error = 1;
  517. break;
  518. case OPT_HELP:
  519. print_help(argc, argv);
  520. return !!parse_error;
  521. case OPT_MODE_CREATE:
  522. mode = i;
  523. bdb_filename = optarg;
  524. break;
  525. case OPT_MODE_ADD:
  526. mode = i;
  527. bdb_filename = optarg;
  528. break;
  529. case OPT_MODE_RESIGN:
  530. mode = i;
  531. bdb_filename = optarg;
  532. break;
  533. case OPT_MODE_VERIFY:
  534. mode = i;
  535. bdb_filename = optarg;
  536. break;
  537. case OPT_BDBKEY_PRI:
  538. bdbkey_pri_filename = optarg;
  539. break;
  540. case OPT_BDBKEY_PUB:
  541. bdbkey_pub_filename = optarg;
  542. break;
  543. case OPT_DATAKEY_PRI:
  544. datakey_pri_filename = optarg;
  545. break;
  546. case OPT_DATAKEY_PUB:
  547. datakey_pub_filename = optarg;
  548. break;
  549. case OPT_DATA:
  550. data_filename = optarg;
  551. break;
  552. case OPT_KEY_DIGEST:
  553. key_digest_filename = optarg;
  554. break;
  555. case OPT_BDBKEY_VERSION:
  556. bdbkey_version = strtoul(optarg, &e, 0);
  557. if (!*optarg || (e && *e)) {
  558. fprintf(stderr, "Invalid --bdbkey_version\n");
  559. parse_error = 1;
  560. }
  561. break;
  562. case OPT_DATAKEY_VERSION:
  563. datakey_version = strtoul(optarg, &e, 0);
  564. if (!*optarg || (e && *e)) {
  565. fprintf(stderr, "Invalid --datakey_version\n");
  566. parse_error = 1;
  567. }
  568. break;
  569. case OPT_DATA_VERSION:
  570. data_version = strtoul(optarg, &e, 0);
  571. if (!*optarg || (e && *e)) {
  572. fprintf(stderr, "Invalid --data_version\n");
  573. parse_error = 1;
  574. }
  575. break;
  576. case OPT_OFFSET:
  577. offset = strtoul(optarg, &e, 0);
  578. if (!*optarg || (e && *e)) {
  579. fprintf(stderr, "Invalid --offset\n");
  580. parse_error = 1;
  581. }
  582. break;
  583. case OPT_PARTITION:
  584. partition = strtoul(optarg, &e, 0);
  585. if (!*optarg || (e && *e)) {
  586. fprintf(stderr, "Invalid --partition\n");
  587. parse_error = 1;
  588. }
  589. break;
  590. case OPT_TYPE:
  591. type = strtoul(optarg, &e, 0);
  592. if (!*optarg || (e && *e)) {
  593. fprintf(stderr, "Invalid --type\n");
  594. parse_error = 1;
  595. }
  596. break;
  597. case OPT_LOAD_ADDRESS:
  598. load_address = strtoul(optarg, &e, 0);
  599. if (!*optarg || (e && *e)) {
  600. fprintf(stderr, "Invalid --load_address\n");
  601. parse_error = 1;
  602. }
  603. break;
  604. case OPT_IGNORE_KEY_DIGEST:
  605. ignore_key_digest = 1;
  606. break;
  607. case OPT_VERSION:
  608. version = strtoul(optarg, &e, 0);
  609. if (!*optarg || (e && *e)) {
  610. fprintf(stderr, "Invalid --version\n");
  611. parse_error = 1;
  612. }
  613. break;
  614. }
  615. }
  616. if (parse_error) {
  617. print_help(argc, argv);
  618. return 1;
  619. }
  620. switch (mode) {
  621. case OPT_MODE_ADD:
  622. return do_add(bdb_filename, data_filename,
  623. offset, partition, type, load_address);
  624. case OPT_MODE_CREATE:
  625. return do_create(bdb_filename, bdbkey_pri_filename,
  626. bdbkey_pub_filename, bdbkey_version,
  627. datakey_pri_filename, datakey_pub_filename,
  628. datakey_version, load_address);
  629. case OPT_MODE_RESIGN:
  630. return do_resign(bdb_filename, bdbkey_pri_filename,
  631. bdbkey_pub_filename, bdbkey_version,
  632. datakey_pri_filename, datakey_pub_filename,
  633. datakey_version, data_version);
  634. case OPT_MODE_VERIFY:
  635. return do_verify(bdb_filename,
  636. key_digest_filename, ignore_key_digest);
  637. case OPT_MODE_NONE:
  638. default:
  639. fprintf(stderr, "Must specify a mode.\n");
  640. print_help(argc, argv);
  641. return 1;
  642. }
  643. }
  644. DECLARE_FUTIL_COMMAND(bdb, do_bdb, VBOOT_VERSION_1_0,
  645. "Common boot flow utility");