cmd_vbutil_key.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. /* Copyright (c) 2011 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. * Verified boot key utility
  6. */
  7. #include <getopt.h>
  8. #include <inttypes.h> /* For PRIu64 */
  9. #include <stdarg.h>
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include "futility.h"
  14. #include "host_common.h"
  15. #include "host_key2.h"
  16. #include "util_misc.h"
  17. #include "vb1_helper.h"
  18. #include "vb2_common.h"
  19. #include "vboot_common.h"
  20. /* Command line options */
  21. enum {
  22. OPT_INKEY = 1000,
  23. OPT_KEY_VERSION,
  24. OPT_ALGORITHM,
  25. OPT_MODE_PACK,
  26. OPT_MODE_UNPACK,
  27. OPT_COPYTO,
  28. OPT_HELP,
  29. };
  30. static const struct option long_opts[] = {
  31. {"key", 1, 0, OPT_INKEY},
  32. {"version", 1, 0, OPT_KEY_VERSION},
  33. {"algorithm", 1, 0, OPT_ALGORITHM},
  34. {"pack", 1, 0, OPT_MODE_PACK},
  35. {"unpack", 1, 0, OPT_MODE_UNPACK},
  36. {"copyto", 1, 0, OPT_COPYTO},
  37. {"help", 0, 0, OPT_HELP},
  38. {NULL, 0, 0, 0}
  39. };
  40. static void print_help(int argc, char *argv[])
  41. {
  42. int i;
  43. printf("\n"
  44. "Usage: " MYNAME " %s --pack <outfile> [PARAMETERS]\n"
  45. "\n"
  46. " Required parameters:\n"
  47. " --key <infile> RSA key file (.keyb or .pem)\n"
  48. " --version <number> Key version number "
  49. "(required for .keyb,\n"
  50. " ignored for .pem)\n"
  51. " --algorithm <number> "
  52. "Signing algorithm to use with key:\n", argv[0]);
  53. for (i = 0; i < VB2_ALG_COUNT; i++) {
  54. printf(" %d = (%s)\n",
  55. i, vb2_get_crypto_algorithm_name(i));
  56. }
  57. printf("\nOR\n\n"
  58. "Usage: " MYNAME " %s --unpack <infile>\n"
  59. "\n"
  60. " Optional parameters:\n"
  61. " --copyto <file> "
  62. "Write a copy of the key to this file.\n\n", argv[0]);
  63. }
  64. /* Pack a .keyb file into a .vbpubk, or a .pem into a .vbprivk */
  65. static int do_pack(const char *infile, const char *outfile, uint32_t algorithm,
  66. uint32_t version)
  67. {
  68. if (!infile || !outfile) {
  69. fprintf(stderr, "vbutil_key: Must specify --in and --out\n");
  70. return 1;
  71. }
  72. struct vb2_packed_key *pubkey =
  73. vb2_read_packed_keyb(infile, algorithm, version);
  74. if (pubkey) {
  75. if (0 != vb2_write_packed_key(outfile, pubkey)) {
  76. fprintf(stderr, "vbutil_key: Error writing key.\n");
  77. free(pubkey);
  78. return 1;
  79. }
  80. free(pubkey);
  81. return 0;
  82. }
  83. struct vb2_private_key *privkey =
  84. vb2_read_private_key_pem(infile, algorithm);
  85. if (privkey) {
  86. if (VB2_SUCCESS != vb2_write_private_key(outfile, privkey)) {
  87. fprintf(stderr, "vbutil_key: Error writing key.\n");
  88. free(privkey);
  89. return 1;
  90. }
  91. free(privkey);
  92. return 0;
  93. }
  94. VbExError("Unable to parse either .keyb or .pem from %s\n", infile);
  95. return 1;
  96. }
  97. /* Unpack a .vbpubk or .vbprivk */
  98. static int do_unpack(const char *infile, const char *outfile)
  99. {
  100. struct vb2_packed_key *pubkey;
  101. if (!infile) {
  102. fprintf(stderr, "Need file to unpack\n");
  103. return 1;
  104. }
  105. pubkey = vb2_read_packed_key(infile);
  106. if (pubkey) {
  107. printf("Public Key file: %s\n", infile);
  108. printf("Algorithm: %u %s\n", pubkey->algorithm,
  109. vb2_get_crypto_algorithm_name(pubkey->algorithm));
  110. printf("Key Version: %u\n", pubkey->key_version);
  111. printf("Key sha1sum: %s\n",
  112. packed_key_sha1_string(pubkey));
  113. if (outfile &&
  114. VB2_SUCCESS != vb2_write_packed_key(outfile, pubkey)) {
  115. fprintf(stderr, "butil_key: Error writing key copy\n");
  116. free(pubkey);
  117. return 1;
  118. }
  119. free(pubkey);
  120. return 0;
  121. }
  122. struct vb2_private_key *privkey = vb2_read_private_key(infile);
  123. if (privkey) {
  124. printf("Private Key file: %s\n", infile);
  125. enum vb2_crypto_algorithm alg =
  126. vb2_get_crypto_algorithm(privkey->hash_alg,
  127. privkey->sig_alg);
  128. printf("Algorithm: %u %s\n", alg,
  129. vb2_get_crypto_algorithm_name(alg));
  130. if (outfile &&
  131. VB2_SUCCESS != vb2_write_private_key(outfile, privkey)) {
  132. fprintf(stderr,"vbutil_key: Error writing key copy\n");
  133. free(privkey);
  134. return 1;
  135. }
  136. free(privkey);
  137. return 0;
  138. }
  139. VbExError("Unable to parse either .vbpubk or vbprivk from %s\n",
  140. infile);
  141. return 1;
  142. }
  143. static int do_vbutil_key(int argc, char *argv[])
  144. {
  145. char *infile = NULL;
  146. char *outfile = NULL;
  147. int mode = 0;
  148. int parse_error = 0;
  149. uint32_t version = 1;
  150. uint32_t algorithm = VB2_ALG_COUNT;
  151. char *e;
  152. int i;
  153. while ((i = getopt_long(argc, argv, "", long_opts, NULL)) != -1) {
  154. switch (i) {
  155. case '?':
  156. /* Unhandled option */
  157. VbExError("Unknown option\n");
  158. parse_error = 1;
  159. break;
  160. case OPT_HELP:
  161. print_help(argc, argv);
  162. return !!parse_error;
  163. case OPT_INKEY:
  164. infile = optarg;
  165. break;
  166. case OPT_KEY_VERSION:
  167. version = strtoul(optarg, &e, 0);
  168. if (!*optarg || (e && *e)) {
  169. VbExError("Invalid --version\n");
  170. parse_error = 1;
  171. }
  172. break;
  173. case OPT_ALGORITHM:
  174. algorithm = strtoul(optarg, &e, 0);
  175. if (!*optarg || (e && *e)) {
  176. VbExError("Invalid --algorithm\n");
  177. parse_error = 1;
  178. }
  179. break;
  180. case OPT_MODE_PACK:
  181. mode = i;
  182. outfile = optarg;
  183. break;
  184. case OPT_MODE_UNPACK:
  185. mode = i;
  186. infile = optarg;
  187. break;
  188. case OPT_COPYTO:
  189. outfile = optarg;
  190. break;
  191. }
  192. }
  193. if (parse_error) {
  194. print_help(argc, argv);
  195. return 1;
  196. }
  197. switch (mode) {
  198. case OPT_MODE_PACK:
  199. return do_pack(infile, outfile, algorithm, version);
  200. case OPT_MODE_UNPACK:
  201. return do_unpack(infile, outfile);
  202. default:
  203. printf("Must specify a mode.\n");
  204. print_help(argc, argv);
  205. return 1;
  206. }
  207. }
  208. DECLARE_FUTIL_COMMAND(vbutil_key, do_vbutil_key, VBOOT_VERSION_1_0,
  209. "Wraps RSA keys with vboot headers");