summaryrefslogtreecommitdiff
path: root/firmware/lib/vboot_common.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/lib/vboot_common.c')
-rw-r--r--firmware/lib/vboot_common.c866
1 files changed, 437 insertions, 429 deletions
diff --git a/firmware/lib/vboot_common.c b/firmware/lib/vboot_common.c
index bf79b81f..50a4cff8 100644
--- a/firmware/lib/vboot_common.c
+++ b/firmware/lib/vboot_common.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*
@@ -6,488 +6,496 @@
* (Firmware portion)
*/
-
#include "vboot_api.h"
#include "vboot_common.h"
#include "utility.h"
-
-char* kVbootErrors[VBOOT_ERROR_MAX] = {
- "Success.",
- "Key block invalid.",
- "Key block signature failed.",
- "Key block hash failed.",
- "Public key invalid.",
- "Preamble invalid.",
- "Preamble signature check failed.",
- "Shared data invalid."
+const char *kVbootErrors[VBOOT_ERROR_MAX] = {
+ "Success.",
+ "Key block invalid.",
+ "Key block signature failed.",
+ "Key block hash failed.",
+ "Public key invalid.",
+ "Preamble invalid.",
+ "Preamble signature check failed.",
+ "Shared data invalid."
};
-
-uint64_t OffsetOf(const void *base, const void *ptr) {
- return (uint64_t)(size_t)ptr - (uint64_t)(size_t)base;
+uint64_t OffsetOf(const void *base, const void *ptr)
+{
+ return (uint64_t)(size_t)ptr - (uint64_t)(size_t)base;
}
-
/* Helper functions to get data pointed to by a public key or signature. */
-uint8_t* GetPublicKeyData(VbPublicKey* key) {
- return (uint8_t*)key + key->key_offset;
+
+uint8_t *GetPublicKeyData(VbPublicKey *key)
+{
+ return (uint8_t *)key + key->key_offset;
}
-const uint8_t* GetPublicKeyDataC(const VbPublicKey* key) {
- return (const uint8_t*)key + key->key_offset;
+const uint8_t *GetPublicKeyDataC(const VbPublicKey *key)
+{
+ return (const uint8_t *)key + key->key_offset;
}
-uint8_t* GetSignatureData(VbSignature* sig) {
- return (uint8_t*)sig + sig->sig_offset;
+uint8_t *GetSignatureData(VbSignature *sig)
+{
+ return (uint8_t *)sig + sig->sig_offset;
}
-const uint8_t* GetSignatureDataC(const VbSignature* sig) {
- return (const uint8_t*)sig + sig->sig_offset;
+const uint8_t *GetSignatureDataC(const VbSignature *sig)
+{
+ return (const uint8_t *)sig + sig->sig_offset;
}
+/*
+ * Helper functions to verify the data pointed to by a subfield is inside
+ * the parent data. Returns 0 if inside, 1 if error.
+ */
-/* Helper functions to verify the data pointed to by a subfield is inside
- * the parent data. Returns 0 if inside, 1 if error. */
-int VerifyMemberInside(const void* parent, uint64_t parent_size,
- const void* member, uint64_t member_size,
+int VerifyMemberInside(const void *parent, uint64_t parent_size,
+ const void *member, uint64_t member_size,
uint64_t member_data_offset,
- uint64_t member_data_size) {
- uint64_t end = OffsetOf(parent, member);
-
- 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;
-
- return 0;
+ uint64_t member_data_size)
+{
+ uint64_t end = OffsetOf(parent, member);
+
+ 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;
+
+ return 0;
}
-
-int VerifyPublicKeyInside(const void* parent, uint64_t parent_size,
- const VbPublicKey* key) {
- return VerifyMemberInside(parent, parent_size,
- key, sizeof(VbPublicKey),
- key->key_offset, key->key_size);
+int VerifyPublicKeyInside(const void *parent, uint64_t parent_size,
+ const VbPublicKey *key)
+{
+ return VerifyMemberInside(parent, parent_size,
+ key, sizeof(VbPublicKey),
+ key->key_offset, key->key_size);
}
-
-int VerifySignatureInside(const void* parent, uint64_t parent_size,
- const VbSignature* sig) {
- return VerifyMemberInside(parent, parent_size,
- sig, sizeof(VbSignature),
- sig->sig_offset, sig->sig_size);
+int VerifySignatureInside(const void *parent, uint64_t parent_size,
+ const VbSignature *sig)
+{
+ return VerifyMemberInside(parent, parent_size,
+ sig, sizeof(VbSignature),
+ sig->sig_offset, sig->sig_size);
}
-
-void PublicKeyInit(VbPublicKey* key, uint8_t* key_data, uint64_t key_size) {
- key->key_offset = OffsetOf(key, key_data);
- key->key_size = key_size;
- key->algorithm = kNumAlgorithms; /* Key not present yet */
- key->key_version = 0;
+void PublicKeyInit(VbPublicKey *key, uint8_t *key_data, uint64_t key_size)
+{
+ key->key_offset = OffsetOf(key, key_data);
+ key->key_size = key_size;
+ key->algorithm = kNumAlgorithms; /* Key not present yet */
+ key->key_version = 0;
}
+int PublicKeyCopy(VbPublicKey *dest, const VbPublicKey *src)
+{
+ if (dest->key_size < src->key_size)
+ return 1;
-int PublicKeyCopy(VbPublicKey* dest, const VbPublicKey* src) {
- if (dest->key_size < src->key_size)
- return 1;
-
- dest->key_size = src->key_size;
- dest->algorithm = src->algorithm;
- dest->key_version = src->key_version;
- Memcpy(GetPublicKeyData(dest), GetPublicKeyDataC(src), src->key_size);
- return 0;
+ dest->key_size = src->key_size;
+ dest->algorithm = src->algorithm;
+ dest->key_version = src->key_version;
+ Memcpy(GetPublicKeyData(dest), GetPublicKeyDataC(src), src->key_size);
+ return 0;
}
-
-RSAPublicKey* PublicKeyToRSA(const VbPublicKey* key) {
- RSAPublicKey *rsa;
- uint64_t key_size;
-
- if (kNumAlgorithms <= key->algorithm) {
- VBDEBUG(("Invalid algorithm.\n"));
- return NULL;
- }
- if (!RSAProcessedKeySize(key->algorithm, &key_size) ||
- key_size != key->key_size) {
- VBDEBUG(("Wrong key size for algorithm\n"));
- return NULL;
- }
-
- rsa = RSAPublicKeyFromBuf(GetPublicKeyDataC(key), key->key_size);
- if (!rsa)
- return NULL;
-
- rsa->algorithm = (unsigned int)key->algorithm;
- return rsa;
+RSAPublicKey *PublicKeyToRSA(const VbPublicKey *key)
+{
+ RSAPublicKey *rsa;
+ uint64_t key_size;
+
+ if (kNumAlgorithms <= key->algorithm) {
+ VBDEBUG(("Invalid algorithm.\n"));
+ return NULL;
+ }
+ if (!RSAProcessedKeySize(key->algorithm, &key_size) ||
+ key_size != key->key_size) {
+ VBDEBUG(("Wrong key size for algorithm\n"));
+ return NULL;
+ }
+
+ rsa = RSAPublicKeyFromBuf(GetPublicKeyDataC(key), key->key_size);
+ if (!rsa)
+ return NULL;
+
+ rsa->algorithm = (unsigned int)key->algorithm;
+ return rsa;
}
-
-int VerifyData(const uint8_t* data, uint64_t size, const VbSignature *sig,
- const RSAPublicKey* key) {
-
- if (sig->sig_size != siglen_map[key->algorithm]) {
- VBDEBUG(("Wrong signature size for algorithm.\n"));
- return 1;
- }
- if (sig->data_size > size) {
- VBDEBUG(("Data buffer smaller than length of signed data.\n"));
- return 1;
- }
-
- if (!RSAVerifyBinary_f(NULL, key, data, sig->data_size,
- GetSignatureDataC(sig), key->algorithm))
- return 1;
-
- return 0;
+int VerifyData(const uint8_t *data, uint64_t size, const VbSignature *sig,
+ const RSAPublicKey *key)
+{
+ if (sig->sig_size != siglen_map[key->algorithm]) {
+ VBDEBUG(("Wrong signature size for algorithm.\n"));
+ return 1;
+ }
+ if (sig->data_size > size) {
+ VBDEBUG(("Data buffer smaller than length of signed data.\n"));
+ return 1;
+ }
+
+ if (!RSAVerifyBinary_f(NULL, key, data, sig->data_size,
+ GetSignatureDataC(sig), key->algorithm))
+ return 1;
+
+ return 0;
}
+int VerifyDigest(const uint8_t *digest, const VbSignature *sig,
+ const RSAPublicKey *key)
+{
+ if (sig->sig_size != siglen_map[key->algorithm]) {
+ VBDEBUG(("Wrong signature size for algorithm.\n"));
+ return 1;
+ }
-int VerifyDigest(const uint8_t* digest, const VbSignature *sig,
- const RSAPublicKey* key) {
-
- if (sig->sig_size != siglen_map[key->algorithm]) {
- VBDEBUG(("Wrong signature size for algorithm.\n"));
- return 1;
- }
-
- if (!RSAVerifyBinaryWithDigest_f(NULL, key, digest,
- GetSignatureDataC(sig), key->algorithm))
- return 1;
+ if (!RSAVerifyBinaryWithDigest_f(NULL, key, digest,
+ GetSignatureDataC(sig),
+ key->algorithm))
+ return 1;
- return 0;
+ return 0;
}
-
-int KeyBlockVerify(const VbKeyBlockHeader* block, uint64_t size,
- const VbPublicKey *key, int hash_only) {
-
- const VbSignature* sig;
-
- /* Sanity checks before attempting signature of data */
- if(size < sizeof(VbKeyBlockHeader)) {
- VBDEBUG(("Not enough space for key block header.\n"));
- return VBOOT_KEY_BLOCK_INVALID;
- }
- if (SafeMemcmp(block->magic, KEY_BLOCK_MAGIC, KEY_BLOCK_MAGIC_SIZE)) {
- VBDEBUG(("Not a valid verified boot key block.\n"));
- return VBOOT_KEY_BLOCK_INVALID;
- }
- if (block->header_version_major != KEY_BLOCK_HEADER_VERSION_MAJOR) {
- VBDEBUG(("Incompatible key block header version.\n"));
- return VBOOT_KEY_BLOCK_INVALID;
- }
- if (size < block->key_block_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 the hash_only parameter. Note that
- * 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 (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;
- }
-
- /* Make sure advertised signature data sizes are sane. */
- if (block->key_block_size < sig->data_size) {
- VBDEBUG(("Signature calculated past end of the 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);
- VbExFree(header_checksum);
- if (rv) {
- VBDEBUG(("Invalid key block hash.\n"));
- return VBOOT_KEY_BLOCK_HASH;
- }
- } else {
- /* Check signature */
- RSAPublicKey* rsa;
- int rv;
-
- sig = &block->key_block_signature;
-
- if (VerifySignatureInside(block, block->key_block_size, sig)) {
- VBDEBUG(("Key block signature off end of block\n"));
- return VBOOT_KEY_BLOCK_INVALID;
- }
-
- rsa = PublicKeyToRSA(key);
- if (!rsa) {
- VBDEBUG(("Invalid public key\n"));
- return VBOOT_PUBLIC_KEY_INVALID;
- }
-
- /* Make sure advertised signature data sizes are sane. */
- if (block->key_block_size < sig->data_size) {
- VBDEBUG(("Signature calculated past end of the block\n"));
- RSAPublicKeyFree(rsa);
- return VBOOT_KEY_BLOCK_INVALID;
- }
-
- VBDEBUG(("Checking key block signature...\n"));
- rv = VerifyData((const uint8_t*)block, size, sig, rsa);
- RSAPublicKeyFree(rsa);
- if (rv) {
- VBDEBUG(("Invalid key block signature.\n"));
- return VBOOT_KEY_BLOCK_SIGNATURE;
- }
- }
-
- /* Verify we signed enough data */
- if (sig->data_size < sizeof(VbKeyBlockHeader)) {
- VBDEBUG(("Didn't sign enough data\n"));
- return VBOOT_KEY_BLOCK_INVALID;
- }
-
- /* Verify data key is inside the block and inside signed data */
- if (VerifyPublicKeyInside(block, block->key_block_size, &block->data_key)) {
- VBDEBUG(("Data key off end of key block\n"));
- return VBOOT_KEY_BLOCK_INVALID;
- }
- if (VerifyPublicKeyInside(block, sig->data_size, &block->data_key)) {
- VBDEBUG(("Data key off end of signed data\n"));
- return VBOOT_KEY_BLOCK_INVALID;
- }
-
- /* Success */
- return VBOOT_SUCCESS;
+int KeyBlockVerify(const VbKeyBlockHeader *block, uint64_t size,
+ const VbPublicKey *key, int hash_only)
+{
+ const VbSignature *sig;
+
+ /* Sanity checks before attempting signature of data */
+ if(size < sizeof(VbKeyBlockHeader)) {
+ VBDEBUG(("Not enough space for key block header.\n"));
+ return VBOOT_KEY_BLOCK_INVALID;
+ }
+ if (SafeMemcmp(block->magic, KEY_BLOCK_MAGIC, KEY_BLOCK_MAGIC_SIZE)) {
+ VBDEBUG(("Not a valid verified boot key block.\n"));
+ return VBOOT_KEY_BLOCK_INVALID;
+ }
+ if (block->header_version_major != KEY_BLOCK_HEADER_VERSION_MAJOR) {
+ VBDEBUG(("Incompatible key block header version.\n"));
+ return VBOOT_KEY_BLOCK_INVALID;
+ }
+ if (size < block->key_block_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 the hash_only parameter. Note
+ * that 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 (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;
+ }
+
+ /* Make sure advertised signature data sizes are sane. */
+ if (block->key_block_size < sig->data_size) {
+ VBDEBUG(("Signature calculated past end of 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);
+ VbExFree(header_checksum);
+ if (rv) {
+ VBDEBUG(("Invalid key block hash.\n"));
+ return VBOOT_KEY_BLOCK_HASH;
+ }
+ } else {
+ /* Check signature */
+ RSAPublicKey *rsa;
+ int rv;
+
+ sig = &block->key_block_signature;
+
+ if (VerifySignatureInside(block, block->key_block_size, sig)) {
+ VBDEBUG(("Key block signature off end of block\n"));
+ return VBOOT_KEY_BLOCK_INVALID;
+ }
+
+ rsa = PublicKeyToRSA(key);
+ if (!rsa) {
+ VBDEBUG(("Invalid public key\n"));
+ return VBOOT_PUBLIC_KEY_INVALID;
+ }
+
+ /* Make sure advertised signature data sizes are sane. */
+ if (block->key_block_size < sig->data_size) {
+ VBDEBUG(("Signature calculated past end of block\n"));
+ RSAPublicKeyFree(rsa);
+ return VBOOT_KEY_BLOCK_INVALID;
+ }
+
+ VBDEBUG(("Checking key block signature...\n"));
+ rv = VerifyData((const uint8_t *)block, size, sig, rsa);
+ RSAPublicKeyFree(rsa);
+ if (rv) {
+ VBDEBUG(("Invalid key block signature.\n"));
+ return VBOOT_KEY_BLOCK_SIGNATURE;
+ }
+ }
+
+ /* Verify we signed enough data */
+ if (sig->data_size < sizeof(VbKeyBlockHeader)) {
+ VBDEBUG(("Didn't sign enough data\n"));
+ return VBOOT_KEY_BLOCK_INVALID;
+ }
+
+ /* Verify data key is inside the block and inside signed data */
+ if (VerifyPublicKeyInside(block, block->key_block_size,
+ &block->data_key)) {
+ VBDEBUG(("Data key off end of key block\n"));
+ return VBOOT_KEY_BLOCK_INVALID;
+ }
+ if (VerifyPublicKeyInside(block, sig->data_size, &block->data_key)) {
+ VBDEBUG(("Data key off end of signed data\n"));
+ return VBOOT_KEY_BLOCK_INVALID;
+ }
+
+ /* Success */
+ return VBOOT_SUCCESS;
}
-int VerifyFirmwarePreamble(const VbFirmwarePreambleHeader* preamble,
- uint64_t size, const RSAPublicKey* key) {
-
- const VbSignature* sig = &preamble->preamble_signature;
-
- /* Sanity checks before attempting signature of data */
- if(size < EXPECTED_VBFIRMWAREPREAMBLEHEADER2_0_SIZE) {
- VBDEBUG(("Not enough data for preamble header 2.0.\n"));
- return VBOOT_PREAMBLE_INVALID;
- }
- if (preamble->header_version_major !=
- FIRMWARE_PREAMBLE_HEADER_VERSION_MAJOR) {
- VBDEBUG(("Incompatible firmware preamble header version.\n"));
- return VBOOT_PREAMBLE_INVALID;
- }
- if (size < preamble->preamble_size) {
- VBDEBUG(("Not enough data for preamble.\n"));
- return VBOOT_PREAMBLE_INVALID;
- }
-
- /* Check signature */
- if (VerifySignatureInside(preamble, preamble->preamble_size, sig)) {
- VBDEBUG(("Preamble signature off end of preamble\n"));
- return VBOOT_PREAMBLE_INVALID;
- }
-
- /* Make sure advertised signature data sizes are sane. */
- if (preamble->preamble_size < sig->data_size) {
- VBDEBUG(("Signature calculated past end of the block\n"));
- return VBOOT_PREAMBLE_INVALID;
- }
-
- if (VerifyData((const uint8_t*)preamble, size, sig, key)) {
- VBDEBUG(("Preamble signature validation failed\n"));
- return VBOOT_PREAMBLE_SIGNATURE;
- }
-
- /* Verify we signed enough data */
- if (sig->data_size < sizeof(VbFirmwarePreambleHeader)) {
- VBDEBUG(("Didn't sign enough data\n"));
- return VBOOT_PREAMBLE_INVALID;
- }
-
- /* Verify body signature is inside the signed data */
- if (VerifySignatureInside(preamble, sig->data_size,
- &preamble->body_signature)) {
- VBDEBUG(("Firmware body signature off end of preamble\n"));
- return VBOOT_PREAMBLE_INVALID;
- }
-
- /* Verify kernel subkey is inside the signed data */
- if (VerifyPublicKeyInside(preamble, sig->data_size,
- &preamble->kernel_subkey)) {
- VBDEBUG(("Kernel subkey off end of preamble\n"));
- return VBOOT_PREAMBLE_INVALID;
- }
-
- /* If the preamble header version is at least 2.1, verify we have
- * space for the added fields from 2.1. */
- if (preamble->header_version_minor >= 1) {
- if(size < EXPECTED_VBFIRMWAREPREAMBLEHEADER2_1_SIZE) {
- VBDEBUG(("Not enough data for preamble header 2.1.\n"));
- return VBOOT_PREAMBLE_INVALID;
- }
- }
-
- /* Success */
- return VBOOT_SUCCESS;
+int VerifyFirmwarePreamble(const VbFirmwarePreambleHeader *preamble,
+ uint64_t size, const RSAPublicKey *key)
+{
+ const VbSignature *sig = &preamble->preamble_signature;
+
+ /* Sanity checks before attempting signature of data */
+ if(size < EXPECTED_VBFIRMWAREPREAMBLEHEADER2_0_SIZE) {
+ VBDEBUG(("Not enough data for preamble header 2.0.\n"));
+ return VBOOT_PREAMBLE_INVALID;
+ }
+ if (preamble->header_version_major !=
+ FIRMWARE_PREAMBLE_HEADER_VERSION_MAJOR) {
+ VBDEBUG(("Incompatible firmware preamble header version.\n"));
+ return VBOOT_PREAMBLE_INVALID;
+ }
+ if (size < preamble->preamble_size) {
+ VBDEBUG(("Not enough data for preamble.\n"));
+ return VBOOT_PREAMBLE_INVALID;
+ }
+
+ /* Check signature */
+ if (VerifySignatureInside(preamble, preamble->preamble_size, sig)) {
+ VBDEBUG(("Preamble signature off end of preamble\n"));
+ return VBOOT_PREAMBLE_INVALID;
+ }
+
+ /* Make sure advertised signature data sizes are sane. */
+ if (preamble->preamble_size < sig->data_size) {
+ VBDEBUG(("Signature calculated past end of the block\n"));
+ return VBOOT_PREAMBLE_INVALID;
+ }
+
+ if (VerifyData((const uint8_t *)preamble, size, sig, key)) {
+ VBDEBUG(("Preamble signature validation failed\n"));
+ return VBOOT_PREAMBLE_SIGNATURE;
+ }
+
+ /* Verify we signed enough data */
+ if (sig->data_size < sizeof(VbFirmwarePreambleHeader)) {
+ VBDEBUG(("Didn't sign enough data\n"));
+ return VBOOT_PREAMBLE_INVALID;
+ }
+
+ /* Verify body signature is inside the signed data */
+ if (VerifySignatureInside(preamble, sig->data_size,
+ &preamble->body_signature)) {
+ VBDEBUG(("Firmware body signature off end of preamble\n"));
+ return VBOOT_PREAMBLE_INVALID;
+ }
+
+ /* Verify kernel subkey is inside the signed data */
+ if (VerifyPublicKeyInside(preamble, sig->data_size,
+ &preamble->kernel_subkey)) {
+ VBDEBUG(("Kernel subkey off end of preamble\n"));
+ return VBOOT_PREAMBLE_INVALID;
+ }
+
+ /*
+ * If the preamble header version is at least 2.1, verify we have space
+ * for the added fields from 2.1.
+ */
+ if (preamble->header_version_minor >= 1) {
+ if(size < EXPECTED_VBFIRMWAREPREAMBLEHEADER2_1_SIZE) {
+ VBDEBUG(("Not enough data for preamble header 2.1.\n"));
+ return VBOOT_PREAMBLE_INVALID;
+ }
+ }
+
+ /* Success */
+ return VBOOT_SUCCESS;
}
-
-uint32_t VbGetFirmwarePreambleFlags(const VbFirmwarePreambleHeader* preamble) {
- if (preamble->header_version_minor < 1) {
- /* Old structure; return default flags. (Note that we don't need
- * to check header_version_major; if that's not 2 then
- * VerifyFirmwarePreamble() would have already failed. */
- return 0;
- }
-
- return preamble->flags;
+uint32_t VbGetFirmwarePreambleFlags(const VbFirmwarePreambleHeader *preamble)
+{
+ if (preamble->header_version_minor < 1) {
+ /*
+ * Old structure; return default flags. (Note that we don't
+ * need to check header_version_major; if that's not 2 then
+ * VerifyFirmwarePreamble() would have already failed.
+ */
+ return 0;
+ }
+
+ return preamble->flags;
}
-
-int VerifyKernelPreamble(const VbKernelPreambleHeader* preamble,
- uint64_t size, const RSAPublicKey* key) {
-
- const VbSignature* sig = &preamble->preamble_signature;
-
- /* Sanity checks before attempting signature of data */
- if(size < sizeof(VbKernelPreambleHeader)) {
- VBDEBUG(("Not enough data for preamble header.\n"));
- return VBOOT_PREAMBLE_INVALID;
- }
- if (preamble->header_version_major != KERNEL_PREAMBLE_HEADER_VERSION_MAJOR) {
- VBDEBUG(("Incompatible kernel preamble header version.\n"));
- return VBOOT_PREAMBLE_INVALID;
- }
- if (size < preamble->preamble_size) {
- VBDEBUG(("Not enough data for preamble.\n"));
- return VBOOT_PREAMBLE_INVALID;
- }
-
- /* Check signature */
- if (VerifySignatureInside(preamble, preamble->preamble_size, sig)) {
- VBDEBUG(("Preamble signature off end of preamble\n"));
- return VBOOT_PREAMBLE_INVALID;
- }
- if (VerifyData((const uint8_t*)preamble, size, sig, key)) {
- VBDEBUG(("Preamble signature validation failed\n"));
- return VBOOT_PREAMBLE_SIGNATURE;
- }
-
- /* Verify we signed enough data */
- if (sig->data_size < sizeof(VbKernelPreambleHeader)) {
- VBDEBUG(("Didn't sign enough data\n"));
- return VBOOT_PREAMBLE_INVALID;
- }
-
- /* Verify body signature is inside the signed data */
- if (VerifySignatureInside(preamble, sig->data_size,
- &preamble->body_signature)) {
- VBDEBUG(("Kernel body signature off end of preamble\n"));
- return VBOOT_PREAMBLE_INVALID;
- }
-
- /* Success */
- return VBOOT_SUCCESS;
+int VerifyKernelPreamble(const VbKernelPreambleHeader *preamble,
+ uint64_t size, const RSAPublicKey *key)
+{
+ const VbSignature *sig = &preamble->preamble_signature;
+
+ /* Sanity checks before attempting signature of data */
+ if(size < sizeof(VbKernelPreambleHeader)) {
+ VBDEBUG(("Not enough data for preamble header.\n"));
+ return VBOOT_PREAMBLE_INVALID;
+ }
+ if (preamble->header_version_major !=
+ KERNEL_PREAMBLE_HEADER_VERSION_MAJOR) {
+ VBDEBUG(("Incompatible kernel preamble header version.\n"));
+ return VBOOT_PREAMBLE_INVALID;
+ }
+ if (size < preamble->preamble_size) {
+ VBDEBUG(("Not enough data for preamble.\n"));
+ return VBOOT_PREAMBLE_INVALID;
+ }
+
+ /* Check signature */
+ if (VerifySignatureInside(preamble, preamble->preamble_size, sig)) {
+ VBDEBUG(("Preamble signature off end of preamble\n"));
+ return VBOOT_PREAMBLE_INVALID;
+ }
+ if (VerifyData((const uint8_t *)preamble, size, sig, key)) {
+ VBDEBUG(("Preamble signature validation failed\n"));
+ return VBOOT_PREAMBLE_SIGNATURE;
+ }
+
+ /* Verify we signed enough data */
+ if (sig->data_size < sizeof(VbKernelPreambleHeader)) {
+ VBDEBUG(("Didn't sign enough data\n"));
+ return VBOOT_PREAMBLE_INVALID;
+ }
+
+ /* Verify body signature is inside the signed data */
+ if (VerifySignatureInside(preamble, sig->data_size,
+ &preamble->body_signature)) {
+ VBDEBUG(("Kernel body signature off end of preamble\n"));
+ return VBOOT_PREAMBLE_INVALID;
+ }
+
+ /* Success */
+ return VBOOT_SUCCESS;
}
-
-int VbSharedDataInit(VbSharedDataHeader* header, uint64_t size) {
-
- VBDEBUG(("VbSharedDataInit, %d bytes, header %d bytes\n", (int)size,
- sizeof(VbSharedDataHeader)));
-
- if (size < sizeof(VbSharedDataHeader)) {
- VBDEBUG(("Not enough data for header.\n"));
- return VBOOT_SHARED_DATA_INVALID;
- }
- if (size < VB_SHARED_DATA_MIN_SIZE) {
- VBDEBUG(("Shared data buffer too small.\n"));
- return VBOOT_SHARED_DATA_INVALID;
- }
-
- if (!header)
- return VBOOT_SHARED_DATA_INVALID;
-
- /* Zero the header */
- Memset(header, 0, sizeof(VbSharedDataHeader));
-
- /* Initialize fields */
- header->magic = VB_SHARED_DATA_MAGIC;
- header->struct_version = VB_SHARED_DATA_VERSION;
- header->struct_size = sizeof(VbSharedDataHeader);
- header->data_size = size;
- header->data_used = sizeof(VbSharedDataHeader);
- header->firmware_index = 0xFF;
-
- /* Success */
- return VBOOT_SUCCESS;
+int VbSharedDataInit(VbSharedDataHeader *header, uint64_t size)
+{
+ VBDEBUG(("VbSharedDataInit, %d bytes, header %d bytes\n", (int)size,
+ sizeof(VbSharedDataHeader)));
+
+ if (size < sizeof(VbSharedDataHeader)) {
+ VBDEBUG(("Not enough data for header.\n"));
+ return VBOOT_SHARED_DATA_INVALID;
+ }
+ if (size < VB_SHARED_DATA_MIN_SIZE) {
+ VBDEBUG(("Shared data buffer too small.\n"));
+ return VBOOT_SHARED_DATA_INVALID;
+ }
+
+ if (!header)
+ return VBOOT_SHARED_DATA_INVALID;
+
+ /* Zero the header */
+ Memset(header, 0, sizeof(VbSharedDataHeader));
+
+ /* Initialize fields */
+ header->magic = VB_SHARED_DATA_MAGIC;
+ header->struct_version = VB_SHARED_DATA_VERSION;
+ header->struct_size = sizeof(VbSharedDataHeader);
+ header->data_size = size;
+ header->data_used = sizeof(VbSharedDataHeader);
+ header->firmware_index = 0xFF;
+
+ /* Success */
+ return VBOOT_SUCCESS;
}
+uint64_t VbSharedDataReserve(VbSharedDataHeader *header, uint64_t size)
+{
+ uint64_t offs = header->data_used;
-uint64_t VbSharedDataReserve(VbSharedDataHeader* header, uint64_t size) {
- uint64_t offs = header->data_used;
-
- VBDEBUG(("VbSharedDataReserve %d bytes at %d\n", (int)size, (int)offs));
+ VBDEBUG(("VbSharedDataReserve %d bytes at %d\n", (int)size, (int)offs));
- if (!header || size > header->data_size - header->data_used) {
- VBDEBUG(("VbSharedData buffer out of space.\n"));
- return 0; /* Not initialized, or not enough space left. */
- }
- header->data_used += size;
- return offs;
+ if (!header || size > header->data_size - header->data_used) {
+ VBDEBUG(("VbSharedData buffer out of space.\n"));
+ return 0; /* Not initialized, or not enough space left. */
+ }
+ header->data_used += size;
+ return offs;
}
+int VbSharedDataSetKernelKey(VbSharedDataHeader *header, const VbPublicKey *src)
+{
+ VbPublicKey *kdest = &header->kernel_subkey;
-int VbSharedDataSetKernelKey(VbSharedDataHeader* header,
- const VbPublicKey* src) {
-
- VbPublicKey *kdest = &header->kernel_subkey;
-
- if (!header)
- return VBOOT_SHARED_DATA_INVALID;
+ if (!header)
+ return VBOOT_SHARED_DATA_INVALID;
- /* Attempt to allocate space for the key, if it hasn't been allocated yet */
- if (!header->kernel_subkey_data_offset) {
- header->kernel_subkey_data_offset = VbSharedDataReserve(header,
- src->key_size);
- if (!header->kernel_subkey_data_offset)
- return VBOOT_SHARED_DATA_INVALID;
- header->kernel_subkey_data_size = src->key_size;
- }
+ /* Attempt to allocate space for key, if it hasn't been allocated yet */
+ if (!header->kernel_subkey_data_offset) {
+ header->kernel_subkey_data_offset =
+ VbSharedDataReserve(header, src->key_size);
+ if (!header->kernel_subkey_data_offset)
+ return VBOOT_SHARED_DATA_INVALID;
+ header->kernel_subkey_data_size = src->key_size;
+ }
- /* Copy the kernel sign key blob into the destination buffer */
- PublicKeyInit(kdest, (uint8_t*)header + header->kernel_subkey_data_offset,
- header->kernel_subkey_data_size);
+ /* Copy the kernel sign key blob into the destination buffer */
+ PublicKeyInit(kdest,
+ (uint8_t *)header + header->kernel_subkey_data_offset,
+ header->kernel_subkey_data_size);
- return PublicKeyCopy(kdest, src);
+ return PublicKeyCopy(kdest, src);
}