blob: 88d8e83bb25241a2b5746bf1225ae0ec1d1fc8f1 [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>
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"
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
21
22/* Command line options */
23enum {
Bill Richardsonabf05502010-07-01 10:22:06 -070024 OPT_INKEY = 1000,
Randall Spanglerd55c6452010-06-10 12:43:51 -070025 OPT_KEY_VERSION,
26 OPT_ALGORITHM,
27 OPT_MODE_PACK,
28 OPT_MODE_UNPACK,
Bill Richardson8adcb432010-09-01 10:40:25 -070029 OPT_COPYTO,
Randall Spanglerd55c6452010-06-10 12:43:51 -070030};
31
Mike Frysinger7351ed72014-08-18 10:47:42 -040032static const struct option long_opts[] = {
Bill Richardsonabf05502010-07-01 10:22:06 -070033 {"key", 1, 0, OPT_INKEY },
Randall Spanglerd55c6452010-06-10 12:43:51 -070034 {"version", 1, 0, OPT_KEY_VERSION },
35 {"algorithm", 1, 0, OPT_ALGORITHM },
Bill Richardsonabf05502010-07-01 10:22:06 -070036 {"pack", 1, 0, OPT_MODE_PACK },
37 {"unpack", 1, 0, OPT_MODE_UNPACK },
Bill Richardson8adcb432010-09-01 10:40:25 -070038 {"copyto", 1, 0, OPT_COPYTO },
Randall Spanglerd55c6452010-06-10 12:43:51 -070039 {NULL, 0, 0, 0}
40};
41
42
43/* Print help and return error */
Bill Richardsonabf05502010-07-01 10:22:06 -070044static int PrintHelp(char *progname) {
Randall Spanglerd55c6452010-06-10 12:43:51 -070045 int i;
46
Bill Richardsonabf05502010-07-01 10:22:06 -070047 fprintf(stderr,
48 "This program wraps RSA keys with verified boot headers\n");
49 fprintf(stderr,
50 "\n"
51 "Usage: %s --pack <outfile> [PARAMETERS]\n"
52 "\n"
53 " Required parameters:\n"
54 " --key <infile> RSA key file (.keyb or .pem)\n"
55 " --version <number> Key version number "
Bill Richardsonb84b81d2014-07-14 14:48:31 -070056 "(required for .keyb,\n"
57 " ignored for .pem)\n"
58 " --algorithm <number> "
59 "Signing algorithm to use with key:\n",
Bill Richardsonabf05502010-07-01 10:22:06 -070060 progname);
Randall Spanglerd55c6452010-06-10 12:43:51 -070061
Bill Richardsonabf05502010-07-01 10:22:06 -070062 for (i = 0; i < kNumAlgorithms; i++) {
63 fprintf(stderr,
64 " %d = (%s)\n",
65 i, algo_strings[i]);
66 }
Randall Spanglerd55c6452010-06-10 12:43:51 -070067
Bill Richardsonabf05502010-07-01 10:22:06 -070068 fprintf(stderr,
69 "\nOR\n\n"
70 "Usage: %s --unpack <infile>\n"
Bill Richardson8adcb432010-09-01 10:40:25 -070071 "\n"
72 " Optional parameters:\n"
73 " --copyto <file> "
74 "Write a copy of the key to this file.\n"
Bill Richardsonabf05502010-07-01 10:22:06 -070075 "\n",
76 progname);
77
Randall Spanglerd55c6452010-06-10 12:43:51 -070078 return 1;
79}
80
Bill Richardsonabf05502010-07-01 10:22:06 -070081/* Pack a .keyb file into a .vbpubk, or a .pem into a .vbprivk */
Randall Spanglerd55c6452010-06-10 12:43:51 -070082static int Pack(const char *infile, const char *outfile, uint64_t algorithm,
83 uint64_t version) {
Bill Richardsonabf05502010-07-01 10:22:06 -070084 VbPublicKey* pubkey;
85 VbPrivateKey* privkey;
Randall Spanglerd55c6452010-06-10 12:43:51 -070086
87 if (!infile || !outfile) {
88 fprintf(stderr, "vbutil_key: Must specify --in and --out\n");
89 return 1;
90 }
91
Bill Richardsonabf05502010-07-01 10:22:06 -070092 if ((pubkey = PublicKeyReadKeyb(infile, algorithm, version))) {
93 if (0 != PublicKeyWrite(outfile, pubkey)) {
94 fprintf(stderr, "vbutil_key: Error writing key.\n");
95 return 1;
96 }
Randall Spangler32a65262011-06-27 10:49:11 -070097 free(pubkey);
Bill Richardsonabf05502010-07-01 10:22:06 -070098 return 0;
Randall Spanglerd55c6452010-06-10 12:43:51 -070099 }
100
Bill Richardsonabf05502010-07-01 10:22:06 -0700101 if ((privkey = PrivateKeyReadPem(infile, algorithm))) {
102 if (0 != PrivateKeyWrite(outfile, privkey)) {
103 fprintf(stderr, "vbutil_key: Error writing key.\n");
104 return 1;
105 }
Randall Spangler32a65262011-06-27 10:49:11 -0700106 free(privkey);
Bill Richardsonabf05502010-07-01 10:22:06 -0700107 return 0;
Bill Richardson8adcb432010-09-01 10:40:25 -0700108 }
Randall Spanglerd55c6452010-06-10 12:43:51 -0700109
Randall Spangler32a65262011-06-27 10:49:11 -0700110 VbExError("Unable to parse either .keyb or .pem from %s\n", infile);
Bill Richardsonabf05502010-07-01 10:22:06 -0700111 return 1;
Randall Spanglerd55c6452010-06-10 12:43:51 -0700112}
113
114
Bill Richardsonabf05502010-07-01 10:22:06 -0700115/* Unpack a .vbpubk or .vbprivk */
Randall Spanglerd55c6452010-06-10 12:43:51 -0700116static int Unpack(const char *infile, const char *outfile) {
Bill Richardsonabf05502010-07-01 10:22:06 -0700117 VbPublicKey* pubkey;
118 VbPrivateKey* privkey;
Randall Spanglerd55c6452010-06-10 12:43:51 -0700119
120 if (!infile) {
Bill Richardsonabf05502010-07-01 10:22:06 -0700121 fprintf(stderr, "Need file to unpack\n");
Randall Spanglerd55c6452010-06-10 12:43:51 -0700122 return 1;
123 }
124
Bill Richardsonabf05502010-07-01 10:22:06 -0700125 if ((pubkey = PublicKeyRead(infile))) {
126 printf("Public Key file: %s\n", infile);
127 printf("Algorithm: %" PRIu64 " %s\n", pubkey->algorithm,
128 (pubkey->algorithm < kNumAlgorithms ?
129 algo_strings[pubkey->algorithm] : "(invalid)"));
130 printf("Key Version: %" PRIu64 "\n", pubkey->key_version);
Bill Richardson8adcb432010-09-01 10:40:25 -0700131 printf("Key sha1sum: ");
Bill Richardson60bcbe32010-09-09 14:53:56 -0700132 PrintPubKeySha1Sum(pubkey);
133 printf("\n");
Bill Richardson8adcb432010-09-01 10:40:25 -0700134 if (outfile) {
135 if (0 != PublicKeyWrite(outfile, pubkey)) {
136 fprintf(stderr, "vbutil_key: Error writing key copy.\n");
Randall Spangler32a65262011-06-27 10:49:11 -0700137 free(pubkey);
Bill Richardson8adcb432010-09-01 10:40:25 -0700138 return 1;
139 }
140 }
Randall Spangler32a65262011-06-27 10:49:11 -0700141 free(pubkey);
Bill Richardsonabf05502010-07-01 10:22:06 -0700142 return 0;
Randall Spanglerd55c6452010-06-10 12:43:51 -0700143 }
144
Bill Richardsonabf05502010-07-01 10:22:06 -0700145 if ((privkey = PrivateKeyRead(infile))) {
146 printf("Private Key file: %s\n", infile);
147 printf("Algorithm: %" PRIu64 " %s\n", privkey->algorithm,
148 (privkey->algorithm < kNumAlgorithms ?
149 algo_strings[privkey->algorithm] : "(invalid)"));
Bill Richardson8adcb432010-09-01 10:40:25 -0700150 if (outfile) {
151 if (0 != PrivateKeyWrite(outfile, privkey)) {
152 fprintf(stderr, "vbutil_key: Error writing key copy.\n");
Randall Spangler32a65262011-06-27 10:49:11 -0700153 free(privkey);
Bill Richardson8adcb432010-09-01 10:40:25 -0700154 return 1;
155 }
156 }
Randall Spangler32a65262011-06-27 10:49:11 -0700157 free(privkey);
Bill Richardsonabf05502010-07-01 10:22:06 -0700158 return 0;
159 }
160
Randall Spangler32a65262011-06-27 10:49:11 -0700161 VbExError("Unable to parse either .vbpubk or vbprivk from %s\n", infile);
Bill Richardsonabf05502010-07-01 10:22:06 -0700162 return 1;
Randall Spanglerd55c6452010-06-10 12:43:51 -0700163}
164
165
Mike Frysinger7351ed72014-08-18 10:47:42 -0400166static int do_vbutil_key(int argc, char* argv[]) {
Randall Spanglerd55c6452010-06-10 12:43:51 -0700167
168 char *infile = NULL;
169 char *outfile = NULL;
170 int mode = 0;
171 int parse_error = 0;
172 uint64_t version = 1;
173 uint64_t algorithm = kNumAlgorithms;
174 char* e;
175 int i;
176
Bill Richardsonabf05502010-07-01 10:22:06 -0700177 char *progname = strrchr(argv[0], '/');
178 if (progname)
179 progname++;
180 else
181 progname = argv[0];
182
Randall Spanglerd55c6452010-06-10 12:43:51 -0700183 while ((i = getopt_long(argc, argv, "", long_opts, NULL)) != -1) {
184 switch (i) {
185 case '?':
186 /* Unhandled option */
Randall Spangler32a65262011-06-27 10:49:11 -0700187 VbExError("Unknown option\n");
Randall Spanglerd55c6452010-06-10 12:43:51 -0700188 parse_error = 1;
189 break;
190
Bill Richardsonabf05502010-07-01 10:22:06 -0700191 case OPT_INKEY:
Randall Spanglerd55c6452010-06-10 12:43:51 -0700192 infile = optarg;
193 break;
194
Randall Spanglerd55c6452010-06-10 12:43:51 -0700195 case OPT_KEY_VERSION:
196 version = strtoul(optarg, &e, 0);
197 if (!*optarg || (e && *e)) {
Randall Spangler32a65262011-06-27 10:49:11 -0700198 VbExError("Invalid --version\n");
Randall Spanglerd55c6452010-06-10 12:43:51 -0700199 parse_error = 1;
200 }
201 break;
202
203 case OPT_ALGORITHM:
204 algorithm = strtoul(optarg, &e, 0);
205 if (!*optarg || (e && *e)) {
Randall Spangler32a65262011-06-27 10:49:11 -0700206 VbExError("Invalid --algorithm\n");
Randall Spanglerd55c6452010-06-10 12:43:51 -0700207 parse_error = 1;
208 }
209 break;
210
211 case OPT_MODE_PACK:
Bill Richardsonabf05502010-07-01 10:22:06 -0700212 mode = i;
213 outfile = optarg;
214 break;
215
Randall Spanglerd55c6452010-06-10 12:43:51 -0700216 case OPT_MODE_UNPACK:
217 mode = i;
Bill Richardsonabf05502010-07-01 10:22:06 -0700218 infile = optarg;
Randall Spanglerd55c6452010-06-10 12:43:51 -0700219 break;
Bill Richardson8adcb432010-09-01 10:40:25 -0700220
221 case OPT_COPYTO:
222 outfile = optarg;
223 break;
Randall Spanglerd55c6452010-06-10 12:43:51 -0700224 }
225 }
226
227 if (parse_error)
Bill Richardsonabf05502010-07-01 10:22:06 -0700228 return PrintHelp(progname);
Randall Spanglerd55c6452010-06-10 12:43:51 -0700229
230 switch(mode) {
231 case OPT_MODE_PACK:
232 return Pack(infile, outfile, algorithm, version);
233 case OPT_MODE_UNPACK:
234 return Unpack(infile, outfile);
235 default:
236 printf("Must specify a mode.\n");
Bill Richardsonabf05502010-07-01 10:22:06 -0700237 return PrintHelp(progname);
Randall Spanglerd55c6452010-06-10 12:43:51 -0700238 }
239}
Bill Richardsonb84b81d2014-07-14 14:48:31 -0700240
241DECLARE_FUTIL_COMMAND(vbutil_key, do_vbutil_key,
242 "Wraps RSA keys with vboot headers");