Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(738)

Side by Side Diff: firmware/lib/vboot_common.c

Issue 3126013: Fix KeyBlockVerify() to take an explicit param for whether to use hash only. (Closed) Base URL: ssh://gitrw.chromium.org/vboot_reference.git
Patch Set: Fix one last typo Created 10 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 * Common functions between firmware and kernel verified boot. 5 * Common functions between firmware and kernel verified boot.
6 * (Firmware portion) 6 * (Firmware portion)
7 */ 7 */
8 8
9 9
10 #include "vboot_common.h" 10 #include "vboot_common.h"
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
49 * the parent data. Returns 0 if inside, 1 if error. */ 49 * the parent data. Returns 0 if inside, 1 if error. */
50 int VerifyMemberInside(const void* parent, uint64_t parent_size, 50 int VerifyMemberInside(const void* parent, uint64_t parent_size,
51 const void* member, uint64_t member_size, 51 const void* member, uint64_t member_size,
52 uint64_t member_data_offset, 52 uint64_t member_data_offset,
53 uint64_t member_data_size) { 53 uint64_t member_data_size) {
54 uint64_t end = OffsetOf(parent, member); 54 uint64_t end = OffsetOf(parent, member);
55 55
56 if (end > parent_size) 56 if (end > parent_size)
57 return 1; 57 return 1;
58 58
59 if (UINT64_MAX - end < member_size)
60 return 1; /* Detect wraparound in integer math */
59 if (end + member_size > parent_size) 61 if (end + member_size > parent_size)
60 return 1; 62 return 1;
61 63
64 if (UINT64_MAX - end < member_data_offset)
65 return 1;
62 end += member_data_offset; 66 end += member_data_offset;
63 if (end > parent_size) 67 if (end > parent_size)
64 return 1; 68 return 1;
69
70 if (UINT64_MAX - end < member_data_size)
71 return 1;
65 if (end + member_data_size > parent_size) 72 if (end + member_data_size > parent_size)
66 return 1; 73 return 1;
67 74
68 return 0; 75 return 0;
69 } 76 }
70 77
71 78
72 int VerifyPublicKeyInside(const void* parent, uint64_t parent_size, 79 int VerifyPublicKeyInside(const void* parent, uint64_t parent_size,
73 const VbPublicKey* key) { 80 const VbPublicKey* key) {
74 return VerifyMemberInside(parent, parent_size, 81 return VerifyMemberInside(parent, parent_size,
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
156 163
157 if (!RSAVerifyBinaryWithDigest_f(NULL, key, digest, 164 if (!RSAVerifyBinaryWithDigest_f(NULL, key, digest,
158 GetSignatureDataC(sig), key->algorithm)) 165 GetSignatureDataC(sig), key->algorithm))
159 return 1; 166 return 1;
160 167
161 return 0; 168 return 0;
162 } 169 }
163 170
164 171
165 int KeyBlockVerify(const VbKeyBlockHeader* block, uint64_t size, 172 int KeyBlockVerify(const VbKeyBlockHeader* block, uint64_t size,
166 const VbPublicKey *key) { 173 const VbPublicKey *key, int hash_only) {
167 174
168 const VbSignature* sig; 175 const VbSignature* sig;
169 176
170 /* Sanity checks before attempting signature of data */ 177 /* Sanity checks before attempting signature of data */
171 if (SafeMemcmp(block->magic, KEY_BLOCK_MAGIC, KEY_BLOCK_MAGIC_SIZE)) { 178 if (SafeMemcmp(block->magic, KEY_BLOCK_MAGIC, KEY_BLOCK_MAGIC_SIZE)) {
172 VBDEBUG(("Not a valid verified boot key block.\n")); 179 VBDEBUG(("Not a valid verified boot key block.\n"));
173 return VBOOT_KEY_BLOCK_INVALID; 180 return VBOOT_KEY_BLOCK_INVALID;
174 } 181 }
175 if (block->header_version_major != KEY_BLOCK_HEADER_VERSION_MAJOR) { 182 if (block->header_version_major != KEY_BLOCK_HEADER_VERSION_MAJOR) {
176 VBDEBUG(("Incompatible key block header version.\n")); 183 VBDEBUG(("Incompatible key block header version.\n"));
177 return VBOOT_KEY_BLOCK_INVALID; 184 return VBOOT_KEY_BLOCK_INVALID;
178 } 185 }
179 if (size < block->key_block_size) { 186 if (size < block->key_block_size) {
180 VBDEBUG(("Not enough data for key block.\n")); 187 VBDEBUG(("Not enough data for key block.\n"));
181 return VBOOT_KEY_BLOCK_INVALID; 188 return VBOOT_KEY_BLOCK_INVALID;
182 } 189 }
190 if (!hash_only && !key) {
191 VBDEBUG(("Missing required public key.\n"));
192 return VBOOT_PUBLIC_KEY_INVALID;
193 }
183 194
184 /* Check signature or hash, depending on whether we provide a key. Note that 195 /* Check signature or hash, depending on whether we provide a key. Note that
gauravsh 2010/08/17 22:24:13 update comment to reflect the hash_only flag
Randall Spangler 2010/08/17 22:43:55 Done.
185 * we don't require a key even if the keyblock has a signature, because the 196 * we don't require a key even if the keyblock has a signature, because the
186 * caller may not care if the keyblock itself is signed (for example, booting 197 * caller may not care if the keyblock itself is signed (for example, booting
187 * a Google-signed kernel in developer mode). 198 * a Google-signed kernel in developer mode).
188 */ 199 */
189 if (key) { 200 if (hash_only) {
201 /* Check hash */
202 uint8_t* header_checksum = NULL;
203 int rv;
204
205 sig = &block->key_block_checksum;
206
207 if (VerifySignatureInside(block, block->key_block_size, sig)) {
208 VBDEBUG(("Key block hash off end of block\n"));
209 return VBOOT_KEY_BLOCK_INVALID;
210 }
211 if (sig->sig_size != SHA512_DIGEST_SIZE) {
212 VBDEBUG(("Wrong hash size for key block.\n"));
213 return VBOOT_KEY_BLOCK_INVALID;
214 }
215
216 VBDEBUG(("Checking key block hash only...\n"));
217 header_checksum = DigestBuf((const uint8_t*)block, sig->data_size,
218 SHA512_DIGEST_ALGORITHM);
219 rv = SafeMemcmp(header_checksum, GetSignatureDataC(sig),
220 SHA512_DIGEST_SIZE);
221 Free(header_checksum);
222 if (rv) {
223 VBDEBUG(("Invalid key block hash.\n"));
224 return VBOOT_KEY_BLOCK_HASH;
225 }
226 } else {
190 /* Check signature */ 227 /* Check signature */
191 RSAPublicKey* rsa; 228 RSAPublicKey* rsa;
192 int rv; 229 int rv;
193 230
194 sig = &block->key_block_signature; 231 sig = &block->key_block_signature;
195 232
196 if (VerifySignatureInside(block, block->key_block_size, sig)) { 233 if (VerifySignatureInside(block, block->key_block_size, sig)) {
197 VBDEBUG(("Key block signature off end of block\n")); 234 VBDEBUG(("Key block signature off end of block\n"));
198 return VBOOT_KEY_BLOCK_INVALID; 235 return VBOOT_KEY_BLOCK_INVALID;
199 } 236 }
200 237
201 rsa = PublicKeyToRSA(key); 238 rsa = PublicKeyToRSA(key);
202 if (!rsa) { 239 if (!rsa) {
203 VBDEBUG(("Invalid public key\n")); 240 VBDEBUG(("Invalid public key\n"));
204 return VBOOT_PUBLIC_KEY_INVALID; 241 return VBOOT_PUBLIC_KEY_INVALID;
205 } 242 }
206 243
207 /* Make sure advertised signature data sizes are sane. */ 244 /* Make sure advertised signature data sizes are sane. */
208 if (block->key_block_size < sig->data_size) { 245 if (block->key_block_size < sig->data_size) {
209 VBDEBUG(("Signature calculated past end of the block\n")); 246 VBDEBUG(("Signature calculated past end of the block\n"));
210 return VBOOT_KEY_BLOCK_INVALID; 247 return VBOOT_KEY_BLOCK_INVALID;
211 } 248 }
212 VBDEBUG(("Checking key block signature...\n")); 249 VBDEBUG(("Checking key block signature...\n"));
213 rv = VerifyData((const uint8_t*)block, size, sig, rsa); 250 rv = VerifyData((const uint8_t*)block, size, sig, rsa);
214 RSAPublicKeyFree(rsa); 251 RSAPublicKeyFree(rsa);
215 if (rv) { 252 if (rv) {
216 VBDEBUG(("Invalid key block signature.\n")); 253 VBDEBUG(("Invalid key block signature.\n"));
217 return VBOOT_KEY_BLOCK_SIGNATURE; 254 return VBOOT_KEY_BLOCK_SIGNATURE;
218 } 255 }
219 } else {
220 /* Check hash */
221 uint8_t* header_checksum = NULL;
222 int rv;
223
224 sig = &block->key_block_checksum;
225
226 if (VerifySignatureInside(block, block->key_block_size, sig)) {
227 VBDEBUG(("Key block hash off end of block\n"));
228 return VBOOT_KEY_BLOCK_INVALID;
229 }
230 if (sig->sig_size != SHA512_DIGEST_SIZE) {
231 VBDEBUG(("Wrong hash size for key block.\n"));
232 return VBOOT_KEY_BLOCK_INVALID;
233 }
234
235 VBDEBUG(("Checking key block hash only...\n"));
236 header_checksum = DigestBuf((const uint8_t*)block, sig->data_size,
237 SHA512_DIGEST_ALGORITHM);
238 rv = SafeMemcmp(header_checksum, GetSignatureDataC(sig),
239 SHA512_DIGEST_SIZE);
240 Free(header_checksum);
241 if (rv) {
242 VBDEBUG(("Invalid key block hash.\n"));
243 return VBOOT_KEY_BLOCK_HASH;
244 }
245 } 256 }
246 257
247 /* Verify we signed enough data */ 258 /* Verify we signed enough data */
248 if (sig->data_size < sizeof(VbKeyBlockHeader)) { 259 if (sig->data_size < sizeof(VbKeyBlockHeader)) {
249 VBDEBUG(("Didn't sign enough data\n")); 260 VBDEBUG(("Didn't sign enough data\n"));
250 return VBOOT_KEY_BLOCK_INVALID; 261 return VBOOT_KEY_BLOCK_INVALID;
251 } 262 }
252 263
253 /* Verify data key is inside the block and inside signed data */ 264 /* Verify data key is inside the block and inside signed data */
254 if (VerifyPublicKeyInside(block, block->key_block_size, &block->data_key)) { 265 if (VerifyPublicKeyInside(block, block->key_block_size, &block->data_key)) {
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
357 /* Verify body signature is inside the block */ 368 /* Verify body signature is inside the block */
358 if (VerifySignatureInside(preamble, preamble->preamble_size, 369 if (VerifySignatureInside(preamble, preamble->preamble_size,
359 &preamble->body_signature)) { 370 &preamble->body_signature)) {
360 VBDEBUG(("Kernel body signature off end of preamble\n")); 371 VBDEBUG(("Kernel body signature off end of preamble\n"));
361 return VBOOT_PREAMBLE_INVALID; 372 return VBOOT_PREAMBLE_INVALID;
362 } 373 }
363 374
364 /* Success */ 375 /* Success */
365 return VBOOT_SUCCESS; 376 return VBOOT_SUCCESS;
366 } 377 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698