| 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 <inttypes.h> /* For PRIu64 */ |
| 10 #include <stdio.h> | 10 #include <stdio.h> |
| (...skipping 28 matching lines...) Expand all Loading... |
| 39 | 39 |
| 40 /* Print help and return error */ | 40 /* Print help and return error */ |
| 41 static int PrintHelp(char *progname) { | 41 static int PrintHelp(char *progname) { |
| 42 fprintf(stderr, | 42 fprintf(stderr, |
| 43 "Verified boot key block utility\n" | 43 "Verified boot key block utility\n" |
| 44 "\n" | 44 "\n" |
| 45 "Usage: %s <--pack|--unpack> <file> [OPTIONS]\n" | 45 "Usage: %s <--pack|--unpack> <file> [OPTIONS]\n" |
| 46 "\n" | 46 "\n" |
| 47 "For '--pack <file>', required OPTIONS are:\n" | 47 "For '--pack <file>', required OPTIONS are:\n" |
| 48 " --datapubkey <file> Data public key in .vbpubk format\n" | 48 " --datapubkey <file> Data public key in .vbpubk format\n" |
| 49 " --signprivate <file>" | |
| 50 " Signing private key in .vbprivk format\n" | |
| 51 "\n" | 49 "\n" |
| 52 "Optional OPTIONS are:\n" | 50 "Optional OPTIONS are:\n" |
| 53 " --flags <number> Flags\n" | 51 " --signprivate <file>" |
| 52 " Signing private key in .vbprivk format. Without this arg,\n" |
| 53 " the keyblock will not be signed.\n" |
| 54 " --flags <number> Specifies allowed use conditions.\n" |
| 54 "\n" | 55 "\n" |
| 55 "For '--unpack <file>', required OPTIONS are:\n" | 56 "For '--unpack <file>', optional OPTIONS are:\n" |
| 56 " --signpubkey <file> Signing public key in .vbpubk format\n" | 57 " --signpubkey <file>" |
| 57 "Optional OPTIONS are:\n" | 58 " Signing public key in .vbpubk format. This is required to\n" |
| 58 " --datapubkey <file> Data public key output file\n", | 59 " verify a signed keyblock.\n" |
| 60 " --datapubkey <file>" |
| 61 " Write the data public key to this file.\n", |
| 59 progname); | 62 progname); |
| 60 return 1; | 63 return 1; |
| 61 } | 64 } |
| 62 | 65 |
| 63 | 66 |
| 64 /* Pack a .keyblock */ | 67 /* Pack a .keyblock */ |
| 65 static int Pack(const char* outfile, const char* datapubkey, | 68 static int Pack(const char* outfile, const char* datapubkey, |
| 66 const char* signprivate, uint64_t flags) { | 69 const char* signprivate, uint64_t flags) { |
| 67 VbPublicKey* data_key; | 70 VbPublicKey* data_key; |
| 68 VbPrivateKey* signing_key; | 71 VbPrivateKey* signing_key = NULL; |
| 69 VbKeyBlockHeader* block; | 72 VbKeyBlockHeader* block; |
| 70 | 73 |
| 71 if (!outfile) { | 74 if (!outfile) { |
| 72 fprintf(stderr, "vbutil_keyblock: Must specify output filename\n"); | 75 fprintf(stderr, "vbutil_keyblock: Must specify output filename.\n"); |
| 73 return 1; | 76 return 1; |
| 74 } | 77 } |
| 75 if (!datapubkey || !signprivate) { | 78 if (!datapubkey) { |
| 76 fprintf(stderr, "vbutil_keyblock: Must specify all keys\n"); | 79 fprintf(stderr, "vbutil_keyblock: Must specify data public key.\n"); |
| 77 return 1; | 80 return 1; |
| 78 } | 81 } |
| 79 | 82 |
| 80 data_key = PublicKeyRead(datapubkey); | 83 data_key = PublicKeyRead(datapubkey); |
| 81 if (!data_key) { | 84 if (!data_key) { |
| 82 fprintf(stderr, "vbutil_keyblock: Error reading data key.\n"); | 85 fprintf(stderr, "vbutil_keyblock: Error reading data key.\n"); |
| 83 return 1; | 86 return 1; |
| 84 } | 87 } |
| 85 signing_key = PrivateKeyRead(signprivate); | 88 |
| 86 if (!signing_key) { | 89 if (signprivate) { |
| 87 fprintf(stderr, "vbutil_keyblock: Error reading signing key.\n"); | 90 signing_key = PrivateKeyRead(signprivate); |
| 88 return 1; | 91 if (!signing_key) { |
| 92 fprintf(stderr, "vbutil_keyblock: Error reading signing key.\n"); |
| 93 return 1; |
| 94 } |
| 89 } | 95 } |
| 90 | 96 |
| 91 block = KeyBlockCreate(data_key, signing_key, flags); | 97 block = KeyBlockCreate(data_key, signing_key, flags); |
| 92 Free(data_key); | 98 Free(data_key); |
| 93 Free(signing_key); | 99 if (signing_key) |
| 100 Free(signing_key); |
| 94 | 101 |
| 95 if (0 != KeyBlockWrite(outfile, block)) { | 102 if (0 != KeyBlockWrite(outfile, block)) { |
| 96 fprintf(stderr, "vbutil_keyblock: Error writing key block.\n"); | 103 fprintf(stderr, "vbutil_keyblock: Error writing key block.\n"); |
| 97 return 1; | 104 return 1; |
| 98 } | 105 } |
| 99 Free(block); | 106 Free(block); |
| 100 return 0; | 107 return 0; |
| 101 } | 108 } |
| 102 | 109 |
| 103 | 110 |
| 104 static int Unpack(const char* infile, const char* datapubkey, | 111 static int Unpack(const char* infile, const char* datapubkey, |
| 105 const char* signpubkey) { | 112 const char* signpubkey) { |
| 106 VbPublicKey* data_key; | 113 VbPublicKey* data_key; |
| 107 VbPublicKey* sign_key; | 114 VbPublicKey* sign_key = NULL; |
| 108 VbKeyBlockHeader* block; | 115 VbKeyBlockHeader* block; |
| 109 | 116 |
| 110 if (!infile || !signpubkey) { | 117 if (!infile) { |
| 111 fprintf(stderr, "vbutil_keyblock: Must specify filename and signpubkey\n"); | 118 fprintf(stderr, "vbutil_keyblock: Must specify filename\n"); |
| 112 return 1; | 119 return 1; |
| 113 } | 120 } |
| 114 | 121 |
| 115 sign_key = PublicKeyRead(signpubkey); | |
| 116 if (!sign_key) { | |
| 117 fprintf(stderr, "vbutil_keyblock: Error reading signpubkey.\n"); | |
| 118 return 1; | |
| 119 } | |
| 120 | |
| 121 block = KeyBlockRead(infile); | 122 block = KeyBlockRead(infile); |
| 122 if (!block) { | 123 if (!block) { |
| 123 fprintf(stderr, "vbutil_keyblock: Error reading key block.\n"); | 124 fprintf(stderr, "vbutil_keyblock: Error reading key block.\n"); |
| 124 return 1; | 125 return 1; |
| 125 } | 126 } |
| 126 /* Verify the block with the signing public key, since | 127 |
| 127 * KeyBlockRead() only verified the hash. */ | 128 /* If the block is signed, then verify it with the signing public key, since |
| 128 /* TODO: should just print a warning, since self-signed key blocks | 129 KeyBlockRead() only verified the hash. */ |
| 129 * won't have a public key; signpubkey should also be an optional | 130 if (block->key_block_signature.sig_size) { |
| 130 * argument. */ | 131 if (!signpubkey) { |
| 131 if (0 != KeyBlockVerify(block, block->key_block_size, sign_key)) { | 132 fprintf(stderr, |
| 132 fprintf(stderr, "vbutil_keyblock: Error verifying key block.\n"); | 133 "vbutil_keyblock: keyblock requires public key to verify\n"); |
| 133 return 1; | 134 return 1; |
| 135 } |
| 136 sign_key = PublicKeyRead(signpubkey); |
| 137 if (!sign_key) { |
| 138 fprintf(stderr, "vbutil_keyblock: Error reading signpubkey.\n"); |
| 139 return 1; |
| 140 } |
| 141 if (0 != KeyBlockVerify(block, block->key_block_size, sign_key)) { |
| 142 fprintf(stderr, "vbutil_keyblock: Error verifying key block.\n"); |
| 143 return 1; |
| 144 } |
| 145 printf("Signature algorithm: %" PRIu64 " %s\n", sign_key->algorithm, |
| 146 (sign_key->algorithm < kNumAlgorithms ? |
| 147 algo_strings[sign_key->algorithm] : "(invalid)")); |
| 148 Free(sign_key); |
| 149 } else { |
| 150 printf("Signature Algorithm: <none>\n"); |
| 134 } | 151 } |
| 135 Free(sign_key); | |
| 136 | 152 |
| 137 printf("Key block file: %s\n", infile); | 153 printf("Key block file: %s\n", infile); |
| 138 printf("Flags: %" PRIu64 "\n", block->key_block_flags); | 154 printf("Flags: %" PRIu64 "\n", block->key_block_flags); |
| 139 | 155 |
| 140 data_key = &block->data_key; | 156 data_key = &block->data_key; |
| 141 printf("Data key algorithm: %" PRIu64 " %s\n", data_key->algorithm, | 157 printf("Data key algorithm: %" PRIu64 " %s\n", data_key->algorithm, |
| 142 (data_key->algorithm < kNumAlgorithms ? | 158 (data_key->algorithm < kNumAlgorithms ? |
| 143 algo_strings[data_key->algorithm] : "(invalid)")); | 159 algo_strings[data_key->algorithm] : "(invalid)")); |
| 144 printf("Data key version: %" PRIu64 "\n", data_key->key_version); | 160 printf("Data key version: %" PRIu64 "\n", data_key->key_version); |
| 145 | 161 |
| 146 /* TODO: write key data, if output file specified */ | 162 if (datapubkey) { |
| 163 if (0 != PublicKeyWrite(datapubkey, data_key)) { |
| 164 fprintf(stderr, |
| 165 "vbutil_keyblock: unable to write public key\n"); |
| 166 return 1; |
| 167 } |
| 168 } |
| 147 | 169 |
| 148 Free(block); | 170 Free(block); |
| 149 return 0; | 171 return 0; |
| 150 } | 172 } |
| 151 | 173 |
| 152 | 174 |
| 153 int main(int argc, char* argv[]) { | 175 int main(int argc, char* argv[]) { |
| 154 | 176 |
| 155 char* filename = NULL; | 177 char* filename = NULL; |
| 156 char* datapubkey = NULL; | 178 char* datapubkey = NULL; |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 210 switch(mode) { | 232 switch(mode) { |
| 211 case OPT_MODE_PACK: | 233 case OPT_MODE_PACK: |
| 212 return Pack(filename, datapubkey, signprivate, flags); | 234 return Pack(filename, datapubkey, signprivate, flags); |
| 213 case OPT_MODE_UNPACK: | 235 case OPT_MODE_UNPACK: |
| 214 return Unpack(filename, datapubkey, signpubkey); | 236 return Unpack(filename, datapubkey, signpubkey); |
| 215 default: | 237 default: |
| 216 printf("Must specify a mode.\n"); | 238 printf("Must specify a mode.\n"); |
| 217 return PrintHelp(progname); | 239 return PrintHelp(progname); |
| 218 } | 240 } |
| 219 } | 241 } |
| OLD | NEW |