Index: firmware/lib/vboot_common.c |
diff --git a/firmware/lib/vboot_common.c b/firmware/lib/vboot_common.c |
index 2635fe64a12910c5c8ae31e827830f81d2896c12..0cfe5fd5ff8db57f4d0ef2a9cba9386f76743ff7 100644 |
--- a/firmware/lib/vboot_common.c |
+++ b/firmware/lib/vboot_common.c |
@@ -56,12 +56,19 @@ int VerifyMemberInside(const void* parent, uint64_t parent_size, |
if (end > parent_size) |
return 1; |
+ if (UINT64_MAX - end < member_size) |
+ return 1; /* Detect wraparound in integer math */ |
if (end + member_size > parent_size) |
return 1; |
+ if (UINT64_MAX - end < member_data_offset) |
+ return 1; |
end += member_data_offset; |
if (end > parent_size) |
return 1; |
+ |
+ if (UINT64_MAX - end < member_data_size) |
+ return 1; |
if (end + member_data_size > parent_size) |
return 1; |
@@ -163,7 +170,7 @@ int VerifyDigest(const uint8_t* digest, const VbSignature *sig, |
int KeyBlockVerify(const VbKeyBlockHeader* block, uint64_t size, |
- const VbPublicKey *key) { |
+ const VbPublicKey *key, int hash_only) { |
const VbSignature* sig; |
@@ -180,13 +187,43 @@ int KeyBlockVerify(const VbKeyBlockHeader* block, uint64_t size, |
VBDEBUG(("Not enough data for key block.\n")); |
return VBOOT_KEY_BLOCK_INVALID; |
} |
+ if (!hash_only && !key) { |
+ VBDEBUG(("Missing required public key.\n")); |
+ return VBOOT_PUBLIC_KEY_INVALID; |
+ } |
/* 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.
|
* we don't require a key even if the keyblock has a signature, because the |
* caller may not care if the keyblock itself is signed (for example, booting |
* a Google-signed kernel in developer mode). |
*/ |
- if (key) { |
+ if (hash_only) { |
+ /* Check hash */ |
+ uint8_t* header_checksum = NULL; |
+ int rv; |
+ |
+ sig = &block->key_block_checksum; |
+ |
+ if (VerifySignatureInside(block, block->key_block_size, sig)) { |
+ VBDEBUG(("Key block hash off end of block\n")); |
+ return VBOOT_KEY_BLOCK_INVALID; |
+ } |
+ if (sig->sig_size != SHA512_DIGEST_SIZE) { |
+ VBDEBUG(("Wrong hash size for key block.\n")); |
+ return VBOOT_KEY_BLOCK_INVALID; |
+ } |
+ |
+ VBDEBUG(("Checking key block hash only...\n")); |
+ header_checksum = DigestBuf((const uint8_t*)block, sig->data_size, |
+ SHA512_DIGEST_ALGORITHM); |
+ rv = SafeMemcmp(header_checksum, GetSignatureDataC(sig), |
+ SHA512_DIGEST_SIZE); |
+ Free(header_checksum); |
+ if (rv) { |
+ VBDEBUG(("Invalid key block hash.\n")); |
+ return VBOOT_KEY_BLOCK_HASH; |
+ } |
+ } else { |
/* Check signature */ |
RSAPublicKey* rsa; |
int rv; |
@@ -216,32 +253,6 @@ int KeyBlockVerify(const VbKeyBlockHeader* block, uint64_t size, |
VBDEBUG(("Invalid key block signature.\n")); |
return VBOOT_KEY_BLOCK_SIGNATURE; |
} |
- } else { |
- /* Check hash */ |
- uint8_t* header_checksum = NULL; |
- int rv; |
- |
- sig = &block->key_block_checksum; |
- |
- if (VerifySignatureInside(block, block->key_block_size, sig)) { |
- VBDEBUG(("Key block hash off end of block\n")); |
- return VBOOT_KEY_BLOCK_INVALID; |
- } |
- if (sig->sig_size != SHA512_DIGEST_SIZE) { |
- VBDEBUG(("Wrong hash size for key block.\n")); |
- return VBOOT_KEY_BLOCK_INVALID; |
- } |
- |
- VBDEBUG(("Checking key block hash only...\n")); |
- header_checksum = DigestBuf((const uint8_t*)block, sig->data_size, |
- SHA512_DIGEST_ALGORITHM); |
- rv = SafeMemcmp(header_checksum, GetSignatureDataC(sig), |
- SHA512_DIGEST_SIZE); |
- Free(header_checksum); |
- if (rv) { |
- VBDEBUG(("Invalid key block hash.\n")); |
- return VBOOT_KEY_BLOCK_HASH; |
- } |
} |
/* Verify we signed enough data */ |