OLD | NEW |
(Empty) | |
| 1 #include <getopt.h> |
| 2 #include <inttypes.h> /* For PRIu64 */ |
| 3 #include <stdio.h> |
| 4 #include <stdlib.h> |
| 5 |
| 6 #include "cryptolib.h" |
| 7 #include "host_common.h" |
| 8 #include "vboot_common.h" |
| 9 |
| 10 |
| 11 /* Command line options */ |
| 12 enum { |
| 13 OPT_MODE_PACK = 1000, |
| 14 OPT_MODE_UNPACK, |
| 15 OPT_DATAPUBKEY, |
| 16 OPT_SIGNPUBKEY, |
| 17 OPT_SIGNPRIVATE, |
| 18 OPT_ALGORITHM, |
| 19 OPT_FLAGS, |
| 20 }; |
| 21 |
| 22 static struct option long_opts[] = { |
| 23 {"pack", 1, 0, OPT_MODE_PACK }, |
| 24 {"unpack", 1, 0, OPT_MODE_UNPACK }, |
| 25 {"datapubkey", 1, 0, OPT_DATAPUBKEY }, |
| 26 {"signpubkey", 1, 0, OPT_SIGNPUBKEY }, |
| 27 {"signprivate", 1, 0, OPT_SIGNPRIVATE }, |
| 28 {"algorithm", 1, 0, OPT_ALGORITHM }, |
| 29 {"flags", 1, 0, OPT_FLAGS }, |
| 30 {NULL, 0, 0, 0} |
| 31 }; |
| 32 |
| 33 |
| 34 /* Print help and return error */ |
| 35 static int PrintHelp(void) { |
| 36 int i; |
| 37 |
| 38 puts("vbutil_keyblock - Verified boot key block utility\n" |
| 39 "\n" |
| 40 "Usage: vbutil_keyblock <--pack|--unpack> <file> [OPTIONS]\n" |
| 41 "\n" |
| 42 "For '--pack <file>', required OPTIONS are:\n" |
| 43 " --datapubkey <file> Data public key in .vbpubk format\n" |
| 44 " --signprivate <file> Signing private key in .pem format\n" |
| 45 " --algorithm <algoid> Signing algorithm for key, one of:"); |
| 46 |
| 47 for (i = 0; i < kNumAlgorithms; i++) |
| 48 printf(" %d (%s)\n", i, algo_strings[i]); |
| 49 |
| 50 puts("\n" |
| 51 "Optional OPTIONS are:\n" |
| 52 " --flags <number> Flags\n" |
| 53 "\n" |
| 54 "For '--unpack <file>', required OPTIONS are:\n" |
| 55 " --signpubkey <file> Signing public key in .vbpubk format\n" |
| 56 "Optional OPTIONS are:\n" |
| 57 " --datapubkey <file> Data public key output file\n" |
| 58 ""); |
| 59 return 1; |
| 60 } |
| 61 |
| 62 |
| 63 /* Pack a .keyblock */ |
| 64 static int Pack(const char* outfile, const char* datapubkey, |
| 65 const char* signprivate, uint64_t algorithm, |
| 66 uint64_t flags) { |
| 67 VbPublicKey* data_key; |
| 68 VbPrivateKey* signing_key; |
| 69 VbKeyBlockHeader* block; |
| 70 |
| 71 if (!outfile) { |
| 72 fprintf(stderr, "vbutil_keyblock: Must specify output filename\n"); |
| 73 return 1; |
| 74 } |
| 75 if (!datapubkey || !signprivate) { |
| 76 fprintf(stderr, "vbutil_keyblock: Must specify all keys\n"); |
| 77 return 1; |
| 78 } |
| 79 if (algorithm >= kNumAlgorithms) { |
| 80 fprintf(stderr, "Invalid algorithm\n"); |
| 81 return 1; |
| 82 } |
| 83 |
| 84 data_key = PublicKeyRead(datapubkey); |
| 85 if (!data_key) { |
| 86 fprintf(stderr, "vbutil_keyblock: Error reading data key.\n"); |
| 87 return 1; |
| 88 } |
| 89 signing_key = PrivateKeyRead(signprivate, algorithm); |
| 90 if (!signing_key) { |
| 91 fprintf(stderr, "vbutil_keyblock: Error reading signing key.\n"); |
| 92 return 1; |
| 93 } |
| 94 |
| 95 block = CreateKeyBlock(data_key, signing_key, flags); |
| 96 Free(data_key); |
| 97 Free(signing_key); |
| 98 |
| 99 if (0 != WriteFile(outfile, block, block->key_block_size)) { |
| 100 fprintf(stderr, "vbutil_keyblock: Error writing key block.\n"); |
| 101 return 1; |
| 102 } |
| 103 Free(block); |
| 104 return 0; |
| 105 } |
| 106 |
| 107 |
| 108 static int Unpack(const char* infile, const char* datapubkey, |
| 109 const char* signpubkey) { |
| 110 VbPublicKey* data_key; |
| 111 VbPublicKey* sign_key; |
| 112 VbKeyBlockHeader* block; |
| 113 uint64_t block_size; |
| 114 |
| 115 if (!infile || !signpubkey) { |
| 116 fprintf(stderr, "vbutil_keyblock: Must specify filename and signpubkey\n"); |
| 117 return 1; |
| 118 } |
| 119 |
| 120 sign_key = PublicKeyRead(signpubkey); |
| 121 if (!sign_key) { |
| 122 fprintf(stderr, "vbutil_keyblock: Error reading signpubkey.\n"); |
| 123 return 1; |
| 124 } |
| 125 |
| 126 block = (VbKeyBlockHeader*)ReadFile(infile, &block_size); |
| 127 if (!block) { |
| 128 fprintf(stderr, "vbutil_keyblock: Error reading key block.\n"); |
| 129 return 1; |
| 130 } |
| 131 if (0 != VerifyKeyBlock(block, block_size, sign_key)) { |
| 132 fprintf(stderr, "vbutil_keyblock: Error verifying key block.\n"); |
| 133 return 1; |
| 134 } |
| 135 Free(sign_key); |
| 136 |
| 137 printf("Key block file: %s\n", infile); |
| 138 printf("Flags: %" PRIu64 "\n", block->key_block_flags); |
| 139 |
| 140 data_key = &block->data_key; |
| 141 printf("Data key algorithm: %" PRIu64 " %s\n", data_key->algorithm, |
| 142 (data_key->algorithm < kNumAlgorithms ? |
| 143 algo_strings[data_key->algorithm] : "(invalid)")); |
| 144 printf("Data key version: %" PRIu64 "\n", data_key->key_version); |
| 145 |
| 146 /* TODO: write key data, if output file specified */ |
| 147 |
| 148 Free(block); |
| 149 return 0; |
| 150 } |
| 151 |
| 152 |
| 153 int main(int argc, char* argv[]) { |
| 154 |
| 155 char* filename = NULL; |
| 156 char* datapubkey = NULL; |
| 157 char* signpubkey = NULL; |
| 158 char* signprivate = NULL; |
| 159 uint64_t flags = 0; |
| 160 uint64_t algorithm = kNumAlgorithms; |
| 161 int mode = 0; |
| 162 int parse_error = 0; |
| 163 char* e; |
| 164 int i; |
| 165 |
| 166 while ((i = getopt_long(argc, argv, "", long_opts, NULL)) != -1) { |
| 167 switch (i) { |
| 168 case '?': |
| 169 /* Unhandled option */ |
| 170 printf("Unknown option\n"); |
| 171 parse_error = 1; |
| 172 break; |
| 173 |
| 174 case OPT_MODE_PACK: |
| 175 case OPT_MODE_UNPACK: |
| 176 mode = i; |
| 177 filename = optarg; |
| 178 break; |
| 179 |
| 180 case OPT_DATAPUBKEY: |
| 181 datapubkey = optarg; |
| 182 break; |
| 183 |
| 184 case OPT_SIGNPUBKEY: |
| 185 signpubkey = optarg; |
| 186 break; |
| 187 |
| 188 case OPT_SIGNPRIVATE: |
| 189 signprivate = optarg; |
| 190 break; |
| 191 |
| 192 case OPT_ALGORITHM: |
| 193 algorithm = strtoul(optarg, &e, 0); |
| 194 if (!*optarg || (e && *e)) { |
| 195 printf("Invalid --algorithm\n"); |
| 196 parse_error = 1; |
| 197 } |
| 198 break; |
| 199 |
| 200 case OPT_FLAGS: |
| 201 flags = strtoul(optarg, &e, 0); |
| 202 if (!*optarg || (e && *e)) { |
| 203 printf("Invalid --flags\n"); |
| 204 parse_error = 1; |
| 205 } |
| 206 break; |
| 207 } |
| 208 } |
| 209 |
| 210 if (parse_error) |
| 211 return PrintHelp(); |
| 212 |
| 213 switch(mode) { |
| 214 case OPT_MODE_PACK: |
| 215 return Pack(filename, datapubkey, signprivate, algorithm, flags); |
| 216 case OPT_MODE_UNPACK: |
| 217 return Unpack(filename, datapubkey, signpubkey); |
| 218 default: |
| 219 printf("Must specify a mode.\n"); |
| 220 return PrintHelp(); |
| 221 } |
| 222 } |
OLD | NEW |