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
8 #include <getopt.h>
9 #include <inttypes.h> /* For PRIu64 */
10 #include <stdarg.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14
15 #include "cryptolib.h"
16 #include "futility.h"
17 #include "host_common.h"
18 #include "util_misc.h"
19 #include "vboot_common.h"
20
21 /* Command line options */
22 enum {
23 OPT_INKEY = 1000,
24 OPT_KEY_VERSION,
25 OPT_ALGORITHM,
26 OPT_MODE_PACK,
27 OPT_MODE_UNPACK,
28 OPT_COPYTO,
29 };
30
31 static const struct option long_opts[] = {
32 {"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}
39 };
40
print_help(const char * progname)41 static void print_help(const char *progname)
42 {
43 int i;
44
45 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);
55
56 for (i = 0; i < kNumAlgorithms; i++) {
57 printf(" %d = (%s)\n",
58 i, algo_strings[i]);
59 }
60
61 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);
67 }
68
69 /* Pack a .keyb file into a .vbpubk, or a .pem into a .vbprivk */
Pack(const char * infile,const char * outfile,uint64_t algorithm,uint64_t version)70 static int Pack(const char *infile, const char *outfile, uint64_t algorithm,
71 uint64_t version)
72 {
73 VbPublicKey *pubkey;
74 VbPrivateKey *privkey;
75
76 if (!infile || !outfile) {
77 fprintf(stderr, "vbutil_key: Must specify --in and --out\n");
78 return 1;
79 }
80
81 pubkey = PublicKeyReadKeyb(infile, algorithm, version);
82 if (pubkey) {
83 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 }
90
91 privkey = PrivateKeyReadPem(infile, algorithm);
92 if (privkey) {
93 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 }
100
101 VbExError("Unable to parse either .keyb or .pem from %s\n", infile);
102 return 1;
103 }
104
105 /* Unpack a .vbpubk or .vbprivk */
Unpack(const char * infile,const char * outfile)106 static int Unpack(const char *infile, const char *outfile)
107 {
108 VbPublicKey *pubkey;
109 VbPrivateKey *privkey;
110
111 if (!infile) {
112 fprintf(stderr, "Need file to unpack\n");
113 return 1;
114 }
115
116 pubkey = PublicKeyRead(infile);
117 if (pubkey) {
118 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 }
137
138 privkey = PrivateKeyRead(infile);
139 if (privkey) {
140 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 }
158
159 VbExError("Unable to parse either .vbpubk or vbprivk from %s\n",
160 infile);
161 return 1;
162 }
163
do_vbutil_key(int argc,char * argv[])164 static int do_vbutil_key(int argc, char *argv[])
165 {
166
167 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;
175
176 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;
183
184 case OPT_INKEY:
185 infile = optarg;
186 break;
187
188 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;
195
196 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;
203
204 case OPT_MODE_PACK:
205 mode = i;
206 outfile = optarg;
207 break;
208
209 case OPT_MODE_UNPACK:
210 mode = i;
211 infile = optarg;
212 break;
213
214 case OPT_COPYTO:
215 outfile = optarg;
216 break;
217 }
218 }
219
220 if (parse_error) {
221 print_help(argv[0]);
222 return 1;
223 }
224
225 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");
232 print_help(argv[0]);
233 return 1;
234 }
235 }
236
237 DECLARE_FUTIL_COMMAND(vbutil_key, do_vbutil_key,
238 VBOOT_VERSION_1_0,
239 "Wraps RSA keys with vboot headers",
240 print_help);
241