From 68f54d44756e8f0a777808b710a4ccc5d2ce353d Mon Sep 17 00:00:00 2001 From: Randall Spangler Date: Fri, 25 Jan 2013 15:05:08 -0800 Subject: Reformat files to kernel style No code changes, just reformatting. BUG=none BRANCH=none TEST=make runtests Change-Id: I30c7f74217c10ac7cc618aee30a22febe1e41f5c Signed-off-by: Randall Spangler Reviewed-on: https://gerrit.chromium.org/gerrit/42053 Reviewed-by: Bill Richardson --- firmware/lib/include/bmpblk_font.h | 24 +- firmware/lib/include/crc8.h | 4 +- firmware/lib/include/rollback_index.h | 153 +++-- firmware/lib/include/stateful_util.h | 50 +- firmware/lib/include/tpm_bootmode.h | 13 +- firmware/lib/include/vboot_audio.h | 20 +- firmware/lib/include/vboot_audio_private.h | 43 +- firmware/lib/include/vboot_common.h | 205 ++++--- firmware/lib/include/vboot_display.h | 8 +- firmware/lib/include/vboot_kernel.h | 21 +- firmware/lib/vboot_common.c | 866 +++++++++++++++-------------- tests/vboot_common3_tests.c | 502 ++++++++--------- 12 files changed, 1009 insertions(+), 900 deletions(-) diff --git a/firmware/lib/include/bmpblk_font.h b/firmware/lib/include/bmpblk_font.h index 1ffaefda..b79274cc 100644 --- a/firmware/lib/include/bmpblk_font.h +++ b/firmware/lib/include/bmpblk_font.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved. +/* Copyright (c) 2013 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. * @@ -45,20 +45,22 @@ __pragma(pack(push, 1)) /* Support packing for MSVC. */ #define FONT_SIGNATURE_SIZE 4 typedef struct FontArrayHeader { - uint8_t signature[FONT_SIGNATURE_SIZE]; - uint32_t num_entries; /* Number of chars encoded here. */ + uint8_t signature[FONT_SIGNATURE_SIZE]; + uint32_t num_entries; /* Number of chars encoded here. */ } __attribute__((packed)) FontArrayHeader; typedef struct FontArrayEntryHeader { - uint32_t ascii; /* What to show. Could even be UTF? */ - ImageInfo info; /* Describes the bitmap. */ - /* The image to use follows immediately, NOT compressed. It's uncompressed - * because each glyph is only a few hundred bytes, but they have much in - * common (colormaps, for example). When we add the whole font blob to the - * bmpblk, it will be compressed as a single item there. - */ -} __attribute__((packed)) FontArrayEntryHeader; + uint32_t ascii; /* What to show. Could even be UTF? */ + ImageInfo info; /* Describes the bitmap. */ + /* + * The image to use follows immediately, NOT compressed. It's + * uncompressed because each glyph is only a few hundred bytes, but + * they have much in common (colormaps, for example). When we add the + * whole font blob to the bmpblk, it will be compressed as a single + * item there. + */ +} __attribute__((packed)) FontArrayEntryHeader; __pragma(pack(pop)) /* Support packing for MSVC. */ diff --git a/firmware/lib/include/crc8.h b/firmware/lib/include/crc8.h index 95bc9862..14341440 100644 --- a/firmware/lib/include/crc8.h +++ b/firmware/lib/include/crc8.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved. +/* Copyright (c) 2013 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. * @@ -8,6 +8,6 @@ #define VBOOT_REFERENCE_CRC8_H_ #include "sysincludes.h" -uint8_t Crc8(const void* data, int len); +uint8_t Crc8(const void *data, int len); #endif /* VBOOT_REFERENCE_CRC8_H_ */ diff --git a/firmware/lib/include/rollback_index.h b/firmware/lib/include/rollback_index.h index 51e6ec10..c8b0147b 100644 --- a/firmware/lib/include/rollback_index.h +++ b/firmware/lib/include/rollback_index.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved. +/* Copyright (c) 2013 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. * @@ -23,106 +23,155 @@ __pragma(pack(push, 1)) /* Support packing for MSVC. */ /* Kernel space - KERNEL_NV_INDEX, locked with physical presence. */ #define ROLLBACK_SPACE_KERNEL_VERSION 2 #define ROLLBACK_SPACE_KERNEL_UID 0x4752574C /* 'GRWL' */ + typedef struct RollbackSpaceKernel { - uint8_t struct_version; /* Struct version, for backwards - * compatibility */ - uint32_t uid; /* Unique ID to detect space redefinition */ - uint32_t kernel_versions; /* Kernel versions */ - uint8_t reserved[3]; /* Reserved for future expansion */ - uint8_t crc8; /* Checksum (v2 and later only) */ + /* Struct version, for backwards compatibility */ + uint8_t struct_version; + /* Unique ID to detect space redefinition */ + uint32_t uid; + /* Kernel versions */ + uint32_t kernel_versions; + /* Reserved for future expansion */ + uint8_t reserved[3]; + /* Checksum (v2 and later only) */ + uint8_t crc8; } __attribute__((packed)) RollbackSpaceKernel; - /* Flags for firmware space */ -/* Last boot was developer mode. TPM ownership is cleared when - * transitioning to/from developer mode. */ +/* + * Last boot was developer mode. TPM ownership is cleared when transitioning + * to/from developer mode. + */ #define FLAG_LAST_BOOT_DEVELOPER 0x01 -/* Some systems may not have a dedicated dev-mode switch, but enter and leave - * dev-mode through some recovery-mode magic keypresses. For those systems, - * the dev-mode "switch" state is in this bit (0=normal, 1=dev). To make it - * work, a new flag is passed to VbInit(), indicating that the system lacks a - * physical dev-mode switch. If a physical switch is present, this bit is - * ignored. */ +/* + * Some systems may not have a dedicated dev-mode switch, but enter and leave + * dev-mode through some recovery-mode magic keypresses. For those systems, the + * dev-mode "switch" state is in this bit (0=normal, 1=dev). To make it work, a + * new flag is passed to VbInit(), indicating that the system lacks a physical + * dev-mode switch. If a physical switch is present, this bit is ignored. + */ #define FLAG_VIRTUAL_DEV_MODE_ON 0x02 -#define ROLLBACK_SPACE_FIRMWARE_VERSION 2 /* Firmware space - FIRMWARE_NV_INDEX, locked with global lock. */ +#define ROLLBACK_SPACE_FIRMWARE_VERSION 2 + typedef struct RollbackSpaceFirmware { - uint8_t struct_version; /* Struct version, for backwards compatibility */ - uint8_t flags; /* Flags (see FLAG_* above) */ - uint32_t fw_versions; /* Firmware versions */ - uint8_t reserved[3]; /* Reserved for future expansion */ - uint8_t crc8; /* Checksum (v2 and later only) */ + /* Struct version, for backwards compatibility */ + uint8_t struct_version; + /* Flags (see FLAG_* above) */ + uint8_t flags; + /* Firmware versions */ + uint32_t fw_versions; + /* Reserved for future expansion */ + uint8_t reserved[3]; + /* Checksum (v2 and later only) */ + uint8_t crc8; } __attribute__((packed)) RollbackSpaceFirmware; __pragma(pack(pop)) /* Support packing for MSVC. */ - /* All functions return TPM_SUCCESS (zero) if successful, non-zero if error */ -/* These functions are called from VbInit(). They cannot use global - * variables. */ +/* + * These functions are called from VbInit(). They cannot use global + * variables. + */ + uint32_t RollbackS3Resume(void); -/* These functions are callable from VbSelectFirmware(). They cannot use - * global variables. */ +/* + * These functions are callable from VbSelectFirmware(). They cannot use + * global variables. + */ -/* This must be called. */ +/** + * This must be called. + */ uint32_t RollbackFirmwareSetup(int recovery_mode, int is_hw_dev, int disable_dev_request, int clear_tpm_owner_request, /* two outputs on success */ int *is_virt_dev, uint32_t *tpm_version); -/* Write may be called if the versions change */ +/** + * Write may be called if the versions change. + */ uint32_t RollbackFirmwareWrite(uint32_t version); -/* Lock must be called */ +/** + * Lock must be called. + */ uint32_t RollbackFirmwareLock(void); -/* These functions are callable from VbSelectAndLoadKernel(). They - * may use global variables. */ +/* + * These functions are callable from VbSelectAndLoadKernel(). They may use + * global variables. + */ + +/** + * Read stored kernel version. + */ +uint32_t RollbackKernelRead(uint32_t *version); -/* Read and write may be called to read and write the kernel version. */ -uint32_t RollbackKernelRead(uint32_t* version); +/** + * Write stored kernel version. + */ uint32_t RollbackKernelWrite(uint32_t version); -/* Lock must be called. Internally, it's ignored in recovery mode. */ +/** + * Lock must be called. Internally, it's ignored in recovery mode. + */ uint32_t RollbackKernelLock(void); /****************************************************************************/ -/* The following functions are internal apis, listed here for use by - * unit tests only. */ -/* Issue a TPM_Clear and reenable/reactivate the TPM. */ +/* + * The following functions are internal apis, listed here for use by unit tests + * only. + */ + +/** + * Issue a TPM_Clear and reenable/reactivate the TPM. + */ uint32_t TPMClearAndReenable(void); -/* Like TlclWrite(), but checks for write errors due to hitting the 64-write +/** + * Like TlclWrite(), but checks for write errors due to hitting the 64-write * limit and clears the TPM when that happens. This can only happen when the * TPM is unowned, so it is OK to clear it (and we really have no choice). - * This is not expected to happen frequently, but it could happen. */ -uint32_t SafeWrite(uint32_t index, const void* data, uint32_t length); + * This is not expected to happen frequently, but it could happen. + */ +uint32_t SafeWrite(uint32_t index, const void *data, uint32_t length); -/* Similarly to SafeWrite(), this ensures we don't fail a DefineSpace because +/** + * Similarly to SafeWrite(), this ensures we don't fail a DefineSpace because * we hit the TPM write limit. This is even less likely to happen than with * writes because we only define spaces once at initialization, but we'd rather - * be paranoid about this. */ + * be paranoid about this. + */ uint32_t SafeDefineSpace(uint32_t index, uint32_t perm, uint32_t size); -/* Performs one-time initializations. Creates the NVRAM spaces, and sets their - * initial values as needed. Sets the nvLocked bit and ensures the physical - * presence command is enabled and locked. +/** + * Perform one-time initializations. + * + * Create the NVRAM spaces, and set their initial values as needed. Sets the + * nvLocked bit and ensures the physical presence command is enabled and + * locked. */ -uint32_t OneTimeInitializeTPM(RollbackSpaceFirmware* rsf, - RollbackSpaceKernel* rsk); +uint32_t OneTimeInitializeTPM(RollbackSpaceFirmware *rsf, + RollbackSpaceKernel *rsk); -/* SetupTPM starts the TPM and establishes the root of trust for the - * anti-rollback mechanism. */ +/** + * Start the TPM and establish the root of trust for the anti-rollback + * mechanism. + */ uint32_t SetupTPM(int recovery_mode, int developer_mode, int disable_dev_request, int clear_tpm_owner_request, - RollbackSpaceFirmware* rsf); + RollbackSpaceFirmware *rsf); -/* Utility function to turn the virtual dev-mode flag on or off. 0=off, 1=on */ +/** + * Utility function to turn the virtual dev-mode flag on or off. 0=off, 1=on. + */ uint32_t SetVirtualDevMode(int val); #endif /* VBOOT_REFERENCE_ROLLBACK_INDEX_H_ */ diff --git a/firmware/lib/include/stateful_util.h b/firmware/lib/include/stateful_util.h index 980b12b0..5d144abf 100644 --- a/firmware/lib/include/stateful_util.h +++ b/firmware/lib/include/stateful_util.h @@ -1,66 +1,76 @@ -/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved. +/* Copyright (c) 2013 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. */ -/* Helper functions/wrappers for memory allocations, manipulation and +/* + * Helper functions/wrappers for memory allocations, manipulation and * comparison. */ -#ifndef VBOOT_FIRMWARE_LIB_UTILITY_H_ -#define VBOOT_FIRMWARE_LIB_UTILITY_H_ +#ifndef VBOOT_FIRMWARE_LIB_STATEFUL_UTIL_H_ +#define VBOOT_FIRMWARE_LIB_STATEFUL_UTIL_H_ #include "sysincludes.h" /* Track remaining data to be read in a buffer. */ typedef struct MemcpyState { - uint8_t* remaining_buf; - uint64_t remaining_len; /* Remaining length of the buffer. */ - uint8_t overrun; /* Flag set to 1 when an overrun occurs. */ + uint8_t *remaining_buf; + uint64_t remaining_len; /* Remaining length of the buffer. */ + uint8_t overrun; /* Flag set to 1 when an overrun occurs. */ } MemcpyState; -/* Initialize a stateful buffer struct to point to the buffer, with - * the specified remaining length in bytes. */ -void StatefulInit(MemcpyState* state, void* buf, uint64_t len); +/** + * Initialize a stateful buffer struct to point to the buffer, with the + * specified remaining length in bytes. + */ +void StatefulInit(MemcpyState *state, void *buf, uint64_t len); -/* Skip [len] bytes only if there's enough data to skip according - * to [state]. +/** + * Skip [len] bytes only if there's enough data to skip according to [state]. + * * On success, return a meaningless but non-NULL pointer and updates [state]. * On failure, return NULL, set state->overrun to 1. * * Useful for iterating through a binary blob to populate a struct. After the * first failure (buffer overrun), successive calls will always fail. */ -void* StatefulSkip(MemcpyState* state, uint64_t len); +void *StatefulSkip(MemcpyState *state, uint64_t len); -/* Copy [len] bytes into [dst] only if there's enough data to read according +/** + * Copy [len] bytes into [dst] only if there's enough data to read according * to [state]. + * * On success, return [dst] and update [state]. * On failure, return NULL, set state->overrun to 1. * * Useful for iterating through a binary blob to populate a struct. After the * first failure (buffer overrun), successive calls will always fail. */ -void* StatefulMemcpy(MemcpyState* state, void* dst, uint64_t len); +void *StatefulMemcpy(MemcpyState *state, void *dst, uint64_t len); -/* Like StatefulMemcpy() but copies in the opposite direction, populating +/** + * Like StatefulMemcpy() but copies in the opposite direction, populating * data from [src] into the buffer encapsulated in state [state]. + * * On success, return [src] and update [state]. * On failure, return NULL, set state->overrun to 1. * * Useful for iterating through a structure to populate a binary blob. After the * first failure (buffer overrun), successive calls will always fail. */ -const void* StatefulMemcpy_r(MemcpyState* state, const void* src, uint64_t len); +const void *StatefulMemcpy_r(MemcpyState *state, const void *src, uint64_t len); -/* Like StatefulMemcpy_r() but fills a portion of the encapsulated buffer with +/** + * Like StatefulMemcpy_r() but fills a portion of the encapsulated buffer with * a constant value. + * * On success, return a meaningless but non-NULL pointer and updates [state]. * On failure, return NULL, set state->overrun to 1. * * After the first failure (buffer overrun), successive calls will always fail. */ -const void* StatefulMemset_r(MemcpyState* state, const uint8_t val, +const void *StatefulMemset_r(MemcpyState *state, const uint8_t val, uint64_t len); -#endif /* VBOOT_FIRMWARE_LIB_UTILITY_H_ */ +#endif diff --git a/firmware/lib/include/tpm_bootmode.h b/firmware/lib/include/tpm_bootmode.h index cdc9fcd1..0a8044ec 100644 --- a/firmware/lib/include/tpm_bootmode.h +++ b/firmware/lib/include/tpm_bootmode.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved. +/* Copyright (c) 2013 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. * @@ -10,16 +10,17 @@ #include "sysincludes.h" -/* Update TPM PCR State with the boot path status. +/** + * Update TPM PCR State with the boot path status. + * * [developer_mode]: State of the developer switch. * [recovery_mode}: State of the recovery mode. - * [fw_keyblock_flags]: Keyblock flags on the to-be-booted + * [fw_keyblock_flags]: Keyblock flags of the to-be-booted * RW firmware keyblock. * - * Returns: TPM_SUCCESS if the TPM extend operation succeeds. + * Returns: TPM_SUCCESS if the TPM extend operation succeeds. */ - uint32_t SetTPMBootModeState(int developer_mode, int recovery_mode, - uint64_t fw_keyblock_flags); + uint64_t fw_keyblock_flags); #endif /* VBOOT_REFERENCE_TPM_BOOTMODE_H_ */ diff --git a/firmware/lib/include/vboot_audio.h b/firmware/lib/include/vboot_audio.h index eea5a65a..afcac140 100644 --- a/firmware/lib/include/vboot_audio.h +++ b/firmware/lib/include/vboot_audio.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved. +/* Copyright (c) 2013 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. * @@ -12,14 +12,20 @@ typedef struct VbAudioContext VbAudioContext; -/* Initialization function. Returns context for processing dev-mode delay */ -VbAudioContext* VbAudioOpen(VbCommonParams* cparams); +/** + * Initialization function. Returns context for processing dev-mode delay. + */ +VbAudioContext *VbAudioOpen(VbCommonParams *cparams); -/* Caller should loop without extra delay until this returns false */ -int VbAudioLooping(VbAudioContext* audio); +/** + * Caller should loop without extra delay until this returns false. + */ +int VbAudioLooping(VbAudioContext *audio); -/* Caller should call this prior to booting */ -void VbAudioClose(VbAudioContext* audio); +/** + * Caller should call this prior to booting. + */ +void VbAudioClose(VbAudioContext *audio); #endif /* VBOOT_REFERENCE_VBOOT_AUDIO_H_ */ diff --git a/firmware/lib/include/vboot_audio_private.h b/firmware/lib/include/vboot_audio_private.h index 236cc09c..902bc62e 100644 --- a/firmware/lib/include/vboot_audio_private.h +++ b/firmware/lib/include/vboot_audio_private.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved. +/* Copyright (c) 2013 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. * @@ -12,32 +12,32 @@ #include "vboot_audio.h" typedef struct VbDevMusicNote { - uint16_t msec; - uint16_t frequency; + uint16_t msec; + uint16_t frequency; } __attribute__((packed)) VbDevMusicNote; typedef struct VbDevMusic { - uint8_t sig[4]; /* "$SND" */ - uint32_t checksum; /* crc32 over count & all notes */ - uint32_t count; /* number of notes */ - VbDevMusicNote notes[1]; /* gcc allows [0], MSVC doesn't */ - /* more VbDevMusicNotes follow immediately */ + uint8_t sig[4]; /* "$SND" */ + uint32_t checksum; /* crc32 over count & all notes */ + uint32_t count; /* number of notes */ + VbDevMusicNote notes[1]; /* gcc allows [0], MSVC doesn't */ + /* more VbDevMusicNotes follow immediately */ } __attribute__((packed)) VbDevMusic; struct VbAudioContext { - /* note tracking */ - VbDevMusicNote* music_notes; - uint32_t note_count; - uint32_t next_note; - - /* implementation flags */ - int background_beep; - int free_notes_when_done; - - /* sound tracking */ - uint16_t current_frequency; - uint64_t play_until; - uint64_t last_time; + /* note tracking */ + VbDevMusicNote *music_notes; + uint32_t note_count; + uint32_t next_note; + + /* implementation flags */ + int background_beep; + int free_notes_when_done; + + /* sound tracking */ + uint16_t current_frequency; + uint64_t play_until; + uint64_t last_time; }; #ifdef FOR_TEST @@ -55,4 +55,3 @@ uint32_t VbExMaxMusicSize(void); #endif #endif /* VBOOT_REFERENCE_VBOOT_AUDIO_PRIVATE_H_ */ - diff --git a/firmware/lib/include/vboot_common.h b/firmware/lib/include/vboot_common.h index fe886ce4..ca9abd0a 100644 --- a/firmware/lib/include/vboot_common.h +++ b/firmware/lib/include/vboot_common.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved. +/* Copyright (c) 2013 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. * @@ -17,122 +17,147 @@ /* Error Codes for all common functions. */ enum { - VBOOT_SUCCESS = 0, - VBOOT_KEY_BLOCK_INVALID, /* Key block internal structure is - * invalid, or not a key block */ - VBOOT_KEY_BLOCK_SIGNATURE, /* Key block signature check failed */ - VBOOT_KEY_BLOCK_HASH, /* Key block hash check failed */ - VBOOT_PUBLIC_KEY_INVALID, /* Invalid public key passed to a - * signature verficiation function. */ - VBOOT_PREAMBLE_INVALID, /* Preamble internal structure is - * invalid */ - VBOOT_PREAMBLE_SIGNATURE, /* Preamble signature check failed */ - VBOOT_SHARED_DATA_INVALID, /* Shared data is invalid. */ - VBOOT_ERROR_MAX, + VBOOT_SUCCESS = 0, + /* Key block internal structure is invalid, or not a key block */ + VBOOT_KEY_BLOCK_INVALID, + /* Key block signature check failed */ + VBOOT_KEY_BLOCK_SIGNATURE, + /* Key block hash check failed */ + VBOOT_KEY_BLOCK_HASH, + /* Invalid public key passed to a signature verficiation function. */ + VBOOT_PUBLIC_KEY_INVALID, + /* Preamble internal structure is invalid */ + VBOOT_PREAMBLE_INVALID, + /* Preamble signature check failed */ + VBOOT_PREAMBLE_SIGNATURE, + /* Shared data is invalid. */ + VBOOT_SHARED_DATA_INVALID, + VBOOT_ERROR_MAX, }; -extern char* kVbootErrors[VBOOT_ERROR_MAX]; +extern const char *kVbootErrors[VBOOT_ERROR_MAX]; +/** + * Return offset of ptr from base. + */ +uint64_t OffsetOf(const void *base, const void *ptr); -/* Return offset of ptr from base. */ -uint64_t OffsetOf(const void* base, const void* ptr); - - -/* Helper functions to get data pointed to by a public key or signature. */ -uint8_t* GetPublicKeyData(VbPublicKey* key); -const uint8_t* GetPublicKeyDataC(const VbPublicKey* key); -uint8_t* GetSignatureData(VbSignature* sig); -const uint8_t* GetSignatureDataC(const VbSignature* sig); - +/* + * Helper functions to get data pointed to by a public key or signature. + */ -/* 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, - uint64_t member_data_offset, - uint64_t member_data_size); +uint8_t *GetPublicKeyData(VbPublicKey *key); +const uint8_t *GetPublicKeyDataC(const VbPublicKey *key); +uint8_t *GetSignatureData(VbSignature *sig); +const uint8_t *GetSignatureDataC(const VbSignature *sig); -int VerifyPublicKeyInside(const void* parent, uint64_t parent_size, - const VbPublicKey* key); +/* + * Helper functions to verify the data pointed to by a subfield is inside the + * parent data. Returns 0 if inside, 1 if error. + */ -int VerifySignatureInside(const void* parent, uint64_t parent_size, - const VbSignature* sig); +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); +int VerifyPublicKeyInside(const void *parent, uint64_t parent_size, + const VbPublicKey *key); -/* Initialize a public key to refer to [key_data]. */ -void PublicKeyInit(VbPublicKey* key, uint8_t* key_data, uint64_t key_size); +int VerifySignatureInside(const void *parent, uint64_t parent_size, + const VbSignature *sig); +/** + * Initialize a public key to refer to [key_data]. + */ +void PublicKeyInit(VbPublicKey *key, uint8_t *key_data, uint64_t key_size); -/* Copy a public key from [src] to [dest]. +/** + * Copy a public key from [src] to [dest]. * - * Returns 0 if success, non-zero if error. */ -int PublicKeyCopy(VbPublicKey* dest, const VbPublicKey* src); - + * Returns 0 if success, non-zero if error. + */ +int PublicKeyCopy(VbPublicKey *dest, const VbPublicKey *src); -/* Converts a public key to RsaPublicKey format. The returned key must - * be freed using RSAPublicKeyFree(). +/** + * Convert a public key to RsaPublicKey format. The returned key must be freed + * using RSAPublicKeyFree(). * - * Returns NULL if error. */ -RSAPublicKey* PublicKeyToRSA(const VbPublicKey* key); - - -/* Verifies [data] matches signature [sig] using [key]. [size] is the size - * of the data buffer; the amount of data to be validated is contained in - * sig->data_size. */ -int VerifyData(const uint8_t* data, uint64_t size, const VbSignature* sig, - const RSAPublicKey* key); - + * Returns NULL if error. + */ +RSAPublicKey *PublicKeyToRSA(const VbPublicKey *key); -/* Verifies a secure hash digest from DigestBuf() or DigestFinal(), - * using [key]. Returns 0 on success. */ -int VerifyDigest(const uint8_t* digest, const VbSignature *sig, - const RSAPublicKey* key); +/** + * Verify [data] matches signature [sig] using [key]. [size] is the size of + * the data buffer; the amount of data to be validated is contained in + * sig->data_size. + */ +int VerifyData(const uint8_t *data, uint64_t size, const VbSignature *sig, + const RSAPublicKey *key); -/* Checks the sanity of a key block of size [size] bytes, using public - * key [key]. If hash_only is non-zero, uses only the block checksum - * to verify the key block. Header fields are also checked for - * sanity. Does not verify key index or key block flags. */ -int KeyBlockVerify(const VbKeyBlockHeader* block, uint64_t size, - const VbPublicKey *key, int hash_only); +/** + * Verify a secure hash digest from DigestBuf() or DigestFinal(), using + * [key]. Returns 0 on success. + */ +int VerifyDigest(const uint8_t *digest, const VbSignature *sig, + const RSAPublicKey *key); + +/** + * Check the sanity of a key block of size [size] bytes, using public key + * [key]. If hash_only is non-zero, uses only the block checksum to verify the + * key block. Header fields are also checked for sanity. Does not verify key + * index or key block flags. + */ +int KeyBlockVerify(const VbKeyBlockHeader *block, uint64_t size, + const VbPublicKey *key, int hash_only); -/* Checks the sanity of a firmware preamble of size [size] bytes, - * using public key [key]. +/** + * Check the sanity of a firmware preamble of size [size] bytes, using public + * key [key]. * - * Returns VBOOT_SUCCESS if successful. */ -int VerifyFirmwarePreamble(const VbFirmwarePreambleHeader* preamble, - uint64_t size, const RSAPublicKey* key); - + * Returns VBOOT_SUCCESS if successful. + */ +int VerifyFirmwarePreamble(const VbFirmwarePreambleHeader *preamble, + uint64_t size, const RSAPublicKey *key); -/* Returns the flags from a firmware preamble, or a default value for - * older preamble versions which didn't contain flags. Use this - * function to ensure compatibility with older preamble versions - * (2.0). Assumes the preamble has already been verified via - * VerifyFirmwarePreamble(). */ -uint32_t VbGetFirmwarePreambleFlags(const VbFirmwarePreambleHeader* preamble); +/** + * Return the flags from a firmware preamble, or a default value for older + * preamble versions which didn't contain flags. Use this function to ensure + * compatibility with older preamble versions (2.0). Assumes the preamble has + * already been verified via VerifyFirmwarePreamble(). + */ +uint32_t VbGetFirmwarePreambleFlags(const VbFirmwarePreambleHeader *preamble); -/* Checks the sanity of a kernel preamble of size [size] bytes, - * using public key [key]. +/** + * Check the sanity of a kernel preamble of size [size] bytes, using public key + * [key]. * - * Returns VBOOT_SUCCESS if successful. */ -int VerifyKernelPreamble(const VbKernelPreambleHeader* preamble, - uint64_t size, const RSAPublicKey* key); + * Returns VBOOT_SUCCESS if successful. + */ +int VerifyKernelPreamble(const VbKernelPreambleHeader *preamble, + uint64_t size, const RSAPublicKey *key); -/* Initialize a verified boot shared data structure. +/** + * Initialize a verified boot shared data structure. * - * Returns 0 if success, non-zero if error. */ -int VbSharedDataInit(VbSharedDataHeader* header, uint64_t size); + * Returns 0 if success, non-zero if error. + */ +int VbSharedDataInit(VbSharedDataHeader *header, uint64_t size); -/* Reserve [size] bytes of the shared data area. Returns the offset of the - * reserved data from the start of the shared data buffer, or 0 if error. */ -uint64_t VbSharedDataReserve(VbSharedDataHeader* header, uint64_t size); +/** + * Reserve [size] bytes of the shared data area. Returns the offset of the + * reserved data from the start of the shared data buffer, or 0 if error. + */ +uint64_t VbSharedDataReserve(VbSharedDataHeader *header, uint64_t size); -/* Copy the kernel subkey into the shared data. +/** + * Copy the kernel subkey into the shared data. * - * Returns 0 if success, non-zero if error. */ -int VbSharedDataSetKernelKey(VbSharedDataHeader* header, - const VbPublicKey* src); - + * Returns 0 if success, non-zero if error. + */ +int VbSharedDataSetKernelKey(VbSharedDataHeader *header, + const VbPublicKey *src); #endif /* VBOOT_REFERENCE_VBOOT_COMMON_H_ */ diff --git a/firmware/lib/include/vboot_display.h b/firmware/lib/include/vboot_display.h index b9ec04c0..f8aa810b 100644 --- a/firmware/lib/include/vboot_display.h +++ b/firmware/lib/include/vboot_display.h @@ -11,12 +11,12 @@ #include "vboot_api.h" #include "vboot_nvstorage.h" -VbError_t VbDisplayScreenFromGBB(VbCommonParams* cparams, uint32_t screen, +VbError_t VbDisplayScreenFromGBB(VbCommonParams *cparams, uint32_t screen, VbNvContext *vncptr); -VbError_t VbDisplayScreen(VbCommonParams* cparams, uint32_t screen, int force, +VbError_t VbDisplayScreen(VbCommonParams *cparams, uint32_t screen, int force, VbNvContext *vncptr); -VbError_t VbDisplayDebugInfo(VbCommonParams* cparams, VbNvContext *vncptr); -VbError_t VbCheckDisplayKey(VbCommonParams* cparams, uint32_t key, +VbError_t VbDisplayDebugInfo(VbCommonParams *cparams, VbNvContext *vncptr); +VbError_t VbCheckDisplayKey(VbCommonParams *cparams, uint32_t key, VbNvContext *vncptr); /* Internal functions, for unit testing */ diff --git a/firmware/lib/include/vboot_kernel.h b/firmware/lib/include/vboot_kernel.h index a9d8a407..6e6c5dc3 100644 --- a/firmware/lib/include/vboot_kernel.h +++ b/firmware/lib/include/vboot_kernel.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved. +/* Copyright (c) 2013 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. * @@ -12,15 +12,18 @@ #include "cgptlib.h" #include "vboot_api.h" -/* Allocates and reads GPT data from the drive. The sector_bytes and - * drive_sectors fields should be filled on input. The primary and - * secondary header and entries are filled on output. +/** + * Allocate and read GPT data from the drive. The sector_bytes and + * drive_sectors fields should be filled on input. The primary and secondary + * header and entries are filled on output. * - * Returns 0 if successful, 1 if error. */ -int AllocAndReadGptData(VbExDiskHandle_t disk_handle, GptData* gptdata); + * Returns 0 if successful, 1 if error. + */ +int AllocAndReadGptData(VbExDiskHandle_t disk_handle, GptData *gptdata); -/* Writes any changes for the GPT data back to the drive, then frees the - * buffers. */ -int WriteAndFreeGptData(VbExDiskHandle_t disk_handle, GptData* gptdata); +/** + * Write any changes for the GPT data back to the drive, then free the buffers. + */ +int WriteAndFreeGptData(VbExDiskHandle_t disk_handle, GptData *gptdata); #endif /* VBOOT_REFERENCE_VBOOT_KERNEL_H_ */ 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); } diff --git a/tests/vboot_common3_tests.c b/tests/vboot_common3_tests.c index 69c54a80..c4f81cd3 100644 --- a/tests/vboot_common3_tests.c +++ b/tests/vboot_common3_tests.c @@ -16,267 +16,273 @@ #include "vboot_common.h" -static void ReChecksumKeyBlock(VbKeyBlockHeader *h) { - uint8_t* newchk = DigestBuf((const uint8_t*)h, - h->key_block_checksum.data_size, - SHA512_DIGEST_ALGORITHM); - Memcpy(GetSignatureData(&h->key_block_checksum), newchk, SHA512_DIGEST_SIZE); - free(newchk); +static void ReChecksumKeyBlock(VbKeyBlockHeader *h) +{ + uint8_t *newchk = DigestBuf((const uint8_t *)h, + h->key_block_checksum.data_size, + SHA512_DIGEST_ALGORITHM); + Memcpy(GetSignatureData(&h->key_block_checksum), newchk, + SHA512_DIGEST_SIZE); + free(newchk); } - -static void KeyBlockVerifyTest(const VbPublicKey* public_key, - const VbPrivateKey* private_key, - const VbPublicKey* data_key) { - - VbKeyBlockHeader *hdr; - VbKeyBlockHeader *h; - unsigned hsize; - - hdr = KeyBlockCreate(data_key, private_key, 0x1234); - TEST_NEQ((size_t)hdr, 0, "KeyBlockVerify() prerequisites"); - if (!hdr) - return; - hsize = (unsigned) hdr->key_block_size; - h = (VbKeyBlockHeader*)malloc(hsize + 1024); - - TEST_EQ(KeyBlockVerify(hdr, hsize, NULL, 1), 0, - "KeyBlockVerify() ok using checksum"); - TEST_EQ(KeyBlockVerify(hdr, hsize, public_key, 0), 0, - "KeyBlockVerify() ok using key"); - TEST_NEQ(KeyBlockVerify(hdr, hsize, NULL, 0), 0, - "KeyBlockVerify() missing key"); - - TEST_NEQ(KeyBlockVerify(hdr, hsize - 1, NULL, 1), 0, - "KeyBlockVerify() size--"); - TEST_EQ(KeyBlockVerify(hdr, hsize + 1, NULL, 1), 0, - "KeyBlockVerify() size++"); - - Memcpy(h, hdr, hsize); - h->magic[0] &= 0x12; - TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0, "KeyBlockVerify() magic"); - - /* Care about major version but not minor */ - Memcpy(h, hdr, hsize); - h->header_version_major++; - ReChecksumKeyBlock(h); - TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0, "KeyBlockVerify() major++"); - - Memcpy(h, hdr, hsize); - h->header_version_major--; - ReChecksumKeyBlock(h); - TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0, "KeyBlockVerify() major--"); - - Memcpy(h, hdr, hsize); - h->header_version_minor++; - ReChecksumKeyBlock(h); - TEST_EQ(KeyBlockVerify(h, hsize, NULL, 1), 0, "KeyBlockVerify() minor++"); - - Memcpy(h, hdr, hsize); - h->header_version_minor--; - ReChecksumKeyBlock(h); - TEST_EQ(KeyBlockVerify(h, hsize, NULL, 1), 0, "KeyBlockVerify() minor--"); - - /* Check hash */ - Memcpy(h, hdr, hsize); - h->key_block_checksum.sig_offset = hsize; - ReChecksumKeyBlock(h); - TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0, - "KeyBlockVerify() checksum off end"); - - Memcpy(h, hdr, hsize); - h->key_block_checksum.sig_size /= 2; - ReChecksumKeyBlock(h); - TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0, - "KeyBlockVerify() checksum too small"); - - Memcpy(h, hdr, hsize); - GetPublicKeyData(&h->data_key)[0] ^= 0x34; - TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0, - "KeyBlockVerify() checksum mismatch"); - - /* Check signature */ - Memcpy(h, hdr, hsize); - h->key_block_signature.sig_offset = hsize; - ReChecksumKeyBlock(h); - TEST_NEQ(KeyBlockVerify(h, hsize, public_key, 0), 0, - "KeyBlockVerify() sig off end"); - - Memcpy(h, hdr, hsize); - h->key_block_signature.sig_size--; - ReChecksumKeyBlock(h); - TEST_NEQ(KeyBlockVerify(h, hsize, public_key, 0), 0, - "KeyBlockVerify() sig too small"); - - Memcpy(h, hdr, hsize); - GetPublicKeyData(&h->data_key)[0] ^= 0x34; - TEST_NEQ(KeyBlockVerify(h, hsize, public_key, 0), 0, - "KeyBlockVerify() sig mismatch"); - - Memcpy(h, hdr, hsize); - //ReChecksumKeyBlock(h); - h->key_block_checksum.data_size = h->key_block_size + 1; - TEST_NEQ(KeyBlockVerify(h, hsize, public_key, 1), 0, - "KeyBlockVerify() checksum data past end of block"); - - /* Check that we signed header and data key */ - Memcpy(h, hdr, hsize); - h->key_block_checksum.data_size = 4; - h->data_key.key_offset = 0; - h->data_key.key_size = 0; - ReChecksumKeyBlock(h); - TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0, - "KeyBlockVerify() didn't sign header"); - - Memcpy(h, hdr, hsize); - h->data_key.key_offset = hsize; - ReChecksumKeyBlock(h); - TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0, - "KeyBlockVerify() data key off end"); - - /* Corner cases for error checking */ - TEST_NEQ(KeyBlockVerify(NULL, 4, NULL, 1), 0, - "KeyBlockVerify size too small"); - - /* TODO: verify parser can support a bigger header (i.e., one where - * data_key.key_offset is bigger than expected). */ - - free(h); - free(hdr); +static void KeyBlockVerifyTest(const VbPublicKey *public_key, + const VbPrivateKey *private_key, + const VbPublicKey *data_key) +{ + VbKeyBlockHeader *hdr; + VbKeyBlockHeader *h; + unsigned hsize; + + hdr = KeyBlockCreate(data_key, private_key, 0x1234); + TEST_NEQ((size_t)hdr, 0, "KeyBlockVerify() prerequisites"); + if (!hdr) + return; + hsize = (unsigned) hdr->key_block_size; + h = (VbKeyBlockHeader *)malloc(hsize + 1024); + + TEST_EQ(KeyBlockVerify(hdr, hsize, NULL, 1), 0, + "KeyBlockVerify() ok using checksum"); + TEST_EQ(KeyBlockVerify(hdr, hsize, public_key, 0), 0, + "KeyBlockVerify() ok using key"); + TEST_NEQ(KeyBlockVerify(hdr, hsize, NULL, 0), 0, + "KeyBlockVerify() missing key"); + + TEST_NEQ(KeyBlockVerify(hdr, hsize - 1, NULL, 1), 0, + "KeyBlockVerify() size--"); + TEST_EQ(KeyBlockVerify(hdr, hsize + 1, NULL, 1), 0, + "KeyBlockVerify() size++"); + + Memcpy(h, hdr, hsize); + h->magic[0] &= 0x12; + TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0, + "KeyBlockVerify() magic"); + + /* Care about major version but not minor */ + Memcpy(h, hdr, hsize); + h->header_version_major++; + ReChecksumKeyBlock(h); + TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0, + "KeyBlockVerify() major++"); + + Memcpy(h, hdr, hsize); + h->header_version_major--; + ReChecksumKeyBlock(h); + TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0, + "KeyBlockVerify() major--"); + + Memcpy(h, hdr, hsize); + h->header_version_minor++; + ReChecksumKeyBlock(h); + TEST_EQ(KeyBlockVerify(h, hsize, NULL, 1), 0, + "KeyBlockVerify() minor++"); + + Memcpy(h, hdr, hsize); + h->header_version_minor--; + ReChecksumKeyBlock(h); + TEST_EQ(KeyBlockVerify(h, hsize, NULL, 1), 0, + "KeyBlockVerify() minor--"); + + /* Check hash */ + Memcpy(h, hdr, hsize); + h->key_block_checksum.sig_offset = hsize; + ReChecksumKeyBlock(h); + TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0, + "KeyBlockVerify() checksum off end"); + + Memcpy(h, hdr, hsize); + h->key_block_checksum.sig_size /= 2; + ReChecksumKeyBlock(h); + TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0, + "KeyBlockVerify() checksum too small"); + + Memcpy(h, hdr, hsize); + GetPublicKeyData(&h->data_key)[0] ^= 0x34; + TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0, + "KeyBlockVerify() checksum mismatch"); + + /* Check signature */ + Memcpy(h, hdr, hsize); + h->key_block_signature.sig_offset = hsize; + ReChecksumKeyBlock(h); + TEST_NEQ(KeyBlockVerify(h, hsize, public_key, 0), 0, + "KeyBlockVerify() sig off end"); + + Memcpy(h, hdr, hsize); + h->key_block_signature.sig_size--; + ReChecksumKeyBlock(h); + TEST_NEQ(KeyBlockVerify(h, hsize, public_key, 0), 0, + "KeyBlockVerify() sig too small"); + + Memcpy(h, hdr, hsize); + GetPublicKeyData(&h->data_key)[0] ^= 0x34; + TEST_NEQ(KeyBlockVerify(h, hsize, public_key, 0), 0, + "KeyBlockVerify() sig mismatch"); + + Memcpy(h, hdr, hsize); + h->key_block_checksum.data_size = h->key_block_size + 1; + TEST_NEQ(KeyBlockVerify(h, hsize, public_key, 1), 0, + "KeyBlockVerify() checksum data past end of block"); + + /* Check that we signed header and data key */ + Memcpy(h, hdr, hsize); + h->key_block_checksum.data_size = 4; + h->data_key.key_offset = 0; + h->data_key.key_size = 0; + ReChecksumKeyBlock(h); + TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0, + "KeyBlockVerify() didn't sign header"); + + Memcpy(h, hdr, hsize); + h->data_key.key_offset = hsize; + ReChecksumKeyBlock(h); + TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0, + "KeyBlockVerify() data key off end"); + + /* Corner cases for error checking */ + TEST_NEQ(KeyBlockVerify(NULL, 4, NULL, 1), 0, + "KeyBlockVerify size too small"); + + /* + * TODO: verify parser can support a bigger header (i.e., one where + * data_key.key_offset is bigger than expected). + */ + + free(h); + free(hdr); } +static void ReSignFirmwarePreamble(VbFirmwarePreambleHeader *h, + const VbPrivateKey *key) +{ + VbSignature *sig = CalculateSignature( + (const uint8_t *)h, h->preamble_signature.data_size, key); -static void ReSignFirmwarePreamble(VbFirmwarePreambleHeader* h, - const VbPrivateKey* key) { - VbSignature *sig = CalculateSignature((const uint8_t*)h, - h->preamble_signature.data_size, key); - - SignatureCopy(&h->preamble_signature, sig); - free(sig); + SignatureCopy(&h->preamble_signature, sig); + free(sig); } - -static void VerifyFirmwarePreambleTest(const VbPublicKey* public_key, - const VbPrivateKey* private_key, - const VbPublicKey* kernel_subkey) { - - VbFirmwarePreambleHeader* hdr; - VbFirmwarePreambleHeader* h; - RSAPublicKey* rsa; - unsigned hsize; - - /* Create a dummy signature */ - VbSignature* body_sig = SignatureAlloc(56, 78); - - rsa = PublicKeyToRSA(public_key); - hdr = CreateFirmwarePreamble(0x1234, kernel_subkey, body_sig, private_key, - 0x5678); - TEST_NEQ(hdr && rsa, 0, "VerifyFirmwarePreamble() prerequisites"); - if (!hdr) - return; - hsize = (unsigned) hdr->preamble_size; - h = (VbFirmwarePreambleHeader*)malloc(hsize + 16384); - - TEST_EQ(VerifyFirmwarePreamble(hdr, hsize, rsa), 0, - "VerifyFirmwarePreamble() ok using key"); - TEST_NEQ(VerifyFirmwarePreamble(hdr, 4, rsa), 0, - "VerifyFirmwarePreamble() size tiny"); - TEST_NEQ(VerifyFirmwarePreamble(hdr, hsize - 1, rsa), 0, - "VerifyFirmwarePreamble() size--"); - TEST_EQ(VerifyFirmwarePreamble(hdr, hsize + 1, rsa), 0, - "VerifyFirmwarePreamble() size++"); - - /* Care about major version but not minor */ - Memcpy(h, hdr, hsize); - h->header_version_major++; - ReSignFirmwarePreamble(h, private_key); - TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0, - "VerifyFirmwarePreamble() major++"); - - Memcpy(h, hdr, hsize); - h->header_version_major--; - ReSignFirmwarePreamble(h, private_key); - TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0, - "VerifyFirmwarePreamble() major--"); - - Memcpy(h, hdr, hsize); - h->header_version_minor++; - ReSignFirmwarePreamble(h, private_key); - TEST_EQ(VerifyFirmwarePreamble(h, hsize, rsa), 0, - "VerifyFirmwarePreamble() minor++"); - - Memcpy(h, hdr, hsize); - h->header_version_minor--; - ReSignFirmwarePreamble(h, private_key); - TEST_EQ(VerifyFirmwarePreamble(h, hsize, rsa), 0, - "VerifyFirmwarePreamble() minor--"); - - /* Check signature */ - Memcpy(h, hdr, hsize); - h->preamble_signature.sig_offset = hsize; - ReSignFirmwarePreamble(h, private_key); - TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0, - "VerifyFirmwarePreamble() sig off end"); - - Memcpy(h, hdr, hsize); - h->preamble_signature.sig_size--; - ReSignFirmwarePreamble(h, private_key); - TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0, - "VerifyFirmwarePreamble() sig too small"); - - Memcpy(h, hdr, hsize); - GetPublicKeyData(&h->kernel_subkey)[0] ^= 0x34; - TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0, - "VerifyFirmwarePreamble() sig mismatch"); - - /* Check that we signed header, kernel subkey, and body sig */ - Memcpy(h, hdr, hsize); - h->preamble_signature.data_size = 4; - h->kernel_subkey.key_offset = 0; - h->kernel_subkey.key_size = 0; - h->body_signature.sig_offset = 0; - h->body_signature.sig_size = 0; - ReSignFirmwarePreamble(h, private_key); - TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0, - "VerifyFirmwarePreamble() didn't sign header"); - - Memcpy(h, hdr, hsize); - h->kernel_subkey.key_offset = hsize; - ReSignFirmwarePreamble(h, private_key); - TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0, - "VerifyFirmwarePreamble() kernel subkey off end"); - - Memcpy(h, hdr, hsize); - h->body_signature.sig_offset = hsize; - ReSignFirmwarePreamble(h, private_key); - TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0, - "VerifyFirmwarePreamble() body sig off end"); - - /* Check that we return flags properly for new and old structs */ - Memcpy(h, hdr, hsize); - TEST_EQ(VbGetFirmwarePreambleFlags(h), 0x5678, - "VbGetFirmwarePreambleFlags() v2.1"); - h->header_version_minor = 0; - TEST_EQ(VbGetFirmwarePreambleFlags(h), 0, - "VbGetFirmwarePreambleFlags() v2.0"); - - /* TODO: verify with extra padding at end of header. */ - - free(h); - RSAPublicKeyFree(rsa); - free(hdr); +static void VerifyFirmwarePreambleTest(const VbPublicKey *public_key, + const VbPrivateKey *private_key, + const VbPublicKey *kernel_subkey) +{ + VbFirmwarePreambleHeader *hdr; + VbFirmwarePreambleHeader *h; + RSAPublicKey *rsa; + unsigned hsize; + + /* Create a dummy signature */ + VbSignature* body_sig = SignatureAlloc(56, 78); + + rsa = PublicKeyToRSA(public_key); + hdr = CreateFirmwarePreamble(0x1234, kernel_subkey, body_sig, + private_key, 0x5678); + TEST_NEQ(hdr && rsa, 0, "VerifyFirmwarePreamble() prerequisites"); + if (!hdr) + return; + hsize = (unsigned) hdr->preamble_size; + h = (VbFirmwarePreambleHeader *)malloc(hsize + 16384); + + TEST_EQ(VerifyFirmwarePreamble(hdr, hsize, rsa), 0, + "VerifyFirmwarePreamble() ok using key"); + TEST_NEQ(VerifyFirmwarePreamble(hdr, 4, rsa), 0, + "VerifyFirmwarePreamble() size tiny"); + TEST_NEQ(VerifyFirmwarePreamble(hdr, hsize - 1, rsa), 0, + "VerifyFirmwarePreamble() size--"); + TEST_EQ(VerifyFirmwarePreamble(hdr, hsize + 1, rsa), 0, + "VerifyFirmwarePreamble() size++"); + + /* Care about major version but not minor */ + Memcpy(h, hdr, hsize); + h->header_version_major++; + ReSignFirmwarePreamble(h, private_key); + TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0, + "VerifyFirmwarePreamble() major++"); + + Memcpy(h, hdr, hsize); + h->header_version_major--; + ReSignFirmwarePreamble(h, private_key); + TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0, + "VerifyFirmwarePreamble() major--"); + + Memcpy(h, hdr, hsize); + h->header_version_minor++; + ReSignFirmwarePreamble(h, private_key); + TEST_EQ(VerifyFirmwarePreamble(h, hsize, rsa), 0, + "VerifyFirmwarePreamble() minor++"); + + Memcpy(h, hdr, hsize); + h->header_version_minor--; + ReSignFirmwarePreamble(h, private_key); + TEST_EQ(VerifyFirmwarePreamble(h, hsize, rsa), 0, + "VerifyFirmwarePreamble() minor--"); + + /* Check signature */ + Memcpy(h, hdr, hsize); + h->preamble_signature.sig_offset = hsize; + ReSignFirmwarePreamble(h, private_key); + TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0, + "VerifyFirmwarePreamble() sig off end"); + + Memcpy(h, hdr, hsize); + h->preamble_signature.sig_size--; + ReSignFirmwarePreamble(h, private_key); + TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0, + "VerifyFirmwarePreamble() sig too small"); + + Memcpy(h, hdr, hsize); + GetPublicKeyData(&h->kernel_subkey)[0] ^= 0x34; + TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0, + "VerifyFirmwarePreamble() sig mismatch"); + + /* Check that we signed header, kernel subkey, and body sig */ + Memcpy(h, hdr, hsize); + h->preamble_signature.data_size = 4; + h->kernel_subkey.key_offset = 0; + h->kernel_subkey.key_size = 0; + h->body_signature.sig_offset = 0; + h->body_signature.sig_size = 0; + ReSignFirmwarePreamble(h, private_key); + TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0, + "VerifyFirmwarePreamble() didn't sign header"); + + Memcpy(h, hdr, hsize); + h->kernel_subkey.key_offset = hsize; + ReSignFirmwarePreamble(h, private_key); + TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0, + "VerifyFirmwarePreamble() kernel subkey off end"); + + Memcpy(h, hdr, hsize); + h->body_signature.sig_offset = hsize; + ReSignFirmwarePreamble(h, private_key); + TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0, + "VerifyFirmwarePreamble() body sig off end"); + + /* Check that we return flags properly for new and old structs */ + Memcpy(h, hdr, hsize); + TEST_EQ(VbGetFirmwarePreambleFlags(h), 0x5678, + "VbGetFirmwarePreambleFlags() v2.1"); + h->header_version_minor = 0; + TEST_EQ(VbGetFirmwarePreambleFlags(h), 0, + "VbGetFirmwarePreambleFlags() v2.0"); + + /* TODO: verify with extra padding at end of header. */ + + free(h); + RSAPublicKeyFree(rsa); + free(hdr); } int test_permutation(int signing_key_algorithm, int data_key_algorithm, const char *keys_dir) { char filename[1024]; - int signing_rsa_len = siglen_map[signing_key_algorithm] * 8;; - int data_rsa_len = siglen_map[data_key_algorithm] * 8;; + int signing_rsa_len = siglen_map[signing_key_algorithm] * 8; + int data_rsa_len = siglen_map[data_key_algorithm] * 8; - VbPrivateKey* signing_private_key = NULL; - VbPublicKey* signing_public_key = NULL; - VbPublicKey* data_public_key = NULL; + VbPrivateKey *signing_private_key = NULL; + VbPublicKey *signing_public_key = NULL; + VbPublicKey *data_public_key = NULL; printf("***Testing signing algorithm: %s\n", algo_strings[signing_key_algorithm]); @@ -339,7 +345,7 @@ struct test_perm */ const struct test_perm test_perms[] = {{7, 4}, {11, 4}, {11, 7}}; -int main(int argc, char* argv[]) +int main(int argc, char *argv[]) { if (argc == 2) { /* Test only the algorithms we use */ -- cgit v1.2.1