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 <rspangler@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/42053
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
This commit is contained in:
Randall Spangler
2013-01-25 15:05:08 -08:00
committed by ChromeBot
parent 3b806ea951
commit 68f54d4475
12 changed files with 929 additions and 820 deletions

View File

@@ -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 * Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. * found in the LICENSE file.
* *
@@ -45,20 +45,22 @@ __pragma(pack(push, 1)) /* Support packing for MSVC. */
#define FONT_SIGNATURE_SIZE 4 #define FONT_SIGNATURE_SIZE 4
typedef struct FontArrayHeader { typedef struct FontArrayHeader {
uint8_t signature[FONT_SIGNATURE_SIZE]; uint8_t signature[FONT_SIGNATURE_SIZE];
uint32_t num_entries; /* Number of chars encoded here. */ uint32_t num_entries; /* Number of chars encoded here. */
} __attribute__((packed)) FontArrayHeader; } __attribute__((packed)) FontArrayHeader;
typedef struct FontArrayEntryHeader { typedef struct FontArrayEntryHeader {
uint32_t ascii; /* What to show. Could even be UTF? */ uint32_t ascii; /* What to show. Could even be UTF? */
ImageInfo info; /* Describes the bitmap. */ 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;
/*
* 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. */ __pragma(pack(pop)) /* Support packing for MSVC. */

View File

@@ -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 * Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. * found in the LICENSE file.
* *
@@ -8,6 +8,6 @@
#define VBOOT_REFERENCE_CRC8_H_ #define VBOOT_REFERENCE_CRC8_H_
#include "sysincludes.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_ */ #endif /* VBOOT_REFERENCE_CRC8_H_ */

View File

@@ -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 * Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. * 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. */ /* Kernel space - KERNEL_NV_INDEX, locked with physical presence. */
#define ROLLBACK_SPACE_KERNEL_VERSION 2 #define ROLLBACK_SPACE_KERNEL_VERSION 2
#define ROLLBACK_SPACE_KERNEL_UID 0x4752574C /* 'GRWL' */ #define ROLLBACK_SPACE_KERNEL_UID 0x4752574C /* 'GRWL' */
typedef struct RollbackSpaceKernel { typedef struct RollbackSpaceKernel {
uint8_t struct_version; /* Struct version, for backwards /* Struct version, for backwards compatibility */
* compatibility */ uint8_t struct_version;
uint32_t uid; /* Unique ID to detect space redefinition */ /* Unique ID to detect space redefinition */
uint32_t kernel_versions; /* Kernel versions */ uint32_t uid;
uint8_t reserved[3]; /* Reserved for future expansion */ /* Kernel versions */
uint8_t crc8; /* Checksum (v2 and later only) */ uint32_t kernel_versions;
/* Reserved for future expansion */
uint8_t reserved[3];
/* Checksum (v2 and later only) */
uint8_t crc8;
} __attribute__((packed)) RollbackSpaceKernel; } __attribute__((packed)) RollbackSpaceKernel;
/* Flags for firmware space */ /* 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 #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, * Some systems may not have a dedicated dev-mode switch, but enter and leave
* the dev-mode "switch" state is in this bit (0=normal, 1=dev). To make it * dev-mode through some recovery-mode magic keypresses. For those systems, the
* work, a new flag is passed to VbInit(), indicating that the system lacks a * dev-mode "switch" state is in this bit (0=normal, 1=dev). To make it work, a
* physical dev-mode switch. If a physical switch is present, this bit is * new flag is passed to VbInit(), indicating that the system lacks a physical
* ignored. */ * dev-mode switch. If a physical switch is present, this bit is ignored.
*/
#define FLAG_VIRTUAL_DEV_MODE_ON 0x02 #define FLAG_VIRTUAL_DEV_MODE_ON 0x02
#define ROLLBACK_SPACE_FIRMWARE_VERSION 2
/* Firmware space - FIRMWARE_NV_INDEX, locked with global lock. */ /* Firmware space - FIRMWARE_NV_INDEX, locked with global lock. */
#define ROLLBACK_SPACE_FIRMWARE_VERSION 2
typedef struct RollbackSpaceFirmware { typedef struct RollbackSpaceFirmware {
uint8_t struct_version; /* Struct version, for backwards compatibility */ /* Struct version, for backwards compatibility */
uint8_t flags; /* Flags (see FLAG_* above) */ uint8_t struct_version;
uint32_t fw_versions; /* Firmware versions */ /* Flags (see FLAG_* above) */
uint8_t reserved[3]; /* Reserved for future expansion */ uint8_t flags;
uint8_t crc8; /* Checksum (v2 and later only) */ /* 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; } __attribute__((packed)) RollbackSpaceFirmware;
__pragma(pack(pop)) /* Support packing for MSVC. */ __pragma(pack(pop)) /* Support packing for MSVC. */
/* All functions return TPM_SUCCESS (zero) if successful, non-zero if error */ /* 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); 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, uint32_t RollbackFirmwareSetup(int recovery_mode, int is_hw_dev,
int disable_dev_request, int disable_dev_request,
int clear_tpm_owner_request, int clear_tpm_owner_request,
/* two outputs on success */ /* two outputs on success */
int *is_virt_dev, uint32_t *tpm_version); 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); uint32_t RollbackFirmwareWrite(uint32_t version);
/* Lock must be called */ /**
* Lock must be called.
*/
uint32_t RollbackFirmwareLock(void); 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 and write may be called to read and write the kernel version. */ /**
uint32_t RollbackKernelRead(uint32_t* version); * Read stored kernel version.
*/
uint32_t RollbackKernelRead(uint32_t *version);
/**
* Write stored kernel version.
*/
uint32_t RollbackKernelWrite(uint32_t 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); 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); 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 * 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). * 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. */ * This is not expected to happen frequently, but it could happen.
uint32_t SafeWrite(uint32_t index, const void* data, uint32_t length); */
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 * 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 * 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); 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 * Perform one-time initializations.
* presence command is enabled and locked. *
* 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, uint32_t OneTimeInitializeTPM(RollbackSpaceFirmware *rsf,
RollbackSpaceKernel* rsk); 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, uint32_t SetupTPM(int recovery_mode, int developer_mode,
int disable_dev_request, int clear_tpm_owner_request, 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); uint32_t SetVirtualDevMode(int val);
#endif /* VBOOT_REFERENCE_ROLLBACK_INDEX_H_ */ #endif /* VBOOT_REFERENCE_ROLLBACK_INDEX_H_ */

View File

@@ -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 * Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. * found in the LICENSE file.
*/ */
/* Helper functions/wrappers for memory allocations, manipulation and /*
* Helper functions/wrappers for memory allocations, manipulation and
* comparison. * comparison.
*/ */
#ifndef VBOOT_FIRMWARE_LIB_UTILITY_H_ #ifndef VBOOT_FIRMWARE_LIB_STATEFUL_UTIL_H_
#define VBOOT_FIRMWARE_LIB_UTILITY_H_ #define VBOOT_FIRMWARE_LIB_STATEFUL_UTIL_H_
#include "sysincludes.h" #include "sysincludes.h"
/* Track remaining data to be read in a buffer. */ /* Track remaining data to be read in a buffer. */
typedef struct MemcpyState { typedef struct MemcpyState {
uint8_t* remaining_buf; uint8_t *remaining_buf;
uint64_t remaining_len; /* Remaining length of the buffer. */ uint64_t remaining_len; /* Remaining length of the buffer. */
uint8_t overrun; /* Flag set to 1 when an overrun occurs. */ uint8_t overrun; /* Flag set to 1 when an overrun occurs. */
} MemcpyState; } MemcpyState;
/* Initialize a stateful buffer struct to point to the buffer, with /**
* the specified remaining length in bytes. */ * Initialize a stateful buffer struct to point to the buffer, with the
void StatefulInit(MemcpyState* state, void* buf, uint64_t len); * 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 success, return a meaningless but non-NULL pointer and updates [state].
* On failure, return NULL, set state->overrun to 1. * On failure, return NULL, set state->overrun to 1.
* *
* Useful for iterating through a binary blob to populate a struct. After the * Useful for iterating through a binary blob to populate a struct. After the
* first failure (buffer overrun), successive calls will always fail. * 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]. * to [state].
*
* On success, return [dst] and update [state]. * On success, return [dst] and update [state].
* On failure, return NULL, set state->overrun to 1. * On failure, return NULL, set state->overrun to 1.
* *
* Useful for iterating through a binary blob to populate a struct. After the * Useful for iterating through a binary blob to populate a struct. After the
* first failure (buffer overrun), successive calls will always fail. * 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]. * data from [src] into the buffer encapsulated in state [state].
*
* On success, return [src] and update [state]. * On success, return [src] and update [state].
* On failure, return NULL, set state->overrun to 1. * On failure, return NULL, set state->overrun to 1.
* *
* Useful for iterating through a structure to populate a binary blob. After the * Useful for iterating through a structure to populate a binary blob. After the
* first failure (buffer overrun), successive calls will always fail. * 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. * a constant value.
*
* On success, return a meaningless but non-NULL pointer and updates [state]. * On success, return a meaningless but non-NULL pointer and updates [state].
* On failure, return NULL, set state->overrun to 1. * On failure, return NULL, set state->overrun to 1.
* *
* After the first failure (buffer overrun), successive calls will always fail. * 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); uint64_t len);
#endif /* VBOOT_FIRMWARE_LIB_UTILITY_H_ */ #endif

View File

@@ -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 * Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. * found in the LICENSE file.
* *
@@ -10,16 +10,17 @@
#include "sysincludes.h" #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. * [developer_mode]: State of the developer switch.
* [recovery_mode}: State of the recovery mode. * [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. * 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, 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_ */ #endif /* VBOOT_REFERENCE_TPM_BOOTMODE_H_ */

View File

@@ -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 * Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. * found in the LICENSE file.
* *
@@ -12,14 +12,20 @@
typedef struct VbAudioContext VbAudioContext; 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_ */ #endif /* VBOOT_REFERENCE_VBOOT_AUDIO_H_ */

View File

@@ -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 * Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. * found in the LICENSE file.
* *
@@ -12,32 +12,32 @@
#include "vboot_audio.h" #include "vboot_audio.h"
typedef struct VbDevMusicNote { typedef struct VbDevMusicNote {
uint16_t msec; uint16_t msec;
uint16_t frequency; uint16_t frequency;
} __attribute__((packed)) VbDevMusicNote; } __attribute__((packed)) VbDevMusicNote;
typedef struct VbDevMusic { typedef struct VbDevMusic {
uint8_t sig[4]; /* "$SND" */ uint8_t sig[4]; /* "$SND" */
uint32_t checksum; /* crc32 over count & all notes */ uint32_t checksum; /* crc32 over count & all notes */
uint32_t count; /* number of notes */ uint32_t count; /* number of notes */
VbDevMusicNote notes[1]; /* gcc allows [0], MSVC doesn't */ VbDevMusicNote notes[1]; /* gcc allows [0], MSVC doesn't */
/* more VbDevMusicNotes follow immediately */ /* more VbDevMusicNotes follow immediately */
} __attribute__((packed)) VbDevMusic; } __attribute__((packed)) VbDevMusic;
struct VbAudioContext { struct VbAudioContext {
/* note tracking */ /* note tracking */
VbDevMusicNote* music_notes; VbDevMusicNote *music_notes;
uint32_t note_count; uint32_t note_count;
uint32_t next_note; uint32_t next_note;
/* implementation flags */ /* implementation flags */
int background_beep; int background_beep;
int free_notes_when_done; int free_notes_when_done;
/* sound tracking */ /* sound tracking */
uint16_t current_frequency; uint16_t current_frequency;
uint64_t play_until; uint64_t play_until;
uint64_t last_time; uint64_t last_time;
}; };
#ifdef FOR_TEST #ifdef FOR_TEST
@@ -55,4 +55,3 @@ uint32_t VbExMaxMusicSize(void);
#endif #endif
#endif /* VBOOT_REFERENCE_VBOOT_AUDIO_PRIVATE_H_ */ #endif /* VBOOT_REFERENCE_VBOOT_AUDIO_PRIVATE_H_ */

View File

@@ -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 * Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. * found in the LICENSE file.
* *
@@ -17,122 +17,147 @@
/* Error Codes for all common functions. */ /* Error Codes for all common functions. */
enum { enum {
VBOOT_SUCCESS = 0, VBOOT_SUCCESS = 0,
VBOOT_KEY_BLOCK_INVALID, /* Key block internal structure is /* Key block internal structure is invalid, or not a key block */
* invalid, or not a key block */ VBOOT_KEY_BLOCK_INVALID,
VBOOT_KEY_BLOCK_SIGNATURE, /* Key block signature check failed */ /* Key block signature check failed */
VBOOT_KEY_BLOCK_HASH, /* Key block hash check failed */ VBOOT_KEY_BLOCK_SIGNATURE,
VBOOT_PUBLIC_KEY_INVALID, /* Invalid public key passed to a /* Key block hash check failed */
* signature verficiation function. */ VBOOT_KEY_BLOCK_HASH,
VBOOT_PREAMBLE_INVALID, /* Preamble internal structure is /* Invalid public key passed to a signature verficiation function. */
* invalid */ VBOOT_PUBLIC_KEY_INVALID,
VBOOT_PREAMBLE_SIGNATURE, /* Preamble signature check failed */ /* Preamble internal structure is invalid */
VBOOT_SHARED_DATA_INVALID, /* Shared data is invalid. */ VBOOT_PREAMBLE_INVALID,
VBOOT_ERROR_MAX, /* 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. */ /*
uint8_t* GetPublicKeyData(VbPublicKey* key); * Helper functions to verify the data pointed to by a subfield is inside the
const uint8_t* GetPublicKeyDataC(const VbPublicKey* key); * parent data. Returns 0 if inside, 1 if error.
uint8_t* GetSignatureData(VbSignature* sig); */
const uint8_t* GetSignatureDataC(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);
/* Helper functions to verify the data pointed to by a subfield is inside int VerifyPublicKeyInside(const void *parent, uint64_t parent_size,
* the parent data. Returns 0 if inside, 1 if error. */ const VbPublicKey *key);
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, int VerifySignatureInside(const void *parent, uint64_t parent_size,
const VbPublicKey* key); const VbSignature *sig);
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);
/**
/* Initialize a public key to refer to [key_data]. */ * Copy a public key from [src] to [dest].
void PublicKeyInit(VbPublicKey* key, uint8_t* key_data, uint64_t key_size);
/* Copy a public key from [src] to [dest].
* *
* Returns 0 if success, non-zero if error. */ * Returns 0 if success, non-zero if error.
int PublicKeyCopy(VbPublicKey* dest, const VbPublicKey* src); */
int PublicKeyCopy(VbPublicKey *dest, const VbPublicKey *src);
/**
/* Converts a public key to RsaPublicKey format. The returned key must * Convert a public key to RsaPublicKey format. The returned key must be freed
* be freed using RSAPublicKeyFree(). * using RSAPublicKeyFree().
* *
* Returns NULL if error. */ * Returns NULL if error.
RSAPublicKey* PublicKeyToRSA(const VbPublicKey* key); */
RSAPublicKey *PublicKeyToRSA(const VbPublicKey *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);
/**
* 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);
/* 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 * Check the sanity of a firmware preamble of size [size] bytes, using public
* sig->data_size. */ * key [key].
int VerifyData(const uint8_t* data, uint64_t size, const VbSignature* sig,
const RSAPublicKey* 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);
/* 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);
/* Checks the sanity of a firmware preamble of size [size] bytes,
* using public key [key].
* *
* Returns VBOOT_SUCCESS if successful. */ * Returns VBOOT_SUCCESS if successful.
int VerifyFirmwarePreamble(const VbFirmwarePreambleHeader* preamble, */
uint64_t size, const RSAPublicKey* key); 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 * Return the flags from a firmware preamble, or a default value for older
* function to ensure compatibility with older preamble versions * preamble versions which didn't contain flags. Use this function to ensure
* (2.0). Assumes the preamble has already been verified via * compatibility with older preamble versions (2.0). Assumes the preamble has
* VerifyFirmwarePreamble(). */ * already been verified via VerifyFirmwarePreamble().
uint32_t VbGetFirmwarePreambleFlags(const VbFirmwarePreambleHeader* preamble); */
uint32_t VbGetFirmwarePreambleFlags(const VbFirmwarePreambleHeader *preamble);
/**
/* Checks the sanity of a kernel preamble of size [size] bytes, * Check the sanity of a kernel preamble of size [size] bytes, using public key
* using public key [key]. * [key].
* *
* Returns VBOOT_SUCCESS if successful. */ * Returns VBOOT_SUCCESS if successful.
int VerifyKernelPreamble(const VbKernelPreambleHeader* preamble, */
uint64_t size, const RSAPublicKey* key); 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. */ * Returns 0 if success, non-zero if error.
int VbSharedDataInit(VbSharedDataHeader* header, uint64_t size); */
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. */ * Reserve [size] bytes of the shared data area. Returns the offset of the
uint64_t VbSharedDataReserve(VbSharedDataHeader* header, uint64_t size); * 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. */ * Returns 0 if success, non-zero if error.
int VbSharedDataSetKernelKey(VbSharedDataHeader* header, */
const VbPublicKey* src); int VbSharedDataSetKernelKey(VbSharedDataHeader *header,
const VbPublicKey *src);
#endif /* VBOOT_REFERENCE_VBOOT_COMMON_H_ */ #endif /* VBOOT_REFERENCE_VBOOT_COMMON_H_ */

View File

@@ -11,12 +11,12 @@
#include "vboot_api.h" #include "vboot_api.h"
#include "vboot_nvstorage.h" #include "vboot_nvstorage.h"
VbError_t VbDisplayScreenFromGBB(VbCommonParams* cparams, uint32_t screen, VbError_t VbDisplayScreenFromGBB(VbCommonParams *cparams, uint32_t screen,
VbNvContext *vncptr); VbNvContext *vncptr);
VbError_t VbDisplayScreen(VbCommonParams* cparams, uint32_t screen, int force, VbError_t VbDisplayScreen(VbCommonParams *cparams, uint32_t screen, int force,
VbNvContext *vncptr); VbNvContext *vncptr);
VbError_t VbDisplayDebugInfo(VbCommonParams* cparams, VbNvContext *vncptr); VbError_t VbDisplayDebugInfo(VbCommonParams *cparams, VbNvContext *vncptr);
VbError_t VbCheckDisplayKey(VbCommonParams* cparams, uint32_t key, VbError_t VbCheckDisplayKey(VbCommonParams *cparams, uint32_t key,
VbNvContext *vncptr); VbNvContext *vncptr);
/* Internal functions, for unit testing */ /* Internal functions, for unit testing */

View File

@@ -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 * Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. * found in the LICENSE file.
* *
@@ -12,15 +12,18 @@
#include "cgptlib.h" #include "cgptlib.h"
#include "vboot_api.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 * Allocate and read GPT data from the drive. The sector_bytes and
* secondary header and entries are filled on output. * 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. */ * Returns 0 if successful, 1 if error.
int AllocAndReadGptData(VbExDiskHandle_t disk_handle, GptData* gptdata); */
int AllocAndReadGptData(VbExDiskHandle_t disk_handle, GptData *gptdata);
/* Writes any changes for the GPT data back to the drive, then frees the /**
* buffers. */ * Write any changes for the GPT data back to the drive, then free the buffers.
int WriteAndFreeGptData(VbExDiskHandle_t disk_handle, GptData* gptdata); */
int WriteAndFreeGptData(VbExDiskHandle_t disk_handle, GptData *gptdata);
#endif /* VBOOT_REFERENCE_VBOOT_KERNEL_H_ */ #endif /* VBOOT_REFERENCE_VBOOT_KERNEL_H_ */

View File

@@ -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 * Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. * found in the LICENSE file.
* *
@@ -6,488 +6,496 @@
* (Firmware portion) * (Firmware portion)
*/ */
#include "vboot_api.h" #include "vboot_api.h"
#include "vboot_common.h" #include "vboot_common.h"
#include "utility.h" #include "utility.h"
const char *kVbootErrors[VBOOT_ERROR_MAX] = {
char* kVbootErrors[VBOOT_ERROR_MAX] = { "Success.",
"Success.", "Key block invalid.",
"Key block invalid.", "Key block signature failed.",
"Key block signature failed.", "Key block hash failed.",
"Key block hash failed.", "Public key invalid.",
"Public key invalid.", "Preamble invalid.",
"Preamble invalid.", "Preamble signature check failed.",
"Preamble signature check failed.", "Shared data invalid."
"Shared data invalid."
}; };
uint64_t OffsetOf(const void *base, const void *ptr)
uint64_t OffsetOf(const void *base, const void *ptr) { {
return (uint64_t)(size_t)ptr - (uint64_t)(size_t)base; return (uint64_t)(size_t)ptr - (uint64_t)(size_t)base;
} }
/* Helper functions to get data pointed to by a public key or signature. */ /* 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) { const uint8_t *GetPublicKeyDataC(const VbPublicKey *key)
return (const uint8_t*)key + key->key_offset; {
return (const uint8_t *)key + key->key_offset;
} }
uint8_t* GetSignatureData(VbSignature* sig) { uint8_t *GetSignatureData(VbSignature *sig)
return (uint8_t*)sig + sig->sig_offset; {
return (uint8_t *)sig + sig->sig_offset;
} }
const uint8_t* GetSignatureDataC(const VbSignature* sig) { const uint8_t *GetSignatureDataC(const VbSignature *sig)
return (const uint8_t*)sig + sig->sig_offset; {
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 int VerifyMemberInside(const void *parent, uint64_t parent_size,
* the parent data. Returns 0 if inside, 1 if error. */ 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_offset,
uint64_t member_data_size) { uint64_t member_data_size)
uint64_t end = OffsetOf(parent, member); {
uint64_t end = OffsetOf(parent, member);
if (end > parent_size) if (end > parent_size)
return 1; return 1;
if (UINT64_MAX - end < member_size) if (UINT64_MAX - end < member_size)
return 1; /* Detect wraparound in integer math */ return 1; /* Detect wraparound in integer math */
if (end + member_size > parent_size) if (end + member_size > parent_size)
return 1; return 1;
if (UINT64_MAX - end < member_data_offset) if (UINT64_MAX - end < member_data_offset)
return 1; return 1;
end += member_data_offset; end += member_data_offset;
if (end > parent_size) if (end > parent_size)
return 1; return 1;
if (UINT64_MAX - end < member_data_size) if (UINT64_MAX - end < member_data_size)
return 1; return 1;
if (end + member_data_size > parent_size) if (end + member_data_size > parent_size)
return 1; return 1;
return 0; return 0;
} }
int VerifyPublicKeyInside(const void *parent, uint64_t parent_size,
int VerifyPublicKeyInside(const void* parent, uint64_t parent_size, const VbPublicKey *key)
const VbPublicKey* key) { {
return VerifyMemberInside(parent, parent_size, return VerifyMemberInside(parent, parent_size,
key, sizeof(VbPublicKey), key, sizeof(VbPublicKey),
key->key_offset, key->key_size); key->key_offset, key->key_size);
} }
int VerifySignatureInside(const void *parent, uint64_t parent_size,
int VerifySignatureInside(const void* parent, uint64_t parent_size, const VbSignature *sig)
const VbSignature* sig) { {
return VerifyMemberInside(parent, parent_size, return VerifyMemberInside(parent, parent_size,
sig, sizeof(VbSignature), sig, sizeof(VbSignature),
sig->sig_offset, sig->sig_size); sig->sig_offset, sig->sig_size);
} }
void PublicKeyInit(VbPublicKey *key, uint8_t *key_data, uint64_t key_size)
void PublicKeyInit(VbPublicKey* key, uint8_t* key_data, uint64_t key_size) { {
key->key_offset = OffsetOf(key, key_data); key->key_offset = OffsetOf(key, key_data);
key->key_size = key_size; key->key_size = key_size;
key->algorithm = kNumAlgorithms; /* Key not present yet */ key->algorithm = kNumAlgorithms; /* Key not present yet */
key->key_version = 0; 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) { dest->key_size = src->key_size;
if (dest->key_size < src->key_size) dest->algorithm = src->algorithm;
return 1; dest->key_version = src->key_version;
Memcpy(GetPublicKeyData(dest), GetPublicKeyDataC(src), src->key_size);
dest->key_size = src->key_size; return 0;
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;
RSAPublicKey* PublicKeyToRSA(const VbPublicKey* key) { if (kNumAlgorithms <= key->algorithm) {
RSAPublicKey *rsa; VBDEBUG(("Invalid algorithm.\n"));
uint64_t key_size; return NULL;
}
if (!RSAProcessedKeySize(key->algorithm, &key_size) ||
key_size != key->key_size) {
VBDEBUG(("Wrong key size for algorithm\n"));
return NULL;
}
if (kNumAlgorithms <= key->algorithm) { rsa = RSAPublicKeyFromBuf(GetPublicKeyDataC(key), key->key_size);
VBDEBUG(("Invalid algorithm.\n")); if (!rsa)
return NULL; 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); rsa->algorithm = (unsigned int)key->algorithm;
if (!rsa) return 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;
}
int VerifyData(const uint8_t* data, uint64_t size, const VbSignature *sig, if (!RSAVerifyBinary_f(NULL, key, data, sig->data_size,
const RSAPublicKey* key) { GetSignatureDataC(sig), key->algorithm))
return 1;
if (sig->sig_size != siglen_map[key->algorithm]) { return 0;
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, if (!RSAVerifyBinaryWithDigest_f(NULL, key, digest,
const RSAPublicKey* key) { GetSignatureDataC(sig),
key->algorithm))
return 1;
if (sig->sig_size != siglen_map[key->algorithm]) { return 0;
VBDEBUG(("Wrong signature size for algorithm.\n"));
return 1;
}
if (!RSAVerifyBinaryWithDigest_f(NULL, key, digest,
GetSignatureDataC(sig), key->algorithm))
return 1;
return 0;
} }
int KeyBlockVerify(const VbKeyBlockHeader *block, uint64_t size,
const VbPublicKey *key, int hash_only)
{
const VbSignature *sig;
int KeyBlockVerify(const VbKeyBlockHeader* block, uint64_t size, /* Sanity checks before attempting signature of data */
const VbPublicKey *key, int hash_only) { 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;
}
const VbSignature* sig; /*
* 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;
/* Sanity checks before attempting signature of data */ sig = &block->key_block_checksum;
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 if (VerifySignatureInside(block, block->key_block_size, sig)) {
* we don't require a key even if the keyblock has a signature, because the VBDEBUG(("Key block hash off end of block\n"));
* caller may not care if the keyblock itself is signed (for example, booting return VBOOT_KEY_BLOCK_INVALID;
* a Google-signed kernel in developer mode). }
*/ if (sig->sig_size != SHA512_DIGEST_SIZE) {
if (hash_only) { VBDEBUG(("Wrong hash size for key block.\n"));
/* Check hash */ return VBOOT_KEY_BLOCK_INVALID;
uint8_t* header_checksum = NULL; }
int rv;
sig = &block->key_block_checksum; /* 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;
}
if (VerifySignatureInside(block, block->key_block_size, sig)) { VBDEBUG(("Checking key block hash only...\n"));
VBDEBUG(("Key block hash off end of block\n")); header_checksum = DigestBuf((const uint8_t *)block,
return VBOOT_KEY_BLOCK_INVALID; sig->data_size,
} SHA512_DIGEST_ALGORITHM);
if (sig->sig_size != SHA512_DIGEST_SIZE) { rv = SafeMemcmp(header_checksum, GetSignatureDataC(sig),
VBDEBUG(("Wrong hash size for key block.\n")); SHA512_DIGEST_SIZE);
return VBOOT_KEY_BLOCK_INVALID; VbExFree(header_checksum);
} if (rv) {
VBDEBUG(("Invalid key block hash.\n"));
return VBOOT_KEY_BLOCK_HASH;
}
} else {
/* Check signature */
RSAPublicKey *rsa;
int rv;
/* Make sure advertised signature data sizes are sane. */ sig = &block->key_block_signature;
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")); if (VerifySignatureInside(block, block->key_block_size, sig)) {
header_checksum = DigestBuf((const uint8_t*)block, sig->data_size, VBDEBUG(("Key block signature off end of block\n"));
SHA512_DIGEST_ALGORITHM); return VBOOT_KEY_BLOCK_INVALID;
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; rsa = PublicKeyToRSA(key);
if (!rsa) {
VBDEBUG(("Invalid public key\n"));
return VBOOT_PUBLIC_KEY_INVALID;
}
if (VerifySignatureInside(block, block->key_block_size, sig)) { /* Make sure advertised signature data sizes are sane. */
VBDEBUG(("Key block signature off end of block\n")); if (block->key_block_size < sig->data_size) {
return VBOOT_KEY_BLOCK_INVALID; VBDEBUG(("Signature calculated past end of block\n"));
} RSAPublicKeyFree(rsa);
return VBOOT_KEY_BLOCK_INVALID;
}
rsa = PublicKeyToRSA(key); VBDEBUG(("Checking key block signature...\n"));
if (!rsa) { rv = VerifyData((const uint8_t *)block, size, sig, rsa);
VBDEBUG(("Invalid public key\n")); RSAPublicKeyFree(rsa);
return VBOOT_PUBLIC_KEY_INVALID; if (rv) {
} VBDEBUG(("Invalid key block signature.\n"));
return VBOOT_KEY_BLOCK_SIGNATURE;
}
}
/* Make sure advertised signature data sizes are sane. */ /* Verify we signed enough data */
if (block->key_block_size < sig->data_size) { if (sig->data_size < sizeof(VbKeyBlockHeader)) {
VBDEBUG(("Signature calculated past end of the block\n")); VBDEBUG(("Didn't sign enough data\n"));
RSAPublicKeyFree(rsa); return VBOOT_KEY_BLOCK_INVALID;
return VBOOT_KEY_BLOCK_INVALID; }
}
VBDEBUG(("Checking key block signature...\n")); /* Verify data key is inside the block and inside signed data */
rv = VerifyData((const uint8_t*)block, size, sig, rsa); if (VerifyPublicKeyInside(block, block->key_block_size,
RSAPublicKeyFree(rsa); &block->data_key)) {
if (rv) { VBDEBUG(("Data key off end of key block\n"));
VBDEBUG(("Invalid key block signature.\n")); return VBOOT_KEY_BLOCK_INVALID;
return VBOOT_KEY_BLOCK_SIGNATURE; }
} if (VerifyPublicKeyInside(block, sig->data_size, &block->data_key)) {
} VBDEBUG(("Data key off end of signed data\n"));
return VBOOT_KEY_BLOCK_INVALID;
}
/* Verify we signed enough data */ /* Success */
if (sig->data_size < sizeof(VbKeyBlockHeader)) { return VBOOT_SUCCESS;
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, int VerifyFirmwarePreamble(const VbFirmwarePreambleHeader *preamble,
uint64_t size, const RSAPublicKey* key) { uint64_t size, const RSAPublicKey *key)
{
const VbSignature *sig = &preamble->preamble_signature;
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;
}
/* Sanity checks before attempting signature of data */ /* Check signature */
if(size < EXPECTED_VBFIRMWAREPREAMBLEHEADER2_0_SIZE) { if (VerifySignatureInside(preamble, preamble->preamble_size, sig)) {
VBDEBUG(("Not enough data for preamble header 2.0.\n")); VBDEBUG(("Preamble signature off end of preamble\n"));
return VBOOT_PREAMBLE_INVALID; 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 */ /* Make sure advertised signature data sizes are sane. */
if (VerifySignatureInside(preamble, preamble->preamble_size, sig)) { if (preamble->preamble_size < sig->data_size) {
VBDEBUG(("Preamble signature off end of preamble\n")); VBDEBUG(("Signature calculated past end of the block\n"));
return VBOOT_PREAMBLE_INVALID; return VBOOT_PREAMBLE_INVALID;
} }
/* Make sure advertised signature data sizes are sane. */ if (VerifyData((const uint8_t *)preamble, size, sig, key)) {
if (preamble->preamble_size < sig->data_size) { VBDEBUG(("Preamble signature validation failed\n"));
VBDEBUG(("Signature calculated past end of the block\n")); return VBOOT_PREAMBLE_SIGNATURE;
return VBOOT_PREAMBLE_INVALID; }
}
if (VerifyData((const uint8_t*)preamble, size, sig, key)) { /* Verify we signed enough data */
VBDEBUG(("Preamble signature validation failed\n")); if (sig->data_size < sizeof(VbFirmwarePreambleHeader)) {
return VBOOT_PREAMBLE_SIGNATURE; VBDEBUG(("Didn't sign enough data\n"));
} return VBOOT_PREAMBLE_INVALID;
}
/* Verify we signed enough data */ /* Verify body signature is inside the signed data */
if (sig->data_size < sizeof(VbFirmwarePreambleHeader)) { if (VerifySignatureInside(preamble, sig->data_size,
VBDEBUG(("Didn't sign enough data\n")); &preamble->body_signature)) {
return VBOOT_PREAMBLE_INVALID; VBDEBUG(("Firmware body signature off end of preamble\n"));
} return VBOOT_PREAMBLE_INVALID;
}
/* Verify body signature is inside the signed data */ /* Verify kernel subkey is inside the signed data */
if (VerifySignatureInside(preamble, sig->data_size, if (VerifyPublicKeyInside(preamble, sig->data_size,
&preamble->body_signature)) { &preamble->kernel_subkey)) {
VBDEBUG(("Firmware body signature off end of preamble\n")); VBDEBUG(("Kernel subkey off end of preamble\n"));
return VBOOT_PREAMBLE_INVALID; return VBOOT_PREAMBLE_INVALID;
} }
/* Verify kernel subkey is inside the signed data */ /*
if (VerifyPublicKeyInside(preamble, sig->data_size, * If the preamble header version is at least 2.1, verify we have space
&preamble->kernel_subkey)) { * for the added fields from 2.1.
VBDEBUG(("Kernel subkey off end of preamble\n")); */
return VBOOT_PREAMBLE_INVALID; 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;
}
}
/* If the preamble header version is at least 2.1, verify we have /* Success */
* space for the added fields from 2.1. */ return VBOOT_SUCCESS;
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;
}
uint32_t VbGetFirmwarePreambleFlags(const VbFirmwarePreambleHeader* preamble) { return preamble->flags;
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;
int VerifyKernelPreamble(const VbKernelPreambleHeader* preamble, /* Sanity checks before attempting signature of data */
uint64_t size, const RSAPublicKey* key) { 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;
}
const VbSignature* sig = &preamble->preamble_signature; /* 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;
}
/* Sanity checks before attempting signature of data */ /* Verify we signed enough data */
if(size < sizeof(VbKernelPreambleHeader)) { if (sig->data_size < sizeof(VbKernelPreambleHeader)) {
VBDEBUG(("Not enough data for preamble header.\n")); VBDEBUG(("Didn't sign enough data\n"));
return VBOOT_PREAMBLE_INVALID; 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 */ /* Verify body signature is inside the signed data */
if (VerifySignatureInside(preamble, preamble->preamble_size, sig)) { if (VerifySignatureInside(preamble, sig->data_size,
VBDEBUG(("Preamble signature off end of preamble\n")); &preamble->body_signature)) {
return VBOOT_PREAMBLE_INVALID; VBDEBUG(("Kernel body 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 */ /* Success */
if (sig->data_size < sizeof(VbKernelPreambleHeader)) { return VBOOT_SUCCESS;
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)));
int VbSharedDataInit(VbSharedDataHeader* header, uint64_t size) { 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;
}
VBDEBUG(("VbSharedDataInit, %d bytes, header %d bytes\n", (int)size, if (!header)
sizeof(VbSharedDataHeader))); return VBOOT_SHARED_DATA_INVALID;
if (size < sizeof(VbSharedDataHeader)) { /* Zero the header */
VBDEBUG(("Not enough data for header.\n")); Memset(header, 0, sizeof(VbSharedDataHeader));
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) /* Initialize fields */
return VBOOT_SHARED_DATA_INVALID; 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;
/* Zero the header */ /* Success */
Memset(header, 0, sizeof(VbSharedDataHeader)); return VBOOT_SUCCESS;
/* 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) { VBDEBUG(("VbSharedDataReserve %d bytes at %d\n", (int)size, (int)offs));
uint64_t offs = header->data_used;
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"));
if (!header || size > header->data_size - header->data_used) { return 0; /* Not initialized, or not enough space left. */
VBDEBUG(("VbSharedData buffer out of space.\n")); }
return 0; /* Not initialized, or not enough space left. */ header->data_used += size;
} return offs;
header->data_used += size;
return offs;
} }
int VbSharedDataSetKernelKey(VbSharedDataHeader *header, const VbPublicKey *src)
{
VbPublicKey *kdest = &header->kernel_subkey;
int VbSharedDataSetKernelKey(VbSharedDataHeader* header, if (!header)
const VbPublicKey* src) { return VBOOT_SHARED_DATA_INVALID;
VbPublicKey *kdest = &header->kernel_subkey; /* 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;
}
if (!header) /* Copy the kernel sign key blob into the destination buffer */
return VBOOT_SHARED_DATA_INVALID; PublicKeyInit(kdest,
(uint8_t *)header + header->kernel_subkey_data_offset,
header->kernel_subkey_data_size);
/* Attempt to allocate space for the key, if it hasn't been allocated yet */ return PublicKeyCopy(kdest, src);
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);
return PublicKeyCopy(kdest, src);
} }

View File

@@ -16,267 +16,273 @@
#include "vboot_common.h" #include "vboot_common.h"
static void ReChecksumKeyBlock(VbKeyBlockHeader *h) { static void ReChecksumKeyBlock(VbKeyBlockHeader *h)
uint8_t* newchk = DigestBuf((const uint8_t*)h, {
h->key_block_checksum.data_size, uint8_t *newchk = DigestBuf((const uint8_t *)h,
SHA512_DIGEST_ALGORITHM); h->key_block_checksum.data_size,
Memcpy(GetSignatureData(&h->key_block_checksum), newchk, SHA512_DIGEST_SIZE); SHA512_DIGEST_ALGORITHM);
free(newchk); 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;
static void KeyBlockVerifyTest(const VbPublicKey* public_key, hdr = KeyBlockCreate(data_key, private_key, 0x1234);
const VbPrivateKey* private_key, TEST_NEQ((size_t)hdr, 0, "KeyBlockVerify() prerequisites");
const VbPublicKey* data_key) { if (!hdr)
return;
hsize = (unsigned) hdr->key_block_size;
h = (VbKeyBlockHeader *)malloc(hsize + 1024);
VbKeyBlockHeader *hdr; TEST_EQ(KeyBlockVerify(hdr, hsize, NULL, 1), 0,
VbKeyBlockHeader *h; "KeyBlockVerify() ok using checksum");
unsigned hsize; TEST_EQ(KeyBlockVerify(hdr, hsize, public_key, 0), 0,
"KeyBlockVerify() ok using key");
TEST_NEQ(KeyBlockVerify(hdr, hsize, NULL, 0), 0,
"KeyBlockVerify() missing key");
hdr = KeyBlockCreate(data_key, private_key, 0x1234); TEST_NEQ(KeyBlockVerify(hdr, hsize - 1, NULL, 1), 0,
TEST_NEQ((size_t)hdr, 0, "KeyBlockVerify() prerequisites"); "KeyBlockVerify() size--");
if (!hdr) TEST_EQ(KeyBlockVerify(hdr, hsize + 1, NULL, 1), 0,
return; "KeyBlockVerify() size++");
hsize = (unsigned) hdr->key_block_size;
h = (VbKeyBlockHeader*)malloc(hsize + 1024);
TEST_EQ(KeyBlockVerify(hdr, hsize, NULL, 1), 0, Memcpy(h, hdr, hsize);
"KeyBlockVerify() ok using checksum"); h->magic[0] &= 0x12;
TEST_EQ(KeyBlockVerify(hdr, hsize, public_key, 0), 0, TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0,
"KeyBlockVerify() ok using key"); "KeyBlockVerify() magic");
TEST_NEQ(KeyBlockVerify(hdr, hsize, NULL, 0), 0,
"KeyBlockVerify() missing key");
TEST_NEQ(KeyBlockVerify(hdr, hsize - 1, NULL, 1), 0, /* Care about major version but not minor */
"KeyBlockVerify() size--"); Memcpy(h, hdr, hsize);
TEST_EQ(KeyBlockVerify(hdr, hsize + 1, NULL, 1), 0, h->header_version_major++;
"KeyBlockVerify() size++"); ReChecksumKeyBlock(h);
TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0,
"KeyBlockVerify() major++");
Memcpy(h, hdr, hsize); Memcpy(h, hdr, hsize);
h->magic[0] &= 0x12; h->header_version_major--;
TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0, "KeyBlockVerify() magic"); ReChecksumKeyBlock(h);
TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0,
"KeyBlockVerify() major--");
/* Care about major version but not minor */ Memcpy(h, hdr, hsize);
Memcpy(h, hdr, hsize); h->header_version_minor++;
h->header_version_major++; ReChecksumKeyBlock(h);
ReChecksumKeyBlock(h); TEST_EQ(KeyBlockVerify(h, hsize, NULL, 1), 0,
TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0, "KeyBlockVerify() major++"); "KeyBlockVerify() minor++");
Memcpy(h, hdr, hsize); Memcpy(h, hdr, hsize);
h->header_version_major--; h->header_version_minor--;
ReChecksumKeyBlock(h); ReChecksumKeyBlock(h);
TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0, "KeyBlockVerify() major--"); TEST_EQ(KeyBlockVerify(h, hsize, NULL, 1), 0,
"KeyBlockVerify() minor--");
Memcpy(h, hdr, hsize); /* Check hash */
h->header_version_minor++; Memcpy(h, hdr, hsize);
ReChecksumKeyBlock(h); h->key_block_checksum.sig_offset = hsize;
TEST_EQ(KeyBlockVerify(h, hsize, NULL, 1), 0, "KeyBlockVerify() minor++"); ReChecksumKeyBlock(h);
TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0,
"KeyBlockVerify() checksum off end");
Memcpy(h, hdr, hsize); Memcpy(h, hdr, hsize);
h->header_version_minor--; h->key_block_checksum.sig_size /= 2;
ReChecksumKeyBlock(h); ReChecksumKeyBlock(h);
TEST_EQ(KeyBlockVerify(h, hsize, NULL, 1), 0, "KeyBlockVerify() minor--"); TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0,
"KeyBlockVerify() checksum too small");
/* Check hash */ Memcpy(h, hdr, hsize);
Memcpy(h, hdr, hsize); GetPublicKeyData(&h->data_key)[0] ^= 0x34;
h->key_block_checksum.sig_offset = hsize; TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0,
ReChecksumKeyBlock(h); "KeyBlockVerify() checksum mismatch");
TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0,
"KeyBlockVerify() checksum off end");
Memcpy(h, hdr, hsize); /* Check signature */
h->key_block_checksum.sig_size /= 2; Memcpy(h, hdr, hsize);
ReChecksumKeyBlock(h); h->key_block_signature.sig_offset = hsize;
TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0, ReChecksumKeyBlock(h);
"KeyBlockVerify() checksum too small"); TEST_NEQ(KeyBlockVerify(h, hsize, public_key, 0), 0,
"KeyBlockVerify() sig off end");
Memcpy(h, hdr, hsize); Memcpy(h, hdr, hsize);
GetPublicKeyData(&h->data_key)[0] ^= 0x34; h->key_block_signature.sig_size--;
TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0, ReChecksumKeyBlock(h);
"KeyBlockVerify() checksum mismatch"); TEST_NEQ(KeyBlockVerify(h, hsize, public_key, 0), 0,
"KeyBlockVerify() sig too small");
/* Check signature */ Memcpy(h, hdr, hsize);
Memcpy(h, hdr, hsize); GetPublicKeyData(&h->data_key)[0] ^= 0x34;
h->key_block_signature.sig_offset = hsize; TEST_NEQ(KeyBlockVerify(h, hsize, public_key, 0), 0,
ReChecksumKeyBlock(h); "KeyBlockVerify() sig mismatch");
TEST_NEQ(KeyBlockVerify(h, hsize, public_key, 0), 0,
"KeyBlockVerify() sig off end");
Memcpy(h, hdr, hsize); Memcpy(h, hdr, hsize);
h->key_block_signature.sig_size--; h->key_block_checksum.data_size = h->key_block_size + 1;
ReChecksumKeyBlock(h); TEST_NEQ(KeyBlockVerify(h, hsize, public_key, 1), 0,
TEST_NEQ(KeyBlockVerify(h, hsize, public_key, 0), 0, "KeyBlockVerify() checksum data past end of block");
"KeyBlockVerify() sig too small");
Memcpy(h, hdr, hsize); /* Check that we signed header and data key */
GetPublicKeyData(&h->data_key)[0] ^= 0x34; Memcpy(h, hdr, hsize);
TEST_NEQ(KeyBlockVerify(h, hsize, public_key, 0), 0, h->key_block_checksum.data_size = 4;
"KeyBlockVerify() sig mismatch"); 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); Memcpy(h, hdr, hsize);
//ReChecksumKeyBlock(h); h->data_key.key_offset = hsize;
h->key_block_checksum.data_size = h->key_block_size + 1; ReChecksumKeyBlock(h);
TEST_NEQ(KeyBlockVerify(h, hsize, public_key, 1), 0, TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0,
"KeyBlockVerify() checksum data past end of block"); "KeyBlockVerify() data key off end");
/* Check that we signed header and data key */ /* Corner cases for error checking */
Memcpy(h, hdr, hsize); TEST_NEQ(KeyBlockVerify(NULL, 4, NULL, 1), 0,
h->key_block_checksum.data_size = 4; "KeyBlockVerify size too small");
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; * TODO: verify parser can support a bigger header (i.e., one where
ReChecksumKeyBlock(h); * data_key.key_offset is bigger than expected).
TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0, */
"KeyBlockVerify() data key off end");
/* Corner cases for error checking */ free(h);
TEST_NEQ(KeyBlockVerify(NULL, 4, NULL, 1), 0, free(hdr);
"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, SignatureCopy(&h->preamble_signature, sig);
const VbPrivateKey* key) { free(sig);
VbSignature *sig = CalculateSignature((const uint8_t*)h,
h->preamble_signature.data_size, key);
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;
static void VerifyFirmwarePreambleTest(const VbPublicKey* public_key, /* Create a dummy signature */
const VbPrivateKey* private_key, VbSignature* body_sig = SignatureAlloc(56, 78);
const VbPublicKey* kernel_subkey) {
VbFirmwarePreambleHeader* hdr; rsa = PublicKeyToRSA(public_key);
VbFirmwarePreambleHeader* h; hdr = CreateFirmwarePreamble(0x1234, kernel_subkey, body_sig,
RSAPublicKey* rsa; private_key, 0x5678);
unsigned hsize; TEST_NEQ(hdr && rsa, 0, "VerifyFirmwarePreamble() prerequisites");
if (!hdr)
return;
hsize = (unsigned) hdr->preamble_size;
h = (VbFirmwarePreambleHeader *)malloc(hsize + 16384);
/* Create a dummy signature */ TEST_EQ(VerifyFirmwarePreamble(hdr, hsize, rsa), 0,
VbSignature* body_sig = SignatureAlloc(56, 78); "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++");
rsa = PublicKeyToRSA(public_key); /* Care about major version but not minor */
hdr = CreateFirmwarePreamble(0x1234, kernel_subkey, body_sig, private_key, Memcpy(h, hdr, hsize);
0x5678); h->header_version_major++;
TEST_NEQ(hdr && rsa, 0, "VerifyFirmwarePreamble() prerequisites"); ReSignFirmwarePreamble(h, private_key);
if (!hdr) TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0,
return; "VerifyFirmwarePreamble() major++");
hsize = (unsigned) hdr->preamble_size;
h = (VbFirmwarePreambleHeader*)malloc(hsize + 16384);
TEST_EQ(VerifyFirmwarePreamble(hdr, hsize, rsa), 0, Memcpy(h, hdr, hsize);
"VerifyFirmwarePreamble() ok using key"); h->header_version_major--;
TEST_NEQ(VerifyFirmwarePreamble(hdr, 4, rsa), 0, ReSignFirmwarePreamble(h, private_key);
"VerifyFirmwarePreamble() size tiny"); TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0,
TEST_NEQ(VerifyFirmwarePreamble(hdr, hsize - 1, rsa), 0, "VerifyFirmwarePreamble() major--");
"VerifyFirmwarePreamble() size--");
TEST_EQ(VerifyFirmwarePreamble(hdr, hsize + 1, rsa), 0,
"VerifyFirmwarePreamble() size++");
/* Care about major version but not minor */ Memcpy(h, hdr, hsize);
Memcpy(h, hdr, hsize); h->header_version_minor++;
h->header_version_major++; ReSignFirmwarePreamble(h, private_key);
ReSignFirmwarePreamble(h, private_key); TEST_EQ(VerifyFirmwarePreamble(h, hsize, rsa), 0,
TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0, "VerifyFirmwarePreamble() minor++");
"VerifyFirmwarePreamble() major++");
Memcpy(h, hdr, hsize); Memcpy(h, hdr, hsize);
h->header_version_major--; h->header_version_minor--;
ReSignFirmwarePreamble(h, private_key); ReSignFirmwarePreamble(h, private_key);
TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0, TEST_EQ(VerifyFirmwarePreamble(h, hsize, rsa), 0,
"VerifyFirmwarePreamble() major--"); "VerifyFirmwarePreamble() minor--");
Memcpy(h, hdr, hsize); /* Check signature */
h->header_version_minor++; Memcpy(h, hdr, hsize);
ReSignFirmwarePreamble(h, private_key); h->preamble_signature.sig_offset = hsize;
TEST_EQ(VerifyFirmwarePreamble(h, hsize, rsa), 0, ReSignFirmwarePreamble(h, private_key);
"VerifyFirmwarePreamble() minor++"); TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0,
"VerifyFirmwarePreamble() sig off end");
Memcpy(h, hdr, hsize); Memcpy(h, hdr, hsize);
h->header_version_minor--; h->preamble_signature.sig_size--;
ReSignFirmwarePreamble(h, private_key); ReSignFirmwarePreamble(h, private_key);
TEST_EQ(VerifyFirmwarePreamble(h, hsize, rsa), 0, TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0,
"VerifyFirmwarePreamble() minor--"); "VerifyFirmwarePreamble() sig too small");
/* Check signature */ Memcpy(h, hdr, hsize);
Memcpy(h, hdr, hsize); GetPublicKeyData(&h->kernel_subkey)[0] ^= 0x34;
h->preamble_signature.sig_offset = hsize; TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0,
ReSignFirmwarePreamble(h, private_key); "VerifyFirmwarePreamble() sig mismatch");
TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0,
"VerifyFirmwarePreamble() sig off end");
Memcpy(h, hdr, hsize); /* Check that we signed header, kernel subkey, and body sig */
h->preamble_signature.sig_size--; Memcpy(h, hdr, hsize);
ReSignFirmwarePreamble(h, private_key); h->preamble_signature.data_size = 4;
TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0, h->kernel_subkey.key_offset = 0;
"VerifyFirmwarePreamble() sig too small"); 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); Memcpy(h, hdr, hsize);
GetPublicKeyData(&h->kernel_subkey)[0] ^= 0x34; h->kernel_subkey.key_offset = hsize;
TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0, ReSignFirmwarePreamble(h, private_key);
"VerifyFirmwarePreamble() sig mismatch"); TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0,
"VerifyFirmwarePreamble() kernel subkey off end");
/* Check that we signed header, kernel subkey, and body sig */ Memcpy(h, hdr, hsize);
Memcpy(h, hdr, hsize); h->body_signature.sig_offset = hsize;
h->preamble_signature.data_size = 4; ReSignFirmwarePreamble(h, private_key);
h->kernel_subkey.key_offset = 0; TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0,
h->kernel_subkey.key_size = 0; "VerifyFirmwarePreamble() body sig off end");
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); /* Check that we return flags properly for new and old structs */
h->kernel_subkey.key_offset = hsize; Memcpy(h, hdr, hsize);
ReSignFirmwarePreamble(h, private_key); TEST_EQ(VbGetFirmwarePreambleFlags(h), 0x5678,
TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0, "VbGetFirmwarePreambleFlags() v2.1");
"VerifyFirmwarePreamble() kernel subkey off end"); h->header_version_minor = 0;
TEST_EQ(VbGetFirmwarePreambleFlags(h), 0,
"VbGetFirmwarePreambleFlags() v2.0");
Memcpy(h, hdr, hsize); /* TODO: verify with extra padding at end of header. */
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 */ free(h);
Memcpy(h, hdr, hsize); RSAPublicKeyFree(rsa);
TEST_EQ(VbGetFirmwarePreambleFlags(h), 0x5678, free(hdr);
"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, int test_permutation(int signing_key_algorithm, int data_key_algorithm,
const char *keys_dir) const char *keys_dir)
{ {
char filename[1024]; char filename[1024];
int signing_rsa_len = siglen_map[signing_key_algorithm] * 8;; int signing_rsa_len = siglen_map[signing_key_algorithm] * 8;
int data_rsa_len = siglen_map[data_key_algorithm] * 8;; int data_rsa_len = siglen_map[data_key_algorithm] * 8;
VbPrivateKey* signing_private_key = NULL; VbPrivateKey *signing_private_key = NULL;
VbPublicKey* signing_public_key = NULL; VbPublicKey *signing_public_key = NULL;
VbPublicKey* data_public_key = NULL; VbPublicKey *data_public_key = NULL;
printf("***Testing signing algorithm: %s\n", printf("***Testing signing algorithm: %s\n",
algo_strings[signing_key_algorithm]); algo_strings[signing_key_algorithm]);
@@ -339,7 +345,7 @@ struct test_perm
*/ */
const struct test_perm test_perms[] = {{7, 4}, {11, 4}, {11, 7}}; 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) { if (argc == 2) {
/* Test only the algorithms we use */ /* Test only the algorithms we use */