blob: c076bfff0fa7a2afb47f490218f0bcc74cf3b360 [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 Richardson8adcb432010-09-01 10:40:25 -0700111static void PrintDigest(const uint8_t* buf, uint64_t buflen) {
112 uint8_t *digest = DigestBuf(buf, buflen, SHA1_DIGEST_ALGORITHM);
113 int i;
114 for (i=0; i<SHA1_DIGEST_SIZE; i++)
115 printf("%02x", digest[i]);
116 printf("\n");
117 Free(digest);
118}
119
Bill Richardsonabf05502010-07-01 10:22:06 -0700120/* Unpack a .vbpubk or .vbprivk */
Randall Spanglerd55c6452010-06-10 12:43:51 -0700121static int Unpack(const char *infile, const char *outfile) {
Bill Richardsonabf05502010-07-01 10:22:06 -0700122 VbPublicKey* pubkey;
123 VbPrivateKey* privkey;
Randall Spanglerd55c6452010-06-10 12:43:51 -0700124
125 if (!infile) {
Bill Richardsonabf05502010-07-01 10:22:06 -0700126 fprintf(stderr, "Need file to unpack\n");
Randall Spanglerd55c6452010-06-10 12:43:51 -0700127 return 1;
128 }
129
Bill Richardsonabf05502010-07-01 10:22:06 -0700130 if ((pubkey = PublicKeyRead(infile))) {
131 printf("Public Key file: %s\n", infile);
132 printf("Algorithm: %" PRIu64 " %s\n", pubkey->algorithm,
133 (pubkey->algorithm < kNumAlgorithms ?
134 algo_strings[pubkey->algorithm] : "(invalid)"));
135 printf("Key Version: %" PRIu64 "\n", pubkey->key_version);
Bill Richardson8adcb432010-09-01 10:40:25 -0700136 printf("Key sha1sum: ");
137 PrintDigest(((uint8_t *)pubkey) + pubkey->key_offset, pubkey->key_size);
138 if (outfile) {
139 if (0 != PublicKeyWrite(outfile, pubkey)) {
140 fprintf(stderr, "vbutil_key: Error writing key copy.\n");
141 Free(pubkey);
142 return 1;
143 }
144 }
Bill Richardsonabf05502010-07-01 10:22:06 -0700145 Free(pubkey);
146 return 0;
Randall Spanglerd55c6452010-06-10 12:43:51 -0700147 }
148
Bill Richardsonabf05502010-07-01 10:22:06 -0700149
150 if ((privkey = PrivateKeyRead(infile))) {
151 printf("Private Key file: %s\n", infile);
152 printf("Algorithm: %" PRIu64 " %s\n", privkey->algorithm,
153 (privkey->algorithm < kNumAlgorithms ?
154 algo_strings[privkey->algorithm] : "(invalid)"));
Bill Richardson8adcb432010-09-01 10:40:25 -0700155 if (outfile) {
156 if (0 != PrivateKeyWrite(outfile, privkey)) {
157 fprintf(stderr, "vbutil_key: Error writing key copy.\n");
158 Free(privkey);
159 return 1;
160 }
161 }
Bill Richardsonabf05502010-07-01 10:22:06 -0700162 Free(privkey);
163 return 0;
164 }
165
Bill Richardsonabf05502010-07-01 10:22:06 -0700166 error("Unable to parse either .vbpubk or vbprivk from %s\n", infile);
167 return 1;
Randall Spanglerd55c6452010-06-10 12:43:51 -0700168}
169
170
171int main(int argc, char* argv[]) {
172
173 char *infile = NULL;
174 char *outfile = NULL;
175 int mode = 0;
176 int parse_error = 0;
177 uint64_t version = 1;
178 uint64_t algorithm = kNumAlgorithms;
179 char* e;
180 int i;
181
Bill Richardsonabf05502010-07-01 10:22:06 -0700182 char *progname = strrchr(argv[0], '/');
183 if (progname)
184 progname++;
185 else
186 progname = argv[0];
187
Randall Spanglerd55c6452010-06-10 12:43:51 -0700188 while ((i = getopt_long(argc, argv, "", long_opts, NULL)) != -1) {
189 switch (i) {
190 case '?':
191 /* Unhandled option */
Bill Richardsonabf05502010-07-01 10:22:06 -0700192 error("Unknown option\n");
Randall Spanglerd55c6452010-06-10 12:43:51 -0700193 parse_error = 1;
194 break;
195
Bill Richardsonabf05502010-07-01 10:22:06 -0700196 case OPT_INKEY:
Randall Spanglerd55c6452010-06-10 12:43:51 -0700197 infile = optarg;
198 break;
199
Randall Spanglerd55c6452010-06-10 12:43:51 -0700200 case OPT_KEY_VERSION:
201 version = strtoul(optarg, &e, 0);
202 if (!*optarg || (e && *e)) {
Bill Richardsonabf05502010-07-01 10:22:06 -0700203 error("Invalid --version\n");
Randall Spanglerd55c6452010-06-10 12:43:51 -0700204 parse_error = 1;
205 }
206 break;
207
208 case OPT_ALGORITHM:
209 algorithm = strtoul(optarg, &e, 0);
210 if (!*optarg || (e && *e)) {
Bill Richardsonabf05502010-07-01 10:22:06 -0700211 error("Invalid --algorithm\n");
Randall Spanglerd55c6452010-06-10 12:43:51 -0700212 parse_error = 1;
213 }
214 break;
215
216 case OPT_MODE_PACK:
Bill Richardsonabf05502010-07-01 10:22:06 -0700217 mode = i;
218 outfile = optarg;
219 break;
220
Randall Spanglerd55c6452010-06-10 12:43:51 -0700221 case OPT_MODE_UNPACK:
222 mode = i;
Bill Richardsonabf05502010-07-01 10:22:06 -0700223 infile = optarg;
Randall Spanglerd55c6452010-06-10 12:43:51 -0700224 break;
Bill Richardson8adcb432010-09-01 10:40:25 -0700225
226 case OPT_COPYTO:
227 outfile = optarg;
228 break;
Randall Spanglerd55c6452010-06-10 12:43:51 -0700229 }
230 }
231
232 if (parse_error)
Bill Richardsonabf05502010-07-01 10:22:06 -0700233 return PrintHelp(progname);
Randall Spanglerd55c6452010-06-10 12:43:51 -0700234
235 switch(mode) {
236 case OPT_MODE_PACK:
237 return Pack(infile, outfile, algorithm, version);
238 case OPT_MODE_UNPACK:
239 return Unpack(infile, outfile);
240 default:
241 printf("Must specify a mode.\n");
Bill Richardsonabf05502010-07-01 10:22:06 -0700242 return PrintHelp(progname);
Randall Spanglerd55c6452010-06-10 12:43:51 -0700243 }
244}