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 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 */ 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 */ 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 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