blob: 38d90003050283804972365dbce384c4a1d90beb [file] [log] [blame]
Randall Spangler7d6898d2010-06-11 09:22:13 -07001/* Copyright (c) 2010 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
Randall Spanglerd55c6452010-06-10 12:43:51 -07008#include <getopt.h>
9#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"
16#include "host_common.h"
17#include "vboot_common.h"
18
19
20/* Command line options */
21enum {
Bill Richardsonabf05502010-07-01 10:22:06 -070022 OPT_INKEY = 1000,
Randall Spanglerd55c6452010-06-10 12:43:51 -070023 OPT_KEY_VERSION,
24 OPT_ALGORITHM,
25 OPT_MODE_PACK,
26 OPT_MODE_UNPACK,
Bill Richardson8adcb432010-09-01 10:40:25 -070027 OPT_COPYTO,
Randall Spanglerd55c6452010-06-10 12:43:51 -070028};
29
30static struct option long_opts[] = {
Bill Richardsonabf05502010-07-01 10:22:06 -070031 {"key", 1, 0, OPT_INKEY },
Randall Spanglerd55c6452010-06-10 12:43:51 -070032 {"version", 1, 0, OPT_KEY_VERSION },
33 {"algorithm", 1, 0, OPT_ALGORITHM },
Bill Richardsonabf05502010-07-01 10:22:06 -070034 {"pack", 1, 0, OPT_MODE_PACK },
35 {"unpack", 1, 0, OPT_MODE_UNPACK },
Bill Richardson8adcb432010-09-01 10:40:25 -070036 {"copyto", 1, 0, OPT_COPYTO },
Randall Spanglerd55c6452010-06-10 12:43:51 -070037 {NULL, 0, 0, 0}
38};
39
40
41/* Print help and return error */
Bill Richardsonabf05502010-07-01 10:22:06 -070042static int PrintHelp(char *progname) {
Randall Spanglerd55c6452010-06-10 12:43:51 -070043 int i;
44
Bill Richardsonabf05502010-07-01 10:22:06 -070045 fprintf(stderr,
46 "This program wraps RSA keys with verified boot headers\n");
47 fprintf(stderr,
48 "\n"
49 "Usage: %s --pack <outfile> [PARAMETERS]\n"
50 "\n"
51 " Required parameters:\n"
52 " --key <infile> RSA key file (.keyb or .pem)\n"
53 " --version <number> Key version number "
54 "(required for .keyb, ignored for .pem)\n"
55 " --algorithm <number> Signing algorithm to use with key:\n",
56 progname);
Randall Spanglerd55c6452010-06-10 12:43:51 -070057
Bill Richardsonabf05502010-07-01 10:22:06 -070058 for (i = 0; i < kNumAlgorithms; i++) {
59 fprintf(stderr,
60 " %d = (%s)\n",
61 i, algo_strings[i]);
62 }
Randall Spanglerd55c6452010-06-10 12:43:51 -070063
Bill Richardsonabf05502010-07-01 10:22:06 -070064 fprintf(stderr,
65 "\nOR\n\n"
66 "Usage: %s --unpack <infile>\n"
Bill Richardson8adcb432010-09-01 10:40:25 -070067 "\n"
68 " Optional parameters:\n"
69 " --copyto <file> "
70 "Write a copy of the key to this file.\n"
Bill Richardsonabf05502010-07-01 10:22:06 -070071 "\n",
72 progname);
73
Randall Spanglerd55c6452010-06-10 12:43:51 -070074 return 1;
75}
76
Bill Richardsonabf05502010-07-01 10:22:06 -070077/* Pack a .keyb file into a .vbpubk, or a .pem into a .vbprivk */
Randall Spanglerd55c6452010-06-10 12:43:51 -070078static int Pack(const char *infile, const char *outfile, uint64_t algorithm,
79 uint64_t version) {
Bill Richardsonabf05502010-07-01 10:22:06 -070080 VbPublicKey* pubkey;
81 VbPrivateKey* privkey;
Randall Spanglerd55c6452010-06-10 12:43:51 -070082
83 if (!infile || !outfile) {
84 fprintf(stderr, "vbutil_key: Must specify --in and --out\n");
85 return 1;
86 }
87
Bill Richardsonabf05502010-07-01 10:22:06 -070088 if ((pubkey = PublicKeyReadKeyb(infile, algorithm, version))) {
89 if (0 != PublicKeyWrite(outfile, pubkey)) {
90 fprintf(stderr, "vbutil_key: Error writing key.\n");
91 return 1;
92 }
93 Free(pubkey);
94 return 0;
Randall Spanglerd55c6452010-06-10 12:43:51 -070095 }
96
Bill Richardsonabf05502010-07-01 10:22:06 -070097 if ((privkey = PrivateKeyReadPem(infile, algorithm))) {
98 if (0 != PrivateKeyWrite(outfile, privkey)) {
99 fprintf(stderr, "vbutil_key: Error writing key.\n");
100 return 1;
101 }
102 Free(privkey);
103 return 0;
Bill Richardson8adcb432010-09-01 10:40:25 -0700104 }
Randall Spanglerd55c6452010-06-10 12:43:51 -0700105
Bill Richardsonabf05502010-07-01 10:22:06 -0700106 error("Unable to parse either .keyb or .pem from %s\n", infile);
107 return 1;
Randall Spanglerd55c6452010-06-10 12:43:51 -0700108}
109
110
Bill Richardsonabf05502010-07-01 10:22:06 -0700111/* Unpack a .vbpubk or .vbprivk */
Randall Spanglerd55c6452010-06-10 12:43:51 -0700112static int Unpack(const char *infile, const char *outfile) {
Bill Richardsonabf05502010-07-01 10:22:06 -0700113 VbPublicKey* pubkey;
114 VbPrivateKey* privkey;
Randall Spanglerd55c6452010-06-10 12:43:51 -0700115
116 if (!infile) {
Bill Richardsonabf05502010-07-01 10:22:06 -0700117 fprintf(stderr, "Need file to unpack\n");
Randall Spanglerd55c6452010-06-10 12:43:51 -0700118 return 1;
119 }
120
Bill Richardsonabf05502010-07-01 10:22:06 -0700121 if ((pubkey = PublicKeyRead(infile))) {
122 printf("Public Key file: %s\n", infile);
123 printf("Algorithm: %" PRIu64 " %s\n", pubkey->algorithm,
124 (pubkey->algorithm < kNumAlgorithms ?
125 algo_strings[pubkey->algorithm] : "(invalid)"));
126 printf("Key Version: %" PRIu64 "\n", pubkey->key_version);
Bill Richardson8adcb432010-09-01 10:40:25 -0700127 printf("Key sha1sum: ");
Bill Richardson60bcbe32010-09-09 14:53:56 -0700128 PrintPubKeySha1Sum(pubkey);
129 printf("\n");
Bill Richardson8adcb432010-09-01 10:40:25 -0700130 if (outfile) {
131 if (0 != PublicKeyWrite(outfile, pubkey)) {
132 fprintf(stderr, "vbutil_key: Error writing key copy.\n");
133 Free(pubkey);
134 return 1;
135 }
136 }
Bill Richardsonabf05502010-07-01 10:22:06 -0700137 Free(pubkey);
138 return 0;
Randall Spanglerd55c6452010-06-10 12:43:51 -0700139 }
140
Bill Richardsonabf05502010-07-01 10:22:06 -0700141 if ((privkey = PrivateKeyRead(infile))) {
142 printf("Private Key file: %s\n", infile);
143 printf("Algorithm: %" PRIu64 " %s\n", privkey->algorithm,
144 (privkey->algorithm < kNumAlgorithms ?
145 algo_strings[privkey->algorithm] : "(invalid)"));
Bill Richardson8adcb432010-09-01 10:40:25 -0700146 if (outfile) {
147 if (0 != PrivateKeyWrite(outfile, privkey)) {
148 fprintf(stderr, "vbutil_key: Error writing key copy.\n");
149 Free(privkey);
150 return 1;
151 }
152 }
Bill Richardsonabf05502010-07-01 10:22:06 -0700153 Free(privkey);
154 return 0;
155 }
156
Bill Richardsonabf05502010-07-01 10:22:06 -0700157 error("Unable to parse either .vbpubk or vbprivk from %s\n", infile);
158 return 1;
Randall Spanglerd55c6452010-06-10 12:43:51 -0700159}
160
161
162int main(int argc, char* argv[]) {
163
164 char *infile = NULL;
165 char *outfile = NULL;
166 int mode = 0;
167 int parse_error = 0;
168 uint64_t version = 1;
169 uint64_t algorithm = kNumAlgorithms;
170 char* e;
171 int i;
172
Bill Richardsonabf05502010-07-01 10:22:06 -0700173 char *progname = strrchr(argv[0], '/');
174 if (progname)
175 progname++;
176 else
177 progname = argv[0];
178
Randall Spanglerd55c6452010-06-10 12:43:51 -0700179 while ((i = getopt_long(argc, argv, "", long_opts, NULL)) != -1) {
180 switch (i) {
181 case '?':
182 /* Unhandled option */
Bill Richardsonabf05502010-07-01 10:22:06 -0700183 error("Unknown option\n");
Randall Spanglerd55c6452010-06-10 12:43:51 -0700184 parse_error = 1;
185 break;
186
Bill Richardsonabf05502010-07-01 10:22:06 -0700187 case OPT_INKEY:
Randall Spanglerd55c6452010-06-10 12:43:51 -0700188 infile = optarg;
189 break;
190
Randall Spanglerd55c6452010-06-10 12:43:51 -0700191 case OPT_KEY_VERSION:
192 version = strtoul(optarg, &e, 0);
193 if (!*optarg || (e && *e)) {
Bill Richardsonabf05502010-07-01 10:22:06 -0700194 error("Invalid --version\n");
Randall Spanglerd55c6452010-06-10 12:43:51 -0700195 parse_error = 1;
196 }
197 break;
198
199 case OPT_ALGORITHM:
200 algorithm = strtoul(optarg, &e, 0);
201 if (!*optarg || (e && *e)) {
Bill Richardsonabf05502010-07-01 10:22:06 -0700202 error("Invalid --algorithm\n");
Randall Spanglerd55c6452010-06-10 12:43:51 -0700203 parse_error = 1;
204 }
205 break;
206
207 case OPT_MODE_PACK:
Bill Richardsonabf05502010-07-01 10:22:06 -0700208 mode = i;
209 outfile = optarg;
210 break;
211
Randall Spanglerd55c6452010-06-10 12:43:51 -0700212 case OPT_MODE_UNPACK:
213 mode = i;
Bill Richardsonabf05502010-07-01 10:22:06 -0700214 infile = optarg;
Randall Spanglerd55c6452010-06-10 12:43:51 -0700215 break;
Bill Richardson8adcb432010-09-01 10:40:25 -0700216
217 case OPT_COPYTO:
218 outfile = optarg;
219 break;
Randall Spanglerd55c6452010-06-10 12:43:51 -0700220 }
221 }
222
223 if (parse_error)
Bill Richardsonabf05502010-07-01 10:22:06 -0700224 return PrintHelp(progname);
Randall Spanglerd55c6452010-06-10 12:43:51 -0700225
226 switch(mode) {
227 case OPT_MODE_PACK:
228 return Pack(infile, outfile, algorithm, version);
229 case OPT_MODE_UNPACK:
230 return Unpack(infile, outfile);
231 default:
232 printf("Must specify a mode.\n");
Bill Richardsonabf05502010-07-01 10:22:06 -0700233 return PrintHelp(progname);
Randall Spanglerd55c6452010-06-10 12:43:51 -0700234 }
235}