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 |