OLD | NEW |
1 /* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 1 /* 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 | 2 * Use of this source code is governed by a BSD-style license that can be |
3 * found in the LICENSE file. | 3 * found in the LICENSE file. |
4 * | 4 * |
5 * Verified boot key block utility | 5 * Verified boot key block utility |
6 */ | 6 */ |
7 | 7 |
8 #include <getopt.h> | 8 #include <getopt.h> |
9 #include <inttypes.h> /* For PRIu64 */ | 9 #include <stdint.h> |
10 #include <stdio.h> | 10 #include <stdio.h> |
11 #include <stdlib.h> | 11 #include <stdlib.h> |
12 #include <string.h> | 12 #include <string.h> |
13 | 13 |
14 #include "cryptolib.h" | 14 #include "cryptolib.h" |
15 #include "host_common.h" | 15 #include "host_common.h" |
16 #include "vboot_common.h" | 16 #include "vboot_common.h" |
17 | 17 |
18 | 18 |
19 /* Command line options */ | 19 /* Command line options */ |
20 enum { | 20 enum { |
21 OPT_MODE_PACK = 1000, | 21 OPT_MODE_PACK = 1000, |
22 OPT_MODE_UNPACK, | 22 OPT_MODE_UNPACK, |
23 OPT_DATAPUBKEY, | 23 OPT_DATAPUBKEY, |
24 OPT_SIGNPUBKEY, | 24 OPT_SIGNPUBKEY, |
25 OPT_SIGNPRIVATE, | 25 OPT_SIGNPRIVATE, |
| 26 OPT_SIGNPRIVATE_PEM, |
| 27 OPT_PEM_ALGORITHM, |
| 28 OPT_EXTERNAL_SIGNER, |
26 OPT_FLAGS, | 29 OPT_FLAGS, |
27 }; | 30 }; |
28 | 31 |
29 static struct option long_opts[] = { | 32 static struct option long_opts[] = { |
30 {"pack", 1, 0, OPT_MODE_PACK }, | 33 {"pack", 1, 0, OPT_MODE_PACK }, |
31 {"unpack", 1, 0, OPT_MODE_UNPACK }, | 34 {"unpack", 1, 0, OPT_MODE_UNPACK }, |
32 {"datapubkey", 1, 0, OPT_DATAPUBKEY }, | 35 {"datapubkey", 1, 0, OPT_DATAPUBKEY }, |
33 {"signpubkey", 1, 0, OPT_SIGNPUBKEY }, | 36 {"signpubkey", 1, 0, OPT_SIGNPUBKEY }, |
34 {"signprivate", 1, 0, OPT_SIGNPRIVATE }, | 37 {"signprivate", 1, 0, OPT_SIGNPRIVATE }, |
| 38 {"signprivate_pem", 1, 0, OPT_SIGNPRIVATE_PEM }, |
| 39 {"pem_algorithm", 1, 0, OPT_PEM_ALGORITHM }, |
| 40 {"externalsigner", 1, 0, OPT_EXTERNAL_SIGNER }, |
35 {"flags", 1, 0, OPT_FLAGS }, | 41 {"flags", 1, 0, OPT_FLAGS }, |
36 {NULL, 0, 0, 0} | 42 {NULL, 0, 0, 0} |
37 }; | 43 }; |
38 | 44 |
39 | 45 |
40 /* Print help and return error */ | 46 /* Print help and return error */ |
41 static int PrintHelp(char *progname) { | 47 static int PrintHelp(char *progname) { |
42 fprintf(stderr, | 48 fprintf(stderr, |
43 "Verified boot key block utility\n" | 49 "Verified boot key block utility\n" |
44 "\n" | 50 "\n" |
45 "Usage: %s <--pack|--unpack> <file> [OPTIONS]\n" | 51 "Usage: %s <--pack|--unpack> <file> [OPTIONS]\n" |
46 "\n" | 52 "\n" |
47 "For '--pack <file>', required OPTIONS are:\n" | 53 "For '--pack <file>', required OPTIONS are:\n" |
48 " --datapubkey <file> Data public key in .vbpubk format\n" | 54 " --datapubkey <file> Data public key in .vbpubk format\n" |
49 "\n" | 55 "\n" |
50 "Optional OPTIONS are:\n" | 56 "Optional OPTIONS are:\n" |
51 " --signprivate <file>" | 57 " --signprivate <file>" |
52 " Signing private key in .vbprivk format. Without this arg,\n" | 58 " Signing private key in .vbprivk format.\n" |
53 " the keyblock will not be signed.\n" | 59 "OR\n" |
| 60 " --signprivate_pem <file>\n" |
| 61 " --pem_algorithm <algo>\n" |
| 62 " Signing private key in .pem format and algorithm id.\n" |
| 63 "(If one of the above arguments is not specified, the keyblock will\n" |
| 64 "not be signed.)\n" |
| 65 "\n" |
54 " --flags <number> Specifies allowed use conditions.\n" | 66 " --flags <number> Specifies allowed use conditions.\n" |
| 67 " --externalsigner \"cmd\"" |
| 68 " Use an external program cmd to calculate the signatures.\n" |
55 "\n" | 69 "\n" |
56 "For '--unpack <file>', optional OPTIONS are:\n" | 70 "For '--unpack <file>', optional OPTIONS are:\n" |
57 " --signpubkey <file>" | 71 " --signpubkey <file>" |
58 " Signing public key in .vbpubk format. This is required to\n" | 72 " Signing public key in .vbpubk format. This is required to\n" |
59 " verify a signed keyblock.\n" | 73 " verify a signed keyblock.\n" |
60 " --datapubkey <file>" | 74 " --datapubkey <file>" |
61 " Write the data public key to this file.\n", | 75 " Write the data public key to this file.\n", |
62 progname); | 76 progname); |
63 return 1; | 77 return 1; |
64 } | 78 } |
65 | 79 |
66 | |
67 /* Pack a .keyblock */ | 80 /* Pack a .keyblock */ |
68 static int Pack(const char* outfile, const char* datapubkey, | 81 static int Pack(const char* outfile, const char* datapubkey, |
69 const char* signprivate, uint64_t flags) { | 82 const char* signprivate, |
| 83 const char* signprivate_pem, uint64_t pem_algorithm, |
| 84 uint64_t flags, |
| 85 const char* external_signer) { |
70 VbPublicKey* data_key; | 86 VbPublicKey* data_key; |
71 VbPrivateKey* signing_key = NULL; | 87 VbPrivateKey* signing_key = NULL; |
72 VbKeyBlockHeader* block; | 88 VbKeyBlockHeader* block; |
73 | 89 |
74 if (!outfile) { | 90 if (!outfile) { |
75 fprintf(stderr, "vbutil_keyblock: Must specify output filename.\n"); | 91 fprintf(stderr, "vbutil_keyblock: Must specify output filename.\n"); |
76 return 1; | 92 return 1; |
77 } | 93 } |
78 if (!datapubkey) { | 94 if (!datapubkey) { |
79 fprintf(stderr, "vbutil_keyblock: Must specify data public key.\n"); | 95 fprintf(stderr, "vbutil_keyblock: Must specify data public key.\n"); |
80 return 1; | 96 return 1; |
81 } | 97 } |
82 | 98 |
83 data_key = PublicKeyRead(datapubkey); | 99 data_key = PublicKeyRead(datapubkey); |
84 if (!data_key) { | 100 if (!data_key) { |
85 fprintf(stderr, "vbutil_keyblock: Error reading data key.\n"); | 101 fprintf(stderr, "vbutil_keyblock: Error reading data key.\n"); |
86 return 1; | 102 return 1; |
87 } | 103 } |
88 | 104 |
89 if (signprivate) { | 105 if (signprivate_pem) { |
90 signing_key = PrivateKeyRead(signprivate); | 106 if (pem_algorithm >= kNumAlgorithms) { |
91 if (!signing_key) { | 107 fprintf(stderr, "vbutil_keyblock: Invalid --pem_algorithm %" PRIu64 "\n", |
92 fprintf(stderr, "vbutil_keyblock: Error reading signing key.\n"); | 108 pem_algorithm); |
93 return 1; | 109 return 1; |
94 } | 110 } |
| 111 if (external_signer) { |
| 112 /* External signing uses the PEM file directly. */ |
| 113 block = KeyBlockCreate_external(data_key, |
| 114 signprivate_pem, pem_algorithm, |
| 115 flags, |
| 116 external_signer); |
| 117 } else { |
| 118 signing_key = PrivateKeyReadPem(signprivate, pem_algorithm); |
| 119 if (!signing_key) { |
| 120 fprintf(stderr, "vbutil_keyblock: Error reading signing key.\n"); |
| 121 return 1; |
| 122 } |
| 123 block = KeyBlockCreate(data_key, signing_key, flags); |
| 124 } |
| 125 } else { |
| 126 if (signprivate) { |
| 127 signing_key = PrivateKeyRead(signprivate); |
| 128 if (!signing_key) { |
| 129 fprintf(stderr, "vbutil_keyblock: Error reading signing key.\n"); |
| 130 return 1; |
| 131 } |
| 132 } |
| 133 block = KeyBlockCreate(data_key, signing_key, flags); |
95 } | 134 } |
96 | 135 |
97 block = KeyBlockCreate(data_key, signing_key, flags); | |
98 Free(data_key); | 136 Free(data_key); |
99 if (signing_key) | 137 if (signing_key) |
100 Free(signing_key); | 138 Free(signing_key); |
101 | 139 |
102 if (0 != KeyBlockWrite(outfile, block)) { | 140 if (0 != KeyBlockWrite(outfile, block)) { |
103 fprintf(stderr, "vbutil_keyblock: Error writing key block.\n"); | 141 fprintf(stderr, "vbutil_keyblock: Error writing key block.\n"); |
104 return 1; | 142 return 1; |
105 } | 143 } |
106 Free(block); | 144 Free(block); |
107 return 0; | 145 return 0; |
108 } | 146 } |
109 | 147 |
110 | |
111 static int Unpack(const char* infile, const char* datapubkey, | 148 static int Unpack(const char* infile, const char* datapubkey, |
112 const char* signpubkey) { | 149 const char* signpubkey) { |
113 VbPublicKey* data_key; | 150 VbPublicKey* data_key; |
114 VbPublicKey* sign_key = NULL; | 151 VbPublicKey* sign_key = NULL; |
115 VbKeyBlockHeader* block; | 152 VbKeyBlockHeader* block; |
116 | 153 |
117 if (!infile) { | 154 if (!infile) { |
118 fprintf(stderr, "vbutil_keyblock: Must specify filename\n"); | 155 fprintf(stderr, "vbutil_keyblock: Must specify filename\n"); |
119 return 1; | 156 return 1; |
120 } | 157 } |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
174 return 0; | 211 return 0; |
175 } | 212 } |
176 | 213 |
177 | 214 |
178 int main(int argc, char* argv[]) { | 215 int main(int argc, char* argv[]) { |
179 | 216 |
180 char* filename = NULL; | 217 char* filename = NULL; |
181 char* datapubkey = NULL; | 218 char* datapubkey = NULL; |
182 char* signpubkey = NULL; | 219 char* signpubkey = NULL; |
183 char* signprivate = NULL; | 220 char* signprivate = NULL; |
| 221 char* signprivate_pem = NULL; |
| 222 char* external_signer = NULL; |
184 uint64_t flags = 0; | 223 uint64_t flags = 0; |
| 224 uint64_t pem_algorithm = 0; |
| 225 int is_pem_algorithm = 0; |
185 int mode = 0; | 226 int mode = 0; |
186 int parse_error = 0; | 227 int parse_error = 0; |
187 char* e; | 228 char* e; |
188 int i; | 229 int i; |
189 | 230 |
190 char *progname = strrchr(argv[0], '/'); | 231 char *progname = strrchr(argv[0], '/'); |
191 if (progname) | 232 if (progname) |
192 progname++; | 233 progname++; |
193 else | 234 else |
194 progname = argv[0]; | 235 progname = argv[0]; |
(...skipping 17 matching lines...) Expand all Loading... |
212 break; | 253 break; |
213 | 254 |
214 case OPT_SIGNPUBKEY: | 255 case OPT_SIGNPUBKEY: |
215 signpubkey = optarg; | 256 signpubkey = optarg; |
216 break; | 257 break; |
217 | 258 |
218 case OPT_SIGNPRIVATE: | 259 case OPT_SIGNPRIVATE: |
219 signprivate = optarg; | 260 signprivate = optarg; |
220 break; | 261 break; |
221 | 262 |
| 263 case OPT_SIGNPRIVATE_PEM: |
| 264 signprivate_pem = optarg; |
| 265 break; |
| 266 |
| 267 case OPT_PEM_ALGORITHM: |
| 268 pem_algorithm = strtoul(optarg, &e, 0); |
| 269 if (!*optarg || (e && *e)) { |
| 270 fprintf(stderr, "Invalid --pem_algorithm\n"); |
| 271 parse_error = 1; |
| 272 } else { |
| 273 is_pem_algorithm = 1; |
| 274 } |
| 275 break; |
| 276 |
| 277 case OPT_EXTERNAL_SIGNER: |
| 278 external_signer = optarg; |
| 279 break; |
| 280 |
222 case OPT_FLAGS: | 281 case OPT_FLAGS: |
223 flags = strtoul(optarg, &e, 0); | 282 flags = strtoul(optarg, &e, 0); |
224 if (!*optarg || (e && *e)) { | 283 if (!*optarg || (e && *e)) { |
225 printf("Invalid --flags\n"); | 284 fprintf(stderr, "Invalid --flags\n"); |
226 parse_error = 1; | 285 parse_error = 1; |
227 } | 286 } |
228 break; | 287 break; |
229 } | 288 } |
230 } | 289 } |
231 | 290 |
| 291 /* Check if the right combination of options was provided. */ |
| 292 if (signprivate && signprivate_pem) { |
| 293 fprintf(stderr, "Only one of --signprivate or --signprivate_pem must" |
| 294 " be specified\n"); |
| 295 parse_error = 1; |
| 296 } |
| 297 |
| 298 if (signprivate_pem && !is_pem_algorithm) { |
| 299 fprintf(stderr, "--pem_algorithm must be used with --signprivate_pem\n"); |
| 300 parse_error = 1; |
| 301 } |
| 302 |
| 303 if (external_signer && !signprivate_pem) { |
| 304 fprintf(stderr, "--externalsigner must be used with --signprivate_pem" |
| 305 "\n"); |
| 306 parse_error = 1; |
| 307 } |
| 308 |
232 if (parse_error) | 309 if (parse_error) |
233 return PrintHelp(progname); | 310 return PrintHelp(progname); |
234 | 311 |
235 switch(mode) { | 312 switch(mode) { |
236 case OPT_MODE_PACK: | 313 case OPT_MODE_PACK: |
237 return Pack(filename, datapubkey, signprivate, flags); | 314 return Pack(filename, datapubkey, signprivate, |
| 315 signprivate_pem, pem_algorithm, |
| 316 flags, |
| 317 external_signer); |
238 case OPT_MODE_UNPACK: | 318 case OPT_MODE_UNPACK: |
239 return Unpack(filename, datapubkey, signpubkey); | 319 return Unpack(filename, datapubkey, signpubkey); |
240 default: | 320 default: |
241 printf("Must specify a mode.\n"); | 321 printf("Must specify a mode.\n"); |
242 return PrintHelp(progname); | 322 return PrintHelp(progname); |
243 } | 323 } |
244 } | 324 } |
OLD | NEW |