blob: de9f97ff511174ca2f8dfd25432d07cef99c693d [file] [log] [blame]
Randall Spangler32a65262011-06-27 10:49:11 -07001/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
Randall Spangler7d6898d2010-06-11 09:22:13 -07002 * 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
Randall Spanglerd55c6452010-06-10 12:43:51 -07008#include <getopt.h>
Bill Richardson31d95c22014-08-24 22:07:17 -07009#include <inttypes.h> /* For PRIu64 */
Bill Richardsonabf05502010-07-01 10:22:06 -070010#include <stdarg.h>
Randall Spanglerd55c6452010-06-10 12:43:51 -070011#include <stdio.h>
12#include <stdlib.h>
Bill Richardsonabf05502010-07-01 10:22:06 -070013#include <string.h>
Randall Spanglerd55c6452010-06-10 12:43:51 -070014
15#include "cryptolib.h"
Bill Richardsonb84b81d2014-07-14 14:48:31 -070016#include "futility.h"
Randall Spanglerd55c6452010-06-10 12:43:51 -070017#include "host_common.h"
Bill Richardson78299022014-06-20 14:33:00 -070018#include "util_misc.h"
Randall Spanglerd55c6452010-06-10 12:43:51 -070019#include "vboot_common.h"
20
Randall Spanglerd55c6452010-06-10 12:43:51 -070021/* Command line options */
22enum {
Bill Richardson31d95c22014-08-24 22:07:17 -070023 OPT_INKEY = 1000,
24 OPT_KEY_VERSION,
25 OPT_ALGORITHM,
26 OPT_MODE_PACK,
27 OPT_MODE_UNPACK,
28 OPT_COPYTO,
Randall Spanglerd55c6452010-06-10 12:43:51 -070029};
30
Mike Frysinger7351ed72014-08-18 10:47:42 -040031static const struct option long_opts[] = {
Bill Richardson31d95c22014-08-24 22:07:17 -070032 {"key", 1, 0, OPT_INKEY},
33 {"version", 1, 0, OPT_KEY_VERSION},
34 {"algorithm", 1, 0, OPT_ALGORITHM},
35 {"pack", 1, 0, OPT_MODE_PACK},
36 {"unpack", 1, 0, OPT_MODE_UNPACK},
37 {"copyto", 1, 0, OPT_COPYTO},
38 {NULL, 0, 0, 0}
Randall Spanglerd55c6452010-06-10 12:43:51 -070039};
40
Bill Richardson779796f2014-09-23 11:47:40 -070041static void print_help(const char *progname)
Bill Richardson31d95c22014-08-24 22:07:17 -070042{
43 int i;
Randall Spanglerd55c6452010-06-10 12:43:51 -070044
Bill Richardson779796f2014-09-23 11:47:40 -070045 printf("\n"
46 "Usage: " MYNAME " %s --pack <outfile> [PARAMETERS]\n"
47 "\n"
48 " Required parameters:\n"
49 " --key <infile> RSA key file (.keyb or .pem)\n"
50 " --version <number> Key version number "
51 "(required for .keyb,\n"
52 " ignored for .pem)\n"
53 " --algorithm <number> "
54 "Signing algorithm to use with key:\n", progname);
Randall Spanglerd55c6452010-06-10 12:43:51 -070055
Bill Richardson31d95c22014-08-24 22:07:17 -070056 for (i = 0; i < kNumAlgorithms; i++) {
Bill Richardson779796f2014-09-23 11:47:40 -070057 printf(" %d = (%s)\n",
58 i, algo_strings[i]);
Bill Richardson31d95c22014-08-24 22:07:17 -070059 }
Randall Spanglerd55c6452010-06-10 12:43:51 -070060
Bill Richardson779796f2014-09-23 11:47:40 -070061 printf("\nOR\n\n"
62 "Usage: " MYNAME " %s --unpack <infile>\n"
63 "\n"
64 " Optional parameters:\n"
65 " --copyto <file> "
66 "Write a copy of the key to this file.\n\n", progname);
Randall Spanglerd55c6452010-06-10 12:43:51 -070067}
68
Bill Richardsonabf05502010-07-01 10:22:06 -070069/* Pack a .keyb file into a .vbpubk, or a .pem into a .vbprivk */
Randall Spanglerd55c6452010-06-10 12:43:51 -070070static int Pack(const char *infile, const char *outfile, uint64_t algorithm,
Bill Richardson31d95c22014-08-24 22:07:17 -070071 uint64_t version)
72{
73 VbPublicKey *pubkey;
74 VbPrivateKey *privkey;
Randall Spanglerd55c6452010-06-10 12:43:51 -070075
Bill Richardson31d95c22014-08-24 22:07:17 -070076 if (!infile || !outfile) {
77 fprintf(stderr, "vbutil_key: Must specify --in and --out\n");
78 return 1;
79 }
Randall Spanglerd55c6452010-06-10 12:43:51 -070080
Bill Richardson779796f2014-09-23 11:47:40 -070081 pubkey = PublicKeyReadKeyb(infile, algorithm, version);
82 if (pubkey) {
Bill Richardson31d95c22014-08-24 22:07:17 -070083 if (0 != PublicKeyWrite(outfile, pubkey)) {
84 fprintf(stderr, "vbutil_key: Error writing key.\n");
85 return 1;
86 }
87 free(pubkey);
88 return 0;
89 }
Randall Spanglerd55c6452010-06-10 12:43:51 -070090
Bill Richardson779796f2014-09-23 11:47:40 -070091 privkey = PrivateKeyReadPem(infile, algorithm);
92 if (privkey) {
Bill Richardson31d95c22014-08-24 22:07:17 -070093 if (0 != PrivateKeyWrite(outfile, privkey)) {
94 fprintf(stderr, "vbutil_key: Error writing key.\n");
95 return 1;
96 }
97 free(privkey);
98 return 0;
99 }
Randall Spanglerd55c6452010-06-10 12:43:51 -0700100
Bill Richardson31d95c22014-08-24 22:07:17 -0700101 VbExError("Unable to parse either .keyb or .pem from %s\n", infile);
102 return 1;
Randall Spanglerd55c6452010-06-10 12:43:51 -0700103}
104
Bill Richardsonabf05502010-07-01 10:22:06 -0700105/* Unpack a .vbpubk or .vbprivk */
Bill Richardson31d95c22014-08-24 22:07:17 -0700106static int Unpack(const char *infile, const char *outfile)
107{
108 VbPublicKey *pubkey;
109 VbPrivateKey *privkey;
Randall Spanglerd55c6452010-06-10 12:43:51 -0700110
Bill Richardson31d95c22014-08-24 22:07:17 -0700111 if (!infile) {
112 fprintf(stderr, "Need file to unpack\n");
113 return 1;
114 }
Randall Spanglerd55c6452010-06-10 12:43:51 -0700115
Bill Richardson779796f2014-09-23 11:47:40 -0700116 pubkey = PublicKeyRead(infile);
117 if (pubkey) {
Bill Richardson31d95c22014-08-24 22:07:17 -0700118 printf("Public Key file: %s\n", infile);
119 printf("Algorithm: %" PRIu64 " %s\n", pubkey->algorithm,
120 (pubkey->algorithm < kNumAlgorithms ?
121 algo_strings[pubkey->algorithm] : "(invalid)"));
122 printf("Key Version: %" PRIu64 "\n", pubkey->key_version);
123 printf("Key sha1sum: ");
124 PrintPubKeySha1Sum(pubkey);
125 printf("\n");
126 if (outfile) {
127 if (0 != PublicKeyWrite(outfile, pubkey)) {
128 fprintf(stderr,
129 "vbutil_key: Error writing key copy\n");
130 free(pubkey);
131 return 1;
132 }
133 }
134 free(pubkey);
135 return 0;
136 }
Randall Spanglerd55c6452010-06-10 12:43:51 -0700137
Bill Richardson779796f2014-09-23 11:47:40 -0700138 privkey = PrivateKeyRead(infile);
139 if (privkey) {
Bill Richardson31d95c22014-08-24 22:07:17 -0700140 printf("Private Key file: %s\n", infile);
141 printf("Algorithm: %" PRIu64 " %s\n",
142 privkey->algorithm,
143 (privkey->algorithm <
144 kNumAlgorithms ? algo_strings[privkey->
145 algorithm] :
146 "(invalid)"));
147 if (outfile) {
148 if (0 != PrivateKeyWrite(outfile, privkey)) {
149 fprintf(stderr,
150 "vbutil_key: Error writing key copy\n");
151 free(privkey);
152 return 1;
153 }
154 }
155 free(privkey);
156 return 0;
157 }
Bill Richardsonabf05502010-07-01 10:22:06 -0700158
Bill Richardson31d95c22014-08-24 22:07:17 -0700159 VbExError("Unable to parse either .vbpubk or vbprivk from %s\n",
160 infile);
161 return 1;
Randall Spanglerd55c6452010-06-10 12:43:51 -0700162}
163
Bill Richardson31d95c22014-08-24 22:07:17 -0700164static int do_vbutil_key(int argc, char *argv[])
165{
Randall Spanglerd55c6452010-06-10 12:43:51 -0700166
Bill Richardson31d95c22014-08-24 22:07:17 -0700167 char *infile = NULL;
168 char *outfile = NULL;
169 int mode = 0;
170 int parse_error = 0;
171 uint64_t version = 1;
172 uint64_t algorithm = kNumAlgorithms;
173 char *e;
174 int i;
Randall Spanglerd55c6452010-06-10 12:43:51 -0700175
Bill Richardson31d95c22014-08-24 22:07:17 -0700176 while ((i = getopt_long(argc, argv, "", long_opts, NULL)) != -1) {
177 switch (i) {
178 case '?':
179 /* Unhandled option */
180 VbExError("Unknown option\n");
181 parse_error = 1;
182 break;
Bill Richardsonabf05502010-07-01 10:22:06 -0700183
Bill Richardson31d95c22014-08-24 22:07:17 -0700184 case OPT_INKEY:
185 infile = optarg;
186 break;
Randall Spanglerd55c6452010-06-10 12:43:51 -0700187
Bill Richardson31d95c22014-08-24 22:07:17 -0700188 case OPT_KEY_VERSION:
189 version = strtoul(optarg, &e, 0);
190 if (!*optarg || (e && *e)) {
191 VbExError("Invalid --version\n");
192 parse_error = 1;
193 }
194 break;
Randall Spanglerd55c6452010-06-10 12:43:51 -0700195
Bill Richardson31d95c22014-08-24 22:07:17 -0700196 case OPT_ALGORITHM:
197 algorithm = strtoul(optarg, &e, 0);
198 if (!*optarg || (e && *e)) {
199 VbExError("Invalid --algorithm\n");
200 parse_error = 1;
201 }
202 break;
Randall Spanglerd55c6452010-06-10 12:43:51 -0700203
Bill Richardson31d95c22014-08-24 22:07:17 -0700204 case OPT_MODE_PACK:
205 mode = i;
206 outfile = optarg;
207 break;
Randall Spanglerd55c6452010-06-10 12:43:51 -0700208
Bill Richardson31d95c22014-08-24 22:07:17 -0700209 case OPT_MODE_UNPACK:
210 mode = i;
211 infile = optarg;
212 break;
Bill Richardsonabf05502010-07-01 10:22:06 -0700213
Bill Richardson31d95c22014-08-24 22:07:17 -0700214 case OPT_COPYTO:
215 outfile = optarg;
216 break;
217 }
218 }
Bill Richardson8adcb432010-09-01 10:40:25 -0700219
Bill Richardson779796f2014-09-23 11:47:40 -0700220 if (parse_error) {
221 print_help(argv[0]);
222 return 1;
223 }
Randall Spanglerd55c6452010-06-10 12:43:51 -0700224
Bill Richardson31d95c22014-08-24 22:07:17 -0700225 switch (mode) {
226 case OPT_MODE_PACK:
227 return Pack(infile, outfile, algorithm, version);
228 case OPT_MODE_UNPACK:
229 return Unpack(infile, outfile);
230 default:
231 printf("Must specify a mode.\n");
Bill Richardson779796f2014-09-23 11:47:40 -0700232 print_help(argv[0]);
233 return 1;
Bill Richardson31d95c22014-08-24 22:07:17 -0700234 }
Randall Spanglerd55c6452010-06-10 12:43:51 -0700235}
Bill Richardsonb84b81d2014-07-14 14:48:31 -0700236
237DECLARE_FUTIL_COMMAND(vbutil_key, do_vbutil_key,
Bill Richardson1eae8732015-02-05 12:36:15 -0800238 VBOOT_VERSION_1_0,
Bill Richardson779796f2014-09-23 11:47:40 -0700239 "Wraps RSA keys with vboot headers",
240 print_help);