mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-11-01 19:07:51 +00:00
firmware/coreboot: Subtree merged vboot
Signed-off-by: David Hendricks <dhendricks@fb.com>
This commit is contained in:
1
firmware/coreboot/3rdparty/vboot
vendored
1
firmware/coreboot/3rdparty/vboot
vendored
Submodule firmware/coreboot/3rdparty/vboot deleted from 392211f035
10
firmware/coreboot/3rdparty/vboot/.gitignore
vendored
Normal file
10
firmware/coreboot/3rdparty/vboot/.gitignore
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
/build
|
||||||
|
/build-au
|
||||||
|
/build-main
|
||||||
|
ID
|
||||||
|
scripts/newbitmaps/default_source/*.bmp
|
||||||
|
scripts/newbitmaps/images/out_*
|
||||||
|
scripts/newbitmaps/lib/*.pyc
|
||||||
|
scripts/newbitmaps/strings/font
|
||||||
|
scripts/newbitmaps/strings/*.png
|
||||||
|
scripts/newbitmaps/strings/localized_text/*/*.png
|
||||||
175
firmware/coreboot/3rdparty/vboot/Android.mk
vendored
Normal file
175
firmware/coreboot/3rdparty/vboot/Android.mk
vendored
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
# Copyright 2015 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.
|
||||||
|
|
||||||
|
# Minimal makefile capable of compiling futility to sign images
|
||||||
|
|
||||||
|
LOCAL_PATH := $(call my-dir)
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_MODULE := libvboot_util-host
|
||||||
|
|
||||||
|
ifeq ($(HOST_OS),darwin)
|
||||||
|
LOCAL_CFLAGS += -DHAVE_MACOS
|
||||||
|
endif
|
||||||
|
|
||||||
|
# These are required to access large disks and files on 32-bit systems.
|
||||||
|
LOCAL_CFLAGS += -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64
|
||||||
|
|
||||||
|
LOCAL_C_INCLUDES += \
|
||||||
|
$(LOCAL_PATH)/firmware/include \
|
||||||
|
$(LOCAL_PATH)/firmware/lib/include \
|
||||||
|
$(LOCAL_PATH)/firmware/lib/cgptlib/include \
|
||||||
|
$(LOCAL_PATH)/firmware/lib/cryptolib/include \
|
||||||
|
$(LOCAL_PATH)/firmware/lib/tpm_lite/include \
|
||||||
|
$(LOCAL_PATH)/firmware/2lib/include \
|
||||||
|
$(LOCAL_PATH)/host/include \
|
||||||
|
$(LOCAL_PATH)/host/lib/include
|
||||||
|
|
||||||
|
# Firmware library sources needed by VbInit() call
|
||||||
|
VBINIT_SRCS = \
|
||||||
|
firmware/lib/crc8.c \
|
||||||
|
firmware/lib/utility.c \
|
||||||
|
firmware/lib/vboot_api_init.c \
|
||||||
|
firmware/lib/vboot_common_init.c \
|
||||||
|
firmware/lib/region-init.c \
|
||||||
|
|
||||||
|
# Additional firmware library sources needed by VbSelectFirmware() call
|
||||||
|
VBSF_SRCS = \
|
||||||
|
firmware/lib/cryptolib/padding.c \
|
||||||
|
firmware/lib/cryptolib/rsa.c \
|
||||||
|
firmware/lib/cryptolib/rsa_utility.c \
|
||||||
|
firmware/lib/cryptolib/sha1.c \
|
||||||
|
firmware/lib/cryptolib/sha256.c \
|
||||||
|
firmware/lib/cryptolib/sha512.c \
|
||||||
|
firmware/lib/cryptolib/sha_utility.c \
|
||||||
|
firmware/lib/stateful_util.c \
|
||||||
|
firmware/lib/vboot_common.c \
|
||||||
|
firmware/lib/region-fw.c \
|
||||||
|
|
||||||
|
# Additional firmware library sources needed by VbSelectAndLoadKernel() call
|
||||||
|
VBSLK_SRCS = \
|
||||||
|
firmware/lib/cgptlib/cgptlib.c \
|
||||||
|
firmware/lib/cgptlib/cgptlib_internal.c \
|
||||||
|
firmware/lib/cgptlib/crc32.c \
|
||||||
|
firmware/lib/gpt_misc.c \
|
||||||
|
firmware/lib/utility_string.c \
|
||||||
|
firmware/lib/vboot_api_kernel.c \
|
||||||
|
firmware/lib/vboot_audio.c \
|
||||||
|
firmware/lib/vboot_display.c \
|
||||||
|
firmware/lib/vboot_kernel.c \
|
||||||
|
firmware/lib/region-kernel.c \
|
||||||
|
|
||||||
|
VBINIT_SRCS += \
|
||||||
|
firmware/stub/tpm_lite_stub.c \
|
||||||
|
firmware/stub/utility_stub.c \
|
||||||
|
firmware/stub/vboot_api_stub_init.c \
|
||||||
|
firmware/stub/vboot_api_stub_region.c
|
||||||
|
|
||||||
|
VBSF_SRCS += \
|
||||||
|
firmware/stub/vboot_api_stub_sf.c
|
||||||
|
|
||||||
|
VBSLK_SRCS += \
|
||||||
|
firmware/stub/vboot_api_stub.c \
|
||||||
|
firmware/stub/vboot_api_stub_disk.c \
|
||||||
|
firmware/stub/vboot_api_stub_stream.c
|
||||||
|
|
||||||
|
UTILLIB_SRCS = \
|
||||||
|
cgpt/cgpt_create.c \
|
||||||
|
cgpt/cgpt_add.c \
|
||||||
|
cgpt/cgpt_boot.c \
|
||||||
|
cgpt/cgpt_show.c \
|
||||||
|
cgpt/cgpt_repair.c \
|
||||||
|
cgpt/cgpt_prioritize.c \
|
||||||
|
cgpt/cgpt_common.c \
|
||||||
|
futility/dump_kernel_config_lib.c \
|
||||||
|
host/lib/crossystem.c \
|
||||||
|
host/lib/file_keys.c \
|
||||||
|
host/lib/fmap.c \
|
||||||
|
host/lib/host_common.c \
|
||||||
|
host/lib/host_key.c \
|
||||||
|
host/lib/host_keyblock.c \
|
||||||
|
host/lib/host_misc.c \
|
||||||
|
host/lib/util_misc.c \
|
||||||
|
host/lib/host_signature.c \
|
||||||
|
host/lib/signature_digest.c
|
||||||
|
|
||||||
|
# host/arch/${HOST_ARCH}/lib/crossystem_arch.c \
|
||||||
|
|
||||||
|
LOCAL_SRC_FILES := \
|
||||||
|
$(VBINIT_SRCS) \
|
||||||
|
$(VBSF_SRCS) \
|
||||||
|
$(VBSLK_SRCS) \
|
||||||
|
$(UTILLIB_SRCS)
|
||||||
|
|
||||||
|
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_C_INCLUDES)
|
||||||
|
LOCAL_STATIC_LIBRARIES := libcrypto_static
|
||||||
|
|
||||||
|
include $(BUILD_HOST_STATIC_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_MODULE := futility-host
|
||||||
|
LOCAL_IS_HOST_MODULE := true
|
||||||
|
LOCAL_MODULE_CLASS := EXECUTABLES
|
||||||
|
generated_sources := $(call local-generated-sources-dir)
|
||||||
|
|
||||||
|
ifeq ($(HOST_OS),darwin)
|
||||||
|
LOCAL_CFLAGS += -DHAVE_MACOS
|
||||||
|
endif
|
||||||
|
|
||||||
|
# These are required to access large disks and files on 32-bit systems.
|
||||||
|
LOCAL_CFLAGS += -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64
|
||||||
|
|
||||||
|
FUTIL_STATIC_SRCS = \
|
||||||
|
futility/futility.c \
|
||||||
|
futility/cmd_dump_fmap.c \
|
||||||
|
futility/cmd_gbb_utility.c \
|
||||||
|
futility/misc.c
|
||||||
|
|
||||||
|
FUTIL_SRCS = \
|
||||||
|
${FUTIL_STATIC_SRCS} \
|
||||||
|
futility/cmd_dump_kernel_config.c \
|
||||||
|
futility/cmd_load_fmap.c \
|
||||||
|
futility/cmd_pcr.c \
|
||||||
|
futility/cmd_show.c \
|
||||||
|
futility/cmd_sign.c \
|
||||||
|
futility/cmd_vbutil_firmware.c \
|
||||||
|
futility/cmd_vbutil_kernel.c \
|
||||||
|
futility/cmd_vbutil_key.c \
|
||||||
|
futility/cmd_vbutil_keyblock.c \
|
||||||
|
futility/file_type.c \
|
||||||
|
futility/traversal.c \
|
||||||
|
futility/vb1_helper.c
|
||||||
|
|
||||||
|
# ${FUTIL_STATIC_WORKAROUND_SRCS:%.c=${BUILD}/%.o} \
|
||||||
|
|
||||||
|
LOCAL_SRC_FILES := \
|
||||||
|
$(FUTIL_SRCS) \
|
||||||
|
|
||||||
|
$(generated_sources)/futility_cmds.c: ${FUTIL_SRCS:%=${LOCAL_PATH}/%}
|
||||||
|
@echo making $< from ${FUTIL_SRCS}
|
||||||
|
@rm -f $@ $@_t $@_commands
|
||||||
|
@mkdir -p $(dir $@)
|
||||||
|
@grep -hoRE '^DECLARE_FUTIL_COMMAND\([^,]+' $^ \
|
||||||
|
| sed 's/DECLARE_FUTIL_COMMAND(\(.*\)/_CMD(\1)/' \
|
||||||
|
| sort >>$@_commands
|
||||||
|
@external/vboot_reference/scripts/getversion.sh >> $@_t
|
||||||
|
@echo '#define _CMD(NAME) extern const struct' \
|
||||||
|
'futil_cmd_t __cmd_##NAME;' >> $@_t
|
||||||
|
@cat $@_commands >> $@_t
|
||||||
|
@echo '#undef _CMD' >> $@_t
|
||||||
|
@echo '#define _CMD(NAME) &__cmd_##NAME,' >> $@_t
|
||||||
|
@echo 'const struct futil_cmd_t *const futil_cmds[] = {' >> $@_t
|
||||||
|
@cat $@_commands >> $@_t
|
||||||
|
@echo '0}; /* null-terminated */' >> $@_t
|
||||||
|
@echo '#undef _CMD' >> $@_t
|
||||||
|
@mv $@_t $@
|
||||||
|
@rm -f $@_commands
|
||||||
|
|
||||||
|
LOCAL_GENERATED_SOURCES := $(generated_sources)/futility_cmds.c
|
||||||
|
|
||||||
|
LOCAL_STATIC_LIBRARIES := libvboot_util-host
|
||||||
|
LOCAL_SHARED_LIBRARIES := libcrypto-host
|
||||||
|
include $(BUILD_HOST_EXECUTABLE)
|
||||||
|
|
||||||
27
firmware/coreboot/3rdparty/vboot/LICENSE
vendored
Normal file
27
firmware/coreboot/3rdparty/vboot/LICENSE
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
1551
firmware/coreboot/3rdparty/vboot/Makefile
vendored
Normal file
1551
firmware/coreboot/3rdparty/vboot/Makefile
vendored
Normal file
File diff suppressed because it is too large
Load Diff
7
firmware/coreboot/3rdparty/vboot/PRESUBMIT.cfg
vendored
Normal file
7
firmware/coreboot/3rdparty/vboot/PRESUBMIT.cfg
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
[Hook Overrides]
|
||||||
|
branch_check: true
|
||||||
|
|
||||||
|
# We are using Linux style indentation with tabs
|
||||||
|
# The indentation is checked by checkpatch not the python script
|
||||||
|
tab_check: false
|
||||||
|
|
||||||
174
firmware/coreboot/3rdparty/vboot/README
vendored
Normal file
174
firmware/coreboot/3rdparty/vboot/README
vendored
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
This directory contains a reference implementation for Chrome OS
|
||||||
|
verified boot in firmware.
|
||||||
|
|
||||||
|
----------
|
||||||
|
Directory Structure
|
||||||
|
----------
|
||||||
|
|
||||||
|
The source is organized into distinct modules -
|
||||||
|
|
||||||
|
firmware/
|
||||||
|
|
||||||
|
Contains ONLY the code required by the BIOS to validate the secure boot
|
||||||
|
components. There shouldn't be any code in here that signs or generates
|
||||||
|
images. BIOS should require ONLY this directory to implement secure boot.
|
||||||
|
Refer to firmware/README for futher details.
|
||||||
|
|
||||||
|
cgpt/
|
||||||
|
|
||||||
|
Utility to read/write/modify GPT partitions. Similar to GNU parted or any
|
||||||
|
other GPT tool, but this has support for Chrome OS extensions.
|
||||||
|
|
||||||
|
host/
|
||||||
|
|
||||||
|
Miscellaneous functions needed by userland utilities.
|
||||||
|
|
||||||
|
futility/
|
||||||
|
|
||||||
|
The "firmware utility" tool, used to create, sign, and validate Chrome OS
|
||||||
|
images.
|
||||||
|
|
||||||
|
utility/
|
||||||
|
|
||||||
|
Random other utilities, not necesssarily related to verified boot as such.
|
||||||
|
|
||||||
|
tests/
|
||||||
|
|
||||||
|
User-land tests and benchmarks that test the reference implementation.
|
||||||
|
Please have a look at these if you'd like to understand how to use the
|
||||||
|
reference implementation.
|
||||||
|
|
||||||
|
build/
|
||||||
|
|
||||||
|
The output directory where the generated files will be placed, and where
|
||||||
|
tests are run.
|
||||||
|
|
||||||
|
scripts/
|
||||||
|
|
||||||
|
Tools and scripts used to generate and use new signing keypairs. These are
|
||||||
|
typically used only on a secure machine.
|
||||||
|
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
Building and testing
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
The suite can be built on the host or in the chroot environment.
|
||||||
|
|
||||||
|
Building on the host could fail if certain packages are not installed. If
|
||||||
|
there are host environment build problems due to missing .h files, try
|
||||||
|
researching what packages the files belong to and install the missing packages
|
||||||
|
before reporting a problem.
|
||||||
|
|
||||||
|
|
||||||
|
The commands are the more-or-less expected ones:
|
||||||
|
|
||||||
|
make
|
||||||
|
make runtests
|
||||||
|
make install [ DESTDIR=/usr/local ]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
----------
|
||||||
|
Some useful utilities:
|
||||||
|
----------
|
||||||
|
|
||||||
|
futility vbutil_key Convert a public key into .vbpubk format
|
||||||
|
futility vbutil_keyblock Wrap a public key inside a signature and checksum
|
||||||
|
futility vbutil_firmware Create a .vblock with signature info for a
|
||||||
|
firmware image
|
||||||
|
futility vbutil_kernel Pack a kernel image, bootloader, and config into
|
||||||
|
a signed binary
|
||||||
|
|
||||||
|
dumpRSAPublicKey Dump RSA Public key (from a DER-encoded X509
|
||||||
|
certificate) in a format suitable for use by
|
||||||
|
RSAVerify* functions in crypto/.
|
||||||
|
|
||||||
|
verify_data.c Verify a given signature on a given file.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
----------
|
||||||
|
Generating a signed firmware image:
|
||||||
|
----------
|
||||||
|
|
||||||
|
* Step 0: Build the tools, install them somewhere.
|
||||||
|
|
||||||
|
* Step 1: Generate RSA root and signing keys.
|
||||||
|
|
||||||
|
The root key is always 8192 bits.
|
||||||
|
|
||||||
|
$ openssl genrsa -F4 -out root_key.pem 8192
|
||||||
|
|
||||||
|
The signing key can be between 1024-8192 bits.
|
||||||
|
|
||||||
|
$ openssl genrsa -F4 -out signing_key.pem <1024|2048|4096|8192>
|
||||||
|
|
||||||
|
Note: The -F4 option must be specified to generate RSA keys with a public
|
||||||
|
exponent of 65535. RSA keys with 3 as a public exponent (the default)
|
||||||
|
won't work.
|
||||||
|
|
||||||
|
* Step 2: Generate pre-processed public versions of the above keys using
|
||||||
|
dumpRSAPublicKey. This utility expects an x509 certificate as
|
||||||
|
input, and emits an intermediate representation for further
|
||||||
|
processing.
|
||||||
|
|
||||||
|
$ openssl req -batch -new -x509 -key root_key.pem -out root_key.crt
|
||||||
|
$ openssl req -batch -new -x509 -key signing_key.pem -out signing_key.crt
|
||||||
|
$ dumpRSAPublicKey root_key.crt > root_key.keyb
|
||||||
|
$ dumpRSAPublicKey signing_key.crt > signing_key.keyb
|
||||||
|
|
||||||
|
************** TODO: STUFF PAST HERE IS OUT OF DATE ***************
|
||||||
|
|
||||||
|
At this point we have all the requisite keys needed to generate a signed
|
||||||
|
firmware image.
|
||||||
|
|
||||||
|
.pem RSA Public/Private Key Pair
|
||||||
|
.crt X509 Key Certificate
|
||||||
|
.keyb Pre-processed RSA Public Key
|
||||||
|
|
||||||
|
|
||||||
|
* Step 3: Use utility/firmware_utility to generate a signed firmare blob.
|
||||||
|
|
||||||
|
$ utility/firmware_utility --generate \
|
||||||
|
--root_key root_key.pem \
|
||||||
|
--firmware_sign_key signing_key.pem \
|
||||||
|
--firmware_sign_key_pub signing_key.keyb \
|
||||||
|
--firmware_sign_algorithm <algoid> \
|
||||||
|
--firmware_key_version 1 \
|
||||||
|
--firmware_version 1 \
|
||||||
|
--in <firmware blob file> \
|
||||||
|
--out <output file>
|
||||||
|
|
||||||
|
Where <algoid> is based on the signature algorithm to use for firmware
|
||||||
|
signining. The list of <algoid> specifications can be output by running
|
||||||
|
'utility/firmware_utility' without any arguments.
|
||||||
|
|
||||||
|
Note: --firmware_key_version and --firmware_version are part of a signed
|
||||||
|
image and are used to prevent rollbacks to older version. For testing,
|
||||||
|
they can just be set to valid values.
|
||||||
|
|
||||||
|
|
||||||
|
* Step 4: Verify that this image verifies.
|
||||||
|
|
||||||
|
$ utility/firmware_utility --verify \
|
||||||
|
--in <signed firmware image>
|
||||||
|
--root_key_pub root_key.keyb
|
||||||
|
Verification SUCCESS.
|
||||||
|
|
||||||
|
|
||||||
|
Note: The verification functions expects a pointer to the
|
||||||
|
pre-processed public root key as input. For testing purposes,
|
||||||
|
root_key.keyb can be stored in RW part of the firmware. For the
|
||||||
|
final firmware, this will be a fixed public key which cannot be
|
||||||
|
changed and must be stored in RO firmware.
|
||||||
|
|
||||||
|
----------
|
||||||
|
Generating a signed kernel image:
|
||||||
|
----------
|
||||||
|
|
||||||
|
The steps for generating a signed kernel image are similar to that of
|
||||||
|
a firmware image. Since verification is chained - RO firmware verifies
|
||||||
|
RW firmware which verifies the kernel, only the keys change. An additional
|
||||||
|
kernel signing key must be generated. The firmware signing generated above
|
||||||
|
is the root key equivalent for signed kernel images.
|
||||||
14
firmware/coreboot/3rdparty/vboot/WATCHLISTS
vendored
Normal file
14
firmware/coreboot/3rdparty/vboot/WATCHLISTS
vendored
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# See http://dev.chromium.org/developers/contributing-code/watchlists for
|
||||||
|
# a description of this file's format.
|
||||||
|
# Please keep these keys in alphabetical order.
|
||||||
|
|
||||||
|
{
|
||||||
|
'WATCHLIST_DEFINITIONS': {
|
||||||
|
'all': {
|
||||||
|
'filepath': '.',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'WATCHLISTS': {
|
||||||
|
'all': ['gauravsh@chromium.org', 'rspangler@chromium.org', 'semenzato@chromium.org', 'wfrichar@chromium.org']
|
||||||
|
},
|
||||||
|
}
|
||||||
27
firmware/coreboot/3rdparty/vboot/bdb/LICENSE
vendored
Normal file
27
firmware/coreboot/3rdparty/vboot/bdb/LICENSE
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
130
firmware/coreboot/3rdparty/vboot/bdb/Makefile
vendored
Normal file
130
firmware/coreboot/3rdparty/vboot/bdb/Makefile
vendored
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
# Copyright 2015 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.
|
||||||
|
|
||||||
|
# This Makefile normally builds in a 'build' subdir, but use
|
||||||
|
#
|
||||||
|
# make BUILD=<dir>
|
||||||
|
#
|
||||||
|
# to put the output somewhere else.
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# Configuration variables come first.
|
||||||
|
|
||||||
|
# Verbose? Use V=1
|
||||||
|
ifeq (${V},)
|
||||||
|
Q := @
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Quiet? Use QUIET=1
|
||||||
|
ifeq (${QUIET},)
|
||||||
|
PRINTF := printf
|
||||||
|
else
|
||||||
|
PRINTF := :
|
||||||
|
endif
|
||||||
|
|
||||||
|
CC ?= gcc
|
||||||
|
LD = ${CC}
|
||||||
|
PKG_CONFIG ?= pkg-config
|
||||||
|
|
||||||
|
SRCDIR := $(shell pwd)
|
||||||
|
export SRCDIR
|
||||||
|
BUILD = ${SRCDIR}/build
|
||||||
|
export BUILD
|
||||||
|
KEYDIR = ${SRCDIR}/testkeys
|
||||||
|
|
||||||
|
CFLAGS = -Wall -Werror
|
||||||
|
|
||||||
|
# Create / use dependency files
|
||||||
|
CFLAGS += -MMD -MF $@.d
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# Create output directories if necessary. Do this via explicit shell commands
|
||||||
|
# so it happens before trying to generate/include dependencies.
|
||||||
|
_dir_create := $(shell [ -d ${BUILD} ] || mkdir -p ${BUILD}))
|
||||||
|
_keydir_create := $(shell [ -d ${KEYDIR} ] || mkdir -p ${KEYDIR}))
|
||||||
|
|
||||||
|
INC_PATH := $(shell ${PKG_CONFIG} --cflags libcrypto)
|
||||||
|
CFLAGS += ${INC_PATH}
|
||||||
|
|
||||||
|
CRYPTO_LIBS := $(shell ${PKG_CONFIG} --libs libcrypto)
|
||||||
|
LDLIBS += ${CRYPTO_LIBS}
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# Sources
|
||||||
|
|
||||||
|
LIBSRC = bdb.c host.c sha.c rsa.c
|
||||||
|
LIBOBJ = ${LIBSRC:%.c=${BUILD}/%.o}
|
||||||
|
|
||||||
|
BDBTESTSRC = bdb_test.c
|
||||||
|
BDBTESTOBJ = ${BDBTESTSRC:%.c=${BUILD}/%.o}
|
||||||
|
BDBTEST = ${BUILD}/bdb_test
|
||||||
|
|
||||||
|
BDBCREATESRC = bdb_create.c
|
||||||
|
BDBCREATEOBJ = ${BDBCREATESRC:%.c=${BUILD}/%.o}
|
||||||
|
BDBCREATE = ${BUILD}/bdb_create
|
||||||
|
|
||||||
|
DUMPRSASRC = dump_rsa.c
|
||||||
|
DUMPRSAOBJ = ${DUMPRSASRC:%.c=${BUILD}/%.o}
|
||||||
|
DUMPRSA = ${BUILD}/dump_rsa
|
||||||
|
|
||||||
|
ALL_OBJS = ${LIBOBJ} ${BDBTESTOBJ} ${BDBCREATEOBJ}
|
||||||
|
ALL_EXES = ${BDBTEST} ${BDBCREATE} ${DUMPRSA}
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# Targets
|
||||||
|
|
||||||
|
.PHONY: all
|
||||||
|
all: ${ALL_EXES}
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
${Q}/bin/rm -rf ${BUILD}
|
||||||
|
|
||||||
|
.PHONY: bdb
|
||||||
|
bdb: ${BDBCREATE}
|
||||||
|
${Q}${BDBCREATE}
|
||||||
|
|
||||||
|
.PHONY: runtests
|
||||||
|
runtests: ${BDBTEST}
|
||||||
|
${Q}${BDBTEST}
|
||||||
|
|
||||||
|
.PHONY: testkeys
|
||||||
|
testkeys: ${DUMPRSA}
|
||||||
|
${Q}openssl genrsa -F4 -out ${KEYDIR}/bdbkey.pem 4096
|
||||||
|
${Q}openssl req -batch -new -x509 -key ${KEYDIR}/bdbkey.pem \
|
||||||
|
-out ${KEYDIR}/bdbkey.crt
|
||||||
|
${Q}${DUMPRSA} -cert ${KEYDIR}/bdbkey.crt > ${KEYDIR}/bdbkey.keyb
|
||||||
|
|
||||||
|
${Q}openssl genrsa -3 -out ${KEYDIR}/subkey.pem 3072
|
||||||
|
${Q}openssl req -batch -new -x509 -key ${KEYDIR}/subkey.pem \
|
||||||
|
-out ${KEYDIR}/subkey.crt
|
||||||
|
${Q}${DUMPRSA} -cert ${KEYDIR}/subkey.crt > ${KEYDIR}/subkey.keyb
|
||||||
|
|
||||||
|
${BDBTEST}: ${BDBTESTOBJ} ${LIBOBJ}
|
||||||
|
@$(PRINTF) " LD $(subst ${BUILD}/,,$@)\n"
|
||||||
|
${Q}${LD} -o ${BDBTEST} ${CFLAGS} $^ ${LIBS} ${LDLIBS}
|
||||||
|
|
||||||
|
${BDBCREATE}: ${BDBCREATEOBJ} ${LIBOBJ}
|
||||||
|
@$(PRINTF) " LD $(subst ${BUILD}/,,$@)\n"
|
||||||
|
${Q}${LD} -o ${BDBCREATE} ${CFLAGS} $^ ${LIBS} ${LDLIBS}
|
||||||
|
|
||||||
|
${DUMPRSA}: ${DUMPRSAOBJ} ${LIBOBJ}
|
||||||
|
@$(PRINTF) " LD $(subst ${BUILD}/,,$@)\n"
|
||||||
|
${Q}${LD} -o ${DUMPRSA} ${CFLAGS} $^ ${LIBS} ${LDLIBS}
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# Generic build rules. LIBS and OBJS can be overridden to tweak the generic
|
||||||
|
# rules for specific targets.
|
||||||
|
|
||||||
|
${BUILD}/%: ${BUILD}/%.o ${OBJS} ${LIBS}
|
||||||
|
@${PRINTF} " LD $(subst ${BUILD}/,,$@)\n"
|
||||||
|
${Q}${LD} -o $@ ${CFLAGS} ${LDFLAGS} $< ${OBJS} ${LIBS} ${LDLIBS}
|
||||||
|
|
||||||
|
${BUILD}/%.o: %.c
|
||||||
|
@${PRINTF} " CC $(subst ${BUILD}/,,$@)\n"
|
||||||
|
${Q}${CC} ${CFLAGS} ${INCLUDES} -c -o $@ $<
|
||||||
|
|
||||||
|
# Include generated dependencies
|
||||||
|
ALL_DEPS += ${ALL_OBJS:%.o=%.o.d}
|
||||||
|
-include ${ALL_DEPS}
|
||||||
30
firmware/coreboot/3rdparty/vboot/bdb/README
vendored
Normal file
30
firmware/coreboot/3rdparty/vboot/bdb/README
vendored
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
Boot Descriptor Block (BDB) library and utilities
|
||||||
|
|
||||||
|
Building:
|
||||||
|
---------
|
||||||
|
The host-side library and utilities requires OpenSSL.
|
||||||
|
|
||||||
|
Do 'make runtests' to ensure everything is working.
|
||||||
|
|
||||||
|
Generating a BDB:
|
||||||
|
-----------------
|
||||||
|
Edit the options in bdb_create.c. Then 'make bdb'.
|
||||||
|
|
||||||
|
In the next release, this will take a config file rather than
|
||||||
|
requiring recompilation each time. Also, the BDB header and data will
|
||||||
|
be signed in two separate steps, so that the private BDB key is not
|
||||||
|
required each time.
|
||||||
|
|
||||||
|
Revision History:
|
||||||
|
-----------------
|
||||||
|
v0.1.2 24-Nov-2015 Add support for RSA-3072B keys and signatures.
|
||||||
|
Add dump_rsa utility and 'make testkeys' to create
|
||||||
|
new keys.
|
||||||
|
Use a RSA-3072B (exponent 3) key for the subkey so
|
||||||
|
the exponent 3 code gets tested.
|
||||||
|
|
||||||
|
v0.1.1 17-Nov-2015 Add support for ECDSA-521 data types. Note that
|
||||||
|
only the data types are supported; there is not a
|
||||||
|
C implementation for ECDSA.
|
||||||
|
|
||||||
|
v0.1.0 15-Sep-2015 Initial version.
|
||||||
398
firmware/coreboot/3rdparty/vboot/bdb/bdb.c
vendored
Normal file
398
firmware/coreboot/3rdparty/vboot/bdb/bdb.c
vendored
Normal file
@@ -0,0 +1,398 @@
|
|||||||
|
/* Copyright (c) 2015 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.
|
||||||
|
*
|
||||||
|
* Boot descriptor block firmware functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "bdb.h"
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if string contains a null terminator.
|
||||||
|
*
|
||||||
|
* Bytes after the null terminator do not need to be null.
|
||||||
|
*
|
||||||
|
* @param s String to check
|
||||||
|
* @param size Size of string buffer in characters
|
||||||
|
* @return 1 if string has a null terminator, 0 if not
|
||||||
|
*/
|
||||||
|
int string_has_null(const char *s, size_t size)
|
||||||
|
{
|
||||||
|
for (; size; size--) {
|
||||||
|
if (*s++ == 0)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bdb_check_header(const struct bdb_header *p, size_t size)
|
||||||
|
{
|
||||||
|
if (size < sizeof(*p) || size < p->struct_size)
|
||||||
|
return BDB_ERROR_BUF_SIZE;
|
||||||
|
|
||||||
|
if (p->struct_magic != BDB_HEADER_MAGIC)
|
||||||
|
return BDB_ERROR_STRUCT_MAGIC;
|
||||||
|
|
||||||
|
if (p->struct_major_version != BDB_HEADER_VERSION_MAJOR)
|
||||||
|
return BDB_ERROR_STRUCT_VERSION;
|
||||||
|
|
||||||
|
/* Note that minor version doesn't matter yet */
|
||||||
|
|
||||||
|
if (p->struct_size < sizeof(*p))
|
||||||
|
return BDB_ERROR_STRUCT_SIZE;
|
||||||
|
|
||||||
|
if (p->oem_area_0_size & 3)
|
||||||
|
return BDB_ERROR_OEM_AREA_SIZE; /* Not 32-bit aligned */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure the BDB is at least big enough for us. At this point, all
|
||||||
|
* the caller may have loaded is this header We'll check if there's
|
||||||
|
* space for everything else after we load it.
|
||||||
|
*/
|
||||||
|
if (p->bdb_size < sizeof(*p))
|
||||||
|
return BDB_ERROR_BDB_SIZE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The rest of the fields don't matter yet; we'll check them when we
|
||||||
|
* check the BDB itself.
|
||||||
|
*/
|
||||||
|
return BDB_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bdb_check_key(const struct bdb_key *p, size_t size)
|
||||||
|
{
|
||||||
|
size_t expect_key_size = 0;
|
||||||
|
|
||||||
|
if (size < sizeof(*p) || size < p->struct_size)
|
||||||
|
return BDB_ERROR_BUF_SIZE;
|
||||||
|
|
||||||
|
if (p->struct_magic != BDB_KEY_MAGIC)
|
||||||
|
return BDB_ERROR_STRUCT_MAGIC;
|
||||||
|
|
||||||
|
if (p->struct_major_version != BDB_KEY_VERSION_MAJOR)
|
||||||
|
return BDB_ERROR_STRUCT_VERSION;
|
||||||
|
|
||||||
|
/* Note that minor version doesn't matter yet */
|
||||||
|
|
||||||
|
if (!string_has_null(p->description, sizeof(p->description)))
|
||||||
|
return BDB_ERROR_DESCRIPTION;
|
||||||
|
|
||||||
|
/* We currently only support SHA-256 */
|
||||||
|
if (p->hash_alg != BDB_HASH_ALG_SHA256)
|
||||||
|
return BDB_ERROR_HASH_ALG;
|
||||||
|
|
||||||
|
/* Make sure signature algorithm and size are correct */
|
||||||
|
switch (p->sig_alg) {
|
||||||
|
case BDB_SIG_ALG_RSA4096:
|
||||||
|
expect_key_size = BDB_RSA4096_KEY_DATA_SIZE;
|
||||||
|
break;
|
||||||
|
case BDB_SIG_ALG_ECSDSA521:
|
||||||
|
expect_key_size = BDB_ECDSA521_KEY_DATA_SIZE;
|
||||||
|
break;
|
||||||
|
case BDB_SIG_ALG_RSA3072B:
|
||||||
|
expect_key_size = BDB_RSA3072B_KEY_DATA_SIZE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return BDB_ERROR_SIG_ALG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p->struct_size < sizeof(*p) + expect_key_size)
|
||||||
|
return BDB_ERROR_STRUCT_SIZE;
|
||||||
|
|
||||||
|
return BDB_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bdb_check_sig(const struct bdb_sig *p, size_t size)
|
||||||
|
{
|
||||||
|
size_t expect_sig_size = 0;
|
||||||
|
|
||||||
|
if (size < sizeof(*p) || size < p->struct_size)
|
||||||
|
return BDB_ERROR_BUF_SIZE;
|
||||||
|
|
||||||
|
if (p->struct_magic != BDB_SIG_MAGIC)
|
||||||
|
return BDB_ERROR_STRUCT_MAGIC;
|
||||||
|
|
||||||
|
if (p->struct_major_version != BDB_SIG_VERSION_MAJOR)
|
||||||
|
return BDB_ERROR_STRUCT_VERSION;
|
||||||
|
|
||||||
|
/* Note that minor version doesn't matter yet */
|
||||||
|
|
||||||
|
if (!string_has_null(p->description, sizeof(p->description)))
|
||||||
|
return BDB_ERROR_DESCRIPTION;
|
||||||
|
|
||||||
|
/* We currently only support SHA-256 */
|
||||||
|
if (p->hash_alg != BDB_HASH_ALG_SHA256)
|
||||||
|
return BDB_ERROR_HASH_ALG;
|
||||||
|
|
||||||
|
/* Make sure signature algorithm and size are correct */
|
||||||
|
switch (p->sig_alg) {
|
||||||
|
case BDB_SIG_ALG_RSA4096:
|
||||||
|
expect_sig_size = BDB_RSA4096_SIG_SIZE;
|
||||||
|
break;
|
||||||
|
case BDB_SIG_ALG_ECSDSA521:
|
||||||
|
expect_sig_size = BDB_ECDSA521_SIG_SIZE;
|
||||||
|
break;
|
||||||
|
case BDB_SIG_ALG_RSA3072B:
|
||||||
|
expect_sig_size = BDB_RSA3072B_SIG_SIZE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return BDB_ERROR_SIG_ALG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p->struct_size < sizeof(*p) + expect_sig_size)
|
||||||
|
return BDB_ERROR_STRUCT_SIZE;
|
||||||
|
|
||||||
|
return BDB_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bdb_check_data(const struct bdb_data *p, size_t size)
|
||||||
|
{
|
||||||
|
size_t need_size;
|
||||||
|
|
||||||
|
if (size < sizeof(*p) || size < p->signed_size)
|
||||||
|
return BDB_ERROR_BUF_SIZE;
|
||||||
|
|
||||||
|
if (p->struct_magic != BDB_DATA_MAGIC)
|
||||||
|
return BDB_ERROR_STRUCT_MAGIC;
|
||||||
|
|
||||||
|
if (p->struct_major_version != BDB_DATA_VERSION_MAJOR)
|
||||||
|
return BDB_ERROR_STRUCT_VERSION;
|
||||||
|
|
||||||
|
/* Note that minor version doesn't matter yet */
|
||||||
|
|
||||||
|
if (!string_has_null(p->description, sizeof(p->description)))
|
||||||
|
return BDB_ERROR_DESCRIPTION;
|
||||||
|
|
||||||
|
if (p->struct_size < sizeof(*p))
|
||||||
|
return BDB_ERROR_STRUCT_SIZE;
|
||||||
|
|
||||||
|
if (p->hash_entry_size < sizeof(struct bdb_hash))
|
||||||
|
return BDB_ERROR_HASH_ENTRY_SIZE;
|
||||||
|
|
||||||
|
/* Calculate expected size */
|
||||||
|
need_size = p->struct_size + p->num_hashes * p->hash_entry_size;
|
||||||
|
|
||||||
|
/* Make sure OEM area size doesn't cause wraparound */
|
||||||
|
if (need_size + p->oem_area_1_size < need_size)
|
||||||
|
return BDB_ERROR_OEM_AREA_SIZE;
|
||||||
|
if (p->oem_area_1_size & 3)
|
||||||
|
return BDB_ERROR_OEM_AREA_SIZE; /* Not 32-bit aligned */
|
||||||
|
need_size += p->oem_area_1_size;
|
||||||
|
|
||||||
|
if (p->signed_size < need_size)
|
||||||
|
return BDB_ERROR_SIGNED_SIZE;
|
||||||
|
|
||||||
|
return BDB_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
const struct bdb_header *bdb_get_header(const void *buf)
|
||||||
|
{
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct bdb_key *bdb_get_bdbkey(const void *buf)
|
||||||
|
{
|
||||||
|
const struct bdb_header *h = bdb_get_header(buf);
|
||||||
|
const uint8_t *b8 = buf;
|
||||||
|
|
||||||
|
/* BDB key follows header */
|
||||||
|
return (const struct bdb_key *)(b8 + h->struct_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
const void *bdb_get_oem_area_0(const void *buf)
|
||||||
|
{
|
||||||
|
const struct bdb_key *k = bdb_get_bdbkey(buf);
|
||||||
|
const uint8_t *b8 = (const uint8_t *)k;
|
||||||
|
|
||||||
|
/* OEM area 0 follows BDB key */
|
||||||
|
return b8 + k->struct_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct bdb_key *bdb_get_subkey(const void *buf)
|
||||||
|
{
|
||||||
|
const struct bdb_header *h = bdb_get_header(buf);
|
||||||
|
const uint8_t *b8 = bdb_get_oem_area_0(buf);
|
||||||
|
|
||||||
|
/* Subkey follows OEM area 0 */
|
||||||
|
return (const struct bdb_key *)(b8 + h->oem_area_0_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct bdb_sig *bdb_get_header_sig(const void *buf)
|
||||||
|
{
|
||||||
|
const struct bdb_header *h = bdb_get_header(buf);
|
||||||
|
const uint8_t *b8 = bdb_get_oem_area_0(buf);
|
||||||
|
|
||||||
|
/* Header signature starts after signed data */
|
||||||
|
return (const struct bdb_sig *)(b8 + h->signed_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct bdb_data *bdb_get_data(const void *buf)
|
||||||
|
{
|
||||||
|
const struct bdb_sig *s = bdb_get_header_sig(buf);
|
||||||
|
const uint8_t *b8 = (const uint8_t *)s;
|
||||||
|
|
||||||
|
/* Data follows header signature */
|
||||||
|
return (const struct bdb_data *)(b8 + s->struct_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
const void *bdb_get_oem_area_1(const void *buf)
|
||||||
|
{
|
||||||
|
const struct bdb_data *p = bdb_get_data(buf);
|
||||||
|
const uint8_t *b8 = (const uint8_t *)p;
|
||||||
|
|
||||||
|
/* OEM area 1 follows BDB data */
|
||||||
|
return b8 + p->struct_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct bdb_hash *bdb_get_hash(const void *buf, enum bdb_data_type type)
|
||||||
|
{
|
||||||
|
const struct bdb_data *data = bdb_get_data(buf);
|
||||||
|
const uint8_t *b8 = bdb_get_oem_area_1(buf);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Hashes follow OEM area 0 */
|
||||||
|
b8 += data->oem_area_1_size;
|
||||||
|
|
||||||
|
/* Search for a matching hash */
|
||||||
|
for (i = 0; i < data->num_hashes; i++, b8 += data->hash_entry_size) {
|
||||||
|
const struct bdb_hash *h = (const struct bdb_hash *)b8;
|
||||||
|
|
||||||
|
if (h->type == type)
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct bdb_sig *bdb_get_data_sig(const void *buf)
|
||||||
|
{
|
||||||
|
const struct bdb_data *data = bdb_get_data(buf);
|
||||||
|
const uint8_t *b8 = (const uint8_t *)data;
|
||||||
|
|
||||||
|
/* Data signature starts after signed data */
|
||||||
|
return (const struct bdb_sig *)(b8 + data->signed_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
int bdb_verify_sig(const struct bdb_key *key,
|
||||||
|
const struct bdb_sig *sig,
|
||||||
|
const uint8_t *digest)
|
||||||
|
{
|
||||||
|
/* Key and signature algorithms must match */
|
||||||
|
if (key->sig_alg != sig->sig_alg)
|
||||||
|
return BDB_ERROR_SIG_ALG;
|
||||||
|
|
||||||
|
switch (key->sig_alg) {
|
||||||
|
case BDB_SIG_ALG_RSA4096:
|
||||||
|
if (bdb_rsa4096_verify(key->key_data, sig->sig_data, digest))
|
||||||
|
return BDB_ERROR_VERIFY_SIG;
|
||||||
|
break;
|
||||||
|
case BDB_SIG_ALG_ECSDSA521:
|
||||||
|
if (bdb_ecdsa521_verify(key->key_data, sig->sig_data, digest))
|
||||||
|
return BDB_ERROR_VERIFY_SIG;
|
||||||
|
break;
|
||||||
|
case BDB_SIG_ALG_RSA3072B:
|
||||||
|
if (bdb_rsa3072b_verify(key->key_data, sig->sig_data, digest))
|
||||||
|
return BDB_ERROR_VERIFY_SIG;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return BDB_ERROR_VERIFY_SIG;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BDB_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bdb_verify(const void *buf, size_t size, const uint8_t *bdb_key_digest)
|
||||||
|
{
|
||||||
|
const uint8_t *end = (const uint8_t *)buf + size;
|
||||||
|
const struct bdb_header *h;
|
||||||
|
const struct bdb_key *bdbkey, *subkey;
|
||||||
|
const struct bdb_sig *sig;
|
||||||
|
const struct bdb_data *data;
|
||||||
|
const void *oem;
|
||||||
|
uint8_t digest[BDB_SHA256_DIGEST_SIZE];
|
||||||
|
int bdb_digest_mismatch;
|
||||||
|
|
||||||
|
/* Make sure buffer doesn't wrap around address space */
|
||||||
|
if (end < (const uint8_t *)buf)
|
||||||
|
return BDB_ERROR_BUF_SIZE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check header now that we've actually loaded it. We can't guarantee
|
||||||
|
* this is the same header which was checked before.
|
||||||
|
*/
|
||||||
|
h = bdb_get_header(buf);
|
||||||
|
if (bdb_check_header(h, size))
|
||||||
|
return BDB_ERROR_HEADER;
|
||||||
|
|
||||||
|
/* Sanity-check BDB key */
|
||||||
|
bdbkey = bdb_get_bdbkey(buf);
|
||||||
|
if (bdb_check_key(bdbkey, end - (const uint8_t *)bdbkey))
|
||||||
|
return BDB_ERROR_BDBKEY;
|
||||||
|
|
||||||
|
/* Calculate BDB key digest and compare with expected */
|
||||||
|
if (bdb_sha256(digest, bdbkey, bdbkey->struct_size))
|
||||||
|
return BDB_ERROR_DIGEST;
|
||||||
|
|
||||||
|
bdb_digest_mismatch = memcmp(digest, bdb_key_digest, sizeof(digest));
|
||||||
|
|
||||||
|
/* Make sure OEM area 0 fits */
|
||||||
|
oem = bdb_get_oem_area_0(buf);
|
||||||
|
if (h->oem_area_0_size > end - (const uint8_t *)oem)
|
||||||
|
return BDB_ERROR_OEM_AREA_0;
|
||||||
|
|
||||||
|
/* Sanity-check subkey */
|
||||||
|
subkey = bdb_get_subkey(buf);
|
||||||
|
if (bdb_check_key(subkey, end - (const uint8_t *)subkey))
|
||||||
|
return BDB_ERROR_SUBKEY;
|
||||||
|
|
||||||
|
/* Make sure enough data was signed, and the signed data fits */
|
||||||
|
if (h->oem_area_0_size + subkey->struct_size > h->signed_size ||
|
||||||
|
h->signed_size > end - (const uint8_t *)oem)
|
||||||
|
return BDB_ERROR_BDB_SIGNED_SIZE;
|
||||||
|
|
||||||
|
/* Sanity-check header signature */
|
||||||
|
sig = bdb_get_header_sig(buf);
|
||||||
|
if (bdb_check_sig(sig, end - (const uint8_t *)sig))
|
||||||
|
return BDB_ERROR_HEADER_SIG;
|
||||||
|
|
||||||
|
/* Make sure it signed the right amount of data */
|
||||||
|
if (sig->signed_size != h->signed_size)
|
||||||
|
return BDB_ERROR_HEADER_SIG;
|
||||||
|
|
||||||
|
/* Calculate header digest and compare with expected signature */
|
||||||
|
if (bdb_sha256(digest, oem, h->signed_size))
|
||||||
|
return BDB_ERROR_DIGEST;
|
||||||
|
if (bdb_verify_sig(bdbkey, sig, digest))
|
||||||
|
return BDB_ERROR_HEADER_SIG;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sanity-check data struct. This also checks that OEM area 1 and the
|
||||||
|
* hashes fit in the remaining buffer.
|
||||||
|
*/
|
||||||
|
data = bdb_get_data(buf);
|
||||||
|
if (bdb_check_data(data, end - (const uint8_t *)data))
|
||||||
|
return BDB_ERROR_DATA;
|
||||||
|
|
||||||
|
/* Sanity-check data signature */
|
||||||
|
sig = bdb_get_data_sig(buf);
|
||||||
|
if (bdb_check_sig(sig, end - (const uint8_t *)sig))
|
||||||
|
return BDB_ERROR_DATA_SIG;
|
||||||
|
if (sig->signed_size != data->signed_size)
|
||||||
|
return BDB_ERROR_DATA_SIG;
|
||||||
|
|
||||||
|
/* Calculate data digest and compare with expected signature */
|
||||||
|
if (bdb_sha256(digest, data, data->signed_size))
|
||||||
|
return BDB_ERROR_DIGEST;
|
||||||
|
if (bdb_verify_sig(subkey, sig, digest))
|
||||||
|
return BDB_ERROR_DATA_SIG;
|
||||||
|
|
||||||
|
/* Return success or success-other-than-BDB-key-mismatch */
|
||||||
|
return bdb_digest_mismatch ? BDB_GOOD_OTHER_THAN_KEY : BDB_SUCCESS;
|
||||||
|
}
|
||||||
181
firmware/coreboot/3rdparty/vboot/bdb/bdb.h
vendored
Normal file
181
firmware/coreboot/3rdparty/vboot/bdb/bdb.h
vendored
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
/* Copyright (c) 2015 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.
|
||||||
|
*
|
||||||
|
* Boot descriptor block firmware functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef VBOOT_REFERENCE_BDB_H_
|
||||||
|
#define VBOOT_REFERENCE_BDB_H_
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "bdb_struct.h"
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/*
|
||||||
|
Expected calling sequence:
|
||||||
|
|
||||||
|
Load and check just the header
|
||||||
|
bdb_check_header(buf, size);
|
||||||
|
|
||||||
|
Load and verify the entire BDB
|
||||||
|
bdb_verify(buf, size, bdb_key_hash, dev_mode_flag);
|
||||||
|
|
||||||
|
Check RW subkey version. If normal boot from primary BDB, roll forward
|
||||||
|
|
||||||
|
Check data version. If normal boot from primary BDB, roll forward
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Codes for functions returning numeric error codes */
|
||||||
|
|
||||||
|
enum bdb_return_code {
|
||||||
|
/* Success */
|
||||||
|
BDB_SUCCESS = 0,
|
||||||
|
|
||||||
|
/* BDB key did not match hash, but other than that the BDB was
|
||||||
|
* fully verified. */
|
||||||
|
BDB_GOOD_OTHER_THAN_KEY = 1,
|
||||||
|
|
||||||
|
/* Other errors */
|
||||||
|
BDB_ERROR_UNKNOWN = 100,
|
||||||
|
|
||||||
|
/* Buffer size too small or wraps around */
|
||||||
|
BDB_ERROR_BUF_SIZE,
|
||||||
|
|
||||||
|
/* Bad fields in structures */
|
||||||
|
BDB_ERROR_STRUCT_MAGIC,
|
||||||
|
BDB_ERROR_STRUCT_VERSION,
|
||||||
|
BDB_ERROR_STRUCT_SIZE,
|
||||||
|
BDB_ERROR_SIGNED_SIZE,
|
||||||
|
BDB_ERROR_BDB_SIZE,
|
||||||
|
BDB_ERROR_OEM_AREA_SIZE,
|
||||||
|
BDB_ERROR_HASH_ENTRY_SIZE,
|
||||||
|
BDB_ERROR_HASH_ALG,
|
||||||
|
BDB_ERROR_SIG_ALG,
|
||||||
|
BDB_ERROR_DESCRIPTION,
|
||||||
|
|
||||||
|
/* Bad components of BDB in bdb_verify() */
|
||||||
|
BDB_ERROR_HEADER,
|
||||||
|
BDB_ERROR_BDBKEY,
|
||||||
|
BDB_ERROR_OEM_AREA_0,
|
||||||
|
BDB_ERROR_SUBKEY,
|
||||||
|
BDB_ERROR_BDB_SIGNED_SIZE,
|
||||||
|
BDB_ERROR_HEADER_SIG,
|
||||||
|
BDB_ERROR_DATA,
|
||||||
|
BDB_ERROR_DATA_SIG,
|
||||||
|
|
||||||
|
/* Other errors in bdb_verify() */
|
||||||
|
BDB_ERROR_DIGEST, /* Error calculating digest */
|
||||||
|
BDB_ERROR_VERIFY_SIG, /* Error verifying signature */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Functions */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sanity-check BDB structures.
|
||||||
|
*
|
||||||
|
* This checks for known version numbers, magic numbers, algorithms, etc. and
|
||||||
|
* ensures the sizes are consistent with those parameters.
|
||||||
|
*
|
||||||
|
* @param p Pointer to structure to check
|
||||||
|
* @param size Size of structure buffer
|
||||||
|
* @return 0 if success, non-zero error code if error.
|
||||||
|
*/
|
||||||
|
int bdb_check_header(const struct bdb_header *p, size_t size);
|
||||||
|
int bdb_check_key(const struct bdb_key *p, size_t size);
|
||||||
|
int bdb_check_sig(const struct bdb_sig *p, size_t size);
|
||||||
|
int bdb_check_data(const struct bdb_data *p, size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify the entire BDB
|
||||||
|
*
|
||||||
|
* @param buf Data to hash
|
||||||
|
* @param size Size of data in bytes
|
||||||
|
* @param bdb_key_digest Pointer to expected digest for BDB key.
|
||||||
|
* Must be BDB_SHA256_DIGEST_SIZE bytes long.
|
||||||
|
*
|
||||||
|
* @return 0 if success, non-zero error code if error. Note that error code
|
||||||
|
* BDB_GOOD_OTHER_THAN_KEY may still indicate an acceptable BDB if the Boot
|
||||||
|
* Verified fuse has not been set, or in developer mode.
|
||||||
|
*/
|
||||||
|
int bdb_verify(const void *buf, size_t size, const uint8_t *bdb_key_digest);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Functions to extract things from a verified BDB buffer.
|
||||||
|
*
|
||||||
|
* Do not call these externally until after bdb_verify()! These methods
|
||||||
|
* assume data structures have already been verified.
|
||||||
|
*
|
||||||
|
* @param buf Pointer to BDB buffer
|
||||||
|
* @param type Data type, for bdb_get_hash()
|
||||||
|
* @return A pointer to the requested data, or NULL if error / not present.
|
||||||
|
*/
|
||||||
|
const struct bdb_header *bdb_get_header(const void *buf);
|
||||||
|
const struct bdb_key *bdb_get_bdbkey(const void *buf);
|
||||||
|
const void *bdb_get_oem_area_0(const void *buf);
|
||||||
|
const struct bdb_key *bdb_get_subkey(const void *buf);
|
||||||
|
const struct bdb_sig *bdb_get_header_sig(const void *buf);
|
||||||
|
const struct bdb_data *bdb_get_data(const void *buf);
|
||||||
|
const void *bdb_get_oem_area_1(const void *buf);
|
||||||
|
const struct bdb_hash *bdb_get_hash(const void *buf, enum bdb_data_type type);
|
||||||
|
const struct bdb_sig *bdb_get_data_sig(const void *buf);
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Functions probably provided by the caller */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate a SHA-256 digest of a buffer.
|
||||||
|
*
|
||||||
|
* @param digest Pointer to the digest buffer. Must be
|
||||||
|
* BDB_SHA256_DIGEST_SIZE bytes long.
|
||||||
|
* @param buf Data to hash
|
||||||
|
* @param size Size of data in bytes
|
||||||
|
* @return 0 if success, non-zero error code if error.
|
||||||
|
*/
|
||||||
|
__attribute__((weak))
|
||||||
|
int bdb_sha256(void *digest, const void *buf, size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify a RSA-4096 signed digest
|
||||||
|
*
|
||||||
|
* @param key_data Key data to use (BDB_RSA4096_KEY_DATA_SIZE bytes)
|
||||||
|
* @param sig_data Signature to verify (BDB_RSA4096_SIG_SIZE bytes)
|
||||||
|
* @param digest Digest of signed data (BDB_SHA256_DIGEST bytes)
|
||||||
|
* @return 0 if success, non-zero error code if error.
|
||||||
|
*/
|
||||||
|
__attribute__((weak))
|
||||||
|
int bdb_rsa4096_verify(const uint8_t *key_data,
|
||||||
|
const uint8_t *sig,
|
||||||
|
const uint8_t *digest);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify a RSA-3072B signed digest
|
||||||
|
*
|
||||||
|
* @param key_data Key data to use (BDB_RSA3072B_KEY_DATA_SIZE bytes)
|
||||||
|
* @param sig_data Signature to verify (BDB_RSA3072B_SIG_SIZE bytes)
|
||||||
|
* @param digest Digest of signed data (BDB_SHA256_DIGEST bytes)
|
||||||
|
* @return 0 if success, non-zero error code if error.
|
||||||
|
*/
|
||||||
|
__attribute__((weak))
|
||||||
|
int bdb_rsa3072b_verify(const uint8_t *key_data,
|
||||||
|
const uint8_t *sig,
|
||||||
|
const uint8_t *digest);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify a ECDSA-521 signed digest
|
||||||
|
*
|
||||||
|
* @param key_data Key data to use (BDB_ECDSA521_KEY_DATA_SIZE bytes)
|
||||||
|
* @param sig_data Signature to verify (BDB_ECDSA521_SIG_SIZE bytes)
|
||||||
|
* @param digest Digest of signed data (BDB_SHA256_DIGEST bytes)
|
||||||
|
* @return 0 if success, non-zero error code if error.
|
||||||
|
*/
|
||||||
|
__attribute__((weak))
|
||||||
|
int bdb_ecdsa521_verify(const uint8_t *key_data,
|
||||||
|
const uint8_t *sig,
|
||||||
|
const uint8_t *digest);
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
#endif /* VBOOT_REFERENCE_BDB_H_ */
|
||||||
232
firmware/coreboot/3rdparty/vboot/bdb/bdb_create.c
vendored
Normal file
232
firmware/coreboot/3rdparty/vboot/bdb/bdb_create.c
vendored
Normal file
@@ -0,0 +1,232 @@
|
|||||||
|
/* Copyright (c) 2015 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.
|
||||||
|
*
|
||||||
|
* Create a BDB
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "bdb.h"
|
||||||
|
#include "host.h"
|
||||||
|
|
||||||
|
/* Parameters for creating a BDB hash entry */
|
||||||
|
struct create_hash {
|
||||||
|
/* File containing data */
|
||||||
|
const char *filename;
|
||||||
|
|
||||||
|
/* Type of data; enum bdb_data_type */
|
||||||
|
uint8_t type;
|
||||||
|
|
||||||
|
/* Address in RAM to load data. -1 means use default. */
|
||||||
|
uint64_t load_address;
|
||||||
|
|
||||||
|
/* Partition number containing data, or -1 to use the same partition as
|
||||||
|
* the BDB. */
|
||||||
|
uint8_t partition;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Offset of data from start of partition.
|
||||||
|
*
|
||||||
|
* TODO: if -1, append after BDB. But need to know how big the BDB
|
||||||
|
* is, and need to round up offset to 32-bit boundary.
|
||||||
|
*/
|
||||||
|
uint64_t offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Parameters for a key */
|
||||||
|
struct create_key {
|
||||||
|
/* Description */
|
||||||
|
const char *description;
|
||||||
|
|
||||||
|
/* Key version (not meaningful for BDB key) */
|
||||||
|
uint32_t key_version;
|
||||||
|
|
||||||
|
/* Public key filename (.keyb) */
|
||||||
|
const char *public_filename;
|
||||||
|
|
||||||
|
/* Private key filename (.pem) */
|
||||||
|
const char *private_filename;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct create_params_2 {
|
||||||
|
/* Destination filename */
|
||||||
|
const char *filename;
|
||||||
|
|
||||||
|
/* Partition to contain the BDB */
|
||||||
|
uint8_t partition;
|
||||||
|
|
||||||
|
/* OEM area files. NULL means there is no data for that area. */
|
||||||
|
const char *oem_area_0_filename;
|
||||||
|
const char *oem_area_1_filename;
|
||||||
|
|
||||||
|
/* BDB key and subkey */
|
||||||
|
struct create_key bdbkey;
|
||||||
|
struct create_key subkey;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* FILL THIS IN WITH YOUR SOURCE DATA */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creation parameters. Hash and num_hashes will be filled in automatically
|
||||||
|
* by create().
|
||||||
|
*/
|
||||||
|
struct bdb_create_params p = {
|
||||||
|
.bdb_load_address = 0x11223344,
|
||||||
|
.header_sig_description = "The header sig",
|
||||||
|
.data_sig_description = "The data sig",
|
||||||
|
.data_description = "Test BDB data",
|
||||||
|
.data_version = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Additional parameters */
|
||||||
|
struct create_params_2 p2 = {
|
||||||
|
.filename = "build/bdb.bin",
|
||||||
|
.partition = 1,
|
||||||
|
.oem_area_0_filename = "testdata/oem0.bin",
|
||||||
|
.oem_area_1_filename = "testdata/oem1.bin",
|
||||||
|
.bdbkey = {
|
||||||
|
.description = "Test BDB key",
|
||||||
|
.key_version = 3,
|
||||||
|
.public_filename = "testkeys/bdbkey.keyb",
|
||||||
|
.private_filename = "testkeys/bdbkey.pem",
|
||||||
|
},
|
||||||
|
.subkey = {
|
||||||
|
.description = "Test Subkey",
|
||||||
|
.key_version = 4,
|
||||||
|
.public_filename = "testkeys/subkey.keyb",
|
||||||
|
.private_filename = "testkeys/subkey.pem",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/* List of hash entries, terminated by one with a NULL filename */
|
||||||
|
struct create_hash hash_entries[] = {
|
||||||
|
{
|
||||||
|
.filename = "testdata/sp-rw.bin",
|
||||||
|
.type = BDB_DATA_SP_RW,
|
||||||
|
.load_address = -1,
|
||||||
|
.partition = -1,
|
||||||
|
.offset = 0x10000,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.filename = "testdata/ap-rw.bin",
|
||||||
|
.type = BDB_DATA_AP_RW,
|
||||||
|
.load_address = 0x200000,
|
||||||
|
.partition = -1,
|
||||||
|
.offset = 0x28000,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.filename = NULL
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
int create(void)
|
||||||
|
{
|
||||||
|
struct bdb_hash *hash;
|
||||||
|
struct bdb_header *h;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Count the number of hash entries */
|
||||||
|
for (p.num_hashes = 0; hash_entries[p.num_hashes].filename;
|
||||||
|
p.num_hashes++)
|
||||||
|
;
|
||||||
|
printf("Found %d hash entries\n", p.num_hashes);
|
||||||
|
|
||||||
|
/* Calculate hashes */
|
||||||
|
p.hash = hash = calloc(sizeof(struct bdb_hash), p.num_hashes);
|
||||||
|
for (i = 0; i < p.num_hashes; i++, hash++) {
|
||||||
|
const struct create_hash *he = hash_entries + i;
|
||||||
|
|
||||||
|
/* Read file and calculate size and hash */
|
||||||
|
uint8_t *buf = read_file(he->filename, &hash->size);
|
||||||
|
if (!buf)
|
||||||
|
return 1;
|
||||||
|
if (bdb_sha256(hash->digest, buf, hash->size)) {
|
||||||
|
fprintf(stderr, "Unable to calculate hash\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
free(buf);
|
||||||
|
|
||||||
|
hash->type = he->type;
|
||||||
|
hash->load_address = he->load_address;
|
||||||
|
|
||||||
|
hash->partition = he->partition == -1 ? p2.partition :
|
||||||
|
he->partition;
|
||||||
|
|
||||||
|
hash->offset = he->offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read OEM data */
|
||||||
|
if (p2.oem_area_0_filename) {
|
||||||
|
p.oem_area_0 = read_file(p2.oem_area_0_filename,
|
||||||
|
&p.oem_area_0_size);
|
||||||
|
if (!p.oem_area_0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (p.oem_area_0_size & 3) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"OEM area 0 size isn't 32-bit aligned\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p2.oem_area_1_filename) {
|
||||||
|
p.oem_area_1 = read_file(p2.oem_area_1_filename,
|
||||||
|
&p.oem_area_1_size);
|
||||||
|
if (!p.oem_area_1)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (p.oem_area_1_size & 3) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"OEM area 1 size isn't 32-bit aligned\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Load keys */
|
||||||
|
p.bdbkey = bdb_create_key(p2.bdbkey.public_filename,
|
||||||
|
p2.bdbkey.key_version,
|
||||||
|
p2.bdbkey.description);
|
||||||
|
p.subkey = bdb_create_key(p2.subkey.public_filename,
|
||||||
|
p2.subkey.key_version,
|
||||||
|
p2.subkey.description);
|
||||||
|
p.private_bdbkey = read_pem(p2.bdbkey.private_filename);
|
||||||
|
p.private_subkey = read_pem(p2.subkey.private_filename);
|
||||||
|
if (!p.bdbkey || !p.subkey || !p.private_bdbkey || !p.private_subkey) {
|
||||||
|
fprintf(stderr, "Unable to load keys\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create the BDB */
|
||||||
|
h = bdb_create(&p);
|
||||||
|
if (!h) {
|
||||||
|
fprintf(stderr, "Unable to create BDB\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write it */
|
||||||
|
if (write_file(p2.filename, h, h->bdb_size))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* Free keys and buffers */
|
||||||
|
free(p.bdbkey);
|
||||||
|
free(p.subkey);
|
||||||
|
RSA_free(p.private_bdbkey);
|
||||||
|
RSA_free(p.private_subkey);
|
||||||
|
free(h);
|
||||||
|
free(p.hash);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
return create();
|
||||||
|
}
|
||||||
268
firmware/coreboot/3rdparty/vboot/bdb/bdb_struct.h
vendored
Normal file
268
firmware/coreboot/3rdparty/vboot/bdb/bdb_struct.h
vendored
Normal file
@@ -0,0 +1,268 @@
|
|||||||
|
/* Copyright (c) 2015 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.
|
||||||
|
*
|
||||||
|
* Boot descriptor block structures
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef VBOOT_REFERENCE_BDB_STRUCT_H_
|
||||||
|
#define VBOOT_REFERENCE_BDB_STRUCT_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/* Size of SHA256 digest in bytes */
|
||||||
|
#define BDB_SHA256_DIGEST_SIZE 32
|
||||||
|
|
||||||
|
/* Size of RSA4096 key data in bytes */
|
||||||
|
#define BDB_RSA4096_KEY_DATA_SIZE 1032
|
||||||
|
|
||||||
|
/* Size of RSA4096 signature in bytes */
|
||||||
|
#define BDB_RSA4096_SIG_SIZE 512
|
||||||
|
|
||||||
|
/* Size of ECDSA521 key data in bytes = ceil(521/8) * 2 */
|
||||||
|
#define BDB_ECDSA521_KEY_DATA_SIZE 132
|
||||||
|
|
||||||
|
/* Size of ECDSA521 signature in bytes = ceil(521/8) * 2 */
|
||||||
|
#define BDB_ECDSA521_SIG_SIZE 132
|
||||||
|
|
||||||
|
/* Size of RSA3072B key data in bytes */
|
||||||
|
#define BDB_RSA3072B_KEY_DATA_SIZE 776
|
||||||
|
|
||||||
|
/* Size of RSA3072B signature in bytes */
|
||||||
|
#define BDB_RSA3072B_SIG_SIZE 384
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Header for BDB */
|
||||||
|
|
||||||
|
/* Magic number for bdb_header.struct_magic */
|
||||||
|
#define BDB_HEADER_MAGIC 0x30426442
|
||||||
|
|
||||||
|
/* Current version of bdb_header struct */
|
||||||
|
#define BDB_HEADER_VERSION_MAJOR 1
|
||||||
|
#define BDB_HEADER_VERSION_MINOR 0
|
||||||
|
|
||||||
|
/* Expected size of bdb_header struct in bytes */
|
||||||
|
#define BDB_HEADER_EXPECTED_SIZE 32
|
||||||
|
|
||||||
|
struct bdb_header {
|
||||||
|
/* Magic number to identify struct = BDB_HEADER_MAGIC. */
|
||||||
|
uint32_t struct_magic;
|
||||||
|
|
||||||
|
/* Structure version = BDB_HEADER_VERSION{MAJOR,MINOR} */
|
||||||
|
uint8_t struct_major_version;
|
||||||
|
uint8_t struct_minor_version;
|
||||||
|
|
||||||
|
/* Size of structure in bytes */
|
||||||
|
uint16_t struct_size;
|
||||||
|
|
||||||
|
/* Recommended address in SP SRAM to load BDB. Set to -1 to use
|
||||||
|
* default address. */
|
||||||
|
uint64_t bdb_load_address;
|
||||||
|
|
||||||
|
/* Size of the entire BDB in bytes */
|
||||||
|
uint32_t bdb_size;
|
||||||
|
|
||||||
|
/* Number of bytes following the BDB key which are signed by the BDB
|
||||||
|
* header signature. */
|
||||||
|
uint32_t signed_size;
|
||||||
|
|
||||||
|
/* Size of OEM area 0 in bytes, or 0 if not present */
|
||||||
|
uint32_t oem_area_0_size;
|
||||||
|
|
||||||
|
/* Reserved; set 0 */
|
||||||
|
uint8_t reserved0[8];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Public key structure for BDB */
|
||||||
|
|
||||||
|
/* Magic number for bdb_key.struct_magic */
|
||||||
|
#define BDB_KEY_MAGIC 0x73334256
|
||||||
|
|
||||||
|
/* Current version of bdb_key struct */
|
||||||
|
#define BDB_KEY_VERSION_MAJOR 1
|
||||||
|
#define BDB_KEY_VERSION_MINOR 0
|
||||||
|
|
||||||
|
/* Supported hash algorithms */
|
||||||
|
enum bdb_hash_alg {
|
||||||
|
BDB_HASH_ALG_INVALID = 0, /* Not used; invalid */
|
||||||
|
BDB_HASH_ALG_SHA256 = 2, /* SHA-256 */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Supported signature algorithms */
|
||||||
|
enum bdb_sig_alg {
|
||||||
|
BDB_SIG_ALG_INVALID = 0, /* Not used; invalid */
|
||||||
|
BDB_SIG_ALG_RSA4096 = 3, /* RSA-4096, exponent 65537 */
|
||||||
|
BDB_SIG_ALG_ECSDSA521 = 5, /* ECDSA-521 */
|
||||||
|
BDB_SIG_ALG_RSA3072B = 7, /* RSA_3072, exponent 3 */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Expected size of bdb_key struct in bytes, not counting variable-length key
|
||||||
|
* data at end.
|
||||||
|
*/
|
||||||
|
#define BDB_KEY_EXPECTED_SIZE 80
|
||||||
|
|
||||||
|
struct bdb_key {
|
||||||
|
/* Magic number to identify struct = BDB_KEY_MAGIC. */
|
||||||
|
uint32_t struct_magic;
|
||||||
|
|
||||||
|
/* Structure version = BDB_KEY_VERSION{MAJOR,MINOR} */
|
||||||
|
uint8_t struct_major_version;
|
||||||
|
uint8_t struct_minor_version;
|
||||||
|
|
||||||
|
/* Size of structure in bytes, including variable-length key data */
|
||||||
|
uint16_t struct_size;
|
||||||
|
|
||||||
|
/* Hash algorithm (enum bdb_hash_alg) */
|
||||||
|
uint8_t hash_alg;
|
||||||
|
|
||||||
|
/* Signature algorithm (enum bdb_sig_alg) */
|
||||||
|
uint8_t sig_alg;
|
||||||
|
|
||||||
|
/* Reserved; set 0 */
|
||||||
|
uint8_t reserved0[2];
|
||||||
|
|
||||||
|
/* Key version */
|
||||||
|
uint32_t key_version;
|
||||||
|
|
||||||
|
/* Description; null-terminated ASCII */
|
||||||
|
char description[128];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Key data. Variable-length; size is struct_size -
|
||||||
|
* offset_of(bdb_key, key_data).
|
||||||
|
*/
|
||||||
|
uint8_t key_data[0];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Signature structure for BDB */
|
||||||
|
|
||||||
|
/* Magic number for bdb_sig.struct_magic */
|
||||||
|
#define BDB_SIG_MAGIC 0x6b334256
|
||||||
|
|
||||||
|
/* Current version of bdb_sig struct */
|
||||||
|
#define BDB_SIG_VERSION_MAJOR 1
|
||||||
|
#define BDB_SIG_VERSION_MINOR 0
|
||||||
|
|
||||||
|
struct bdb_sig {
|
||||||
|
/* Magic number to identify struct = BDB_SIG_MAGIC. */
|
||||||
|
uint32_t struct_magic;
|
||||||
|
|
||||||
|
/* Structure version = BDB_SIG_VERSION{MAJOR,MINOR} */
|
||||||
|
uint8_t struct_major_version;
|
||||||
|
uint8_t struct_minor_version;
|
||||||
|
|
||||||
|
/* Size of structure in bytes, including variable-length signature
|
||||||
|
* data. */
|
||||||
|
uint16_t struct_size;
|
||||||
|
|
||||||
|
/* Hash algorithm used for this signature (enum bdb_hash_alg) */
|
||||||
|
uint8_t hash_alg;
|
||||||
|
|
||||||
|
/* Signature algorithm (enum bdb_sig_alg) */
|
||||||
|
uint8_t sig_alg;
|
||||||
|
|
||||||
|
/* Reserved; set 0 */
|
||||||
|
uint8_t reserved0[2];
|
||||||
|
|
||||||
|
/* Number of bytes of data signed by this signature */
|
||||||
|
uint32_t signed_size;
|
||||||
|
|
||||||
|
/* Description; null-terminated ASCII */
|
||||||
|
char description[128];
|
||||||
|
|
||||||
|
/* Signature data. Variable-length; size is struct_size -
|
||||||
|
* offset_of(bdb_sig, sig_data). */
|
||||||
|
uint8_t sig_data[0];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Data structure for BDB */
|
||||||
|
|
||||||
|
/* Magic number for bdb_data.struct_magic */
|
||||||
|
#define BDB_DATA_MAGIC 0x31426442
|
||||||
|
|
||||||
|
/* Current version of bdb_sig struct */
|
||||||
|
#define BDB_DATA_VERSION_MAJOR 1
|
||||||
|
#define BDB_DATA_VERSION_MINOR 0
|
||||||
|
|
||||||
|
struct bdb_data {
|
||||||
|
/* Magic number to identify struct = BDB_DATA_MAGIC. */
|
||||||
|
uint32_t struct_magic;
|
||||||
|
|
||||||
|
/* Structure version = BDB_DATA_VERSION{MAJOR,MINOR} */
|
||||||
|
uint8_t struct_major_version;
|
||||||
|
uint8_t struct_minor_version;
|
||||||
|
|
||||||
|
/* Size of structure in bytes, NOT including hashes which follow. */
|
||||||
|
uint16_t struct_size;
|
||||||
|
|
||||||
|
/* Version of data (RW firmware) contained */
|
||||||
|
uint32_t data_version;
|
||||||
|
|
||||||
|
/* Size of OEM area 1 in bytes, or 0 if not present */
|
||||||
|
uint32_t oem_area_1_size;
|
||||||
|
|
||||||
|
/* Number of hashes which follow */
|
||||||
|
uint8_t num_hashes;
|
||||||
|
|
||||||
|
/* Size of each hash entry in bytes */
|
||||||
|
uint8_t hash_entry_size;
|
||||||
|
|
||||||
|
/* Reserved; set 0 */
|
||||||
|
uint8_t reserved0[2];
|
||||||
|
|
||||||
|
/* Number of bytes of data signed by the subkey, including this
|
||||||
|
* header */
|
||||||
|
uint32_t signed_size;
|
||||||
|
|
||||||
|
/* Reserved; set 0 */
|
||||||
|
uint8_t reserved1[8];
|
||||||
|
|
||||||
|
/* Description; null-terminated ASCII */
|
||||||
|
char description[128];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
/* Type of data for bdb_hash.type */
|
||||||
|
enum bdb_data_type {
|
||||||
|
/* Types of data for boot descriptor blocks */
|
||||||
|
BDB_DATA_SP_RW = 1, /* SP-RW firmware */
|
||||||
|
BDB_DATA_AP_RW = 2, /* AP-RW firmware */
|
||||||
|
BDB_DATA_MCU = 3, /* MCU firmware */
|
||||||
|
|
||||||
|
/* Types of data for kernel descriptor blocks */
|
||||||
|
BDB_DATA_KERNEL = 128, /* Kernel */
|
||||||
|
BDB_DATA_CMD_LINE = 129, /* Command line */
|
||||||
|
BDB_DATA_HEADER16 = 130, /* 16-bit vmlinuz header */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Hash entries which follow the structure */
|
||||||
|
struct bdb_hash {
|
||||||
|
/* Offset of data from start of partition */
|
||||||
|
uint64_t offset;
|
||||||
|
|
||||||
|
/* Size of data in bytes */
|
||||||
|
uint32_t size;
|
||||||
|
|
||||||
|
/* Partition number containing data */
|
||||||
|
uint8_t partition;
|
||||||
|
|
||||||
|
/* Type of data; enum bdb_data_type */
|
||||||
|
uint8_t type;
|
||||||
|
|
||||||
|
/* Reserved; set 0 */
|
||||||
|
uint8_t reserved0[2];
|
||||||
|
|
||||||
|
/* Address in RAM to load data. -1 means use default. */
|
||||||
|
uint64_t load_address;
|
||||||
|
|
||||||
|
/* SHA-256 hash digest */
|
||||||
|
uint8_t digest[BDB_SHA256_DIGEST_SIZE];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
#endif /* VBOOT_REFERENCE_BDB_STRUCT_H_ */
|
||||||
|
|
||||||
492
firmware/coreboot/3rdparty/vboot/bdb/bdb_test.c
vendored
Normal file
492
firmware/coreboot/3rdparty/vboot/bdb/bdb_test.c
vendored
Normal file
@@ -0,0 +1,492 @@
|
|||||||
|
/* Copyright (c) 2015 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.
|
||||||
|
*
|
||||||
|
* Unit tests
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "bdb.h"
|
||||||
|
#include "host.h"
|
||||||
|
|
||||||
|
#define TEST_EQ(got, want) test_eq(got, want, #got, #want, __LINE__)
|
||||||
|
|
||||||
|
void test_eq(int got, int want, const char *gotstr, const char *wantstr,
|
||||||
|
int line)
|
||||||
|
{
|
||||||
|
if (got == want)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fprintf(stderr, "Fail(%d): %s != %s\n"
|
||||||
|
"got: 0x%08x (%d)\n"
|
||||||
|
"wanted: 0x%08x (%d)\n",
|
||||||
|
line, gotstr, wantstr, got, got, want, want);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void check_header_tests(void)
|
||||||
|
{
|
||||||
|
struct bdb_header sgood = {
|
||||||
|
.struct_magic = BDB_HEADER_MAGIC,
|
||||||
|
.struct_major_version = BDB_HEADER_VERSION_MAJOR,
|
||||||
|
.struct_minor_version = BDB_HEADER_VERSION_MINOR,
|
||||||
|
.struct_size = sizeof(struct bdb_header),
|
||||||
|
.bdb_load_address = -1,
|
||||||
|
.bdb_size = 1024,
|
||||||
|
.signed_size = 512,
|
||||||
|
.oem_area_0_size = 256,
|
||||||
|
};
|
||||||
|
const size_t ssize = sgood.struct_size;
|
||||||
|
struct bdb_header s;
|
||||||
|
|
||||||
|
s = sgood;
|
||||||
|
TEST_EQ(bdb_check_header(&s, ssize), BDB_SUCCESS);
|
||||||
|
TEST_EQ(bdb_check_header(&s, ssize - 1), BDB_ERROR_BUF_SIZE);
|
||||||
|
|
||||||
|
s = sgood;
|
||||||
|
s.struct_size++;
|
||||||
|
TEST_EQ(bdb_check_header(&s, ssize), BDB_ERROR_BUF_SIZE);
|
||||||
|
|
||||||
|
s = sgood;
|
||||||
|
s.struct_size--;
|
||||||
|
TEST_EQ(bdb_check_header(&s, ssize), BDB_ERROR_STRUCT_SIZE);
|
||||||
|
|
||||||
|
s = sgood;
|
||||||
|
s.struct_magic++;
|
||||||
|
TEST_EQ(bdb_check_header(&s, ssize), BDB_ERROR_STRUCT_MAGIC);
|
||||||
|
|
||||||
|
s = sgood;
|
||||||
|
s.struct_major_version++;
|
||||||
|
TEST_EQ(bdb_check_header(&s, ssize), BDB_ERROR_STRUCT_VERSION);
|
||||||
|
|
||||||
|
s = sgood;
|
||||||
|
s.oem_area_0_size++;
|
||||||
|
TEST_EQ(bdb_check_header(&s, ssize), BDB_ERROR_OEM_AREA_SIZE);
|
||||||
|
|
||||||
|
s = sgood;
|
||||||
|
s.bdb_size = ssize - 1;
|
||||||
|
TEST_EQ(bdb_check_header(&s, ssize), BDB_ERROR_BDB_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void check_key_tests(void)
|
||||||
|
{
|
||||||
|
struct bdb_key sgood = {
|
||||||
|
.struct_magic = BDB_KEY_MAGIC,
|
||||||
|
.struct_major_version = BDB_KEY_VERSION_MAJOR,
|
||||||
|
.struct_minor_version = BDB_KEY_VERSION_MINOR,
|
||||||
|
.struct_size = (sizeof(struct bdb_key) +
|
||||||
|
BDB_RSA4096_KEY_DATA_SIZE),
|
||||||
|
.hash_alg = BDB_HASH_ALG_SHA256,
|
||||||
|
.sig_alg = BDB_SIG_ALG_RSA4096,
|
||||||
|
.key_version = 1,
|
||||||
|
.description = "Test key",
|
||||||
|
};
|
||||||
|
const size_t ssize = sgood.struct_size;
|
||||||
|
struct bdb_key s;
|
||||||
|
|
||||||
|
s = sgood;
|
||||||
|
TEST_EQ(bdb_check_key(&s, ssize), BDB_SUCCESS);
|
||||||
|
TEST_EQ(bdb_check_key(&s, ssize - 1), BDB_ERROR_BUF_SIZE);
|
||||||
|
|
||||||
|
s = sgood;
|
||||||
|
s.struct_size++;
|
||||||
|
TEST_EQ(bdb_check_key(&s, ssize), BDB_ERROR_BUF_SIZE);
|
||||||
|
|
||||||
|
s = sgood;
|
||||||
|
s.struct_size--;
|
||||||
|
TEST_EQ(bdb_check_key(&s, ssize), BDB_ERROR_STRUCT_SIZE);
|
||||||
|
|
||||||
|
s = sgood;
|
||||||
|
s.struct_magic++;
|
||||||
|
TEST_EQ(bdb_check_key(&s, ssize), BDB_ERROR_STRUCT_MAGIC);
|
||||||
|
|
||||||
|
s = sgood;
|
||||||
|
s.struct_major_version++;
|
||||||
|
TEST_EQ(bdb_check_key(&s, ssize), BDB_ERROR_STRUCT_VERSION);
|
||||||
|
|
||||||
|
/* Description must contain a null */
|
||||||
|
s = sgood;
|
||||||
|
memset(s.description, 'x', sizeof(s.description));
|
||||||
|
TEST_EQ(bdb_check_key(&s, ssize), BDB_ERROR_DESCRIPTION);
|
||||||
|
|
||||||
|
/* Data AFTER the null is explicitly allowed, though */
|
||||||
|
s = sgood;
|
||||||
|
s.description[100] = 'x';
|
||||||
|
TEST_EQ(bdb_check_key(&s, ssize), BDB_SUCCESS);
|
||||||
|
|
||||||
|
/* Limited algorithm choices at present */
|
||||||
|
s = sgood;
|
||||||
|
s.hash_alg = BDB_HASH_ALG_INVALID;
|
||||||
|
TEST_EQ(bdb_check_key(&s, ssize), BDB_ERROR_HASH_ALG);
|
||||||
|
|
||||||
|
/* This works because ECDSA521 signatures are smaller than RSA4096 */
|
||||||
|
s = sgood;
|
||||||
|
s.sig_alg = BDB_SIG_ALG_ECSDSA521;
|
||||||
|
TEST_EQ(bdb_check_key(&s, ssize), BDB_SUCCESS);
|
||||||
|
|
||||||
|
s = sgood;
|
||||||
|
s.sig_alg = BDB_SIG_ALG_INVALID;
|
||||||
|
TEST_EQ(bdb_check_key(&s, ssize), BDB_ERROR_SIG_ALG);
|
||||||
|
}
|
||||||
|
|
||||||
|
void check_sig_tests(void)
|
||||||
|
{
|
||||||
|
struct bdb_sig sgood = {
|
||||||
|
.struct_magic = BDB_SIG_MAGIC,
|
||||||
|
.struct_major_version = BDB_SIG_VERSION_MAJOR,
|
||||||
|
.struct_minor_version = BDB_SIG_VERSION_MINOR,
|
||||||
|
.struct_size = sizeof(struct bdb_sig) + BDB_RSA4096_SIG_SIZE,
|
||||||
|
.hash_alg = BDB_HASH_ALG_SHA256,
|
||||||
|
.sig_alg = BDB_SIG_ALG_RSA4096,
|
||||||
|
.signed_size = 123,
|
||||||
|
.description = "Test sig",
|
||||||
|
};
|
||||||
|
const size_t ssize = sgood.struct_size;
|
||||||
|
struct bdb_sig s;
|
||||||
|
|
||||||
|
s = sgood;
|
||||||
|
TEST_EQ(bdb_check_sig(&s, ssize), BDB_SUCCESS);
|
||||||
|
TEST_EQ(bdb_check_sig(&s, ssize - 1), BDB_ERROR_BUF_SIZE);
|
||||||
|
|
||||||
|
s = sgood;
|
||||||
|
s.struct_size++;
|
||||||
|
TEST_EQ(bdb_check_sig(&s, ssize), BDB_ERROR_BUF_SIZE);
|
||||||
|
|
||||||
|
s = sgood;
|
||||||
|
s.struct_size--;
|
||||||
|
TEST_EQ(bdb_check_sig(&s, ssize), BDB_ERROR_STRUCT_SIZE);
|
||||||
|
|
||||||
|
s = sgood;
|
||||||
|
s.struct_magic++;
|
||||||
|
TEST_EQ(bdb_check_sig(&s, ssize), BDB_ERROR_STRUCT_MAGIC);
|
||||||
|
|
||||||
|
s = sgood;
|
||||||
|
s.struct_major_version++;
|
||||||
|
TEST_EQ(bdb_check_sig(&s, ssize), BDB_ERROR_STRUCT_VERSION);
|
||||||
|
|
||||||
|
/* Description must contain a null */
|
||||||
|
s = sgood;
|
||||||
|
memset(s.description, 'x', sizeof(s.description));
|
||||||
|
TEST_EQ(bdb_check_sig(&s, ssize), BDB_ERROR_DESCRIPTION);
|
||||||
|
|
||||||
|
/* Data AFTER the null is explicitly allowed, though */
|
||||||
|
s = sgood;
|
||||||
|
s.description[100] = 'x';
|
||||||
|
TEST_EQ(bdb_check_sig(&s, ssize), BDB_SUCCESS);
|
||||||
|
|
||||||
|
/* Limited algorithm choices at present */
|
||||||
|
s = sgood;
|
||||||
|
s.hash_alg = BDB_HASH_ALG_INVALID;
|
||||||
|
TEST_EQ(bdb_check_sig(&s, ssize), BDB_ERROR_HASH_ALG);
|
||||||
|
|
||||||
|
/* This works because ECDSA521 signatures are smaller than RSA4096 */
|
||||||
|
s = sgood;
|
||||||
|
s.sig_alg = BDB_SIG_ALG_ECSDSA521;
|
||||||
|
TEST_EQ(bdb_check_sig(&s, ssize), BDB_SUCCESS);
|
||||||
|
|
||||||
|
s = sgood;
|
||||||
|
s.sig_alg = BDB_SIG_ALG_INVALID;
|
||||||
|
TEST_EQ(bdb_check_sig(&s, ssize), BDB_ERROR_SIG_ALG);
|
||||||
|
}
|
||||||
|
|
||||||
|
void check_data_tests(void)
|
||||||
|
{
|
||||||
|
struct bdb_data sgood = {
|
||||||
|
.struct_magic = BDB_DATA_MAGIC,
|
||||||
|
.struct_major_version = BDB_DATA_VERSION_MAJOR,
|
||||||
|
.struct_minor_version = BDB_DATA_VERSION_MINOR,
|
||||||
|
.struct_size = sizeof(struct bdb_data),
|
||||||
|
.data_version = 1,
|
||||||
|
.oem_area_1_size = 256,
|
||||||
|
.num_hashes = 3,
|
||||||
|
.hash_entry_size = sizeof(struct bdb_hash),
|
||||||
|
.signed_size = 2048,
|
||||||
|
.description = "Test data",
|
||||||
|
};
|
||||||
|
const size_t ssize = sgood.signed_size;
|
||||||
|
struct bdb_data s;
|
||||||
|
|
||||||
|
s = sgood;
|
||||||
|
TEST_EQ(bdb_check_data(&s, ssize), BDB_SUCCESS);
|
||||||
|
TEST_EQ(bdb_check_data(&s, ssize - 1), BDB_ERROR_BUF_SIZE);
|
||||||
|
|
||||||
|
s = sgood;
|
||||||
|
s.struct_size--;
|
||||||
|
TEST_EQ(bdb_check_data(&s, ssize), BDB_ERROR_STRUCT_SIZE);
|
||||||
|
|
||||||
|
s = sgood;
|
||||||
|
s.struct_magic++;
|
||||||
|
TEST_EQ(bdb_check_data(&s, ssize), BDB_ERROR_STRUCT_MAGIC);
|
||||||
|
|
||||||
|
s = sgood;
|
||||||
|
s.struct_major_version++;
|
||||||
|
TEST_EQ(bdb_check_data(&s, ssize), BDB_ERROR_STRUCT_VERSION);
|
||||||
|
|
||||||
|
/* Description must contain a null */
|
||||||
|
s = sgood;
|
||||||
|
memset(s.description, 'x', sizeof(s.description));
|
||||||
|
TEST_EQ(bdb_check_data(&s, ssize), BDB_ERROR_DESCRIPTION);
|
||||||
|
|
||||||
|
/* Data AFTER the null is explicitly allowed, though */
|
||||||
|
s = sgood;
|
||||||
|
s.description[100] = 'x';
|
||||||
|
TEST_EQ(bdb_check_data(&s, ssize), BDB_SUCCESS);
|
||||||
|
|
||||||
|
s = sgood;
|
||||||
|
s.hash_entry_size--;
|
||||||
|
TEST_EQ(bdb_check_data(&s, ssize), BDB_ERROR_HASH_ENTRY_SIZE);
|
||||||
|
|
||||||
|
s = sgood;
|
||||||
|
s.oem_area_1_size++;
|
||||||
|
TEST_EQ(bdb_check_data(&s, ssize), BDB_ERROR_OEM_AREA_SIZE);
|
||||||
|
|
||||||
|
/* Check exact size needed */
|
||||||
|
s = sgood;
|
||||||
|
s.signed_size = sizeof(s) + s.num_hashes * sizeof(struct bdb_hash) +
|
||||||
|
s.oem_area_1_size;
|
||||||
|
TEST_EQ(bdb_check_data(&s, ssize), BDB_SUCCESS);
|
||||||
|
s.signed_size--;
|
||||||
|
TEST_EQ(bdb_check_data(&s, ssize), BDB_ERROR_SIGNED_SIZE);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO: Verify wraparound check works. That can only be tested on a
|
||||||
|
* platform where size_t is uint32_t, because otherwise a 32-bit
|
||||||
|
* oem_area_1_size can't cause wraparound.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test bdb_verify() and bdb_create()
|
||||||
|
*/
|
||||||
|
void check_bdb_verify(void)
|
||||||
|
{
|
||||||
|
uint8_t oem_area_0[32] = "Some OEM area.";
|
||||||
|
uint8_t oem_area_1[64] = "Some other OEM area.";
|
||||||
|
|
||||||
|
struct bdb_hash hash[2] = {
|
||||||
|
{
|
||||||
|
.offset = 0x10000,
|
||||||
|
.size = 0x18000,
|
||||||
|
.partition = 1,
|
||||||
|
.type = BDB_DATA_SP_RW,
|
||||||
|
.load_address = 0x100000,
|
||||||
|
.digest = {0x11, 0x11, 0x11, 0x10},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.offset = 0x28000,
|
||||||
|
.size = 0x20000,
|
||||||
|
.partition = 1,
|
||||||
|
.type = BDB_DATA_AP_RW,
|
||||||
|
.load_address = 0x200000,
|
||||||
|
.digest = {0x22, 0x22, 0x22, 0x20},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
struct bdb_create_params p = {
|
||||||
|
.bdb_load_address = 0x11223344,
|
||||||
|
.oem_area_0 = oem_area_0,
|
||||||
|
.oem_area_0_size = sizeof(oem_area_0),
|
||||||
|
.oem_area_1 = oem_area_1,
|
||||||
|
.oem_area_1_size = sizeof(oem_area_1),
|
||||||
|
.header_sig_description = "The header sig",
|
||||||
|
.data_sig_description = "The data sig",
|
||||||
|
.data_description = "Test BDB data",
|
||||||
|
.data_version = 3,
|
||||||
|
.hash = hash,
|
||||||
|
.num_hashes = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t bdbkey_digest[BDB_SHA256_DIGEST_SIZE];
|
||||||
|
struct bdb_header *hgood, *h;
|
||||||
|
size_t hsize;
|
||||||
|
|
||||||
|
/* Load keys */
|
||||||
|
p.bdbkey = bdb_create_key("testkeys/bdbkey.keyb", 100, "BDB key");
|
||||||
|
p.subkey = bdb_create_key("testkeys/subkey.keyb", 200, "Subkey");
|
||||||
|
p.private_bdbkey = read_pem("testkeys/bdbkey.pem");
|
||||||
|
p.private_subkey = read_pem("testkeys/subkey.pem");
|
||||||
|
if (!p.bdbkey || !p.subkey || !p.private_bdbkey || !p.private_subkey) {
|
||||||
|
fprintf(stderr, "Unable to load test keys\n");
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
bdb_sha256(bdbkey_digest, p.bdbkey, p.bdbkey->struct_size);
|
||||||
|
|
||||||
|
/* Create the test BDB */
|
||||||
|
hgood = bdb_create(&p);
|
||||||
|
if (!hgood) {
|
||||||
|
fprintf(stderr, "Unable to create test BDB\n");
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
hsize = hgood->bdb_size;
|
||||||
|
|
||||||
|
/* Allocate a copy we can mangle */
|
||||||
|
h = calloc(hsize, 1);
|
||||||
|
|
||||||
|
/* As created, it should pass */
|
||||||
|
memcpy(h, hgood, hsize);
|
||||||
|
TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_SUCCESS);
|
||||||
|
|
||||||
|
/* Mangle each component in turn */
|
||||||
|
memcpy(h, hgood, hsize);
|
||||||
|
h->struct_magic++;
|
||||||
|
TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_HEADER);
|
||||||
|
|
||||||
|
memcpy(h, hgood, hsize);
|
||||||
|
((struct bdb_key *)bdb_get_bdbkey(h))->struct_magic++;
|
||||||
|
TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_BDBKEY);
|
||||||
|
|
||||||
|
memcpy(h, hgood, hsize);
|
||||||
|
((struct bdb_key *)bdb_get_bdbkey(h))->key_version++;
|
||||||
|
TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_GOOD_OTHER_THAN_KEY);
|
||||||
|
|
||||||
|
memcpy(h, hgood, hsize);
|
||||||
|
h->oem_area_0_size += hsize;
|
||||||
|
TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_OEM_AREA_0);
|
||||||
|
|
||||||
|
memcpy(h, hgood, hsize);
|
||||||
|
((struct bdb_key *)bdb_get_subkey(h))->struct_magic++;
|
||||||
|
TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_SUBKEY);
|
||||||
|
|
||||||
|
memcpy(h, hgood, hsize);
|
||||||
|
((struct bdb_key *)bdb_get_subkey(h))->struct_size += 4;
|
||||||
|
TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_BDB_SIGNED_SIZE);
|
||||||
|
|
||||||
|
memcpy(h, hgood, hsize);
|
||||||
|
((struct bdb_sig *)bdb_get_header_sig(h))->struct_magic++;
|
||||||
|
TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_HEADER_SIG);
|
||||||
|
|
||||||
|
memcpy(h, hgood, hsize);
|
||||||
|
((struct bdb_sig *)bdb_get_header_sig(h))->signed_size--;
|
||||||
|
TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_HEADER_SIG);
|
||||||
|
|
||||||
|
memcpy(h, hgood, hsize);
|
||||||
|
((struct bdb_sig *)bdb_get_header_sig(h))->sig_data[0] ^= 0x42;
|
||||||
|
TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_HEADER_SIG);
|
||||||
|
|
||||||
|
/* Also make sure the header sig really covers all the fields */
|
||||||
|
memcpy(h, hgood, hsize);
|
||||||
|
((struct bdb_key *)bdb_get_subkey(h))->key_version++;
|
||||||
|
TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_HEADER_SIG);
|
||||||
|
|
||||||
|
memcpy(h, hgood, hsize);
|
||||||
|
((uint8_t *)bdb_get_oem_area_0(h))[0] ^= 0x42;
|
||||||
|
TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_HEADER_SIG);
|
||||||
|
|
||||||
|
memcpy(h, hgood, hsize);
|
||||||
|
((uint8_t *)bdb_get_oem_area_0(h))[p.oem_area_0_size - 1] ^= 0x24;
|
||||||
|
TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_HEADER_SIG);
|
||||||
|
|
||||||
|
/* Check data header */
|
||||||
|
memcpy(h, hgood, hsize);
|
||||||
|
((struct bdb_data *)bdb_get_data(h))->struct_magic++;
|
||||||
|
TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_DATA);
|
||||||
|
|
||||||
|
memcpy(h, hgood, hsize);
|
||||||
|
((struct bdb_sig *)bdb_get_data_sig(h))->struct_magic++;
|
||||||
|
TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_DATA_SIG);
|
||||||
|
|
||||||
|
memcpy(h, hgood, hsize);
|
||||||
|
((struct bdb_sig *)bdb_get_data_sig(h))->signed_size--;
|
||||||
|
TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_DATA_SIG);
|
||||||
|
|
||||||
|
memcpy(h, hgood, hsize);
|
||||||
|
((struct bdb_sig *)bdb_get_data_sig(h))->sig_data[0] ^= 0x42;
|
||||||
|
TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_DATA_SIG);
|
||||||
|
|
||||||
|
/* Also make sure the data sig really covers all the fields */
|
||||||
|
memcpy(h, hgood, hsize);
|
||||||
|
((struct bdb_data *)bdb_get_data(h))->data_version--;
|
||||||
|
TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_DATA_SIG);
|
||||||
|
|
||||||
|
memcpy(h, hgood, hsize);
|
||||||
|
((uint8_t *)bdb_get_oem_area_1(h))[0] ^= 0x42;
|
||||||
|
TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_DATA_SIG);
|
||||||
|
|
||||||
|
memcpy(h, hgood, hsize);
|
||||||
|
((uint8_t *)bdb_get_oem_area_1(h))[p.oem_area_1_size - 1] ^= 0x24;
|
||||||
|
TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_DATA_SIG);
|
||||||
|
|
||||||
|
memcpy(h, hgood, hsize);
|
||||||
|
((struct bdb_hash *)bdb_get_hash(h, BDB_DATA_SP_RW))->offset++;
|
||||||
|
TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_DATA_SIG);
|
||||||
|
|
||||||
|
memcpy(h, hgood, hsize);
|
||||||
|
((struct bdb_hash *)bdb_get_hash(h, BDB_DATA_AP_RW))->digest[0] ^= 0x96;
|
||||||
|
TEST_EQ(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_DATA_SIG);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is also a convenient place to test that all the parameters we
|
||||||
|
* fed into bdb_create() also worked. That also tests all the
|
||||||
|
* bdb_get_*() functions.
|
||||||
|
*/
|
||||||
|
memcpy(h, hgood, hsize);
|
||||||
|
TEST_EQ(h->bdb_load_address, p.bdb_load_address);
|
||||||
|
|
||||||
|
TEST_EQ(strcmp(bdb_get_bdbkey(h)->description,
|
||||||
|
p.bdbkey->description), 0);
|
||||||
|
TEST_EQ(bdb_get_bdbkey(h)->key_version, p.bdbkey->key_version);
|
||||||
|
|
||||||
|
TEST_EQ(h->oem_area_0_size, p.oem_area_0_size);
|
||||||
|
TEST_EQ(memcmp(bdb_get_oem_area_0(h), oem_area_0, sizeof(oem_area_0)),
|
||||||
|
0);
|
||||||
|
|
||||||
|
TEST_EQ(strcmp(bdb_get_subkey(h)->description, p.subkey->description),
|
||||||
|
0);
|
||||||
|
TEST_EQ(bdb_get_subkey(h)->key_version, p.subkey->key_version);
|
||||||
|
|
||||||
|
TEST_EQ(strcmp(bdb_get_header_sig(h)->description,
|
||||||
|
p.header_sig_description), 0);
|
||||||
|
|
||||||
|
TEST_EQ(strcmp(bdb_get_data(h)->description, p.data_description), 0);
|
||||||
|
TEST_EQ(bdb_get_data(h)->data_version, p.data_version);
|
||||||
|
TEST_EQ(bdb_get_data(h)->num_hashes, p.num_hashes);
|
||||||
|
|
||||||
|
TEST_EQ(bdb_get_data(h)->oem_area_1_size, p.oem_area_1_size);
|
||||||
|
TEST_EQ(memcmp(bdb_get_oem_area_1(h), oem_area_1, sizeof(oem_area_1)),
|
||||||
|
0);
|
||||||
|
|
||||||
|
TEST_EQ(strcmp(bdb_get_data_sig(h)->description,
|
||||||
|
p.data_sig_description), 0);
|
||||||
|
|
||||||
|
/* Test getting hash entries */
|
||||||
|
memcpy(h, hgood, hsize);
|
||||||
|
TEST_EQ(bdb_get_hash(h, BDB_DATA_SP_RW)->offset, hash[0].offset);
|
||||||
|
TEST_EQ(bdb_get_hash(h, BDB_DATA_AP_RW)->offset, hash[1].offset);
|
||||||
|
/* And a non-existent one */
|
||||||
|
TEST_EQ(bdb_get_hash(h, BDB_DATA_MCU)!=NULL, 0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO: Verify wraparound checks works. That can only be tested on a
|
||||||
|
* platform where size_t is uint32_t, because otherwise a 32-bit
|
||||||
|
* oem_area_1_size can't cause wraparound.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Free keys and buffers */
|
||||||
|
free(p.bdbkey);
|
||||||
|
free(p.subkey);
|
||||||
|
RSA_free(p.private_bdbkey);
|
||||||
|
RSA_free(p.private_subkey);
|
||||||
|
free(hgood);
|
||||||
|
free(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
printf("Running tests...\n");
|
||||||
|
|
||||||
|
check_header_tests();
|
||||||
|
check_key_tests();
|
||||||
|
check_sig_tests();
|
||||||
|
check_data_tests();
|
||||||
|
check_bdb_verify();
|
||||||
|
|
||||||
|
printf("All tests passed!\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
200
firmware/coreboot/3rdparty/vboot/bdb/dump_rsa.c
vendored
Normal file
200
firmware/coreboot/3rdparty/vboot/bdb/dump_rsa.c
vendored
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
/* Copyright (c) 2010 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* C port of DumpPublicKey.java from the Android Open source project with
|
||||||
|
* support for additional RSA key sizes. (platform/system/core,git/libmincrypt
|
||||||
|
* /tools/DumpPublicKey.java). Uses the OpenSSL X509 and BIGNUM library.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <openssl/pem.h>
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Command line tool to extract RSA public keys from X.509 certificates and
|
||||||
|
* output a pre-processed version of keys for use by RSA verification routines.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int check(RSA *key)
|
||||||
|
{
|
||||||
|
int public_exponent = BN_get_word(key->e);
|
||||||
|
int modulus = BN_num_bits(key->n);
|
||||||
|
|
||||||
|
if (public_exponent != 65537 && public_exponent != 3) {
|
||||||
|
fprintf(stderr, "WARNING: Non-standard public exponent %d.\n",
|
||||||
|
public_exponent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modulus != 1024 && modulus != 2048 && modulus != 3072 &&
|
||||||
|
modulus != 4096 && modulus != 8192) {
|
||||||
|
fprintf(stderr, "WARNING: Non-standard modulus length = %d.\n",
|
||||||
|
modulus);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pre-processes and outputs RSA public key to standard output.
|
||||||
|
*/
|
||||||
|
void output(RSA *key)
|
||||||
|
{
|
||||||
|
BIGNUM *N;
|
||||||
|
BIGNUM *Big1 = NULL, *Big2 = NULL, *Big32 = NULL, *BigMinus1 = NULL;
|
||||||
|
BIGNUM *B = NULL;
|
||||||
|
BIGNUM *N0inv= NULL, *R = NULL, *RR = NULL, *RRTemp = NULL;
|
||||||
|
BIGNUM *NnumBits = NULL;
|
||||||
|
BIGNUM *n = NULL, *rr = NULL;
|
||||||
|
BN_CTX *bn_ctx = BN_CTX_new();
|
||||||
|
uint32_t n0invout;
|
||||||
|
int nwords, i;
|
||||||
|
|
||||||
|
N = key->n;
|
||||||
|
/* Output size of RSA key in 32-bit words */
|
||||||
|
nwords = BN_num_bits(N) / 32;
|
||||||
|
if (-1 == write(1, &nwords, sizeof(nwords)))
|
||||||
|
goto failure;
|
||||||
|
|
||||||
|
/* Initialize BIGNUMs */
|
||||||
|
Big1 = BN_new();
|
||||||
|
Big2 = BN_new();
|
||||||
|
Big32 = BN_new();
|
||||||
|
BigMinus1 = BN_new();
|
||||||
|
N0inv= BN_new();
|
||||||
|
R = BN_new();
|
||||||
|
RR = BN_new();
|
||||||
|
RRTemp = BN_new();
|
||||||
|
NnumBits = BN_new();
|
||||||
|
n = BN_new();
|
||||||
|
rr = BN_new();
|
||||||
|
|
||||||
|
BN_set_word(Big1, 1L);
|
||||||
|
BN_set_word(Big2, 2L);
|
||||||
|
BN_set_word(Big32, 32L);
|
||||||
|
BN_sub(BigMinus1, Big1, Big2);
|
||||||
|
|
||||||
|
B = BN_new();
|
||||||
|
BN_exp(B, Big2, Big32, bn_ctx); /* B = 2^32 */
|
||||||
|
|
||||||
|
/* Calculate and output N0inv = -1 / N[0] mod 2^32 */
|
||||||
|
BN_mod_inverse(N0inv, N, B, bn_ctx);
|
||||||
|
BN_sub(N0inv, B, N0inv);
|
||||||
|
n0invout = BN_get_word(N0inv);
|
||||||
|
if (-1 == write(1, &n0invout, sizeof(n0invout)))
|
||||||
|
goto failure;
|
||||||
|
|
||||||
|
/* Calculate R = 2^(# of key bits) */
|
||||||
|
BN_set_word(NnumBits, BN_num_bits(N));
|
||||||
|
BN_exp(R, Big2, NnumBits, bn_ctx);
|
||||||
|
|
||||||
|
/* Calculate RR = R^2 mod N */
|
||||||
|
BN_copy(RR, R);
|
||||||
|
BN_mul(RRTemp, RR, R, bn_ctx);
|
||||||
|
BN_mod(RR, RRTemp, N, bn_ctx);
|
||||||
|
|
||||||
|
/* Write out modulus as little endian array of integers. */
|
||||||
|
for (i = 0; i < nwords; ++i) {
|
||||||
|
uint32_t nout;
|
||||||
|
|
||||||
|
BN_mod(n, N, B, bn_ctx); /* n = N mod B */
|
||||||
|
nout = BN_get_word(n);
|
||||||
|
if (-1 == write(1, &nout, sizeof(nout)))
|
||||||
|
goto failure;
|
||||||
|
|
||||||
|
BN_rshift(N, N, 32); /* N = N/B */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write R^2 as little endian array of integers. */
|
||||||
|
for (i = 0; i < nwords; ++i) {
|
||||||
|
uint32_t rrout;
|
||||||
|
|
||||||
|
BN_mod(rr, RR, B, bn_ctx); /* rr = RR mod B */
|
||||||
|
rrout = BN_get_word(rr);
|
||||||
|
if (-1 == write(1, &rrout, sizeof(rrout)))
|
||||||
|
goto failure;
|
||||||
|
|
||||||
|
BN_rshift(RR, RR, 32); /* RR = RR/B */
|
||||||
|
}
|
||||||
|
|
||||||
|
failure:
|
||||||
|
/* Free BIGNUMs. */
|
||||||
|
BN_free(Big1);
|
||||||
|
BN_free(Big2);
|
||||||
|
BN_free(Big32);
|
||||||
|
BN_free(BigMinus1);
|
||||||
|
BN_free(N0inv);
|
||||||
|
BN_free(R);
|
||||||
|
BN_free(RRTemp);
|
||||||
|
BN_free(NnumBits);
|
||||||
|
BN_free(n);
|
||||||
|
BN_free(rr);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
int cert_mode = 0;
|
||||||
|
FILE* fp;
|
||||||
|
X509* cert = NULL;
|
||||||
|
RSA* pubkey = NULL;
|
||||||
|
EVP_PKEY* key;
|
||||||
|
char *progname;
|
||||||
|
|
||||||
|
if (argc != 3 ||
|
||||||
|
(strcmp(argv[1], "-cert") && strcmp(argv[1], "-pub"))) {
|
||||||
|
progname = strrchr(argv[0], '/');
|
||||||
|
if (progname)
|
||||||
|
progname++;
|
||||||
|
else
|
||||||
|
progname = argv[0];
|
||||||
|
fprintf(stderr, "Usage: %s <-cert | -pub> <file>\n", progname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(argv[1], "-cert"))
|
||||||
|
cert_mode = 1;
|
||||||
|
|
||||||
|
fp = fopen(argv[2], "r");
|
||||||
|
|
||||||
|
if (!fp) {
|
||||||
|
fprintf(stderr, "Couldn't open file %s!\n", argv[2]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cert_mode) {
|
||||||
|
/* Read the certificate */
|
||||||
|
if (!PEM_read_X509(fp, &cert, NULL, NULL)) {
|
||||||
|
fprintf(stderr, "Couldn't read certificate.\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the public key from the certificate. */
|
||||||
|
key = X509_get_pubkey(cert);
|
||||||
|
|
||||||
|
/* Convert to a RSA_style key. */
|
||||||
|
if (!(pubkey = EVP_PKEY_get1_RSA(key))) {
|
||||||
|
fprintf(stderr, "Couldn't convert to RSA style key.\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Read the pubkey in .PEM format. */
|
||||||
|
if (!(pubkey = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL))) {
|
||||||
|
fprintf(stderr, "Couldn't read public key file.\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check(pubkey)) {
|
||||||
|
output(pubkey);
|
||||||
|
}
|
||||||
|
|
||||||
|
fail:
|
||||||
|
X509_free(cert);
|
||||||
|
RSA_free(pubkey);
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
17
firmware/coreboot/3rdparty/vboot/bdb/ecdsa.c
vendored
Normal file
17
firmware/coreboot/3rdparty/vboot/bdb/ecdsa.c
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
/* Copyright (c) 2015 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.
|
||||||
|
*
|
||||||
|
* Boot descriptor block firmware ECDSA stub
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "bdb.h"
|
||||||
|
|
||||||
|
int bdb_ecdsa521_verify(const uint8_t *key_data,
|
||||||
|
const uint8_t *sig,
|
||||||
|
const uint8_t *digest)
|
||||||
|
{
|
||||||
|
/* This is just a stub */
|
||||||
|
return BDB_ERROR_DIGEST;
|
||||||
|
}
|
||||||
347
firmware/coreboot/3rdparty/vboot/bdb/host.c
vendored
Normal file
347
firmware/coreboot/3rdparty/vboot/bdb/host.c
vendored
Normal file
@@ -0,0 +1,347 @@
|
|||||||
|
/* Copyright (c) 2015 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.
|
||||||
|
*
|
||||||
|
* Host functions for signing
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "bdb.h"
|
||||||
|
#include "host.h"
|
||||||
|
|
||||||
|
char *strzcpy(char *dest, const char *src, size_t size)
|
||||||
|
{
|
||||||
|
strncpy(dest, src, size);
|
||||||
|
dest[size - 1] = 0;
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *read_file(const char *filename, uint32_t *size_ptr)
|
||||||
|
{
|
||||||
|
FILE *f;
|
||||||
|
uint8_t *buf;
|
||||||
|
long size;
|
||||||
|
|
||||||
|
*size_ptr = 0;
|
||||||
|
|
||||||
|
f = fopen(filename, "rb");
|
||||||
|
if (!f) {
|
||||||
|
fprintf(stderr, "Unable to open file %s\n", filename);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(f, 0, SEEK_END);
|
||||||
|
size = ftell(f);
|
||||||
|
rewind(f);
|
||||||
|
|
||||||
|
if (size < 0 || size > UINT32_MAX) {
|
||||||
|
fclose(f);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf = malloc(size);
|
||||||
|
if (!buf) {
|
||||||
|
fclose(f);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (1 != fread(buf, size, 1, f)) {
|
||||||
|
fprintf(stderr, "Unable to read file %s\n", filename);
|
||||||
|
fclose(f);
|
||||||
|
free(buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
*size_ptr = size;
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
int write_file(const char *filename, const void *buf, uint32_t size)
|
||||||
|
{
|
||||||
|
FILE *f = fopen(filename, "wb");
|
||||||
|
|
||||||
|
if (!f) {
|
||||||
|
fprintf(stderr, "Unable to open file %s\n", filename);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (1 != fwrite(buf, size, 1, f)) {
|
||||||
|
fprintf(stderr, "Unable to write to file %s\n", filename);
|
||||||
|
fclose(f);
|
||||||
|
unlink(filename); /* Delete any partial file */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct rsa_st *read_pem(const char *filename)
|
||||||
|
{
|
||||||
|
struct rsa_st *pem;
|
||||||
|
FILE *f;
|
||||||
|
|
||||||
|
/* Read private key */
|
||||||
|
f = fopen(filename, "rb");
|
||||||
|
if (!f) {
|
||||||
|
fprintf(stderr, "%s: unable to read key from %s\n",
|
||||||
|
__func__, filename);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pem = PEM_read_RSAPrivateKey(f, NULL, NULL, NULL);
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
return pem;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct bdb_key *bdb_create_key(const char *filename,
|
||||||
|
uint32_t key_version,
|
||||||
|
const char *desc)
|
||||||
|
{
|
||||||
|
uint32_t sig_alg;
|
||||||
|
size_t key_size = sizeof(struct bdb_key);
|
||||||
|
struct bdb_key *k;
|
||||||
|
uint8_t *kdata;
|
||||||
|
uint32_t kdata_size = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read key data. Somewhat lame assumption that we can determine the
|
||||||
|
* signature algorithm from the key size, but it's true right now.
|
||||||
|
*/
|
||||||
|
kdata = read_file(filename, &kdata_size);
|
||||||
|
if (kdata_size == BDB_RSA4096_KEY_DATA_SIZE) {
|
||||||
|
sig_alg = BDB_SIG_ALG_RSA4096;
|
||||||
|
} else if (kdata_size == BDB_RSA3072B_KEY_DATA_SIZE) {
|
||||||
|
sig_alg = BDB_SIG_ALG_RSA3072B;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "%s: bad key size from %s\n",
|
||||||
|
__func__, filename);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
key_size += kdata_size;
|
||||||
|
|
||||||
|
/* Allocate buffer */
|
||||||
|
k = (struct bdb_key *)calloc(key_size, 1);
|
||||||
|
if (!k) {
|
||||||
|
free(kdata);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
k->struct_magic = BDB_KEY_MAGIC;
|
||||||
|
k->struct_major_version = BDB_KEY_VERSION_MAJOR;
|
||||||
|
k->struct_minor_version = BDB_KEY_VERSION_MINOR;
|
||||||
|
k->struct_size = key_size;
|
||||||
|
k->hash_alg = BDB_HASH_ALG_SHA256;
|
||||||
|
k->sig_alg = sig_alg;
|
||||||
|
k->key_version = key_version;
|
||||||
|
|
||||||
|
/* Copy description, if any */
|
||||||
|
if (desc)
|
||||||
|
strzcpy(k->description, desc, sizeof(k->description));
|
||||||
|
|
||||||
|
/* Copy key data */
|
||||||
|
memcpy(k->key_data, kdata, kdata_size);
|
||||||
|
free(kdata);
|
||||||
|
|
||||||
|
return k;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct bdb_sig *bdb_create_sig(const void *data,
|
||||||
|
size_t size,
|
||||||
|
struct rsa_st *key,
|
||||||
|
uint32_t sig_alg,
|
||||||
|
const char *desc)
|
||||||
|
{
|
||||||
|
static const uint8_t info[] = {
|
||||||
|
0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
|
||||||
|
0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
|
||||||
|
0x00, 0x04, 0x20
|
||||||
|
};
|
||||||
|
|
||||||
|
size_t sig_size = sizeof(struct bdb_sig);
|
||||||
|
uint8_t digest[sizeof(info) + BDB_SHA256_DIGEST_SIZE];
|
||||||
|
struct bdb_sig *sig;
|
||||||
|
|
||||||
|
if (size >= UINT32_MAX)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
switch(sig_alg) {
|
||||||
|
case BDB_SIG_ALG_RSA4096:
|
||||||
|
sig_size += BDB_RSA4096_SIG_SIZE;
|
||||||
|
break;
|
||||||
|
case BDB_SIG_ALG_RSA3072B:
|
||||||
|
sig_size += BDB_RSA3072B_SIG_SIZE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "%s: bad signature algorithm %d\n",
|
||||||
|
__func__, sig_alg);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate buffer */
|
||||||
|
sig = (struct bdb_sig *)calloc(sig_size, 1);
|
||||||
|
if (!sig)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
sig->struct_magic = BDB_SIG_MAGIC;
|
||||||
|
sig->struct_major_version = BDB_SIG_VERSION_MAJOR;
|
||||||
|
sig->struct_minor_version = BDB_SIG_VERSION_MINOR;
|
||||||
|
sig->struct_size = sig_size;
|
||||||
|
sig->hash_alg = BDB_HASH_ALG_SHA256;
|
||||||
|
sig->sig_alg = sig_alg;
|
||||||
|
sig->signed_size = size;
|
||||||
|
|
||||||
|
/* Copy description, if any */
|
||||||
|
if (desc)
|
||||||
|
strzcpy(sig->description, desc, sizeof(sig->description));
|
||||||
|
|
||||||
|
/* Calculate info-padded digest */
|
||||||
|
memcpy(digest, info, sizeof(info));
|
||||||
|
if (bdb_sha256(digest + sizeof(info), data, size)) {
|
||||||
|
free(sig);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* RSA-encrypt the signature */
|
||||||
|
if (RSA_private_encrypt(sizeof(digest),
|
||||||
|
digest,
|
||||||
|
sig->sig_data,
|
||||||
|
key,
|
||||||
|
RSA_PKCS1_PADDING) == -1) {
|
||||||
|
free(sig);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return sig;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct bdb_header *bdb_create(struct bdb_create_params *p)
|
||||||
|
{
|
||||||
|
size_t bdb_size = 0;
|
||||||
|
size_t sig_size = sizeof(struct bdb_sig) + BDB_RSA4096_SIG_SIZE;
|
||||||
|
size_t hashes_size = sizeof(struct bdb_hash) * p->num_hashes;
|
||||||
|
uint8_t *buf, *bnext;
|
||||||
|
struct bdb_header *h;
|
||||||
|
struct bdb_sig *sig;
|
||||||
|
struct bdb_data *data;
|
||||||
|
const void *oem;
|
||||||
|
|
||||||
|
/* We can do some checks before we even allocate the buffer */
|
||||||
|
|
||||||
|
/* Make sure OEM sizes are aligned */
|
||||||
|
if ((p->oem_area_0_size & 3) || (p->oem_area_1_size & 3)) {
|
||||||
|
fprintf(stderr, "%s: OEM areas not 32-bit aligned\n",
|
||||||
|
__func__);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hash count must fit in uint8_t */
|
||||||
|
if (p->num_hashes > 255) {
|
||||||
|
fprintf(stderr, "%s: too many hashes\n", __func__);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculate BDB size */
|
||||||
|
bdb_size = sizeof(struct bdb_header);
|
||||||
|
bdb_size += p->bdbkey->struct_size;
|
||||||
|
bdb_size += p->oem_area_0_size;
|
||||||
|
bdb_size += p->subkey->struct_size;
|
||||||
|
bdb_size += sig_size;
|
||||||
|
bdb_size += sizeof(struct bdb_data);
|
||||||
|
bdb_size += p->oem_area_1_size;
|
||||||
|
bdb_size += sizeof(struct bdb_hash) * p->num_hashes;
|
||||||
|
bdb_size += sig_size;
|
||||||
|
|
||||||
|
/* Make sure it fits */
|
||||||
|
if (bdb_size > UINT32_MAX) {
|
||||||
|
fprintf(stderr, "%s: BDB size > UINT32_MAX\n", __func__);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate a buffer */
|
||||||
|
bnext = buf = calloc(bdb_size, 1);
|
||||||
|
if (!buf) {
|
||||||
|
fprintf(stderr, "%s: can't allocate buffer\n", __func__);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fill in the header */
|
||||||
|
h = (struct bdb_header *)bnext;
|
||||||
|
h->struct_magic = BDB_HEADER_MAGIC;
|
||||||
|
h->struct_major_version = BDB_HEADER_VERSION_MAJOR;
|
||||||
|
h->struct_minor_version = BDB_HEADER_VERSION_MINOR;
|
||||||
|
h->struct_size = sizeof(*h);
|
||||||
|
h->bdb_load_address = p->bdb_load_address;
|
||||||
|
h->bdb_size = bdb_size;
|
||||||
|
h->signed_size = p->oem_area_0_size + p->subkey->struct_size;
|
||||||
|
h->oem_area_0_size = p->oem_area_0_size;
|
||||||
|
bnext += h->struct_size;
|
||||||
|
|
||||||
|
/* Copy BDB key */
|
||||||
|
memcpy(bnext, p->bdbkey, p->bdbkey->struct_size);
|
||||||
|
bnext += p->bdbkey->struct_size;
|
||||||
|
|
||||||
|
/* Copy OEM area 0 */
|
||||||
|
oem = bnext;
|
||||||
|
if (p->oem_area_0_size) {
|
||||||
|
memcpy(bnext, p->oem_area_0, p->oem_area_0_size);
|
||||||
|
bnext += p->oem_area_0_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy subkey */
|
||||||
|
memcpy(bnext, p->subkey, p->subkey->struct_size);
|
||||||
|
bnext += p->subkey->struct_size;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create header signature using private BDB key.
|
||||||
|
*
|
||||||
|
* TODO: create the header signature in a totally separate step. That
|
||||||
|
* way, the private BDB key is not required each time a BDB is created.
|
||||||
|
*/
|
||||||
|
sig = bdb_create_sig(oem, h->signed_size, p->private_bdbkey,
|
||||||
|
p->bdbkey->sig_alg, p->header_sig_description);
|
||||||
|
memcpy(bnext, sig, sig->struct_size);
|
||||||
|
bnext += sig->struct_size;
|
||||||
|
|
||||||
|
/* Fill in the data */
|
||||||
|
data = (struct bdb_data *)bnext;
|
||||||
|
data->struct_magic = BDB_DATA_MAGIC;
|
||||||
|
data->struct_major_version = BDB_DATA_VERSION_MAJOR;
|
||||||
|
data->struct_minor_version = BDB_DATA_VERSION_MINOR;
|
||||||
|
data->struct_size = sizeof(struct bdb_data);
|
||||||
|
data->data_version = p->data_version;
|
||||||
|
data->oem_area_1_size = p->oem_area_1_size;
|
||||||
|
data->num_hashes = p->num_hashes;
|
||||||
|
data->hash_entry_size = sizeof(struct bdb_hash);
|
||||||
|
data->signed_size = data->struct_size + data->oem_area_1_size +
|
||||||
|
hashes_size;
|
||||||
|
if (p->data_description) {
|
||||||
|
strzcpy(data->description, p->data_description,
|
||||||
|
sizeof(data->description));
|
||||||
|
}
|
||||||
|
bnext += data->struct_size;
|
||||||
|
|
||||||
|
/* Copy OEM area 1 */
|
||||||
|
oem = bnext;
|
||||||
|
if (p->oem_area_1_size) {
|
||||||
|
memcpy(bnext, p->oem_area_1, p->oem_area_1_size);
|
||||||
|
bnext += p->oem_area_1_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy hashes */
|
||||||
|
memcpy(bnext, p->hash, hashes_size);
|
||||||
|
bnext += hashes_size;
|
||||||
|
|
||||||
|
/* Create data signature using private subkey */
|
||||||
|
sig = bdb_create_sig(data, data->signed_size, p->private_subkey,
|
||||||
|
p->subkey->sig_alg, p->data_sig_description);
|
||||||
|
memcpy(bnext, sig, sig->struct_size);
|
||||||
|
|
||||||
|
/* Return the BDB */
|
||||||
|
return h;
|
||||||
|
}
|
||||||
171
firmware/coreboot/3rdparty/vboot/bdb/host.h
vendored
Normal file
171
firmware/coreboot/3rdparty/vboot/bdb/host.h
vendored
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
/* Copyright (c) 2015 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.
|
||||||
|
*
|
||||||
|
* Boot descriptor block host functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef VBOOT_REFERENCE_BDB_HOST_H_
|
||||||
|
#define VBOOT_REFERENCE_BDB_HOST_H_
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <openssl/pem.h>
|
||||||
|
#include "bdb_struct.h"
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/*
|
||||||
|
Expected calling sequence:
|
||||||
|
|
||||||
|
Load and check just the header
|
||||||
|
bdb_check_header(buf, size);
|
||||||
|
|
||||||
|
Load and verify the entire BDB
|
||||||
|
bdb_verify(buf, size, bdb_key_hash, dev_mode_flag);
|
||||||
|
|
||||||
|
bdb_check_header() again - paranoia against bad storage devices
|
||||||
|
|
||||||
|
bdb_check_key() on BDB key
|
||||||
|
bdb_sha256() on BDB key
|
||||||
|
Compare with appropriate root key hash
|
||||||
|
If dev_mode_flag(), mismatch is not fatal
|
||||||
|
|
||||||
|
bdb_check_sig() on BDB header sig
|
||||||
|
bdb_sha256() on OEM area 1, RW subkey
|
||||||
|
bdb_rsa_verify() on digest using BDB key
|
||||||
|
|
||||||
|
bdb_check_key() on RW subkey
|
||||||
|
|
||||||
|
bdb_check_data() on RW data
|
||||||
|
bdb_check_sig() on data sig
|
||||||
|
bdb_sha256() on data, OEM area 1, hashes
|
||||||
|
bdb_rsa_verify() on digest using RW subkey
|
||||||
|
|
||||||
|
Check RW subkey version. If normal boot from primary BDB, roll forward
|
||||||
|
Check data version. If normal boot from primary BDB, roll forward
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Codes for functions returning numeric error codes */
|
||||||
|
|
||||||
|
enum bdb_host_return_code {
|
||||||
|
/* All/any of bdb_return_code, and the following... */
|
||||||
|
|
||||||
|
/* Other errors */
|
||||||
|
BDB_ERROR_HOST = 200,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Functions */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Like strncpy, but guaranteeing null termination
|
||||||
|
*/
|
||||||
|
char *strzcpy(char *dest, const char *src, size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a file.
|
||||||
|
*
|
||||||
|
* Caller must free() the returned buffer.
|
||||||
|
*
|
||||||
|
* @param filename Path to file
|
||||||
|
* @param size_ptr Destination for size of buffer
|
||||||
|
* @return A newly allocated buffer containing the data, or NULL if error.
|
||||||
|
*/
|
||||||
|
uint8_t *read_file(const char *filename, uint32_t *size_ptr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a file.
|
||||||
|
*
|
||||||
|
* @param buf Data to write
|
||||||
|
* @param size Size of data in bytes
|
||||||
|
* @return 0 if success, non-zero error code if error.
|
||||||
|
*/
|
||||||
|
int write_file(const char *filename, const void *buf, uint32_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a PEM from a file.
|
||||||
|
*
|
||||||
|
* Caller must free the PEM with RSA_free().
|
||||||
|
*
|
||||||
|
* @param filename Path to file
|
||||||
|
* @return A newly allocated PEM object, or NULL if error.
|
||||||
|
*/
|
||||||
|
struct rsa_st *read_pem(const char *filename);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a BDB public key object.
|
||||||
|
*
|
||||||
|
* Caller must free() the returned key.
|
||||||
|
*
|
||||||
|
* @param filename Path to file containing public key (.keyb)
|
||||||
|
* @param key_version Version for key
|
||||||
|
* @param desc Description. Optional; may be NULL.
|
||||||
|
* @return A newly allocated public key, or NULL if error.
|
||||||
|
*/
|
||||||
|
struct bdb_key *bdb_create_key(const char *filename,
|
||||||
|
uint32_t key_version,
|
||||||
|
const char *desc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a BDB signature object.
|
||||||
|
*
|
||||||
|
* Caller must free() the returned signature.
|
||||||
|
*
|
||||||
|
* @param data Data to sign
|
||||||
|
* @param size Size of data in bytes
|
||||||
|
* @param key PEM key
|
||||||
|
* @param sig_alg Signature algorithm
|
||||||
|
* @param desc Description. Optional; may be NULL.
|
||||||
|
* @return A newly allocated signature, or NULL if error.
|
||||||
|
*/
|
||||||
|
struct bdb_sig *bdb_create_sig(const void *data,
|
||||||
|
size_t size,
|
||||||
|
struct rsa_st *key,
|
||||||
|
uint32_t sig_alg,
|
||||||
|
const char *desc);
|
||||||
|
|
||||||
|
struct bdb_create_params
|
||||||
|
{
|
||||||
|
/* Load address */
|
||||||
|
uint64_t bdb_load_address;
|
||||||
|
|
||||||
|
/* OEM areas. Size may be 0, in which case the buffer is ignored */
|
||||||
|
uint8_t *oem_area_0;
|
||||||
|
uint32_t oem_area_0_size;
|
||||||
|
uint8_t *oem_area_1;
|
||||||
|
uint32_t oem_area_1_size;
|
||||||
|
|
||||||
|
/* Public BDB key and subkey */
|
||||||
|
struct bdb_key *bdbkey;
|
||||||
|
struct bdb_key *subkey;
|
||||||
|
|
||||||
|
/* Private BDB key and subkey */
|
||||||
|
struct rsa_st *private_bdbkey;
|
||||||
|
struct rsa_st *private_subkey;
|
||||||
|
|
||||||
|
/* Descriptions for header and data signatures */
|
||||||
|
char *header_sig_description;
|
||||||
|
char *data_sig_description;
|
||||||
|
|
||||||
|
/* Data description and version */
|
||||||
|
char *data_description;
|
||||||
|
uint32_t data_version;
|
||||||
|
|
||||||
|
/* Data hashes and count */
|
||||||
|
struct bdb_hash *hash;
|
||||||
|
uint32_t num_hashes;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new BDB
|
||||||
|
*
|
||||||
|
* Caller must free() returned object.
|
||||||
|
*
|
||||||
|
* @param p Creation parameters
|
||||||
|
* @return A newly allocated BDB, or NULL if error.
|
||||||
|
*/
|
||||||
|
struct bdb_header *bdb_create(struct bdb_create_params *p);
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
#endif /* VBOOT_REFERENCE_BDB_HOST_H_ */
|
||||||
339
firmware/coreboot/3rdparty/vboot/bdb/rsa.c
vendored
Normal file
339
firmware/coreboot/3rdparty/vboot/bdb/rsa.c
vendored
Normal file
@@ -0,0 +1,339 @@
|
|||||||
|
/* Copyright (c) 2015 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.
|
||||||
|
*
|
||||||
|
* Boot descriptor block firmware RSA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "bdb.h"
|
||||||
|
|
||||||
|
/* Public key structure in RAM */
|
||||||
|
struct public_key {
|
||||||
|
uint32_t arrsize; /* Size of n[] and rr[] arrays in elements */
|
||||||
|
uint32_t n0inv; /* -1 / n[0] mod 2^32 */
|
||||||
|
const uint32_t *n; /* Modulus as little endian array */
|
||||||
|
const uint32_t *rr; /* R^2 as little endian array */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* a[] -= mod
|
||||||
|
*/
|
||||||
|
static void subM(const struct public_key *key, uint32_t *a)
|
||||||
|
{
|
||||||
|
int64_t A = 0;
|
||||||
|
uint32_t i;
|
||||||
|
for (i = 0; i < key->arrsize; ++i) {
|
||||||
|
A += (uint64_t)a[i] - key->n[i];
|
||||||
|
a[i] = (uint32_t)A;
|
||||||
|
A >>= 32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a[] >= mod
|
||||||
|
*/
|
||||||
|
int vb2_mont_ge(const struct public_key *key, uint32_t *a)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
for (i = key->arrsize; i;) {
|
||||||
|
--i;
|
||||||
|
if (a[i] < key->n[i])
|
||||||
|
return 0;
|
||||||
|
if (a[i] > key->n[i])
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 1; /* equal */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Montgomery c[] += a * b[] / R % mod
|
||||||
|
*/
|
||||||
|
static void montMulAdd(const struct public_key *key,
|
||||||
|
uint32_t *c,
|
||||||
|
const uint32_t a,
|
||||||
|
const uint32_t *b)
|
||||||
|
{
|
||||||
|
uint64_t A = (uint64_t)a * b[0] + c[0];
|
||||||
|
uint32_t d0 = (uint32_t)A * key->n0inv;
|
||||||
|
uint64_t B = (uint64_t)d0 * key->n[0] + (uint32_t)A;
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
for (i = 1; i < key->arrsize; ++i) {
|
||||||
|
A = (A >> 32) + (uint64_t)a * b[i] + c[i];
|
||||||
|
B = (B >> 32) + (uint64_t)d0 * key->n[i] + (uint32_t)A;
|
||||||
|
c[i - 1] = (uint32_t)B;
|
||||||
|
}
|
||||||
|
|
||||||
|
A = (A >> 32) + (B >> 32);
|
||||||
|
|
||||||
|
c[i - 1] = (uint32_t)A;
|
||||||
|
|
||||||
|
if (A >> 32) {
|
||||||
|
subM(key, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Montgomery c[] = a[] * b[] / R % mod
|
||||||
|
*/
|
||||||
|
static void montMul(const struct public_key *key,
|
||||||
|
uint32_t *c,
|
||||||
|
const uint32_t *a,
|
||||||
|
const uint32_t *b)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
for (i = 0; i < key->arrsize; ++i) {
|
||||||
|
c[i] = 0;
|
||||||
|
}
|
||||||
|
for (i = 0; i < key->arrsize; ++i) {
|
||||||
|
montMulAdd(key, c, a[i], b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int vb2_safe_memcmp(const void *s1, const void *s2, size_t size)
|
||||||
|
{
|
||||||
|
const unsigned char *us1 = s1;
|
||||||
|
const unsigned char *us2 = s2;
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
if (0 == size)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Code snippet without data-dependent branch due to Nate Lawson
|
||||||
|
* (nate@root.org) of Root Labs.
|
||||||
|
*/
|
||||||
|
while (size--)
|
||||||
|
result |= *us1++ ^ *us2++;
|
||||||
|
|
||||||
|
return result != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PKCS 1.5 padding (from the RSA PKCS#1 v2.1 standard)
|
||||||
|
*
|
||||||
|
* Depending on the RSA key size and hash function, the padding is calculated
|
||||||
|
* as follows:
|
||||||
|
*
|
||||||
|
* 0x00 || 0x01 || PS || 0x00 || T
|
||||||
|
*
|
||||||
|
* T: DER Encoded DigestInfo value which depends on the hash function used.
|
||||||
|
*
|
||||||
|
* SHA-256: (0x)30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20 || H.
|
||||||
|
*
|
||||||
|
* Length(T) = 51 octets for SHA-256
|
||||||
|
*
|
||||||
|
* PS: octet string consisting of {Length(RSA Key) - Length(T) - 3} 0xFF
|
||||||
|
*/
|
||||||
|
static const uint8_t sha256_tail[] = {
|
||||||
|
0x00,0x30,0x31,0x30,0x0d,0x06,0x09,0x60,
|
||||||
|
0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,
|
||||||
|
0x05,0x00,0x04,0x20
|
||||||
|
};
|
||||||
|
|
||||||
|
int vb2_check_padding(const uint8_t *sig, const struct public_key *key,
|
||||||
|
uint32_t pad_size)
|
||||||
|
{
|
||||||
|
/* Determine padding to use depending on the signature type */
|
||||||
|
const uint32_t tail_size = sizeof(sha256_tail);
|
||||||
|
int result = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* First 2 bytes are always 0x00 0x01 */
|
||||||
|
result |= *sig++ ^ 0x00;
|
||||||
|
result |= *sig++ ^ 0x01;
|
||||||
|
|
||||||
|
/* Then 0xff bytes until the tail */
|
||||||
|
for (i = 0; i < pad_size - tail_size - 2; i++)
|
||||||
|
result |= *sig++ ^ 0xff;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Then the tail. Even though there are probably no timing issues
|
||||||
|
* here, we use vb2_safe_memcmp() just to be on the safe side.
|
||||||
|
*/
|
||||||
|
result |= vb2_safe_memcmp(sig, sha256_tail, tail_size);
|
||||||
|
|
||||||
|
return result ? BDB_ERROR_DIGEST : BDB_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Array size for RSA4096 */
|
||||||
|
#define ARRSIZE4096 (4096 / 32)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In-place public exponentiation. (exponent 65537, key size 4096 bits)
|
||||||
|
*
|
||||||
|
* @param key Key to use in signing
|
||||||
|
* @param inout Input and output big-endian byte array
|
||||||
|
*/
|
||||||
|
static void modpowF4(const struct public_key *key, uint8_t *inout)
|
||||||
|
{
|
||||||
|
uint32_t a[ARRSIZE4096];
|
||||||
|
uint32_t aR[ARRSIZE4096];
|
||||||
|
uint32_t aaR[ARRSIZE4096];
|
||||||
|
uint32_t *aaa = aaR; /* Re-use location. */
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Convert from big endian byte array to little endian word array. */
|
||||||
|
for (i = 0; i < ARRSIZE4096; ++i) {
|
||||||
|
uint32_t tmp =
|
||||||
|
(inout[((ARRSIZE4096 - 1 - i) * 4) + 0] << 24) |
|
||||||
|
(inout[((ARRSIZE4096 - 1 - i) * 4) + 1] << 16) |
|
||||||
|
(inout[((ARRSIZE4096 - 1 - i) * 4) + 2] << 8) |
|
||||||
|
(inout[((ARRSIZE4096 - 1 - i) * 4) + 3] << 0);
|
||||||
|
a[i] = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
montMul(key, aR, a, key->rr); /* aR = a * RR / R mod M */
|
||||||
|
for (i = 0; i < 16; i+=2) {
|
||||||
|
montMul(key, aaR, aR, aR); /* aaR = aR * aR / R mod M */
|
||||||
|
montMul(key, aR, aaR, aaR); /* aR = aaR * aaR / R mod M */
|
||||||
|
}
|
||||||
|
montMul(key, aaa, aR, a); /* aaa = aR * a / R mod M */
|
||||||
|
|
||||||
|
/* Make sure aaa < mod; aaa is at most 1x mod too large. */
|
||||||
|
if (vb2_mont_ge(key, aaa)) {
|
||||||
|
subM(key, aaa);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert to bigendian byte array */
|
||||||
|
for (i = ARRSIZE4096 - 1; i >= 0; --i) {
|
||||||
|
uint32_t tmp = aaa[i];
|
||||||
|
*inout++ = (uint8_t)(tmp >> 24);
|
||||||
|
*inout++ = (uint8_t)(tmp >> 16);
|
||||||
|
*inout++ = (uint8_t)(tmp >> 8);
|
||||||
|
*inout++ = (uint8_t)(tmp >> 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int bdb_rsa4096_verify(const uint8_t *key_data,
|
||||||
|
const uint8_t *sig,
|
||||||
|
const uint8_t *digest)
|
||||||
|
{
|
||||||
|
const uint32_t *kdata32 = (const uint32_t *)key_data;
|
||||||
|
struct public_key key;
|
||||||
|
uint8_t sig_work[BDB_RSA4096_SIG_SIZE];
|
||||||
|
uint32_t pad_size;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
/* Unpack key */
|
||||||
|
if (kdata32[0] != ARRSIZE4096)
|
||||||
|
return BDB_ERROR_DIGEST; /* Wrong key size */
|
||||||
|
|
||||||
|
key.arrsize = kdata32[0];
|
||||||
|
key.n0inv = kdata32[1];
|
||||||
|
key.n = kdata32 + 2;
|
||||||
|
key.rr = kdata32 + 2 + key.arrsize;
|
||||||
|
|
||||||
|
/* Copy signature to work buffer */
|
||||||
|
memcpy(sig_work, sig, sizeof(sig_work));
|
||||||
|
|
||||||
|
modpowF4(&key, sig_work);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check padding. Continue on to check the digest even if error to
|
||||||
|
* reduce the risk of timing based attacks.
|
||||||
|
*/
|
||||||
|
pad_size = key.arrsize * sizeof(uint32_t) - BDB_SHA256_DIGEST_SIZE;
|
||||||
|
rv = vb2_check_padding(sig_work, &key, pad_size);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check digest. Even though there are probably no timing issues here,
|
||||||
|
* use vb2_safe_memcmp() just to be on the safe side. (That's also why
|
||||||
|
* we don't return before this check if the padding check failed.)
|
||||||
|
*/
|
||||||
|
if (vb2_safe_memcmp(sig_work + pad_size, digest,
|
||||||
|
BDB_SHA256_DIGEST_SIZE))
|
||||||
|
rv = BDB_ERROR_DIGEST;
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Array size for RSA3072B */
|
||||||
|
#define ARRSIZE3072B (3072 / 32)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In-place public exponentiation. (exponent 3, key size 3072 bits)
|
||||||
|
*
|
||||||
|
* @param key Key to use in signing
|
||||||
|
* @param inout Input and output big-endian byte array
|
||||||
|
*/
|
||||||
|
static void modpow3(const struct public_key *key, uint8_t *inout)
|
||||||
|
{
|
||||||
|
uint32_t a[ARRSIZE3072B];
|
||||||
|
uint32_t aR[ARRSIZE3072B];
|
||||||
|
uint32_t aaR[ARRSIZE3072B];
|
||||||
|
uint32_t *aaa = aR; /* Re-use location */
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Convert from big endian byte array to little endian word array. */
|
||||||
|
for (i = 0; i < ARRSIZE3072B; ++i) {
|
||||||
|
uint32_t tmp =
|
||||||
|
(inout[((ARRSIZE3072B - 1 - i) * 4) + 0] << 24) |
|
||||||
|
(inout[((ARRSIZE3072B - 1 - i) * 4) + 1] << 16) |
|
||||||
|
(inout[((ARRSIZE3072B - 1 - i) * 4) + 2] << 8) |
|
||||||
|
(inout[((ARRSIZE3072B - 1 - i) * 4) + 3] << 0);
|
||||||
|
a[i] = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
montMul(key, aR, a, key->rr); /* aR = a * RR / R mod M */
|
||||||
|
montMul(key, aaR, aR, aR); /* aaR = aR * aR / R mod M */
|
||||||
|
montMul(key, aaa, aaR, a); /* aaa = aaR * a / R mod M */
|
||||||
|
|
||||||
|
/* Make sure aaa < mod; aaa is at most 1x mod too large. */
|
||||||
|
if (vb2_mont_ge(key, aaa)) {
|
||||||
|
subM(key, aaa);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert to bigendian byte array */
|
||||||
|
for (i = ARRSIZE3072B - 1; i >= 0; --i) {
|
||||||
|
uint32_t tmp = aaa[i];
|
||||||
|
*inout++ = (uint8_t)(tmp >> 24);
|
||||||
|
*inout++ = (uint8_t)(tmp >> 16);
|
||||||
|
*inout++ = (uint8_t)(tmp >> 8);
|
||||||
|
*inout++ = (uint8_t)(tmp >> 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int bdb_rsa3072b_verify(const uint8_t *key_data,
|
||||||
|
const uint8_t *sig,
|
||||||
|
const uint8_t *digest)
|
||||||
|
{
|
||||||
|
const uint32_t *kdata32 = (const uint32_t *)key_data;
|
||||||
|
struct public_key key;
|
||||||
|
uint8_t sig_work[BDB_RSA3072B_SIG_SIZE];
|
||||||
|
uint32_t pad_size;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
/* Unpack key */
|
||||||
|
if (kdata32[0] != ARRSIZE3072B)
|
||||||
|
return BDB_ERROR_DIGEST; /* Wrong key size */
|
||||||
|
|
||||||
|
key.arrsize = kdata32[0];
|
||||||
|
key.n0inv = kdata32[1];
|
||||||
|
key.n = kdata32 + 2;
|
||||||
|
key.rr = kdata32 + 2 + key.arrsize;
|
||||||
|
|
||||||
|
/* Copy signature to work buffer */
|
||||||
|
memcpy(sig_work, sig, sizeof(sig_work));
|
||||||
|
|
||||||
|
modpow3(&key, sig_work);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check padding. Continue on to check the digest even if error to
|
||||||
|
* reduce the risk of timing based attacks.
|
||||||
|
*/
|
||||||
|
pad_size = key.arrsize * sizeof(uint32_t) - BDB_SHA256_DIGEST_SIZE;
|
||||||
|
rv = vb2_check_padding(sig_work, &key, pad_size);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check digest. Even though there are probably no timing issues here,
|
||||||
|
* use vb2_safe_memcmp() just to be on the safe side. (That's also why
|
||||||
|
* we don't return before this check if the padding check failed.)
|
||||||
|
*/
|
||||||
|
if (vb2_safe_memcmp(sig_work + pad_size, digest,
|
||||||
|
BDB_SHA256_DIGEST_SIZE))
|
||||||
|
rv = BDB_ERROR_DIGEST;
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
210
firmware/coreboot/3rdparty/vboot/bdb/sha.c
vendored
Normal file
210
firmware/coreboot/3rdparty/vboot/bdb/sha.c
vendored
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
/* SHA-256 and SHA-512 implementation based on code by Oliver Gay
|
||||||
|
* <olivier.gay@a3.epfl.ch> under a BSD-style license. See below.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* FIPS 180-2 SHA-224/256/384/512 implementation
|
||||||
|
* Last update: 02/02/2007
|
||||||
|
* Issue date: 04/30/2005
|
||||||
|
*
|
||||||
|
* Copyright (C) 2005, 2007 Olivier Gay <olivier.gay@a3.epfl.ch>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the project nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "bdb.h"
|
||||||
|
|
||||||
|
#define VB2_SHA256_DIGEST_SIZE 32
|
||||||
|
#define VB2_SHA256_BLOCK_SIZE 64
|
||||||
|
|
||||||
|
struct vb2_sha256_context {
|
||||||
|
uint32_t h[8];
|
||||||
|
uint32_t total_size;
|
||||||
|
uint32_t size;
|
||||||
|
uint8_t block[2 * VB2_SHA256_BLOCK_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define SHFR(x, n) (x >> n)
|
||||||
|
#define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
|
||||||
|
#define ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n)))
|
||||||
|
#define CH(x, y, z) ((x & y) ^ (~x & z))
|
||||||
|
#define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
|
||||||
|
#define SHA256_F1(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
|
||||||
|
#define SHA256_F2(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
|
||||||
|
#define SHA256_F3(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHFR(x, 3))
|
||||||
|
#define SHA256_F4(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10))
|
||||||
|
#define UNPACK32(x, str) \
|
||||||
|
{ \
|
||||||
|
*((str) + 3) = (uint8_t) ((x) ); \
|
||||||
|
*((str) + 2) = (uint8_t) ((x) >> 8); \
|
||||||
|
*((str) + 1) = (uint8_t) ((x) >> 16); \
|
||||||
|
*((str) + 0) = (uint8_t) ((x) >> 24); \
|
||||||
|
}
|
||||||
|
#define PACK32(str, x) \
|
||||||
|
{ \
|
||||||
|
*(x) = ((uint32_t) *((str) + 3) ) \
|
||||||
|
| ((uint32_t) *((str) + 2) << 8) \
|
||||||
|
| ((uint32_t) *((str) + 1) << 16) \
|
||||||
|
| ((uint32_t) *((str) + 0) << 24); \
|
||||||
|
}
|
||||||
|
#define SHA256_SCR(i) \
|
||||||
|
{ \
|
||||||
|
w[i] = SHA256_F4(w[i - 2]) + w[i - 7] \
|
||||||
|
+ SHA256_F3(w[i - 15]) + w[i - 16]; \
|
||||||
|
}
|
||||||
|
|
||||||
|
static const uint32_t sha256_h0[8] = {
|
||||||
|
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
|
||||||
|
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint32_t sha256_k[64] = {
|
||||||
|
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
|
||||||
|
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
||||||
|
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
||||||
|
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
||||||
|
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
|
||||||
|
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||||
|
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
|
||||||
|
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
||||||
|
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
||||||
|
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
||||||
|
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
|
||||||
|
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||||
|
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
|
||||||
|
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
||||||
|
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
||||||
|
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
||||||
|
};
|
||||||
|
|
||||||
|
/* SHA-256 implementation from verified boot library */
|
||||||
|
void vb2_sha256_init(struct vb2_sha256_context *ctx)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
ctx->h[i] = sha256_h0[i];
|
||||||
|
}
|
||||||
|
ctx->size = 0;
|
||||||
|
ctx->total_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vb2_sha256_transform(struct vb2_sha256_context *ctx,
|
||||||
|
const uint8_t *message,
|
||||||
|
unsigned int block_nb)
|
||||||
|
{
|
||||||
|
/* Note that these arrays use 72*4=288 bytes of stack */
|
||||||
|
uint32_t w[64];
|
||||||
|
uint32_t wv[8];
|
||||||
|
uint32_t t1, t2;
|
||||||
|
const unsigned char *sub_block;
|
||||||
|
int i;
|
||||||
|
int j;
|
||||||
|
for (i = 0; i < (int) block_nb; i++) {
|
||||||
|
sub_block = message + (i << 6);
|
||||||
|
for (j = 0; j < 16; j++) {
|
||||||
|
PACK32(&sub_block[j << 2], &w[j]);
|
||||||
|
}
|
||||||
|
for (j = 16; j < 64; j++) {
|
||||||
|
SHA256_SCR(j);
|
||||||
|
}
|
||||||
|
for (j = 0; j < 8; j++) {
|
||||||
|
wv[j] = ctx->h[j];
|
||||||
|
}
|
||||||
|
for (j = 0; j < 64; j++) {
|
||||||
|
t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6])
|
||||||
|
+ sha256_k[j] + w[j];
|
||||||
|
t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
|
||||||
|
wv[7] = wv[6];
|
||||||
|
wv[6] = wv[5];
|
||||||
|
wv[5] = wv[4];
|
||||||
|
wv[4] = wv[3] + t1;
|
||||||
|
wv[3] = wv[2];
|
||||||
|
wv[2] = wv[1];
|
||||||
|
wv[1] = wv[0];
|
||||||
|
wv[0] = t1 + t2;
|
||||||
|
}
|
||||||
|
for (j = 0; j < 8; j++) {
|
||||||
|
ctx->h[j] += wv[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void vb2_sha256_update(struct vb2_sha256_context *ctx,
|
||||||
|
const uint8_t *data,
|
||||||
|
uint32_t size)
|
||||||
|
{
|
||||||
|
unsigned int block_nb;
|
||||||
|
unsigned int new_size, rem_size, tmp_size;
|
||||||
|
const uint8_t *shifted_data;
|
||||||
|
tmp_size = VB2_SHA256_BLOCK_SIZE - ctx->size;
|
||||||
|
rem_size = size < tmp_size ? size : tmp_size;
|
||||||
|
memcpy(&ctx->block[ctx->size], data, rem_size);
|
||||||
|
if (ctx->size + size < VB2_SHA256_BLOCK_SIZE) {
|
||||||
|
ctx->size += size;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
new_size = size - rem_size;
|
||||||
|
block_nb = new_size / VB2_SHA256_BLOCK_SIZE;
|
||||||
|
shifted_data = data + rem_size;
|
||||||
|
vb2_sha256_transform(ctx, ctx->block, 1);
|
||||||
|
vb2_sha256_transform(ctx, shifted_data, block_nb);
|
||||||
|
rem_size = new_size % VB2_SHA256_BLOCK_SIZE;
|
||||||
|
memcpy(ctx->block, &shifted_data[block_nb << 6],
|
||||||
|
rem_size);
|
||||||
|
ctx->size = rem_size;
|
||||||
|
ctx->total_size += (block_nb + 1) << 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vb2_sha256_finalize(struct vb2_sha256_context *ctx, uint8_t *digest)
|
||||||
|
{
|
||||||
|
unsigned int block_nb;
|
||||||
|
unsigned int pm_size;
|
||||||
|
unsigned int size_b;
|
||||||
|
int i;
|
||||||
|
block_nb = (1 + ((VB2_SHA256_BLOCK_SIZE - 9)
|
||||||
|
< (ctx->size % VB2_SHA256_BLOCK_SIZE)));
|
||||||
|
size_b = (ctx->total_size + ctx->size) << 3;
|
||||||
|
pm_size = block_nb << 6;
|
||||||
|
memset(ctx->block + ctx->size, 0, pm_size - ctx->size);
|
||||||
|
ctx->block[ctx->size] = 0x80;
|
||||||
|
UNPACK32(size_b, ctx->block + pm_size - 4);
|
||||||
|
vb2_sha256_transform(ctx, ctx->block, block_nb);
|
||||||
|
for (i = 0 ; i < 8; i++) {
|
||||||
|
UNPACK32(ctx->h[i], &digest[i << 2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int bdb_sha256(void *digest, const void *buf, size_t size)
|
||||||
|
{
|
||||||
|
struct vb2_sha256_context ctx;
|
||||||
|
|
||||||
|
vb2_sha256_init(&ctx);
|
||||||
|
vb2_sha256_update(&ctx, buf, size);
|
||||||
|
vb2_sha256_finalize(&ctx, digest);
|
||||||
|
|
||||||
|
return BDB_SUCCESS;
|
||||||
|
}
|
||||||
1
firmware/coreboot/3rdparty/vboot/bdb/testdata/ap-rw.bin
vendored
Normal file
1
firmware/coreboot/3rdparty/vboot/bdb/testdata/ap-rw.bin
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
This is a pretend ap-rw.bin image. Exciting.
|
||||||
1
firmware/coreboot/3rdparty/vboot/bdb/testdata/oem0.bin
vendored
Normal file
1
firmware/coreboot/3rdparty/vboot/bdb/testdata/oem0.bin
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
This is some OEM0 data.
|
||||||
1
firmware/coreboot/3rdparty/vboot/bdb/testdata/oem1.bin
vendored
Normal file
1
firmware/coreboot/3rdparty/vboot/bdb/testdata/oem1.bin
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
This is some OEM1 data of some sort
|
||||||
1
firmware/coreboot/3rdparty/vboot/bdb/testdata/sp-rw.bin
vendored
Normal file
1
firmware/coreboot/3rdparty/vboot/bdb/testdata/sp-rw.bin
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
This is a pretend sp-rw.bin image.
|
||||||
33
firmware/coreboot/3rdparty/vboot/bdb/testkeys/bdbkey.crt
vendored
Normal file
33
firmware/coreboot/3rdparty/vboot/bdb/testkeys/bdbkey.crt
vendored
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIFtTCCA52gAwIBAgIJANitnQKymb5VMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
|
||||||
|
BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX
|
||||||
|
aWRnaXRzIFB0eSBMdGQwHhcNMTAwOTI5MTgxNjM4WhcNMTAxMDI5MTgxNjM4WjBF
|
||||||
|
MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50
|
||||||
|
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
|
||||||
|
CgKCAgEAm5v71oqFynujT4FVq5lKaYxpmKfXdeBNKDmLzgu7fXLUKaEqTGEDsseE
|
||||||
|
5qyaaP+dmTnQKfne7G31zgf46//YEl+u5Gt/S4oAgYyvs3rjymzD5kVOLEAzgrIX
|
||||||
|
AwyhDFARRzAFWos43hypunHGvu4fDBAzZ3zGVulhjgAzD/gNjToVYCP7bj6kTaDx
|
||||||
|
1u9siCKdYN09vGwSUt9WuV+yort7kns/B8ArVxt3bFSjsAxuWel/dJyLwCMQ9XAx
|
||||||
|
dgWpg3RBUsK/KgekQybPLrhLYJn1AeOApwzJ4HoJSqU/1jCEaGrKA/KtCRXiurZz
|
||||||
|
6lBi7sElsigjBvEZH0iCmmRgH3Oi/cbpHIs1C6YHvCCbO90ntwgtDf0+2WJtFtbG
|
||||||
|
t5Do3CXri0tcsXBWqISSK3VzzjHH691BVwLuoBvF1XICMEjmq9aJ+MdbEe4E+GU8
|
||||||
|
TV9NnRnuYyOUoxeisyXiArUUI9+1qL6pIgulTlY2Ch51QZY5n2aYY97PtosNotbS
|
||||||
|
ylMrLvWXGiiQWxux12eOnB3c/3wNYWey8Km4cmOhEOYz7hLz2r1uIoC/SzM5wLnn
|
||||||
|
TEQmaiUDNV9R3Gj3E3xkpTq3UNSSPsV7k8lInMtWqzps6aTvBw1k6i6CUvWbEZqm
|
||||||
|
t/0bimQHOEdg3OrJjQpwTKSp4ouSyVu0IphDwy1yjKCfNWKRzrUCAwEAAaOBpzCB
|
||||||
|
pDAdBgNVHQ4EFgQUyBKBgFg+vONV1sbup7QtFa7DR78wdQYDVR0jBG4wbIAUyBKB
|
||||||
|
gFg+vONV1sbup7QtFa7DR7+hSaRHMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpT
|
||||||
|
b21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGSCCQDY
|
||||||
|
rZ0Cspm+VTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4ICAQA0wtlLEAKR
|
||||||
|
ctB41x/V10SMFIg5eLbDrUKQQT33BddrhFu0blc7U5jgXjqTYS80xIlOC0hXtN7D
|
||||||
|
Z478st3NAxjtvBKxNMWB9Ppz6+15UENnXNGLElhRPaeAbxBs7zVB64b8fY69EJRe
|
||||||
|
JOJNp6+c4WJsHWzxrmfHD0Wx18pJ877ThRi/ZH0QP2TjPc0gZT4szP1taoOJ7SXy
|
||||||
|
gO10WfPoF1GgI/VXhPLnk2zXpTlFdp+qyKOtDFxOOK/cVKdXAxDDDO9DAw6cvrEn
|
||||||
|
mPS2Zml9HI25/CrE00y+k4w7bqzNeGNzhSGPBvq5Yqnefc1dJSdDQZ3XLG9Fis4a
|
||||||
|
nVfuSTvP1MUrFEGEvuxRcA0rWPwQtYSHHs8ZnpT6eayTPcpDvWSihe4xUywirXTT
|
||||||
|
kbWgeABGQGaoAnFJYhjqBROGdVb4V3vbsjbCi8k2r4IIcqOzp6OIJxha2LvkZ+iu
|
||||||
|
f+OlMVAO/C1LbRsVQkfJp7NxEt6PVewQV5Kgnwlf+x7Q2tUfZfdpLd/EMtojv3BD
|
||||||
|
Ewx5X2yHGXcYZG/C1kNzyGTfg97/+55mtNlkTmo8elcPxlpnEuMXEv4JthnRy90x
|
||||||
|
ZLflcR9q0pOiV+n//KyQvfjH99JmRtVJGG8xlDEtRbJWjFQD/uSEBxeS0T6INrza
|
||||||
|
0WTaiIOZB1vMPe6CDYDWDzrFdQrD6HoWDQ==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
BIN
firmware/coreboot/3rdparty/vboot/bdb/testkeys/bdbkey.keyb
vendored
Normal file
BIN
firmware/coreboot/3rdparty/vboot/bdb/testkeys/bdbkey.keyb
vendored
Normal file
Binary file not shown.
51
firmware/coreboot/3rdparty/vboot/bdb/testkeys/bdbkey.pem
vendored
Normal file
51
firmware/coreboot/3rdparty/vboot/bdb/testkeys/bdbkey.pem
vendored
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIIJKQIBAAKCAgEAm5v71oqFynujT4FVq5lKaYxpmKfXdeBNKDmLzgu7fXLUKaEq
|
||||||
|
TGEDsseE5qyaaP+dmTnQKfne7G31zgf46//YEl+u5Gt/S4oAgYyvs3rjymzD5kVO
|
||||||
|
LEAzgrIXAwyhDFARRzAFWos43hypunHGvu4fDBAzZ3zGVulhjgAzD/gNjToVYCP7
|
||||||
|
bj6kTaDx1u9siCKdYN09vGwSUt9WuV+yort7kns/B8ArVxt3bFSjsAxuWel/dJyL
|
||||||
|
wCMQ9XAxdgWpg3RBUsK/KgekQybPLrhLYJn1AeOApwzJ4HoJSqU/1jCEaGrKA/Kt
|
||||||
|
CRXiurZz6lBi7sElsigjBvEZH0iCmmRgH3Oi/cbpHIs1C6YHvCCbO90ntwgtDf0+
|
||||||
|
2WJtFtbGt5Do3CXri0tcsXBWqISSK3VzzjHH691BVwLuoBvF1XICMEjmq9aJ+Mdb
|
||||||
|
Ee4E+GU8TV9NnRnuYyOUoxeisyXiArUUI9+1qL6pIgulTlY2Ch51QZY5n2aYY97P
|
||||||
|
tosNotbSylMrLvWXGiiQWxux12eOnB3c/3wNYWey8Km4cmOhEOYz7hLz2r1uIoC/
|
||||||
|
SzM5wLnnTEQmaiUDNV9R3Gj3E3xkpTq3UNSSPsV7k8lInMtWqzps6aTvBw1k6i6C
|
||||||
|
UvWbEZqmt/0bimQHOEdg3OrJjQpwTKSp4ouSyVu0IphDwy1yjKCfNWKRzrUCAwEA
|
||||||
|
AQKCAgEAlbfvBu0g7UEoUEbQdtp2jjdbIlXbKL83fYxgx07ihkEFgUhfuj1doZX2
|
||||||
|
eTt5Fa1bpSHK95hCtJjX9/QTvH3dF1CYpY4IXFXbRspmAvoqUYl0swnbvRfId+eB
|
||||||
|
3J06Fu6ysRuzCvsJLCvH4mu2Hd5eYOz1iIy1CMpj4oyulJ7F6ywHhQkZ0WjUDRzd
|
||||||
|
kz+p3RHw+lHkJHaW6sWYW6OH7KsWqkmKy5pKGPWEYebN14UeZ8QRrdExZRxYJM5d
|
||||||
|
yICKKMCiWU6nP3k6wqGElh8b50Y6RibukcvsMN86MWftk9f6jbyxwjqr4iH8lEkY
|
||||||
|
HkpZ5f5QlqmnifZPhZnujz4kfh50oteC2QPQ0hrNYCDG75wuiNX/vINVfrKG0ddg
|
||||||
|
iQDFqyQyQirxCGQgy7Wto08KAzKt146ST28N+kdF/kY14ou5f5+GlWQJcnqdHd2p
|
||||||
|
R25MueXUsY3I63dULR6k02Y6M7Tzo39lYe0LV82+G0A3iGpI+eM7xw/sQDNb2sQs
|
||||||
|
jCcz7XPrfTomrVJaW1FkM8vM6eWhuhAyDFP+unz0aMnKrkUrarh4t9QpriiCjm3E
|
||||||
|
HV2Hc7t/Do/w+B3rywKy3PE2yO49eGz20um0JqWcAbGDZY2vDnyV+/xibxqaIZUo
|
||||||
|
saI/btlyvCv00812momkX/qWwS+1GHvyYYcpIg0XQbZY1TvEi8ECggEBAM6LTfVu
|
||||||
|
MKNwW/QdZ6pxKl/Oy8zlb1o8HET5hKCdhoMvpwlvpO2qSvlCxH3VZTmcXIXd+Mkd
|
||||||
|
e4OZrzeMLVxMd64xP10k2ui/O2/8G38xmpMGqZihc+LnY6JgajujfAQHljOgrAJL
|
||||||
|
xzO2Gk4oWX72oA6jqP8LZkRp/9acTWqBTKs6MOdrfn6I3k0urBB29+jcbqFAfgMx
|
||||||
|
hfcTKAOHYmg/SeEZDvKP6fRDJGMGXqJ4TaBXjsnhNGCjGmuCqJhxxIGCI/AVK10B
|
||||||
|
CjEboo9vACzNE1/JMxH8aT5up7e+7R/WoiJ5e3jlvSKmcO7KiR27JVsAlZeIddKd
|
||||||
|
LzG9KKZ8Yla0U3MCggEBAMDefKVTqSPaG7cmAQGtXrbBDLdCWIaT08v+kMw/drlq
|
||||||
|
NqLD+1ct098iFwRtKaYPERPKqNtxfJdkUMqWELBWV2Sq4Fi+JVXjGOUctP7Atd2x
|
||||||
|
6NJ9xHqQKQwKUv0/9jN5Oie9sFvsLwPAJNOJej1BrmvPZvc0CoMyOjkmxEhYu3qG
|
||||||
|
i26ZTSZSCTrbE8eAL0EJdH0gB7Ryuks8O+jEF7eXuZLZyN3AromISJtmLVlMFZ7m
|
||||||
|
+0sQnZQqwNF+BIrOgO+3R61jjNzCJbFo7frvRIlDSnrbmWp6sYns1cjhZiKCnO78
|
||||||
|
RgDiaJcuceqsalgBZi8/Fmam2IPeqhvTNg+5alCuWzcCggEAXFjglFmeGZVFJ9J1
|
||||||
|
5TkPzyJw8L2smdXCdfxyFjYYTFNkBc4LGdBIEUaPAAwHZEjK/XePoqwx61cthlKA
|
||||||
|
fYIbCKEwSX8O+X13H8zCpo4RJKeX8IxPeiYm4BTnqp6f9lVGDPNLtQMYn8BN5qAX
|
||||||
|
07KFQcZe6xm3seMK5nOgEXyaQPyVnQLs3bpoWm4BtKLcmRrlw+dH8DmWQjAoddt0
|
||||||
|
XlPdvm0rx7wcyH+0pynT6iSL4KMFTrIIbyS9zU/v/ajwSU9crh1o8/5hBi/q8OKa
|
||||||
|
W22dufgFg4ctryJejsMo1lFq0KssT5O4iuOMHtgjkk14mEWcnNIAjBiHX1/J6xY2
|
||||||
|
Cbo6jQKCAQBtvmt4e1kz8Ehy92n9NVQ+cyy0HklXEkiiu9BSmA4LRPefuBqNKaN0
|
||||||
|
ROaJ+z+GoO4br+ZTL4kwb8FU9Py8CfUib+TGOjPuYhFpVONcTfVuF2yeUTf6cYsZ
|
||||||
|
sco1Fi8WbPV9ZX8zXvoFjVCnGYP31SbVa6dwJCmTK4JbwMZRUEQlXOd74Dk5A9cC
|
||||||
|
qWPg0fyRajrhc9dOgzWj17tTIDlKm0fZ2phkLd5inayK2CIXvKZUy6PTu7medJFQ
|
||||||
|
4v7cqNJPFJ/xdkLR3psqDsXTUlBSNnrr24a5QuVA0QV4j2DZZC6+Acgneqz+0Uu6
|
||||||
|
t66vMuSdH620bV2n84wh1xXc7qkjDYMTAoIBAQC6DsTyBGNNI0/DGwAsae5Zri8w
|
||||||
|
T/SOER7Tc/PCgQyFUNsJJc/OmSy66PPiH2HzqLjl6/jeiJP++oCnfO6pNTq1Fjz4
|
||||||
|
Le2iS1szlcuJ9QLdtn2LTqORzdQVpka42X+o+NqJEdzkZb/N6eBA4PPQdTxHIiu1
|
||||||
|
WGBpDc5vGkpuzLm9SVCw/4SD84z+Nhs0pqOvwWhmQWCtl28fgqU4LMeOX1Wz5P8E
|
||||||
|
IledlgbCZh2KwXuv3BJdkawuwrSPsahnZmoJapx2dE+FkNl4equaBwImfLf5Qifj
|
||||||
|
IhIN5GueO9k/D2/7/XvW2qJ3Vy0z0xMMNiTVYufVpbh77Kn2ebKfROlkzMEU
|
||||||
|
-----END RSA PRIVATE KEY-----
|
||||||
26
firmware/coreboot/3rdparty/vboot/bdb/testkeys/subkey.crt
vendored
Normal file
26
firmware/coreboot/3rdparty/vboot/bdb/testkeys/subkey.crt
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIEWzCCAsOgAwIBAgIJAKOPQrNCNRSqMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
|
||||||
|
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
|
||||||
|
aWRnaXRzIFB0eSBMdGQwHhcNMTUxMTIzMjA1MTI4WhcNMTUxMjIzMjA1MTI4WjBF
|
||||||
|
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
|
||||||
|
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBoDANBgkqhkiG9w0BAQEFAAOCAY0AMIIB
|
||||||
|
iAKCAYEA1/JAfpirBAFZdm+m6AcX5QQt7vWDV6OAN4T5nWxAtedRb0XLeV9ICJJI
|
||||||
|
4CwxWKhvM4pe8pUwwldjoIHIs7viDjBnFVO6+41Gwdsp54AO9qpd//izjarwrOFq
|
||||||
|
QcZIn7KVOaYxTlMWlfIDOS3K0rr2adBuR/Yq4Nj61XevNsxRelojDLAQeamRia8t
|
||||||
|
hB3vR1LHQJlMT7R8VXy3AOHx+YcYKUFCgf5A7J+pdAaOIgkFKuakZZNDC+7D0Ykq
|
||||||
|
jPHadHKzT1SCJxILD/YkCUCOn5bdh7oQekCnhJgf3bwPRDaGEsJL3nnxhc8hx3tI
|
||||||
|
7DHwKmz9naz63S41Zqd+VvWam7Jttyb6lQjj7Y8TauXGAL3vEiI/u0iiVyw6b3c3
|
||||||
|
77/W4RWuRIiMAn6FAkUY6oxKB+67ZA1PoRLfiIxFGot1KEpTeLzdsyYx7fB1Scj+
|
||||||
|
DDzx3EaHQAz12E4anTozljvdAPMoZ6i9Dar3eZvA0KFsM5sdNy0Hp96PBeBNiw1O
|
||||||
|
XZYUrYgVAgEDo1AwTjAdBgNVHQ4EFgQUiwtVmJWqyIBZWV1xvn7iMbLeE30wHwYD
|
||||||
|
VR0jBBgwFoAUiwtVmJWqyIBZWV1xvn7iMbLeE30wDAYDVR0TBAUwAwEB/zANBgkq
|
||||||
|
hkiG9w0BAQsFAAOCAYEAJXgsYoQ7QDNf1GF0bQQKnSqIKMssecD8x66rrJQr1Yon
|
||||||
|
biJeUfN9N/pAca7CI/vjeTC1w6BlXEbUDNNwLKQYVfTOBdmbW1qDANMUP05PaiAG
|
||||||
|
cZHVKMZZrR/5+z+LWG157cP7HzHPGfw78LopVXUDZmd5fRD2d7MnqYCrswp/dORM
|
||||||
|
brHTwzpPhH75uNQmq6w2RowjrntDnKhGT0tSY57/OI+Gke3ch3XPPg3juhREaVUm
|
||||||
|
4ZXSCwajKmPBju+7adT46gY/LjAYv/rAEiUN5YHOBVHxHdoMOIqsf6VfPVc8USpg
|
||||||
|
5fsV7NWGNSuvpiA7xBIBKai3dZl8nztFHvjn7z4x6XrqQ1KTMBvnGONHAHopeUtj
|
||||||
|
a3WPd3GpBmLMpSfDWtcaSSuwOAgZro6vGqcHN4FybKASbtS0RynPRL42DBbLiarn
|
||||||
|
nA0hhR1YR03Kqc6hexrsg7zrjcNL6b8dzu6o+VxD30ecj68D7IliORtouJahvk5/
|
||||||
|
F8MyzvHvAa+K7Hb/IcJv
|
||||||
|
-----END CERTIFICATE-----
|
||||||
BIN
firmware/coreboot/3rdparty/vboot/bdb/testkeys/subkey.keyb
vendored
Normal file
BIN
firmware/coreboot/3rdparty/vboot/bdb/testkeys/subkey.keyb
vendored
Normal file
Binary file not shown.
39
firmware/coreboot/3rdparty/vboot/bdb/testkeys/subkey.pem
vendored
Normal file
39
firmware/coreboot/3rdparty/vboot/bdb/testkeys/subkey.pem
vendored
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIIG4wIBAAKCAYEA1/JAfpirBAFZdm+m6AcX5QQt7vWDV6OAN4T5nWxAtedRb0XL
|
||||||
|
eV9ICJJI4CwxWKhvM4pe8pUwwldjoIHIs7viDjBnFVO6+41Gwdsp54AO9qpd//iz
|
||||||
|
jarwrOFqQcZIn7KVOaYxTlMWlfIDOS3K0rr2adBuR/Yq4Nj61XevNsxRelojDLAQ
|
||||||
|
eamRia8thB3vR1LHQJlMT7R8VXy3AOHx+YcYKUFCgf5A7J+pdAaOIgkFKuakZZND
|
||||||
|
C+7D0YkqjPHadHKzT1SCJxILD/YkCUCOn5bdh7oQekCnhJgf3bwPRDaGEsJL3nnx
|
||||||
|
hc8hx3tI7DHwKmz9naz63S41Zqd+VvWam7Jttyb6lQjj7Y8TauXGAL3vEiI/u0ii
|
||||||
|
Vyw6b3c377/W4RWuRIiMAn6FAkUY6oxKB+67ZA1PoRLfiIxFGot1KEpTeLzdsyYx
|
||||||
|
7fB1Scj+DDzx3EaHQAz12E4anTozljvdAPMoZ6i9Dar3eZvA0KFsM5sdNy0Hp96P
|
||||||
|
BeBNiw1OXZYUrYgVAgEDAoIBgQCP9tWpuxytVjukSm9FWg/uAslJ+QI6bQAlA1ET
|
||||||
|
nYB5ROD02TJQ6jAFtttAHXY7GvTNBun3DiCBj5fAVoXNJ+wJdZoON9H9CNnWkhvv
|
||||||
|
qrSkcZP/+yJecfXIlkbWhDBqdw4mbsuJjLm5TAImHoc3J07xNZ7apByV5fyOT8ok
|
||||||
|
iDZRkWyzIAr7xmEGdMkCvp+E4dorEN2KeFLjqHoAlqFRBLrGK4Gr/tXzFRuirwls
|
||||||
|
BgNx7xhDt4IH9IKLsMcIoTxNocul86msFzeUDFXM/ruLFa34DBtT935WhGn+18+/
|
||||||
|
bYA+qM4GoC8N/4sSQtENQ8bX21aUHRs1MIOa82rJEmkCWW+Tgw8kYSSi8gVmd7Ly
|
||||||
|
QFp4XN17ReaIZZKBYJt/3XamcV2tcapxwqBNiGOLPQM4wnnuinkiZD7rXf1u/NFV
|
||||||
|
rHiVFu1+ORZaTX34+Vq9/wdj18E3cm1ghQsN3BQNzCE1qtulDcs5w2O1iZlP29wq
|
||||||
|
mtgeU7YHK7CzqNuUiPJWJardCWsCgcEA8VAXoPMSAJByCk3l92eDTOe8n5IMZ307
|
||||||
|
qXpGMlSUT+SctpgVdoN9iV+7bUQE636Hn37E5czANNpERIoVjFJRm0ioYW/9jOEN
|
||||||
|
B8zPnvwtLN1vVD1u5XNlumDGWGU1bQCdjgA07DtCM0S5xfhWOACCUJ4l4TDE3DAz
|
||||||
|
eNfnaXXP8UNfpL6gaWb/xZZwwTesS+hcX8zw14Gzn/GHkyGEtSMA+lezI5C37bzk
|
||||||
|
ao2pWr+W26HeDPwdG/38gBQceUujidJ9AoHBAOUW7AP8JbFTMUt0j1eO1UbAKty7
|
||||||
|
XZtURTX+EXK9sWTgeh3xlXpMU6K3U+sIQPsldCACjSeYr8lgGeTP54vZ9L6Zu30H
|
||||||
|
L2xC/kllafZhOjC5hC4iWaUgePMFiFeOb3prBDJd12ufUlqzydO4bvrKgi2fdAxL
|
||||||
|
vEtPFXs4U75RzqfXGdER7/0VOI68hS4GunqaiQ0UYPAE1mh+je5oJntP3fW8WRN1
|
||||||
|
KfuQdm5J+JjzQi4NmJAg6NxlB6wrxmMR8NgneQKBwQCg4A/AogwAYEwG3plPmleI
|
||||||
|
mn2/trLvqNJw/C7MOGLf7b3PEA5PAlOw6nzzgq3yVFpqVIND3dV4kYLYXA5djDZn
|
||||||
|
hcWWSqkIlgiv3d+/UsjIk5+NfknuTO58QIQ67iOeAGkJVXidfNbM2HvZUDl6qwGL
|
||||||
|
FBlAyy3oICJQj++bo9/2LOpt1Grw71UuZEsrenLdRZLqiKCPq80VS6+3a63OF1X8
|
||||||
|
OndtCyVJKJhHCRuR1Q89FpQIqBNn/qhVYr2mMm0GjFMCgcEAmLnyrVLDy4zLh6MK
|
||||||
|
Ol842dVx6HzpEjguI/62TH52Q0BRaUu4/DLibHo38gWAp25NaqxeGmXKhkARQzVF
|
||||||
|
B+ajKbvSU1ofnYH+25jxTut8IHutdBbmbhWl91kFj7RKUZytduk6R7+MPHfb4nr0
|
||||||
|
pzGsHmpNXYfS3N9jp3rifuE0b+S74Laf/g4ltH2uHq8m/GcGCLhAoAM5mv8JSZrE
|
||||||
|
UjU+o9LmDPjGp7WkSYalu0zWyV5ltWtF6ENacsfZl2FLOsT7AoHARP9ZNA7JMYMs
|
||||||
|
dbx2l7eLaTtdOeeSE9AxssmzXBsNHWklEx8DTI3MAFcIXPNesqnm++D/T5sXsIy6
|
||||||
|
kd3srldHGYHoh1IT5mOO7S8SlKLdYTIlsVIg+I4jpqmHTgk7DWDDpjYzkmJz3A29
|
||||||
|
q4HHmNx92SXNZD+mX0GnDdP9XDbT3tbt3ANuR1LoTcI3wAUMTN/NQiF8qj2NHzb1
|
||||||
|
CFOpBOJ9cuUgkWcntjqLJ6mUAMcQ8kF7Pyuhn46qDhY5ceVhrPt9
|
||||||
|
-----END RSA PRIVATE KEY-----
|
||||||
97
firmware/coreboot/3rdparty/vboot/cgpt/cgpt.c
vendored
Normal file
97
firmware/coreboot/3rdparty/vboot/cgpt/cgpt.c
vendored
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
/* Copyright (c) 2010 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.
|
||||||
|
*
|
||||||
|
* Utility for ChromeOS-specific GPT partitions, Please see corresponding .c
|
||||||
|
* files for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <uuid/uuid.h>
|
||||||
|
|
||||||
|
#include "cgpt.h"
|
||||||
|
#include "vboot_host.h"
|
||||||
|
|
||||||
|
const char* progname;
|
||||||
|
|
||||||
|
int GenerateGuid(Guid *newguid)
|
||||||
|
{
|
||||||
|
/* From libuuid */
|
||||||
|
uuid_generate(newguid->u.raw);
|
||||||
|
return CGPT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct {
|
||||||
|
const char *name;
|
||||||
|
int (*fp)(int argc, char *argv[]);
|
||||||
|
const char *comment;
|
||||||
|
} cmds[] = {
|
||||||
|
{"create", cmd_create, "Create or reset GPT headers and tables"},
|
||||||
|
{"add", cmd_add, "Add, edit or remove a partition entry"},
|
||||||
|
{"show", cmd_show, "Show partition table and entries"},
|
||||||
|
{"repair", cmd_repair, "Repair damaged GPT headers and tables"},
|
||||||
|
{"boot", cmd_boot, "Edit the PMBR sector for legacy BIOSes"},
|
||||||
|
{"find", cmd_find, "Locate a partition by its GUID"},
|
||||||
|
{"prioritize", cmd_prioritize,
|
||||||
|
"Reorder the priority of all kernel partitions"},
|
||||||
|
{"legacy", cmd_legacy, "Switch between GPT and Legacy GPT"},
|
||||||
|
};
|
||||||
|
|
||||||
|
void Usage(void) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
printf("\nUsage: %s COMMAND [OPTIONS] DRIVE\n\n"
|
||||||
|
"Supported COMMANDs:\n\n",
|
||||||
|
progname);
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof(cmds)/sizeof(cmds[0]); ++i) {
|
||||||
|
printf(" %-15s %s\n", cmds[i].name, cmds[i].comment);
|
||||||
|
}
|
||||||
|
printf("\nFor more detailed usage, use %s COMMAND -h\n\n", progname);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
int i;
|
||||||
|
int match_count = 0;
|
||||||
|
int match_index = 0;
|
||||||
|
char* command;
|
||||||
|
|
||||||
|
progname = strrchr(argv[0], '/');
|
||||||
|
if (progname)
|
||||||
|
progname++;
|
||||||
|
else
|
||||||
|
progname = argv[0];
|
||||||
|
|
||||||
|
if (argc < 2) {
|
||||||
|
Usage();
|
||||||
|
return CGPT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// increment optind now, so that getopt skips argv[0] in command function
|
||||||
|
command = argv[optind++];
|
||||||
|
|
||||||
|
// Find the command to invoke.
|
||||||
|
for (i = 0; command && i < sizeof(cmds)/sizeof(cmds[0]); ++i) {
|
||||||
|
// exact match?
|
||||||
|
if (0 == strcmp(cmds[i].name, command)) {
|
||||||
|
match_index = i;
|
||||||
|
match_count = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// unique match?
|
||||||
|
else if (0 == strncmp(cmds[i].name, command, strlen(command))) {
|
||||||
|
match_index = i;
|
||||||
|
match_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match_count == 1)
|
||||||
|
return cmds[match_index].fp(argc, argv);
|
||||||
|
|
||||||
|
// Couldn't find a single matching command.
|
||||||
|
Usage();
|
||||||
|
|
||||||
|
return CGPT_FAILED;
|
||||||
|
}
|
||||||
222
firmware/coreboot/3rdparty/vboot/cgpt/cgpt.h
vendored
Normal file
222
firmware/coreboot/3rdparty/vboot/cgpt/cgpt.h
vendored
Normal file
@@ -0,0 +1,222 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#ifndef VBOOT_REFERENCE_UTILITY_CGPT_CGPT_H_
|
||||||
|
#define VBOOT_REFERENCE_UTILITY_CGPT_CGPT_H_
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#ifndef HAVE_MACOS
|
||||||
|
#include <features.h>
|
||||||
|
#endif
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "cgpt_endian.h"
|
||||||
|
#include "cgptlib.h"
|
||||||
|
#include "gpt.h"
|
||||||
|
|
||||||
|
struct legacy_partition {
|
||||||
|
uint8_t status;
|
||||||
|
uint8_t f_head;
|
||||||
|
uint8_t f_sect;
|
||||||
|
uint8_t f_cyl;
|
||||||
|
uint8_t type;
|
||||||
|
uint8_t l_head;
|
||||||
|
uint8_t l_sect;
|
||||||
|
uint8_t l_cyl;
|
||||||
|
uint32_t f_lba;
|
||||||
|
uint32_t num_sect;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
// syslinux uses this format:
|
||||||
|
struct pmbr {
|
||||||
|
uint8_t bootcode[424];
|
||||||
|
Guid boot_guid;
|
||||||
|
uint32_t disk_id;
|
||||||
|
uint8_t magic[2]; // 0x1d, 0x9a
|
||||||
|
struct legacy_partition part[4];
|
||||||
|
uint8_t sig[2]; // 0x55, 0xaa
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
void PMBRToStr(struct pmbr *pmbr, char *str, unsigned int buflen);
|
||||||
|
|
||||||
|
// Handle to the drive storing the GPT.
|
||||||
|
struct drive {
|
||||||
|
uint64_t size; /* total size (in bytes) */
|
||||||
|
GptData gpt;
|
||||||
|
struct pmbr pmbr;
|
||||||
|
int fd; /* file descriptor */
|
||||||
|
};
|
||||||
|
|
||||||
|
// Opens a block device or file, loads raw GPT data from it.
|
||||||
|
// 'mode' should be O_RDONLY or O_RDWR.
|
||||||
|
// If 'drive_size' is 0, both the partitions and GPT structs reside on the same
|
||||||
|
// 'drive_path'.
|
||||||
|
// Otherwise, 'drive_size' is taken as the size of the device that all
|
||||||
|
// partitions will reside on, and 'drive_path' is where we store GPT structs.
|
||||||
|
//
|
||||||
|
// Returns CGPT_FAILED if any error happens.
|
||||||
|
// Returns CGPT_OK if success and information are stored in 'drive'. */
|
||||||
|
int DriveOpen(const char *drive_path, struct drive *drive, int mode,
|
||||||
|
uint64_t drive_size);
|
||||||
|
int DriveClose(struct drive *drive, int update_as_needed);
|
||||||
|
int CheckValid(const struct drive *drive);
|
||||||
|
|
||||||
|
/* Loads sectors from 'drive'.
|
||||||
|
* *buf is pointed to an allocated memory when returned, and should be
|
||||||
|
* freed.
|
||||||
|
*
|
||||||
|
* drive -- open drive.
|
||||||
|
* buf -- pointer to buffer pointer
|
||||||
|
* sector -- offset of starting sector (in sectors)
|
||||||
|
* sector_bytes -- bytes per sector
|
||||||
|
* sector_count -- number of sectors to load
|
||||||
|
*
|
||||||
|
* Returns CGPT_OK for successful. Aborts if any error occurs.
|
||||||
|
*/
|
||||||
|
int Load(struct drive *drive, uint8_t **buf,
|
||||||
|
const uint64_t sector,
|
||||||
|
const uint64_t sector_bytes,
|
||||||
|
const uint64_t sector_count);
|
||||||
|
|
||||||
|
/* Saves sectors to 'drive'.
|
||||||
|
*
|
||||||
|
* drive -- open drive
|
||||||
|
* buf -- pointer to buffer
|
||||||
|
* sector -- starting sector offset
|
||||||
|
* sector_bytes -- bytes per sector
|
||||||
|
* sector_count -- number of sector to save
|
||||||
|
*
|
||||||
|
* Returns CGPT_OK for successful, CGPT_FAILED for failed.
|
||||||
|
*/
|
||||||
|
int Save(struct drive *drive, const uint8_t *buf,
|
||||||
|
const uint64_t sector,
|
||||||
|
const uint64_t sector_bytes,
|
||||||
|
const uint64_t sector_count);
|
||||||
|
|
||||||
|
|
||||||
|
/* GUID conversion functions. Accepted format:
|
||||||
|
*
|
||||||
|
* "C12A7328-F81F-11D2-BA4B-00A0C93EC93B"
|
||||||
|
*
|
||||||
|
* At least GUID_STRLEN bytes should be reserved in 'str' (included the tailing
|
||||||
|
* '\0').
|
||||||
|
*/
|
||||||
|
#define GUID_STRLEN 37
|
||||||
|
int StrToGuid(const char *str, Guid *guid);
|
||||||
|
void GuidToStr(const Guid *guid, char *str, unsigned int buflen);
|
||||||
|
int GuidEqual(const Guid *guid1, const Guid *guid2);
|
||||||
|
int IsZero(const Guid *guid);
|
||||||
|
|
||||||
|
/* Constant global type values to compare against */
|
||||||
|
extern const Guid guid_chromeos_firmware;
|
||||||
|
extern const Guid guid_chromeos_kernel;
|
||||||
|
extern const Guid guid_chromeos_rootfs;
|
||||||
|
extern const Guid guid_linux_data;
|
||||||
|
extern const Guid guid_chromeos_reserved;
|
||||||
|
extern const Guid guid_efi;
|
||||||
|
extern const Guid guid_unused;
|
||||||
|
|
||||||
|
int ReadPMBR(struct drive *drive);
|
||||||
|
int WritePMBR(struct drive *drive);
|
||||||
|
|
||||||
|
/* Convert possibly unterminated UTF16 string to UTF8.
|
||||||
|
* Caller must prepare enough space for UTF8, which could be up to
|
||||||
|
* twice the byte length of UTF16 string plus the terminating '\0'.
|
||||||
|
*
|
||||||
|
* Return: CGPT_OK --- all character are converted successfully.
|
||||||
|
* CGPT_FAILED --- convert error, i.e. output buffer is too short.
|
||||||
|
*/
|
||||||
|
int UTF16ToUTF8(const uint16_t *utf16, unsigned int maxinput,
|
||||||
|
uint8_t *utf8, unsigned int maxoutput);
|
||||||
|
|
||||||
|
/* Convert null-terminated UTF8 string to UTF16.
|
||||||
|
* Caller must prepare enough space for UTF16, which is the byte length of UTF8
|
||||||
|
* plus the terminating 0x0000.
|
||||||
|
*
|
||||||
|
* Return: CGPT_OK --- all character are converted successfully.
|
||||||
|
* CGPT_FAILED --- convert error, i.e. output buffer is too short.
|
||||||
|
*/
|
||||||
|
int UTF8ToUTF16(const uint8_t *utf8, uint16_t *utf16, unsigned int maxoutput);
|
||||||
|
|
||||||
|
/* Helper functions for supported GPT types. */
|
||||||
|
int ResolveType(const Guid *type, char *buf);
|
||||||
|
int SupportedType(const char *name, Guid *type);
|
||||||
|
void PrintTypes(void);
|
||||||
|
void EntryDetails(GptEntry *entry, uint32_t index, int raw);
|
||||||
|
|
||||||
|
uint32_t GetNumberOfEntries(const struct drive *drive);
|
||||||
|
GptEntry *GetEntry(GptData *gpt, int secondary, uint32_t entry_index);
|
||||||
|
|
||||||
|
void SetRequired(struct drive *drive, int secondary, uint32_t entry_index,
|
||||||
|
int required);
|
||||||
|
int GetRequired(struct drive *drive, int secondary, uint32_t entry_index);
|
||||||
|
void SetLegacyBoot(struct drive *drive, int secondary, uint32_t entry_index,
|
||||||
|
int legacy_boot);
|
||||||
|
int GetLegacyBoot(struct drive *drive, int secondary, uint32_t entry_index);
|
||||||
|
void SetPriority(struct drive *drive, int secondary, uint32_t entry_index,
|
||||||
|
int priority);
|
||||||
|
int GetPriority(struct drive *drive, int secondary, uint32_t entry_index);
|
||||||
|
void SetTries(struct drive *drive, int secondary, uint32_t entry_index,
|
||||||
|
int tries);
|
||||||
|
int GetTries(struct drive *drive, int secondary, uint32_t entry_index);
|
||||||
|
void SetSuccessful(struct drive *drive, int secondary, uint32_t entry_index,
|
||||||
|
int success);
|
||||||
|
int GetSuccessful(struct drive *drive, int secondary, uint32_t entry_index);
|
||||||
|
|
||||||
|
void SetRaw(struct drive *drive, int secondary, uint32_t entry_index,
|
||||||
|
uint32_t raw);
|
||||||
|
|
||||||
|
void UpdateAllEntries(struct drive *drive);
|
||||||
|
|
||||||
|
uint8_t RepairHeader(GptData *gpt, const uint32_t valid_headers);
|
||||||
|
uint8_t RepairEntries(GptData *gpt, const uint32_t valid_entries);
|
||||||
|
void UpdateCrc(GptData *gpt);
|
||||||
|
int IsSynonymous(const GptHeader* a, const GptHeader* b);
|
||||||
|
|
||||||
|
int IsUnused(struct drive *drive, int secondary, uint32_t index);
|
||||||
|
int IsKernel(struct drive *drive, int secondary, uint32_t index);
|
||||||
|
|
||||||
|
// Optional. Applications that need this must provide an implementation.
|
||||||
|
//
|
||||||
|
// Explanation:
|
||||||
|
// Some external utilities need to manipulate the GPT, but don't create new
|
||||||
|
// partitions from scratch. The cgpt executable uses libuuid to provide this
|
||||||
|
// functionality, but we don't want to have to build or install a separate
|
||||||
|
// instance of that library just for the 32-bit static post-install tool,
|
||||||
|
// which doesn't need this function.
|
||||||
|
int GenerateGuid(Guid *newguid);
|
||||||
|
|
||||||
|
// For usage and error messages.
|
||||||
|
void Error(const char *format, ...);
|
||||||
|
void Warning(const char *format, ...);
|
||||||
|
|
||||||
|
// Command functions.
|
||||||
|
int check_int_parse(char option, const char *buf);
|
||||||
|
int check_int_limit(char option, int val, int low, int high);
|
||||||
|
int cmd_show(int argc, char *argv[]);
|
||||||
|
int cmd_repair(int argc, char *argv[]);
|
||||||
|
int cmd_create(int argc, char *argv[]);
|
||||||
|
int cmd_add(int argc, char *argv[]);
|
||||||
|
int cmd_boot(int argc, char *argv[]);
|
||||||
|
int cmd_find(int argc, char *argv[]);
|
||||||
|
int cmd_prioritize(int argc, char *argv[]);
|
||||||
|
int cmd_legacy(int argc, char *argv[]);
|
||||||
|
|
||||||
|
#define ARRAY_COUNT(array) (sizeof(array)/sizeof((array)[0]))
|
||||||
|
const char *GptError(int errnum);
|
||||||
|
|
||||||
|
// Size in chars of the GPT Entry's PartitionName field
|
||||||
|
#define GPT_PARTNAME_LEN 72
|
||||||
|
|
||||||
|
/* The standard "assert" macro goes away when NDEBUG is defined. This doesn't.
|
||||||
|
*/
|
||||||
|
#define require(A) do { \
|
||||||
|
if (!(A)) { \
|
||||||
|
fprintf(stderr, "condition (%s) failed at %s:%d\n", \
|
||||||
|
#A, __FILE__, __LINE__); \
|
||||||
|
exit(1); } \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#endif // VBOOT_REFERENCE_UTILITY_CGPT_CGPT_H_
|
||||||
332
firmware/coreboot/3rdparty/vboot/cgpt/cgpt_add.c
vendored
Normal file
332
firmware/coreboot/3rdparty/vboot/cgpt/cgpt_add.c
vendored
Normal file
@@ -0,0 +1,332 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "cgpt.h"
|
||||||
|
#include "cgpt_params.h"
|
||||||
|
#include "cgptlib_internal.h"
|
||||||
|
#include "utility.h"
|
||||||
|
#include "vboot_host.h"
|
||||||
|
|
||||||
|
static const char* DumpCgptAddParams(const CgptAddParams *params) {
|
||||||
|
static char buf[256];
|
||||||
|
char tmp[64];
|
||||||
|
|
||||||
|
buf[0] = 0;
|
||||||
|
snprintf(tmp, sizeof(tmp), "-i %d ", params->partition);
|
||||||
|
StrnAppend(buf, tmp, sizeof(buf));
|
||||||
|
if (params->label) {
|
||||||
|
snprintf(tmp, sizeof(tmp), "-l %s ", params->label);
|
||||||
|
StrnAppend(buf, tmp, sizeof(buf));
|
||||||
|
}
|
||||||
|
if (params->set_begin) {
|
||||||
|
snprintf(tmp, sizeof(tmp), "-b %llu ", (unsigned long long)params->begin);
|
||||||
|
StrnAppend(buf, tmp, sizeof(buf));
|
||||||
|
}
|
||||||
|
if (params->set_size) {
|
||||||
|
snprintf(tmp, sizeof(tmp), "-s %llu ", (unsigned long long)params->size);
|
||||||
|
StrnAppend(buf, tmp, sizeof(buf));
|
||||||
|
}
|
||||||
|
if (params->set_type) {
|
||||||
|
GuidToStr(¶ms->type_guid, tmp, sizeof(tmp));
|
||||||
|
StrnAppend(buf, "-t ", sizeof(buf));
|
||||||
|
StrnAppend(buf, tmp, sizeof(buf));
|
||||||
|
StrnAppend(buf, " ", sizeof(buf));
|
||||||
|
}
|
||||||
|
if (params->set_unique) {
|
||||||
|
GuidToStr(¶ms->unique_guid, tmp, sizeof(tmp));
|
||||||
|
StrnAppend(buf, "-u ", sizeof(buf));
|
||||||
|
StrnAppend(buf, tmp, sizeof(buf));
|
||||||
|
StrnAppend(buf, " ", sizeof(buf));
|
||||||
|
}
|
||||||
|
if (params->set_successful) {
|
||||||
|
snprintf(tmp, sizeof(tmp), "-S %d ", params->successful);
|
||||||
|
StrnAppend(buf, tmp, sizeof(buf));
|
||||||
|
}
|
||||||
|
if (params->set_tries) {
|
||||||
|
snprintf(tmp, sizeof(tmp), "-T %d ", params->tries);
|
||||||
|
StrnAppend(buf, tmp, sizeof(buf));
|
||||||
|
}
|
||||||
|
if (params->set_priority) {
|
||||||
|
snprintf(tmp, sizeof(tmp), "-P %d ", params->priority);
|
||||||
|
StrnAppend(buf, tmp, sizeof(buf));
|
||||||
|
}
|
||||||
|
if (params->set_required) {
|
||||||
|
snprintf(tmp, sizeof(tmp), "-R %d ", params->required);
|
||||||
|
StrnAppend(buf, tmp, sizeof(buf));
|
||||||
|
}
|
||||||
|
if (params->set_legacy_boot) {
|
||||||
|
snprintf(tmp, sizeof(tmp), "-B %d ", params->legacy_boot);
|
||||||
|
StrnAppend(buf, tmp, sizeof(buf));
|
||||||
|
}
|
||||||
|
if (params->set_raw) {
|
||||||
|
snprintf(tmp, sizeof(tmp), "-A 0x%x ", params->raw_value);
|
||||||
|
StrnAppend(buf, tmp, sizeof(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
StrnAppend(buf, "\n", sizeof(buf));
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is the implementation-specific helper function.
|
||||||
|
static int GptSetEntryAttributes(struct drive *drive,
|
||||||
|
uint32_t index,
|
||||||
|
CgptAddParams *params) {
|
||||||
|
GptEntry *entry;
|
||||||
|
|
||||||
|
entry = GetEntry(&drive->gpt, PRIMARY, index);
|
||||||
|
if (params->set_begin)
|
||||||
|
entry->starting_lba = params->begin;
|
||||||
|
if (params->set_size)
|
||||||
|
entry->ending_lba = entry->starting_lba + params->size - 1;
|
||||||
|
if (params->set_unique) {
|
||||||
|
memcpy(&entry->unique, ¶ms->unique_guid, sizeof(Guid));
|
||||||
|
} else if (GuidIsZero(&entry->type)) {
|
||||||
|
if (CGPT_OK != GenerateGuid(&entry->unique)) {
|
||||||
|
Error("Unable to generate new GUID.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (params->set_type)
|
||||||
|
memcpy(&entry->type, ¶ms->type_guid, sizeof(Guid));
|
||||||
|
if (params->label) {
|
||||||
|
if (CGPT_OK != UTF8ToUTF16((uint8_t *)params->label, entry->name,
|
||||||
|
sizeof(entry->name) / sizeof(entry->name[0]))) {
|
||||||
|
Error("The label cannot be converted to UTF16.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is an internal helper function which assumes no NULL args are passed.
|
||||||
|
// It sets the given attribute values for a single entry at the given index.
|
||||||
|
static int SetEntryAttributes(struct drive *drive,
|
||||||
|
uint32_t index,
|
||||||
|
CgptAddParams *params) {
|
||||||
|
if (params->set_raw) {
|
||||||
|
SetRaw(drive, PRIMARY, index, params->raw_value);
|
||||||
|
} else {
|
||||||
|
if (params->set_successful)
|
||||||
|
SetSuccessful(drive, PRIMARY, index, params->successful);
|
||||||
|
if (params->set_tries)
|
||||||
|
SetTries(drive, PRIMARY, index, params->tries);
|
||||||
|
if (params->set_priority)
|
||||||
|
SetPriority(drive, PRIMARY, index, params->priority);
|
||||||
|
if (params->set_legacy_boot)
|
||||||
|
SetLegacyBoot(drive, PRIMARY, index, params->legacy_boot);
|
||||||
|
if (params->set_required)
|
||||||
|
SetRequired(drive, PRIMARY, index, params->required);
|
||||||
|
}
|
||||||
|
|
||||||
|
// New partitions must specify type, begin, and size.
|
||||||
|
if (IsUnused(drive, PRIMARY, index)) {
|
||||||
|
if (!params->set_begin || !params->set_size || !params->set_type) {
|
||||||
|
Error("-t, -b, and -s options are required for new partitions\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (GuidIsZero(¶ms->type_guid)) {
|
||||||
|
Error("New partitions must have a type other than \"unused\"\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int CgptCheckAddValidity(struct drive *drive) {
|
||||||
|
int gpt_retval;
|
||||||
|
if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive->gpt))) {
|
||||||
|
Error("GptSanityCheck() returned %d: %s\n",
|
||||||
|
gpt_retval, GptError(gpt_retval));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CGPT_OK != CheckValid(drive)) {
|
||||||
|
Error("please run 'cgpt repair' before adding anything.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int CgptGetUnusedPartition(struct drive *drive, uint32_t *index,
|
||||||
|
CgptAddParams *params) {
|
||||||
|
uint32_t i;
|
||||||
|
uint32_t max_part = GetNumberOfEntries(drive);
|
||||||
|
if (params->partition) {
|
||||||
|
if (params->partition > max_part) {
|
||||||
|
Error("invalid partition number: %d\n", params->partition);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*index = params->partition - 1;
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
// Find next empty partition.
|
||||||
|
for (i = 0; i < max_part; i++) {
|
||||||
|
if (IsUnused(drive, PRIMARY, i)) {
|
||||||
|
params->partition = i + 1;
|
||||||
|
*index = i;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Error("no unused partitions available\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int CgptSetAttributes(CgptAddParams *params) {
|
||||||
|
struct drive drive;
|
||||||
|
|
||||||
|
if (params == NULL)
|
||||||
|
return CGPT_FAILED;
|
||||||
|
|
||||||
|
if (CGPT_OK != DriveOpen(params->drive_name, &drive, O_RDWR,
|
||||||
|
params->drive_size))
|
||||||
|
return CGPT_FAILED;
|
||||||
|
|
||||||
|
if (CgptCheckAddValidity(&drive)) {
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params->partition == 0 ||
|
||||||
|
params->partition >= GetNumberOfEntries(&drive)) {
|
||||||
|
Error("invalid partition number: %d\n", params->partition);
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetEntryAttributes(&drive, params->partition - 1, params);
|
||||||
|
|
||||||
|
UpdateAllEntries(&drive);
|
||||||
|
|
||||||
|
// Write it all out.
|
||||||
|
return DriveClose(&drive, 1);
|
||||||
|
|
||||||
|
bad:
|
||||||
|
DriveClose(&drive, 0);
|
||||||
|
return CGPT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This method gets the partition details such as the attributes, the
|
||||||
|
// guids of the partitions, etc. Input is the partition number or the
|
||||||
|
// unique id of the partition. Output is populated in the respective
|
||||||
|
// fields of params.
|
||||||
|
int CgptGetPartitionDetails(CgptAddParams *params) {
|
||||||
|
struct drive drive;
|
||||||
|
int result = CGPT_FAILED;
|
||||||
|
int index;
|
||||||
|
|
||||||
|
if (params == NULL)
|
||||||
|
return CGPT_FAILED;
|
||||||
|
|
||||||
|
if (CGPT_OK != DriveOpen(params->drive_name, &drive, O_RDWR,
|
||||||
|
params->drive_size))
|
||||||
|
return CGPT_FAILED;
|
||||||
|
|
||||||
|
if (CgptCheckAddValidity(&drive)) {
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
|
||||||
|
int max_part = GetNumberOfEntries(&drive);
|
||||||
|
if (params->partition > 0) {
|
||||||
|
if (params->partition >= max_part) {
|
||||||
|
Error("invalid partition number: %d\n", params->partition);
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!params->set_unique) {
|
||||||
|
Error("either partition or unique_id must be specified\n");
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
for (index = 0; index < max_part; index++) {
|
||||||
|
GptEntry *entry = GetEntry(&drive.gpt, PRIMARY, index);
|
||||||
|
if (GuidEqual(&entry->unique, ¶ms->unique_guid)) {
|
||||||
|
params->partition = index + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (index >= max_part) {
|
||||||
|
Error("no partitions with the given unique id available\n");
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
index = params->partition - 1;
|
||||||
|
|
||||||
|
// GPT-specific code
|
||||||
|
GptEntry *entry = GetEntry(&drive.gpt, PRIMARY, index);
|
||||||
|
params->begin = entry->starting_lba;
|
||||||
|
params->size = entry->ending_lba - entry->starting_lba + 1;
|
||||||
|
memcpy(¶ms->type_guid, &entry->type, sizeof(Guid));
|
||||||
|
memcpy(¶ms->unique_guid, &entry->unique, sizeof(Guid));
|
||||||
|
params->raw_value = entry->attrs.fields.gpt_att;
|
||||||
|
|
||||||
|
params->successful = GetSuccessful(&drive, PRIMARY, index);
|
||||||
|
params->tries = GetTries(&drive, PRIMARY, index);
|
||||||
|
params->priority = GetPriority(&drive, PRIMARY, index);
|
||||||
|
result = CGPT_OK;
|
||||||
|
|
||||||
|
bad:
|
||||||
|
DriveClose(&drive, 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int GptAdd(struct drive *drive, CgptAddParams *params, uint32_t index) {
|
||||||
|
GptEntry *entry, backup;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
entry = GetEntry(&drive->gpt, PRIMARY, index);
|
||||||
|
memcpy(&backup, entry, sizeof(backup));
|
||||||
|
|
||||||
|
if (SetEntryAttributes(drive, index, params) ||
|
||||||
|
GptSetEntryAttributes(drive, index, params)) {
|
||||||
|
memcpy(entry, &backup, sizeof(*entry));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateAllEntries(drive);
|
||||||
|
|
||||||
|
rv = CheckEntries((GptEntry*)drive->gpt.primary_entries,
|
||||||
|
(GptHeader*)drive->gpt.primary_header);
|
||||||
|
|
||||||
|
if (0 != rv) {
|
||||||
|
// If the modified entry is illegal, recover it and return error.
|
||||||
|
memcpy(entry, &backup, sizeof(*entry));
|
||||||
|
Error("%s\n", GptErrorText(rv));
|
||||||
|
Error(DumpCgptAddParams(params));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CgptAdd(CgptAddParams *params) {
|
||||||
|
struct drive drive;
|
||||||
|
uint32_t index;
|
||||||
|
|
||||||
|
if (params == NULL)
|
||||||
|
return CGPT_FAILED;
|
||||||
|
|
||||||
|
if (CGPT_OK != DriveOpen(params->drive_name, &drive, O_RDWR,
|
||||||
|
params->drive_size))
|
||||||
|
return CGPT_FAILED;
|
||||||
|
|
||||||
|
if (CgptCheckAddValidity(&drive)) {
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CgptGetUnusedPartition(&drive, &index, params)) {
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GptAdd(&drive, params, index))
|
||||||
|
goto bad;
|
||||||
|
|
||||||
|
// Write it all out.
|
||||||
|
return DriveClose(&drive, 1);
|
||||||
|
|
||||||
|
bad:
|
||||||
|
DriveClose(&drive, 0);
|
||||||
|
return CGPT_FAILED;
|
||||||
|
}
|
||||||
152
firmware/coreboot/3rdparty/vboot/cgpt/cgpt_boot.c
vendored
Normal file
152
firmware/coreboot/3rdparty/vboot/cgpt/cgpt_boot.c
vendored
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "cgpt.h"
|
||||||
|
#include "cgpt_params.h"
|
||||||
|
#include "cgptlib_internal.h"
|
||||||
|
#include "vboot_host.h"
|
||||||
|
|
||||||
|
int CgptGetBootPartitionNumber(CgptBootParams *params) {
|
||||||
|
struct drive drive;
|
||||||
|
int gpt_retval= 0;
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
if (params == NULL)
|
||||||
|
return CGPT_FAILED;
|
||||||
|
|
||||||
|
if (CGPT_OK != DriveOpen(params->drive_name, &drive, O_RDONLY,
|
||||||
|
params->drive_size))
|
||||||
|
return CGPT_FAILED;
|
||||||
|
|
||||||
|
if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive.gpt))) {
|
||||||
|
Error("GptSanityCheck() returned %d: %s\n",
|
||||||
|
gpt_retval, GptError(gpt_retval));
|
||||||
|
retval = CGPT_FAILED;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CGPT_OK != ReadPMBR(&drive)) {
|
||||||
|
Error("Unable to read PMBR\n");
|
||||||
|
retval = CGPT_FAILED;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
char buf[GUID_STRLEN];
|
||||||
|
GuidToStr(&drive.pmbr.boot_guid, buf, sizeof(buf));
|
||||||
|
|
||||||
|
int numEntries = GetNumberOfEntries(&drive);
|
||||||
|
int i;
|
||||||
|
for(i = 0; i < numEntries; i++) {
|
||||||
|
GptEntry *entry = GetEntry(&drive.gpt, ANY_VALID, i);
|
||||||
|
|
||||||
|
if (GuidEqual(&entry->unique, &drive.pmbr.boot_guid)) {
|
||||||
|
params->partition = i + 1;
|
||||||
|
retval = CGPT_OK;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Error("Didn't find any boot partition\n");
|
||||||
|
params->partition = 0;
|
||||||
|
retval = CGPT_FAILED;
|
||||||
|
|
||||||
|
done:
|
||||||
|
(void) DriveClose(&drive, 1);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int CgptBoot(CgptBootParams *params) {
|
||||||
|
struct drive drive;
|
||||||
|
int retval = 1;
|
||||||
|
int gpt_retval= 0;
|
||||||
|
int mode = O_RDONLY;
|
||||||
|
|
||||||
|
if (params == NULL)
|
||||||
|
return CGPT_FAILED;
|
||||||
|
|
||||||
|
if (params->create_pmbr || params->partition || params->bootfile)
|
||||||
|
mode = O_RDWR;
|
||||||
|
|
||||||
|
if (CGPT_OK != DriveOpen(params->drive_name, &drive, mode,
|
||||||
|
params->drive_size)) {
|
||||||
|
return CGPT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CGPT_OK != ReadPMBR(&drive)) {
|
||||||
|
Error("Unable to read PMBR\n");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params->create_pmbr) {
|
||||||
|
drive.pmbr.magic[0] = 0x1d;
|
||||||
|
drive.pmbr.magic[1] = 0x9a;
|
||||||
|
drive.pmbr.sig[0] = 0x55;
|
||||||
|
drive.pmbr.sig[1] = 0xaa;
|
||||||
|
memset(&drive.pmbr.part, 0, sizeof(drive.pmbr.part));
|
||||||
|
drive.pmbr.part[0].f_head = 0x00;
|
||||||
|
drive.pmbr.part[0].f_sect = 0x02;
|
||||||
|
drive.pmbr.part[0].f_cyl = 0x00;
|
||||||
|
drive.pmbr.part[0].type = 0xee;
|
||||||
|
drive.pmbr.part[0].l_head = 0xff;
|
||||||
|
drive.pmbr.part[0].l_sect = 0xff;
|
||||||
|
drive.pmbr.part[0].l_cyl = 0xff;
|
||||||
|
drive.pmbr.part[0].f_lba = htole32(1);
|
||||||
|
uint32_t max = 0xffffffff;
|
||||||
|
if (drive.gpt.streaming_drive_sectors < 0xffffffff)
|
||||||
|
max = drive.gpt.streaming_drive_sectors - 1;
|
||||||
|
drive.pmbr.part[0].num_sect = htole32(max);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params->partition) {
|
||||||
|
if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive.gpt))) {
|
||||||
|
Error("GptSanityCheck() returned %d: %s\n",
|
||||||
|
gpt_retval, GptError(gpt_retval));
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params->partition > GetNumberOfEntries(&drive)) {
|
||||||
|
Error("invalid partition number: %d\n", params->partition);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t index = params->partition - 1;
|
||||||
|
GptEntry *entry = GetEntry(&drive.gpt, ANY_VALID, index);
|
||||||
|
memcpy(&drive.pmbr.boot_guid, &entry->unique, sizeof(Guid));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params->bootfile) {
|
||||||
|
int fd = open(params->bootfile, O_RDONLY);
|
||||||
|
if (fd < 0) {
|
||||||
|
Error("Can't read %s: %s\n", params->bootfile, strerror(errno));
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
int n = read(fd, drive.pmbr.bootcode, sizeof(drive.pmbr.bootcode));
|
||||||
|
if (n < 1) {
|
||||||
|
Error("problem reading %s: %s\n", params->bootfile, strerror(errno));
|
||||||
|
close(fd);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
char buf[GUID_STRLEN];
|
||||||
|
GuidToStr(&drive.pmbr.boot_guid, buf, sizeof(buf));
|
||||||
|
printf("%s\n", buf);
|
||||||
|
|
||||||
|
// Write it all out, if needed.
|
||||||
|
if (mode == O_RDONLY || CGPT_OK == WritePMBR(&drive))
|
||||||
|
retval = 0;
|
||||||
|
|
||||||
|
done:
|
||||||
|
(void) DriveClose(&drive, 1);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
1096
firmware/coreboot/3rdparty/vboot/cgpt/cgpt_common.c
vendored
Normal file
1096
firmware/coreboot/3rdparty/vboot/cgpt/cgpt_common.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
127
firmware/coreboot/3rdparty/vboot/cgpt/cgpt_create.c
vendored
Normal file
127
firmware/coreboot/3rdparty/vboot/cgpt/cgpt_create.c
vendored
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "cgpt.h"
|
||||||
|
#include "cgptlib_internal.h"
|
||||||
|
#include "vboot_host.h"
|
||||||
|
|
||||||
|
static void AllocAndClear(uint8_t **buf, uint64_t size) {
|
||||||
|
if (*buf) {
|
||||||
|
memset(*buf, 0, size);
|
||||||
|
} else {
|
||||||
|
*buf = calloc(1, size);
|
||||||
|
if (!*buf) {
|
||||||
|
Error("Cannot allocate %u bytes.\n", size);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int GptCreate(struct drive *drive, CgptCreateParams *params) {
|
||||||
|
// Allocate and/or erase the data.
|
||||||
|
// We cannot assume the GPT headers or entry arrays have been allocated
|
||||||
|
// by GptLoad() because those fields might have failed validation checks.
|
||||||
|
AllocAndClear(&drive->gpt.primary_header,
|
||||||
|
drive->gpt.sector_bytes * GPT_HEADER_SECTORS);
|
||||||
|
AllocAndClear(&drive->gpt.secondary_header,
|
||||||
|
drive->gpt.sector_bytes * GPT_HEADER_SECTORS);
|
||||||
|
|
||||||
|
drive->gpt.modified |= (GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1 |
|
||||||
|
GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2);
|
||||||
|
|
||||||
|
// Initialize a blank set
|
||||||
|
if (!params->zap) {
|
||||||
|
GptHeader *h = (GptHeader *)drive->gpt.primary_header;
|
||||||
|
memcpy(h->signature, GPT_HEADER_SIGNATURE, GPT_HEADER_SIGNATURE_SIZE);
|
||||||
|
h->revision = GPT_HEADER_REVISION;
|
||||||
|
h->size = sizeof(GptHeader);
|
||||||
|
h->my_lba = GPT_PMBR_SECTORS; /* The second sector on drive. */
|
||||||
|
h->alternate_lba = drive->gpt.gpt_drive_sectors - GPT_HEADER_SECTORS;
|
||||||
|
if (CGPT_OK != GenerateGuid(&h->disk_uuid)) {
|
||||||
|
Error("Unable to generate new GUID.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculate number of entries */
|
||||||
|
h->size_of_entry = sizeof(GptEntry);
|
||||||
|
h->number_of_entries = MAX_NUMBER_OF_ENTRIES;
|
||||||
|
if (drive->gpt.flags & GPT_FLAG_EXTERNAL) {
|
||||||
|
// We might have smaller space for the GPT table. Scale accordingly.
|
||||||
|
//
|
||||||
|
// +------+------------+---------------+-----+--------------+-----------+
|
||||||
|
// | PMBR | Prim. Head | Prim. Entries | ... | Sec. Entries | Sec. Head |
|
||||||
|
// +------+------------+---------------+-----+--------------+-----------+
|
||||||
|
//
|
||||||
|
// Half the size of gpt_drive_sectors must be big enough to hold PMBR +
|
||||||
|
// GPT Header + Entries Table, though the secondary structures do not
|
||||||
|
// contain PMBR.
|
||||||
|
size_t required_headers_size =
|
||||||
|
(GPT_PMBR_SECTORS + GPT_HEADER_SECTORS) * drive->gpt.sector_bytes;
|
||||||
|
size_t min_entries_size = MIN_NUMBER_OF_ENTRIES * h->size_of_entry;
|
||||||
|
size_t required_min_size = required_headers_size + min_entries_size;
|
||||||
|
size_t half_size =
|
||||||
|
(drive->gpt.gpt_drive_sectors / 2) * drive->gpt.sector_bytes;
|
||||||
|
if (half_size < required_min_size) {
|
||||||
|
Error("Not enough space to store GPT structures. Required %d bytes.\n",
|
||||||
|
required_min_size * 2);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
size_t max_entries =
|
||||||
|
(half_size - required_headers_size) / h->size_of_entry;
|
||||||
|
if (h->number_of_entries > max_entries) {
|
||||||
|
h->number_of_entries = max_entries;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Then use number of entries to calculate entries_lba. */
|
||||||
|
h->entries_lba = h->my_lba + GPT_HEADER_SECTORS;
|
||||||
|
if (!(drive->gpt.flags & GPT_FLAG_EXTERNAL)) {
|
||||||
|
h->entries_lba += params->padding;
|
||||||
|
h->first_usable_lba = h->entries_lba + CalculateEntriesSectors(h,
|
||||||
|
drive->gpt.sector_bytes);
|
||||||
|
h->last_usable_lba =
|
||||||
|
(drive->gpt.streaming_drive_sectors - GPT_HEADER_SECTORS -
|
||||||
|
CalculateEntriesSectors(h, drive->gpt.sector_bytes) - 1);
|
||||||
|
} else {
|
||||||
|
h->first_usable_lba = params->padding;
|
||||||
|
h->last_usable_lba = (drive->gpt.streaming_drive_sectors - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t entries_size = h->number_of_entries * h->size_of_entry;
|
||||||
|
AllocAndClear(&drive->gpt.primary_entries, entries_size);
|
||||||
|
AllocAndClear(&drive->gpt.secondary_entries, entries_size);
|
||||||
|
|
||||||
|
// Copy to secondary
|
||||||
|
RepairHeader(&drive->gpt, MASK_PRIMARY);
|
||||||
|
|
||||||
|
UpdateCrc(&drive->gpt);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CgptCreate(CgptCreateParams *params) {
|
||||||
|
struct drive drive;
|
||||||
|
|
||||||
|
if (params == NULL)
|
||||||
|
return CGPT_FAILED;
|
||||||
|
|
||||||
|
if (CGPT_OK != DriveOpen(params->drive_name, &drive, O_RDWR,
|
||||||
|
params->drive_size))
|
||||||
|
return CGPT_FAILED;
|
||||||
|
|
||||||
|
if (GptCreate(&drive, params))
|
||||||
|
goto bad;
|
||||||
|
|
||||||
|
// Write it all out
|
||||||
|
return DriveClose(&drive, 1);
|
||||||
|
|
||||||
|
bad:
|
||||||
|
|
||||||
|
DriveClose(&drive, 0);
|
||||||
|
return CGPT_FAILED;
|
||||||
|
}
|
||||||
53
firmware/coreboot/3rdparty/vboot/cgpt/cgpt_endian.h
vendored
Normal file
53
firmware/coreboot/3rdparty/vboot/cgpt/cgpt_endian.h
vendored
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
/* Copyright (c) 2010 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef VBOOT_REFERENCE_UTILITY_CGPT_ENDIAN_H_
|
||||||
|
#define VBOOT_REFERENCE_UTILITY_CGPT_ENDIAN_H_
|
||||||
|
|
||||||
|
// Newer distros already have this. For those that don't, we add it here.
|
||||||
|
#ifndef HAVE_MACOS
|
||||||
|
#include <endian.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef le16toh
|
||||||
|
|
||||||
|
#ifndef HAVE_MACOS
|
||||||
|
# include <byteswap.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
# if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||||
|
# define htobe16(x) __bswap_16 (x)
|
||||||
|
# define htole16(x) (x)
|
||||||
|
# define be16toh(x) __bswap_16 (x)
|
||||||
|
# define le16toh(x) (x)
|
||||||
|
|
||||||
|
# define htobe32(x) __bswap_32 (x)
|
||||||
|
# define htole32(x) (x)
|
||||||
|
# define be32toh(x) __bswap_32 (x)
|
||||||
|
# define le32toh(x) (x)
|
||||||
|
|
||||||
|
# define htobe64(x) __bswap_64 (x)
|
||||||
|
# define htole64(x) (x)
|
||||||
|
# define be64toh(x) __bswap_64 (x)
|
||||||
|
# define le64toh(x) (x)
|
||||||
|
# else
|
||||||
|
# define htobe16(x) (x)
|
||||||
|
# define htole16(x) __bswap_16 (x)
|
||||||
|
# define be16toh(x) (x)
|
||||||
|
# define le16toh(x) __bswap_16 (x)
|
||||||
|
|
||||||
|
# define htobe32(x) (x)
|
||||||
|
# define htole32(x) __bswap_32 (x)
|
||||||
|
# define be32toh(x) (x)
|
||||||
|
# define le32toh(x) __bswap_32 (x)
|
||||||
|
|
||||||
|
# define htobe64(x) (x)
|
||||||
|
# define htole64(x) __bswap_64 (x)
|
||||||
|
# define be64toh(x) (x)
|
||||||
|
# define le64toh(x) __bswap_64 (x)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif // VBOOT_REFERENCE_UTILITY_CGPT_ENDIAN_H_
|
||||||
311
firmware/coreboot/3rdparty/vboot/cgpt/cgpt_find.c
vendored
Normal file
311
firmware/coreboot/3rdparty/vboot/cgpt/cgpt_find.c
vendored
Normal file
@@ -0,0 +1,311 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "cgpt.h"
|
||||||
|
#include "cgpt_nor.h"
|
||||||
|
#include "cgptlib_internal.h"
|
||||||
|
#include "vboot_host.h"
|
||||||
|
|
||||||
|
#define BUFSIZE 1024
|
||||||
|
|
||||||
|
// fill comparebuf with the data to be examined, returning true on success.
|
||||||
|
static int FillBuffer(CgptFindParams *params, int fd, uint64_t pos,
|
||||||
|
uint64_t count) {
|
||||||
|
uint8_t *bufptr = params->comparebuf;
|
||||||
|
|
||||||
|
if (-1 == lseek(fd, pos, SEEK_SET))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// keep reading until done or error
|
||||||
|
while (count) {
|
||||||
|
ssize_t bytes_read = read(fd, bufptr, count);
|
||||||
|
// negative means error, 0 means (unexpected) EOF
|
||||||
|
if (bytes_read <= 0)
|
||||||
|
return 0;
|
||||||
|
count -= bytes_read;
|
||||||
|
bufptr += bytes_read;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check partition data content. return true for match, 0 for no match or error
|
||||||
|
static int match_content(CgptFindParams *params, struct drive *drive,
|
||||||
|
GptEntry *entry) {
|
||||||
|
uint64_t part_size;
|
||||||
|
|
||||||
|
if (!params->matchlen)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
// Ensure that the region we want to match against is inside the partition.
|
||||||
|
part_size = drive->gpt.sector_bytes *
|
||||||
|
(entry->ending_lba - entry->starting_lba + 1);
|
||||||
|
if (params->matchoffset + params->matchlen > part_size) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the partition data.
|
||||||
|
if (!FillBuffer(params, drive->fd,
|
||||||
|
(drive->gpt.sector_bytes * entry->starting_lba) + params->matchoffset,
|
||||||
|
params->matchlen)) {
|
||||||
|
Error("unable to read partition data\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare it
|
||||||
|
if (0 == memcmp(params->matchbuf, params->comparebuf, params->matchlen)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nope.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This needs to handle /dev/mmcblk0 -> /dev/mmcblk0p3, /dev/sda -> /dev/sda3
|
||||||
|
static void showmatch(CgptFindParams *params, char *filename,
|
||||||
|
int partnum, GptEntry *entry) {
|
||||||
|
char * format = "%s%d\n";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Follow convention from disk_name() in kernel block/partition-generic.c
|
||||||
|
* code:
|
||||||
|
* If the last digit of the device name is a number, add a 'p' between the
|
||||||
|
* device name and the partition number.
|
||||||
|
*/
|
||||||
|
if (isdigit(filename[strlen(filename) - 1]))
|
||||||
|
format = "%sp%d\n";
|
||||||
|
|
||||||
|
if (params->numeric) {
|
||||||
|
printf("%d\n", partnum);
|
||||||
|
} else {
|
||||||
|
if (params->show_fn) {
|
||||||
|
params->show_fn(params, filename, partnum, entry);
|
||||||
|
} else {
|
||||||
|
printf(format, filename, partnum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (params->verbose > 0)
|
||||||
|
EntryDetails(entry, partnum - 1, params->numeric);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This handles the MTD devices. ChromeOS uses /dev/mtdX for kernel partitions,
|
||||||
|
// /dev/ubiblockX_0 for root partitions, and /dev/ubiX for stateful partition.
|
||||||
|
static void chromeos_mtd_show(CgptFindParams *params, char *filename,
|
||||||
|
int partnum, GptEntry *entry) {
|
||||||
|
if (GuidEqual(&guid_chromeos_kernel, &entry->type)) {
|
||||||
|
printf("/dev/mtd%d\n", partnum);
|
||||||
|
} else if (GuidEqual(&guid_chromeos_rootfs, &entry->type)) {
|
||||||
|
printf("/dev/ubiblock%d_0\n", partnum);
|
||||||
|
} else {
|
||||||
|
printf("/dev/ubi%d_0\n", partnum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This returns true if a GPT partition matches the search criteria. If a match
|
||||||
|
// isn't found (or if the file doesn't contain a GPT), it returns false. The
|
||||||
|
// filename and partition number that matched is left in a global, since we
|
||||||
|
// could have multiple hits.
|
||||||
|
static int gpt_search(CgptFindParams *params, struct drive *drive,
|
||||||
|
char *filename) {
|
||||||
|
int i;
|
||||||
|
GptEntry *entry;
|
||||||
|
int retval = 0;
|
||||||
|
char partlabel[GPT_PARTNAME_LEN];
|
||||||
|
|
||||||
|
if (GPT_SUCCESS != GptSanityCheck(&drive->gpt)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < GetNumberOfEntries(drive); ++i) {
|
||||||
|
entry = GetEntry(&drive->gpt, ANY_VALID, i);
|
||||||
|
|
||||||
|
if (GuidIsZero(&entry->type))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int found = 0;
|
||||||
|
if ((params->set_unique && GuidEqual(¶ms->unique_guid, &entry->unique))
|
||||||
|
|| (params->set_type && GuidEqual(¶ms->type_guid, &entry->type))) {
|
||||||
|
found = 1;
|
||||||
|
} else if (params->set_label) {
|
||||||
|
if (CGPT_OK != UTF16ToUTF8(entry->name,
|
||||||
|
sizeof(entry->name) / sizeof(entry->name[0]),
|
||||||
|
(uint8_t *)partlabel, sizeof(partlabel))) {
|
||||||
|
Error("The label cannot be converted from UTF16, so abort.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!strncmp(params->label, partlabel, sizeof(partlabel)))
|
||||||
|
found = 1;
|
||||||
|
}
|
||||||
|
if (found && match_content(params, drive, entry)) {
|
||||||
|
params->hits++;
|
||||||
|
retval++;
|
||||||
|
showmatch(params, filename, i+1, entry);
|
||||||
|
if (!params->match_partnum)
|
||||||
|
params->match_partnum = i+1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int do_search(CgptFindParams *params, char *fileName) {
|
||||||
|
int retval;
|
||||||
|
struct drive drive;
|
||||||
|
|
||||||
|
if (CGPT_OK != DriveOpen(fileName, &drive, O_RDONLY, params->drive_size))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
retval = gpt_search(params, &drive, fileName);
|
||||||
|
|
||||||
|
(void) DriveClose(&drive, 0);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define PROC_MTD "/proc/mtd"
|
||||||
|
#define PROC_PARTITIONS "/proc/partitions"
|
||||||
|
#define DEV_DIR "/dev"
|
||||||
|
#define SYS_BLOCK_DIR "/sys/block"
|
||||||
|
#define MAX_PARTITION_NAME_LEN 128
|
||||||
|
|
||||||
|
static const char *devdirs[] = { "/dev", "/devices", "/devfs", 0 };
|
||||||
|
|
||||||
|
// Given basename "foo", see if we can find a whole, real device by that name.
|
||||||
|
// This is copied from the logic in the linux utility 'findfs', although that
|
||||||
|
// does more exhaustive searching.
|
||||||
|
static char *is_wholedev(const char *basename) {
|
||||||
|
int i;
|
||||||
|
struct stat statbuf;
|
||||||
|
static char pathname[BUFSIZE]; // we'll return this.
|
||||||
|
char tmpname[BUFSIZE];
|
||||||
|
|
||||||
|
// It should be a block device under /dev/,
|
||||||
|
for (i = 0; devdirs[i]; i++) {
|
||||||
|
sprintf(pathname, "%s/%s", devdirs[i], basename);
|
||||||
|
|
||||||
|
if (0 != stat(pathname, &statbuf))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!S_ISBLK(statbuf.st_mode))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// It should have a symlink called /sys/block/*/device
|
||||||
|
sprintf(tmpname, "%s/%s/device", SYS_BLOCK_DIR, basename);
|
||||||
|
|
||||||
|
if (0 != lstat(tmpname, &statbuf))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!S_ISLNK(statbuf.st_mode))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// found it
|
||||||
|
return pathname;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This scans all the physical devices it can find, looking for a match. It
|
||||||
|
// returns true if any matches were found, false otherwise.
|
||||||
|
static int scan_real_devs(CgptFindParams *params) {
|
||||||
|
int found = 0;
|
||||||
|
char partname[MAX_PARTITION_NAME_LEN];
|
||||||
|
char partname_prev[MAX_PARTITION_NAME_LEN];
|
||||||
|
FILE *fp;
|
||||||
|
char *pathname;
|
||||||
|
|
||||||
|
fp = fopen(PROC_PARTITIONS, "re");
|
||||||
|
if (!fp) {
|
||||||
|
perror("can't read " PROC_PARTITIONS);
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t line_length = 0;
|
||||||
|
char *line = NULL;
|
||||||
|
partname_prev[0] = '\0';
|
||||||
|
while (getline(&line, &line_length, fp) != -1) {
|
||||||
|
int ma, mi;
|
||||||
|
long long unsigned int sz;
|
||||||
|
|
||||||
|
if (sscanf(line, " %d %d %llu %127[^\n ]", &ma, &mi, &sz, partname) != 4)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Only check devices that have partitions under them.
|
||||||
|
* We can tell by checking that an entry like "sda" is immediately
|
||||||
|
* followed by one like "sda0". */
|
||||||
|
if (!strncmp(partname_prev, partname, strlen(partname_prev)) &&
|
||||||
|
strlen(partname_prev)) {
|
||||||
|
if ((pathname = is_wholedev(partname_prev))) {
|
||||||
|
if (do_search(params, pathname)) {
|
||||||
|
found++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(partname_prev, partname);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
fp = fopen(PROC_MTD, "re");
|
||||||
|
if (!fp) {
|
||||||
|
free(line);
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (getline(&line, &line_length, fp) != -1) {
|
||||||
|
uint64_t sz;
|
||||||
|
uint32_t erasesz;
|
||||||
|
char name[128];
|
||||||
|
// dev: size erasesize name
|
||||||
|
if (sscanf(line, "%64[^:]: %" PRIx64 " %x \"%127[^\"]\"",
|
||||||
|
partname, &sz, &erasesz, name) != 4)
|
||||||
|
continue;
|
||||||
|
if (strcmp(partname, "mtd0") == 0) {
|
||||||
|
char temp_dir[] = "/tmp/cgpt_find.XXXXXX";
|
||||||
|
if (params->drive_size == 0) {
|
||||||
|
if (GetMtdSize("/dev/mtd0", ¶ms->drive_size) != 0) {
|
||||||
|
perror("GetMtdSize");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ReadNorFlash(temp_dir) != 0) {
|
||||||
|
perror("ReadNorFlash");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
char nor_file[64];
|
||||||
|
if (snprintf(nor_file, sizeof(nor_file), "%s/rw_gpt", temp_dir) > 0) {
|
||||||
|
params->show_fn = chromeos_mtd_show;
|
||||||
|
if (do_search(params, nor_file)) {
|
||||||
|
found++;
|
||||||
|
}
|
||||||
|
params->show_fn = NULL;
|
||||||
|
}
|
||||||
|
RemoveDir(temp_dir);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cleanup:
|
||||||
|
fclose(fp);
|
||||||
|
free(line);
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CgptFind(CgptFindParams *params) {
|
||||||
|
if (params == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (params->drive_name != NULL)
|
||||||
|
do_search(params, params->drive_name);
|
||||||
|
else
|
||||||
|
scan_real_devs(params);
|
||||||
|
}
|
||||||
61
firmware/coreboot/3rdparty/vboot/cgpt/cgpt_legacy.c
vendored
Normal file
61
firmware/coreboot/3rdparty/vboot/cgpt/cgpt_legacy.c
vendored
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "cgpt.h"
|
||||||
|
#include "cgptlib_internal.h"
|
||||||
|
#include "vboot_host.h"
|
||||||
|
|
||||||
|
int CgptLegacy(CgptLegacyParams *params) {
|
||||||
|
struct drive drive;
|
||||||
|
int gpt_retval;
|
||||||
|
GptHeader *h1, *h2;
|
||||||
|
|
||||||
|
if (params == NULL)
|
||||||
|
return CGPT_FAILED;
|
||||||
|
|
||||||
|
if (CGPT_OK != DriveOpen(params->drive_name, &drive, O_RDWR,
|
||||||
|
params->drive_size))
|
||||||
|
return CGPT_FAILED;
|
||||||
|
|
||||||
|
if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive.gpt))) {
|
||||||
|
Error("GptSanityCheck() returned %d: %s\n",
|
||||||
|
gpt_retval, GptError(gpt_retval));
|
||||||
|
return CGPT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 = (GptHeader *)drive.gpt.primary_header;
|
||||||
|
h2 = (GptHeader *)drive.gpt.secondary_header;
|
||||||
|
if (params->mode == CGPT_LEGACY_MODE_EFIPART) {
|
||||||
|
drive.gpt.ignored = MASK_NONE;
|
||||||
|
memcpy(h1->signature, GPT_HEADER_SIGNATURE, GPT_HEADER_SIGNATURE_SIZE);
|
||||||
|
memcpy(h2->signature, GPT_HEADER_SIGNATURE, GPT_HEADER_SIGNATURE_SIZE);
|
||||||
|
RepairEntries(&drive.gpt, MASK_SECONDARY);
|
||||||
|
drive.gpt.modified |= (GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1 |
|
||||||
|
GPT_MODIFIED_HEADER2);
|
||||||
|
} else if (params->mode == CGPT_LEGACY_MODE_IGNORE_PRIMARY) {
|
||||||
|
if (!(drive.gpt.valid_headers & MASK_SECONDARY) ||
|
||||||
|
!(drive.gpt.valid_entries & MASK_SECONDARY) ||
|
||||||
|
drive.gpt.ignored & MASK_SECONDARY) {
|
||||||
|
Error("Refusing to mark primary GPT ignored unless secondary is valid.");
|
||||||
|
return CGPT_FAILED;
|
||||||
|
}
|
||||||
|
memset(h1, 0, sizeof(*h1));
|
||||||
|
memcpy(h1->signature, GPT_HEADER_SIGNATURE_IGNORED,
|
||||||
|
GPT_HEADER_SIGNATURE_SIZE);
|
||||||
|
drive.gpt.modified |= GPT_MODIFIED_HEADER1;
|
||||||
|
} else {
|
||||||
|
memcpy(h1->signature, GPT_HEADER_SIGNATURE2, GPT_HEADER_SIGNATURE_SIZE);
|
||||||
|
memcpy(h2->signature, GPT_HEADER_SIGNATURE2, GPT_HEADER_SIGNATURE_SIZE);
|
||||||
|
memset(drive.gpt.primary_entries, 0, drive.gpt.sector_bytes);
|
||||||
|
drive.gpt.modified |= (GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1 |
|
||||||
|
GPT_MODIFIED_HEADER2);
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateCrc(&drive.gpt);
|
||||||
|
|
||||||
|
// Write it all out
|
||||||
|
return DriveClose(&drive, 1);
|
||||||
|
}
|
||||||
263
firmware/coreboot/3rdparty/vboot/cgpt/cgpt_nor.c
vendored
Normal file
263
firmware/coreboot/3rdparty/vboot/cgpt/cgpt_nor.c
vendored
Normal file
@@ -0,0 +1,263 @@
|
|||||||
|
/* Copyright 2015 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <err.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <ftw.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <linux/major.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "cgpt.h"
|
||||||
|
#include "cgpt_nor.h"
|
||||||
|
|
||||||
|
static const char FLASHROM_PATH[] = "/usr/sbin/flashrom";
|
||||||
|
|
||||||
|
// Obtain the MTD size from its sysfs node.
|
||||||
|
int GetMtdSize(const char *mtd_device, uint64_t *size) {
|
||||||
|
mtd_device = strrchr(mtd_device, '/');
|
||||||
|
if (mtd_device == NULL) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
char *sysfs_name;
|
||||||
|
if (asprintf(&sysfs_name, "/sys/class/mtd%s/size", mtd_device) == -1) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
FILE *fp = fopen(sysfs_name, "r");
|
||||||
|
free(sysfs_name);
|
||||||
|
if (fp == NULL) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
int ret = (fscanf(fp, "%" PRIu64 "\n", size) != 1);
|
||||||
|
fclose(fp);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ForkExecV(const char *cwd, const char *const argv[]) {
|
||||||
|
pid_t pid = fork();
|
||||||
|
if (pid == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int status = -1;
|
||||||
|
if (pid == 0) {
|
||||||
|
if (cwd && chdir(cwd) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
execv(argv[0], (char *const *)argv);
|
||||||
|
// If this is reached, execv fails.
|
||||||
|
err(-1, "Cannot exec %s in %s.", argv[0], cwd);
|
||||||
|
} else {
|
||||||
|
if (waitpid(pid, &status, 0) != -1 && WIFEXITED(status))
|
||||||
|
return WEXITSTATUS(status);
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ForkExecL(const char *cwd, const char *cmd, ...) {
|
||||||
|
int argc;
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, cmd);
|
||||||
|
for (argc = 1; va_arg(ap, char *) != NULL; ++argc);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
va_start(ap, cmd);
|
||||||
|
const char **argv = calloc(argc + 1, sizeof(char *));
|
||||||
|
if (argv == NULL) {
|
||||||
|
errno = ENOMEM;
|
||||||
|
va_end(ap);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
argv[0] = cmd;
|
||||||
|
int i;
|
||||||
|
for (i = 1; i < argc; ++i) {
|
||||||
|
argv[i] = va_arg(ap, char *);
|
||||||
|
}
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
int ret = ForkExecV(cwd, argv);
|
||||||
|
free(argv);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int read_write(int source_fd,
|
||||||
|
uint64_t size,
|
||||||
|
const char *src_name,
|
||||||
|
int idx) {
|
||||||
|
int ret = 1;
|
||||||
|
const int bufsize = 4096;
|
||||||
|
char *buf = malloc(bufsize);
|
||||||
|
if (buf == NULL) {
|
||||||
|
goto clean_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret++;
|
||||||
|
char *dest;
|
||||||
|
if (asprintf(&dest, "%s_%d", src_name, idx) == -1) {
|
||||||
|
goto free_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret++;
|
||||||
|
int dest_fd = open(dest, O_WRONLY | O_CLOEXEC | O_CREAT, 0600);
|
||||||
|
if (dest_fd < 0) {
|
||||||
|
goto free_dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret++;
|
||||||
|
uint64_t copied = 0;
|
||||||
|
ssize_t nr_read;
|
||||||
|
ssize_t nr_write;
|
||||||
|
while (copied < size) {
|
||||||
|
size_t to_read = size - copied;
|
||||||
|
if (to_read > bufsize) {
|
||||||
|
to_read = bufsize;
|
||||||
|
}
|
||||||
|
nr_read = read(source_fd, buf, to_read);
|
||||||
|
if (nr_read < 0) {
|
||||||
|
goto close_dest_fd;
|
||||||
|
}
|
||||||
|
nr_write = 0;
|
||||||
|
while (nr_write < nr_read) {
|
||||||
|
ssize_t s = write(dest_fd, buf + nr_write, nr_read - nr_write);
|
||||||
|
if (s < 0) {
|
||||||
|
goto close_dest_fd;
|
||||||
|
}
|
||||||
|
nr_write += s;
|
||||||
|
}
|
||||||
|
copied += nr_read;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
close_dest_fd:
|
||||||
|
close(dest_fd);
|
||||||
|
free_dest:
|
||||||
|
free(dest);
|
||||||
|
free_buf:
|
||||||
|
free(buf);
|
||||||
|
clean_exit:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int split_gpt(const char *dir_name, const char *file_name) {
|
||||||
|
int ret = 1;
|
||||||
|
char *source;
|
||||||
|
if (asprintf(&source, "%s/%s", dir_name, file_name) == -1) {
|
||||||
|
goto clean_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret++;
|
||||||
|
int fd = open(source, O_RDONLY | O_CLOEXEC);
|
||||||
|
if (fd < 0) {
|
||||||
|
goto free_source;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret++;
|
||||||
|
struct stat stat;
|
||||||
|
if (fstat(fd, &stat) != 0 || (stat.st_size & 1) != 0) {
|
||||||
|
goto close_fd;
|
||||||
|
}
|
||||||
|
uint64_t half_size = stat.st_size / 2;
|
||||||
|
|
||||||
|
ret++;
|
||||||
|
if (read_write(fd, half_size, source, 1) != 0 ||
|
||||||
|
read_write(fd, half_size, source, 2) != 0) {
|
||||||
|
goto close_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
close_fd:
|
||||||
|
close(fd);
|
||||||
|
free_source:
|
||||||
|
free(source);
|
||||||
|
clean_exit:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int remove_file_or_dir(const char *fpath, const struct stat *sb,
|
||||||
|
int typeflag, struct FTW *ftwbuf) {
|
||||||
|
return remove(fpath);
|
||||||
|
}
|
||||||
|
|
||||||
|
int RemoveDir(const char *dir) {
|
||||||
|
return nftw(dir, remove_file_or_dir, 20, FTW_DEPTH | FTW_PHYS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read RW_GPT from NOR flash to "rw_gpt" in a temp dir |temp_dir_template|.
|
||||||
|
// |temp_dir_template| is passed to mkdtemp() so it must satisfy all
|
||||||
|
// requirements by mkdtemp.
|
||||||
|
int ReadNorFlash(char *temp_dir_template) {
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
// Create a temp dir to work in.
|
||||||
|
ret++;
|
||||||
|
if (mkdtemp(temp_dir_template) == NULL) {
|
||||||
|
Error("Cannot create a temporary directory.\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read RW_GPT section from NOR flash to "rw_gpt".
|
||||||
|
ret++;
|
||||||
|
int fd_flags = fcntl(1, F_GETFD);
|
||||||
|
// Close stdout on exec so that flashrom does not muck up cgpt's output.
|
||||||
|
if (0 != fcntl(1, F_SETFD, FD_CLOEXEC))
|
||||||
|
Warning("Can't stop flashrom from mucking up our output\n");
|
||||||
|
if (ForkExecL(temp_dir_template, FLASHROM_PATH, "-i", "RW_GPT:rw_gpt", "-r",
|
||||||
|
NULL) != 0) {
|
||||||
|
Error("Cannot exec flashrom to read from RW_GPT section.\n");
|
||||||
|
RemoveDir(temp_dir_template);
|
||||||
|
} else {
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore stdout flags
|
||||||
|
if (0 != fcntl(1, F_SETFD, fd_flags))
|
||||||
|
Warning("Can't restore stdout flags\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write "rw_gpt" back to NOR flash. We write the file in two parts for safety.
|
||||||
|
int WriteNorFlash(const char *dir) {
|
||||||
|
int ret = 0;
|
||||||
|
ret++;
|
||||||
|
if (split_gpt(dir, "rw_gpt") != 0) {
|
||||||
|
Error("Cannot split rw_gpt in two.\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
ret++;
|
||||||
|
int nr_fails = 0;
|
||||||
|
int fd_flags = fcntl(1, F_GETFD);
|
||||||
|
// Close stdout on exec so that flashrom does not muck up cgpt's output.
|
||||||
|
if (0 != fcntl(1, F_SETFD, FD_CLOEXEC))
|
||||||
|
Warning("Can't stop flashrom from mucking up our output\n");
|
||||||
|
if (ForkExecL(dir, FLASHROM_PATH, "-i", "RW_GPT_PRIMARY:rw_gpt_1",
|
||||||
|
"-w", "--fast-verify", NULL) != 0) {
|
||||||
|
Warning("Cannot write the 1st half of rw_gpt back with flashrom.\n");
|
||||||
|
nr_fails++;
|
||||||
|
}
|
||||||
|
if (ForkExecL(dir, FLASHROM_PATH, "-i", "RW_GPT_SECONDARY:rw_gpt_2",
|
||||||
|
"-w", "--fast-verify", NULL) != 0) {
|
||||||
|
Warning("Cannot write the 2nd half of rw_gpt back with flashrom.\n");
|
||||||
|
nr_fails++;
|
||||||
|
}
|
||||||
|
if (0 != fcntl(1, F_SETFD, fd_flags))
|
||||||
|
Warning("Can't restore stdout flags\n");
|
||||||
|
switch (nr_fails) {
|
||||||
|
case 0: ret = 0; break;
|
||||||
|
case 1: Warning("It might still be okay.\n"); break;
|
||||||
|
case 2: Error("Cannot write both parts back with flashrom.\n"); break;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
34
firmware/coreboot/3rdparty/vboot/cgpt/cgpt_nor.h
vendored
Normal file
34
firmware/coreboot/3rdparty/vboot/cgpt/cgpt_nor.h
vendored
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
/* Copyright 2015 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.
|
||||||
|
*
|
||||||
|
* This module provides some utility functions to use "flashrom" to read from
|
||||||
|
* and write to NOR flash.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef VBOOT_REFERCENCE_CGPT_CGPT_NOR_H_
|
||||||
|
#define VBOOT_REFERCENCE_CGPT_CGPT_NOR_H_
|
||||||
|
|
||||||
|
// Obtain the MTD size from its sysfs node. |mtd_device| should point to
|
||||||
|
// a dev node such as /dev/mtd0. This function returns 0 on success.
|
||||||
|
int GetMtdSize(const char *mtd_device, uint64_t *size);
|
||||||
|
|
||||||
|
// Exec |argv| in |cwd|. Return -1 on error, or exit code on success. |argv|
|
||||||
|
// must be terminated with a NULL element as is required by execv().
|
||||||
|
int ForkExecV(const char *cwd, const char *const argv[]);
|
||||||
|
|
||||||
|
// Similar to ForkExecV but with a vararg instead of an array of pointers.
|
||||||
|
int ForkExecL(const char *cwd, const char *cmd, ...);
|
||||||
|
|
||||||
|
// Exec "rm" to remove |dir|.
|
||||||
|
int RemoveDir(const char *dir);
|
||||||
|
|
||||||
|
// Read RW_GPT from NOR flash to "rw_gpt" in a temp dir |temp_dir_template|.
|
||||||
|
// |temp_dir_template| is passed to mkdtemp() so it must satisfy all
|
||||||
|
// requirements by mkdtemp().
|
||||||
|
int ReadNorFlash(char *temp_dir_template);
|
||||||
|
|
||||||
|
// Write "rw_gpt" back to NOR flash. We write the file in two parts for safety.
|
||||||
|
int WriteNorFlash(const char *dir);
|
||||||
|
|
||||||
|
#endif // VBOOT_REFERCENCE_CGPT_CGPT_NOR_H_
|
||||||
213
firmware/coreboot/3rdparty/vboot/cgpt/cgpt_prioritize.c
vendored
Normal file
213
firmware/coreboot/3rdparty/vboot/cgpt/cgpt_prioritize.c
vendored
Normal file
@@ -0,0 +1,213 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "cgpt.h"
|
||||||
|
#include "cgptlib_internal.h"
|
||||||
|
#include "vboot_host.h"
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// We need a sorted list of priority groups, where each element in the list
|
||||||
|
// contains an unordered list of GPT partition numbers.
|
||||||
|
|
||||||
|
#define MAX_GROUPS 17 // 0-15, plus one "higher"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int priority; // priority of this group
|
||||||
|
int num_parts; // number of partitions in this group
|
||||||
|
uint32_t *part; // array of partitions in this group
|
||||||
|
} group_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int max_parts; // max number of partitions in any group
|
||||||
|
int num_groups; // number of non-empty groups
|
||||||
|
group_t group[MAX_GROUPS]; // array of groups
|
||||||
|
} group_list_t;
|
||||||
|
|
||||||
|
|
||||||
|
static group_list_t *NewGroupList(int max_p) {
|
||||||
|
int i;
|
||||||
|
group_list_t *gl = (group_list_t *)malloc(sizeof(group_list_t));
|
||||||
|
require(gl);
|
||||||
|
gl->max_parts = max_p;
|
||||||
|
gl->num_groups = 0;
|
||||||
|
// reserve space for the maximum number of partitions in every group
|
||||||
|
for (i=0; i<MAX_GROUPS; i++) {
|
||||||
|
gl->group[i].priority = -1;
|
||||||
|
gl->group[i].num_parts = 0;
|
||||||
|
gl->group[i].part = (uint32_t *)malloc(sizeof(uint32_t) * max_p);
|
||||||
|
require(gl->group[i].part);
|
||||||
|
}
|
||||||
|
|
||||||
|
return gl;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void FreeGroups(group_list_t *gl) {
|
||||||
|
int i;
|
||||||
|
for (i=0; i<MAX_GROUPS; i++)
|
||||||
|
free(gl->group[i].part);
|
||||||
|
free(gl);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void AddToGroup(group_list_t *gl, int priority, int partition) {
|
||||||
|
int i;
|
||||||
|
// See if I've already got a group with this priority
|
||||||
|
for (i=0; i<gl->num_groups; i++)
|
||||||
|
if (gl->group[i].priority == priority)
|
||||||
|
break;
|
||||||
|
if (i == gl->num_groups) {
|
||||||
|
// no, add a group
|
||||||
|
require(i < MAX_GROUPS);
|
||||||
|
gl->num_groups++;
|
||||||
|
gl->group[i].priority = priority;
|
||||||
|
}
|
||||||
|
// add the partition to it
|
||||||
|
int j = gl->group[i].num_parts;
|
||||||
|
gl->group[i].part[j] = partition;
|
||||||
|
gl->group[i].num_parts++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ChangeGroup(group_list_t *gl, int old_priority, int new_priority) {
|
||||||
|
int i;
|
||||||
|
for (i=0; i<gl->num_groups; i++)
|
||||||
|
if (gl->group[i].priority == old_priority) {
|
||||||
|
gl->group[i].priority = new_priority;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SortGroups(group_list_t *gl) {
|
||||||
|
int i, j;
|
||||||
|
group_t tmp;
|
||||||
|
|
||||||
|
// straight insertion sort is fast enough
|
||||||
|
for (i=1; i<gl->num_groups; i++) {
|
||||||
|
tmp = gl->group[i];
|
||||||
|
for (j=i; j && (gl->group[j-1].priority < tmp.priority); j--)
|
||||||
|
gl->group[j] = gl->group[j-1];
|
||||||
|
gl->group[j] = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int CgptPrioritize(CgptPrioritizeParams *params) {
|
||||||
|
struct drive drive;
|
||||||
|
|
||||||
|
int priority;
|
||||||
|
|
||||||
|
int gpt_retval;
|
||||||
|
uint32_t index;
|
||||||
|
uint32_t max_part;
|
||||||
|
int num_kernels;
|
||||||
|
int i,j;
|
||||||
|
group_list_t *groups;
|
||||||
|
|
||||||
|
if (params == NULL)
|
||||||
|
return CGPT_FAILED;
|
||||||
|
|
||||||
|
if (CGPT_OK != DriveOpen(params->drive_name, &drive, O_RDWR,
|
||||||
|
params->drive_size))
|
||||||
|
return CGPT_FAILED;
|
||||||
|
|
||||||
|
if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive.gpt))) {
|
||||||
|
Error("GptSanityCheck() returned %d: %s\n",
|
||||||
|
gpt_retval, GptError(gpt_retval));
|
||||||
|
return CGPT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CGPT_OK != CheckValid(&drive)) {
|
||||||
|
Error("please run 'cgpt repair' before reordering the priority.\n");
|
||||||
|
return CGPT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
max_part = GetNumberOfEntries(&drive);
|
||||||
|
|
||||||
|
if (params->set_partition) {
|
||||||
|
if (params->set_partition < 1 || params->set_partition > max_part) {
|
||||||
|
Error("invalid partition number: %d (must be between 1 and %d\n",
|
||||||
|
params->set_partition, max_part);
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
index = params->set_partition - 1;
|
||||||
|
// it must be a kernel
|
||||||
|
if (!IsKernel(&drive, PRIMARY, index)) {
|
||||||
|
Error("partition %d is not a ChromeOS kernel\n", params->set_partition);
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// How many kernel partitions do I have?
|
||||||
|
num_kernels = 0;
|
||||||
|
for (i = 0; i < max_part; i++) {
|
||||||
|
if (IsKernel(&drive, PRIMARY, i))
|
||||||
|
num_kernels++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_kernels) {
|
||||||
|
// Determine the current priority groups
|
||||||
|
groups = NewGroupList(num_kernels);
|
||||||
|
for (i = 0; i < max_part; i++) {
|
||||||
|
if (!IsKernel(&drive, PRIMARY, i))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
priority = GetPriority(&drive, PRIMARY, i);
|
||||||
|
|
||||||
|
// Is this partition special?
|
||||||
|
if (params->set_partition && (i+1 == params->set_partition)) {
|
||||||
|
params->orig_priority = priority; // remember the original priority
|
||||||
|
if (params->set_friends)
|
||||||
|
AddToGroup(groups, priority, i); // we'll move them all later
|
||||||
|
else
|
||||||
|
AddToGroup(groups, 99, i); // move only this one
|
||||||
|
} else {
|
||||||
|
AddToGroup(groups, priority, i); // just remember
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're including friends, then change the original group priority
|
||||||
|
if (params->set_partition && params->set_friends) {
|
||||||
|
ChangeGroup(groups, params->orig_priority, 99);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sorting gives the new order. Now we just need to reassign the
|
||||||
|
// priorities.
|
||||||
|
SortGroups(groups);
|
||||||
|
|
||||||
|
// We'll never lower anything to zero, so if the last group is priority zero
|
||||||
|
// we can ignore it.
|
||||||
|
i = groups->num_groups;
|
||||||
|
if (groups->group[i-1].priority == 0)
|
||||||
|
groups->num_groups--;
|
||||||
|
|
||||||
|
// Where do we start?
|
||||||
|
if (params->max_priority)
|
||||||
|
priority = params->max_priority;
|
||||||
|
else
|
||||||
|
priority = groups->num_groups > 15 ? 15 : groups->num_groups;
|
||||||
|
|
||||||
|
// Figure out what the new values should be
|
||||||
|
for (i=0; i<groups->num_groups; i++) {
|
||||||
|
groups->group[i].priority = priority;
|
||||||
|
if (priority > 1)
|
||||||
|
priority--;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now apply the ranking to the GPT
|
||||||
|
for (i=0; i<groups->num_groups; i++)
|
||||||
|
for (j=0; j<groups->group[i].num_parts; j++)
|
||||||
|
SetPriority(&drive, PRIMARY,
|
||||||
|
groups->group[i].part[j], groups->group[i].priority);
|
||||||
|
|
||||||
|
FreeGroups(groups);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write it all out
|
||||||
|
UpdateAllEntries(&drive);
|
||||||
|
|
||||||
|
return DriveClose(&drive, 1);
|
||||||
|
|
||||||
|
bad:
|
||||||
|
(void) DriveClose(&drive, 0);
|
||||||
|
return CGPT_FAILED;
|
||||||
|
}
|
||||||
56
firmware/coreboot/3rdparty/vboot/cgpt/cgpt_repair.c
vendored
Normal file
56
firmware/coreboot/3rdparty/vboot/cgpt/cgpt_repair.c
vendored
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "cgpt.h"
|
||||||
|
#include "cgptlib_internal.h"
|
||||||
|
#include "vboot_host.h"
|
||||||
|
|
||||||
|
int CgptRepair(CgptRepairParams *params) {
|
||||||
|
struct drive drive;
|
||||||
|
|
||||||
|
if (params == NULL)
|
||||||
|
return CGPT_FAILED;
|
||||||
|
|
||||||
|
if (CGPT_OK != DriveOpen(params->drive_name, &drive, O_RDWR,
|
||||||
|
params->drive_size))
|
||||||
|
return CGPT_FAILED;
|
||||||
|
|
||||||
|
int gpt_retval = GptSanityCheck(&drive.gpt);
|
||||||
|
if (params->verbose)
|
||||||
|
printf("GptSanityCheck() returned %d: %s\n",
|
||||||
|
gpt_retval, GptError(gpt_retval));
|
||||||
|
|
||||||
|
GptHeader *header;
|
||||||
|
if (MASK_PRIMARY == drive.gpt.valid_headers ||
|
||||||
|
MASK_BOTH == drive.gpt.valid_headers) {
|
||||||
|
header = (GptHeader *)(drive.gpt.primary_header);
|
||||||
|
} else {
|
||||||
|
header = (GptHeader *)(drive.gpt.secondary_header);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MASK_PRIMARY == drive.gpt.valid_entries) {
|
||||||
|
free(drive.gpt.secondary_entries);
|
||||||
|
drive.gpt.secondary_entries =
|
||||||
|
malloc(header->size_of_entry * header->number_of_entries);
|
||||||
|
} else if (MASK_SECONDARY == drive.gpt.valid_entries) {
|
||||||
|
free(drive.gpt.primary_entries);
|
||||||
|
drive.gpt.primary_entries =
|
||||||
|
malloc(header->size_of_entry * header->number_of_entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
GptRepair(&drive.gpt);
|
||||||
|
if (drive.gpt.modified & GPT_MODIFIED_HEADER1)
|
||||||
|
printf("Primary Header is updated.\n");
|
||||||
|
if (drive.gpt.modified & GPT_MODIFIED_ENTRIES1)
|
||||||
|
printf("Primary Entries is updated.\n");
|
||||||
|
if (drive.gpt.modified & GPT_MODIFIED_ENTRIES2)
|
||||||
|
printf("Secondary Entries is updated.\n");
|
||||||
|
if (drive.gpt.modified & GPT_MODIFIED_HEADER2)
|
||||||
|
printf("Secondary Header is updated.\n");
|
||||||
|
|
||||||
|
return DriveClose(&drive, 1);
|
||||||
|
}
|
||||||
392
firmware/coreboot/3rdparty/vboot/cgpt/cgpt_show.c
vendored
Normal file
392
firmware/coreboot/3rdparty/vboot/cgpt/cgpt_show.c
vendored
Normal file
@@ -0,0 +1,392 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#define __STDC_FORMAT_MACROS
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "cgpt.h"
|
||||||
|
#include "cgptlib_internal.h"
|
||||||
|
#include "crc32.h"
|
||||||
|
#include "vboot_host.h"
|
||||||
|
|
||||||
|
/* Generate output like:
|
||||||
|
*
|
||||||
|
* [AB-CD-EF-01] for group = 1
|
||||||
|
* [ABCD-EF01] for group = 3 (low byte first)
|
||||||
|
*
|
||||||
|
* Needs (size*3-1+3) bytes of space in 'buf' (included the tailing '\0').
|
||||||
|
*/
|
||||||
|
#define BUFFER_SIZE(size) (size *3 - 1 + 3)
|
||||||
|
static short Uint8To2Chars(const uint8_t t) {
|
||||||
|
int h = t >> 4;
|
||||||
|
int l = t & 0xf;
|
||||||
|
h = (h >= 0xA) ? h - 0xA + 'A' : h + '0';
|
||||||
|
l = (l >= 0xA) ? l - 0xA + 'A' : l + '0';
|
||||||
|
return (h << 8) + l;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void RawDump(const uint8_t *memory, const int size,
|
||||||
|
char *buf, int group) {
|
||||||
|
int i, outlen = 0;
|
||||||
|
buf[outlen++] = '[';
|
||||||
|
for (i = 0; i < size; ++i) {
|
||||||
|
short c2 = Uint8To2Chars(memory[i]);
|
||||||
|
buf[outlen++] = c2 >> 8;
|
||||||
|
buf[outlen++] = c2 & 0xff;
|
||||||
|
if (i != (size - 1) && ((i + 1) % group) == 0)
|
||||||
|
buf[outlen++] = '-';
|
||||||
|
}
|
||||||
|
buf[outlen++] = ']';
|
||||||
|
buf[outlen++] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Output formatters */
|
||||||
|
#define TITLE_FMT "%12s%12s%8s %s\n"
|
||||||
|
#define GPT_FMT "%12"PRId64"%12"PRId64"%8s %s\n"
|
||||||
|
#define GPT_MORE "%12s%12s%8s ", "", "", ""
|
||||||
|
#define PARTITION_FMT "%12"PRId64"%12"PRId64"%8d %s\n"
|
||||||
|
#define PARTITION_MORE "%12s%12s%8s %s%s\n", "", "", ""
|
||||||
|
|
||||||
|
void PrintSignature(const char *indent, const char *sig, size_t n, int raw) {
|
||||||
|
size_t i;
|
||||||
|
printf("%sSig: ", indent);
|
||||||
|
if (!raw) {
|
||||||
|
printf("[");
|
||||||
|
for (i = 0; i < n; ++i)
|
||||||
|
printf("%c", sig[i]);
|
||||||
|
printf("]");
|
||||||
|
} else {
|
||||||
|
char *buf = malloc(BUFFER_SIZE(n));
|
||||||
|
RawDump((uint8_t *)sig, n, buf, 1);
|
||||||
|
printf("%s", buf);
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void HeaderDetails(GptHeader *header, GptEntry *entries,
|
||||||
|
const char *indent, int raw) {
|
||||||
|
PrintSignature(indent, header->signature, sizeof(header->signature), raw);
|
||||||
|
|
||||||
|
printf("%sRev: 0x%08x\n", indent, header->revision);
|
||||||
|
printf("%sSize: %d\n", indent, header->size);
|
||||||
|
printf("%sHeader CRC: 0x%08x %s\n", indent, header->header_crc32,
|
||||||
|
(HeaderCrc(header) != header->header_crc32) ? "(INVALID)" : "");
|
||||||
|
printf("%sMy LBA: %lld\n", indent, (long long)header->my_lba);
|
||||||
|
printf("%sAlternate LBA: %lld\n", indent, (long long)header->alternate_lba);
|
||||||
|
printf("%sFirst LBA: %lld\n", indent, (long long)header->first_usable_lba);
|
||||||
|
printf("%sLast LBA: %lld\n", indent, (long long)header->last_usable_lba);
|
||||||
|
|
||||||
|
{ /* For disk guid */
|
||||||
|
char buf[GUID_STRLEN];
|
||||||
|
GuidToStr(&header->disk_uuid, buf, GUID_STRLEN);
|
||||||
|
printf("%sDisk UUID: %s\n", indent, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%sEntries LBA: %lld\n", indent, (long long)header->entries_lba);
|
||||||
|
printf("%sNumber of entries: %d\n", indent, header->number_of_entries);
|
||||||
|
printf("%sSize of entry: %d\n", indent, header->size_of_entry);
|
||||||
|
printf("%sEntries CRC: 0x%08x %s\n", indent, header->entries_crc32,
|
||||||
|
header->entries_crc32 !=
|
||||||
|
Crc32((const uint8_t *)entries,header->size_of_entry *
|
||||||
|
header->number_of_entries)
|
||||||
|
? "INVALID" : ""
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EntryDetails(GptEntry *entry, uint32_t index, int raw) {
|
||||||
|
char contents[256]; // scratch buffer for formatting output
|
||||||
|
uint8_t label[GPT_PARTNAME_LEN];
|
||||||
|
char type[GUID_STRLEN], unique[GUID_STRLEN];
|
||||||
|
int clen;
|
||||||
|
|
||||||
|
UTF16ToUTF8(entry->name, sizeof(entry->name) / sizeof(entry->name[0]),
|
||||||
|
label, sizeof(label));
|
||||||
|
require(snprintf(contents, sizeof(contents),
|
||||||
|
"Label: \"%s\"", label) < sizeof(contents));
|
||||||
|
printf(PARTITION_FMT, (uint64_t)entry->starting_lba,
|
||||||
|
(uint64_t)(entry->ending_lba - entry->starting_lba + 1),
|
||||||
|
index+1, contents);
|
||||||
|
|
||||||
|
if (!raw && CGPT_OK == ResolveType(&entry->type, type)) {
|
||||||
|
printf(PARTITION_MORE, "Type: ", type);
|
||||||
|
} else {
|
||||||
|
GuidToStr(&entry->type, type, GUID_STRLEN);
|
||||||
|
printf(PARTITION_MORE, "Type: ", type);
|
||||||
|
}
|
||||||
|
GuidToStr(&entry->unique, unique, GUID_STRLEN);
|
||||||
|
printf(PARTITION_MORE, "UUID: ", unique);
|
||||||
|
|
||||||
|
clen = 0;
|
||||||
|
if (!raw) {
|
||||||
|
if (GuidEqual(&guid_chromeos_kernel, &entry->type)) {
|
||||||
|
int tries = (entry->attrs.fields.gpt_att &
|
||||||
|
CGPT_ATTRIBUTE_TRIES_MASK) >>
|
||||||
|
CGPT_ATTRIBUTE_TRIES_OFFSET;
|
||||||
|
int successful = (entry->attrs.fields.gpt_att &
|
||||||
|
CGPT_ATTRIBUTE_SUCCESSFUL_MASK) >>
|
||||||
|
CGPT_ATTRIBUTE_SUCCESSFUL_OFFSET;
|
||||||
|
int priority = (entry->attrs.fields.gpt_att &
|
||||||
|
CGPT_ATTRIBUTE_PRIORITY_MASK) >>
|
||||||
|
CGPT_ATTRIBUTE_PRIORITY_OFFSET;
|
||||||
|
clen = snprintf(contents, sizeof(contents),
|
||||||
|
"priority=%d tries=%d successful=%d ",
|
||||||
|
priority, tries, successful);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry->attrs.fields.required) {
|
||||||
|
clen += snprintf(contents + clen, sizeof(contents) - clen,
|
||||||
|
"required=%d ", entry->attrs.fields.required);
|
||||||
|
require(clen < sizeof(contents));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry->attrs.fields.efi_ignore) {
|
||||||
|
clen += snprintf(contents + clen, sizeof(contents) - clen,
|
||||||
|
"efi_ignore=%d ", entry->attrs.fields.efi_ignore);
|
||||||
|
require(clen < sizeof(contents));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry->attrs.fields.legacy_boot) {
|
||||||
|
clen += snprintf(contents + clen, sizeof(contents) - clen,
|
||||||
|
"legacy_boot=%d ", entry->attrs.fields.legacy_boot);
|
||||||
|
require(clen < sizeof(contents));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
clen = snprintf(contents, sizeof(contents),
|
||||||
|
"[%x]", entry->attrs.fields.gpt_att);
|
||||||
|
}
|
||||||
|
require(clen < sizeof(contents));
|
||||||
|
if (clen)
|
||||||
|
printf(PARTITION_MORE, "Attr: ", contents);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EntriesDetails(struct drive *drive, const int secondary, int raw) {
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < GetNumberOfEntries(drive); ++i) {
|
||||||
|
GptEntry *entry;
|
||||||
|
entry = GetEntry(&drive->gpt, secondary, i);
|
||||||
|
|
||||||
|
if (GuidIsZero(&entry->type))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
EntryDetails(entry, i, raw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int GptShow(struct drive *drive, CgptShowParams *params) {
|
||||||
|
int gpt_retval;
|
||||||
|
if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive->gpt))) {
|
||||||
|
Error("GptSanityCheck() returned %d: %s\n",
|
||||||
|
gpt_retval, GptError(gpt_retval));
|
||||||
|
return CGPT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params->partition) { // show single partition
|
||||||
|
|
||||||
|
if (params->partition > GetNumberOfEntries(drive)) {
|
||||||
|
Error("invalid partition number: %d\n", params->partition);
|
||||||
|
return CGPT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t index = params->partition - 1;
|
||||||
|
GptEntry *entry = GetEntry(&drive->gpt, ANY_VALID, index);
|
||||||
|
char buf[256]; // scratch buffer for string conversion
|
||||||
|
|
||||||
|
if (params->single_item) {
|
||||||
|
switch(params->single_item) {
|
||||||
|
case 'b':
|
||||||
|
printf("%" PRId64 "\n", entry->starting_lba);
|
||||||
|
break;
|
||||||
|
case 's': {
|
||||||
|
uint64_t size = 0;
|
||||||
|
// If these aren't actually defined, don't show anything
|
||||||
|
if (entry->ending_lba || entry->starting_lba)
|
||||||
|
size = entry->ending_lba - entry->starting_lba + 1;
|
||||||
|
printf("%" PRId64 "\n", size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 't':
|
||||||
|
GuidToStr(&entry->type, buf, sizeof(buf));
|
||||||
|
printf("%s\n", buf);
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
GuidToStr(&entry->unique, buf, sizeof(buf));
|
||||||
|
printf("%s\n", buf);
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
UTF16ToUTF8(entry->name, sizeof(entry->name) / sizeof(entry->name[0]),
|
||||||
|
(uint8_t *)buf, sizeof(buf));
|
||||||
|
printf("%s\n", buf);
|
||||||
|
break;
|
||||||
|
case 'S':
|
||||||
|
printf("%d\n", GetSuccessful(drive, ANY_VALID, index));
|
||||||
|
break;
|
||||||
|
case 'T':
|
||||||
|
printf("%d\n", GetTries(drive, ANY_VALID, index));
|
||||||
|
break;
|
||||||
|
case 'P':
|
||||||
|
printf("%d\n", GetPriority(drive, ANY_VALID, index));
|
||||||
|
break;
|
||||||
|
case 'R':
|
||||||
|
printf("%d\n", GetRequired(drive, ANY_VALID, index));
|
||||||
|
break;
|
||||||
|
case 'B':
|
||||||
|
printf("%d\n", GetLegacyBoot(drive, ANY_VALID, index));
|
||||||
|
break;
|
||||||
|
case 'A':
|
||||||
|
printf("0x%x\n", entry->attrs.fields.gpt_att);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printf(TITLE_FMT, "start", "size", "part", "contents");
|
||||||
|
EntryDetails(entry, index, params->numeric);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (params->quick) { // show all partitions, quickly
|
||||||
|
uint32_t i;
|
||||||
|
GptEntry *entry;
|
||||||
|
char type[GUID_STRLEN];
|
||||||
|
|
||||||
|
for (i = 0; i < GetNumberOfEntries(drive); ++i) {
|
||||||
|
entry = GetEntry(&drive->gpt, ANY_VALID, i);
|
||||||
|
|
||||||
|
if (GuidIsZero(&entry->type))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!params->numeric && CGPT_OK == ResolveType(&entry->type, type)) {
|
||||||
|
} else {
|
||||||
|
GuidToStr(&entry->type, type, GUID_STRLEN);
|
||||||
|
}
|
||||||
|
printf(PARTITION_FMT, (uint64_t)entry->starting_lba,
|
||||||
|
(uint64_t)(entry->ending_lba - entry->starting_lba + 1),
|
||||||
|
i+1, type);
|
||||||
|
}
|
||||||
|
} else { // show all partitions
|
||||||
|
GptEntry *entries;
|
||||||
|
|
||||||
|
if (CGPT_OK != ReadPMBR(drive)) {
|
||||||
|
Error("Unable to read PMBR\n");
|
||||||
|
return CGPT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(TITLE_FMT, "start", "size", "part", "contents");
|
||||||
|
char buf[256]; // buffer for formatted PMBR content
|
||||||
|
PMBRToStr(&drive->pmbr, buf, sizeof(buf)); // will exit if buf is too small
|
||||||
|
printf(GPT_FMT, (uint64_t)0, (uint64_t)GPT_PMBR_SECTORS, "", buf);
|
||||||
|
|
||||||
|
if (drive->gpt.ignored & MASK_PRIMARY) {
|
||||||
|
printf(GPT_FMT, (uint64_t)GPT_PMBR_SECTORS,
|
||||||
|
(uint64_t)GPT_HEADER_SECTORS, "IGNORED", "Pri GPT header");
|
||||||
|
} else {
|
||||||
|
if (drive->gpt.valid_headers & MASK_PRIMARY) {
|
||||||
|
printf(GPT_FMT, (uint64_t)GPT_PMBR_SECTORS,
|
||||||
|
(uint64_t)GPT_HEADER_SECTORS, "", "Pri GPT header");
|
||||||
|
} else {
|
||||||
|
printf(GPT_FMT, (uint64_t)GPT_PMBR_SECTORS,
|
||||||
|
(uint64_t)GPT_HEADER_SECTORS, "INVALID", "Pri GPT header");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params->debug ||
|
||||||
|
((drive->gpt.valid_headers & MASK_PRIMARY) && params->verbose)) {
|
||||||
|
GptHeader *header;
|
||||||
|
char indent[64];
|
||||||
|
|
||||||
|
require(snprintf(indent, sizeof(indent), GPT_MORE) < sizeof(indent));
|
||||||
|
header = (GptHeader*)drive->gpt.primary_header;
|
||||||
|
entries = (GptEntry*)drive->gpt.primary_entries;
|
||||||
|
HeaderDetails(header, entries, indent, params->numeric);
|
||||||
|
}
|
||||||
|
|
||||||
|
GptHeader* primary_header = (GptHeader*)drive->gpt.primary_header;
|
||||||
|
printf(GPT_FMT, (uint64_t)primary_header->entries_lba,
|
||||||
|
(uint64_t)CalculateEntriesSectors(primary_header,
|
||||||
|
drive->gpt.sector_bytes),
|
||||||
|
drive->gpt.valid_entries & MASK_PRIMARY ? "" : "INVALID",
|
||||||
|
"Pri GPT table");
|
||||||
|
|
||||||
|
if (params->debug ||
|
||||||
|
(drive->gpt.valid_entries & MASK_PRIMARY))
|
||||||
|
EntriesDetails(drive, PRIMARY, params->numeric);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************** Secondary *************************/
|
||||||
|
if (drive->gpt.ignored & MASK_SECONDARY) {
|
||||||
|
printf(GPT_FMT,
|
||||||
|
(uint64_t)(drive->gpt.gpt_drive_sectors - GPT_HEADER_SECTORS),
|
||||||
|
(uint64_t)GPT_HEADER_SECTORS, "IGNORED", "Sec GPT header");
|
||||||
|
} else {
|
||||||
|
GptHeader* secondary_header = (GptHeader*)drive->gpt.secondary_header;
|
||||||
|
printf(GPT_FMT, (uint64_t)secondary_header->entries_lba,
|
||||||
|
(uint64_t)CalculateEntriesSectors(secondary_header,
|
||||||
|
drive->gpt.sector_bytes),
|
||||||
|
drive->gpt.valid_entries & MASK_SECONDARY ? "" : "INVALID",
|
||||||
|
"Sec GPT table");
|
||||||
|
/* We show secondary table details if any of following is true.
|
||||||
|
* 1. in debug mode.
|
||||||
|
* 2. primary table is being ignored
|
||||||
|
* 3. only secondary is valid.
|
||||||
|
* 4. secondary is not identical to promary.
|
||||||
|
*/
|
||||||
|
if (params->debug || (drive->gpt.ignored & MASK_PRIMARY) ||
|
||||||
|
((drive->gpt.valid_entries & MASK_SECONDARY) &&
|
||||||
|
(!(drive->gpt.valid_entries & MASK_PRIMARY) ||
|
||||||
|
memcmp(drive->gpt.primary_entries, drive->gpt.secondary_entries,
|
||||||
|
secondary_header->number_of_entries *
|
||||||
|
secondary_header->size_of_entry)))) {
|
||||||
|
EntriesDetails(drive, SECONDARY, params->numeric);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (drive->gpt.valid_headers & MASK_SECONDARY) {
|
||||||
|
printf(GPT_FMT,
|
||||||
|
(uint64_t)(drive->gpt.gpt_drive_sectors - GPT_HEADER_SECTORS),
|
||||||
|
(uint64_t)GPT_HEADER_SECTORS, "", "Sec GPT header");
|
||||||
|
} else {
|
||||||
|
printf(GPT_FMT, (uint64_t)GPT_PMBR_SECTORS,
|
||||||
|
(uint64_t)GPT_HEADER_SECTORS, "INVALID", "Sec GPT header");
|
||||||
|
}
|
||||||
|
/* We show secondary header if any of following is true:
|
||||||
|
* 1. in debug mode.
|
||||||
|
* 2. only secondary is valid.
|
||||||
|
* 3. secondary is not synonymous to primary and not ignored.
|
||||||
|
*/
|
||||||
|
if (params->debug ||
|
||||||
|
((drive->gpt.valid_headers & MASK_SECONDARY) &&
|
||||||
|
(!(drive->gpt.valid_headers & MASK_PRIMARY) ||
|
||||||
|
!IsSynonymous((GptHeader*)drive->gpt.primary_header,
|
||||||
|
(GptHeader*)drive->gpt.secondary_header)) &&
|
||||||
|
params->verbose)) {
|
||||||
|
GptHeader *header;
|
||||||
|
char indent[64];
|
||||||
|
|
||||||
|
require(snprintf(indent, sizeof(indent), GPT_MORE) < sizeof(indent));
|
||||||
|
header = (GptHeader*)drive->gpt.secondary_header;
|
||||||
|
entries = (GptEntry*)drive->gpt.secondary_entries;
|
||||||
|
HeaderDetails(header, entries, indent, params->numeric);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CheckValid(drive);
|
||||||
|
|
||||||
|
return CGPT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CgptShow(CgptShowParams *params) {
|
||||||
|
struct drive drive;
|
||||||
|
|
||||||
|
if (params == NULL)
|
||||||
|
return CGPT_FAILED;
|
||||||
|
|
||||||
|
if (CGPT_OK != DriveOpen(params->drive_name, &drive, O_RDONLY,
|
||||||
|
params->drive_size))
|
||||||
|
return CGPT_FAILED;
|
||||||
|
|
||||||
|
if (GptShow(&drive, params))
|
||||||
|
return CGPT_FAILED;
|
||||||
|
|
||||||
|
DriveClose(&drive, 0);
|
||||||
|
return CGPT_OK;
|
||||||
|
}
|
||||||
196
firmware/coreboot/3rdparty/vboot/cgpt/cgpt_wrapper.c
vendored
Normal file
196
firmware/coreboot/3rdparty/vboot/cgpt/cgpt_wrapper.c
vendored
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
/* Copyright 2015 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.
|
||||||
|
*
|
||||||
|
* This utility wraps around "cgpt" execution to work with NAND. If the target
|
||||||
|
* device is an MTD device, this utility will read the GPT structures from
|
||||||
|
* FMAP, invokes "cgpt" on that, and writes the result back to NOR flash. */
|
||||||
|
|
||||||
|
#include <err.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <linux/major.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/sysmacros.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "2sysincludes.h"
|
||||||
|
|
||||||
|
#include "2common.h"
|
||||||
|
#include "2sha.h"
|
||||||
|
#include "cgpt.h"
|
||||||
|
#include "cgpt_nor.h"
|
||||||
|
#include "file_keys.h"
|
||||||
|
|
||||||
|
// Check if cmdline |argv| has "-D". "-D" signifies that GPT structs are stored
|
||||||
|
// off device, and hence we should not wrap around cgpt.
|
||||||
|
static bool has_dash_D(int argc, const char *const argv[]) {
|
||||||
|
int i;
|
||||||
|
// We go from 2, because the second arg is a cgpt command such as "create".
|
||||||
|
for (i = 2; i < argc; ++i) {
|
||||||
|
if (strcmp("-D", argv[i]) == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if |device_path| is an MTD device based on its major number being 90.
|
||||||
|
static bool is_mtd(const char *device_path) {
|
||||||
|
struct stat stat;
|
||||||
|
if (lstat(device_path, &stat) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (major(stat.st_rdev) != MTD_CHAR_MAJOR) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the element in |argv| that is an MTD device.
|
||||||
|
static const char *find_mtd_device(int argc, const char *const argv[]) {
|
||||||
|
int i;
|
||||||
|
for (i = 2; i < argc; ++i) {
|
||||||
|
if (is_mtd(argv[i])) {
|
||||||
|
return argv[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int wrap_cgpt(int argc,
|
||||||
|
const char *const argv[],
|
||||||
|
const char *mtd_device) {
|
||||||
|
uint8_t original_hash[VB2_SHA1_DIGEST_SIZE];
|
||||||
|
uint8_t modified_hash[VB2_SHA1_DIGEST_SIZE];
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
// Create a temp dir to work in.
|
||||||
|
ret++;
|
||||||
|
char temp_dir[] = "/tmp/cgpt_wrapper.XXXXXX";
|
||||||
|
if (ReadNorFlash(temp_dir) != 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
char rw_gpt_path[PATH_MAX];
|
||||||
|
if (snprintf(rw_gpt_path, sizeof(rw_gpt_path), "%s/rw_gpt", temp_dir) < 0) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
if (VB2_SUCCESS != DigestFile(rw_gpt_path, VB2_HASH_SHA1,
|
||||||
|
original_hash, sizeof(original_hash))) {
|
||||||
|
Error("Cannot compute original GPT digest.\n");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Obtain the MTD size.
|
||||||
|
ret++;
|
||||||
|
uint64_t drive_size = 0;
|
||||||
|
if (GetMtdSize(mtd_device, &drive_size) != 0) {
|
||||||
|
Error("Cannot get the size of %s.\n", mtd_device);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Launch cgpt on "rw_gpt" with -D size.
|
||||||
|
ret++;
|
||||||
|
const char** my_argv = calloc(argc + 2 + 1, sizeof(char *));
|
||||||
|
if (my_argv == NULL) {
|
||||||
|
errno = ENOMEM;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
memcpy(my_argv, argv, sizeof(char *) * argc);
|
||||||
|
char *real_cgpt;
|
||||||
|
if (asprintf(&real_cgpt, "%s.bin", argv[0]) == -1) {
|
||||||
|
free(my_argv);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
my_argv[0] = real_cgpt;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for (i = 2; i < argc; ++i) {
|
||||||
|
if (strcmp(my_argv[i], mtd_device) == 0) {
|
||||||
|
my_argv[i] = rw_gpt_path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
my_argv[argc] = "-D";
|
||||||
|
char size[32];
|
||||||
|
snprintf(size, sizeof(size), "%" PRIu64, drive_size);
|
||||||
|
my_argv[argc + 1] = size;
|
||||||
|
i = ForkExecV(NULL, my_argv);
|
||||||
|
free(real_cgpt);
|
||||||
|
free(my_argv);
|
||||||
|
if (i != 0) {
|
||||||
|
Error("Cannot exec cgpt to modify rw_gpt.\n");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write back "rw_gpt" to NOR flash in two chunks.
|
||||||
|
ret++;
|
||||||
|
if (VB2_SUCCESS == DigestFile(rw_gpt_path, VB2_HASH_SHA1,
|
||||||
|
modified_hash, sizeof(modified_hash))) {
|
||||||
|
if (memcmp(original_hash, modified_hash, VB2_SHA1_DIGEST_SIZE) != 0) {
|
||||||
|
ret = WriteNorFlash(temp_dir);
|
||||||
|
} else {
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
RemoveDir(temp_dir);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, const char *argv[]) {
|
||||||
|
char resolved_cgpt[PATH_MAX];
|
||||||
|
pid_t pid = getpid();
|
||||||
|
char exe_link[40];
|
||||||
|
int retval = 0;
|
||||||
|
|
||||||
|
if (argc < 1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *orig_argv0 = argv[0];
|
||||||
|
|
||||||
|
snprintf(exe_link, sizeof(exe_link), "/proc/%d/exe", pid);
|
||||||
|
memset(resolved_cgpt, 0, sizeof(resolved_cgpt));
|
||||||
|
if (readlink(exe_link, resolved_cgpt, sizeof(resolved_cgpt) - 1) == -1) {
|
||||||
|
perror("readlink");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
argv[0] = resolved_cgpt;
|
||||||
|
|
||||||
|
if (argc > 2 && !has_dash_D(argc, argv)) {
|
||||||
|
const char *mtd_device = find_mtd_device(argc, argv);
|
||||||
|
if (mtd_device) {
|
||||||
|
retval = wrap_cgpt(argc, argv, mtd_device);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Forward to cgpt as-is. Real cgpt has been renamed cgpt.bin.
|
||||||
|
char *real_cgpt;
|
||||||
|
if (asprintf(&real_cgpt, "%s.bin", argv[0]) == -1) {
|
||||||
|
retval = -1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
argv[0] = real_cgpt;
|
||||||
|
if (execv(argv[0], (char * const *)argv) == -1) {
|
||||||
|
err(-2, "execv(%s) failed", real_cgpt);
|
||||||
|
}
|
||||||
|
free(real_cgpt);
|
||||||
|
retval = -2;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
argv[0] = orig_argv0;
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
157
firmware/coreboot/3rdparty/vboot/cgpt/cmd_add.c
vendored
Normal file
157
firmware/coreboot/3rdparty/vboot/cgpt/cmd_add.c
vendored
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "cgpt.h"
|
||||||
|
#include "vboot_host.h"
|
||||||
|
|
||||||
|
extern const char* progname;
|
||||||
|
|
||||||
|
static void Usage(void)
|
||||||
|
{
|
||||||
|
printf("\nUsage: %s add [OPTIONS] DRIVE\n\n"
|
||||||
|
"Add, edit, or remove a partition entry.\n\n"
|
||||||
|
"Options:\n"
|
||||||
|
" -D NUM Size (in bytes) of the disk where partitions reside\n"
|
||||||
|
" default 0, meaning partitions and GPT structs are\n"
|
||||||
|
" both on DRIVE\n"
|
||||||
|
" -i NUM Specify partition (default is next available)\n"
|
||||||
|
" -b NUM Beginning sector\n"
|
||||||
|
" -s NUM Size in sectors\n"
|
||||||
|
" -t GUID Partition Type GUID\n"
|
||||||
|
" -u GUID Partition Unique ID\n"
|
||||||
|
" -l LABEL Label\n"
|
||||||
|
" -S NUM set Successful flag (0|1)\n"
|
||||||
|
" -T NUM set Tries flag (0-15)\n"
|
||||||
|
" -P NUM set Priority flag (0-15)\n"
|
||||||
|
" -R NUM set Required flag (0|1)\n"
|
||||||
|
" -B NUM set Legacy Boot flag (0|1)\n"
|
||||||
|
" -A NUM set raw 16-bit attribute value (bits 48-63)\n"
|
||||||
|
"\n"
|
||||||
|
"Use the -i option to modify an existing partition.\n"
|
||||||
|
"The -b, -s, and -t options must be given for new partitions.\n"
|
||||||
|
"\n", progname);
|
||||||
|
PrintTypes();
|
||||||
|
}
|
||||||
|
|
||||||
|
int cmd_add(int argc, char *argv[]) {
|
||||||
|
|
||||||
|
CgptAddParams params;
|
||||||
|
memset(¶ms, 0, sizeof(params));
|
||||||
|
|
||||||
|
int c;
|
||||||
|
int errorcnt = 0;
|
||||||
|
char *e = 0;
|
||||||
|
|
||||||
|
opterr = 0; // quiet, you
|
||||||
|
while ((c=getopt(argc, argv, ":hi:b:s:t:u:l:S:T:P:R:B:A:D:")) != -1)
|
||||||
|
{
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case 'D':
|
||||||
|
params.drive_size = strtoull(optarg, &e, 0);
|
||||||
|
errorcnt += check_int_parse(c, e);
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
params.partition = (uint32_t)strtoul(optarg, &e, 0);
|
||||||
|
errorcnt += check_int_parse(c, e);
|
||||||
|
break;
|
||||||
|
case 'b':
|
||||||
|
params.set_begin = 1;
|
||||||
|
params.begin = strtoull(optarg, &e, 0);
|
||||||
|
errorcnt += check_int_parse(c, e);
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
params.set_size = 1;
|
||||||
|
params.size = strtoull(optarg, &e, 0);
|
||||||
|
errorcnt += check_int_parse(c, e);
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
params.set_type = 1;
|
||||||
|
if (CGPT_OK != SupportedType(optarg, ¶ms.type_guid) &&
|
||||||
|
CGPT_OK != StrToGuid(optarg, ¶ms.type_guid)) {
|
||||||
|
Error("invalid argument to -%c: %s\n", c, optarg);
|
||||||
|
errorcnt++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
params.set_unique = 1;
|
||||||
|
if (CGPT_OK != StrToGuid(optarg, ¶ms.unique_guid)) {
|
||||||
|
Error("invalid argument to -%c: %s\n", c, optarg);
|
||||||
|
errorcnt++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
params.label = optarg;
|
||||||
|
break;
|
||||||
|
case 'S':
|
||||||
|
params.set_successful = 1;
|
||||||
|
params.successful = (uint32_t)strtoul(optarg, &e, 0);
|
||||||
|
errorcnt += check_int_parse(c, e);
|
||||||
|
errorcnt += check_int_limit(c, params.successful, 0, 1);
|
||||||
|
break;
|
||||||
|
case 'T':
|
||||||
|
params.set_tries = 1;
|
||||||
|
params.tries = (uint32_t)strtoul(optarg, &e, 0);
|
||||||
|
errorcnt += check_int_parse(c, e);
|
||||||
|
errorcnt += check_int_limit(c, params.tries, 0, 15);
|
||||||
|
break;
|
||||||
|
case 'P':
|
||||||
|
params.set_priority = 1;
|
||||||
|
params.priority = (uint32_t)strtoul(optarg, &e, 0);
|
||||||
|
errorcnt += check_int_parse(c, e);
|
||||||
|
errorcnt += check_int_limit(c, params.priority, 0, 15);
|
||||||
|
break;
|
||||||
|
case 'R':
|
||||||
|
params.set_required = 1;
|
||||||
|
params.required = (uint32_t)strtoul(optarg, &e, 0);
|
||||||
|
errorcnt += check_int_parse(c, e);
|
||||||
|
errorcnt += check_int_limit(c, params.required, 0, 1);
|
||||||
|
break;
|
||||||
|
case 'B':
|
||||||
|
params.set_legacy_boot = 1;
|
||||||
|
params.legacy_boot = (uint32_t)strtoul(optarg, &e, 0);
|
||||||
|
errorcnt += check_int_parse(c, e);
|
||||||
|
errorcnt += check_int_limit(c, params.legacy_boot, 0, 1);
|
||||||
|
break;
|
||||||
|
case 'A':
|
||||||
|
params.set_raw = 1;
|
||||||
|
params.raw_value = strtoull(optarg, &e, 0);
|
||||||
|
errorcnt += check_int_parse(c, e);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'h':
|
||||||
|
Usage();
|
||||||
|
return CGPT_OK;
|
||||||
|
case '?':
|
||||||
|
Error("unrecognized option: -%c\n", optopt);
|
||||||
|
errorcnt++;
|
||||||
|
break;
|
||||||
|
case ':':
|
||||||
|
Error("missing argument to -%c\n", optopt);
|
||||||
|
errorcnt++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
errorcnt++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (errorcnt)
|
||||||
|
{
|
||||||
|
Usage();
|
||||||
|
return CGPT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (optind >= argc)
|
||||||
|
{
|
||||||
|
Error("missing drive argument\n");
|
||||||
|
return CGPT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
params.drive_name = argv[optind];
|
||||||
|
|
||||||
|
return CgptAdd(¶ms);
|
||||||
|
}
|
||||||
89
firmware/coreboot/3rdparty/vboot/cgpt/cmd_boot.c
vendored
Normal file
89
firmware/coreboot/3rdparty/vboot/cgpt/cmd_boot.c
vendored
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "cgpt.h"
|
||||||
|
#include "vboot_host.h"
|
||||||
|
|
||||||
|
extern const char* progname;
|
||||||
|
|
||||||
|
static void Usage(void)
|
||||||
|
{
|
||||||
|
printf("\nUsage: %s boot [OPTIONS] DRIVE\n\n"
|
||||||
|
"Edit the PMBR sector for legacy BIOSes\n\n"
|
||||||
|
"Options:\n"
|
||||||
|
" -D NUM Size (in bytes) of the disk where partitions reside\n"
|
||||||
|
" default 0, meaning partitions and GPT structs are\n"
|
||||||
|
" both on DRIVE\n"
|
||||||
|
" -i NUM Set bootable partition\n"
|
||||||
|
" -b FILE Install bootloader code in the PMBR\n"
|
||||||
|
" -p Create legacy PMBR partition table\n"
|
||||||
|
"\n"
|
||||||
|
"With no options, it will just print the PMBR boot guid\n"
|
||||||
|
"\n", progname);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int cmd_boot(int argc, char *argv[]) {
|
||||||
|
CgptBootParams params;
|
||||||
|
memset(¶ms, 0, sizeof(params));
|
||||||
|
|
||||||
|
|
||||||
|
int c;
|
||||||
|
int errorcnt = 0;
|
||||||
|
char *e = 0;
|
||||||
|
|
||||||
|
opterr = 0; // quiet, you
|
||||||
|
while ((c=getopt(argc, argv, ":hi:b:pD:")) != -1)
|
||||||
|
{
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case 'D':
|
||||||
|
params.drive_size = strtoull(optarg, &e, 0);
|
||||||
|
errorcnt += check_int_parse(c, e);
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
params.partition = (uint32_t)strtoul(optarg, &e, 0);
|
||||||
|
errorcnt += check_int_parse(c, e);
|
||||||
|
break;
|
||||||
|
case 'b':
|
||||||
|
params.bootfile = optarg;
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
params.create_pmbr = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'h':
|
||||||
|
Usage();
|
||||||
|
return CGPT_OK;
|
||||||
|
case '?':
|
||||||
|
Error("unrecognized option: -%c\n", optopt);
|
||||||
|
errorcnt++;
|
||||||
|
break;
|
||||||
|
case ':':
|
||||||
|
Error("missing argument to -%c\n", optopt);
|
||||||
|
errorcnt++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
errorcnt++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (errorcnt)
|
||||||
|
{
|
||||||
|
Usage();
|
||||||
|
return CGPT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (optind >= argc) {
|
||||||
|
Error("missing drive argument\n");
|
||||||
|
return CGPT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
params.drive_name = argv[optind];
|
||||||
|
|
||||||
|
return CgptBoot(¶ms);
|
||||||
|
}
|
||||||
81
firmware/coreboot/3rdparty/vboot/cgpt/cmd_create.c
vendored
Normal file
81
firmware/coreboot/3rdparty/vboot/cgpt/cmd_create.c
vendored
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "cgpt.h"
|
||||||
|
#include "vboot_host.h"
|
||||||
|
|
||||||
|
extern const char* progname;
|
||||||
|
|
||||||
|
static void Usage(void)
|
||||||
|
{
|
||||||
|
printf("\nUsage: %s create [OPTIONS] DRIVE\n\n"
|
||||||
|
"Create or reset an empty GPT.\n\n"
|
||||||
|
"Options:\n"
|
||||||
|
" -D NUM Size (in bytes) of the disk where partitions reside\n"
|
||||||
|
" default 0, meaning partitions and GPT structs are\n"
|
||||||
|
" both on DRIVE\n"
|
||||||
|
" -z Zero the sectors of the GPT table and entries\n"
|
||||||
|
" -p NUM Size (in blocks) of the disk to pad between the\n"
|
||||||
|
" primary GPT header and its entries, default 0\n"
|
||||||
|
"\n", progname);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cmd_create(int argc, char *argv[]) {
|
||||||
|
CgptCreateParams params;
|
||||||
|
memset(¶ms, 0, sizeof(params));
|
||||||
|
|
||||||
|
int c;
|
||||||
|
int errorcnt = 0;
|
||||||
|
char *e = 0;
|
||||||
|
|
||||||
|
opterr = 0; // quiet, you
|
||||||
|
while ((c=getopt(argc, argv, ":hzp:D:")) != -1)
|
||||||
|
{
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case 'D':
|
||||||
|
params.drive_size = strtoull(optarg, &e, 0);
|
||||||
|
errorcnt += check_int_parse(c, e);
|
||||||
|
break;
|
||||||
|
case 'z':
|
||||||
|
params.zap = 1;
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
params.padding = strtoull(optarg, &e, 0);
|
||||||
|
errorcnt += check_int_parse(c, e);
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
Usage();
|
||||||
|
return CGPT_OK;
|
||||||
|
case '?':
|
||||||
|
Error("unrecognized option: -%c\n", optopt);
|
||||||
|
errorcnt++;
|
||||||
|
break;
|
||||||
|
case ':':
|
||||||
|
Error("missing argument to -%c\n", optopt);
|
||||||
|
errorcnt++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
errorcnt++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (errorcnt)
|
||||||
|
{
|
||||||
|
Usage();
|
||||||
|
return CGPT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (optind >= argc) {
|
||||||
|
Usage();
|
||||||
|
return CGPT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
params.drive_name = argv[optind];
|
||||||
|
|
||||||
|
return CgptCreate(¶ms);
|
||||||
|
}
|
||||||
182
firmware/coreboot/3rdparty/vboot/cgpt/cmd_find.c
vendored
Normal file
182
firmware/coreboot/3rdparty/vboot/cgpt/cmd_find.c
vendored
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "cgpt.h"
|
||||||
|
#include "vboot_host.h"
|
||||||
|
|
||||||
|
extern const char* progname;
|
||||||
|
|
||||||
|
static void Usage(void)
|
||||||
|
{
|
||||||
|
printf("\nUsage: %s find [OPTIONS] [DRIVE]\n\n"
|
||||||
|
"Find a partition by its UUID or label. With no specified DRIVE\n"
|
||||||
|
"it scans all physical drives.\n\n"
|
||||||
|
"Options:\n"
|
||||||
|
" -D NUM Size (in bytes) of the disk where partitions reside\n"
|
||||||
|
" default 0, meaning partitions and GPT structs are\n"
|
||||||
|
" both on DRIVE\n"
|
||||||
|
" -t GUID Search for Partition Type GUID\n"
|
||||||
|
" -u GUID Search for Partition Unique ID\n"
|
||||||
|
" -l LABEL Search for Label\n"
|
||||||
|
" -v Be verbose in displaying matches (repeatable)\n"
|
||||||
|
" -n Numeric output only\n"
|
||||||
|
" -1 Fail if more than one match is found\n"
|
||||||
|
" -M FILE"
|
||||||
|
" Matching partition data must also contain FILE content\n"
|
||||||
|
" -O NUM"
|
||||||
|
" Byte offset into partition to match content (default 0)\n"
|
||||||
|
"\n", progname);
|
||||||
|
PrintTypes();
|
||||||
|
}
|
||||||
|
|
||||||
|
// read a file into a buffer, return buffer and update size
|
||||||
|
static uint8_t *ReadFile(const char *filename, uint64_t *size) {
|
||||||
|
FILE *f;
|
||||||
|
uint8_t *buf;
|
||||||
|
long pos;
|
||||||
|
|
||||||
|
f = fopen(filename, "rb");
|
||||||
|
if (!f) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(f, 0, SEEK_END);
|
||||||
|
pos = ftell(f);
|
||||||
|
if (pos < 0) {
|
||||||
|
fclose(f);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
*size = pos;
|
||||||
|
rewind(f);
|
||||||
|
|
||||||
|
buf = malloc(*size);
|
||||||
|
if (!buf) {
|
||||||
|
fclose(f);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(1 != fread(buf, *size, 1, f)) {
|
||||||
|
fclose(f);
|
||||||
|
free(buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cmd_find(int argc, char *argv[]) {
|
||||||
|
|
||||||
|
CgptFindParams params;
|
||||||
|
memset(¶ms, 0, sizeof(params));
|
||||||
|
|
||||||
|
int i;
|
||||||
|
int errorcnt = 0;
|
||||||
|
char *e = 0;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
opterr = 0; // quiet, you
|
||||||
|
while ((c=getopt(argc, argv, ":hv1nt:u:l:M:O:D:")) != -1)
|
||||||
|
{
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case 'D':
|
||||||
|
params.drive_size = strtoull(optarg, &e, 0);
|
||||||
|
errorcnt += check_int_parse(c, e);
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
params.verbose++;
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
params.numeric = 1;
|
||||||
|
break;
|
||||||
|
case '1':
|
||||||
|
params.oneonly = 1;
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
params.set_label = 1;
|
||||||
|
params.label = optarg;
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
params.set_type = 1;
|
||||||
|
if (CGPT_OK != SupportedType(optarg, ¶ms.type_guid) &&
|
||||||
|
CGPT_OK != StrToGuid(optarg, ¶ms.type_guid)) {
|
||||||
|
Error("invalid argument to -%c: %s\n", c, optarg);
|
||||||
|
errorcnt++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
params.set_unique = 1;
|
||||||
|
if (CGPT_OK != StrToGuid(optarg, ¶ms.unique_guid)) {
|
||||||
|
Error("invalid argument to -%c: %s\n", c, optarg);
|
||||||
|
errorcnt++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'M':
|
||||||
|
params.matchbuf = ReadFile(optarg, ¶ms.matchlen);
|
||||||
|
if (!params.matchbuf || !params.matchlen) {
|
||||||
|
Error("Unable to read from %s\n", optarg);
|
||||||
|
errorcnt++;
|
||||||
|
}
|
||||||
|
// Go ahead and allocate space for the comparison too
|
||||||
|
params.comparebuf = (uint8_t *)malloc(params.matchlen);
|
||||||
|
if (!params.comparebuf) {
|
||||||
|
Error("Unable to allocate %" PRIu64 "bytes for comparison buffer\n",
|
||||||
|
params.matchlen);
|
||||||
|
errorcnt++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'O':
|
||||||
|
params.matchoffset = strtoull(optarg, &e, 0);
|
||||||
|
errorcnt += check_int_parse(c, e);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'h':
|
||||||
|
Usage();
|
||||||
|
return CGPT_OK;
|
||||||
|
case '?':
|
||||||
|
Error("unrecognized option: -%c\n", optopt);
|
||||||
|
errorcnt++;
|
||||||
|
break;
|
||||||
|
case ':':
|
||||||
|
Error("missing argument to -%c\n", optopt);
|
||||||
|
errorcnt++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
errorcnt++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!params.set_unique && !params.set_type && !params.set_label) {
|
||||||
|
Error("You must specify at least one of -t, -u, or -l\n");
|
||||||
|
errorcnt++;
|
||||||
|
}
|
||||||
|
if (errorcnt)
|
||||||
|
{
|
||||||
|
Usage();
|
||||||
|
return CGPT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (optind < argc) {
|
||||||
|
for (i=optind; i<argc; i++) {
|
||||||
|
params.drive_name = argv[i];
|
||||||
|
CgptFind(¶ms);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
CgptFind(¶ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.oneonly && params.hits != 1) {
|
||||||
|
return CGPT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.match_partnum) {
|
||||||
|
return CGPT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CGPT_FAILED;
|
||||||
|
}
|
||||||
87
firmware/coreboot/3rdparty/vboot/cgpt/cmd_legacy.c
vendored
Normal file
87
firmware/coreboot/3rdparty/vboot/cgpt/cmd_legacy.c
vendored
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "cgpt.h"
|
||||||
|
#include "vboot_host.h"
|
||||||
|
|
||||||
|
extern const char* progname;
|
||||||
|
|
||||||
|
static void Usage(void)
|
||||||
|
{
|
||||||
|
printf("\nUsage: %s legacy [OPTIONS] DRIVE\n\n"
|
||||||
|
"Switch GPT header signature to \"CHROMEOS\".\n\n"
|
||||||
|
"Options:\n"
|
||||||
|
" -D NUM Size (in bytes) of the disk where partitions reside\n"
|
||||||
|
" default 0, meaning partitions and GPT structs are\n"
|
||||||
|
" both on DRIVE\n"
|
||||||
|
" -e Switch GPT header signature back to \"EFI PART\"\n"
|
||||||
|
" -p Switch primary GPT header signature to \"IGNOREME\"\n"
|
||||||
|
"\n", progname);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cmd_legacy(int argc, char *argv[]) {
|
||||||
|
CgptLegacyParams params;
|
||||||
|
memset(¶ms, 0, sizeof(params));
|
||||||
|
|
||||||
|
int c;
|
||||||
|
char* e = 0;
|
||||||
|
int errorcnt = 0;
|
||||||
|
|
||||||
|
opterr = 0; // quiet, you
|
||||||
|
while ((c=getopt(argc, argv, ":hepD:")) != -1)
|
||||||
|
{
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case 'D':
|
||||||
|
params.drive_size = strtoull(optarg, &e, 0);
|
||||||
|
errorcnt += check_int_parse(c, e);
|
||||||
|
break;
|
||||||
|
case 'e':
|
||||||
|
if (params.mode) {
|
||||||
|
Error("Incompatible flags, pick either -e or -p\n");
|
||||||
|
errorcnt++;
|
||||||
|
}
|
||||||
|
params.mode = CGPT_LEGACY_MODE_EFIPART;
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
if (params.mode) {
|
||||||
|
Error("Incompatible flags, pick either -e or -p\n");
|
||||||
|
errorcnt++;
|
||||||
|
}
|
||||||
|
params.mode = CGPT_LEGACY_MODE_IGNORE_PRIMARY;
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
Usage();
|
||||||
|
return CGPT_OK;
|
||||||
|
case '?':
|
||||||
|
Error("unrecognized option: -%c\n", optopt);
|
||||||
|
errorcnt++;
|
||||||
|
break;
|
||||||
|
case ':':
|
||||||
|
Error("missing argument to -%c\n", optopt);
|
||||||
|
errorcnt++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
errorcnt++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (errorcnt)
|
||||||
|
{
|
||||||
|
Usage();
|
||||||
|
return CGPT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (optind >= argc) {
|
||||||
|
Usage();
|
||||||
|
return CGPT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
params.drive_name = argv[optind];
|
||||||
|
|
||||||
|
return CgptLegacy(¶ms);
|
||||||
|
}
|
||||||
106
firmware/coreboot/3rdparty/vboot/cgpt/cmd_prioritize.c
vendored
Normal file
106
firmware/coreboot/3rdparty/vboot/cgpt/cmd_prioritize.c
vendored
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <uuid/uuid.h>
|
||||||
|
|
||||||
|
#include "cgpt.h"
|
||||||
|
#include "vboot_host.h"
|
||||||
|
|
||||||
|
extern const char* progname;
|
||||||
|
|
||||||
|
static void Usage(void)
|
||||||
|
{
|
||||||
|
printf("\nUsage: %s prioritize [OPTIONS] DRIVE\n\n"
|
||||||
|
"Reorder the priority of all active ChromeOS Kernel partitions.\n\n"
|
||||||
|
"Options:\n"
|
||||||
|
" -D NUM Size (in bytes) of the disk where partitions reside\n"
|
||||||
|
" default 0, meaning partitions and GPT structs are\n"
|
||||||
|
" both on DRIVE\n"
|
||||||
|
" -P NUM Highest priority to use in the new ordering. The\n"
|
||||||
|
" other partitions will be ranked in decreasing\n"
|
||||||
|
" priority while preserving their original order.\n"
|
||||||
|
" If necessary the lowest ranks will be coalesced.\n"
|
||||||
|
" No active kernels will be lowered to priority 0.\n"
|
||||||
|
" -i NUM Specify the partition to make the highest in the new\n"
|
||||||
|
" order.\n"
|
||||||
|
" -f Friends of the given partition (those with the same\n"
|
||||||
|
" starting priority) are also updated to the new\n"
|
||||||
|
" highest priority.\n"
|
||||||
|
"\n"
|
||||||
|
"With no options this will set the lowest active kernel to\n"
|
||||||
|
"priority 1 while maintaining the original order.\n"
|
||||||
|
"\n", progname);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cmd_prioritize(int argc, char *argv[]) {
|
||||||
|
CgptPrioritizeParams params;
|
||||||
|
memset(¶ms, 0, sizeof(params));
|
||||||
|
|
||||||
|
int c;
|
||||||
|
int errorcnt = 0;
|
||||||
|
char *e = 0;
|
||||||
|
|
||||||
|
opterr = 0; // quiet, you
|
||||||
|
while ((c=getopt(argc, argv, ":hi:fP:D:")) != -1)
|
||||||
|
{
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case 'D':
|
||||||
|
params.drive_size = strtoull(optarg, &e, 0);
|
||||||
|
errorcnt += check_int_parse(c, e);
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
params.set_partition = (uint32_t)strtoul(optarg, &e, 0);
|
||||||
|
errorcnt += check_int_parse(c, e);
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
params.set_friends = 1;
|
||||||
|
break;
|
||||||
|
case 'P':
|
||||||
|
params.max_priority = (int)strtol(optarg, &e, 0);
|
||||||
|
errorcnt += check_int_parse(c, e);
|
||||||
|
errorcnt += check_int_limit(c, params.max_priority, 1, 15);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'h':
|
||||||
|
Usage();
|
||||||
|
return CGPT_OK;
|
||||||
|
case '?':
|
||||||
|
Error("unrecognized option: -%c\n", optopt);
|
||||||
|
errorcnt++;
|
||||||
|
break;
|
||||||
|
case ':':
|
||||||
|
Error("missing argument to -%c\n", optopt);
|
||||||
|
errorcnt++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
errorcnt++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (errorcnt)
|
||||||
|
{
|
||||||
|
Usage();
|
||||||
|
return CGPT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.set_friends && !params.set_partition) {
|
||||||
|
Error("the -f option is only useful with the -i option\n");
|
||||||
|
Usage();
|
||||||
|
return CGPT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (optind >= argc) {
|
||||||
|
Error("missing drive argument\n");
|
||||||
|
return CGPT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
params.drive_name = argv[optind];
|
||||||
|
|
||||||
|
return CgptPrioritize(¶ms);
|
||||||
|
}
|
||||||
71
firmware/coreboot/3rdparty/vboot/cgpt/cmd_repair.c
vendored
Normal file
71
firmware/coreboot/3rdparty/vboot/cgpt/cmd_repair.c
vendored
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "cgpt.h"
|
||||||
|
#include "vboot_host.h"
|
||||||
|
|
||||||
|
extern const char* progname;
|
||||||
|
|
||||||
|
static void Usage(void)
|
||||||
|
{
|
||||||
|
printf("\nUsage: %s repair [OPTIONS] DRIVE\n\n"
|
||||||
|
"Repair damaged GPT headers and tables.\n\n"
|
||||||
|
"Options:\n"
|
||||||
|
" -D NUM Size (in bytes) of the disk where partitions reside\n"
|
||||||
|
" default 0, meaning partitions and GPT structs are\n"
|
||||||
|
" both on DRIVE\n"
|
||||||
|
" -v Verbose\n"
|
||||||
|
"\n", progname);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cmd_repair(int argc, char *argv[]) {
|
||||||
|
CgptRepairParams params;
|
||||||
|
memset(¶ms, 0, sizeof(params));
|
||||||
|
|
||||||
|
int c;
|
||||||
|
char* e = 0;
|
||||||
|
int errorcnt = 0;
|
||||||
|
|
||||||
|
opterr = 0; // quiet, you
|
||||||
|
while ((c=getopt(argc, argv, ":hvD:")) != -1)
|
||||||
|
{
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case 'D':
|
||||||
|
params.drive_size = strtoull(optarg, &e, 0);
|
||||||
|
errorcnt += check_int_parse(c, e);
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
params.verbose++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'h':
|
||||||
|
Usage();
|
||||||
|
return CGPT_OK;
|
||||||
|
case '?':
|
||||||
|
Error("unrecognized option: -%c\n", optopt);
|
||||||
|
errorcnt++;
|
||||||
|
break;
|
||||||
|
case ':':
|
||||||
|
Error("missing argument to -%c\n", optopt);
|
||||||
|
errorcnt++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
errorcnt++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (errorcnt)
|
||||||
|
{
|
||||||
|
Usage();
|
||||||
|
return CGPT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
params.drive_name = argv[optind];
|
||||||
|
|
||||||
|
return CgptRepair(¶ms);
|
||||||
|
}
|
||||||
121
firmware/coreboot/3rdparty/vboot/cgpt/cmd_show.c
vendored
Normal file
121
firmware/coreboot/3rdparty/vboot/cgpt/cmd_show.c
vendored
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#define __STDC_FORMAT_MACROS
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "cgpt.h"
|
||||||
|
#include "vboot_host.h"
|
||||||
|
|
||||||
|
extern const char* progname;
|
||||||
|
|
||||||
|
static void Usage(void)
|
||||||
|
{
|
||||||
|
printf("\nUsage: %s show [OPTIONS] DRIVE\n\n"
|
||||||
|
"Display the GPT table\n\n"
|
||||||
|
"Options:\n"
|
||||||
|
" -D NUM Size (in bytes) of the disk where partitions reside\n"
|
||||||
|
" default 0, meaning partitions and GPT structs are\n"
|
||||||
|
" both on DRIVE\n"
|
||||||
|
" -n Numeric output only\n"
|
||||||
|
" -v Verbose output\n"
|
||||||
|
" -q Quick output\n"
|
||||||
|
" -i NUM Show specified partition only - pick one of:\n"
|
||||||
|
" -b beginning sector\n"
|
||||||
|
" -s partition size\n"
|
||||||
|
" -t type guid\n"
|
||||||
|
" -u unique guid\n"
|
||||||
|
" -l label\n"
|
||||||
|
" -S Successful flag\n"
|
||||||
|
" -T Tries flag\n"
|
||||||
|
" -P Priority flag\n"
|
||||||
|
" -R Required flag\n"
|
||||||
|
" -B Legacy Boot flag\n"
|
||||||
|
" -A raw 16-bit attribute value (bits 48-63)\n"
|
||||||
|
" -d Debug output (including invalid headers)\n"
|
||||||
|
"\n", progname);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cmd_show(int argc, char *argv[]) {
|
||||||
|
CgptShowParams params;
|
||||||
|
memset(¶ms, 0, sizeof(params));
|
||||||
|
|
||||||
|
int c;
|
||||||
|
int errorcnt = 0;
|
||||||
|
char *e = 0;
|
||||||
|
|
||||||
|
opterr = 0; // quiet, you
|
||||||
|
while ((c=getopt(argc, argv, ":hnvqi:bstulSTPRBAdD:")) != -1)
|
||||||
|
{
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case 'D':
|
||||||
|
params.drive_size = strtoull(optarg, &e, 0);
|
||||||
|
errorcnt += check_int_parse(c, e);
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
params.numeric = 1;
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
params.verbose = 1;
|
||||||
|
break;
|
||||||
|
case 'q':
|
||||||
|
params.quick = 1;
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
params.partition = (uint32_t)strtoul(optarg, &e, 0);
|
||||||
|
errorcnt += check_int_parse(c, e);
|
||||||
|
break;
|
||||||
|
case 'b':
|
||||||
|
case 's':
|
||||||
|
case 't':
|
||||||
|
case 'u':
|
||||||
|
case 'l':
|
||||||
|
case 'S':
|
||||||
|
case 'T':
|
||||||
|
case 'P':
|
||||||
|
case 'R':
|
||||||
|
case 'B':
|
||||||
|
case 'A':
|
||||||
|
params.single_item = c;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'd':
|
||||||
|
params.debug = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'h':
|
||||||
|
Usage();
|
||||||
|
return CGPT_OK;
|
||||||
|
case '?':
|
||||||
|
Error("unrecognized option: -%c\n", optopt);
|
||||||
|
errorcnt++;
|
||||||
|
break;
|
||||||
|
case ':':
|
||||||
|
Error("missing argument to -%c\n", optopt);
|
||||||
|
errorcnt++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
errorcnt++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (errorcnt)
|
||||||
|
{
|
||||||
|
Usage();
|
||||||
|
return CGPT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (optind >= argc) {
|
||||||
|
Error("missing drive argument\n");
|
||||||
|
Usage();
|
||||||
|
return CGPT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
params.drive_name = argv[optind];
|
||||||
|
|
||||||
|
return CgptShow(¶ms);
|
||||||
|
}
|
||||||
60
firmware/coreboot/3rdparty/vboot/emerge_test.sh
vendored
Executable file
60
firmware/coreboot/3rdparty/vboot/emerge_test.sh
vendored
Executable file
@@ -0,0 +1,60 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Copyright 2014 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.
|
||||||
|
|
||||||
|
# Tests emerging all the ebuilds that use vboot_reference either as an
|
||||||
|
# ebuild dependency or by checking out the code and compiling it in a
|
||||||
|
# different ebuild. This is meant to be run from the chroot as part of testing
|
||||||
|
# a new change in vboot_reference.
|
||||||
|
|
||||||
|
# Required ebuilds:
|
||||||
|
TEST_EBUILDS="
|
||||||
|
sys-boot/chromeos-bootimage
|
||||||
|
sys-boot/chromeos-u-boot
|
||||||
|
sys-boot/coreboot
|
||||||
|
sys-boot/depthcharge
|
||||||
|
chromeos-base/chromeos-cryptohome
|
||||||
|
chromeos-base/chromeos-ec
|
||||||
|
chromeos-base/chromeos-installer
|
||||||
|
chromeos-base/chromeos-initramfs
|
||||||
|
chromeos-base/chromeos-login
|
||||||
|
chromeos-base/update_engine
|
||||||
|
chromeos-base/vboot_reference
|
||||||
|
chromeos-base/verity
|
||||||
|
"
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Check running inside the chroot.
|
||||||
|
if [ ! -e /etc/cros_chroot_version ]; then
|
||||||
|
echo "You must run this inside the chroot." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Detect the target board.
|
||||||
|
if [ "x${BOARD}" == "x" ]; then
|
||||||
|
if [ -e ~/trunk/src/scripts/.default_board ]; then
|
||||||
|
BOARD="`cat ~/trunk/src/scripts/.default_board`"
|
||||||
|
else
|
||||||
|
echo "You must pass BOARD environment variable or set a default board." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
VBOOT_REF_DIR="$(dirname "$0")"
|
||||||
|
echo "Running tests for board '${BOARD}' from ${VBOOT_REF_DIR}"
|
||||||
|
|
||||||
|
cd "${VBOOT_REF_DIR}"
|
||||||
|
|
||||||
|
echo "Running make runtests..."
|
||||||
|
make runtests -j32
|
||||||
|
|
||||||
|
echo "Removing build artifacts."
|
||||||
|
rm -rf build build-main
|
||||||
|
|
||||||
|
echo "Running emerge tests (runs cros_workon start)."
|
||||||
|
# Ignore errors about already working on those repos.
|
||||||
|
cros_workon-${BOARD} start ${TEST_EBUILDS} || true
|
||||||
|
|
||||||
|
emerge-${BOARD} ${TEST_EBUILDS}
|
||||||
208
firmware/coreboot/3rdparty/vboot/firmware/2lib/2api.c
vendored
Normal file
208
firmware/coreboot/3rdparty/vboot/firmware/2lib/2api.c
vendored
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
/* Copyright (c) 2014 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.
|
||||||
|
*
|
||||||
|
* Externally-callable APIs
|
||||||
|
* (Firmware portion)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "2sysincludes.h"
|
||||||
|
#include "2api.h"
|
||||||
|
#include "2common.h"
|
||||||
|
#include "2misc.h"
|
||||||
|
#include "2nvstorage.h"
|
||||||
|
#include "2secdata.h"
|
||||||
|
#include "2sha.h"
|
||||||
|
#include "2rsa.h"
|
||||||
|
#include "2tpm_bootmode.h"
|
||||||
|
|
||||||
|
int vb2api_secdata_check(const struct vb2_context *ctx)
|
||||||
|
{
|
||||||
|
return vb2_secdata_check_crc(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
int vb2api_secdata_create(struct vb2_context *ctx)
|
||||||
|
{
|
||||||
|
return vb2_secdata_create(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void vb2api_fail(struct vb2_context *ctx, uint8_t reason, uint8_t subcode)
|
||||||
|
{
|
||||||
|
/* Initialize the vboot context if it hasn't been yet */
|
||||||
|
vb2_init_context(ctx);
|
||||||
|
|
||||||
|
vb2_fail(ctx, reason, subcode);
|
||||||
|
}
|
||||||
|
|
||||||
|
int vb2api_fw_phase1(struct vb2_context *ctx)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
/* Initialize the vboot context if it hasn't been yet */
|
||||||
|
vb2_init_context(ctx);
|
||||||
|
|
||||||
|
/* Initialize NV context */
|
||||||
|
vb2_nv_init(ctx);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle caller-requested reboot due to secdata. Do this before we
|
||||||
|
* even look at secdata. If we fail because of a reboot loop we'll be
|
||||||
|
* the first failure so will get to set the recovery reason.
|
||||||
|
*/
|
||||||
|
if (!(ctx->flags & VB2_CONTEXT_SECDATA_WANTS_REBOOT)) {
|
||||||
|
/* No reboot requested */
|
||||||
|
vb2_nv_set(ctx, VB2_NV_TPM_REQUESTED_REBOOT, 0);
|
||||||
|
} else if (vb2_nv_get(ctx, VB2_NV_TPM_REQUESTED_REBOOT)) {
|
||||||
|
/*
|
||||||
|
* Reboot requested... again. Fool me once, shame on you.
|
||||||
|
* Fool me twice, shame on me. Fail into recovery to avoid
|
||||||
|
* a reboot loop.
|
||||||
|
*/
|
||||||
|
vb2_fail(ctx, VB2_RECOVERY_RO_TPM_REBOOT, 0);
|
||||||
|
} else {
|
||||||
|
/* Reboot requested for the first time */
|
||||||
|
vb2_nv_set(ctx, VB2_NV_TPM_REQUESTED_REBOOT, 1);
|
||||||
|
return VB2_ERROR_API_PHASE1_SECDATA_REBOOT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize secure data */
|
||||||
|
rv = vb2_secdata_init(ctx);
|
||||||
|
if (rv)
|
||||||
|
vb2_fail(ctx, VB2_RECOVERY_SECDATA_INIT, rv);
|
||||||
|
|
||||||
|
/* Load and parse the GBB header */
|
||||||
|
rv = vb2_fw_parse_gbb(ctx);
|
||||||
|
if (rv)
|
||||||
|
vb2_fail(ctx, VB2_RECOVERY_GBB_HEADER, rv);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check for recovery. Note that this function returns void, since any
|
||||||
|
* errors result in requesting recovery. That's also why we don't
|
||||||
|
* return error from failures in the preceding two steps; those
|
||||||
|
* failures simply cause us to detect recovery mode here.
|
||||||
|
*/
|
||||||
|
vb2_check_recovery(ctx);
|
||||||
|
|
||||||
|
/* Check for dev switch */
|
||||||
|
rv = vb2_check_dev_switch(ctx);
|
||||||
|
if (rv && !(ctx->flags & VB2_CONTEXT_RECOVERY_MODE)) {
|
||||||
|
/*
|
||||||
|
* Error in dev switch processing, and we weren't already
|
||||||
|
* headed for recovery mode. Reboot into recovery mode, since
|
||||||
|
* it's too late to handle those errors this boot, and we need
|
||||||
|
* to take a different path through the dev switch checking
|
||||||
|
* code in that case.
|
||||||
|
*/
|
||||||
|
vb2_fail(ctx, VB2_RECOVERY_DEV_SWITCH, rv);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return error if recovery is needed */
|
||||||
|
if (ctx->flags & VB2_CONTEXT_RECOVERY_MODE) {
|
||||||
|
/* Always clear RAM when entering recovery mode */
|
||||||
|
ctx->flags |= VB2_CONTEXT_CLEAR_RAM;
|
||||||
|
return VB2_ERROR_API_PHASE1_RECOVERY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vb2api_fw_phase2(struct vb2_context *ctx)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use the slot from the last boot if this is a resume. Do not set
|
||||||
|
* VB2_SD_STATUS_CHOSE_SLOT so the try counter is not decremented on
|
||||||
|
* failure as we are explicitly not attempting to boot from a new slot.
|
||||||
|
*/
|
||||||
|
if (ctx->flags & VB2_CONTEXT_S3_RESUME) {
|
||||||
|
struct vb2_shared_data *sd = vb2_get_sd(ctx);
|
||||||
|
|
||||||
|
/* Set the current slot to the last booted slot */
|
||||||
|
sd->fw_slot = vb2_nv_get(ctx, VB2_NV_FW_TRIED);
|
||||||
|
|
||||||
|
/* Set context flag if we're using slot B */
|
||||||
|
if (sd->fw_slot)
|
||||||
|
ctx->flags |= VB2_CONTEXT_FW_SLOT_B;
|
||||||
|
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Always clear RAM when entering developer mode */
|
||||||
|
if (ctx->flags & VB2_CONTEXT_DEVELOPER_MODE)
|
||||||
|
ctx->flags |= VB2_CONTEXT_CLEAR_RAM;
|
||||||
|
|
||||||
|
/* Check for explicit request to clear TPM */
|
||||||
|
rv = vb2_check_tpm_clear(ctx);
|
||||||
|
if (rv) {
|
||||||
|
vb2_fail(ctx, VB2_RECOVERY_TPM_CLEAR_OWNER, rv);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Decide which firmware slot to try this boot */
|
||||||
|
rv = vb2_select_fw_slot(ctx);
|
||||||
|
if (rv) {
|
||||||
|
vb2_fail(ctx, VB2_RECOVERY_FW_SLOT, rv);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vb2api_extend_hash(struct vb2_context *ctx,
|
||||||
|
const void *buf,
|
||||||
|
uint32_t size)
|
||||||
|
{
|
||||||
|
struct vb2_shared_data *sd = vb2_get_sd(ctx);
|
||||||
|
struct vb2_digest_context *dc = (struct vb2_digest_context *)
|
||||||
|
(ctx->workbuf + sd->workbuf_hash_offset);
|
||||||
|
|
||||||
|
/* Must have initialized hash digest work area */
|
||||||
|
if (!sd->workbuf_hash_size)
|
||||||
|
return VB2_ERROR_API_EXTEND_HASH_WORKBUF;
|
||||||
|
|
||||||
|
/* Don't extend past the data we expect to hash */
|
||||||
|
if (!size || size > sd->hash_remaining_size)
|
||||||
|
return VB2_ERROR_API_EXTEND_HASH_SIZE;
|
||||||
|
|
||||||
|
sd->hash_remaining_size -= size;
|
||||||
|
|
||||||
|
if (dc->using_hwcrypto)
|
||||||
|
return vb2ex_hwcrypto_digest_extend(buf, size);
|
||||||
|
else
|
||||||
|
return vb2_digest_extend(dc, buf, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int vb2api_get_pcr_digest(struct vb2_context *ctx,
|
||||||
|
enum vb2_pcr_digest which_digest,
|
||||||
|
uint8_t *dest,
|
||||||
|
uint32_t *dest_size)
|
||||||
|
{
|
||||||
|
const uint8_t *digest;
|
||||||
|
uint32_t digest_size;
|
||||||
|
|
||||||
|
switch (which_digest) {
|
||||||
|
case BOOT_MODE_PCR:
|
||||||
|
digest = vb2_get_boot_state_digest(ctx);
|
||||||
|
digest_size = VB2_SHA1_DIGEST_SIZE;
|
||||||
|
break;
|
||||||
|
case HWID_DIGEST_PCR:
|
||||||
|
digest = vb2_get_sd(ctx)->gbb_hwid_digest;
|
||||||
|
digest_size = VB2_GBB_HWID_DIGEST_SIZE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return VB2_ERROR_API_PCR_DIGEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (digest == NULL || *dest_size < digest_size)
|
||||||
|
return VB2_ERROR_API_PCR_DIGEST_BUF;
|
||||||
|
|
||||||
|
memcpy(dest, digest, digest_size);
|
||||||
|
if (digest_size < *dest_size)
|
||||||
|
memset(dest + digest_size, 0, *dest_size - digest_size);
|
||||||
|
|
||||||
|
*dest_size = digest_size;
|
||||||
|
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
}
|
||||||
105
firmware/coreboot/3rdparty/vboot/firmware/2lib/2common.c
vendored
Normal file
105
firmware/coreboot/3rdparty/vboot/firmware/2lib/2common.c
vendored
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
/* Copyright (c) 2014 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.
|
||||||
|
*
|
||||||
|
* Common functions between firmware and kernel verified boot.
|
||||||
|
* (Firmware portion)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "2sysincludes.h"
|
||||||
|
#include "2common.h"
|
||||||
|
#include "2rsa.h"
|
||||||
|
#include "2sha.h"
|
||||||
|
|
||||||
|
int vb2_safe_memcmp(const void *s1, const void *s2, size_t size)
|
||||||
|
{
|
||||||
|
const unsigned char *us1 = s1;
|
||||||
|
const unsigned char *us2 = s2;
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
if (0 == size)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Code snippet without data-dependent branch due to Nate Lawson
|
||||||
|
* (nate@root.org) of Root Labs.
|
||||||
|
*/
|
||||||
|
while (size--)
|
||||||
|
result |= *us1++ ^ *us2++;
|
||||||
|
|
||||||
|
return result != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vb2_align(uint8_t **ptr, uint32_t *size, uint32_t align, uint32_t want_size)
|
||||||
|
{
|
||||||
|
uintptr_t p = (uintptr_t)*ptr;
|
||||||
|
uintptr_t offs = p & (align - 1);
|
||||||
|
|
||||||
|
if (offs) {
|
||||||
|
offs = align - offs;
|
||||||
|
|
||||||
|
if (*size < offs)
|
||||||
|
return VB2_ERROR_ALIGN_BIGGER_THAN_SIZE;
|
||||||
|
|
||||||
|
*ptr += offs;
|
||||||
|
*size -= offs;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*size < want_size)
|
||||||
|
return VB2_ERROR_ALIGN_SIZE;
|
||||||
|
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vb2_workbuf_init(struct vb2_workbuf *wb, uint8_t *buf, uint32_t size)
|
||||||
|
{
|
||||||
|
wb->buf = buf;
|
||||||
|
wb->size = size;
|
||||||
|
|
||||||
|
/* Align the buffer so allocations will be aligned */
|
||||||
|
if (vb2_align(&wb->buf, &wb->size, VB2_WORKBUF_ALIGN, 0))
|
||||||
|
wb->size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *vb2_workbuf_alloc(struct vb2_workbuf *wb, uint32_t size)
|
||||||
|
{
|
||||||
|
uint8_t *ptr = wb->buf;
|
||||||
|
|
||||||
|
/* Round up size to work buffer alignment */
|
||||||
|
size = vb2_wb_round_up(size);
|
||||||
|
|
||||||
|
if (size > wb->size)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
wb->buf += size;
|
||||||
|
wb->size -= size;
|
||||||
|
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *vb2_workbuf_realloc(struct vb2_workbuf *wb,
|
||||||
|
uint32_t oldsize,
|
||||||
|
uint32_t newsize)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Just free and allocate to update the size. No need to move/copy
|
||||||
|
* memory, since the new pointer is guaranteed to be the same as the
|
||||||
|
* old one. The new allocation can fail, if the new size is too big.
|
||||||
|
*/
|
||||||
|
vb2_workbuf_free(wb, oldsize);
|
||||||
|
return vb2_workbuf_alloc(wb, newsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void vb2_workbuf_free(struct vb2_workbuf *wb, uint32_t size)
|
||||||
|
{
|
||||||
|
/* Round up size to work buffer alignment */
|
||||||
|
size = vb2_wb_round_up(size);
|
||||||
|
|
||||||
|
wb->buf -= size;
|
||||||
|
wb->size += size;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptrdiff_t vb2_offset_of(const void *base, const void *ptr)
|
||||||
|
{
|
||||||
|
return (uintptr_t)ptr - (uintptr_t)base;
|
||||||
|
}
|
||||||
29
firmware/coreboot/3rdparty/vboot/firmware/2lib/2crc8.c
vendored
Normal file
29
firmware/coreboot/3rdparty/vboot/firmware/2lib/2crc8.c
vendored
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/* Copyright (c) 2014 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "2sysincludes.h"
|
||||||
|
#include "2crc8.h"
|
||||||
|
|
||||||
|
uint8_t vb2_crc8(const void *vptr, uint32_t size)
|
||||||
|
{
|
||||||
|
const uint8_t *data = vptr;
|
||||||
|
unsigned crc = 0;
|
||||||
|
uint32_t i, j;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calculate CRC-8 directly. A table-based algorithm would be faster,
|
||||||
|
* but for only a few bytes it isn't worth the code size.
|
||||||
|
*/
|
||||||
|
for (j = size; j; j--, data++) {
|
||||||
|
crc ^= (*data << 8);
|
||||||
|
for(i = 8; i; i--) {
|
||||||
|
if (crc & 0x8000)
|
||||||
|
crc ^= (0x1070 << 3);
|
||||||
|
crc <<= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (uint8_t)(crc >> 8);
|
||||||
|
}
|
||||||
60
firmware/coreboot/3rdparty/vboot/firmware/2lib/2hmac.c
vendored
Normal file
60
firmware/coreboot/3rdparty/vboot/firmware/2lib/2hmac.c
vendored
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/* Copyright 2016 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "2sysincludes.h"
|
||||||
|
#include "2sha.h"
|
||||||
|
#include "2hmac.h"
|
||||||
|
|
||||||
|
int hmac(enum vb2_hash_algorithm alg,
|
||||||
|
const void *key, uint32_t key_size,
|
||||||
|
const void *msg, uint32_t msg_size,
|
||||||
|
uint8_t *mac, uint32_t mac_size)
|
||||||
|
{
|
||||||
|
uint32_t block_size;
|
||||||
|
uint32_t digest_size;
|
||||||
|
uint8_t k[VB2_MAX_BLOCK_SIZE];
|
||||||
|
uint8_t o_pad[VB2_MAX_BLOCK_SIZE];
|
||||||
|
uint8_t i_pad[VB2_MAX_BLOCK_SIZE];
|
||||||
|
uint8_t b[VB2_MAX_DIGEST_SIZE];
|
||||||
|
struct vb2_digest_context dc;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!key | !msg | !mac)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
digest_size = vb2_digest_size(alg);
|
||||||
|
block_size = vb2_hash_block_size(alg);
|
||||||
|
if (!digest_size || !block_size)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (mac_size < digest_size)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (key_size > block_size) {
|
||||||
|
vb2_digest_buffer((uint8_t *)key, key_size, alg, k, block_size);
|
||||||
|
key_size = digest_size;
|
||||||
|
} else {
|
||||||
|
memcpy(k, key, key_size);
|
||||||
|
}
|
||||||
|
if (key_size < block_size)
|
||||||
|
memset(k + key_size, 0, block_size - key_size);
|
||||||
|
|
||||||
|
for (i = 0; i < block_size; i++) {
|
||||||
|
o_pad[i] = 0x5c ^ k[i];
|
||||||
|
i_pad[i] = 0x36 ^ k[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
vb2_digest_init(&dc, alg);
|
||||||
|
vb2_digest_extend(&dc, i_pad, block_size);
|
||||||
|
vb2_digest_extend(&dc, msg, msg_size);
|
||||||
|
vb2_digest_finalize(&dc, b, digest_size);
|
||||||
|
|
||||||
|
vb2_digest_init(&dc, alg);
|
||||||
|
vb2_digest_extend(&dc, o_pad, block_size);
|
||||||
|
vb2_digest_extend(&dc, b, digest_size);
|
||||||
|
vb2_digest_finalize(&dc, mac, mac_size);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
413
firmware/coreboot/3rdparty/vboot/firmware/2lib/2misc.c
vendored
Normal file
413
firmware/coreboot/3rdparty/vboot/firmware/2lib/2misc.c
vendored
Normal file
@@ -0,0 +1,413 @@
|
|||||||
|
/* Copyright (c) 2014 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.
|
||||||
|
*
|
||||||
|
* Misc functions which need access to vb2_context but are not public APIs
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "2sysincludes.h"
|
||||||
|
#include "2api.h"
|
||||||
|
#include "2common.h"
|
||||||
|
#include "2misc.h"
|
||||||
|
#include "2nvstorage.h"
|
||||||
|
#include "2secdata.h"
|
||||||
|
#include "2sha.h"
|
||||||
|
#include "2rsa.h"
|
||||||
|
|
||||||
|
int vb2_validate_gbb_signature(uint8_t *sig) {
|
||||||
|
const static uint8_t sig_xor[VB2_GBB_SIGNATURE_SIZE] =
|
||||||
|
VB2_GBB_XOR_SIGNATURE;
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < VB2_GBB_SIGNATURE_SIZE; i++) {
|
||||||
|
if (sig[i] != (sig_xor[i] ^ VB2_GBB_XOR_CHARS[i]))
|
||||||
|
return VB2_ERROR_GBB_MAGIC;
|
||||||
|
}
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vb2_workbuf_from_ctx(struct vb2_context *ctx, struct vb2_workbuf *wb)
|
||||||
|
{
|
||||||
|
vb2_workbuf_init(wb, ctx->workbuf + ctx->workbuf_used,
|
||||||
|
ctx->workbuf_size - ctx->workbuf_used);
|
||||||
|
}
|
||||||
|
|
||||||
|
void vb2_set_workbuf_used(struct vb2_context *ctx, uint32_t used)
|
||||||
|
{
|
||||||
|
ctx->workbuf_used = vb2_wb_round_up(used);
|
||||||
|
}
|
||||||
|
|
||||||
|
int vb2_read_gbb_header(struct vb2_context *ctx, struct vb2_gbb_header *gbb)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
/* Read the entire header */
|
||||||
|
rv = vb2ex_read_resource(ctx, VB2_RES_GBB, 0, gbb, sizeof(*gbb));
|
||||||
|
if (rv)
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
/* Make sure it's really a GBB */
|
||||||
|
rv = vb2_validate_gbb_signature(gbb->signature);
|
||||||
|
if (rv)
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
/* Check for compatible version */
|
||||||
|
if (gbb->major_version != VB2_GBB_MAJOR_VER)
|
||||||
|
return VB2_ERROR_GBB_VERSION;
|
||||||
|
|
||||||
|
/* Current code is not backwards-compatible to 1.1 headers or older */
|
||||||
|
if (gbb->minor_version < VB2_GBB_MINOR_VER)
|
||||||
|
return VB2_ERROR_GBB_TOO_OLD;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Header size should be at least as big as we expect. It could be
|
||||||
|
* bigger, if the header has grown.
|
||||||
|
*/
|
||||||
|
if (gbb->header_size < sizeof(*gbb))
|
||||||
|
return VB2_ERROR_GBB_HEADER_SIZE;
|
||||||
|
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vb2_fail(struct vb2_context *ctx, uint8_t reason, uint8_t subcode)
|
||||||
|
{
|
||||||
|
struct vb2_shared_data *sd = vb2_get_sd(ctx);
|
||||||
|
|
||||||
|
/* If NV data hasn't been initialized, initialize it now */
|
||||||
|
if (!(sd->status & VB2_SD_STATUS_NV_INIT))
|
||||||
|
vb2_nv_init(ctx);
|
||||||
|
|
||||||
|
/* See if we were far enough in the boot process to choose a slot */
|
||||||
|
if (sd->status & VB2_SD_STATUS_CHOSE_SLOT) {
|
||||||
|
|
||||||
|
/* Boot failed */
|
||||||
|
vb2_nv_set(ctx, VB2_NV_FW_RESULT, VB2_FW_RESULT_FAILURE);
|
||||||
|
|
||||||
|
/* Use up remaining tries */
|
||||||
|
vb2_nv_set(ctx, VB2_NV_TRY_COUNT, 0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Try the other slot next time. We'll alternate
|
||||||
|
* between slots, which may help if one or both slots is
|
||||||
|
* flaky.
|
||||||
|
*/
|
||||||
|
vb2_nv_set(ctx, VB2_NV_TRY_NEXT, 1 - sd->fw_slot);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we didn't try the other slot last boot, or we tried it
|
||||||
|
* and it didn't fail, try it next boot.
|
||||||
|
*/
|
||||||
|
if (sd->last_fw_slot != 1 - sd->fw_slot ||
|
||||||
|
sd->last_fw_result != VB2_FW_RESULT_FAILURE)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we're still here, we failed before choosing a slot, or both
|
||||||
|
* this slot and the other slot failed in successive boots. So we
|
||||||
|
* need to go to recovery.
|
||||||
|
*
|
||||||
|
* Set a recovery reason and subcode only if they're not already set.
|
||||||
|
* If recovery is already requested, it's a more specific error code
|
||||||
|
* than later code is providing and we shouldn't overwrite it.
|
||||||
|
*/
|
||||||
|
VB2_DEBUG("Need recovery, reason: %#x / %#x\n", reason, subcode);
|
||||||
|
if (!vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST)) {
|
||||||
|
vb2_nv_set(ctx, VB2_NV_RECOVERY_REQUEST, reason);
|
||||||
|
vb2_nv_set(ctx, VB2_NV_RECOVERY_SUBCODE, subcode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int vb2_init_context(struct vb2_context *ctx)
|
||||||
|
{
|
||||||
|
struct vb2_shared_data *sd = vb2_get_sd(ctx);
|
||||||
|
|
||||||
|
/* Don't do anything if the context has already been initialized */
|
||||||
|
if (ctx->workbuf_used)
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Workbuf had better be big enough for our shared data struct and
|
||||||
|
* aligned. Not much we can do if it isn't; we'll die before we can
|
||||||
|
* store a recovery reason.
|
||||||
|
*/
|
||||||
|
if (ctx->workbuf_size < sizeof(*sd))
|
||||||
|
return VB2_ERROR_INITCTX_WORKBUF_SMALL;
|
||||||
|
if (!vb2_aligned(ctx->workbuf, VB2_WORKBUF_ALIGN))
|
||||||
|
return VB2_ERROR_INITCTX_WORKBUF_ALIGN;
|
||||||
|
|
||||||
|
/* Initialize the shared data at the start of the work buffer */
|
||||||
|
memset(sd, 0, sizeof(*sd));
|
||||||
|
ctx->workbuf_used = vb2_wb_round_up(sizeof(*sd));
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vb2_check_recovery(struct vb2_context *ctx)
|
||||||
|
{
|
||||||
|
struct vb2_shared_data *sd = vb2_get_sd(ctx);
|
||||||
|
uint32_t reason = vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST);
|
||||||
|
uint32_t subcode = vb2_nv_get(ctx, VB2_NV_RECOVERY_SUBCODE);
|
||||||
|
|
||||||
|
VB2_DEBUG("Recovery reason from previous boot: %#x / %#x\n",
|
||||||
|
reason, subcode);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sets the current recovery request, unless there's already been a
|
||||||
|
* failure earlier in the boot process.
|
||||||
|
*/
|
||||||
|
if (!sd->recovery_reason)
|
||||||
|
sd->recovery_reason = reason;
|
||||||
|
|
||||||
|
/* Clear request and subcode so we don't get stuck in recovery mode */
|
||||||
|
vb2_nv_set(ctx, VB2_NV_RECOVERY_REQUEST, VB2_RECOVERY_NOT_REQUESTED);
|
||||||
|
vb2_nv_set(ctx, VB2_NV_RECOVERY_SUBCODE, VB2_RECOVERY_NOT_REQUESTED);
|
||||||
|
|
||||||
|
if (ctx->flags & VB2_CONTEXT_FORCE_RECOVERY_MODE) {
|
||||||
|
VB2_DEBUG("Recovery was requested manually\n");
|
||||||
|
if (subcode && !sd->recovery_reason)
|
||||||
|
/*
|
||||||
|
* Recovery was requested at 'broken' screen.
|
||||||
|
* Promote subcode to reason.
|
||||||
|
*/
|
||||||
|
sd->recovery_reason = subcode;
|
||||||
|
else
|
||||||
|
/* Recovery was forced. Override recovery reason */
|
||||||
|
sd->recovery_reason = VB2_RECOVERY_RO_MANUAL;
|
||||||
|
sd->flags |= VB2_SD_FLAG_MANUAL_RECOVERY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If recovery reason is non-zero, tell caller we need recovery mode */
|
||||||
|
if (sd->recovery_reason) {
|
||||||
|
ctx->flags |= VB2_CONTEXT_RECOVERY_MODE;
|
||||||
|
VB2_DEBUG("We have a recovery request: %#x / %#x\n",
|
||||||
|
sd->recovery_reason,
|
||||||
|
vb2_nv_get(ctx, VB2_NV_RECOVERY_SUBCODE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int vb2_fw_parse_gbb(struct vb2_context *ctx)
|
||||||
|
{
|
||||||
|
struct vb2_shared_data *sd = vb2_get_sd(ctx);
|
||||||
|
struct vb2_gbb_header *gbb;
|
||||||
|
struct vb2_workbuf wb;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
vb2_workbuf_from_ctx(ctx, &wb);
|
||||||
|
|
||||||
|
/* Read GBB into next chunk of work buffer */
|
||||||
|
gbb = vb2_workbuf_alloc(&wb, sizeof(*gbb));
|
||||||
|
if (!gbb)
|
||||||
|
return VB2_ERROR_GBB_WORKBUF;
|
||||||
|
|
||||||
|
rv = vb2_read_gbb_header(ctx, gbb);
|
||||||
|
if (rv)
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
/* Extract the only things we care about at firmware time */
|
||||||
|
sd->gbb_flags = gbb->flags;
|
||||||
|
sd->gbb_rootkey_offset = gbb->rootkey_offset;
|
||||||
|
sd->gbb_rootkey_size = gbb->rootkey_size;
|
||||||
|
memcpy(sd->gbb_hwid_digest, gbb->hwid_digest, VB2_GBB_HWID_DIGEST_SIZE);
|
||||||
|
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vb2_check_dev_switch(struct vb2_context *ctx)
|
||||||
|
{
|
||||||
|
struct vb2_shared_data *sd = vb2_get_sd(ctx);
|
||||||
|
uint32_t flags = 0;
|
||||||
|
uint32_t old_flags;
|
||||||
|
int is_dev = 0;
|
||||||
|
int use_secdata = 1;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
/* Read secure flags */
|
||||||
|
rv = vb2_secdata_get(ctx, VB2_SECDATA_FLAGS, &flags);
|
||||||
|
if (rv) {
|
||||||
|
if (ctx->flags & VB2_CONTEXT_RECOVERY_MODE) {
|
||||||
|
/*
|
||||||
|
* Recovery mode needs to check other ways developer
|
||||||
|
* mode can be enabled, so don't give up yet. But
|
||||||
|
* since we can't read secdata, assume dev mode was
|
||||||
|
* disabled.
|
||||||
|
*/
|
||||||
|
use_secdata = 0;
|
||||||
|
flags = 0;
|
||||||
|
} else {
|
||||||
|
/* Normal mode simply fails */
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
old_flags = flags;
|
||||||
|
|
||||||
|
/* Handle dev disable request */
|
||||||
|
if (use_secdata && vb2_nv_get(ctx, VB2_NV_DISABLE_DEV_REQUEST)) {
|
||||||
|
flags &= ~VB2_SECDATA_FLAG_DEV_MODE;
|
||||||
|
|
||||||
|
/* Clear the request */
|
||||||
|
vb2_nv_set(ctx, VB2_NV_DISABLE_DEV_REQUEST, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if we've been asked by the caller to disable dev mode. Note
|
||||||
|
* that hardware switch and GBB flag will take precedence over this.
|
||||||
|
*/
|
||||||
|
if (ctx->flags & VB2_DISABLE_DEVELOPER_MODE)
|
||||||
|
flags &= ~VB2_SECDATA_FLAG_DEV_MODE;
|
||||||
|
|
||||||
|
/* Check virtual dev switch */
|
||||||
|
if (flags & VB2_SECDATA_FLAG_DEV_MODE)
|
||||||
|
is_dev = 1;
|
||||||
|
|
||||||
|
/* Handle forcing dev mode via physical switch */
|
||||||
|
if (ctx->flags & VB2_CONTEXT_FORCE_DEVELOPER_MODE)
|
||||||
|
is_dev = 1;
|
||||||
|
|
||||||
|
/* Check if GBB is forcing dev mode */
|
||||||
|
if (sd->gbb_flags & VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON)
|
||||||
|
is_dev = 1;
|
||||||
|
|
||||||
|
/* Handle whichever mode we end up in */
|
||||||
|
if (is_dev) {
|
||||||
|
/* Developer mode */
|
||||||
|
sd->flags |= VB2_SD_DEV_MODE_ENABLED;
|
||||||
|
ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE;
|
||||||
|
|
||||||
|
flags |= VB2_SECDATA_FLAG_LAST_BOOT_DEVELOPER;
|
||||||
|
} else {
|
||||||
|
/* Normal mode */
|
||||||
|
flags &= ~VB2_SECDATA_FLAG_LAST_BOOT_DEVELOPER;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Disable dev_boot_* flags. This ensures they will be
|
||||||
|
* initially disabled if the user later transitions back into
|
||||||
|
* developer mode.
|
||||||
|
*/
|
||||||
|
vb2_nv_set(ctx, VB2_NV_DEV_BOOT_USB, 0);
|
||||||
|
vb2_nv_set(ctx, VB2_NV_DEV_BOOT_LEGACY, 0);
|
||||||
|
vb2_nv_set(ctx, VB2_NV_DEV_BOOT_SIGNED_ONLY, 0);
|
||||||
|
vb2_nv_set(ctx, VB2_NV_DEV_BOOT_FASTBOOT_FULL_CAP, 0);
|
||||||
|
vb2_nv_set(ctx, VB2_NV_DEV_DEFAULT_BOOT, 0);
|
||||||
|
vb2_nv_set(ctx, VB2_NV_FASTBOOT_UNLOCK_IN_FW, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->flags & VB2_CONTEXT_FORCE_WIPEOUT_MODE)
|
||||||
|
vb2_nv_set(ctx, VB2_NV_REQ_WIPEOUT, 1);
|
||||||
|
|
||||||
|
if (flags != old_flags) {
|
||||||
|
/*
|
||||||
|
* Just changed dev mode state. Clear TPM owner. This must be
|
||||||
|
* done here instead of simply passing a flag to
|
||||||
|
* vb2_check_tpm_clear(), because we don't want to update
|
||||||
|
* last_boot_developer and then fail to clear the TPM owner.
|
||||||
|
*
|
||||||
|
* Note that we do this even if we couldn't read secdata, since
|
||||||
|
* the TPM owner and secdata may be independent, and we want
|
||||||
|
* the owner to be cleared if *this boot* is different than the
|
||||||
|
* last one (perhaps due to GBB or hardware override).
|
||||||
|
*/
|
||||||
|
rv = vb2ex_tpm_clear_owner(ctx);
|
||||||
|
if (use_secdata) {
|
||||||
|
/* Check for failure to clear owner */
|
||||||
|
if (rv) {
|
||||||
|
/*
|
||||||
|
* Note that this truncates rv to 8 bit. Which
|
||||||
|
* is not as useful as the full error code, but
|
||||||
|
* we don't have NVRAM space to store the full
|
||||||
|
* 32-bit code.
|
||||||
|
*/
|
||||||
|
vb2_fail(ctx, VB2_RECOVERY_TPM_CLEAR_OWNER, rv);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Save new flags */
|
||||||
|
rv = vb2_secdata_set(ctx, VB2_SECDATA_FLAGS, flags);
|
||||||
|
if (rv)
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vb2_check_tpm_clear(struct vb2_context *ctx)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
/* Check if we've been asked to clear the owner */
|
||||||
|
if (!vb2_nv_get(ctx, VB2_NV_CLEAR_TPM_OWNER_REQUEST))
|
||||||
|
return VB2_SUCCESS; /* No need to clear */
|
||||||
|
|
||||||
|
/* Request applies one time only */
|
||||||
|
vb2_nv_set(ctx, VB2_NV_CLEAR_TPM_OWNER_REQUEST, 0);
|
||||||
|
|
||||||
|
/* Try clearing */
|
||||||
|
rv = vb2ex_tpm_clear_owner(ctx);
|
||||||
|
if (rv) {
|
||||||
|
/*
|
||||||
|
* Note that this truncates rv to 8 bit. Which is not as
|
||||||
|
* useful as the full error code, but we don't have NVRAM space
|
||||||
|
* to store the full 32-bit code.
|
||||||
|
*/
|
||||||
|
vb2_fail(ctx, VB2_RECOVERY_TPM_CLEAR_OWNER, rv);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear successful */
|
||||||
|
vb2_nv_set(ctx, VB2_NV_CLEAR_TPM_OWNER_DONE, 1);
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vb2_select_fw_slot(struct vb2_context *ctx)
|
||||||
|
{
|
||||||
|
struct vb2_shared_data *sd = vb2_get_sd(ctx);
|
||||||
|
uint32_t tries;
|
||||||
|
|
||||||
|
/* Get result of last boot */
|
||||||
|
sd->last_fw_slot = vb2_nv_get(ctx, VB2_NV_FW_TRIED);
|
||||||
|
sd->last_fw_result = vb2_nv_get(ctx, VB2_NV_FW_RESULT);
|
||||||
|
|
||||||
|
/* Save to the previous result fields in NV storage */
|
||||||
|
vb2_nv_set(ctx, VB2_NV_FW_PREV_TRIED, sd->last_fw_slot);
|
||||||
|
vb2_nv_set(ctx, VB2_NV_FW_PREV_RESULT, sd->last_fw_result);
|
||||||
|
|
||||||
|
/* Clear result, since we don't know what will happen this boot */
|
||||||
|
vb2_nv_set(ctx, VB2_NV_FW_RESULT, VB2_FW_RESULT_UNKNOWN);
|
||||||
|
|
||||||
|
/* Get slot to try */
|
||||||
|
sd->fw_slot = vb2_nv_get(ctx, VB2_NV_TRY_NEXT);
|
||||||
|
|
||||||
|
/* Check try count */
|
||||||
|
tries = vb2_nv_get(ctx, VB2_NV_TRY_COUNT);
|
||||||
|
|
||||||
|
if (sd->last_fw_result == VB2_FW_RESULT_TRYING &&
|
||||||
|
sd->last_fw_slot == sd->fw_slot &&
|
||||||
|
tries == 0) {
|
||||||
|
/*
|
||||||
|
* We used up our last try on the previous boot, so fall back
|
||||||
|
* to the other slot this boot.
|
||||||
|
*/
|
||||||
|
sd->fw_slot = 1 - sd->fw_slot;
|
||||||
|
vb2_nv_set(ctx, VB2_NV_TRY_NEXT, sd->fw_slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tries > 0) {
|
||||||
|
/* Still trying this firmware */
|
||||||
|
vb2_nv_set(ctx, VB2_NV_FW_RESULT, VB2_FW_RESULT_TRYING);
|
||||||
|
|
||||||
|
/* Decrement non-zero try count, unless told not to */
|
||||||
|
if (!(ctx->flags & VB2_CONTEXT_NOFAIL_BOOT))
|
||||||
|
vb2_nv_set(ctx, VB2_NV_TRY_COUNT, tries - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Store the slot we're trying */
|
||||||
|
vb2_nv_set(ctx, VB2_NV_FW_TRIED, sd->fw_slot);
|
||||||
|
|
||||||
|
/* Set context flag if we're using slot B */
|
||||||
|
if (sd->fw_slot)
|
||||||
|
ctx->flags |= VB2_CONTEXT_FW_SLOT_B;
|
||||||
|
|
||||||
|
/* Set status flag */
|
||||||
|
sd->status |= VB2_SD_STATUS_CHOSE_SLOT;
|
||||||
|
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
}
|
||||||
433
firmware/coreboot/3rdparty/vboot/firmware/2lib/2nvstorage.c
vendored
Normal file
433
firmware/coreboot/3rdparty/vboot/firmware/2lib/2nvstorage.c
vendored
Normal file
@@ -0,0 +1,433 @@
|
|||||||
|
/* Copyright (c) 2014 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Non-volatile storage routines */
|
||||||
|
|
||||||
|
#include "2sysincludes.h"
|
||||||
|
#include "2common.h"
|
||||||
|
#include "2crc8.h"
|
||||||
|
#include "2misc.h"
|
||||||
|
#include "2nvstorage.h"
|
||||||
|
#include "2nvstorage_fields.h"
|
||||||
|
|
||||||
|
static void vb2_nv_regen_crc(struct vb2_context *ctx)
|
||||||
|
{
|
||||||
|
const int offs = ctx->flags & VB2_CONTEXT_NVDATA_V2 ?
|
||||||
|
VB2_NV_OFFS_CRC_V2 : VB2_NV_OFFS_CRC_V1;
|
||||||
|
|
||||||
|
ctx->nvdata[offs] = vb2_crc8(ctx->nvdata, offs);
|
||||||
|
ctx->flags |= VB2_CONTEXT_NVDATA_CHANGED;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vb2_nv_get_size(const struct vb2_context *ctx)
|
||||||
|
{
|
||||||
|
return ctx->flags & VB2_CONTEXT_NVDATA_V2 ?
|
||||||
|
VB2_NVDATA_SIZE_V2 : VB2_NVDATA_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check the CRC of the non-volatile storage context.
|
||||||
|
*
|
||||||
|
* Use this if reading from non-volatile storage may be flaky, and you want to
|
||||||
|
* retry reading it several times.
|
||||||
|
*
|
||||||
|
* This may be called before vb2_context_init().
|
||||||
|
*
|
||||||
|
* @param ctx Context pointer
|
||||||
|
* @return VB2_SUCCESS, or non-zero error code if error.
|
||||||
|
*/
|
||||||
|
int vb2_nv_check_crc(const struct vb2_context *ctx)
|
||||||
|
{
|
||||||
|
const uint8_t *p = ctx->nvdata;
|
||||||
|
const int offs = ctx->flags & VB2_CONTEXT_NVDATA_V2 ?
|
||||||
|
VB2_NV_OFFS_CRC_V2 : VB2_NV_OFFS_CRC_V1;
|
||||||
|
const int sig = ctx->flags & VB2_CONTEXT_NVDATA_V2 ?
|
||||||
|
VB2_NV_HEADER_SIGNATURE_V2 : VB2_NV_HEADER_SIGNATURE_V1;
|
||||||
|
|
||||||
|
/* Check header */
|
||||||
|
if (sig != (p[VB2_NV_OFFS_HEADER] & VB2_NV_HEADER_SIGNATURE_MASK))
|
||||||
|
return VB2_ERROR_NV_HEADER;
|
||||||
|
|
||||||
|
/* Check CRC */
|
||||||
|
if (vb2_crc8(p, offs) != p[offs])
|
||||||
|
return VB2_ERROR_NV_CRC;
|
||||||
|
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vb2_nv_init(struct vb2_context *ctx)
|
||||||
|
{
|
||||||
|
const int sig = ctx->flags & VB2_CONTEXT_NVDATA_V2 ?
|
||||||
|
VB2_NV_HEADER_SIGNATURE_V2 : VB2_NV_HEADER_SIGNATURE_V1;
|
||||||
|
struct vb2_shared_data *sd = vb2_get_sd(ctx);
|
||||||
|
uint8_t *p = ctx->nvdata;
|
||||||
|
|
||||||
|
|
||||||
|
/* Check data for consistency */
|
||||||
|
if (vb2_nv_check_crc(ctx) != VB2_SUCCESS) {
|
||||||
|
/* Data is inconsistent (bad CRC or header); reset defaults */
|
||||||
|
memset(p, 0, VB2_NVDATA_SIZE_V2);
|
||||||
|
p[VB2_NV_OFFS_HEADER] = (sig |
|
||||||
|
VB2_NV_HEADER_FW_SETTINGS_RESET |
|
||||||
|
VB2_NV_HEADER_KERNEL_SETTINGS_RESET);
|
||||||
|
|
||||||
|
/* Regenerate CRC */
|
||||||
|
vb2_nv_regen_crc(ctx);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set status flag.
|
||||||
|
*
|
||||||
|
* Note that early in some calling sequences, shared data may
|
||||||
|
* not be available. For example, if there is an error
|
||||||
|
* allocating the context work buffer, and we're trying to
|
||||||
|
* initialize non-volatile storage so we can write a recovery
|
||||||
|
* request. In that case, sd will be NULL. So while we don't
|
||||||
|
* usually need to check for that in other library functions,
|
||||||
|
* here we do.
|
||||||
|
*/
|
||||||
|
if (sd)
|
||||||
|
sd->status |= VB2_SD_STATUS_NV_REINIT;
|
||||||
|
/* TODO: unit test for status flag being set */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sd)
|
||||||
|
sd->status |= VB2_SD_STATUS_NV_INIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Macro for vb2_nv_get() single-bit settings to reduce duplicate code. */
|
||||||
|
#define GETBIT(offs, mask) (p[offs] & mask ? 1 : 0)
|
||||||
|
|
||||||
|
uint32_t vb2_nv_get(struct vb2_context *ctx, enum vb2_nv_param param)
|
||||||
|
{
|
||||||
|
const uint8_t *p = ctx->nvdata;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO: We could reduce the binary size for this code by #ifdef'ing
|
||||||
|
* out the params not used by firmware verification.
|
||||||
|
*/
|
||||||
|
switch (param) {
|
||||||
|
case VB2_NV_FIRMWARE_SETTINGS_RESET:
|
||||||
|
return GETBIT(VB2_NV_OFFS_HEADER,
|
||||||
|
VB2_NV_HEADER_FW_SETTINGS_RESET);
|
||||||
|
|
||||||
|
case VB2_NV_KERNEL_SETTINGS_RESET:
|
||||||
|
return GETBIT(VB2_NV_OFFS_HEADER,
|
||||||
|
VB2_NV_HEADER_KERNEL_SETTINGS_RESET);
|
||||||
|
|
||||||
|
case VB2_NV_DEBUG_RESET_MODE:
|
||||||
|
return GETBIT(VB2_NV_OFFS_BOOT, VB2_NV_BOOT_DEBUG_RESET);
|
||||||
|
|
||||||
|
case VB2_NV_TRY_NEXT:
|
||||||
|
return GETBIT(VB2_NV_OFFS_BOOT2, VB2_NV_BOOT2_TRY_NEXT);
|
||||||
|
|
||||||
|
case VB2_NV_TRY_COUNT:
|
||||||
|
return p[VB2_NV_OFFS_BOOT] & VB2_NV_BOOT_TRY_COUNT_MASK;
|
||||||
|
|
||||||
|
case VB2_NV_FW_TRIED:
|
||||||
|
return GETBIT(VB2_NV_OFFS_BOOT2, VB2_NV_BOOT2_TRIED);
|
||||||
|
|
||||||
|
case VB2_NV_FW_RESULT:
|
||||||
|
return p[VB2_NV_OFFS_BOOT2] & VB2_NV_BOOT2_RESULT_MASK;
|
||||||
|
|
||||||
|
case VB2_NV_FW_PREV_TRIED:
|
||||||
|
return GETBIT(VB2_NV_OFFS_BOOT2, VB2_NV_BOOT2_PREV_TRIED);
|
||||||
|
|
||||||
|
case VB2_NV_FW_PREV_RESULT:
|
||||||
|
return (p[VB2_NV_OFFS_BOOT2] & VB2_NV_BOOT2_PREV_RESULT_MASK)
|
||||||
|
>> VB2_NV_BOOT2_PREV_RESULT_SHIFT;
|
||||||
|
|
||||||
|
case VB2_NV_RECOVERY_REQUEST:
|
||||||
|
return p[VB2_NV_OFFS_RECOVERY];
|
||||||
|
|
||||||
|
case VB2_NV_RECOVERY_SUBCODE:
|
||||||
|
return p[VB2_NV_OFFS_RECOVERY_SUBCODE];
|
||||||
|
|
||||||
|
case VB2_NV_LOCALIZATION_INDEX:
|
||||||
|
return p[VB2_NV_OFFS_LOCALIZATION];
|
||||||
|
|
||||||
|
case VB2_NV_KERNEL_FIELD:
|
||||||
|
return p[VB2_NV_OFFS_KERNEL1] | (p[VB2_NV_OFFS_KERNEL2] << 8);
|
||||||
|
|
||||||
|
case VB2_NV_DEV_BOOT_USB:
|
||||||
|
return GETBIT(VB2_NV_OFFS_DEV, VB2_NV_DEV_FLAG_USB);
|
||||||
|
|
||||||
|
case VB2_NV_DEV_BOOT_LEGACY:
|
||||||
|
return GETBIT(VB2_NV_OFFS_DEV, VB2_NV_DEV_FLAG_LEGACY);
|
||||||
|
|
||||||
|
case VB2_NV_DEV_BOOT_SIGNED_ONLY:
|
||||||
|
return GETBIT(VB2_NV_OFFS_DEV, VB2_NV_DEV_FLAG_SIGNED_ONLY);
|
||||||
|
|
||||||
|
case VB2_NV_DEV_BOOT_FASTBOOT_FULL_CAP:
|
||||||
|
return GETBIT(VB2_NV_OFFS_DEV,
|
||||||
|
VB2_NV_DEV_FLAG_FASTBOOT_FULL_CAP);
|
||||||
|
|
||||||
|
case VB2_NV_DEV_DEFAULT_BOOT:
|
||||||
|
return (p[VB2_NV_OFFS_DEV] & VB2_NV_DEV_FLAG_DEFAULT_BOOT)
|
||||||
|
>> VB2_NV_DEV_DEFAULT_BOOT_SHIFT;
|
||||||
|
|
||||||
|
case VB2_NV_DEV_ENABLE_UDC:
|
||||||
|
return GETBIT(VB2_NV_OFFS_DEV, VB2_NV_DEV_FLAG_UDC);
|
||||||
|
|
||||||
|
case VB2_NV_DISABLE_DEV_REQUEST:
|
||||||
|
return GETBIT(VB2_NV_OFFS_BOOT, VB2_NV_BOOT_DISABLE_DEV);
|
||||||
|
|
||||||
|
case VB2_NV_OPROM_NEEDED:
|
||||||
|
return GETBIT(VB2_NV_OFFS_BOOT, VB2_NV_BOOT_OPROM_NEEDED);
|
||||||
|
|
||||||
|
case VB2_NV_BACKUP_NVRAM_REQUEST:
|
||||||
|
return GETBIT(VB2_NV_OFFS_BOOT, VB2_NV_BOOT_BACKUP_NVRAM);
|
||||||
|
|
||||||
|
case VB2_NV_CLEAR_TPM_OWNER_REQUEST:
|
||||||
|
return GETBIT(VB2_NV_OFFS_TPM, VB2_NV_TPM_CLEAR_OWNER_REQUEST);
|
||||||
|
|
||||||
|
case VB2_NV_CLEAR_TPM_OWNER_DONE:
|
||||||
|
return GETBIT(VB2_NV_OFFS_TPM, VB2_NV_TPM_CLEAR_OWNER_DONE);
|
||||||
|
|
||||||
|
case VB2_NV_TPM_REQUESTED_REBOOT:
|
||||||
|
return GETBIT(VB2_NV_OFFS_TPM, VB2_NV_TPM_REBOOTED);
|
||||||
|
|
||||||
|
case VB2_NV_REQ_WIPEOUT:
|
||||||
|
return GETBIT(VB2_NV_OFFS_HEADER , VB2_NV_HEADER_WIPEOUT);
|
||||||
|
|
||||||
|
case VB2_NV_FASTBOOT_UNLOCK_IN_FW:
|
||||||
|
return GETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_UNLOCK_FASTBOOT);
|
||||||
|
|
||||||
|
case VB2_NV_BOOT_ON_AC_DETECT:
|
||||||
|
return GETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_BOOT_ON_AC_DETECT);
|
||||||
|
|
||||||
|
case VB2_NV_TRY_RO_SYNC:
|
||||||
|
return GETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_TRY_RO_SYNC);
|
||||||
|
|
||||||
|
case VB2_NV_BATTERY_CUTOFF_REQUEST:
|
||||||
|
return GETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_BATTERY_CUTOFF);
|
||||||
|
|
||||||
|
case VB2_NV_KERNEL_MAX_ROLLFORWARD:
|
||||||
|
return (p[VB2_NV_OFFS_KERNEL_MAX_ROLLFORWARD1]
|
||||||
|
| (p[VB2_NV_OFFS_KERNEL_MAX_ROLLFORWARD2] << 8)
|
||||||
|
| (p[VB2_NV_OFFS_KERNEL_MAX_ROLLFORWARD3] << 16)
|
||||||
|
| (p[VB2_NV_OFFS_KERNEL_MAX_ROLLFORWARD4] << 24));
|
||||||
|
|
||||||
|
case VB2_NV_FW_MAX_ROLLFORWARD:
|
||||||
|
/* Field only present in V2 */
|
||||||
|
if (!(ctx->flags & VB2_CONTEXT_NVDATA_V2))
|
||||||
|
return VB2_FW_MAX_ROLLFORWARD_V1_DEFAULT;
|
||||||
|
|
||||||
|
return (p[VB2_NV_OFFS_FW_MAX_ROLLFORWARD1]
|
||||||
|
| (p[VB2_NV_OFFS_FW_MAX_ROLLFORWARD2] << 8)
|
||||||
|
| (p[VB2_NV_OFFS_FW_MAX_ROLLFORWARD3] << 16)
|
||||||
|
| (p[VB2_NV_OFFS_FW_MAX_ROLLFORWARD4] << 24));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Put default return outside the switch() instead of in default:, so
|
||||||
|
* that adding a new param will cause a compiler warning.
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef GETBIT
|
||||||
|
|
||||||
|
/* Macro for vb2_nv_set() single-bit settings to reduce duplicate code. */
|
||||||
|
#define SETBIT(offs, mask) \
|
||||||
|
{ if (value) p[offs] |= mask; else p[offs] &= ~mask; }
|
||||||
|
|
||||||
|
void vb2_nv_set(struct vb2_context *ctx,
|
||||||
|
enum vb2_nv_param param,
|
||||||
|
uint32_t value)
|
||||||
|
{
|
||||||
|
uint8_t *p = ctx->nvdata;
|
||||||
|
|
||||||
|
/* If not changing the value, don't regenerate the CRC. */
|
||||||
|
if (vb2_nv_get(ctx, param) == value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO: We could reduce the binary size for this code by #ifdef'ing
|
||||||
|
* out the params not used by firmware verification.
|
||||||
|
*/
|
||||||
|
switch (param) {
|
||||||
|
case VB2_NV_FIRMWARE_SETTINGS_RESET:
|
||||||
|
SETBIT(VB2_NV_OFFS_HEADER, VB2_NV_HEADER_FW_SETTINGS_RESET);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VB2_NV_KERNEL_SETTINGS_RESET:
|
||||||
|
SETBIT(VB2_NV_OFFS_HEADER, VB2_NV_HEADER_KERNEL_SETTINGS_RESET);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VB2_NV_DEBUG_RESET_MODE:
|
||||||
|
SETBIT(VB2_NV_OFFS_BOOT, VB2_NV_BOOT_DEBUG_RESET);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VB2_NV_TRY_NEXT:
|
||||||
|
SETBIT(VB2_NV_OFFS_BOOT2, VB2_NV_BOOT2_TRY_NEXT);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VB2_NV_TRY_COUNT:
|
||||||
|
/* Clip to valid range. */
|
||||||
|
if (value > VB2_NV_BOOT_TRY_COUNT_MASK)
|
||||||
|
value = VB2_NV_BOOT_TRY_COUNT_MASK;
|
||||||
|
|
||||||
|
p[VB2_NV_OFFS_BOOT] &= ~VB2_NV_BOOT_TRY_COUNT_MASK;
|
||||||
|
p[VB2_NV_OFFS_BOOT] |= (uint8_t)value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VB2_NV_FW_TRIED:
|
||||||
|
SETBIT(VB2_NV_OFFS_BOOT2, VB2_NV_BOOT2_TRIED);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VB2_NV_FW_RESULT:
|
||||||
|
/* Map out of range values to unknown */
|
||||||
|
if (value > VB2_NV_BOOT2_RESULT_MASK)
|
||||||
|
value = VB2_FW_RESULT_UNKNOWN;
|
||||||
|
|
||||||
|
p[VB2_NV_OFFS_BOOT2] &= ~VB2_NV_BOOT2_RESULT_MASK;
|
||||||
|
p[VB2_NV_OFFS_BOOT2] |= (uint8_t)value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VB2_NV_FW_PREV_TRIED:
|
||||||
|
SETBIT(VB2_NV_OFFS_BOOT2, VB2_NV_BOOT2_PREV_TRIED);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VB2_NV_FW_PREV_RESULT:
|
||||||
|
/* Map out of range values to unknown */
|
||||||
|
if (value > VB2_NV_BOOT2_RESULT_MASK)
|
||||||
|
value = VB2_FW_RESULT_UNKNOWN;
|
||||||
|
|
||||||
|
p[VB2_NV_OFFS_BOOT2] &= ~VB2_NV_BOOT2_PREV_RESULT_MASK;
|
||||||
|
p[VB2_NV_OFFS_BOOT2] |=
|
||||||
|
(uint8_t)(value << VB2_NV_BOOT2_PREV_RESULT_SHIFT);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VB2_NV_RECOVERY_REQUEST:
|
||||||
|
/*
|
||||||
|
* Map values outside the valid range to the legacy reason,
|
||||||
|
* since we can't determine if we're called from kernel or user
|
||||||
|
* mode.
|
||||||
|
*/
|
||||||
|
if (value > 0xff)
|
||||||
|
value = VB2_RECOVERY_LEGACY;
|
||||||
|
p[VB2_NV_OFFS_RECOVERY] = (uint8_t)value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VB2_NV_RECOVERY_SUBCODE:
|
||||||
|
p[VB2_NV_OFFS_RECOVERY_SUBCODE] = (uint8_t)value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VB2_NV_LOCALIZATION_INDEX:
|
||||||
|
/* Map values outside the valid range to the default index. */
|
||||||
|
if (value > 0xFF)
|
||||||
|
value = 0;
|
||||||
|
p[VB2_NV_OFFS_LOCALIZATION] = (uint8_t)value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VB2_NV_KERNEL_FIELD:
|
||||||
|
p[VB2_NV_OFFS_KERNEL1] = (uint8_t)(value);
|
||||||
|
p[VB2_NV_OFFS_KERNEL2] = (uint8_t)(value >> 8);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VB2_NV_DEV_BOOT_USB:
|
||||||
|
SETBIT(VB2_NV_OFFS_DEV, VB2_NV_DEV_FLAG_USB);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VB2_NV_DEV_BOOT_LEGACY:
|
||||||
|
SETBIT(VB2_NV_OFFS_DEV, VB2_NV_DEV_FLAG_LEGACY);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VB2_NV_DEV_BOOT_SIGNED_ONLY:
|
||||||
|
SETBIT(VB2_NV_OFFS_DEV, VB2_NV_DEV_FLAG_SIGNED_ONLY);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VB2_NV_DEV_BOOT_FASTBOOT_FULL_CAP:
|
||||||
|
SETBIT(VB2_NV_OFFS_DEV, VB2_NV_DEV_FLAG_FASTBOOT_FULL_CAP);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VB2_NV_DEV_DEFAULT_BOOT:
|
||||||
|
/* Map out of range values to disk */
|
||||||
|
if (value > (VB2_NV_DEV_FLAG_DEFAULT_BOOT >>
|
||||||
|
VB2_NV_DEV_DEFAULT_BOOT_SHIFT))
|
||||||
|
value = VB2_DEV_DEFAULT_BOOT_DISK;
|
||||||
|
|
||||||
|
p[VB2_NV_OFFS_DEV] &= ~VB2_NV_DEV_FLAG_DEFAULT_BOOT;
|
||||||
|
p[VB2_NV_OFFS_DEV] |=
|
||||||
|
(uint8_t)(value << VB2_NV_DEV_DEFAULT_BOOT_SHIFT);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VB2_NV_DEV_ENABLE_UDC:
|
||||||
|
SETBIT(VB2_NV_OFFS_DEV, VB2_NV_DEV_FLAG_UDC);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VB2_NV_DISABLE_DEV_REQUEST:
|
||||||
|
SETBIT(VB2_NV_OFFS_BOOT, VB2_NV_BOOT_DISABLE_DEV);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VB2_NV_OPROM_NEEDED:
|
||||||
|
SETBIT(VB2_NV_OFFS_BOOT, VB2_NV_BOOT_OPROM_NEEDED);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VB2_NV_BACKUP_NVRAM_REQUEST:
|
||||||
|
SETBIT(VB2_NV_OFFS_BOOT, VB2_NV_BOOT_BACKUP_NVRAM);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VB2_NV_CLEAR_TPM_OWNER_REQUEST:
|
||||||
|
SETBIT(VB2_NV_OFFS_TPM, VB2_NV_TPM_CLEAR_OWNER_REQUEST);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VB2_NV_CLEAR_TPM_OWNER_DONE:
|
||||||
|
SETBIT(VB2_NV_OFFS_TPM, VB2_NV_TPM_CLEAR_OWNER_DONE);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VB2_NV_TPM_REQUESTED_REBOOT:
|
||||||
|
SETBIT(VB2_NV_OFFS_TPM, VB2_NV_TPM_REBOOTED);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VB2_NV_REQ_WIPEOUT:
|
||||||
|
SETBIT(VB2_NV_OFFS_HEADER , VB2_NV_HEADER_WIPEOUT);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VB2_NV_FASTBOOT_UNLOCK_IN_FW:
|
||||||
|
SETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_UNLOCK_FASTBOOT);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VB2_NV_BOOT_ON_AC_DETECT:
|
||||||
|
SETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_BOOT_ON_AC_DETECT);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VB2_NV_TRY_RO_SYNC:
|
||||||
|
SETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_TRY_RO_SYNC);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VB2_NV_BATTERY_CUTOFF_REQUEST:
|
||||||
|
SETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_BATTERY_CUTOFF);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VB2_NV_KERNEL_MAX_ROLLFORWARD:
|
||||||
|
p[VB2_NV_OFFS_KERNEL_MAX_ROLLFORWARD1] = (uint8_t)(value);
|
||||||
|
p[VB2_NV_OFFS_KERNEL_MAX_ROLLFORWARD2] = (uint8_t)(value >> 8);
|
||||||
|
p[VB2_NV_OFFS_KERNEL_MAX_ROLLFORWARD3] = (uint8_t)(value >> 16);
|
||||||
|
p[VB2_NV_OFFS_KERNEL_MAX_ROLLFORWARD4] = (uint8_t)(value >> 24);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VB2_NV_FW_MAX_ROLLFORWARD:
|
||||||
|
/* Field only present in V2 */
|
||||||
|
if (!(ctx->flags & VB2_CONTEXT_NVDATA_V2))
|
||||||
|
return;
|
||||||
|
|
||||||
|
p[VB2_NV_OFFS_FW_MAX_ROLLFORWARD1] = (uint8_t)(value);
|
||||||
|
p[VB2_NV_OFFS_FW_MAX_ROLLFORWARD2] = (uint8_t)(value >> 8);
|
||||||
|
p[VB2_NV_OFFS_FW_MAX_ROLLFORWARD3] = (uint8_t)(value >> 16);
|
||||||
|
p[VB2_NV_OFFS_FW_MAX_ROLLFORWARD4] = (uint8_t)(value >> 24);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note there is no default case. This causes a compiler warning if
|
||||||
|
* a new param is added to the enum without adding support here.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Need to regenerate CRC, since the value changed. */
|
||||||
|
vb2_nv_regen_crc(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef SETBIT
|
||||||
425
firmware/coreboot/3rdparty/vboot/firmware/2lib/2rsa.c
vendored
Normal file
425
firmware/coreboot/3rdparty/vboot/firmware/2lib/2rsa.c
vendored
Normal file
@@ -0,0 +1,425 @@
|
|||||||
|
/* Copyright (c) 2014 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Implementation of RSA signature verification which uses a pre-processed key
|
||||||
|
* for computation. The code extends Android's RSA verification code to support
|
||||||
|
* multiple RSA key lengths and hash digest algorithms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "2sysincludes.h"
|
||||||
|
#include "2common.h"
|
||||||
|
#include "2rsa.h"
|
||||||
|
#include "2sha.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* a[] -= mod
|
||||||
|
*/
|
||||||
|
static void subM(const struct vb2_public_key *key, uint32_t *a)
|
||||||
|
{
|
||||||
|
int64_t A = 0;
|
||||||
|
uint32_t i;
|
||||||
|
for (i = 0; i < key->arrsize; ++i) {
|
||||||
|
A += (uint64_t)a[i] - key->n[i];
|
||||||
|
a[i] = (uint32_t)A;
|
||||||
|
A >>= 32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a[] >= mod
|
||||||
|
*/
|
||||||
|
int vb2_mont_ge(const struct vb2_public_key *key, uint32_t *a)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
for (i = key->arrsize; i;) {
|
||||||
|
--i;
|
||||||
|
if (a[i] < key->n[i])
|
||||||
|
return 0;
|
||||||
|
if (a[i] > key->n[i])
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 1; /* equal */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Montgomery c[] += a * b[] / R % mod
|
||||||
|
*/
|
||||||
|
static void montMulAdd(const struct vb2_public_key *key,
|
||||||
|
uint32_t *c,
|
||||||
|
const uint32_t a,
|
||||||
|
const uint32_t *b)
|
||||||
|
{
|
||||||
|
uint64_t A = (uint64_t)a * b[0] + c[0];
|
||||||
|
uint32_t d0 = (uint32_t)A * key->n0inv;
|
||||||
|
uint64_t B = (uint64_t)d0 * key->n[0] + (uint32_t)A;
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
for (i = 1; i < key->arrsize; ++i) {
|
||||||
|
A = (A >> 32) + (uint64_t)a * b[i] + c[i];
|
||||||
|
B = (B >> 32) + (uint64_t)d0 * key->n[i] + (uint32_t)A;
|
||||||
|
c[i - 1] = (uint32_t)B;
|
||||||
|
}
|
||||||
|
|
||||||
|
A = (A >> 32) + (B >> 32);
|
||||||
|
|
||||||
|
c[i - 1] = (uint32_t)A;
|
||||||
|
|
||||||
|
if (A >> 32) {
|
||||||
|
subM(key, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Montgomery c[] += 0 * b[] / R % mod
|
||||||
|
*/
|
||||||
|
static void montMulAdd0(const struct vb2_public_key *key,
|
||||||
|
uint32_t *c,
|
||||||
|
const uint32_t *b)
|
||||||
|
{
|
||||||
|
uint32_t d0 = c[0] * key->n0inv;
|
||||||
|
uint64_t B = (uint64_t)d0 * key->n[0] + c[0];
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
for (i = 1; i < key->arrsize; ++i) {
|
||||||
|
B = (B >> 32) + (uint64_t)d0 * key->n[i] + c[i];
|
||||||
|
c[i - 1] = (uint32_t)B;
|
||||||
|
}
|
||||||
|
|
||||||
|
c[i - 1] = B >> 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Montgomery c[] = a[] * b[] / R % mod
|
||||||
|
*/
|
||||||
|
static void montMul(const struct vb2_public_key *key,
|
||||||
|
uint32_t *c,
|
||||||
|
const uint32_t *a,
|
||||||
|
const uint32_t *b)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
for (i = 0; i < key->arrsize; ++i) {
|
||||||
|
c[i] = 0;
|
||||||
|
}
|
||||||
|
for (i = 0; i < key->arrsize; ++i) {
|
||||||
|
montMulAdd(key, c, a[i], b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Montgomery c[] = a[] * 1 / R % key. */
|
||||||
|
static void montMul1(const struct vb2_public_key *key,
|
||||||
|
uint32_t *c,
|
||||||
|
const uint32_t *a)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < key->arrsize; ++i)
|
||||||
|
c[i] = 0;
|
||||||
|
|
||||||
|
montMulAdd(key, c, 1, a);
|
||||||
|
for (i = 1; i < key->arrsize; ++i)
|
||||||
|
montMulAdd0(key, c, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In-place public exponentiation.
|
||||||
|
*
|
||||||
|
* @param key Key to use in signing
|
||||||
|
* @param inout Input and output big-endian byte array
|
||||||
|
* @param workbuf32 Work buffer; caller must verify this is
|
||||||
|
* (3 * key->arrsize) elements long.
|
||||||
|
* @param exp RSA public exponent: either 65537 (F4) or 3
|
||||||
|
*/
|
||||||
|
static void modpow(const struct vb2_public_key *key, uint8_t *inout,
|
||||||
|
uint32_t *workbuf32, int exp)
|
||||||
|
{
|
||||||
|
uint32_t *a = workbuf32;
|
||||||
|
uint32_t *aR = a + key->arrsize;
|
||||||
|
uint32_t *aaR = aR + key->arrsize;
|
||||||
|
uint32_t *aaa = aaR; /* Re-use location. */
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Convert from big endian byte array to little endian word array. */
|
||||||
|
for (i = 0; i < (int)key->arrsize; ++i) {
|
||||||
|
uint32_t tmp =
|
||||||
|
(inout[((key->arrsize - 1 - i) * 4) + 0] << 24) |
|
||||||
|
(inout[((key->arrsize - 1 - i) * 4) + 1] << 16) |
|
||||||
|
(inout[((key->arrsize - 1 - i) * 4) + 2] << 8) |
|
||||||
|
(inout[((key->arrsize - 1 - i) * 4) + 3] << 0);
|
||||||
|
a[i] = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
montMul(key, aR, a, key->rr); /* aR = a * RR / R mod M */
|
||||||
|
if (exp == 3) {
|
||||||
|
montMul(key, aaR, aR, aR); /* aaR = aR * aR / R mod M */
|
||||||
|
montMul(key, a, aaR, aR); /* a = aaR * aR / R mod M */
|
||||||
|
montMul1(key, aaa, a); /* aaa = a * 1 / R mod M */
|
||||||
|
} else {
|
||||||
|
/* Exponent 65537 */
|
||||||
|
for (i = 0; i < 16; i+=2) {
|
||||||
|
montMul(key, aaR, aR, aR); /* aaR = aR * aR / R mod M */
|
||||||
|
montMul(key, aR, aaR, aaR); /* aR = aaR * aaR / R mod M */
|
||||||
|
}
|
||||||
|
montMul(key, aaa, aR, a); /* aaa = aR * a / R mod M */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure aaa < mod; aaa is at most 1x mod too large. */
|
||||||
|
if (vb2_mont_ge(key, aaa)) {
|
||||||
|
subM(key, aaa);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert to bigendian byte array */
|
||||||
|
for (i = (int)key->arrsize - 1; i >= 0; --i) {
|
||||||
|
uint32_t tmp = aaa[i];
|
||||||
|
*inout++ = (uint8_t)(tmp >> 24);
|
||||||
|
*inout++ = (uint8_t)(tmp >> 16);
|
||||||
|
*inout++ = (uint8_t)(tmp >> 8);
|
||||||
|
*inout++ = (uint8_t)(tmp >> 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const uint8_t crypto_to_sig[] = {
|
||||||
|
VB2_SIG_RSA1024,
|
||||||
|
VB2_SIG_RSA1024,
|
||||||
|
VB2_SIG_RSA1024,
|
||||||
|
VB2_SIG_RSA2048,
|
||||||
|
VB2_SIG_RSA2048,
|
||||||
|
VB2_SIG_RSA2048,
|
||||||
|
VB2_SIG_RSA4096,
|
||||||
|
VB2_SIG_RSA4096,
|
||||||
|
VB2_SIG_RSA4096,
|
||||||
|
VB2_SIG_RSA8192,
|
||||||
|
VB2_SIG_RSA8192,
|
||||||
|
VB2_SIG_RSA8192,
|
||||||
|
VB2_SIG_RSA2048_EXP3,
|
||||||
|
VB2_SIG_RSA2048_EXP3,
|
||||||
|
VB2_SIG_RSA2048_EXP3,
|
||||||
|
VB2_SIG_RSA3072_EXP3,
|
||||||
|
VB2_SIG_RSA3072_EXP3,
|
||||||
|
VB2_SIG_RSA3072_EXP3,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert vb2_crypto_algorithm to vb2_signature_algorithm.
|
||||||
|
*
|
||||||
|
* @param algorithm Crypto algorithm (vb2_crypto_algorithm)
|
||||||
|
*
|
||||||
|
* @return The signature algorithm for that crypto algorithm, or
|
||||||
|
* VB2_SIG_INVALID if the crypto algorithm or its corresponding signature
|
||||||
|
* algorithm is invalid or not supported.
|
||||||
|
*/
|
||||||
|
enum vb2_signature_algorithm vb2_crypto_to_signature(uint32_t algorithm)
|
||||||
|
{
|
||||||
|
if (algorithm < ARRAY_SIZE(crypto_to_sig))
|
||||||
|
return crypto_to_sig[algorithm];
|
||||||
|
else
|
||||||
|
return VB2_SIG_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t vb2_rsa_sig_size(enum vb2_signature_algorithm sig_alg)
|
||||||
|
{
|
||||||
|
switch (sig_alg) {
|
||||||
|
case VB2_SIG_RSA1024:
|
||||||
|
return 1024 / 8;
|
||||||
|
case VB2_SIG_RSA2048:
|
||||||
|
case VB2_SIG_RSA2048_EXP3:
|
||||||
|
return 2048 / 8;
|
||||||
|
case VB2_SIG_RSA3072_EXP3:
|
||||||
|
return 3072 / 8;
|
||||||
|
case VB2_SIG_RSA4096:
|
||||||
|
return 4096 / 8;
|
||||||
|
case VB2_SIG_RSA8192:
|
||||||
|
return 8192 / 8;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the exponent used by an RSA algorithm
|
||||||
|
*
|
||||||
|
* @param sig_alg Signature algorithm
|
||||||
|
* @return The exponent to use (3 or 65537(F4)), or 0 if error.
|
||||||
|
*/
|
||||||
|
static uint32_t vb2_rsa_exponent(enum vb2_signature_algorithm sig_alg)
|
||||||
|
{
|
||||||
|
switch (sig_alg) {
|
||||||
|
case VB2_SIG_RSA1024:
|
||||||
|
case VB2_SIG_RSA2048:
|
||||||
|
case VB2_SIG_RSA4096:
|
||||||
|
case VB2_SIG_RSA8192:
|
||||||
|
return 65537;
|
||||||
|
case VB2_SIG_RSA2048_EXP3:
|
||||||
|
case VB2_SIG_RSA3072_EXP3:
|
||||||
|
return 3;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t vb2_packed_key_size(enum vb2_signature_algorithm sig_alg)
|
||||||
|
{
|
||||||
|
uint32_t sig_size = vb2_rsa_sig_size(sig_alg);
|
||||||
|
|
||||||
|
if (!sig_size)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Total size needed by a RSAPublicKey buffer is =
|
||||||
|
* 2 * key_len bytes for the n and rr arrays
|
||||||
|
* + sizeof len + sizeof n0inv.
|
||||||
|
*/
|
||||||
|
return 2 * sig_size + 2 * sizeof(uint32_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PKCS 1.5 padding (from the RSA PKCS#1 v2.1 standard)
|
||||||
|
*
|
||||||
|
* Depending on the RSA key size and hash function, the padding is calculated
|
||||||
|
* as follows:
|
||||||
|
*
|
||||||
|
* 0x00 || 0x01 || PS || 0x00 || T
|
||||||
|
*
|
||||||
|
* T: DER Encoded DigestInfo value which depends on the hash function used.
|
||||||
|
*
|
||||||
|
* SHA-1: (0x)30 21 30 09 06 05 2b 0e 03 02 1a 05 00 04 14 || H.
|
||||||
|
* SHA-256: (0x)30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20 || H.
|
||||||
|
* SHA-512: (0x)30 51 30 0d 06 09 60 86 48 01 65 03 04 02 03 05 00 04 40 || H.
|
||||||
|
*
|
||||||
|
* Length(T) = 35 octets for SHA-1
|
||||||
|
* Length(T) = 51 octets for SHA-256
|
||||||
|
* Length(T) = 83 octets for SHA-512
|
||||||
|
*
|
||||||
|
* PS: octet string consisting of {Length(RSA Key) - Length(T) - 3} 0xFF
|
||||||
|
*/
|
||||||
|
static const uint8_t sha1_tail[] = {
|
||||||
|
0x00,0x30,0x21,0x30,0x09,0x06,0x05,0x2b,
|
||||||
|
0x0e,0x03,0x02,0x1a,0x05,0x00,0x04,0x14
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t sha256_tail[] = {
|
||||||
|
0x00,0x30,0x31,0x30,0x0d,0x06,0x09,0x60,
|
||||||
|
0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,
|
||||||
|
0x05,0x00,0x04,0x20
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t sha512_tail[] = {
|
||||||
|
0x00,0x30,0x51,0x30,0x0d,0x06,0x09,0x60,
|
||||||
|
0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,
|
||||||
|
0x05,0x00,0x04,0x40
|
||||||
|
};
|
||||||
|
|
||||||
|
int vb2_check_padding(const uint8_t *sig, const struct vb2_public_key *key)
|
||||||
|
{
|
||||||
|
/* Determine padding to use depending on the signature type */
|
||||||
|
uint32_t sig_size = vb2_rsa_sig_size(key->sig_alg);
|
||||||
|
uint32_t hash_size = vb2_digest_size(key->hash_alg);
|
||||||
|
uint32_t pad_size = sig_size - hash_size;
|
||||||
|
const uint8_t *tail;
|
||||||
|
uint32_t tail_size;
|
||||||
|
int result = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!sig_size || !hash_size || hash_size > sig_size)
|
||||||
|
return VB2_ERROR_RSA_PADDING_SIZE;
|
||||||
|
|
||||||
|
switch (key->hash_alg) {
|
||||||
|
case VB2_HASH_SHA1:
|
||||||
|
tail = sha1_tail;
|
||||||
|
tail_size = sizeof(sha1_tail);
|
||||||
|
break;
|
||||||
|
case VB2_HASH_SHA256:
|
||||||
|
tail = sha256_tail;
|
||||||
|
tail_size = sizeof(sha256_tail);
|
||||||
|
break;
|
||||||
|
case VB2_HASH_SHA512:
|
||||||
|
tail = sha512_tail;
|
||||||
|
tail_size = sizeof(sha512_tail);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return VB2_ERROR_RSA_PADDING_ALGORITHM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* First 2 bytes are always 0x00 0x01 */
|
||||||
|
result |= *sig++ ^ 0x00;
|
||||||
|
result |= *sig++ ^ 0x01;
|
||||||
|
|
||||||
|
/* Then 0xff bytes until the tail */
|
||||||
|
for (i = 0; i < pad_size - tail_size - 2; i++)
|
||||||
|
result |= *sig++ ^ 0xff;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Then the tail. Even though there are probably no timing issues
|
||||||
|
* here, we use vb2_safe_memcmp() just to be on the safe side.
|
||||||
|
*/
|
||||||
|
result |= vb2_safe_memcmp(sig, tail, tail_size);
|
||||||
|
|
||||||
|
return result ? VB2_ERROR_RSA_PADDING : VB2_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vb2_rsa_verify_digest(const struct vb2_public_key *key,
|
||||||
|
uint8_t *sig,
|
||||||
|
const uint8_t *digest,
|
||||||
|
const struct vb2_workbuf *wb)
|
||||||
|
{
|
||||||
|
struct vb2_workbuf wblocal = *wb;
|
||||||
|
uint32_t *workbuf32;
|
||||||
|
uint32_t key_bytes;
|
||||||
|
int sig_size;
|
||||||
|
int pad_size;
|
||||||
|
int exp;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
if (!key || !sig || !digest)
|
||||||
|
return VB2_ERROR_RSA_VERIFY_PARAM;
|
||||||
|
|
||||||
|
sig_size = vb2_rsa_sig_size(key->sig_alg);
|
||||||
|
exp = vb2_rsa_exponent(key->sig_alg);
|
||||||
|
if (!sig_size || !exp) {
|
||||||
|
VB2_DEBUG("Invalid signature type!\n");
|
||||||
|
return VB2_ERROR_RSA_VERIFY_ALGORITHM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Signature length should be same as key length */
|
||||||
|
key_bytes = key->arrsize * sizeof(uint32_t);
|
||||||
|
if (key_bytes != sig_size) {
|
||||||
|
VB2_DEBUG("Signature is of incorrect length!\n");
|
||||||
|
return VB2_ERROR_RSA_VERIFY_SIG_LEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
workbuf32 = vb2_workbuf_alloc(&wblocal, 3 * key_bytes);
|
||||||
|
if (!workbuf32) {
|
||||||
|
VB2_DEBUG("ERROR - vboot2 work buffer too small!\n");
|
||||||
|
return VB2_ERROR_RSA_VERIFY_WORKBUF;
|
||||||
|
}
|
||||||
|
|
||||||
|
modpow(key, sig, workbuf32, exp);
|
||||||
|
|
||||||
|
vb2_workbuf_free(&wblocal, 3 * key_bytes);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check padding. Only fail immediately if the padding size is bad.
|
||||||
|
* Otherwise, continue on to check the digest to reduce the risk of
|
||||||
|
* timing based attacks.
|
||||||
|
*/
|
||||||
|
rv = vb2_check_padding(sig, key);
|
||||||
|
if (rv == VB2_ERROR_RSA_PADDING_SIZE)
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check digest. Even though there are probably no timing issues here,
|
||||||
|
* use vb2_safe_memcmp() just to be on the safe side. (That's also why
|
||||||
|
* we don't return before this check if the padding check failed.)
|
||||||
|
*/
|
||||||
|
pad_size = sig_size - vb2_digest_size(key->hash_alg);
|
||||||
|
if (vb2_safe_memcmp(sig + pad_size, digest, key_bytes - pad_size)) {
|
||||||
|
VB2_DEBUG("Digest check failed!\n");
|
||||||
|
if (!rv)
|
||||||
|
rv = VB2_ERROR_RSA_VERIFY_DIGEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
126
firmware/coreboot/3rdparty/vboot/firmware/2lib/2secdata.c
vendored
Normal file
126
firmware/coreboot/3rdparty/vboot/firmware/2lib/2secdata.c
vendored
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
/* Copyright (c) 2014 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.
|
||||||
|
*
|
||||||
|
* Secure storage APIs
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "2sysincludes.h"
|
||||||
|
#include "2common.h"
|
||||||
|
#include "2crc8.h"
|
||||||
|
#include "2misc.h"
|
||||||
|
#include "2secdata.h"
|
||||||
|
|
||||||
|
int vb2_secdata_check_crc(const struct vb2_context *ctx)
|
||||||
|
{
|
||||||
|
const struct vb2_secdata *sec =
|
||||||
|
(const struct vb2_secdata *)ctx->secdata;
|
||||||
|
|
||||||
|
/* Verify CRC */
|
||||||
|
if (sec->crc8 != vb2_crc8(sec, offsetof(struct vb2_secdata, crc8)))
|
||||||
|
return VB2_ERROR_SECDATA_CRC;
|
||||||
|
|
||||||
|
/* CRC(<000...00>) is 0, so check version as well (should never be 0) */
|
||||||
|
if (!sec->struct_version)
|
||||||
|
return VB2_ERROR_SECDATA_ZERO;
|
||||||
|
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vb2_secdata_create(struct vb2_context *ctx)
|
||||||
|
{
|
||||||
|
struct vb2_secdata *sec = (struct vb2_secdata *)ctx->secdata;
|
||||||
|
|
||||||
|
/* Clear the entire struct */
|
||||||
|
memset(sec, 0, sizeof(*sec));
|
||||||
|
|
||||||
|
/* Set to current version */
|
||||||
|
sec->struct_version = VB2_SECDATA_VERSION;
|
||||||
|
|
||||||
|
/* Calculate initial CRC */
|
||||||
|
sec->crc8 = vb2_crc8(sec, offsetof(struct vb2_secdata, crc8));
|
||||||
|
ctx->flags |= VB2_CONTEXT_SECDATA_CHANGED;
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vb2_secdata_init(struct vb2_context *ctx)
|
||||||
|
{
|
||||||
|
struct vb2_shared_data *sd = vb2_get_sd(ctx);
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
rv = vb2_secdata_check_crc(ctx);
|
||||||
|
if (rv)
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
/* Set status flag */
|
||||||
|
sd->status |= VB2_SD_STATUS_SECDATA_INIT;
|
||||||
|
/* TODO: unit test for that */
|
||||||
|
|
||||||
|
/* Read this now to make sure crossystem has it even in rec mode. */
|
||||||
|
rv = vb2_secdata_get(ctx, VB2_SECDATA_VERSIONS,
|
||||||
|
&sd->fw_version_secdata);
|
||||||
|
if (rv)
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vb2_secdata_get(struct vb2_context *ctx,
|
||||||
|
enum vb2_secdata_param param,
|
||||||
|
uint32_t *dest)
|
||||||
|
{
|
||||||
|
struct vb2_secdata *sec = (struct vb2_secdata *)ctx->secdata;
|
||||||
|
|
||||||
|
if (!(vb2_get_sd(ctx)->status & VB2_SD_STATUS_SECDATA_INIT))
|
||||||
|
return VB2_ERROR_SECDATA_GET_UNINITIALIZED;
|
||||||
|
|
||||||
|
switch(param) {
|
||||||
|
case VB2_SECDATA_FLAGS:
|
||||||
|
*dest = sec->flags;
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
|
||||||
|
case VB2_SECDATA_VERSIONS:
|
||||||
|
*dest = sec->fw_versions;
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return VB2_ERROR_SECDATA_GET_PARAM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int vb2_secdata_set(struct vb2_context *ctx,
|
||||||
|
enum vb2_secdata_param param,
|
||||||
|
uint32_t value)
|
||||||
|
{
|
||||||
|
struct vb2_secdata *sec = (struct vb2_secdata *)ctx->secdata;
|
||||||
|
uint32_t now;
|
||||||
|
|
||||||
|
if (!(vb2_get_sd(ctx)->status & VB2_SD_STATUS_SECDATA_INIT))
|
||||||
|
return VB2_ERROR_SECDATA_SET_UNINITIALIZED;
|
||||||
|
|
||||||
|
/* If not changing the value, don't regenerate the CRC. */
|
||||||
|
if (vb2_secdata_get(ctx, param, &now) == VB2_SUCCESS && now == value)
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
|
||||||
|
switch(param) {
|
||||||
|
case VB2_SECDATA_FLAGS:
|
||||||
|
/* Make sure flags is in valid range */
|
||||||
|
if (value > 0xff)
|
||||||
|
return VB2_ERROR_SECDATA_SET_FLAGS;
|
||||||
|
|
||||||
|
sec->flags = value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VB2_SECDATA_VERSIONS:
|
||||||
|
sec->fw_versions = value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return VB2_ERROR_SECDATA_SET_PARAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Regenerate CRC */
|
||||||
|
sec->crc8 = vb2_crc8(sec, offsetof(struct vb2_secdata, crc8));
|
||||||
|
ctx->flags |= VB2_CONTEXT_SECDATA_CHANGED;
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
}
|
||||||
112
firmware/coreboot/3rdparty/vboot/firmware/2lib/2secdatak.c
vendored
Normal file
112
firmware/coreboot/3rdparty/vboot/firmware/2lib/2secdatak.c
vendored
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
/* Copyright 2015 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.
|
||||||
|
*
|
||||||
|
* Secure storage APIs - kernel version space
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "2sysincludes.h"
|
||||||
|
#include "2common.h"
|
||||||
|
#include "2crc8.h"
|
||||||
|
#include "2misc.h"
|
||||||
|
#include "2secdata.h"
|
||||||
|
|
||||||
|
int vb2_secdatak_check_crc(const struct vb2_context *ctx)
|
||||||
|
{
|
||||||
|
const struct vb2_secdatak *sec =
|
||||||
|
(const struct vb2_secdatak *)ctx->secdatak;
|
||||||
|
|
||||||
|
/* Verify CRC */
|
||||||
|
if (sec->crc8 != vb2_crc8(sec, offsetof(struct vb2_secdatak, crc8)))
|
||||||
|
return VB2_ERROR_SECDATAK_CRC;
|
||||||
|
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vb2_secdatak_create(struct vb2_context *ctx)
|
||||||
|
{
|
||||||
|
struct vb2_secdatak *sec = (struct vb2_secdatak *)ctx->secdatak;
|
||||||
|
|
||||||
|
/* Clear the entire struct */
|
||||||
|
memset(sec, 0, sizeof(*sec));
|
||||||
|
|
||||||
|
/* Set to current version */
|
||||||
|
sec->struct_version = VB2_SECDATAK_VERSION;
|
||||||
|
|
||||||
|
/* Set UID */
|
||||||
|
sec->uid = VB2_SECDATAK_UID;
|
||||||
|
|
||||||
|
/* Calculate initial CRC */
|
||||||
|
sec->crc8 = vb2_crc8(sec, offsetof(struct vb2_secdatak, crc8));
|
||||||
|
ctx->flags |= VB2_CONTEXT_SECDATAK_CHANGED;
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vb2_secdatak_init(struct vb2_context *ctx)
|
||||||
|
{
|
||||||
|
struct vb2_secdatak *sec = (struct vb2_secdatak *)ctx->secdatak;
|
||||||
|
struct vb2_shared_data *sd = vb2_get_sd(ctx);
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
rv = vb2_secdatak_check_crc(ctx);
|
||||||
|
if (rv)
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
/* Make sure the UID is correct */
|
||||||
|
if (sec->uid != VB2_SECDATAK_UID)
|
||||||
|
return VB2_ERROR_SECDATAK_UID;
|
||||||
|
|
||||||
|
/* Set status flag */
|
||||||
|
sd->status |= VB2_SD_STATUS_SECDATAK_INIT;
|
||||||
|
/* TODO: unit test for that */
|
||||||
|
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vb2_secdatak_get(struct vb2_context *ctx,
|
||||||
|
enum vb2_secdatak_param param,
|
||||||
|
uint32_t *dest)
|
||||||
|
{
|
||||||
|
struct vb2_secdatak *sec = (struct vb2_secdatak *)ctx->secdatak;
|
||||||
|
|
||||||
|
if (!(vb2_get_sd(ctx)->status & VB2_SD_STATUS_SECDATAK_INIT))
|
||||||
|
return VB2_ERROR_SECDATAK_GET_UNINITIALIZED;
|
||||||
|
|
||||||
|
switch(param) {
|
||||||
|
case VB2_SECDATAK_VERSIONS:
|
||||||
|
*dest = sec->kernel_versions;
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return VB2_ERROR_SECDATAK_GET_PARAM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int vb2_secdatak_set(struct vb2_context *ctx,
|
||||||
|
enum vb2_secdatak_param param,
|
||||||
|
uint32_t value)
|
||||||
|
{
|
||||||
|
struct vb2_secdatak *sec = (struct vb2_secdatak *)ctx->secdatak;
|
||||||
|
uint32_t now;
|
||||||
|
|
||||||
|
if (!(vb2_get_sd(ctx)->status & VB2_SD_STATUS_SECDATAK_INIT))
|
||||||
|
return VB2_ERROR_SECDATAK_SET_UNINITIALIZED;
|
||||||
|
|
||||||
|
/* If not changing the value, don't regenerate the CRC. */
|
||||||
|
if (vb2_secdatak_get(ctx, param, &now) == VB2_SUCCESS && now == value)
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
|
||||||
|
switch(param) {
|
||||||
|
case VB2_SECDATAK_VERSIONS:
|
||||||
|
sec->kernel_versions = value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return VB2_ERROR_SECDATAK_SET_PARAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Regenerate CRC */
|
||||||
|
sec->crc8 = vb2_crc8(sec, offsetof(struct vb2_secdatak, crc8));
|
||||||
|
ctx->flags |= VB2_CONTEXT_SECDATAK_CHANGED;
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
}
|
||||||
292
firmware/coreboot/3rdparty/vboot/firmware/2lib/2sha1.c
vendored
Normal file
292
firmware/coreboot/3rdparty/vboot/firmware/2lib/2sha1.c
vendored
Normal file
@@ -0,0 +1,292 @@
|
|||||||
|
/* Copyright (c) 2014 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.
|
||||||
|
*
|
||||||
|
* SHA-1 implementation largely based on libmincrypt in the the Android
|
||||||
|
* Open Source Project (platorm/system/core.git/libmincrypt/sha.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "2sysincludes.h"
|
||||||
|
#include "2common.h"
|
||||||
|
#include "2sha.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some machines lack byteswap.h and endian.h. These have to use the
|
||||||
|
* slower code, even if they're little-endian.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(HAVE_ENDIAN_H) && defined(HAVE_LITTLE_ENDIAN)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This version is about 28% faster than the generic version below,
|
||||||
|
* but assumes little-endianness.
|
||||||
|
*/
|
||||||
|
static uint32_t ror27(uint32_t val)
|
||||||
|
{
|
||||||
|
return (val >> 27) | (val << 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t ror2(uint32_t val)
|
||||||
|
{
|
||||||
|
return (val >> 2) | (val << 30);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t ror31(uint32_t val)
|
||||||
|
{
|
||||||
|
return (val >> 31) | (val << 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sha1_transform(struct vb2_sha1_context *ctx)
|
||||||
|
{
|
||||||
|
/* Note that this array uses 80*4=320 bytes of stack */
|
||||||
|
uint32_t W[80];
|
||||||
|
register uint32_t A, B, C, D, E;
|
||||||
|
int t;
|
||||||
|
|
||||||
|
A = ctx->state[0];
|
||||||
|
B = ctx->state[1];
|
||||||
|
C = ctx->state[2];
|
||||||
|
D = ctx->state[3];
|
||||||
|
E = ctx->state[4];
|
||||||
|
|
||||||
|
#define SHA_F1(A,B,C,D,E,t) \
|
||||||
|
E += ror27(A) + \
|
||||||
|
(W[t] = bswap_32(ctx->buf.w[t])) + \
|
||||||
|
(D^(B&(C^D))) + 0x5A827999; \
|
||||||
|
B = ror2(B);
|
||||||
|
|
||||||
|
for (t = 0; t < 15; t += 5) {
|
||||||
|
SHA_F1(A,B,C,D,E,t + 0);
|
||||||
|
SHA_F1(E,A,B,C,D,t + 1);
|
||||||
|
SHA_F1(D,E,A,B,C,t + 2);
|
||||||
|
SHA_F1(C,D,E,A,B,t + 3);
|
||||||
|
SHA_F1(B,C,D,E,A,t + 4);
|
||||||
|
}
|
||||||
|
SHA_F1(A,B,C,D,E,t + 0); /* 16th one, t == 15 */
|
||||||
|
|
||||||
|
#undef SHA_F1
|
||||||
|
|
||||||
|
#define SHA_F1(A,B,C,D,E,t) \
|
||||||
|
E += ror27(A) + \
|
||||||
|
(W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) + \
|
||||||
|
(D^(B&(C^D))) + 0x5A827999; \
|
||||||
|
B = ror2(B);
|
||||||
|
|
||||||
|
SHA_F1(E,A,B,C,D,t + 1);
|
||||||
|
SHA_F1(D,E,A,B,C,t + 2);
|
||||||
|
SHA_F1(C,D,E,A,B,t + 3);
|
||||||
|
SHA_F1(B,C,D,E,A,t + 4);
|
||||||
|
|
||||||
|
#undef SHA_F1
|
||||||
|
|
||||||
|
#define SHA_F2(A,B,C,D,E,t) \
|
||||||
|
E += ror27(A) + \
|
||||||
|
(W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) + \
|
||||||
|
(B^C^D) + 0x6ED9EBA1; \
|
||||||
|
B = ror2(B);
|
||||||
|
|
||||||
|
for (t = 20; t < 40; t += 5) {
|
||||||
|
SHA_F2(A,B,C,D,E,t + 0);
|
||||||
|
SHA_F2(E,A,B,C,D,t + 1);
|
||||||
|
SHA_F2(D,E,A,B,C,t + 2);
|
||||||
|
SHA_F2(C,D,E,A,B,t + 3);
|
||||||
|
SHA_F2(B,C,D,E,A,t + 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef SHA_F2
|
||||||
|
|
||||||
|
#define SHA_F3(A,B,C,D,E,t) \
|
||||||
|
E += ror27(A) + \
|
||||||
|
(W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) + \
|
||||||
|
((B&C)|(D&(B|C))) + 0x8F1BBCDC; \
|
||||||
|
B = ror2(B);
|
||||||
|
|
||||||
|
for (; t < 60; t += 5) {
|
||||||
|
SHA_F3(A,B,C,D,E,t + 0);
|
||||||
|
SHA_F3(E,A,B,C,D,t + 1);
|
||||||
|
SHA_F3(D,E,A,B,C,t + 2);
|
||||||
|
SHA_F3(C,D,E,A,B,t + 3);
|
||||||
|
SHA_F3(B,C,D,E,A,t + 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef SHA_F3
|
||||||
|
|
||||||
|
#define SHA_F4(A,B,C,D,E,t) \
|
||||||
|
E += ror27(A) + \
|
||||||
|
(W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) + \
|
||||||
|
(B^C^D) + 0xCA62C1D6; \
|
||||||
|
B = ror2(B);
|
||||||
|
|
||||||
|
for (; t < 80; t += 5) {
|
||||||
|
SHA_F4(A,B,C,D,E,t + 0);
|
||||||
|
SHA_F4(E,A,B,C,D,t + 1);
|
||||||
|
SHA_F4(D,E,A,B,C,t + 2);
|
||||||
|
SHA_F4(C,D,E,A,B,t + 3);
|
||||||
|
SHA_F4(B,C,D,E,A,t + 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef SHA_F4
|
||||||
|
|
||||||
|
ctx->state[0] += A;
|
||||||
|
ctx->state[1] += B;
|
||||||
|
ctx->state[2] += C;
|
||||||
|
ctx->state[3] += D;
|
||||||
|
ctx->state[4] += E;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vb2_sha1_update(struct vb2_sha1_context *ctx,
|
||||||
|
const uint8_t *data,
|
||||||
|
uint32_t size)
|
||||||
|
{
|
||||||
|
int i = ctx->count % sizeof(ctx->buf);
|
||||||
|
const uint8_t *p = (const uint8_t*)data;
|
||||||
|
|
||||||
|
ctx->count += size;
|
||||||
|
|
||||||
|
while (size > sizeof(ctx->buf) - i) {
|
||||||
|
memcpy(&ctx->buf.b[i], p, sizeof(ctx->buf) - i);
|
||||||
|
size -= sizeof(ctx->buf) - i;
|
||||||
|
p += sizeof(ctx->buf) - i;
|
||||||
|
sha1_transform(ctx);
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (size--) {
|
||||||
|
ctx->buf.b[i++] = *p++;
|
||||||
|
if (i == sizeof(ctx->buf)) {
|
||||||
|
sha1_transform(ctx);
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *vb2_sha1_finalize(struct vb2_sha1_context *ctx)
|
||||||
|
{
|
||||||
|
uint32_t cnt = ctx->count * 8;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
vb2_sha1_update(ctx, (uint8_t*)"\x80", 1);
|
||||||
|
while ((ctx->count % sizeof(ctx->buf)) != (sizeof(ctx->buf) - 8)) {
|
||||||
|
vb2_sha1_update(ctx, (uint8_t*)"\0", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 8; ++i) {
|
||||||
|
uint8_t tmp = cnt >> ((7 - i) * 8);
|
||||||
|
vb2_sha1_update(ctx, &tmp, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 5; i++) {
|
||||||
|
ctx->buf.w[i] = bswap_32(ctx->state[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx->buf.b;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* #if defined(HAVE_ENDIAN_H) && defined(HAVE_LITTLE_ENDIAN) */
|
||||||
|
|
||||||
|
#define rol(bits, value) (((value) << (bits)) | ((value) >> (32 - (bits))))
|
||||||
|
|
||||||
|
static void sha1_transform(struct vb2_sha1_context *ctx)
|
||||||
|
{
|
||||||
|
/* Note that this array uses 80*4=320 bytes of stack */
|
||||||
|
uint32_t W[80];
|
||||||
|
uint32_t A, B, C, D, E;
|
||||||
|
uint8_t *p = ctx->buf;
|
||||||
|
int t;
|
||||||
|
|
||||||
|
for(t = 0; t < 16; ++t) {
|
||||||
|
uint32_t tmp = *p++ << 24;
|
||||||
|
tmp |= *p++ << 16;
|
||||||
|
tmp |= *p++ << 8;
|
||||||
|
tmp |= *p++;
|
||||||
|
W[t] = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(; t < 80; t++) {
|
||||||
|
W[t] = rol(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
|
||||||
|
}
|
||||||
|
|
||||||
|
A = ctx->state[0];
|
||||||
|
B = ctx->state[1];
|
||||||
|
C = ctx->state[2];
|
||||||
|
D = ctx->state[3];
|
||||||
|
E = ctx->state[4];
|
||||||
|
|
||||||
|
for(t = 0; t < 80; t++) {
|
||||||
|
uint32_t tmp = rol(5,A) + E + W[t];
|
||||||
|
|
||||||
|
if (t < 20)
|
||||||
|
tmp += (D^(B&(C^D))) + 0x5A827999;
|
||||||
|
else if ( t < 40)
|
||||||
|
tmp += (B^C^D) + 0x6ED9EBA1;
|
||||||
|
else if ( t < 60)
|
||||||
|
tmp += ((B&C)|(D&(B|C))) + 0x8F1BBCDC;
|
||||||
|
else
|
||||||
|
tmp += (B^C^D) + 0xCA62C1D6;
|
||||||
|
|
||||||
|
E = D;
|
||||||
|
D = C;
|
||||||
|
C = rol(30,B);
|
||||||
|
B = A;
|
||||||
|
A = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->state[0] += A;
|
||||||
|
ctx->state[1] += B;
|
||||||
|
ctx->state[2] += C;
|
||||||
|
ctx->state[3] += D;
|
||||||
|
ctx->state[4] += E;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vb2_sha1_update(struct vb2_sha1_context *ctx,
|
||||||
|
const uint8_t *data,
|
||||||
|
uint32_t size)
|
||||||
|
{
|
||||||
|
int i = (int)(ctx->count % sizeof(ctx->buf));
|
||||||
|
const uint8_t* p = (const uint8_t*) data;
|
||||||
|
|
||||||
|
ctx->count += size;
|
||||||
|
|
||||||
|
while (size--) {
|
||||||
|
ctx->buf[i++] = *p++;
|
||||||
|
if (i == sizeof(ctx->buf)) {
|
||||||
|
sha1_transform(ctx);
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void vb2_sha1_finalize(struct vb2_sha1_context *ctx, uint8_t *digest)
|
||||||
|
{
|
||||||
|
uint32_t cnt = ctx->count << 3;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
vb2_sha1_update(ctx, (uint8_t*)"\x80", 1);
|
||||||
|
while ((ctx->count % sizeof(ctx->buf)) != (sizeof(ctx->buf) - 8)) {
|
||||||
|
vb2_sha1_update(ctx, (uint8_t*)"\0", 1);
|
||||||
|
}
|
||||||
|
for (i = 0; i < 8; ++i) {
|
||||||
|
uint8_t tmp = (uint8_t)((uint64_t)cnt >> ((7 - i) * 8));
|
||||||
|
vb2_sha1_update(ctx, &tmp, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 5; i++) {
|
||||||
|
uint32_t tmp = ctx->state[i];
|
||||||
|
*digest++ = (uint8_t)(tmp >> 24);
|
||||||
|
*digest++ = (uint8_t)(tmp >> 16);
|
||||||
|
*digest++ = (uint8_t)(tmp >> 8);
|
||||||
|
*digest++ = (uint8_t)(tmp >> 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* endianness */
|
||||||
|
|
||||||
|
void vb2_sha1_init(struct vb2_sha1_context *ctx)
|
||||||
|
{
|
||||||
|
ctx->state[0] = 0x67452301;
|
||||||
|
ctx->state[1] = 0xefcdab89;
|
||||||
|
ctx->state[2] = 0x98badcfe;
|
||||||
|
ctx->state[3] = 0x10325476;
|
||||||
|
ctx->state[4] = 0xc3d2e1f0;
|
||||||
|
ctx->count = 0;
|
||||||
|
}
|
||||||
334
firmware/coreboot/3rdparty/vboot/firmware/2lib/2sha256.c
vendored
Normal file
334
firmware/coreboot/3rdparty/vboot/firmware/2lib/2sha256.c
vendored
Normal file
@@ -0,0 +1,334 @@
|
|||||||
|
/* SHA-256 and SHA-512 implementation based on code by Oliver Gay
|
||||||
|
* <olivier.gay@a3.epfl.ch> under a BSD-style license. See below.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FIPS 180-2 SHA-224/256/384/512 implementation
|
||||||
|
* Last update: 02/02/2007
|
||||||
|
* Issue date: 04/30/2005
|
||||||
|
*
|
||||||
|
* Copyright (C) 2005, 2007 Olivier Gay <olivier.gay@a3.epfl.ch>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the project nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "2sysincludes.h"
|
||||||
|
#include "2common.h"
|
||||||
|
#include "2sha.h"
|
||||||
|
|
||||||
|
#define SHFR(x, n) (x >> n)
|
||||||
|
#define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
|
||||||
|
#define ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n)))
|
||||||
|
#define CH(x, y, z) ((x & y) ^ (~x & z))
|
||||||
|
#define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
|
||||||
|
|
||||||
|
#define SHA256_F1(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
|
||||||
|
#define SHA256_F2(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
|
||||||
|
#define SHA256_F3(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHFR(x, 3))
|
||||||
|
#define SHA256_F4(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10))
|
||||||
|
|
||||||
|
#define UNPACK32(x, str) \
|
||||||
|
{ \
|
||||||
|
*((str) + 3) = (uint8_t) ((x) ); \
|
||||||
|
*((str) + 2) = (uint8_t) ((x) >> 8); \
|
||||||
|
*((str) + 1) = (uint8_t) ((x) >> 16); \
|
||||||
|
*((str) + 0) = (uint8_t) ((x) >> 24); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PACK32(str, x) \
|
||||||
|
{ \
|
||||||
|
*(x) = ((uint32_t) *((str) + 3) ) \
|
||||||
|
| ((uint32_t) *((str) + 2) << 8) \
|
||||||
|
| ((uint32_t) *((str) + 1) << 16) \
|
||||||
|
| ((uint32_t) *((str) + 0) << 24); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Macros used for loops unrolling */
|
||||||
|
|
||||||
|
#define SHA256_SCR(i) \
|
||||||
|
{ \
|
||||||
|
w[i] = SHA256_F4(w[i - 2]) + w[i - 7] \
|
||||||
|
+ SHA256_F3(w[i - 15]) + w[i - 16]; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SHA256_EXP(a, b, c, d, e, f, g, h, j) \
|
||||||
|
{ \
|
||||||
|
t1 = wv[h] + SHA256_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) \
|
||||||
|
+ sha256_k[j] + w[j]; \
|
||||||
|
t2 = SHA256_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]); \
|
||||||
|
wv[d] += t1; \
|
||||||
|
wv[h] = t1 + t2; \
|
||||||
|
}
|
||||||
|
|
||||||
|
static const uint32_t sha256_h0[8] = {
|
||||||
|
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
|
||||||
|
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint32_t sha256_k[64] = {
|
||||||
|
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
|
||||||
|
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
||||||
|
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
||||||
|
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
||||||
|
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
|
||||||
|
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||||
|
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
|
||||||
|
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
||||||
|
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
||||||
|
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
||||||
|
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
|
||||||
|
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||||
|
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
|
||||||
|
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
||||||
|
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
||||||
|
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
||||||
|
};
|
||||||
|
|
||||||
|
/* SHA-256 implementation */
|
||||||
|
void vb2_sha256_init(struct vb2_sha256_context *ctx)
|
||||||
|
{
|
||||||
|
#ifndef UNROLL_LOOPS
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
ctx->h[i] = sha256_h0[i];
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
ctx->h[0] = sha256_h0[0]; ctx->h[1] = sha256_h0[1];
|
||||||
|
ctx->h[2] = sha256_h0[2]; ctx->h[3] = sha256_h0[3];
|
||||||
|
ctx->h[4] = sha256_h0[4]; ctx->h[5] = sha256_h0[5];
|
||||||
|
ctx->h[6] = sha256_h0[6]; ctx->h[7] = sha256_h0[7];
|
||||||
|
#endif /* !UNROLL_LOOPS */
|
||||||
|
|
||||||
|
ctx->size = 0;
|
||||||
|
ctx->total_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vb2_sha256_transform(struct vb2_sha256_context *ctx,
|
||||||
|
const uint8_t *message,
|
||||||
|
unsigned int block_nb)
|
||||||
|
{
|
||||||
|
/* Note that these arrays use 72*4=288 bytes of stack */
|
||||||
|
uint32_t w[64];
|
||||||
|
uint32_t wv[8];
|
||||||
|
uint32_t t1, t2;
|
||||||
|
const unsigned char *sub_block;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
#ifndef UNROLL_LOOPS
|
||||||
|
int j;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (i = 0; i < (int) block_nb; i++) {
|
||||||
|
sub_block = message + (i << 6);
|
||||||
|
|
||||||
|
#ifndef UNROLL_LOOPS
|
||||||
|
for (j = 0; j < 16; j++) {
|
||||||
|
PACK32(&sub_block[j << 2], &w[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 16; j < 64; j++) {
|
||||||
|
SHA256_SCR(j);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 0; j < 8; j++) {
|
||||||
|
wv[j] = ctx->h[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 0; j < 64; j++) {
|
||||||
|
t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6])
|
||||||
|
+ sha256_k[j] + w[j];
|
||||||
|
t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
|
||||||
|
wv[7] = wv[6];
|
||||||
|
wv[6] = wv[5];
|
||||||
|
wv[5] = wv[4];
|
||||||
|
wv[4] = wv[3] + t1;
|
||||||
|
wv[3] = wv[2];
|
||||||
|
wv[2] = wv[1];
|
||||||
|
wv[1] = wv[0];
|
||||||
|
wv[0] = t1 + t2;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 0; j < 8; j++) {
|
||||||
|
ctx->h[j] += wv[j];
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
PACK32(&sub_block[ 0], &w[ 0]); PACK32(&sub_block[ 4], &w[ 1]);
|
||||||
|
PACK32(&sub_block[ 8], &w[ 2]); PACK32(&sub_block[12], &w[ 3]);
|
||||||
|
PACK32(&sub_block[16], &w[ 4]); PACK32(&sub_block[20], &w[ 5]);
|
||||||
|
PACK32(&sub_block[24], &w[ 6]); PACK32(&sub_block[28], &w[ 7]);
|
||||||
|
PACK32(&sub_block[32], &w[ 8]); PACK32(&sub_block[36], &w[ 9]);
|
||||||
|
PACK32(&sub_block[40], &w[10]); PACK32(&sub_block[44], &w[11]);
|
||||||
|
PACK32(&sub_block[48], &w[12]); PACK32(&sub_block[52], &w[13]);
|
||||||
|
PACK32(&sub_block[56], &w[14]); PACK32(&sub_block[60], &w[15]);
|
||||||
|
|
||||||
|
SHA256_SCR(16); SHA256_SCR(17); SHA256_SCR(18); SHA256_SCR(19);
|
||||||
|
SHA256_SCR(20); SHA256_SCR(21); SHA256_SCR(22); SHA256_SCR(23);
|
||||||
|
SHA256_SCR(24); SHA256_SCR(25); SHA256_SCR(26); SHA256_SCR(27);
|
||||||
|
SHA256_SCR(28); SHA256_SCR(29); SHA256_SCR(30); SHA256_SCR(31);
|
||||||
|
SHA256_SCR(32); SHA256_SCR(33); SHA256_SCR(34); SHA256_SCR(35);
|
||||||
|
SHA256_SCR(36); SHA256_SCR(37); SHA256_SCR(38); SHA256_SCR(39);
|
||||||
|
SHA256_SCR(40); SHA256_SCR(41); SHA256_SCR(42); SHA256_SCR(43);
|
||||||
|
SHA256_SCR(44); SHA256_SCR(45); SHA256_SCR(46); SHA256_SCR(47);
|
||||||
|
SHA256_SCR(48); SHA256_SCR(49); SHA256_SCR(50); SHA256_SCR(51);
|
||||||
|
SHA256_SCR(52); SHA256_SCR(53); SHA256_SCR(54); SHA256_SCR(55);
|
||||||
|
SHA256_SCR(56); SHA256_SCR(57); SHA256_SCR(58); SHA256_SCR(59);
|
||||||
|
SHA256_SCR(60); SHA256_SCR(61); SHA256_SCR(62); SHA256_SCR(63);
|
||||||
|
|
||||||
|
wv[0] = ctx->h[0]; wv[1] = ctx->h[1];
|
||||||
|
wv[2] = ctx->h[2]; wv[3] = ctx->h[3];
|
||||||
|
wv[4] = ctx->h[4]; wv[5] = ctx->h[5];
|
||||||
|
wv[6] = ctx->h[6]; wv[7] = ctx->h[7];
|
||||||
|
|
||||||
|
SHA256_EXP(0,1,2,3,4,5,6,7, 0); SHA256_EXP(7,0,1,2,3,4,5,6, 1);
|
||||||
|
SHA256_EXP(6,7,0,1,2,3,4,5, 2); SHA256_EXP(5,6,7,0,1,2,3,4, 3);
|
||||||
|
SHA256_EXP(4,5,6,7,0,1,2,3, 4); SHA256_EXP(3,4,5,6,7,0,1,2, 5);
|
||||||
|
SHA256_EXP(2,3,4,5,6,7,0,1, 6); SHA256_EXP(1,2,3,4,5,6,7,0, 7);
|
||||||
|
SHA256_EXP(0,1,2,3,4,5,6,7, 8); SHA256_EXP(7,0,1,2,3,4,5,6, 9);
|
||||||
|
SHA256_EXP(6,7,0,1,2,3,4,5,10); SHA256_EXP(5,6,7,0,1,2,3,4,11);
|
||||||
|
SHA256_EXP(4,5,6,7,0,1,2,3,12); SHA256_EXP(3,4,5,6,7,0,1,2,13);
|
||||||
|
SHA256_EXP(2,3,4,5,6,7,0,1,14); SHA256_EXP(1,2,3,4,5,6,7,0,15);
|
||||||
|
SHA256_EXP(0,1,2,3,4,5,6,7,16); SHA256_EXP(7,0,1,2,3,4,5,6,17);
|
||||||
|
SHA256_EXP(6,7,0,1,2,3,4,5,18); SHA256_EXP(5,6,7,0,1,2,3,4,19);
|
||||||
|
SHA256_EXP(4,5,6,7,0,1,2,3,20); SHA256_EXP(3,4,5,6,7,0,1,2,21);
|
||||||
|
SHA256_EXP(2,3,4,5,6,7,0,1,22); SHA256_EXP(1,2,3,4,5,6,7,0,23);
|
||||||
|
SHA256_EXP(0,1,2,3,4,5,6,7,24); SHA256_EXP(7,0,1,2,3,4,5,6,25);
|
||||||
|
SHA256_EXP(6,7,0,1,2,3,4,5,26); SHA256_EXP(5,6,7,0,1,2,3,4,27);
|
||||||
|
SHA256_EXP(4,5,6,7,0,1,2,3,28); SHA256_EXP(3,4,5,6,7,0,1,2,29);
|
||||||
|
SHA256_EXP(2,3,4,5,6,7,0,1,30); SHA256_EXP(1,2,3,4,5,6,7,0,31);
|
||||||
|
SHA256_EXP(0,1,2,3,4,5,6,7,32); SHA256_EXP(7,0,1,2,3,4,5,6,33);
|
||||||
|
SHA256_EXP(6,7,0,1,2,3,4,5,34); SHA256_EXP(5,6,7,0,1,2,3,4,35);
|
||||||
|
SHA256_EXP(4,5,6,7,0,1,2,3,36); SHA256_EXP(3,4,5,6,7,0,1,2,37);
|
||||||
|
SHA256_EXP(2,3,4,5,6,7,0,1,38); SHA256_EXP(1,2,3,4,5,6,7,0,39);
|
||||||
|
SHA256_EXP(0,1,2,3,4,5,6,7,40); SHA256_EXP(7,0,1,2,3,4,5,6,41);
|
||||||
|
SHA256_EXP(6,7,0,1,2,3,4,5,42); SHA256_EXP(5,6,7,0,1,2,3,4,43);
|
||||||
|
SHA256_EXP(4,5,6,7,0,1,2,3,44); SHA256_EXP(3,4,5,6,7,0,1,2,45);
|
||||||
|
SHA256_EXP(2,3,4,5,6,7,0,1,46); SHA256_EXP(1,2,3,4,5,6,7,0,47);
|
||||||
|
SHA256_EXP(0,1,2,3,4,5,6,7,48); SHA256_EXP(7,0,1,2,3,4,5,6,49);
|
||||||
|
SHA256_EXP(6,7,0,1,2,3,4,5,50); SHA256_EXP(5,6,7,0,1,2,3,4,51);
|
||||||
|
SHA256_EXP(4,5,6,7,0,1,2,3,52); SHA256_EXP(3,4,5,6,7,0,1,2,53);
|
||||||
|
SHA256_EXP(2,3,4,5,6,7,0,1,54); SHA256_EXP(1,2,3,4,5,6,7,0,55);
|
||||||
|
SHA256_EXP(0,1,2,3,4,5,6,7,56); SHA256_EXP(7,0,1,2,3,4,5,6,57);
|
||||||
|
SHA256_EXP(6,7,0,1,2,3,4,5,58); SHA256_EXP(5,6,7,0,1,2,3,4,59);
|
||||||
|
SHA256_EXP(4,5,6,7,0,1,2,3,60); SHA256_EXP(3,4,5,6,7,0,1,2,61);
|
||||||
|
SHA256_EXP(2,3,4,5,6,7,0,1,62); SHA256_EXP(1,2,3,4,5,6,7,0,63);
|
||||||
|
|
||||||
|
ctx->h[0] += wv[0]; ctx->h[1] += wv[1];
|
||||||
|
ctx->h[2] += wv[2]; ctx->h[3] += wv[3];
|
||||||
|
ctx->h[4] += wv[4]; ctx->h[5] += wv[5];
|
||||||
|
ctx->h[6] += wv[6]; ctx->h[7] += wv[7];
|
||||||
|
#endif /* !UNROLL_LOOPS */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void vb2_sha256_update(struct vb2_sha256_context *ctx,
|
||||||
|
const uint8_t *data,
|
||||||
|
uint32_t size)
|
||||||
|
{
|
||||||
|
unsigned int block_nb;
|
||||||
|
unsigned int new_size, rem_size, tmp_size;
|
||||||
|
const uint8_t *shifted_data;
|
||||||
|
|
||||||
|
tmp_size = VB2_SHA256_BLOCK_SIZE - ctx->size;
|
||||||
|
rem_size = size < tmp_size ? size : tmp_size;
|
||||||
|
|
||||||
|
memcpy(&ctx->block[ctx->size], data, rem_size);
|
||||||
|
|
||||||
|
if (ctx->size + size < VB2_SHA256_BLOCK_SIZE) {
|
||||||
|
ctx->size += size;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_size = size - rem_size;
|
||||||
|
block_nb = new_size / VB2_SHA256_BLOCK_SIZE;
|
||||||
|
|
||||||
|
shifted_data = data + rem_size;
|
||||||
|
|
||||||
|
vb2_sha256_transform(ctx, ctx->block, 1);
|
||||||
|
vb2_sha256_transform(ctx, shifted_data, block_nb);
|
||||||
|
|
||||||
|
rem_size = new_size % VB2_SHA256_BLOCK_SIZE;
|
||||||
|
|
||||||
|
memcpy(ctx->block, &shifted_data[block_nb << 6],
|
||||||
|
rem_size);
|
||||||
|
|
||||||
|
ctx->size = rem_size;
|
||||||
|
ctx->total_size += (block_nb + 1) << 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vb2_sha256_finalize(struct vb2_sha256_context *ctx, uint8_t *digest)
|
||||||
|
{
|
||||||
|
unsigned int block_nb;
|
||||||
|
unsigned int pm_size;
|
||||||
|
unsigned int size_b;
|
||||||
|
#ifndef UNROLL_LOOPS
|
||||||
|
int i;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
block_nb = (1 + ((VB2_SHA256_BLOCK_SIZE - 9)
|
||||||
|
< (ctx->size % VB2_SHA256_BLOCK_SIZE)));
|
||||||
|
|
||||||
|
size_b = (ctx->total_size + ctx->size) << 3;
|
||||||
|
pm_size = block_nb << 6;
|
||||||
|
|
||||||
|
memset(ctx->block + ctx->size, 0, pm_size - ctx->size);
|
||||||
|
ctx->block[ctx->size] = 0x80;
|
||||||
|
UNPACK32(size_b, ctx->block + pm_size - 4);
|
||||||
|
|
||||||
|
vb2_sha256_transform(ctx, ctx->block, block_nb);
|
||||||
|
|
||||||
|
#ifndef UNROLL_LOOPS
|
||||||
|
for (i = 0 ; i < 8; i++) {
|
||||||
|
UNPACK32(ctx->h[i], &digest[i << 2]);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
UNPACK32(ctx->h[0], &digest[ 0]);
|
||||||
|
UNPACK32(ctx->h[1], &digest[ 4]);
|
||||||
|
UNPACK32(ctx->h[2], &digest[ 8]);
|
||||||
|
UNPACK32(ctx->h[3], &digest[12]);
|
||||||
|
UNPACK32(ctx->h[4], &digest[16]);
|
||||||
|
UNPACK32(ctx->h[5], &digest[20]);
|
||||||
|
UNPACK32(ctx->h[6], &digest[24]);
|
||||||
|
UNPACK32(ctx->h[7], &digest[28]);
|
||||||
|
#endif /* !UNROLL_LOOPS */
|
||||||
|
}
|
||||||
|
|
||||||
|
void vb2_sha256_extend(const uint8_t *from, const uint8_t *by, uint8_t *to)
|
||||||
|
{
|
||||||
|
struct vb2_sha256_context dc;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
PACK32(from, &dc.h[i]);
|
||||||
|
from += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
vb2_sha256_transform(&dc, by, 1);
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
UNPACK32(dc.h[i], to);
|
||||||
|
to += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
346
firmware/coreboot/3rdparty/vboot/firmware/2lib/2sha512.c
vendored
Normal file
346
firmware/coreboot/3rdparty/vboot/firmware/2lib/2sha512.c
vendored
Normal file
@@ -0,0 +1,346 @@
|
|||||||
|
/* SHA-256 and SHA-512 implementation based on code by Oliver Gay
|
||||||
|
* <olivier.gay@a3.epfl.ch> under a BSD-style license. See below.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FIPS 180-2 SHA-224/256/384/512 implementation
|
||||||
|
* Last update: 02/02/2007
|
||||||
|
* Issue date: 04/30/2005
|
||||||
|
*
|
||||||
|
* Copyright (C) 2005, 2007 Olivier Gay <olivier.gay@a3.epfl.ch>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the project nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "2sysincludes.h"
|
||||||
|
#include "2common.h"
|
||||||
|
#include "2sha.h"
|
||||||
|
|
||||||
|
#define SHFR(x, n) (x >> n)
|
||||||
|
#define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
|
||||||
|
#define ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n)))
|
||||||
|
#define CH(x, y, z) ((x & y) ^ (~x & z))
|
||||||
|
#define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
|
||||||
|
|
||||||
|
#define SHA512_F1(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39))
|
||||||
|
#define SHA512_F2(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41))
|
||||||
|
#define SHA512_F3(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHFR(x, 7))
|
||||||
|
#define SHA512_F4(x) (ROTR(x, 19) ^ ROTR(x, 61) ^ SHFR(x, 6))
|
||||||
|
|
||||||
|
#define UNPACK32(x, str) \
|
||||||
|
{ \
|
||||||
|
*((str) + 3) = (uint8_t) ((x) ); \
|
||||||
|
*((str) + 2) = (uint8_t) ((x) >> 8); \
|
||||||
|
*((str) + 1) = (uint8_t) ((x) >> 16); \
|
||||||
|
*((str) + 0) = (uint8_t) ((x) >> 24); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define UNPACK64(x, str) \
|
||||||
|
{ \
|
||||||
|
*((str) + 7) = (uint8_t) x; \
|
||||||
|
*((str) + 6) = (uint8_t) ((uint64_t)x >> 8); \
|
||||||
|
*((str) + 5) = (uint8_t) ((uint64_t)x >> 16); \
|
||||||
|
*((str) + 4) = (uint8_t) ((uint64_t)x >> 24); \
|
||||||
|
*((str) + 3) = (uint8_t) ((uint64_t)x >> 32); \
|
||||||
|
*((str) + 2) = (uint8_t) ((uint64_t)x >> 40); \
|
||||||
|
*((str) + 1) = (uint8_t) ((uint64_t)x >> 48); \
|
||||||
|
*((str) + 0) = (uint8_t) ((uint64_t)x >> 56); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PACK64(str, x) \
|
||||||
|
{ \
|
||||||
|
*(x) = ((uint64_t) *((str) + 7) ) \
|
||||||
|
| ((uint64_t) *((str) + 6) << 8) \
|
||||||
|
| ((uint64_t) *((str) + 5) << 16) \
|
||||||
|
| ((uint64_t) *((str) + 4) << 24) \
|
||||||
|
| ((uint64_t) *((str) + 3) << 32) \
|
||||||
|
| ((uint64_t) *((str) + 2) << 40) \
|
||||||
|
| ((uint64_t) *((str) + 1) << 48) \
|
||||||
|
| ((uint64_t) *((str) + 0) << 56); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Macros used for loops unrolling */
|
||||||
|
|
||||||
|
#define SHA512_SCR(i) \
|
||||||
|
{ \
|
||||||
|
w[i] = SHA512_F4(w[i - 2]) + w[i - 7] \
|
||||||
|
+ SHA512_F3(w[i - 15]) + w[i - 16]; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SHA512_EXP(a, b, c, d, e, f, g ,h, j) \
|
||||||
|
{ \
|
||||||
|
t1 = wv[h] + SHA512_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) \
|
||||||
|
+ sha512_k[j] + w[j]; \
|
||||||
|
t2 = SHA512_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]); \
|
||||||
|
wv[d] += t1; \
|
||||||
|
wv[h] = t1 + t2; \
|
||||||
|
}
|
||||||
|
|
||||||
|
static const uint64_t sha512_h0[8] = {
|
||||||
|
0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
|
||||||
|
0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
|
||||||
|
0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
|
||||||
|
0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint64_t sha512_k[80] = {
|
||||||
|
0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
|
||||||
|
0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
|
||||||
|
0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
|
||||||
|
0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
|
||||||
|
0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
|
||||||
|
0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
|
||||||
|
0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
|
||||||
|
0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
|
||||||
|
0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
|
||||||
|
0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
|
||||||
|
0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
|
||||||
|
0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
|
||||||
|
0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
|
||||||
|
0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
|
||||||
|
0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
|
||||||
|
0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
|
||||||
|
0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
|
||||||
|
0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
|
||||||
|
0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
|
||||||
|
0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
|
||||||
|
0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
|
||||||
|
0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
|
||||||
|
0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
|
||||||
|
0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
|
||||||
|
0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
|
||||||
|
0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
|
||||||
|
0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
|
||||||
|
0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
|
||||||
|
0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
|
||||||
|
0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
|
||||||
|
0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
|
||||||
|
0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
|
||||||
|
0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
|
||||||
|
0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
|
||||||
|
0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
|
||||||
|
0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
|
||||||
|
0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
|
||||||
|
0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
|
||||||
|
0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
|
||||||
|
0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
|
||||||
|
};
|
||||||
|
|
||||||
|
/* SHA-512 implementation */
|
||||||
|
|
||||||
|
void vb2_sha512_init(struct vb2_sha512_context *ctx)
|
||||||
|
{
|
||||||
|
#ifdef UNROLL_LOOPS_SHA512
|
||||||
|
ctx->h[0] = sha512_h0[0]; ctx->h[1] = sha512_h0[1];
|
||||||
|
ctx->h[2] = sha512_h0[2]; ctx->h[3] = sha512_h0[3];
|
||||||
|
ctx->h[4] = sha512_h0[4]; ctx->h[5] = sha512_h0[5];
|
||||||
|
ctx->h[6] = sha512_h0[6]; ctx->h[7] = sha512_h0[7];
|
||||||
|
#else
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
ctx->h[i] = sha512_h0[i];
|
||||||
|
#endif /* UNROLL_LOOPS_SHA512 */
|
||||||
|
|
||||||
|
ctx->size = 0;
|
||||||
|
ctx->total_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vb2_sha512_transform(struct vb2_sha512_context *ctx,
|
||||||
|
const uint8_t *message,
|
||||||
|
unsigned int block_nb)
|
||||||
|
{
|
||||||
|
/* Note that these arrays use 88*8=704 bytes of stack */
|
||||||
|
uint64_t w[80];
|
||||||
|
uint64_t wv[8];
|
||||||
|
uint64_t t1, t2;
|
||||||
|
const uint8_t *sub_block;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
for (i = 0; i < (int) block_nb; i++) {
|
||||||
|
sub_block = message + (i << 7);
|
||||||
|
|
||||||
|
#ifdef UNROLL_LOOPS_SHA512
|
||||||
|
PACK64(&sub_block[ 0], &w[ 0]);
|
||||||
|
PACK64(&sub_block[ 8], &w[ 1]);
|
||||||
|
PACK64(&sub_block[ 16], &w[ 2]);
|
||||||
|
PACK64(&sub_block[ 24], &w[ 3]);
|
||||||
|
PACK64(&sub_block[ 32], &w[ 4]);
|
||||||
|
PACK64(&sub_block[ 40], &w[ 5]);
|
||||||
|
PACK64(&sub_block[ 48], &w[ 6]);
|
||||||
|
PACK64(&sub_block[ 56], &w[ 7]);
|
||||||
|
PACK64(&sub_block[ 64], &w[ 8]);
|
||||||
|
PACK64(&sub_block[ 72], &w[ 9]);
|
||||||
|
PACK64(&sub_block[ 80], &w[10]);
|
||||||
|
PACK64(&sub_block[ 88], &w[11]);
|
||||||
|
PACK64(&sub_block[ 96], &w[12]);
|
||||||
|
PACK64(&sub_block[104], &w[13]);
|
||||||
|
PACK64(&sub_block[112], &w[14]);
|
||||||
|
PACK64(&sub_block[120], &w[15]);
|
||||||
|
|
||||||
|
SHA512_SCR(16); SHA512_SCR(17); SHA512_SCR(18); SHA512_SCR(19);
|
||||||
|
SHA512_SCR(20); SHA512_SCR(21); SHA512_SCR(22); SHA512_SCR(23);
|
||||||
|
SHA512_SCR(24); SHA512_SCR(25); SHA512_SCR(26); SHA512_SCR(27);
|
||||||
|
SHA512_SCR(28); SHA512_SCR(29); SHA512_SCR(30); SHA512_SCR(31);
|
||||||
|
SHA512_SCR(32); SHA512_SCR(33); SHA512_SCR(34); SHA512_SCR(35);
|
||||||
|
SHA512_SCR(36); SHA512_SCR(37); SHA512_SCR(38); SHA512_SCR(39);
|
||||||
|
SHA512_SCR(40); SHA512_SCR(41); SHA512_SCR(42); SHA512_SCR(43);
|
||||||
|
SHA512_SCR(44); SHA512_SCR(45); SHA512_SCR(46); SHA512_SCR(47);
|
||||||
|
SHA512_SCR(48); SHA512_SCR(49); SHA512_SCR(50); SHA512_SCR(51);
|
||||||
|
SHA512_SCR(52); SHA512_SCR(53); SHA512_SCR(54); SHA512_SCR(55);
|
||||||
|
SHA512_SCR(56); SHA512_SCR(57); SHA512_SCR(58); SHA512_SCR(59);
|
||||||
|
SHA512_SCR(60); SHA512_SCR(61); SHA512_SCR(62); SHA512_SCR(63);
|
||||||
|
SHA512_SCR(64); SHA512_SCR(65); SHA512_SCR(66); SHA512_SCR(67);
|
||||||
|
SHA512_SCR(68); SHA512_SCR(69); SHA512_SCR(70); SHA512_SCR(71);
|
||||||
|
SHA512_SCR(72); SHA512_SCR(73); SHA512_SCR(74); SHA512_SCR(75);
|
||||||
|
SHA512_SCR(76); SHA512_SCR(77); SHA512_SCR(78); SHA512_SCR(79);
|
||||||
|
|
||||||
|
wv[0] = ctx->h[0]; wv[1] = ctx->h[1];
|
||||||
|
wv[2] = ctx->h[2]; wv[3] = ctx->h[3];
|
||||||
|
wv[4] = ctx->h[4]; wv[5] = ctx->h[5];
|
||||||
|
wv[6] = ctx->h[6]; wv[7] = ctx->h[7];
|
||||||
|
|
||||||
|
j = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
SHA512_EXP(0,1,2,3,4,5,6,7,j); j++;
|
||||||
|
SHA512_EXP(7,0,1,2,3,4,5,6,j); j++;
|
||||||
|
SHA512_EXP(6,7,0,1,2,3,4,5,j); j++;
|
||||||
|
SHA512_EXP(5,6,7,0,1,2,3,4,j); j++;
|
||||||
|
SHA512_EXP(4,5,6,7,0,1,2,3,j); j++;
|
||||||
|
SHA512_EXP(3,4,5,6,7,0,1,2,j); j++;
|
||||||
|
SHA512_EXP(2,3,4,5,6,7,0,1,j); j++;
|
||||||
|
SHA512_EXP(1,2,3,4,5,6,7,0,j); j++;
|
||||||
|
} while (j < 80);
|
||||||
|
|
||||||
|
ctx->h[0] += wv[0]; ctx->h[1] += wv[1];
|
||||||
|
ctx->h[2] += wv[2]; ctx->h[3] += wv[3];
|
||||||
|
ctx->h[4] += wv[4]; ctx->h[5] += wv[5];
|
||||||
|
ctx->h[6] += wv[6]; ctx->h[7] += wv[7];
|
||||||
|
#else
|
||||||
|
for (j = 0; j < 16; j++) {
|
||||||
|
PACK64(&sub_block[j << 3], &w[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 16; j < 80; j++) {
|
||||||
|
SHA512_SCR(j);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 0; j < 8; j++) {
|
||||||
|
wv[j] = ctx->h[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 0; j < 80; j++) {
|
||||||
|
t1 = wv[7] + SHA512_F2(wv[4]) + CH(wv[4], wv[5], wv[6])
|
||||||
|
+ sha512_k[j] + w[j];
|
||||||
|
t2 = SHA512_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
|
||||||
|
wv[7] = wv[6];
|
||||||
|
wv[6] = wv[5];
|
||||||
|
wv[5] = wv[4];
|
||||||
|
wv[4] = wv[3] + t1;
|
||||||
|
wv[3] = wv[2];
|
||||||
|
wv[2] = wv[1];
|
||||||
|
wv[1] = wv[0];
|
||||||
|
wv[0] = t1 + t2;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 0; j < 8; j++)
|
||||||
|
ctx->h[j] += wv[j];
|
||||||
|
#endif /* UNROLL_LOOPS_SHA512 */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void vb2_sha512_update(struct vb2_sha512_context *ctx,
|
||||||
|
const uint8_t *data,
|
||||||
|
uint32_t size)
|
||||||
|
{
|
||||||
|
unsigned int block_nb;
|
||||||
|
unsigned int new_size, rem_size, tmp_size;
|
||||||
|
const uint8_t *shifted_data;
|
||||||
|
|
||||||
|
tmp_size = VB2_SHA512_BLOCK_SIZE - ctx->size;
|
||||||
|
rem_size = size < tmp_size ? size : tmp_size;
|
||||||
|
|
||||||
|
memcpy(&ctx->block[ctx->size], data, rem_size);
|
||||||
|
|
||||||
|
if (ctx->size + size < VB2_SHA512_BLOCK_SIZE) {
|
||||||
|
ctx->size += size;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_size = size - rem_size;
|
||||||
|
block_nb = new_size / VB2_SHA512_BLOCK_SIZE;
|
||||||
|
|
||||||
|
shifted_data = data + rem_size;
|
||||||
|
|
||||||
|
vb2_sha512_transform(ctx, ctx->block, 1);
|
||||||
|
vb2_sha512_transform(ctx, shifted_data, block_nb);
|
||||||
|
|
||||||
|
rem_size = new_size % VB2_SHA512_BLOCK_SIZE;
|
||||||
|
|
||||||
|
memcpy(ctx->block, &shifted_data[block_nb << 7],
|
||||||
|
rem_size);
|
||||||
|
|
||||||
|
ctx->size = rem_size;
|
||||||
|
ctx->total_size += (block_nb + 1) << 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vb2_sha512_finalize(struct vb2_sha512_context *ctx, uint8_t *digest)
|
||||||
|
{
|
||||||
|
unsigned int block_nb;
|
||||||
|
unsigned int pm_size;
|
||||||
|
unsigned int size_b;
|
||||||
|
|
||||||
|
#ifndef UNROLL_LOOPS_SHA512
|
||||||
|
int i;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
block_nb = 1 + ((VB2_SHA512_BLOCK_SIZE - 17)
|
||||||
|
< (ctx->size % VB2_SHA512_BLOCK_SIZE));
|
||||||
|
|
||||||
|
size_b = (ctx->total_size + ctx->size) << 3;
|
||||||
|
pm_size = block_nb << 7;
|
||||||
|
|
||||||
|
memset(ctx->block + ctx->size, 0, pm_size - ctx->size);
|
||||||
|
ctx->block[ctx->size] = 0x80;
|
||||||
|
UNPACK32(size_b, ctx->block + pm_size - 4);
|
||||||
|
|
||||||
|
vb2_sha512_transform(ctx, ctx->block, block_nb);
|
||||||
|
|
||||||
|
#ifdef UNROLL_LOOPS_SHA512
|
||||||
|
UNPACK64(ctx->h[0], &digest[ 0]);
|
||||||
|
UNPACK64(ctx->h[1], &digest[ 8]);
|
||||||
|
UNPACK64(ctx->h[2], &digest[16]);
|
||||||
|
UNPACK64(ctx->h[3], &digest[24]);
|
||||||
|
UNPACK64(ctx->h[4], &digest[32]);
|
||||||
|
UNPACK64(ctx->h[5], &digest[40]);
|
||||||
|
UNPACK64(ctx->h[6], &digest[48]);
|
||||||
|
UNPACK64(ctx->h[7], &digest[56]);
|
||||||
|
#else
|
||||||
|
for (i = 0 ; i < 8; i++)
|
||||||
|
UNPACK64(ctx->h[i], &digest[i << 3]);
|
||||||
|
#endif /* UNROLL_LOOPS_SHA512 */
|
||||||
|
}
|
||||||
217
firmware/coreboot/3rdparty/vboot/firmware/2lib/2sha_utility.c
vendored
Normal file
217
firmware/coreboot/3rdparty/vboot/firmware/2lib/2sha_utility.c
vendored
Normal file
@@ -0,0 +1,217 @@
|
|||||||
|
/* Copyright (c) 2014 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.
|
||||||
|
*
|
||||||
|
* Utility functions for message digest functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "2sysincludes.h"
|
||||||
|
#include "2common.h"
|
||||||
|
#include "2sha.h"
|
||||||
|
|
||||||
|
#if VB2_SUPPORT_SHA1
|
||||||
|
#define CTH_SHA1 VB2_HASH_SHA1
|
||||||
|
#else
|
||||||
|
#define CTH_SHA1 VB2_HASH_INVALID
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if VB2_SUPPORT_SHA256
|
||||||
|
#define CTH_SHA256 VB2_HASH_SHA256
|
||||||
|
#else
|
||||||
|
#define CTH_SHA256 VB2_HASH_INVALID
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if VB2_SUPPORT_SHA512
|
||||||
|
#define CTH_SHA512 VB2_HASH_SHA512
|
||||||
|
#else
|
||||||
|
#define CTH_SHA512 VB2_HASH_INVALID
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static const uint8_t crypto_to_hash[] = {
|
||||||
|
CTH_SHA1,
|
||||||
|
CTH_SHA256,
|
||||||
|
CTH_SHA512,
|
||||||
|
CTH_SHA1,
|
||||||
|
CTH_SHA256,
|
||||||
|
CTH_SHA512,
|
||||||
|
CTH_SHA1,
|
||||||
|
CTH_SHA256,
|
||||||
|
CTH_SHA512,
|
||||||
|
CTH_SHA1,
|
||||||
|
CTH_SHA256,
|
||||||
|
CTH_SHA512,
|
||||||
|
CTH_SHA1,
|
||||||
|
CTH_SHA256,
|
||||||
|
CTH_SHA512,
|
||||||
|
CTH_SHA1,
|
||||||
|
CTH_SHA256,
|
||||||
|
CTH_SHA512,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum vb2_hash_algorithm vb2_crypto_to_hash(uint32_t algorithm)
|
||||||
|
{
|
||||||
|
if (algorithm < ARRAY_SIZE(crypto_to_hash))
|
||||||
|
return crypto_to_hash[algorithm];
|
||||||
|
else
|
||||||
|
return VB2_HASH_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vb2_digest_size(enum vb2_hash_algorithm hash_alg)
|
||||||
|
{
|
||||||
|
switch (hash_alg) {
|
||||||
|
#if VB2_SUPPORT_SHA1
|
||||||
|
case VB2_HASH_SHA1:
|
||||||
|
return VB2_SHA1_DIGEST_SIZE;
|
||||||
|
#endif
|
||||||
|
#if VB2_SUPPORT_SHA256
|
||||||
|
case VB2_HASH_SHA256:
|
||||||
|
return VB2_SHA256_DIGEST_SIZE;
|
||||||
|
#endif
|
||||||
|
#if VB2_SUPPORT_SHA512
|
||||||
|
case VB2_HASH_SHA512:
|
||||||
|
return VB2_SHA512_DIGEST_SIZE;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int vb2_hash_block_size(enum vb2_hash_algorithm alg)
|
||||||
|
{
|
||||||
|
switch (alg) {
|
||||||
|
#if VB2_SUPPORT_SHA1
|
||||||
|
case VB2_HASH_SHA1:
|
||||||
|
return VB2_SHA1_BLOCK_SIZE;
|
||||||
|
#endif
|
||||||
|
#if VB2_SUPPORT_SHA256
|
||||||
|
case VB2_HASH_SHA256:
|
||||||
|
return VB2_SHA256_BLOCK_SIZE;
|
||||||
|
#endif
|
||||||
|
#if VB2_SUPPORT_SHA512
|
||||||
|
case VB2_HASH_SHA512:
|
||||||
|
return VB2_SHA512_BLOCK_SIZE;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *vb2_get_hash_algorithm_name(enum vb2_hash_algorithm alg)
|
||||||
|
{
|
||||||
|
switch (alg) {
|
||||||
|
#if VB2_SUPPORT_SHA1
|
||||||
|
case VB2_HASH_SHA1:
|
||||||
|
return VB2_SHA1_ALG_NAME;
|
||||||
|
#endif
|
||||||
|
#if VB2_SUPPORT_SHA256
|
||||||
|
case VB2_HASH_SHA256:
|
||||||
|
return VB2_SHA256_ALG_NAME;
|
||||||
|
#endif
|
||||||
|
#if VB2_SUPPORT_SHA512
|
||||||
|
case VB2_HASH_SHA512:
|
||||||
|
return VB2_SHA512_ALG_NAME;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
return VB2_INVALID_ALG_NAME;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int vb2_digest_init(struct vb2_digest_context *dc,
|
||||||
|
enum vb2_hash_algorithm hash_alg)
|
||||||
|
{
|
||||||
|
dc->hash_alg = hash_alg;
|
||||||
|
dc->using_hwcrypto = 0;
|
||||||
|
|
||||||
|
switch (dc->hash_alg) {
|
||||||
|
#if VB2_SUPPORT_SHA1
|
||||||
|
case VB2_HASH_SHA1:
|
||||||
|
vb2_sha1_init(&dc->sha1);
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
#endif
|
||||||
|
#if VB2_SUPPORT_SHA256
|
||||||
|
case VB2_HASH_SHA256:
|
||||||
|
vb2_sha256_init(&dc->sha256);
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
#endif
|
||||||
|
#if VB2_SUPPORT_SHA512
|
||||||
|
case VB2_HASH_SHA512:
|
||||||
|
vb2_sha512_init(&dc->sha512);
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
return VB2_ERROR_SHA_INIT_ALGORITHM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int vb2_digest_extend(struct vb2_digest_context *dc,
|
||||||
|
const uint8_t *buf,
|
||||||
|
uint32_t size)
|
||||||
|
{
|
||||||
|
switch (dc->hash_alg) {
|
||||||
|
#if VB2_SUPPORT_SHA1
|
||||||
|
case VB2_HASH_SHA1:
|
||||||
|
vb2_sha1_update(&dc->sha1, buf, size);
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
#endif
|
||||||
|
#if VB2_SUPPORT_SHA256
|
||||||
|
case VB2_HASH_SHA256:
|
||||||
|
vb2_sha256_update(&dc->sha256, buf, size);
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
#endif
|
||||||
|
#if VB2_SUPPORT_SHA512
|
||||||
|
case VB2_HASH_SHA512:
|
||||||
|
vb2_sha512_update(&dc->sha512, buf, size);
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
return VB2_ERROR_SHA_EXTEND_ALGORITHM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int vb2_digest_finalize(struct vb2_digest_context *dc,
|
||||||
|
uint8_t *digest,
|
||||||
|
uint32_t digest_size)
|
||||||
|
{
|
||||||
|
if (digest_size < vb2_digest_size(dc->hash_alg))
|
||||||
|
return VB2_ERROR_SHA_FINALIZE_DIGEST_SIZE;
|
||||||
|
|
||||||
|
switch (dc->hash_alg) {
|
||||||
|
#if VB2_SUPPORT_SHA1
|
||||||
|
case VB2_HASH_SHA1:
|
||||||
|
vb2_sha1_finalize(&dc->sha1, digest);
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
#endif
|
||||||
|
#if VB2_SUPPORT_SHA256
|
||||||
|
case VB2_HASH_SHA256:
|
||||||
|
vb2_sha256_finalize(&dc->sha256, digest);
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
#endif
|
||||||
|
#if VB2_SUPPORT_SHA512
|
||||||
|
case VB2_HASH_SHA512:
|
||||||
|
vb2_sha512_finalize(&dc->sha512, digest);
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
return VB2_ERROR_SHA_FINALIZE_ALGORITHM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int vb2_digest_buffer(const uint8_t *buf,
|
||||||
|
uint32_t size,
|
||||||
|
enum vb2_hash_algorithm hash_alg,
|
||||||
|
uint8_t *digest,
|
||||||
|
uint32_t digest_size)
|
||||||
|
{
|
||||||
|
struct vb2_digest_context dc;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
rv = vb2_digest_init(&dc, hash_alg);
|
||||||
|
if (rv)
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
rv = vb2_digest_extend(&dc, buf, size);
|
||||||
|
if (rv)
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
return vb2_digest_finalize(&dc, digest, digest_size);
|
||||||
|
}
|
||||||
60
firmware/coreboot/3rdparty/vboot/firmware/2lib/2stub.c
vendored
Normal file
60
firmware/coreboot/3rdparty/vboot/firmware/2lib/2stub.c
vendored
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/* Copyright (c) 2014 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.
|
||||||
|
*
|
||||||
|
* Stub API implementations which should be implemented by the caller.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "2sysincludes.h"
|
||||||
|
#include "2api.h"
|
||||||
|
|
||||||
|
__attribute__((weak))
|
||||||
|
void vb2ex_printf(const char *func, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
if (func)
|
||||||
|
fprintf(stderr, "%s: ", func);
|
||||||
|
vfprintf(stderr, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((weak))
|
||||||
|
int vb2ex_tpm_clear_owner(struct vb2_context *ctx)
|
||||||
|
{
|
||||||
|
return VB2_ERROR_EX_TPM_CLEAR_OWNER_UNIMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((weak))
|
||||||
|
int vb2ex_read_resource(struct vb2_context *ctx,
|
||||||
|
enum vb2_resource_index index,
|
||||||
|
uint32_t offset,
|
||||||
|
void *buf,
|
||||||
|
uint32_t size)
|
||||||
|
{
|
||||||
|
return VB2_ERROR_EX_READ_RESOURCE_UNIMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((weak))
|
||||||
|
int vb2ex_hwcrypto_digest_init(enum vb2_hash_algorithm hash_alg,
|
||||||
|
uint32_t data_size)
|
||||||
|
{
|
||||||
|
return VB2_ERROR_EX_HWCRYPTO_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((weak))
|
||||||
|
int vb2ex_hwcrypto_digest_extend(const uint8_t *buf,
|
||||||
|
uint32_t size)
|
||||||
|
{
|
||||||
|
return VB2_ERROR_SHA_EXTEND_ALGORITHM; /* Should not be called. */
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((weak))
|
||||||
|
int vb2ex_hwcrypto_digest_finalize(uint8_t *digest,
|
||||||
|
uint32_t digest_size)
|
||||||
|
{
|
||||||
|
return VB2_ERROR_SHA_FINALIZE_ALGORITHM; /* Should not be called. */
|
||||||
|
}
|
||||||
54
firmware/coreboot/3rdparty/vboot/firmware/2lib/2tpm_bootmode.c
vendored
Normal file
54
firmware/coreboot/3rdparty/vboot/firmware/2lib/2tpm_bootmode.c
vendored
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
/* Copyright 2015 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.
|
||||||
|
*
|
||||||
|
* Functions for updating the TPM state with the status of boot path.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "2sysincludes.h"
|
||||||
|
#include "2common.h"
|
||||||
|
#include "2sha.h"
|
||||||
|
#include "2tpm_bootmode.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Input digests for PCR extend.
|
||||||
|
* These are calculated as:
|
||||||
|
* SHA1("|Developer_Mode||Recovery_Mode||Keyblock_Mode|").
|
||||||
|
* Developer_Mode can be 0 or 1.
|
||||||
|
* Recovery_Mode can be 0 or 1.
|
||||||
|
* Keyblock flags are defined in 2struct.h and assumed always 0 in recovery mode
|
||||||
|
* or 7 in non-recovery mode.
|
||||||
|
*
|
||||||
|
* We map them to Keyblock_Mode as follows:
|
||||||
|
* -----------------------------------------
|
||||||
|
* Keyblock Flags | Keyblock Mode
|
||||||
|
* -----------------------------------------
|
||||||
|
* 0 recovery mode | 0
|
||||||
|
* 7 Normal-signed firmware | 1
|
||||||
|
*/
|
||||||
|
|
||||||
|
const uint8_t kBootStateSHA1Digests[][VB2_SHA1_DIGEST_SIZE] = {
|
||||||
|
/* SHA1(0x00|0x00|0x01) */
|
||||||
|
{0x25, 0x47, 0xcc, 0x73, 0x6e, 0x95, 0x1f, 0xa4, 0x91, 0x98, 0x53, 0xc4,
|
||||||
|
0x3a, 0xe8, 0x90, 0x86, 0x1a, 0x3b, 0x32, 0x64},
|
||||||
|
|
||||||
|
/* SHA1(0x01|0x00|0x01) */
|
||||||
|
{0xc4, 0x2a, 0xc1, 0xc4, 0x6f, 0x1d, 0x4e, 0x21, 0x1c, 0x73, 0x5c, 0xc7,
|
||||||
|
0xdf, 0xad, 0x4f, 0xf8, 0x39, 0x11, 0x10, 0xe9},
|
||||||
|
|
||||||
|
/* SHA1(0x00|0x01|0x00) */
|
||||||
|
{0x62, 0x57, 0x18, 0x91, 0x21, 0x5b, 0x4e, 0xfc, 0x1c, 0xea, 0xb7, 0x44,
|
||||||
|
0xce, 0x59, 0xdd, 0x0b, 0x66, 0xea, 0x6f, 0x73},
|
||||||
|
|
||||||
|
/* SHA1(0x01|0x01|0x00) */
|
||||||
|
{0x47, 0xec, 0x8d, 0x98, 0x36, 0x64, 0x33, 0xdc, 0x00, 0x2e, 0x77, 0x21,
|
||||||
|
0xc9, 0xe3, 0x7d, 0x50, 0x67, 0x54, 0x79, 0x37},
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t *vb2_get_boot_state_digest(struct vb2_context *ctx)
|
||||||
|
{
|
||||||
|
int index = (ctx->flags & VB2_CONTEXT_RECOVERY_MODE ? 2 : 0) +
|
||||||
|
(ctx->flags & VB2_CONTEXT_DEVELOPER_MODE ? 1 : 0);
|
||||||
|
|
||||||
|
return kBootStateSHA1Digests[index];
|
||||||
|
}
|
||||||
716
firmware/coreboot/3rdparty/vboot/firmware/2lib/include/2api.h
vendored
Normal file
716
firmware/coreboot/3rdparty/vboot/firmware/2lib/include/2api.h
vendored
Normal file
@@ -0,0 +1,716 @@
|
|||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* APIs between calling firmware and vboot_reference
|
||||||
|
*
|
||||||
|
* General notes:
|
||||||
|
*
|
||||||
|
* TODO: split this file into a vboot_entry_points.h file which contains the
|
||||||
|
* entry points for the firmware to call vboot_reference, and a
|
||||||
|
* vboot_firmware_exports.h which contains the APIs to be implemented by the
|
||||||
|
* calling firmware and exported to vboot_reference.
|
||||||
|
*
|
||||||
|
* Notes:
|
||||||
|
* * Assumes this code is never called in the S3 resume path. TPM resume
|
||||||
|
* must be done elsewhere, and VB2_NV_DEBUG_RESET_MODE is ignored.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef VBOOT_2_API_H_
|
||||||
|
#define VBOOT_2_API_H_
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "2common.h"
|
||||||
|
#include "2crypto.h"
|
||||||
|
#include "2fw_hash_tags.h"
|
||||||
|
#include "2id.h"
|
||||||
|
#include "2recovery_reasons.h"
|
||||||
|
#include "2return_codes.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Size of non-volatile data used by vboot.
|
||||||
|
*
|
||||||
|
* If you only support non-volatile data format V1, then use VB2_NVDATA_SIZE.
|
||||||
|
* If you support V2, use VB2_NVDATA_SIZE_V2 and set context flag
|
||||||
|
* VB2_CONTEXT_NVDATA_V2.
|
||||||
|
*/
|
||||||
|
#define VB2_NVDATA_SIZE 16
|
||||||
|
#define VB2_NVDATA_SIZE_V2 64
|
||||||
|
|
||||||
|
/* Size of secure data spaces used by vboot */
|
||||||
|
#define VB2_SECDATA_SIZE 10
|
||||||
|
#define VB2_SECDATAK_SIZE 14
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Recommended size of work buffer for firmware verification stage
|
||||||
|
*
|
||||||
|
* TODO: The recommended size really depends on which key algorithms are
|
||||||
|
* used. Should have a better / more accurate recommendation than this.
|
||||||
|
*/
|
||||||
|
#define VB2_WORKBUF_RECOMMENDED_SIZE (12 * 1024)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Recommended size of work buffer for kernel verification stage
|
||||||
|
*
|
||||||
|
* This is bigger because vboot 2.0 kernel preambles are usually padded to
|
||||||
|
* 64 KB.
|
||||||
|
*
|
||||||
|
* TODO: The recommended size really depends on which key algorithms are
|
||||||
|
* used. Should have a better / more accurate recommendation than this.
|
||||||
|
*/
|
||||||
|
#define VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE (80 * 1024)
|
||||||
|
|
||||||
|
/* Recommended buffer size for vb2api_get_pcr_digest */
|
||||||
|
#define VB2_PCR_DIGEST_RECOMMENDED_SIZE 32
|
||||||
|
|
||||||
|
/* Flags for vb2_context.
|
||||||
|
*
|
||||||
|
* Unless otherwise noted, flags are set by verified boot and may be read (but
|
||||||
|
* not set or cleared) by the caller.
|
||||||
|
*/
|
||||||
|
enum vb2_context_flags {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Verified boot has changed nvdata[]. Caller must save nvdata[] back
|
||||||
|
* to its underlying storage, then may clear this flag.
|
||||||
|
*/
|
||||||
|
VB2_CONTEXT_NVDATA_CHANGED = (1 << 0),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Verified boot has changed secdata[]. Caller must save secdata[]
|
||||||
|
* back to its underlying storage, then may clear this flag.
|
||||||
|
*/
|
||||||
|
VB2_CONTEXT_SECDATA_CHANGED = (1 << 1),
|
||||||
|
|
||||||
|
/* Recovery mode is requested this boot */
|
||||||
|
VB2_CONTEXT_RECOVERY_MODE = (1 << 2),
|
||||||
|
|
||||||
|
/* Developer mode is requested this boot */
|
||||||
|
VB2_CONTEXT_DEVELOPER_MODE = (1 << 3),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Force recovery mode due to physical user request. Caller may set
|
||||||
|
* this flag when initializing the context.
|
||||||
|
*/
|
||||||
|
VB2_CONTEXT_FORCE_RECOVERY_MODE = (1 << 4),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Force developer mode enabled. Caller may set this flag when
|
||||||
|
* initializing the context.
|
||||||
|
*/
|
||||||
|
VB2_CONTEXT_FORCE_DEVELOPER_MODE = (1 << 5),
|
||||||
|
|
||||||
|
/* Using firmware slot B. If this flag is clear, using slot A. */
|
||||||
|
VB2_CONTEXT_FW_SLOT_B = (1 << 6),
|
||||||
|
|
||||||
|
/* RAM should be cleared by caller this boot */
|
||||||
|
VB2_CONTEXT_CLEAR_RAM = (1 << 7),
|
||||||
|
|
||||||
|
/* Wipeout by the app should be requested. */
|
||||||
|
VB2_CONTEXT_FORCE_WIPEOUT_MODE = (1 << 8),
|
||||||
|
|
||||||
|
/* Erase TPM developer mode state if it is enabled. */
|
||||||
|
VB2_DISABLE_DEVELOPER_MODE = (1 << 9),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Verified boot has changed secdatak[]. Caller must save secdatak[]
|
||||||
|
* back to its underlying storage, then may clear this flag.
|
||||||
|
*/
|
||||||
|
VB2_CONTEXT_SECDATAK_CHANGED = (1 << 10),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allow kernel verification to roll forward the version in secdatak[].
|
||||||
|
* Caller may set this flag before calling vb2api_kernel_phase3().
|
||||||
|
*/
|
||||||
|
VB2_CONTEXT_ALLOW_KERNEL_ROLL_FORWARD = (1 << 11),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Boot optimistically: don't touch failure counters. Caller may set
|
||||||
|
* this flag when initializing the context.
|
||||||
|
*/
|
||||||
|
VB2_CONTEXT_NOFAIL_BOOT = (1 << 12),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Secdata is not ready this boot, but should be ready next boot. It
|
||||||
|
* would like to reboot. The decision whether to reboot or not must be
|
||||||
|
* deferred until vboot, because rebooting all the time before then
|
||||||
|
* could cause a device with malfunctioning secdata to get stuck in an
|
||||||
|
* unrecoverable crash loop.
|
||||||
|
*/
|
||||||
|
VB2_CONTEXT_SECDATA_WANTS_REBOOT = (1 << 13),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Boot is S3->S0 resume, not S5->S0 normal boot. Caller may set this
|
||||||
|
* flag when initializing the context.
|
||||||
|
*/
|
||||||
|
VB2_CONTEXT_S3_RESUME = (1 << 14),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* System supports EC software sync. Caller may set this flag at any
|
||||||
|
* time before calling VbSelectAndLoadKernel().
|
||||||
|
*/
|
||||||
|
VB2_CONTEXT_EC_SYNC_SUPPORTED = (1 << 15),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* EC software sync is slow to update; warning screen should be
|
||||||
|
* displayed. Caller may set this flag at any time before calling
|
||||||
|
* VbSelectAndLoadKernel().
|
||||||
|
*/
|
||||||
|
VB2_CONTEXT_EC_SYNC_SLOW = (1 << 16),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* EC firmware supports early firmware selection; two EC images exist,
|
||||||
|
* and EC may have already verified and jumped to EC-RW prior to EC
|
||||||
|
* software sync.
|
||||||
|
*/
|
||||||
|
VB2_CONTEXT_EC_EFS = (1 << 17),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NV storage uses data format V2. Data is size VB2_NVDATA_SIZE_V2,
|
||||||
|
* not VB2_NVDATA_SIZE.
|
||||||
|
*
|
||||||
|
* Caller must set this flag when initializing the context to use V2.
|
||||||
|
* (Vboot cannot infer the data size from the data itself, because the
|
||||||
|
* data provided by the caller could be uninitialized.)
|
||||||
|
*/
|
||||||
|
VB2_CONTEXT_NVDATA_V2 = (1 << 18),
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Context for firmware verification. Pass this to all vboot APIs.
|
||||||
|
*
|
||||||
|
* Caller may relocate this between calls to vboot APIs.
|
||||||
|
*/
|
||||||
|
struct vb2_context {
|
||||||
|
/**********************************************************************
|
||||||
|
* Fields which must be initialized by caller.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Flags; see vb2_context_flags. Some flags may only be set by caller
|
||||||
|
* prior to calling vboot functions.
|
||||||
|
*/
|
||||||
|
uint32_t flags;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Work buffer, and length in bytes. Caller may relocate this between
|
||||||
|
* calls to vboot APIs; it contains no internal pointers. Caller must
|
||||||
|
* not examine the contents of this work buffer directly.
|
||||||
|
*/
|
||||||
|
uint8_t *workbuf;
|
||||||
|
uint32_t workbuf_size;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Non-volatile data. Caller must fill this from some non-volatile
|
||||||
|
* location. If the VB2_CONTEXT_NVDATA_CHANGED flag is set when a
|
||||||
|
* vb2api function returns, caller must save the data back to the
|
||||||
|
* non-volatile location and then clear the flag.
|
||||||
|
*/
|
||||||
|
uint8_t nvdata[VB2_NVDATA_SIZE_V2];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Secure data for firmware verification stage. Caller must fill this
|
||||||
|
* from some secure non-volatile location. If the
|
||||||
|
* VB2_CONTEXT_SECDATA_CHANGED flag is set when a function returns,
|
||||||
|
* caller must save the data back to the secure non-volatile location
|
||||||
|
* and then clear the flag.
|
||||||
|
*/
|
||||||
|
uint8_t secdata[VB2_SECDATA_SIZE];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Context pointer for use by caller. Verified boot never looks at
|
||||||
|
* this. Put context here if you need it for APIs that verified boot
|
||||||
|
* may call (vb2ex_...() functions).
|
||||||
|
*/
|
||||||
|
void *non_vboot_context;
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* Fields caller may examine after calling vb2api_fw_phase1(). Caller
|
||||||
|
* must set these fields to 0 before calling any vboot functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Amount of work buffer used so far. Verified boot sub-calls use
|
||||||
|
* this to know where the unused work area starts. Caller may use
|
||||||
|
* this between calls to vboot APIs to know how much data must be
|
||||||
|
* copied when relocating the work buffer.
|
||||||
|
*/
|
||||||
|
uint32_t workbuf_used;
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* Fields caller must initialize before calling vb2api_kernel_phase1().
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Secure data for kernel verification stage. Caller must fill this
|
||||||
|
* from some secure non-volatile location. If the
|
||||||
|
* VB2_CONTEXT_SECDATAK_CHANGED flag is set when a function returns,
|
||||||
|
* caller must save the data back to the secure non-volatile location
|
||||||
|
* and then clear the flag.
|
||||||
|
*/
|
||||||
|
uint8_t secdatak[VB2_SECDATAK_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Resource index for vb2ex_read_resource() */
|
||||||
|
enum vb2_resource_index {
|
||||||
|
|
||||||
|
/* Google binary block */
|
||||||
|
VB2_RES_GBB,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Firmware verified boot block (keyblock+preamble). Use
|
||||||
|
* VB2_CONTEXT_FW_SLOT_B to determine whether this refers to slot A or
|
||||||
|
* slot B; vboot will set that flag to the proper state before reading
|
||||||
|
* the vblock.
|
||||||
|
*/
|
||||||
|
VB2_RES_FW_VBLOCK,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Kernel verified boot block (keyblock+preamble) for the current
|
||||||
|
* kernel partition. Used only by vb2api_kernel_load_vblock().
|
||||||
|
* Contents are allowed to change between calls to that function (to
|
||||||
|
* allow multiple kernels to be examined).
|
||||||
|
*/
|
||||||
|
VB2_RES_KERNEL_VBLOCK,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Digest ID for vbapi_get_pcr_digest() */
|
||||||
|
enum vb2_pcr_digest {
|
||||||
|
/* Digest based on current developer and recovery mode flags */
|
||||||
|
BOOT_MODE_PCR,
|
||||||
|
|
||||||
|
/* SHA-256 hash digest of HWID, from GBB */
|
||||||
|
HWID_DIGEST_PCR,
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* APIs provided by verified boot.
|
||||||
|
*
|
||||||
|
* At a high level, call functions in the order described below. After each
|
||||||
|
* call, examine vb2_context.flags to determine whether nvdata or secdata
|
||||||
|
* needs to be written.
|
||||||
|
*
|
||||||
|
* If you need to cause the boot process to fail at any point, call
|
||||||
|
* vb2api_fail(). Then check vb2_context.flags to see what data needs to be
|
||||||
|
* written. Then reboot.
|
||||||
|
*
|
||||||
|
* Load nvdata from wherever you keep it.
|
||||||
|
*
|
||||||
|
* Load secdata from wherever you keep it.
|
||||||
|
*
|
||||||
|
* If it wasn't there at all (for example, this is the first boot
|
||||||
|
* of a new system in the factory), call vb2api_secdata_create()
|
||||||
|
* to initialize the data.
|
||||||
|
*
|
||||||
|
* If access to your storage is unreliable (reads/writes may
|
||||||
|
* contain corrupt data), you may call vb2api_secdata_check() to
|
||||||
|
* determine if the data was valid, and retry reading if it
|
||||||
|
* wasn't. (In that case, you should also read back and check the
|
||||||
|
* data after any time you write it, to make sure it was written
|
||||||
|
* correctly.)
|
||||||
|
*
|
||||||
|
* Call vb2api_fw_phase1(). At present, this nominally decides whether
|
||||||
|
* recovery mode is needed this boot.
|
||||||
|
*
|
||||||
|
* Call vb2api_fw_phase2(). At present, this nominally decides which
|
||||||
|
* firmware slot will be attempted (A or B).
|
||||||
|
*
|
||||||
|
* Call vb2api_fw_phase3(). At present, this nominally verifies the
|
||||||
|
* firmware keyblock and preamble.
|
||||||
|
*
|
||||||
|
* Lock down wherever you keep secdata. It should no longer be writable
|
||||||
|
* this boot.
|
||||||
|
*
|
||||||
|
* Verify the hash of each section of code/data you need to boot the RW
|
||||||
|
* firmware. For each section:
|
||||||
|
*
|
||||||
|
* Call vb2_init_hash() to see if the hash exists.
|
||||||
|
*
|
||||||
|
* Load the data for the section. Call vb2_extend_hash() on the
|
||||||
|
* data as you load it. You can load it all at once and make one
|
||||||
|
* call, or load and hash-extend a block at a time.
|
||||||
|
*
|
||||||
|
* Call vb2_check_hash() to see if the hash is valid.
|
||||||
|
*
|
||||||
|
* If it is valid, you may use the data and/or execute
|
||||||
|
* code from that section.
|
||||||
|
*
|
||||||
|
* If the hash was invalid, you must reboot.
|
||||||
|
*
|
||||||
|
* At this point, firmware verification is done, and vb2_context contains the
|
||||||
|
* kernel key needed to verify the kernel. That context should be preserved
|
||||||
|
* and passed on to kernel selection. The kernel selection process may be
|
||||||
|
* done by the same firmware image, or may be done by the RW firmware. The
|
||||||
|
* recommended order is:
|
||||||
|
*
|
||||||
|
* Load secdatak from wherever you keep it.
|
||||||
|
*
|
||||||
|
* If it wasn't there at all (for example, this is the first boot
|
||||||
|
* of a new system in the factory), call vb2api_secdatak_create()
|
||||||
|
* to initialize the data.
|
||||||
|
*
|
||||||
|
* If access to your storage is unreliable (reads/writes may
|
||||||
|
* contain corrupt data), you may call vb2api_secdatak_check() to
|
||||||
|
* determine if the data was valid, and retry reading if it
|
||||||
|
* wasn't. (In that case, you should also read back and check the
|
||||||
|
* data after any time you write it, to make sure it was written
|
||||||
|
* correctly.)
|
||||||
|
*
|
||||||
|
* Call vb2api_kernel_phase1(). At present, this decides which key to
|
||||||
|
* use to verify kernel data - the recovery key from the GBB, or the
|
||||||
|
* kernel subkey from the firmware verification stage.
|
||||||
|
*
|
||||||
|
* Kernel phase 2 is finding loading, and verifying the kernel partition.
|
||||||
|
*
|
||||||
|
* Find a boot device (you're on your own here).
|
||||||
|
*
|
||||||
|
* Call vb2api_load_kernel_vblock() for each kernel partition on the
|
||||||
|
* boot device, until one succeeds.
|
||||||
|
*
|
||||||
|
* When that succeeds, call vb2api_get_kernel_size() to determine where
|
||||||
|
* the kernel is located in the stream and how big it is. Load or map
|
||||||
|
* the kernel. (Again, you're on your own. This is the responsibility of
|
||||||
|
* the caller so that the caller can choose whether to allocate a buffer,
|
||||||
|
* load the kernel data into a predefined area of RAM, or directly map a
|
||||||
|
* kernel file into the address space. Note that technically it doesn't
|
||||||
|
* matter whether the kernel data is even in the same file or stream as
|
||||||
|
* the vblock, as long as the caller loads the right data.
|
||||||
|
*
|
||||||
|
* Call vb2api_verify_kernel_data() on the kernel data.
|
||||||
|
*
|
||||||
|
* If you ran out of kernels before finding a good one, call vb2api_fail()
|
||||||
|
* with an appropriate recovery reason.
|
||||||
|
*
|
||||||
|
* Set the VB2_CONTEXT_ALLOW_KERNEL_ROLL_FORWARD flag if the current
|
||||||
|
* kernel partition has the successful flag (that is, it's already known
|
||||||
|
* or assumed to be a functional kernel partition).
|
||||||
|
*
|
||||||
|
* Call vb2api_kernel_phase3(). This cleans up from kernel verification
|
||||||
|
* and updates the secure data if needed.
|
||||||
|
*
|
||||||
|
* Lock down wherever you keep secdatak. It should no longer be writable
|
||||||
|
* this boot.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sanity-check the contents of the secure storage context.
|
||||||
|
*
|
||||||
|
* Use this if reading from secure storage may be flaky, and you want to retry
|
||||||
|
* reading it several times.
|
||||||
|
*
|
||||||
|
* This may be called before vb2api_phase1().
|
||||||
|
*
|
||||||
|
* @param ctx Context pointer
|
||||||
|
* @return VB2_SUCCESS, or non-zero error code if error.
|
||||||
|
*/
|
||||||
|
int vb2api_secdata_check(const struct vb2_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create fresh data in the secure storage context.
|
||||||
|
*
|
||||||
|
* Use this only when initializing the secure storage context on a new machine
|
||||||
|
* the first time it boots. Do NOT simply use this if vb2api_secdata_check()
|
||||||
|
* (or any other API in this library) fails; that could allow the secure data
|
||||||
|
* to be rolled back to an insecure state.
|
||||||
|
*
|
||||||
|
* This may be called before vb2api_phase1().
|
||||||
|
*
|
||||||
|
* @param ctx Context pointer
|
||||||
|
* @return VB2_SUCCESS, or non-zero error code if error.
|
||||||
|
*/
|
||||||
|
int vb2api_secdata_create(struct vb2_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sanity-check the contents of the kernel version secure storage context.
|
||||||
|
*
|
||||||
|
* Use this if reading from secure storage may be flaky, and you want to retry
|
||||||
|
* reading it several times.
|
||||||
|
*
|
||||||
|
* This may be called before vb2api_phase1().
|
||||||
|
*
|
||||||
|
* @param ctx Context pointer
|
||||||
|
* @return VB2_SUCCESS, or non-zero error code if error.
|
||||||
|
*/
|
||||||
|
int vb2api_secdatak_check(const struct vb2_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create fresh data in the kernel version secure storage context.
|
||||||
|
*
|
||||||
|
* Use this only when initializing the secure storage context on a new machine
|
||||||
|
* the first time it boots. Do NOT simply use this if vb2api_secdatak_check()
|
||||||
|
* (or any other API in this library) fails; that could allow the secure data
|
||||||
|
* to be rolled back to an insecure state.
|
||||||
|
*
|
||||||
|
* This may be called before vb2api_phase1().
|
||||||
|
*
|
||||||
|
* @param ctx Context pointer
|
||||||
|
* @return VB2_SUCCESS, or non-zero error code if error.
|
||||||
|
*/
|
||||||
|
int vb2api_secdatak_create(struct vb2_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Report firmware failure to vboot.
|
||||||
|
*
|
||||||
|
* This may be called before vb2api_phase1() to indicate errors in the boot
|
||||||
|
* process prior to the start of vboot.
|
||||||
|
*
|
||||||
|
* If this is called after vb2api_phase1(), on return, the calling firmware
|
||||||
|
* should check for updates to secdata and/or nvdata, then reboot.
|
||||||
|
*
|
||||||
|
* @param reason Recovery reason
|
||||||
|
* @param subcode Recovery subcode
|
||||||
|
*/
|
||||||
|
void vb2api_fail(struct vb2_context *ctx, uint8_t reason, uint8_t subcode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Firmware selection, phase 1.
|
||||||
|
*
|
||||||
|
* If the returned error is VB2_ERROR_API_PHASE1_RECOVERY, the calling firmware
|
||||||
|
* should jump directly to recovery-mode firmware without rebooting.
|
||||||
|
*
|
||||||
|
* For other errors, the calling firmware should check for updates to secdata
|
||||||
|
* and/or nvdata, then reboot.
|
||||||
|
*
|
||||||
|
* @param ctx Vboot context
|
||||||
|
* @return VB2_SUCCESS, or error code on error.
|
||||||
|
*/
|
||||||
|
int vb2api_fw_phase1(struct vb2_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Firmware selection, phase 2.
|
||||||
|
*
|
||||||
|
* On error, the calling firmware should check for updates to secdata and/or
|
||||||
|
* nvdata, then reboot.
|
||||||
|
*
|
||||||
|
* @param ctx Vboot context
|
||||||
|
* @return VB2_SUCCESS, or error code on error.
|
||||||
|
*/
|
||||||
|
int vb2api_fw_phase2(struct vb2_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Firmware selection, phase 3.
|
||||||
|
*
|
||||||
|
* On error, the calling firmware should check for updates to secdata and/or
|
||||||
|
* nvdata, then reboot.
|
||||||
|
*
|
||||||
|
* On success, the calling firmware should lock down secdata before continuing
|
||||||
|
* with the boot process.
|
||||||
|
*
|
||||||
|
* @param ctx Vboot context
|
||||||
|
* @return VB2_SUCCESS, or error code on error.
|
||||||
|
*/
|
||||||
|
int vb2api_fw_phase3(struct vb2_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same, but for new-style structs.
|
||||||
|
*/
|
||||||
|
int vb21api_fw_phase3(struct vb2_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize hashing data for the specified tag.
|
||||||
|
*
|
||||||
|
* @param ctx Vboot context
|
||||||
|
* @param tag Tag to start hashing (enum vb2_hash_tag)
|
||||||
|
* @param size If non-null, expected size of data for tag will be
|
||||||
|
* stored here on output.
|
||||||
|
* @return VB2_SUCCESS, or error code on error.
|
||||||
|
*/
|
||||||
|
int vb2api_init_hash(struct vb2_context *ctx, uint32_t tag, uint32_t *size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same, but for new-style structs.
|
||||||
|
*/
|
||||||
|
int vb21api_init_hash(struct vb2_context *ctx,
|
||||||
|
const struct vb2_id *id,
|
||||||
|
uint32_t *size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extend the hash started by vb2api_init_hash() with additional data.
|
||||||
|
*
|
||||||
|
* (This is the same for both old and new style structs.)
|
||||||
|
*
|
||||||
|
* @param ctx Vboot context
|
||||||
|
* @param buf Data to hash
|
||||||
|
* @param size Size of data in bytes
|
||||||
|
* @return VB2_SUCCESS, or error code on error.
|
||||||
|
*/
|
||||||
|
int vb2api_extend_hash(struct vb2_context *ctx,
|
||||||
|
const void *buf,
|
||||||
|
uint32_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check the hash value started by vb2api_init_hash().
|
||||||
|
*
|
||||||
|
* @param ctx Vboot context
|
||||||
|
* @return VB2_SUCCESS, or error code on error.
|
||||||
|
*/
|
||||||
|
int vb2api_check_hash(struct vb2_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same, but for new-style structs.
|
||||||
|
*/
|
||||||
|
int vb21api_check_hash(struct vb2_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check the hash value started by vb2api_init_hash() while retrieving
|
||||||
|
* calculated digest.
|
||||||
|
*
|
||||||
|
* @param ctx Vboot context
|
||||||
|
* @param digest_out optional pointer to buffer to store digest
|
||||||
|
* @param digest_out_size optional size of buffer to store digest
|
||||||
|
* @return VB2_SUCCESS, or error code on error.
|
||||||
|
*/
|
||||||
|
int vb2api_check_hash_get_digest(struct vb2_context *ctx, void *digest_out,
|
||||||
|
uint32_t digest_out_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a PCR digest
|
||||||
|
*
|
||||||
|
* @param ctx Vboot context
|
||||||
|
* @param which_digest PCR index of the digest
|
||||||
|
* @param dest Destination where the digest is copied.
|
||||||
|
* Recommended size is VB2_PCR_DIGEST_RECOMMENDED_SIZE.
|
||||||
|
* @param dest_size IN: size of the buffer pointed by dest
|
||||||
|
* OUT: size of the copied digest
|
||||||
|
* @return VB2_SUCCESS, or error code on error
|
||||||
|
*/
|
||||||
|
int vb2api_get_pcr_digest(struct vb2_context *ctx,
|
||||||
|
enum vb2_pcr_digest which_digest,
|
||||||
|
uint8_t *dest,
|
||||||
|
uint32_t *dest_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare for kernel verification stage.
|
||||||
|
*
|
||||||
|
* Must be called before other vb2api kernel functions.
|
||||||
|
*
|
||||||
|
* @param ctx Vboot context
|
||||||
|
* @return VB2_SUCCESS, or error code on error.
|
||||||
|
*/
|
||||||
|
int vb2api_kernel_phase1(struct vb2_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load the verified boot block (vblock) for a kernel.
|
||||||
|
*
|
||||||
|
* This function may be called multiple times, to load and verify the
|
||||||
|
* vblocks from multiple kernel partitions.
|
||||||
|
*
|
||||||
|
* @param ctx Vboot context
|
||||||
|
* @param stream Kernel stream
|
||||||
|
* @return VB2_SUCCESS, or error code on error.
|
||||||
|
*/
|
||||||
|
int vb2api_load_kernel_vblock(struct vb2_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the size and offset of the kernel data for the most recent vblock.
|
||||||
|
*
|
||||||
|
* Valid after a successful call to vb2api_load_kernel_vblock().
|
||||||
|
*
|
||||||
|
* @param ctx Vboot context
|
||||||
|
* @param offset_ptr Destination for offset in bytes of kernel data as
|
||||||
|
* reported by vblock.
|
||||||
|
* @param size_ptr Destination for size of kernel data in bytes.
|
||||||
|
* @return VB2_SUCCESS, or error code on error.
|
||||||
|
*/
|
||||||
|
int vb2api_get_kernel_size(struct vb2_context *ctx,
|
||||||
|
uint32_t *offset_ptr,
|
||||||
|
uint32_t *size_ptr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify kernel data using the previously loaded kernel vblock.
|
||||||
|
*
|
||||||
|
* Valid after a successful call to vb2api_load_kernel_vblock(). This allows
|
||||||
|
* the caller to load or map the kernel data, as appropriate, and pass the
|
||||||
|
* pointer to the kernel data into vboot.
|
||||||
|
*
|
||||||
|
* @param ctx Vboot context
|
||||||
|
* @param buf Pointer to kernel data
|
||||||
|
* @param size Size of kernel data in bytes
|
||||||
|
* @return VB2_SUCCESS, or error code on error.
|
||||||
|
*/
|
||||||
|
int vb2api_verify_kernel_data(struct vb2_context *ctx,
|
||||||
|
const void *buf,
|
||||||
|
uint32_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clean up after kernel verification.
|
||||||
|
*
|
||||||
|
* Call this after successfully loading a vblock and verifying kernel data,
|
||||||
|
* or if you've run out of boot devices and/or kernel partitions.
|
||||||
|
*
|
||||||
|
* This cleans up intermediate data structures in the vboot context, and
|
||||||
|
* updates the version in the secure data if necessary.
|
||||||
|
*/
|
||||||
|
int vb2api_kernel_phase3(struct vb2_context *ctx);
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* APIs provided by the caller to verified boot */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the TPM owner.
|
||||||
|
*
|
||||||
|
* @param ctx Vboot context
|
||||||
|
* @return VB2_SUCCESS, or error code on error.
|
||||||
|
*/
|
||||||
|
int vb2ex_tpm_clear_owner(struct vb2_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a verified boot resource.
|
||||||
|
*
|
||||||
|
* @param ctx Vboot context
|
||||||
|
* @param index Resource index to read
|
||||||
|
* @param offset Byte offset within resource to start at
|
||||||
|
* @param buf Destination for data
|
||||||
|
* @param size Amount of data to read
|
||||||
|
* @return VB2_SUCCESS, or error code on error.
|
||||||
|
*/
|
||||||
|
int vb2ex_read_resource(struct vb2_context *ctx,
|
||||||
|
enum vb2_resource_index index,
|
||||||
|
uint32_t offset,
|
||||||
|
void *buf,
|
||||||
|
uint32_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print debug output
|
||||||
|
*
|
||||||
|
* This should work like printf(). If func!=NULL, it will be a string with
|
||||||
|
* the current function name; that can be used to generate prettier debug
|
||||||
|
* output. If func==NULL, don't print any extra header/trailer so that this
|
||||||
|
* can be used to composite a bigger output string from several calls - for
|
||||||
|
* example, when doing a hex dump.
|
||||||
|
*
|
||||||
|
* @param func Function name generating output, or NULL.
|
||||||
|
* @param fmt Printf format string
|
||||||
|
*/
|
||||||
|
void vb2ex_printf(const char *func, const char *fmt, ...);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the hardware crypto engine to calculate a block-style digest.
|
||||||
|
*
|
||||||
|
* @param hash_alg Hash algorithm to use
|
||||||
|
* @param data_size Expected total size of data to hash
|
||||||
|
* @return VB2_SUCCESS, or non-zero error code (HWCRYPTO_UNSUPPORTED not fatal).
|
||||||
|
*/
|
||||||
|
int vb2ex_hwcrypto_digest_init(enum vb2_hash_algorithm hash_alg,
|
||||||
|
uint32_t data_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extend the hash in the hardware crypto engine with another block of data.
|
||||||
|
*
|
||||||
|
* @param buf Next data block to hash
|
||||||
|
* @param size Length of data block in bytes
|
||||||
|
* @return VB2_SUCCESS, or non-zero error code.
|
||||||
|
*/
|
||||||
|
int vb2ex_hwcrypto_digest_extend(const uint8_t *buf, uint32_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finalize the digest in the hardware crypto engine and extract the result.
|
||||||
|
*
|
||||||
|
* @param digest Destination buffer for resulting digest
|
||||||
|
* @param digest_size Length of digest buffer in bytes
|
||||||
|
* @return VB2_SUCCESS, or non-zero error code.
|
||||||
|
*/
|
||||||
|
int vb2ex_hwcrypto_digest_finalize(uint8_t *digest, uint32_t digest_size);
|
||||||
|
|
||||||
|
#endif /* VBOOT_2_API_H_ */
|
||||||
225
firmware/coreboot/3rdparty/vboot/firmware/2lib/include/2common.h
vendored
Normal file
225
firmware/coreboot/3rdparty/vboot/firmware/2lib/include/2common.h
vendored
Normal file
@@ -0,0 +1,225 @@
|
|||||||
|
/* Copyright (c) 2014 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.
|
||||||
|
*
|
||||||
|
* Common functions between firmware and kernel verified boot.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef VBOOT_REFERENCE_VBOOT_2COMMON_H_
|
||||||
|
#define VBOOT_REFERENCE_VBOOT_2COMMON_H_
|
||||||
|
|
||||||
|
#include "2api.h"
|
||||||
|
#include "2return_codes.h"
|
||||||
|
#include "2sha.h"
|
||||||
|
#include "2struct.h"
|
||||||
|
#include "2sysincludes.h"
|
||||||
|
|
||||||
|
struct vb2_public_key;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the greater of A and B. This is used in macros which calculate the
|
||||||
|
* required buffer size, so can't be turned into a static inline function.
|
||||||
|
*/
|
||||||
|
#ifndef VB2_MAX
|
||||||
|
#define VB2_MAX(A, B) ((A) > (B) ? (A) : (B))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Return the number of elements in an array */
|
||||||
|
#ifndef ARRAY_SIZE
|
||||||
|
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Platform-dependent debug output macros. */
|
||||||
|
#if defined(VBOOT_DEBUG)
|
||||||
|
# define VB2_DEBUG(format, args...) vb2ex_printf(__func__, format, ## args)
|
||||||
|
# define VB2_DEBUG_RAW(format, args...) vb2ex_printf(NULL, format, ## args)
|
||||||
|
#else
|
||||||
|
# define VB2_DEBUG(format, args...)
|
||||||
|
# define VB2_DEBUG_RAW(format, args...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define test_mockable and for mocking functions when compiled for Chrome OS
|
||||||
|
* environment (that is, not for firmware).
|
||||||
|
*/
|
||||||
|
#ifndef test_mockable
|
||||||
|
#ifdef CHROMEOS_ENVIRONMENT
|
||||||
|
#define test_mockable __attribute__((weak))
|
||||||
|
#else
|
||||||
|
#define test_mockable
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Alignment for work buffer pointers/allocations should be useful for any
|
||||||
|
* data type. When declaring workbuf buffers on the stack, the caller should
|
||||||
|
* use explicit alignment to avoid run-time errors. For example:
|
||||||
|
*
|
||||||
|
* int foo(void)
|
||||||
|
* {
|
||||||
|
* struct vb2_workbuf wb;
|
||||||
|
* uint8_t buf[NUM] __attribute__ ((aligned (VB2_WORKBUF_ALIGN)));
|
||||||
|
* wb.buf = buf;
|
||||||
|
* wb.size = sizeof(buf);
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* We might get away with using __alignof__(void *), but since GCC defines a
|
||||||
|
* macro for us we'll be safe and use that. */
|
||||||
|
#define VB2_WORKBUF_ALIGN __BIGGEST_ALIGNMENT__
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Round up a number to a multiple of VB2_WORKBUF_ALIGN
|
||||||
|
*
|
||||||
|
* @param v Number to round up
|
||||||
|
* @return The number, rounded up.
|
||||||
|
*/
|
||||||
|
static __inline uint32_t vb2_wb_round_up(uint32_t v)
|
||||||
|
{
|
||||||
|
return (v + VB2_WORKBUF_ALIGN - 1) & ~(VB2_WORKBUF_ALIGN - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Work buffer */
|
||||||
|
struct vb2_workbuf {
|
||||||
|
uint8_t *buf;
|
||||||
|
uint32_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize a work buffer.
|
||||||
|
*
|
||||||
|
* @param wb Work buffer to init
|
||||||
|
* @param buf Pointer to work buffer data
|
||||||
|
* @param size Size of work buffer data in bytes
|
||||||
|
*/
|
||||||
|
void vb2_workbuf_init(struct vb2_workbuf *wb, uint8_t *buf, uint32_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate space in a work buffer.
|
||||||
|
*
|
||||||
|
* Note that the returned buffer will always be aligned to VB2_WORKBUF_ALIGN.
|
||||||
|
*
|
||||||
|
* The work buffer acts like a stack, and detailed tracking of allocs and frees
|
||||||
|
* is not done. The caller must track the size of each allocation and free via
|
||||||
|
* vb2_workbuf_free() in the reverse order they were allocated.
|
||||||
|
*
|
||||||
|
* An acceptable alternate workflow inside a function is to pass in a const
|
||||||
|
* work buffer, then make a local copy. Allocations done to the local copy
|
||||||
|
* then don't change the passed-in work buffer, and will effectively be freed
|
||||||
|
* when the local copy goes out of scope.
|
||||||
|
*
|
||||||
|
* @param wb Work buffer
|
||||||
|
* @param size Requested size in bytes
|
||||||
|
* @return A pointer to the allocated space, or NULL if error.
|
||||||
|
*/
|
||||||
|
void *vb2_workbuf_alloc(struct vb2_workbuf *wb, uint32_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reallocate space in a work buffer.
|
||||||
|
*
|
||||||
|
* Note that the returned buffer will always be aligned to VB2_WORKBUF_ALIGN.
|
||||||
|
* The work buffer acts like a stack, so this must only be done to the most
|
||||||
|
* recently allocated buffer.
|
||||||
|
*
|
||||||
|
* @param wb Work buffer
|
||||||
|
* @param oldsize Old allocation size in bytes
|
||||||
|
* @param newsize Requested size in bytes
|
||||||
|
* @return A pointer to the allocated space, or NULL if error.
|
||||||
|
*/
|
||||||
|
void *vb2_workbuf_realloc(struct vb2_workbuf *wb,
|
||||||
|
uint32_t oldsize,
|
||||||
|
uint32_t newsize);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free the preceding allocation.
|
||||||
|
*
|
||||||
|
* Note that the work buffer acts like a stack, and detailed tracking of
|
||||||
|
* allocs and frees is not done. The caller must track the size of each
|
||||||
|
* allocation and free them in reverse order.
|
||||||
|
*
|
||||||
|
* @param wb Work buffer
|
||||||
|
* @param size Size of data to free
|
||||||
|
*/
|
||||||
|
void vb2_workbuf_free(struct vb2_workbuf *wb, uint32_t size);
|
||||||
|
|
||||||
|
/* Check if a pointer is aligned on an align-byte boundary */
|
||||||
|
#define vb2_aligned(ptr, align) (!(((uintptr_t)(ptr)) & ((align) - 1)))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Safer memcmp() for use in crypto.
|
||||||
|
*
|
||||||
|
* Compares the buffers to see if they are equal. Time taken to perform
|
||||||
|
* the comparison is dependent only on the size, not the relationship of
|
||||||
|
* the match between the buffers. Note that unlike memcmp(), this only
|
||||||
|
* indicates inequality, not which buffer is lesser.
|
||||||
|
*
|
||||||
|
* @param s1 First buffer
|
||||||
|
* @param s2 Second buffer
|
||||||
|
* @param size Number of bytes to compare
|
||||||
|
* @return 0 if match or size=0, non-zero if at least one byte mismatched.
|
||||||
|
*/
|
||||||
|
int vb2_safe_memcmp(const void *s1, const void *s2, size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Align a buffer and check its size.
|
||||||
|
*
|
||||||
|
* @param **ptr Pointer to pointer to align
|
||||||
|
* @param *size Points to size of buffer pointed to by *ptr
|
||||||
|
* @param align Required alignment (must be power of 2)
|
||||||
|
* @param want_size Required size
|
||||||
|
* @return VB2_SUCCESS, or non-zero if error.
|
||||||
|
*/
|
||||||
|
int vb2_align(uint8_t **ptr,
|
||||||
|
uint32_t *size,
|
||||||
|
uint32_t align,
|
||||||
|
uint32_t want_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return offset of ptr from base.
|
||||||
|
*
|
||||||
|
* @param base Base pointer
|
||||||
|
* @param ptr Pointer at some offset from base
|
||||||
|
* @return The offset of ptr from base.
|
||||||
|
*/
|
||||||
|
ptrdiff_t vb2_offset_of(const void *base, const void *ptr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return expected signature size for a signature/hash algorithm pair
|
||||||
|
*
|
||||||
|
* @param sig_alg Signature algorithm
|
||||||
|
* @param hash_alg Hash algorithm
|
||||||
|
* @return The signature size, or zero if error / unsupported algorithm.
|
||||||
|
*/
|
||||||
|
uint32_t vb2_sig_size(enum vb2_signature_algorithm sig_alg,
|
||||||
|
enum vb2_hash_algorithm hash_alg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a key ID for an unsigned hash algorithm.
|
||||||
|
*
|
||||||
|
* @param hash_alg Hash algorithm to return key for
|
||||||
|
* @return A pointer to the key ID for that hash algorithm with
|
||||||
|
* sig_alg=VB2_SIG_NONE, or NULL if error.
|
||||||
|
*/
|
||||||
|
const struct vb2_id *vb2_hash_id(enum vb2_hash_algorithm hash_alg);
|
||||||
|
|
||||||
|
/* Size of work buffer sufficient for vb2_verify_digest() worst case. */
|
||||||
|
#define VB2_VERIFY_DIGEST_WORKBUF_BYTES VB2_VERIFY_RSA_DIGEST_WORKBUF_BYTES
|
||||||
|
|
||||||
|
/* Size of work buffer sufficient for vb2_verify_data() worst case. */
|
||||||
|
#define VB2_VERIFY_DATA_WORKBUF_BYTES \
|
||||||
|
(VB2_SHA512_DIGEST_SIZE + \
|
||||||
|
VB2_MAX(VB2_VERIFY_DIGEST_WORKBUF_BYTES, \
|
||||||
|
sizeof(struct vb2_digest_context)))
|
||||||
|
|
||||||
|
/* Size of work buffer sufficient for vb2_verify_keyblock() worst case. */
|
||||||
|
#define VB2_KEY_BLOCK_VERIFY_WORKBUF_BYTES VB2_VERIFY_DATA_WORKBUF_BYTES
|
||||||
|
|
||||||
|
/* Size of work buffer sufficient for vb2_verify_fw_preamble() worst case. */
|
||||||
|
#define VB2_VERIFY_FIRMWARE_PREAMBLE_WORKBUF_BYTES VB2_VERIFY_DATA_WORKBUF_BYTES
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Size of work buffer sufficient for vb2_verify_kernel_preamble() worst
|
||||||
|
* case.
|
||||||
|
*/
|
||||||
|
#define VB2_VERIFY_KERNEL_PREAMBLE_WORKBUF_BYTES VB2_VERIFY_DATA_WORKBUF_BYTES
|
||||||
|
|
||||||
|
#endif /* VBOOT_REFERENCE_VBOOT_2COMMON_H_ */
|
||||||
20
firmware/coreboot/3rdparty/vboot/firmware/2lib/include/2crc8.h
vendored
Normal file
20
firmware/coreboot/3rdparty/vboot/firmware/2lib/include/2crc8.h
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
/* Copyright (c) 2014 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.
|
||||||
|
*
|
||||||
|
* Very simple 8-bit CRC function.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef VBOOT_REFERENCE_2_CRC8_H_
|
||||||
|
#define VBOOT_REFERENCE_2_CRC8_H_
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate CRC-8 of the data, using x^8 + x^2 + x + 1 polynomial.
|
||||||
|
*
|
||||||
|
* @param data Data to CRC
|
||||||
|
* @param size Size of data in bytes
|
||||||
|
* @return CRC-8 of the data.
|
||||||
|
*/
|
||||||
|
uint8_t vb2_crc8(const void *data, uint32_t size);
|
||||||
|
|
||||||
|
#endif /* VBOOT_REFERENCE_2_CRC8_H_ */
|
||||||
75
firmware/coreboot/3rdparty/vboot/firmware/2lib/include/2crypto.h
vendored
Normal file
75
firmware/coreboot/3rdparty/vboot/firmware/2lib/include/2crypto.h
vendored
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
/* Copyright (c) 2014 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.
|
||||||
|
*
|
||||||
|
* Crypto constants for verified boot
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef VBOOT_REFERENCE_VBOOT_2CRYPTO_H_
|
||||||
|
#define VBOOT_REFERENCE_VBOOT_2CRYPTO_H_
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/* Verified boot crypto algorithms */
|
||||||
|
enum vb2_crypto_algorithm {
|
||||||
|
VB2_ALG_RSA1024_SHA1 = 0,
|
||||||
|
VB2_ALG_RSA1024_SHA256 = 1,
|
||||||
|
VB2_ALG_RSA1024_SHA512 = 2,
|
||||||
|
VB2_ALG_RSA2048_SHA1 = 3,
|
||||||
|
VB2_ALG_RSA2048_SHA256 = 4,
|
||||||
|
VB2_ALG_RSA2048_SHA512 = 5,
|
||||||
|
VB2_ALG_RSA4096_SHA1 = 6,
|
||||||
|
VB2_ALG_RSA4096_SHA256 = 7,
|
||||||
|
VB2_ALG_RSA4096_SHA512 = 8,
|
||||||
|
VB2_ALG_RSA8192_SHA1 = 9,
|
||||||
|
VB2_ALG_RSA8192_SHA256 = 10,
|
||||||
|
VB2_ALG_RSA8192_SHA512 = 11,
|
||||||
|
VB2_ALG_RSA2048_EXP3_SHA1 = 12,
|
||||||
|
VB2_ALG_RSA2048_EXP3_SHA256 = 13,
|
||||||
|
VB2_ALG_RSA2048_EXP3_SHA512 = 14,
|
||||||
|
VB2_ALG_RSA3072_EXP3_SHA1 = 15,
|
||||||
|
VB2_ALG_RSA3072_EXP3_SHA256 = 16,
|
||||||
|
VB2_ALG_RSA3072_EXP3_SHA512 = 17,
|
||||||
|
/* Number of algorithms */
|
||||||
|
VB2_ALG_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Algorithm types for signatures */
|
||||||
|
enum vb2_signature_algorithm {
|
||||||
|
/* Invalid or unsupported signature type */
|
||||||
|
VB2_SIG_INVALID = 0,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* No signature algorithm. The digest is unsigned. See
|
||||||
|
* VB2_ID_NONE_* for key IDs to use with this algorithm.
|
||||||
|
*/
|
||||||
|
VB2_SIG_NONE = 1,
|
||||||
|
|
||||||
|
/* RSA algorithms of the given length in bits (1024-8192) */
|
||||||
|
VB2_SIG_RSA1024 = 2, /* Warning! This is likely to be deprecated! */
|
||||||
|
VB2_SIG_RSA2048 = 3,
|
||||||
|
VB2_SIG_RSA4096 = 4,
|
||||||
|
VB2_SIG_RSA8192 = 5,
|
||||||
|
VB2_SIG_RSA2048_EXP3 = 6,
|
||||||
|
VB2_SIG_RSA3072_EXP3 = 7,
|
||||||
|
|
||||||
|
/* Last index. Don't add anything below. */
|
||||||
|
VB2_SIG_ALG_COUNT,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Algorithm types for hash digests */
|
||||||
|
enum vb2_hash_algorithm {
|
||||||
|
/* Invalid or unsupported digest type */
|
||||||
|
VB2_HASH_INVALID = 0,
|
||||||
|
|
||||||
|
/* SHA-1. Warning: This is likely to be deprecated soon! */
|
||||||
|
VB2_HASH_SHA1 = 1,
|
||||||
|
|
||||||
|
/* SHA-256 and SHA-512 */
|
||||||
|
VB2_HASH_SHA256 = 2,
|
||||||
|
VB2_HASH_SHA512 = 3,
|
||||||
|
|
||||||
|
/* Last index. Don't add anything below. */
|
||||||
|
VB2_HASH_ALG_COUNT,
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* VBOOT_REFERENCE_VBOOT_2CRYPTO_H_ */
|
||||||
40
firmware/coreboot/3rdparty/vboot/firmware/2lib/include/2fw_hash_tags.h
vendored
Normal file
40
firmware/coreboot/3rdparty/vboot/firmware/2lib/include/2fw_hash_tags.h
vendored
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
/* Copyright (c) 2014 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.
|
||||||
|
*
|
||||||
|
* Firmware hash tags for verified boot
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef VBOOT_REFERENCE_VBOOT_2FW_HASH_TAGS_H_
|
||||||
|
#define VBOOT_REFERENCE_VBOOT_2FW_HASH_TAGS_H_
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tags for types of hashable data.
|
||||||
|
*
|
||||||
|
* Note that not every firmware image will contain every tag.
|
||||||
|
*
|
||||||
|
* TODO: These are the ones that vboot specifically knows about given the
|
||||||
|
* current data structures. In the future, I'd really like the vboot preamble
|
||||||
|
* to contain an arbitrary list of tags and their hashes, so that we can hash
|
||||||
|
* ram init, main RW body, EC-RW for software sync, etc. all separately.
|
||||||
|
*/
|
||||||
|
enum vb2_hash_tag {
|
||||||
|
/* Invalid hash tag; never present in table */
|
||||||
|
VB2_HASH_TAG_INVALID = 0,
|
||||||
|
|
||||||
|
/* Firmware body */
|
||||||
|
VB2_HASH_TAG_FW_BODY = 1,
|
||||||
|
|
||||||
|
/* Kernel data key */
|
||||||
|
VB2_HASH_TAG_KERNEL_DATA_KEY = 2,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tags over 0x40000000 are reserved for use by the calling firmware,
|
||||||
|
* which may associate them with arbitrary types of RW firmware data
|
||||||
|
* that it wants to track.
|
||||||
|
*/
|
||||||
|
VB2_HASH_TAG_CALLER_BASE = 0x40000000
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* VBOOT_REFERENCE_VBOOT_2FW_HASH_TAGS_H_ */
|
||||||
29
firmware/coreboot/3rdparty/vboot/firmware/2lib/include/2hmac.h
vendored
Normal file
29
firmware/coreboot/3rdparty/vboot/firmware/2lib/include/2hmac.h
vendored
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/* Copyright 2016 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef VBOOT_REFERENCE_VBOOT_2HMAC_H_
|
||||||
|
#define VBOOT_REFERENCE_VBOOT_2HMAC_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "2crypto.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute HMAC
|
||||||
|
*
|
||||||
|
* @param alg Hash algorithm ID
|
||||||
|
* @param key HMAC key
|
||||||
|
* @param key_size HMAC key size
|
||||||
|
* @param msg Message to compute HMAC for
|
||||||
|
* @param msg_size Message size
|
||||||
|
* @param mac Computed message authentication code
|
||||||
|
* @param mac_size Size of the buffer pointed by <mac>
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
int hmac(enum vb2_hash_algorithm alg,
|
||||||
|
const void *key, uint32_t key_size,
|
||||||
|
const void *msg, uint32_t msg_size,
|
||||||
|
uint8_t *mac, uint32_t mac_size);
|
||||||
|
|
||||||
|
#endif
|
||||||
28
firmware/coreboot/3rdparty/vboot/firmware/2lib/include/2id.h
vendored
Normal file
28
firmware/coreboot/3rdparty/vboot/firmware/2lib/include/2id.h
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
/* Copyright 2015 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.
|
||||||
|
*
|
||||||
|
* Key ID, used to quickly match keys with signatures. There's not a standard
|
||||||
|
* fingerprint for private keys, so we're using the sha1sum of the public key
|
||||||
|
* in our keyb format. Pretty much anything would work as long as it's
|
||||||
|
* resistant to collisions and easy to compare.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef VBOOT_REFERENCE_VBOOT_2ID_H_
|
||||||
|
#define VBOOT_REFERENCE_VBOOT_2ID_H_
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define VB2_ID_NUM_BYTES 20
|
||||||
|
|
||||||
|
struct vb2_id {
|
||||||
|
uint8_t raw[VB2_ID_NUM_BYTES];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
#define EXPECTED_ID_SIZE VB2_ID_NUM_BYTES
|
||||||
|
|
||||||
|
/* IDs to use for "keys" with sig_alg==VB2_SIG_NONE */
|
||||||
|
#define VB2_ID_NONE_SHA1 {{0x00, 0x01,}}
|
||||||
|
#define VB2_ID_NONE_SHA256 {{0x02, 0x56,}}
|
||||||
|
#define VB2_ID_NONE_SHA512 {{0x05, 0x12,}}
|
||||||
|
|
||||||
|
#endif /* VBOOT_REFERENCE_VBOOT_2ID_H_ */
|
||||||
177
firmware/coreboot/3rdparty/vboot/firmware/2lib/include/2misc.h
vendored
Normal file
177
firmware/coreboot/3rdparty/vboot/firmware/2lib/include/2misc.h
vendored
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
/* Copyright (c) 2014 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.
|
||||||
|
*
|
||||||
|
* Misc functions which need access to vb2_context but are not public APIs
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef VBOOT_REFERENCE_VBOOT_2MISC_H_
|
||||||
|
#define VBOOT_REFERENCE_VBOOT_2MISC_H_
|
||||||
|
|
||||||
|
#include "2api.h"
|
||||||
|
|
||||||
|
struct vb2_gbb_header;
|
||||||
|
struct vb2_workbuf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the shared data pointer from the vboot context
|
||||||
|
*
|
||||||
|
* @param ctx Vboot context
|
||||||
|
* @return The shared data pointer.
|
||||||
|
*/
|
||||||
|
static __inline struct vb2_shared_data *vb2_get_sd(struct vb2_context *ctx) {
|
||||||
|
return (struct vb2_shared_data *)ctx->workbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate gbb signature (the magic number)
|
||||||
|
*
|
||||||
|
* @param sig Pointer to the signature bytes to validate
|
||||||
|
* @return VB2_SUCCESS if valid or non-zero if error.
|
||||||
|
*/
|
||||||
|
int vb2_validate_gbb_signature(uint8_t *sig);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize a work buffer from the vboot context.
|
||||||
|
*
|
||||||
|
* This sets the work buffer to the unused portion of the context work buffer.
|
||||||
|
*
|
||||||
|
* @param ctx Vboot context
|
||||||
|
* @param wb Work buffer to initialize
|
||||||
|
*/
|
||||||
|
void vb2_workbuf_from_ctx(struct vb2_context *ctx, struct vb2_workbuf *wb);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the amount of work buffer used in the vboot context.
|
||||||
|
*
|
||||||
|
* This will round up to VB2_WORKBUF_ALIGN, so that the next allocation will
|
||||||
|
* be aligned as expected.
|
||||||
|
*
|
||||||
|
* @param ctx Vboot context
|
||||||
|
* @param used Number of bytes used
|
||||||
|
*/
|
||||||
|
void vb2_set_workbuf_used(struct vb2_context *ctx, uint32_t used);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the GBB header.
|
||||||
|
*
|
||||||
|
* @param ctx Vboot context
|
||||||
|
* @param gbb Destination for header
|
||||||
|
* @return VB2_SUCCESS, or non-zero if error.
|
||||||
|
*/
|
||||||
|
int vb2_read_gbb_header(struct vb2_context *ctx, struct vb2_gbb_header *gbb);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle vboot failure.
|
||||||
|
*
|
||||||
|
* If the failure occurred after choosing a firmware slot, and the other
|
||||||
|
* firmware slot is not known-bad, try the other firmware slot after reboot.
|
||||||
|
*
|
||||||
|
* If the failure occurred before choosing a firmware slot, or both slots have
|
||||||
|
* failed in successive boots, request recovery.
|
||||||
|
*
|
||||||
|
* @param reason Recovery reason
|
||||||
|
* @param subcode Recovery subcode
|
||||||
|
*/
|
||||||
|
void vb2_fail(struct vb2_context *ctx, uint8_t reason, uint8_t subcode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set up the verified boot context data, if not already set up.
|
||||||
|
*
|
||||||
|
* This uses ctx->workbuf_used=0 as a flag to indicate that the data has not
|
||||||
|
* yet been set up. Caller must set that before calling any vboot functions;
|
||||||
|
* see 2api.h.
|
||||||
|
*
|
||||||
|
* @param ctx Vboot context to initialize
|
||||||
|
* @return VB2_SUCCESS, or error code on error.
|
||||||
|
*/
|
||||||
|
int vb2_init_context(struct vb2_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check for recovery reasons we can determine early in the boot process.
|
||||||
|
*
|
||||||
|
* On exit, check ctx->flags for VB2_CONTEXT_RECOVERY_MODE; if present, jump to
|
||||||
|
* the recovery path instead of continuing with normal boot. This is the only
|
||||||
|
* direct path to recovery mode. All other errors later in the boot process
|
||||||
|
* should induce a reboot instead of jumping to recovery, so that recovery mode
|
||||||
|
* starts from a consistent firmware state.
|
||||||
|
*
|
||||||
|
* @param ctx Vboot context
|
||||||
|
*/
|
||||||
|
void vb2_check_recovery(struct vb2_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the GBB header.
|
||||||
|
*
|
||||||
|
* @param ctx Vboot context
|
||||||
|
* @return VB2_SUCCESS, or error code on error.
|
||||||
|
*/
|
||||||
|
int vb2_fw_parse_gbb(struct vb2_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check developer switch position.
|
||||||
|
*
|
||||||
|
* @param ctx Vboot context
|
||||||
|
* @return VB2_SUCCESS, or error code on error.
|
||||||
|
*/
|
||||||
|
int vb2_check_dev_switch(struct vb2_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if we need to clear the TPM owner.
|
||||||
|
*
|
||||||
|
* @param ctx Vboot context
|
||||||
|
* @return VB2_SUCCESS, or error code on error.
|
||||||
|
*/
|
||||||
|
int vb2_check_tpm_clear(struct vb2_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decide which firmware slot to try this boot.
|
||||||
|
*
|
||||||
|
* @param ctx Vboot context
|
||||||
|
* @return VB2_SUCCESS, or error code on error.
|
||||||
|
*/
|
||||||
|
int vb2_select_fw_slot(struct vb2_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify the firmware keyblock using the root key.
|
||||||
|
*
|
||||||
|
* After this call, the data key is stored in the work buffer.
|
||||||
|
*
|
||||||
|
* @param ctx Vboot context
|
||||||
|
* @return VB2_SUCCESS, or error code on error.
|
||||||
|
*/
|
||||||
|
int vb2_load_fw_keyblock(struct vb2_context *ctx);
|
||||||
|
int vb21_load_fw_keyblock(struct vb2_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify the firmware preamble using the data subkey from the keyblock.
|
||||||
|
*
|
||||||
|
* After this call, the preamble is stored in the work buffer.
|
||||||
|
*
|
||||||
|
* @param ctx Vboot context
|
||||||
|
* @return VB2_SUCCESS, or error code on error.
|
||||||
|
*/
|
||||||
|
int vb2_load_fw_preamble(struct vb2_context *ctx);
|
||||||
|
int vb21_load_fw_preamble(struct vb2_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify the kernel keyblock using the previously-loaded kernel key.
|
||||||
|
*
|
||||||
|
* After this call, the data key is stored in the work buffer.
|
||||||
|
*
|
||||||
|
* @param ctx Vboot context
|
||||||
|
* @return VB2_SUCCESS, or error code on error.
|
||||||
|
*/
|
||||||
|
int vb2_load_kernel_keyblock(struct vb2_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify the kernel preamble using the data subkey from the keyblock.
|
||||||
|
*
|
||||||
|
* After this call, the preamble is stored in the work buffer.
|
||||||
|
*
|
||||||
|
* @param ctx Vboot context
|
||||||
|
* @return VB2_SUCCESS, or error code on error.
|
||||||
|
*/
|
||||||
|
int vb2_load_kernel_preamble(struct vb2_context *ctx);
|
||||||
|
|
||||||
|
#endif /* VBOOT_REFERENCE_VBOOT_2MISC_H_ */
|
||||||
223
firmware/coreboot/3rdparty/vboot/firmware/2lib/include/2nvstorage.h
vendored
Normal file
223
firmware/coreboot/3rdparty/vboot/firmware/2lib/include/2nvstorage.h
vendored
Normal file
@@ -0,0 +1,223 @@
|
|||||||
|
/* Copyright (c) 2014 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.
|
||||||
|
*
|
||||||
|
* Non-volatile storage routines
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef VBOOT_REFERENCE_VBOOT_2NVSTORAGE_H_
|
||||||
|
#define VBOOT_REFERENCE_VBOOT_2NVSTORAGE_H_
|
||||||
|
|
||||||
|
struct vb2_context;
|
||||||
|
|
||||||
|
enum vb2_nv_param {
|
||||||
|
/*
|
||||||
|
* Parameter values have been reset to defaults (flag for firmware).
|
||||||
|
* 0=clear; 1=set.
|
||||||
|
*/
|
||||||
|
VB2_NV_FIRMWARE_SETTINGS_RESET = 0,
|
||||||
|
/*
|
||||||
|
* Parameter values have been reset to defaults (flag for kernel).
|
||||||
|
* 0=clear; 1=set.
|
||||||
|
*/
|
||||||
|
VB2_NV_KERNEL_SETTINGS_RESET,
|
||||||
|
/* Request debug reset on next S3->S0 transition. 0=clear; 1=set. */
|
||||||
|
VB2_NV_DEBUG_RESET_MODE,
|
||||||
|
/* Firmware slot to try next. 0=A, 1=B */
|
||||||
|
VB2_NV_TRY_NEXT,
|
||||||
|
/*
|
||||||
|
* Number of times to try booting RW firmware slot B before slot A.
|
||||||
|
* Valid range: 0-15.
|
||||||
|
*
|
||||||
|
* For VB2, number of times to try booting the slot indicated by
|
||||||
|
* VB2_NV_TRY_NEXT. On a 1->0 transition of try count, VB2_NV_TRY_NEXT
|
||||||
|
* will be set to the other slot.
|
||||||
|
*/
|
||||||
|
VB2_NV_TRY_COUNT,
|
||||||
|
/*
|
||||||
|
* Request recovery mode on next boot; see 2recovery_reason.h for
|
||||||
|
* currently defined reason codes. 8-bit value.
|
||||||
|
*/
|
||||||
|
VB2_NV_RECOVERY_REQUEST,
|
||||||
|
/*
|
||||||
|
* Localization index for screen bitmaps displayed by firmware.
|
||||||
|
* 8-bit value.
|
||||||
|
*/
|
||||||
|
VB2_NV_LOCALIZATION_INDEX,
|
||||||
|
/* Field reserved for kernel/user-mode use; 16-bit value. */
|
||||||
|
VB2_NV_KERNEL_FIELD,
|
||||||
|
/* Allow booting from USB in developer mode. 0=no, 1=yes. */
|
||||||
|
VB2_NV_DEV_BOOT_USB,
|
||||||
|
/* Allow booting of legacy OSes in developer mode. 0=no, 1=yes. */
|
||||||
|
VB2_NV_DEV_BOOT_LEGACY,
|
||||||
|
/* Only boot Google-signed images in developer mode. 0=no, 1=yes. */
|
||||||
|
VB2_NV_DEV_BOOT_SIGNED_ONLY,
|
||||||
|
/*
|
||||||
|
* Allow full fastboot capability in firmware in developer mode.
|
||||||
|
* 0=no, 1=yes.
|
||||||
|
*/
|
||||||
|
VB2_NV_DEV_BOOT_FASTBOOT_FULL_CAP,
|
||||||
|
/* Set default boot mode (see vb2_dev_default_boot) */
|
||||||
|
VB2_NV_DEV_DEFAULT_BOOT,
|
||||||
|
/* Enable USB Device Controller */
|
||||||
|
VB2_NV_DEV_ENABLE_UDC,
|
||||||
|
/*
|
||||||
|
* Set by userspace to request that RO firmware disable dev-mode on the
|
||||||
|
* next boot. This is likely only possible if the dev-switch is
|
||||||
|
* virtual.
|
||||||
|
*/
|
||||||
|
VB2_NV_DISABLE_DEV_REQUEST,
|
||||||
|
/*
|
||||||
|
* Set and cleared by vboot to request that the video Option ROM be
|
||||||
|
* loaded at boot time, so that BIOS screens can be displayed. 0=no,
|
||||||
|
* 1=yes.
|
||||||
|
*/
|
||||||
|
VB2_NV_OPROM_NEEDED,
|
||||||
|
/* Request that the firmware clear the TPM owner on the next boot. */
|
||||||
|
VB2_NV_CLEAR_TPM_OWNER_REQUEST,
|
||||||
|
/* Flag that TPM owner was cleared on request. */
|
||||||
|
VB2_NV_CLEAR_TPM_OWNER_DONE,
|
||||||
|
/* TPM requested a reboot already. */
|
||||||
|
VB2_NV_TPM_REQUESTED_REBOOT,
|
||||||
|
/* More details on recovery reason */
|
||||||
|
VB2_NV_RECOVERY_SUBCODE,
|
||||||
|
/* Request that NVRAM be backed up at next boot if possible. */
|
||||||
|
VB2_NV_BACKUP_NVRAM_REQUEST,
|
||||||
|
/* Firmware slot tried this boot (0=A, 1=B) */
|
||||||
|
VB2_NV_FW_TRIED,
|
||||||
|
/* Result of trying that firmware (see vb2_fw_result) */
|
||||||
|
VB2_NV_FW_RESULT,
|
||||||
|
/* Firmware slot tried previous boot (0=A, 1=B) */
|
||||||
|
VB2_NV_FW_PREV_TRIED,
|
||||||
|
/* Result of trying that firmware (see vb2_fw_result) */
|
||||||
|
VB2_NV_FW_PREV_RESULT,
|
||||||
|
/* Request wipeout of the device by the app. */
|
||||||
|
VB2_NV_REQ_WIPEOUT,
|
||||||
|
|
||||||
|
/* Fastboot: Unlock in firmware, 0=disabled, 1=enabled. */
|
||||||
|
VB2_NV_FASTBOOT_UNLOCK_IN_FW,
|
||||||
|
/* Boot system when AC detected (0=no, 1=yes). */
|
||||||
|
VB2_NV_BOOT_ON_AC_DETECT,
|
||||||
|
/*
|
||||||
|
* Try to update the EC-RO image after updating the EC-RW image
|
||||||
|
* (0=no, 1=yes).
|
||||||
|
*/
|
||||||
|
VB2_NV_TRY_RO_SYNC,
|
||||||
|
/* Cut off battery and shutdown on next boot. */
|
||||||
|
VB2_NV_BATTERY_CUTOFF_REQUEST,
|
||||||
|
/* Maximum kernel version to roll forward to */
|
||||||
|
VB2_NV_KERNEL_MAX_ROLLFORWARD,
|
||||||
|
|
||||||
|
/*** Fields only available in NV storage V2 ***/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Maximum firmware version to roll forward to. Returns
|
||||||
|
* VB2_MAX_ROLLFORWARD_MAX_V1_DEFAULT for V1.
|
||||||
|
*/
|
||||||
|
VB2_NV_FW_MAX_ROLLFORWARD,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Set default boot in developer mode */
|
||||||
|
enum vb2_dev_default_boot {
|
||||||
|
/* Default to boot from disk*/
|
||||||
|
VB2_DEV_DEFAULT_BOOT_DISK = 0,
|
||||||
|
|
||||||
|
/* Default to boot from USB */
|
||||||
|
VB2_DEV_DEFAULT_BOOT_USB = 1,
|
||||||
|
|
||||||
|
/* Default to boot legacy OS */
|
||||||
|
VB2_DEV_DEFAULT_BOOT_LEGACY = 2,
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Firmware result codes for VB2_NV_FW_RESULT and VB2_NV_FW_PREV_RESULT */
|
||||||
|
enum vb2_fw_result {
|
||||||
|
/* Unknown */
|
||||||
|
VB2_FW_RESULT_UNKNOWN = 0,
|
||||||
|
|
||||||
|
/* Trying a new slot, but haven't reached success/failure */
|
||||||
|
VB2_FW_RESULT_TRYING = 1,
|
||||||
|
|
||||||
|
/* Successfully booted to the OS */
|
||||||
|
VB2_FW_RESULT_SUCCESS = 2,
|
||||||
|
|
||||||
|
/* Known failure */
|
||||||
|
VB2_FW_RESULT_FAILURE = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Default value for VB2_NV_FIRMWARE_MAX_ROLLFORWARD on V1. This preserves the
|
||||||
|
* existing behavior that V1 systems will always roll forward the firmware
|
||||||
|
* version when possible.
|
||||||
|
*/
|
||||||
|
#define VB2_FW_MAX_ROLLFORWARD_V1_DEFAULT 0xfffffffe
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the size of the non-volatile storage data in the context.
|
||||||
|
*
|
||||||
|
* This may be called before vb2_context_init(), but you must set
|
||||||
|
* VB2_CONTEXT_NVDATA_V2 if you support V2 record size.
|
||||||
|
*
|
||||||
|
* @param ctx Context pointer
|
||||||
|
* @return Size of the non-volatile storage data in bytes.
|
||||||
|
*/
|
||||||
|
int vb2_nv_get_size(const struct vb2_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check the CRC of the non-volatile storage context.
|
||||||
|
*
|
||||||
|
* Use this if reading from non-volatile storage may be flaky, and you want to
|
||||||
|
* retry reading it several times.
|
||||||
|
*
|
||||||
|
* This may be called before vb2_context_init().
|
||||||
|
*
|
||||||
|
* @param ctx Context pointer
|
||||||
|
* @return VB2_SUCCESS, or non-zero error code if error.
|
||||||
|
*/
|
||||||
|
int vb2_nv_check_crc(const struct vb2_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the non-volatile storage context and verify its CRC.
|
||||||
|
*
|
||||||
|
* This may be called before vb2_context_init(), as long as:
|
||||||
|
*
|
||||||
|
* 1) The ctx structure has been cleared to 0.
|
||||||
|
* 2) Existing non-volatile data, if any, has been stored to ctx->nvdata[].
|
||||||
|
*
|
||||||
|
* This is to support using the non-volatile storage functions to request
|
||||||
|
* recovery if there is an error allocating the workbuf for the context. It
|
||||||
|
* also allows host-side code to use this library without setting up a bunch of
|
||||||
|
* extra context.
|
||||||
|
*
|
||||||
|
* @param ctx Context pointer
|
||||||
|
*/
|
||||||
|
void vb2_nv_init(struct vb2_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a non-volatile value.
|
||||||
|
*
|
||||||
|
* Valid only after calling vb2_nv_init().
|
||||||
|
*
|
||||||
|
* @param ctx Context pointer
|
||||||
|
* @param param Parameter to read
|
||||||
|
* @return The value of the parameter. If you somehow force an invalid
|
||||||
|
* parameter number, returns 0.
|
||||||
|
*/
|
||||||
|
uint32_t vb2_nv_get(struct vb2_context *ctx, enum vb2_nv_param param);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a non-volatile value.
|
||||||
|
*
|
||||||
|
* Ignores writes to unknown params. Valid only after calling vb2_nv_init().
|
||||||
|
* If this changes ctx->nvdata[], it will set VB2_CONTEXT_NVDATA_CHANGED in
|
||||||
|
* ctx->flags.
|
||||||
|
*
|
||||||
|
* @param ctx Context pointer
|
||||||
|
* @param param Parameter to write
|
||||||
|
* @param value New value
|
||||||
|
*/
|
||||||
|
void vb2_nv_set(struct vb2_context *ctx,
|
||||||
|
enum vb2_nv_param param,
|
||||||
|
uint32_t value);
|
||||||
|
|
||||||
|
#endif /* VBOOT_REFERENCE_VBOOT_2NVSTORAGE_H_ */
|
||||||
110
firmware/coreboot/3rdparty/vboot/firmware/2lib/include/2nvstorage_fields.h
vendored
Normal file
110
firmware/coreboot/3rdparty/vboot/firmware/2lib/include/2nvstorage_fields.h
vendored
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
/* Copyright 2015 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.
|
||||||
|
*
|
||||||
|
* Non-volatile storage bitfields
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef VBOOT_REFERENCE_VBOOT_2NVSTORAGE_FIELDS_H_
|
||||||
|
#define VBOOT_REFERENCE_VBOOT_2NVSTORAGE_FIELDS_H_
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Constants for NV storage. We use this rather than structs and bitfields so
|
||||||
|
* the data format is consistent across platforms and compilers. Total NV
|
||||||
|
* storage size is:
|
||||||
|
*
|
||||||
|
* Version 1: VB2_NVDATA_SIZE = 16 bytes
|
||||||
|
* Version 2: VB2_NVDATA_SIZE_V2 = 64 bytes
|
||||||
|
*
|
||||||
|
* Unused bits/bytes must be set to 0.
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum vb2_nv_offset {
|
||||||
|
/*** The following fields are present in all versions ***/
|
||||||
|
VB2_NV_OFFS_HEADER = 0,
|
||||||
|
VB2_NV_OFFS_BOOT = 1,
|
||||||
|
VB2_NV_OFFS_RECOVERY = 2,
|
||||||
|
VB2_NV_OFFS_LOCALIZATION = 3,
|
||||||
|
VB2_NV_OFFS_DEV = 4,
|
||||||
|
VB2_NV_OFFS_TPM = 5,
|
||||||
|
VB2_NV_OFFS_RECOVERY_SUBCODE = 6,
|
||||||
|
VB2_NV_OFFS_BOOT2 = 7,
|
||||||
|
VB2_NV_OFFS_MISC = 8,
|
||||||
|
VB2_NV_OFFS_KERNEL_MAX_ROLLFORWARD1 = 9, /* bits 0-7 of 32 */
|
||||||
|
VB2_NV_OFFS_KERNEL_MAX_ROLLFORWARD2 = 10, /* bits 8-15 of 32 */
|
||||||
|
VB2_NV_OFFS_KERNEL1 = 11, /* bits 0-7 of 16 */
|
||||||
|
VB2_NV_OFFS_KERNEL2 = 12, /* bits 8-15 of 16 */
|
||||||
|
VB2_NV_OFFS_KERNEL_MAX_ROLLFORWARD3 = 13, /* bits 16-23 of 32 */
|
||||||
|
VB2_NV_OFFS_KERNEL_MAX_ROLLFORWARD4 = 14, /* bits 24-31 of 32 */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CRC_V1 must be last field in V1. This byte can be reused in later
|
||||||
|
* versions.
|
||||||
|
*/
|
||||||
|
VB2_NV_OFFS_CRC_V1 = 15,
|
||||||
|
|
||||||
|
/* The following fields are only present in V2+ */
|
||||||
|
VB2_NV_OFFS_RESERVED_V2 = 15, /* Was CRC in V1 (unused = 0xff) */
|
||||||
|
VB2_NV_OFFS_FW_MAX_ROLLFORWARD1 = 16, /* bits 0-7 of 32 */
|
||||||
|
VB2_NV_OFFS_FW_MAX_ROLLFORWARD2 = 17, /* bits 8-15 of 32 */
|
||||||
|
VB2_NV_OFFS_FW_MAX_ROLLFORWARD3 = 18, /* bits 16-23 of 32 */
|
||||||
|
VB2_NV_OFFS_FW_MAX_ROLLFORWARD4 = 19, /* bits 24-31 of 32 */
|
||||||
|
|
||||||
|
/* CRC must be last field */
|
||||||
|
VB2_NV_OFFS_CRC_V2 = 63,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Fields in VB2_NV_OFFS_HEADER (unused = 0x04) */
|
||||||
|
#define VB2_NV_HEADER_WIPEOUT 0x08
|
||||||
|
#define VB2_NV_HEADER_KERNEL_SETTINGS_RESET 0x10
|
||||||
|
#define VB2_NV_HEADER_FW_SETTINGS_RESET 0x20
|
||||||
|
#define VB2_NV_HEADER_SIGNATURE_MASK 0xc3
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Valid signature values. Note that V1 readers only looked at mask 0xc0, and
|
||||||
|
* expect it to have value 0x40. Versions != V1 must have the top two bits !=
|
||||||
|
* 0x40 so old readers will reject the data. Using all 1-bits or all 0-bits is
|
||||||
|
* also discouraged, because that is indistinguishable from all-erased data on
|
||||||
|
* some platforms.
|
||||||
|
*/
|
||||||
|
/* Version 1 = 16-byte record */
|
||||||
|
#define VB2_NV_HEADER_SIGNATURE_V1 0x40
|
||||||
|
/* Version 2 = 64-byte record */
|
||||||
|
#define VB2_NV_HEADER_SIGNATURE_V2 0x03
|
||||||
|
|
||||||
|
/* Fields in VB2_NV_OFFS_BOOT */
|
||||||
|
#define VB2_NV_BOOT_TRY_COUNT_MASK 0x0f
|
||||||
|
#define VB2_NV_BOOT_BACKUP_NVRAM 0x10
|
||||||
|
#define VB2_NV_BOOT_OPROM_NEEDED 0x20
|
||||||
|
#define VB2_NV_BOOT_DISABLE_DEV 0x40
|
||||||
|
#define VB2_NV_BOOT_DEBUG_RESET 0x80
|
||||||
|
|
||||||
|
/* Fields in VB2_NV_OFFS_BOOT2 (unused = 0x80) */
|
||||||
|
#define VB2_NV_BOOT2_RESULT_MASK 0x03
|
||||||
|
#define VB2_NV_BOOT2_TRIED 0x04
|
||||||
|
#define VB2_NV_BOOT2_TRY_NEXT 0x08
|
||||||
|
#define VB2_NV_BOOT2_PREV_RESULT_MASK 0x30
|
||||||
|
#define VB2_NV_BOOT2_PREV_RESULT_SHIFT 4 /* Number of bits to shift result */
|
||||||
|
#define VB2_NV_BOOT2_PREV_TRIED 0x40
|
||||||
|
|
||||||
|
/* Fields in VB2_NV_OFFS_DEV (unused = 0x80) */
|
||||||
|
#define VB2_NV_DEV_FLAG_USB 0x01
|
||||||
|
#define VB2_NV_DEV_FLAG_SIGNED_ONLY 0x02
|
||||||
|
#define VB2_NV_DEV_FLAG_LEGACY 0x04
|
||||||
|
#define VB2_NV_DEV_FLAG_FASTBOOT_FULL_CAP 0x08
|
||||||
|
#define VB2_NV_DEV_FLAG_DEFAULT_BOOT 0x30
|
||||||
|
#define VB2_NV_DEV_DEFAULT_BOOT_SHIFT 4 /* Number of bits to shift */
|
||||||
|
#define VB2_NV_DEV_FLAG_UDC 0x40
|
||||||
|
|
||||||
|
/* Fields in VB2_NV_OFFS_TPM (unused = 0xf8) */
|
||||||
|
#define VB2_NV_TPM_CLEAR_OWNER_REQUEST 0x01
|
||||||
|
#define VB2_NV_TPM_CLEAR_OWNER_DONE 0x02
|
||||||
|
#define VB2_NV_TPM_REBOOTED 0x04
|
||||||
|
|
||||||
|
/* Fields in VB2_NV_OFFS_MISC (unused = 0xf0) */
|
||||||
|
#define VB2_NV_MISC_UNLOCK_FASTBOOT 0x01
|
||||||
|
#define VB2_NV_MISC_BOOT_ON_AC_DETECT 0x02
|
||||||
|
#define VB2_NV_MISC_TRY_RO_SYNC 0x04
|
||||||
|
#define VB2_NV_MISC_BATTERY_CUTOFF 0x08
|
||||||
|
|
||||||
|
#endif /* VBOOT_REFERENCE_VBOOT_2NVSTORAGE_FIELDS_H_ */
|
||||||
247
firmware/coreboot/3rdparty/vboot/firmware/2lib/include/2recovery_reasons.h
vendored
Normal file
247
firmware/coreboot/3rdparty/vboot/firmware/2lib/include/2recovery_reasons.h
vendored
Normal file
@@ -0,0 +1,247 @@
|
|||||||
|
/* Copyright (c) 2014 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.
|
||||||
|
*
|
||||||
|
* Recovery reasons
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef VBOOT_REFERENCE_VBOOT_2RECOVERY_REASONS_H_
|
||||||
|
#define VBOOT_REFERENCE_VBOOT_2RECOVERY_REASONS_H_
|
||||||
|
|
||||||
|
/* Recovery reason codes */
|
||||||
|
enum vb2_nv_recovery {
|
||||||
|
/* Recovery not requested. */
|
||||||
|
VB2_RECOVERY_NOT_REQUESTED = 0x00,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Recovery requested from legacy utility. (Prior to the NV storage
|
||||||
|
* spec, recovery mode was a single bitfield; this value is reserved so
|
||||||
|
* that scripts which wrote 1 to the recovery field are distinguishable
|
||||||
|
* from scripts whch use the recovery reasons listed here.
|
||||||
|
*/
|
||||||
|
VB2_RECOVERY_LEGACY = 0x01,
|
||||||
|
|
||||||
|
/* User manually requested recovery via recovery button */
|
||||||
|
VB2_RECOVERY_RO_MANUAL = 0x02,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RW firmware failed signature check (neither RW firmware slot was
|
||||||
|
* valid)
|
||||||
|
*/
|
||||||
|
VB2_RECOVERY_RO_INVALID_RW = 0x03,
|
||||||
|
|
||||||
|
/* S3 resume failed */
|
||||||
|
VB2_RECOVERY_RO_S3_RESUME = 0x04,
|
||||||
|
|
||||||
|
/* TPM error in read-only firmware (deprecated) */
|
||||||
|
VB2_RECOVERY_DEP_RO_TPM_ERROR = 0x05,
|
||||||
|
|
||||||
|
/* Shared data error in read-only firmware */
|
||||||
|
VB2_RECOVERY_RO_SHARED_DATA = 0x06,
|
||||||
|
|
||||||
|
/* Test error from S3Resume() */
|
||||||
|
VB2_RECOVERY_RO_TEST_S3 = 0x07,
|
||||||
|
|
||||||
|
/* Test error from LoadFirmwareSetup() (deprecated) */
|
||||||
|
VB2_RECOVERY_RO_TEST_LFS = 0x08,
|
||||||
|
|
||||||
|
/* Test error from LoadFirmware() (deprecated) */
|
||||||
|
VB2_RECOVERY_RO_TEST_LF = 0x09,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RW firmware failed signature check (neither RW firmware slot was
|
||||||
|
* valid). Recovery reason is VB2_RECOVERY_RO_INVALID_RW_CHECK_MIN +
|
||||||
|
* the check value for the slot which came closest to validating; see
|
||||||
|
* VBSD_LF_CHECK_* in vboot_struct.h.
|
||||||
|
*/
|
||||||
|
VB2_RECOVERY_RO_INVALID_RW_CHECK_MIN = 0x10,
|
||||||
|
|
||||||
|
/* Latest tried RW firmware keyblock verification failed */
|
||||||
|
VB2_RECOVERY_FW_KEYBLOCK = 0x13,
|
||||||
|
|
||||||
|
/* Latest tried RW firmware key version too old */
|
||||||
|
VB2_RECOVERY_FW_KEY_ROLLBACK = 0x14,
|
||||||
|
|
||||||
|
/* Latest tried RW firmware preamble verification failed */
|
||||||
|
VB2_RECOVERY_FW_PREAMBLE = 0x16,
|
||||||
|
|
||||||
|
/* Latest tried RW firmware version too old */
|
||||||
|
VB2_RECOVERY_FW_ROLLBACK = 0x17,
|
||||||
|
|
||||||
|
/* Latest tried RW firmware body verification failed */
|
||||||
|
VB2_RECOVERY_FW_BODY = 0x1b,
|
||||||
|
|
||||||
|
/* Highest reason for failed RW firmware signature check */
|
||||||
|
VB2_RECOVERY_RO_INVALID_RW_CHECK_MAX = 0x1f,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Firmware boot failure outside of verified boot (RAM init, missing
|
||||||
|
* SSD, etc.).
|
||||||
|
*/
|
||||||
|
VB2_RECOVERY_RO_FIRMWARE = 0x20,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Recovery mode TPM initialization requires a system reboot. The
|
||||||
|
* system was already in recovery mode for some other reason when this
|
||||||
|
* happened.
|
||||||
|
*/
|
||||||
|
VB2_RECOVERY_RO_TPM_REBOOT = 0x21,
|
||||||
|
|
||||||
|
/* EC software sync - other error */
|
||||||
|
VB2_RECOVERY_EC_SOFTWARE_SYNC = 0x22,
|
||||||
|
|
||||||
|
/* EC software sync - unable to determine active EC image */
|
||||||
|
VB2_RECOVERY_EC_UNKNOWN_IMAGE = 0x23,
|
||||||
|
|
||||||
|
/* EC software sync - error obtaining EC image hash (deprecated) */
|
||||||
|
VB2_RECOVERY_DEP_EC_HASH = 0x24,
|
||||||
|
|
||||||
|
/* EC software sync - error obtaining expected EC image */
|
||||||
|
VB2_RECOVERY_EC_EXPECTED_IMAGE = 0x25,
|
||||||
|
|
||||||
|
/* EC software sync - error updating EC */
|
||||||
|
VB2_RECOVERY_EC_UPDATE = 0x26,
|
||||||
|
|
||||||
|
/* EC software sync - unable to jump to EC-RW */
|
||||||
|
VB2_RECOVERY_EC_JUMP_RW = 0x27,
|
||||||
|
|
||||||
|
/* EC software sync - unable to protect / unprotect EC-RW */
|
||||||
|
VB2_RECOVERY_EC_PROTECT = 0x28,
|
||||||
|
|
||||||
|
/* EC software sync - error obtaining expected EC hash */
|
||||||
|
VB2_RECOVERY_EC_EXPECTED_HASH = 0x29,
|
||||||
|
|
||||||
|
/* EC software sync - expected EC image doesn't match hash */
|
||||||
|
VB2_RECOVERY_EC_HASH_MISMATCH = 0x2a,
|
||||||
|
|
||||||
|
/* New error codes from VB2 */
|
||||||
|
/* TODO: may need to add strings for these in the original fwlib */
|
||||||
|
|
||||||
|
/* Secure data inititalization error */
|
||||||
|
VB2_RECOVERY_SECDATA_INIT = 0x2b,
|
||||||
|
|
||||||
|
/* GBB header is bad */
|
||||||
|
VB2_RECOVERY_GBB_HEADER = 0x2c,
|
||||||
|
|
||||||
|
/* Unable to clear TPM owner */
|
||||||
|
VB2_RECOVERY_TPM_CLEAR_OWNER = 0x2d,
|
||||||
|
|
||||||
|
/* Error determining/updating virtual dev switch */
|
||||||
|
VB2_RECOVERY_DEV_SWITCH = 0x2e,
|
||||||
|
|
||||||
|
/* Error determining firmware slot */
|
||||||
|
VB2_RECOVERY_FW_SLOT = 0x2f,
|
||||||
|
|
||||||
|
/* Error updating AUX firmware */
|
||||||
|
VB2_RECOVERY_AUX_FW_UPDATE = 0x30,
|
||||||
|
|
||||||
|
/* Unspecified/unknown error in read-only firmware */
|
||||||
|
VB2_RECOVERY_RO_UNSPECIFIED = 0x3f,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* User manually requested recovery by pressing a key at developer
|
||||||
|
* warning screen
|
||||||
|
*/
|
||||||
|
VB2_RECOVERY_RW_DEV_SCREEN = 0x41,
|
||||||
|
|
||||||
|
/* No OS kernel detected */
|
||||||
|
VB2_RECOVERY_RW_NO_OS = 0x42,
|
||||||
|
|
||||||
|
/* OS kernel failed signature check */
|
||||||
|
VB2_RECOVERY_RW_INVALID_OS = 0x43,
|
||||||
|
|
||||||
|
/* TPM error in rewritable firmware (deprecated) */
|
||||||
|
VB2_RECOVERY_DEP_RW_TPM_ERROR = 0x44,
|
||||||
|
|
||||||
|
/* RW firmware in dev mode, but dev switch is off */
|
||||||
|
VB2_RECOVERY_RW_DEV_MISMATCH = 0x45,
|
||||||
|
|
||||||
|
/* Shared data error in rewritable firmware */
|
||||||
|
VB2_RECOVERY_RW_SHARED_DATA = 0x46,
|
||||||
|
|
||||||
|
/* Test error from LoadKernel() */
|
||||||
|
VB2_RECOVERY_RW_TEST_LK = 0x47,
|
||||||
|
|
||||||
|
/* No bootable disk found (deprecated)*/
|
||||||
|
VB2_RECOVERY_DEP_RW_NO_DISK = 0x48,
|
||||||
|
|
||||||
|
/* Rebooting did not correct TPM_E_FAIL or TPM_E_FAILEDSELFTEST */
|
||||||
|
VB2_RECOVERY_TPM_E_FAIL = 0x49,
|
||||||
|
|
||||||
|
/* TPM setup error in read-only firmware */
|
||||||
|
VB2_RECOVERY_RO_TPM_S_ERROR = 0x50,
|
||||||
|
|
||||||
|
/* TPM write error in read-only firmware */
|
||||||
|
VB2_RECOVERY_RO_TPM_W_ERROR = 0x51,
|
||||||
|
|
||||||
|
/* TPM lock error in read-only firmware */
|
||||||
|
VB2_RECOVERY_RO_TPM_L_ERROR = 0x52,
|
||||||
|
|
||||||
|
/* TPM update error in read-only firmware */
|
||||||
|
VB2_RECOVERY_RO_TPM_U_ERROR = 0x53,
|
||||||
|
|
||||||
|
/* TPM read error in rewritable firmware */
|
||||||
|
VB2_RECOVERY_RW_TPM_R_ERROR = 0x54,
|
||||||
|
|
||||||
|
/* TPM write error in rewritable firmware */
|
||||||
|
VB2_RECOVERY_RW_TPM_W_ERROR = 0x55,
|
||||||
|
|
||||||
|
/* TPM lock error in rewritable firmware */
|
||||||
|
VB2_RECOVERY_RW_TPM_L_ERROR = 0x56,
|
||||||
|
|
||||||
|
/* EC software sync unable to get EC image hash */
|
||||||
|
VB2_RECOVERY_EC_HASH_FAILED = 0x57,
|
||||||
|
|
||||||
|
/* EC software sync invalid image hash size */
|
||||||
|
VB2_RECOVERY_EC_HASH_SIZE = 0x58,
|
||||||
|
|
||||||
|
/* Unspecified error while trying to load kernel */
|
||||||
|
VB2_RECOVERY_LK_UNSPECIFIED = 0x59,
|
||||||
|
|
||||||
|
/* No bootable storage device in system */
|
||||||
|
VB2_RECOVERY_RW_NO_DISK = 0x5a,
|
||||||
|
|
||||||
|
/* No bootable kernel found on disk */
|
||||||
|
VB2_RECOVERY_RW_NO_KERNEL = 0x5b,
|
||||||
|
|
||||||
|
/* BCB related error in RW firmware */
|
||||||
|
VB2_RECOVERY_RW_BCB_ERROR = 0x5c,
|
||||||
|
|
||||||
|
/* New error codes from VB2 */
|
||||||
|
/* TODO: may need to add strings for these in the original fwlib */
|
||||||
|
|
||||||
|
/* Secure data inititalization error */
|
||||||
|
VB2_RECOVERY_SECDATAK_INIT = 0x5d,
|
||||||
|
|
||||||
|
/* Fastboot mode requested in firmware */
|
||||||
|
VB2_RECOVERY_FW_FASTBOOT = 0x5e,
|
||||||
|
|
||||||
|
/* Recovery hash space lock error in RO firmware */
|
||||||
|
VB2_RECOVERY_RO_TPM_REC_HASH_L_ERROR = 0x5f,
|
||||||
|
|
||||||
|
/* Unspecified/unknown error in rewritable firmware */
|
||||||
|
VB2_RECOVERY_RW_UNSPECIFIED = 0x7f,
|
||||||
|
|
||||||
|
/* DM-verity error */
|
||||||
|
VB2_RECOVERY_KE_DM_VERITY = 0x81,
|
||||||
|
|
||||||
|
/* Unspecified/unknown error in kernel */
|
||||||
|
VB2_RECOVERY_KE_UNSPECIFIED = 0xbf,
|
||||||
|
|
||||||
|
/* Recovery mode test from user-mode */
|
||||||
|
VB2_RECOVERY_US_TEST = 0xc1,
|
||||||
|
|
||||||
|
/* Recovery requested by user-mode via BCB */
|
||||||
|
VB2_RECOVERY_BCB_USER_MODE = 0xc2,
|
||||||
|
|
||||||
|
/* Fastboot mode requested by user-mode */
|
||||||
|
VB2_RECOVERY_US_FASTBOOT = 0xc3,
|
||||||
|
|
||||||
|
/* User requested recovery for training memory and rebooting. */
|
||||||
|
VB2_RECOVERY_TRAIN_AND_REBOOT = 0xc4,
|
||||||
|
|
||||||
|
/* Unspecified/unknown error in user-mode */
|
||||||
|
VB2_RECOVERY_US_UNSPECIFIED = 0xff,
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* VBOOT_REFERENCE_VBOOT_2RECOVERY_REASONS_H_ */
|
||||||
827
firmware/coreboot/3rdparty/vboot/firmware/2lib/include/2return_codes.h
vendored
Normal file
827
firmware/coreboot/3rdparty/vboot/firmware/2lib/include/2return_codes.h
vendored
Normal file
@@ -0,0 +1,827 @@
|
|||||||
|
/* Copyright (c) 2014 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef VBOOT_2_RETURN_CODES_H_
|
||||||
|
#define VBOOT_2_RETURN_CODES_H_
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return codes from verified boot functions.
|
||||||
|
*
|
||||||
|
* Note that other values may be passed through from vb2ex_*() calls; see
|
||||||
|
* the comment for VB2_ERROR_EX below.
|
||||||
|
*/
|
||||||
|
enum vb2_return_code {
|
||||||
|
/* Success - no error */
|
||||||
|
VB2_SUCCESS = 0,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* All vboot2 error codes start at a large offset from zero, to reduce
|
||||||
|
* the risk of overlap with other error codes (TPM, etc.).
|
||||||
|
*/
|
||||||
|
VB2_ERROR_BASE = 0x10000000,
|
||||||
|
|
||||||
|
/* Unknown / unspecified error */
|
||||||
|
VB2_ERROR_UNKNOWN = VB2_ERROR_BASE + 1,
|
||||||
|
|
||||||
|
/* Mock error for testing */
|
||||||
|
VB2_ERROR_MOCK,
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* SHA errors
|
||||||
|
*/
|
||||||
|
VB2_ERROR_SHA = VB2_ERROR_BASE + 0x010000,
|
||||||
|
|
||||||
|
/* Bad algorithm in vb2_digest_init() */
|
||||||
|
VB2_ERROR_SHA_INIT_ALGORITHM,
|
||||||
|
|
||||||
|
/* Bad algorithm in vb2_digest_extend() */
|
||||||
|
VB2_ERROR_SHA_EXTEND_ALGORITHM,
|
||||||
|
|
||||||
|
/* Bad algorithm in vb2_digest_finalize() */
|
||||||
|
VB2_ERROR_SHA_FINALIZE_ALGORITHM,
|
||||||
|
|
||||||
|
/* Digest size buffer too small in vb2_digest_finalize() */
|
||||||
|
VB2_ERROR_SHA_FINALIZE_DIGEST_SIZE,
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* RSA errors
|
||||||
|
*/
|
||||||
|
VB2_ERROR_RSA = VB2_ERROR_BASE + 0x020000,
|
||||||
|
|
||||||
|
/* Padding mismatch in vb2_check_padding() */
|
||||||
|
VB2_ERROR_RSA_PADDING,
|
||||||
|
|
||||||
|
/* Bad algorithm in vb2_check_padding() */
|
||||||
|
VB2_ERROR_RSA_PADDING_ALGORITHM,
|
||||||
|
|
||||||
|
/* Null param passed to vb2_verify_digest() */
|
||||||
|
VB2_ERROR_RSA_VERIFY_PARAM,
|
||||||
|
|
||||||
|
/* Bad algorithm in vb2_verify_digest() */
|
||||||
|
VB2_ERROR_RSA_VERIFY_ALGORITHM,
|
||||||
|
|
||||||
|
/* Bad signature length in vb2_verify_digest() */
|
||||||
|
VB2_ERROR_RSA_VERIFY_SIG_LEN,
|
||||||
|
|
||||||
|
/* Work buffer too small in vb2_verify_digest() */
|
||||||
|
VB2_ERROR_RSA_VERIFY_WORKBUF,
|
||||||
|
|
||||||
|
/* Digest mismatch in vb2_verify_digest() */
|
||||||
|
VB2_ERROR_RSA_VERIFY_DIGEST,
|
||||||
|
|
||||||
|
/* Bad size calculation in vb2_check_padding() */
|
||||||
|
VB2_ERROR_RSA_PADDING_SIZE,
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* NV storage errors
|
||||||
|
*/
|
||||||
|
VB2_ERROR_NV = VB2_ERROR_BASE + 0x030000,
|
||||||
|
|
||||||
|
/* Bad header in vb2_nv_check_crc() */
|
||||||
|
VB2_ERROR_NV_HEADER,
|
||||||
|
|
||||||
|
/* Bad CRC in vb2_nv_check_crc() */
|
||||||
|
VB2_ERROR_NV_CRC,
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* Secure data storage errors
|
||||||
|
*/
|
||||||
|
VB2_ERROR_SECDATA = VB2_ERROR_BASE + 0x040000,
|
||||||
|
|
||||||
|
/* Bad CRC in vb2_secdata_check_crc() */
|
||||||
|
VB2_ERROR_SECDATA_CRC,
|
||||||
|
|
||||||
|
/* Secdata is all zeroes (uninitialized) in vb2_secdata_check_crc() */
|
||||||
|
VB2_ERROR_SECDATA_ZERO,
|
||||||
|
|
||||||
|
/* Invalid param in vb2_secdata_get() */
|
||||||
|
VB2_ERROR_SECDATA_GET_PARAM,
|
||||||
|
|
||||||
|
/* Invalid param in vb2_secdata_set() */
|
||||||
|
VB2_ERROR_SECDATA_SET_PARAM,
|
||||||
|
|
||||||
|
/* Invalid flags passed to vb2_secdata_set() */
|
||||||
|
VB2_ERROR_SECDATA_SET_FLAGS,
|
||||||
|
|
||||||
|
/* Called vb2_secdata_get() with uninitialized secdata */
|
||||||
|
VB2_ERROR_SECDATA_GET_UNINITIALIZED,
|
||||||
|
|
||||||
|
/* Called vb2_secdata_set() with uninitialized secdata */
|
||||||
|
VB2_ERROR_SECDATA_SET_UNINITIALIZED,
|
||||||
|
|
||||||
|
/* Bad CRC in vb2_secdatak_check_crc() */
|
||||||
|
VB2_ERROR_SECDATAK_CRC,
|
||||||
|
|
||||||
|
/* Bad struct version in vb2_secdatak_init() */
|
||||||
|
VB2_ERROR_SECDATAK_VERSION,
|
||||||
|
|
||||||
|
/* Bad uid in vb2_secdatak_init() */
|
||||||
|
VB2_ERROR_SECDATAK_UID,
|
||||||
|
|
||||||
|
/* Invalid param in vb2_secdatak_get() */
|
||||||
|
VB2_ERROR_SECDATAK_GET_PARAM,
|
||||||
|
|
||||||
|
/* Invalid param in vb2_secdatak_set() */
|
||||||
|
VB2_ERROR_SECDATAK_SET_PARAM,
|
||||||
|
|
||||||
|
/* Invalid flags passed to vb2_secdatak_set() */
|
||||||
|
VB2_ERROR_SECDATAK_SET_FLAGS,
|
||||||
|
|
||||||
|
/* Called vb2_secdatak_get() with uninitialized secdatak */
|
||||||
|
VB2_ERROR_SECDATAK_GET_UNINITIALIZED,
|
||||||
|
|
||||||
|
/* Called vb2_secdatak_set() with uninitialized secdatak */
|
||||||
|
VB2_ERROR_SECDATAK_SET_UNINITIALIZED,
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* Common code errors
|
||||||
|
*/
|
||||||
|
VB2_ERROR_COMMON = VB2_ERROR_BASE + 0x050000,
|
||||||
|
|
||||||
|
/* Buffer is smaller than alignment offset in vb2_align() */
|
||||||
|
VB2_ERROR_ALIGN_BIGGER_THAN_SIZE,
|
||||||
|
|
||||||
|
/* Buffer is smaller than request in vb2_align() */
|
||||||
|
VB2_ERROR_ALIGN_SIZE,
|
||||||
|
|
||||||
|
/* Parent wraps around in vb2_verify_member_inside() */
|
||||||
|
VB2_ERROR_INSIDE_PARENT_WRAPS,
|
||||||
|
|
||||||
|
/* Member wraps around in vb2_verify_member_inside() */
|
||||||
|
VB2_ERROR_INSIDE_MEMBER_WRAPS,
|
||||||
|
|
||||||
|
/* Member outside parent in vb2_verify_member_inside() */
|
||||||
|
VB2_ERROR_INSIDE_MEMBER_OUTSIDE,
|
||||||
|
|
||||||
|
/* Member data wraps around in vb2_verify_member_inside() */
|
||||||
|
VB2_ERROR_INSIDE_DATA_WRAPS,
|
||||||
|
|
||||||
|
/* Member data outside parent in vb2_verify_member_inside() */
|
||||||
|
VB2_ERROR_INSIDE_DATA_OUTSIDE,
|
||||||
|
|
||||||
|
/* Unsupported signature algorithm in vb2_unpack_key_buffer() */
|
||||||
|
VB2_ERROR_UNPACK_KEY_SIG_ALGORITHM, /* 0x150008 */
|
||||||
|
|
||||||
|
/* Bad key size in vb2_unpack_key_buffer() */
|
||||||
|
VB2_ERROR_UNPACK_KEY_SIZE,
|
||||||
|
|
||||||
|
/* Bad key alignment in vb2_unpack_key_buffer() */
|
||||||
|
VB2_ERROR_UNPACK_KEY_ALIGN,
|
||||||
|
|
||||||
|
/* Bad key array size in vb2_unpack_key_buffer() */
|
||||||
|
VB2_ERROR_UNPACK_KEY_ARRAY_SIZE,
|
||||||
|
|
||||||
|
/* Bad algorithm in vb2_verify_data() */
|
||||||
|
VB2_ERROR_VDATA_ALGORITHM,
|
||||||
|
|
||||||
|
/* Incorrect signature size for algorithm in vb2_verify_data() */
|
||||||
|
VB2_ERROR_VDATA_SIG_SIZE,
|
||||||
|
|
||||||
|
/* Data smaller than length of signed data in vb2_verify_data() */
|
||||||
|
VB2_ERROR_VDATA_NOT_ENOUGH_DATA,
|
||||||
|
|
||||||
|
/* Not enough work buffer for digest in vb2_verify_data() */
|
||||||
|
VB2_ERROR_VDATA_WORKBUF_DIGEST,
|
||||||
|
|
||||||
|
/* Not enough work buffer for hash temp data in vb2_verify_data() */
|
||||||
|
VB2_ERROR_VDATA_WORKBUF_HASHING, /* 0x150010 */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Bad digest size in vb2_verify_data() - probably because algorithm
|
||||||
|
* is bad.
|
||||||
|
*/
|
||||||
|
VB2_ERROR_VDATA_DIGEST_SIZE,
|
||||||
|
|
||||||
|
/* Unsupported hash algorithm in vb2_unpack_key_buffer() */
|
||||||
|
VB2_ERROR_UNPACK_KEY_HASH_ALGORITHM,
|
||||||
|
|
||||||
|
/* Member data overlaps member header */
|
||||||
|
VB2_ERROR_INSIDE_DATA_OVERLAP,
|
||||||
|
|
||||||
|
/* Unsupported packed key struct version */
|
||||||
|
VB2_ERROR_UNPACK_KEY_STRUCT_VERSION,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Buffer too small for total, fixed size, or description reported in
|
||||||
|
* common header, or member data checked via
|
||||||
|
* vb21_verify_common_member().
|
||||||
|
*/
|
||||||
|
VB2_ERROR_COMMON_TOTAL_SIZE,
|
||||||
|
VB2_ERROR_COMMON_FIXED_SIZE,
|
||||||
|
VB2_ERROR_COMMON_DESC_SIZE,
|
||||||
|
VB2_ERROR_COMMON_MEMBER_SIZE, /* 0x150018 */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Total, fixed, description, or member offset/size not a multiple of
|
||||||
|
* 32 bits.
|
||||||
|
*/
|
||||||
|
VB2_ERROR_COMMON_TOTAL_UNALIGNED,
|
||||||
|
VB2_ERROR_COMMON_FIXED_UNALIGNED,
|
||||||
|
VB2_ERROR_COMMON_DESC_UNALIGNED,
|
||||||
|
VB2_ERROR_COMMON_MEMBER_UNALIGNED,
|
||||||
|
|
||||||
|
/* Common struct description or member data wraps address space */
|
||||||
|
VB2_ERROR_COMMON_DESC_WRAPS,
|
||||||
|
VB2_ERROR_COMMON_MEMBER_WRAPS,
|
||||||
|
|
||||||
|
/* Common struct description is not null-terminated */
|
||||||
|
VB2_ERROR_COMMON_DESC_TERMINATOR,
|
||||||
|
|
||||||
|
/* Member data overlaps previous data */
|
||||||
|
VB2_ERROR_COMMON_MEMBER_OVERLAP, /* 0x150020 */
|
||||||
|
|
||||||
|
/* Signature bad magic number */
|
||||||
|
VB2_ERROR_SIG_MAGIC,
|
||||||
|
|
||||||
|
/* Signature incompatible version */
|
||||||
|
VB2_ERROR_SIG_VERSION,
|
||||||
|
|
||||||
|
/* Signature header doesn't fit */
|
||||||
|
VB2_ERROR_SIG_HEADER_SIZE,
|
||||||
|
|
||||||
|
/* Signature unsupported algorithm */
|
||||||
|
VB2_ERROR_SIG_ALGORITHM,
|
||||||
|
|
||||||
|
/* Signature bad size for algorithm */
|
||||||
|
VB2_ERROR_SIG_SIZE,
|
||||||
|
|
||||||
|
/* Wrong amount of data signed */
|
||||||
|
VB2_ERROR_VDATA_SIZE,
|
||||||
|
|
||||||
|
/* Digest mismatch */
|
||||||
|
VB2_ERROR_VDATA_VERIFY_DIGEST,
|
||||||
|
|
||||||
|
/* Key algorithm doesn't match signature algorithm */
|
||||||
|
VB2_ERROR_VDATA_ALGORITHM_MISMATCH,
|
||||||
|
|
||||||
|
/* Bad magic number in vb2_unpack_key_buffer() */
|
||||||
|
VB2_ERROR_UNPACK_KEY_MAGIC,
|
||||||
|
|
||||||
|
/* Null public key buffer passed to vb2_unpack_key_buffer() */
|
||||||
|
VB2_ERROR_UNPACK_KEY_BUFFER,
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* Keyblock verification errors (all in vb2_verify_keyblock())
|
||||||
|
*/
|
||||||
|
VB2_ERROR_KEYBLOCK = VB2_ERROR_BASE + 0x060000,
|
||||||
|
|
||||||
|
/* Data buffer too small for header */
|
||||||
|
VB2_ERROR_KEYBLOCK_TOO_SMALL_FOR_HEADER,
|
||||||
|
|
||||||
|
/* Magic number not present */
|
||||||
|
VB2_ERROR_KEYBLOCK_MAGIC,
|
||||||
|
|
||||||
|
/* Header version incompatible */
|
||||||
|
VB2_ERROR_KEYBLOCK_HEADER_VERSION,
|
||||||
|
|
||||||
|
/* Data buffer too small for keyblock */
|
||||||
|
VB2_ERROR_KEYBLOCK_SIZE,
|
||||||
|
|
||||||
|
/* Signature data offset outside keyblock */
|
||||||
|
VB2_ERROR_KEYBLOCK_SIG_OUTSIDE,
|
||||||
|
|
||||||
|
/* Signature signed more data than size of keyblock */
|
||||||
|
VB2_ERROR_KEYBLOCK_SIGNED_TOO_MUCH,
|
||||||
|
|
||||||
|
/* Signature signed less data than size of keyblock header */
|
||||||
|
VB2_ERROR_KEYBLOCK_SIGNED_TOO_LITTLE,
|
||||||
|
|
||||||
|
/* Signature invalid */
|
||||||
|
VB2_ERROR_KEYBLOCK_SIG_INVALID,
|
||||||
|
|
||||||
|
/* Data key outside keyblock */
|
||||||
|
VB2_ERROR_KEYBLOCK_DATA_KEY_OUTSIDE,
|
||||||
|
|
||||||
|
/* Data key outside signed part of keyblock */
|
||||||
|
VB2_ERROR_KEYBLOCK_DATA_KEY_UNSIGNED,
|
||||||
|
|
||||||
|
/* Signature signed wrong amount of data */
|
||||||
|
VB2_ERROR_KEYBLOCK_SIGNED_SIZE,
|
||||||
|
|
||||||
|
/* No signature matching key ID */
|
||||||
|
VB2_ERROR_KEYBLOCK_SIG_ID,
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* Preamble verification errors (all in vb2_verify_preamble())
|
||||||
|
*/
|
||||||
|
VB2_ERROR_PREAMBLE = VB2_ERROR_BASE + 0x070000,
|
||||||
|
|
||||||
|
/* Preamble data too small to contain header */
|
||||||
|
VB2_ERROR_PREAMBLE_TOO_SMALL_FOR_HEADER,
|
||||||
|
|
||||||
|
/* Header version incompatible */
|
||||||
|
VB2_ERROR_PREAMBLE_HEADER_VERSION,
|
||||||
|
|
||||||
|
/* Header version too old */
|
||||||
|
VB2_ERROR_PREAMBLE_HEADER_OLD,
|
||||||
|
|
||||||
|
/* Data buffer too small for preamble */
|
||||||
|
VB2_ERROR_PREAMBLE_SIZE,
|
||||||
|
|
||||||
|
/* Signature data offset outside preamble */
|
||||||
|
VB2_ERROR_PREAMBLE_SIG_OUTSIDE,
|
||||||
|
|
||||||
|
/* Signature signed more data than size of preamble */
|
||||||
|
VB2_ERROR_PREAMBLE_SIGNED_TOO_MUCH,
|
||||||
|
|
||||||
|
/* Signature signed less data than size of preamble header */
|
||||||
|
VB2_ERROR_PREAMBLE_SIGNED_TOO_LITTLE,
|
||||||
|
|
||||||
|
/* Signature invalid */
|
||||||
|
VB2_ERROR_PREAMBLE_SIG_INVALID,
|
||||||
|
|
||||||
|
/* Body signature outside preamble */
|
||||||
|
VB2_ERROR_PREAMBLE_BODY_SIG_OUTSIDE,
|
||||||
|
|
||||||
|
/* Kernel subkey outside preamble */
|
||||||
|
VB2_ERROR_PREAMBLE_KERNEL_SUBKEY_OUTSIDE,
|
||||||
|
|
||||||
|
/* Bad magic number */
|
||||||
|
VB2_ERROR_PREAMBLE_MAGIC,
|
||||||
|
|
||||||
|
/* Hash is signed */
|
||||||
|
VB2_ERROR_PREAMBLE_HASH_SIGNED,
|
||||||
|
|
||||||
|
/* Bootloader outside signed portion of body */
|
||||||
|
VB2_ERROR_PREAMBLE_BOOTLOADER_OUTSIDE,
|
||||||
|
|
||||||
|
/* Vmlinuz header outside signed portion of body */
|
||||||
|
VB2_ERROR_PREAMBLE_VMLINUZ_HEADER_OUTSIDE,
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* Misc higher-level code errors
|
||||||
|
*/
|
||||||
|
VB2_ERROR_MISC = VB2_ERROR_BASE + 0x080000,
|
||||||
|
|
||||||
|
/* Work buffer too small in vb2_init_context() */
|
||||||
|
VB2_ERROR_INITCTX_WORKBUF_SMALL,
|
||||||
|
|
||||||
|
/* Work buffer unaligned in vb2_init_context() */
|
||||||
|
VB2_ERROR_INITCTX_WORKBUF_ALIGN,
|
||||||
|
|
||||||
|
/* Work buffer too small in vb2_fw_parse_gbb() */
|
||||||
|
VB2_ERROR_GBB_WORKBUF,
|
||||||
|
|
||||||
|
/* Bad magic number in vb2_read_gbb_header() */
|
||||||
|
VB2_ERROR_GBB_MAGIC,
|
||||||
|
|
||||||
|
/* Incompatible version in vb2_read_gbb_header() */
|
||||||
|
VB2_ERROR_GBB_VERSION,
|
||||||
|
|
||||||
|
/* Old version in vb2_read_gbb_header() */
|
||||||
|
VB2_ERROR_GBB_TOO_OLD,
|
||||||
|
|
||||||
|
/* Header size too small in vb2_read_gbb_header() */
|
||||||
|
VB2_ERROR_GBB_HEADER_SIZE,
|
||||||
|
|
||||||
|
/* Work buffer too small for root key in vb2_load_fw_keyblock() */
|
||||||
|
VB2_ERROR_FW_KEYBLOCK_WORKBUF_ROOT_KEY,
|
||||||
|
|
||||||
|
/* Work buffer too small for header in vb2_load_fw_keyblock() */
|
||||||
|
VB2_ERROR_FW_KEYBLOCK_WORKBUF_HEADER,
|
||||||
|
|
||||||
|
/* Work buffer too small for keyblock in vb2_load_fw_keyblock() */
|
||||||
|
VB2_ERROR_FW_KEYBLOCK_WORKBUF,
|
||||||
|
|
||||||
|
/* Keyblock version out of range in vb2_load_fw_keyblock() */
|
||||||
|
VB2_ERROR_FW_KEYBLOCK_VERSION_RANGE,
|
||||||
|
|
||||||
|
/* Keyblock version rollback in vb2_load_fw_keyblock() */
|
||||||
|
VB2_ERROR_FW_KEYBLOCK_VERSION_ROLLBACK,
|
||||||
|
|
||||||
|
/* Missing firmware data key in vb2_load_fw_preamble() */
|
||||||
|
VB2_ERROR_FW_PREAMBLE2_DATA_KEY,
|
||||||
|
|
||||||
|
/* Work buffer too small for header in vb2_load_fw_preamble() */
|
||||||
|
VB2_ERROR_FW_PREAMBLE2_WORKBUF_HEADER,
|
||||||
|
|
||||||
|
/* Work buffer too small for preamble in vb2_load_fw_preamble() */
|
||||||
|
VB2_ERROR_FW_PREAMBLE2_WORKBUF,
|
||||||
|
|
||||||
|
/* Firmware version out of range in vb2_load_fw_preamble() */
|
||||||
|
VB2_ERROR_FW_PREAMBLE_VERSION_RANGE,
|
||||||
|
|
||||||
|
/* Firmware version rollback in vb2_load_fw_preamble() */
|
||||||
|
VB2_ERROR_FW_PREAMBLE_VERSION_ROLLBACK,
|
||||||
|
|
||||||
|
/* Not enough space in work buffer for resource object */
|
||||||
|
VB2_ERROR_READ_RESOURCE_OBJECT_BUF,
|
||||||
|
|
||||||
|
/* Work buffer too small for header in vb2_load_kernel_keyblock() */
|
||||||
|
VB2_ERROR_KERNEL_KEYBLOCK_WORKBUF_HEADER,
|
||||||
|
|
||||||
|
/* Work buffer too small for keyblock in vb2_load_kernel_keyblock() */
|
||||||
|
VB2_ERROR_KERNEL_KEYBLOCK_WORKBUF,
|
||||||
|
|
||||||
|
/* Keyblock version out of range in vb2_load_kernel_keyblock() */
|
||||||
|
VB2_ERROR_KERNEL_KEYBLOCK_VERSION_RANGE,
|
||||||
|
|
||||||
|
/* Keyblock version rollback in vb2_load_kernel_keyblock() */
|
||||||
|
VB2_ERROR_KERNEL_KEYBLOCK_VERSION_ROLLBACK,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Keyblock flags don't match current mode in
|
||||||
|
* vb2_load_kernel_keyblock().
|
||||||
|
*/
|
||||||
|
VB2_ERROR_KERNEL_KEYBLOCK_DEV_FLAG,
|
||||||
|
VB2_ERROR_KERNEL_KEYBLOCK_REC_FLAG,
|
||||||
|
|
||||||
|
/* Missing firmware data key in vb2_load_kernel_preamble() */
|
||||||
|
VB2_ERROR_KERNEL_PREAMBLE2_DATA_KEY,
|
||||||
|
|
||||||
|
/* Work buffer too small for header in vb2_load_kernel_preamble() */
|
||||||
|
VB2_ERROR_KERNEL_PREAMBLE2_WORKBUF_HEADER,
|
||||||
|
|
||||||
|
/* Work buffer too small for preamble in vb2_load_kernel_preamble() */
|
||||||
|
VB2_ERROR_KERNEL_PREAMBLE2_WORKBUF,
|
||||||
|
|
||||||
|
/* Kernel version out of range in vb2_load_kernel_preamble() */
|
||||||
|
VB2_ERROR_KERNEL_PREAMBLE_VERSION_RANGE,
|
||||||
|
|
||||||
|
/* Kernel version rollback in vb2_load_kernel_preamble() */
|
||||||
|
VB2_ERROR_KERNEL_PREAMBLE_VERSION_ROLLBACK,
|
||||||
|
|
||||||
|
/* Kernel preamble not loaded before calling vb2api_get_kernel_size() */
|
||||||
|
VB2_ERROR_API_GET_KERNEL_SIZE_PREAMBLE,
|
||||||
|
|
||||||
|
/* Unable to unpack kernel subkey in vb2_verify_vblock() */
|
||||||
|
VB2_ERROR_VBLOCK_KERNEL_SUBKEY,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Got a self-signed kernel in vb2_verify_vblock(), but need an
|
||||||
|
* officially signed one.
|
||||||
|
*/
|
||||||
|
VB2_ERROR_VBLOCK_SELF_SIGNED,
|
||||||
|
|
||||||
|
/* Invalid keyblock hash in vb2_verify_vblock() */
|
||||||
|
VB2_ERROR_VBLOCK_KEYBLOCK_HASH,
|
||||||
|
|
||||||
|
/* Invalid keyblock in vb2_verify_vblock() */
|
||||||
|
VB2_ERROR_VBLOCK_KEYBLOCK,
|
||||||
|
|
||||||
|
/* Wrong developer key hash in vb2_verify_vblock() */
|
||||||
|
VB2_ERROR_VBLOCK_DEV_KEY_HASH,
|
||||||
|
|
||||||
|
/* Work buffer too small in vb2_load_partition() */
|
||||||
|
VB2_ERROR_LOAD_PARTITION_WORKBUF,
|
||||||
|
|
||||||
|
/* Unable to read vblock in vb2_load_partition() */
|
||||||
|
VB2_ERROR_LOAD_PARTITION_READ_VBLOCK,
|
||||||
|
|
||||||
|
/* Unable to verify vblock in vb2_load_partition() */
|
||||||
|
VB2_ERROR_LOAD_PARTITION_VERIFY_VBLOCK,
|
||||||
|
|
||||||
|
/* Kernel body offset too large in vb2_load_partition() */
|
||||||
|
VB2_ERROR_LOAD_PARTITION_BODY_OFFSET,
|
||||||
|
|
||||||
|
/* Kernel body too big in vb2_load_partition() */
|
||||||
|
VB2_ERROR_LOAD_PARTITION_BODY_SIZE,
|
||||||
|
|
||||||
|
/* Unable to read kernel body in vb2_load_partition() */
|
||||||
|
VB2_ERROR_LOAD_PARTITION_READ_BODY,
|
||||||
|
|
||||||
|
/* Unable to unpack data key in vb2_load_partition() */
|
||||||
|
VB2_ERROR_LOAD_PARTITION_DATA_KEY,
|
||||||
|
|
||||||
|
/* Unable to verify body in vb2_load_partition() */
|
||||||
|
VB2_ERROR_LOAD_PARTITION_VERIFY_BODY,
|
||||||
|
|
||||||
|
/* Unable to get EC image hash in ec_sync_phase1() */
|
||||||
|
VB2_ERROR_EC_HASH_IMAGE,
|
||||||
|
|
||||||
|
/* Unable to get expected EC image hash in ec_sync_phase1() */
|
||||||
|
VB2_ERROR_EC_HASH_EXPECTED,
|
||||||
|
|
||||||
|
/* Expected and image hashes are different size in ec_sync_phase1() */
|
||||||
|
VB2_ERROR_EC_HASH_SIZE,
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* API-level errors
|
||||||
|
*/
|
||||||
|
VB2_ERROR_API = VB2_ERROR_BASE + 0x090000,
|
||||||
|
|
||||||
|
/* Bad tag in vb2api_init_hash() */
|
||||||
|
VB2_ERROR_API_INIT_HASH_TAG,
|
||||||
|
|
||||||
|
/* Preamble not present in vb2api_init_hash() */
|
||||||
|
VB2_ERROR_API_INIT_HASH_PREAMBLE,
|
||||||
|
|
||||||
|
/* Work buffer too small in vb2api_init_hash() */
|
||||||
|
VB2_ERROR_API_INIT_HASH_WORKBUF,
|
||||||
|
|
||||||
|
/* Missing firmware data key in vb2api_init_hash() */
|
||||||
|
VB2_ERROR_API_INIT_HASH_DATA_KEY,
|
||||||
|
|
||||||
|
/* Uninitialized work area in vb2api_extend_hash() */
|
||||||
|
VB2_ERROR_API_EXTEND_HASH_WORKBUF,
|
||||||
|
|
||||||
|
/* Too much data hashed in vb2api_extend_hash() */
|
||||||
|
VB2_ERROR_API_EXTEND_HASH_SIZE,
|
||||||
|
|
||||||
|
/* Preamble not present in vb2api_check_hash() */
|
||||||
|
VB2_ERROR_API_CHECK_HASH_PREAMBLE,
|
||||||
|
|
||||||
|
/* Uninitialized work area in vb2api_check_hash() */
|
||||||
|
VB2_ERROR_API_CHECK_HASH_WORKBUF,
|
||||||
|
|
||||||
|
/* Wrong amount of data hashed in vb2api_check_hash() */
|
||||||
|
VB2_ERROR_API_CHECK_HASH_SIZE,
|
||||||
|
|
||||||
|
/* Work buffer too small in vb2api_check_hash() */
|
||||||
|
VB2_ERROR_API_CHECK_HASH_WORKBUF_DIGEST,
|
||||||
|
|
||||||
|
/* Bad tag in vb2api_check_hash() */
|
||||||
|
VB2_ERROR_API_CHECK_HASH_TAG,
|
||||||
|
|
||||||
|
/* Missing firmware data key in vb2api_check_hash() */
|
||||||
|
VB2_ERROR_API_CHECK_HASH_DATA_KEY,
|
||||||
|
|
||||||
|
/* Signature size mismatch in vb2api_check_hash() */
|
||||||
|
VB2_ERROR_API_CHECK_HASH_SIG_SIZE,
|
||||||
|
|
||||||
|
/* Phase one needs recovery mode */
|
||||||
|
VB2_ERROR_API_PHASE1_RECOVERY,
|
||||||
|
|
||||||
|
/* Bad tag in vb2api_check_hash() */
|
||||||
|
VB2_ERROR_API_INIT_HASH_ID,
|
||||||
|
|
||||||
|
/* Signature mismatch in vb2api_check_hash() */
|
||||||
|
VB2_ERROR_API_CHECK_HASH_SIG,
|
||||||
|
|
||||||
|
/* Invalid enum vb2_pcr_digest requested to vb2api_get_pcr_digest */
|
||||||
|
VB2_ERROR_API_PCR_DIGEST,
|
||||||
|
|
||||||
|
/* Buffer size for the digest is too small for vb2api_get_pcr_digest */
|
||||||
|
VB2_ERROR_API_PCR_DIGEST_BUF,
|
||||||
|
|
||||||
|
/* Work buffer too small for recovery key in vb2api_kernel_phase1() */
|
||||||
|
VB2_ERROR_API_KPHASE1_WORKBUF_REC_KEY,
|
||||||
|
|
||||||
|
/* Firmware preamble not present for vb2api_kernel_phase1() */
|
||||||
|
VB2_ERROR_API_KPHASE1_PREAMBLE,
|
||||||
|
|
||||||
|
/* Wrong amount of kernel data in vb2api_verify_kernel_data() */
|
||||||
|
VB2_ERROR_API_VERIFY_KDATA_SIZE,
|
||||||
|
|
||||||
|
/* Kernel preamble not present for vb2api_verify_kernel_data() */
|
||||||
|
VB2_ERROR_API_VERIFY_KDATA_PREAMBLE,
|
||||||
|
|
||||||
|
/* Insufficient workbuf for hashing in vb2api_verify_kernel_data() */
|
||||||
|
VB2_ERROR_API_VERIFY_KDATA_WORKBUF,
|
||||||
|
|
||||||
|
/* Bad data key in vb2api_verify_kernel_data() */
|
||||||
|
VB2_ERROR_API_VERIFY_KDATA_KEY,
|
||||||
|
|
||||||
|
/* Phase one passing through secdata's request to reboot */
|
||||||
|
VB2_ERROR_API_PHASE1_SECDATA_REBOOT,
|
||||||
|
|
||||||
|
/* Digest buffer passed into vb2api_check_hash incorrect. */
|
||||||
|
VB2_ERROR_API_CHECK_DIGEST_SIZE,
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* Errors which may be generated by implementations of vb2ex functions.
|
||||||
|
* Implementation may also return its own specific errors, which should
|
||||||
|
* NOT be in the range VB2_ERROR_BASE...VB2_ERROR_MAX to avoid
|
||||||
|
* conflicting with future vboot2 error codes.
|
||||||
|
*/
|
||||||
|
VB2_ERROR_EX = VB2_ERROR_BASE + 0x0a0000,
|
||||||
|
|
||||||
|
/* Read resource not implemented */
|
||||||
|
VB2_ERROR_EX_READ_RESOURCE_UNIMPLEMENTED,
|
||||||
|
|
||||||
|
/* Resource index not found */
|
||||||
|
VB2_ERROR_EX_READ_RESOURCE_INDEX,
|
||||||
|
|
||||||
|
/* Size of resource not big enough for requested offset and/or size */
|
||||||
|
VB2_ERROR_EX_READ_RESOURCE_SIZE,
|
||||||
|
|
||||||
|
/* TPM clear owner failed */
|
||||||
|
VB2_ERROR_EX_TPM_CLEAR_OWNER,
|
||||||
|
|
||||||
|
/* TPM clear owner not implemented */
|
||||||
|
VB2_ERROR_EX_TPM_CLEAR_OWNER_UNIMPLEMENTED,
|
||||||
|
|
||||||
|
/* Hardware crypto engine doesn't support this algorithm (non-fatal) */
|
||||||
|
VB2_ERROR_EX_HWCRYPTO_UNSUPPORTED,
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* Errors generated by host library (non-firmware) start here.
|
||||||
|
*/
|
||||||
|
VB2_ERROR_HOST_BASE = 0x20000000,
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* Errors generated by host library misc functions
|
||||||
|
*/
|
||||||
|
VB2_ERROR_HOST_MISC = VB2_ERROR_HOST_BASE + 0x010000,
|
||||||
|
|
||||||
|
/* Unable to open file in read_file() */
|
||||||
|
VB2_ERROR_READ_FILE_OPEN,
|
||||||
|
|
||||||
|
/* Bad size in read_file() */
|
||||||
|
VB2_ERROR_READ_FILE_SIZE,
|
||||||
|
|
||||||
|
/* Unable to allocate buffer in read_file() */
|
||||||
|
VB2_ERROR_READ_FILE_ALLOC,
|
||||||
|
|
||||||
|
/* Unable to read data in read_file() */
|
||||||
|
VB2_ERROR_READ_FILE_DATA,
|
||||||
|
|
||||||
|
/* Unable to open file in write_file() */
|
||||||
|
VB2_ERROR_WRITE_FILE_OPEN,
|
||||||
|
|
||||||
|
/* Unable to write data in write_file() */
|
||||||
|
VB2_ERROR_WRITE_FILE_DATA,
|
||||||
|
|
||||||
|
/* Unable to convert string to struct vb_id */
|
||||||
|
VB2_ERROR_STR_TO_ID,
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* Errors generated by host library key functions
|
||||||
|
*/
|
||||||
|
VB2_ERROR_HOST_KEY = VB2_ERROR_HOST_BASE + 0x020000,
|
||||||
|
|
||||||
|
/* Unable to allocate key in vb2_private_key_read_pem() */
|
||||||
|
VB2_ERROR_READ_PEM_ALLOC,
|
||||||
|
|
||||||
|
/* Unable to open .pem file in vb2_private_key_read_pem() */
|
||||||
|
VB2_ERROR_READ_PEM_FILE_OPEN,
|
||||||
|
|
||||||
|
/* Bad RSA data from .pem file in vb2_private_key_read_pem() */
|
||||||
|
VB2_ERROR_READ_PEM_RSA,
|
||||||
|
|
||||||
|
/* Unable to set private key description */
|
||||||
|
VB2_ERROR_PRIVATE_KEY_SET_DESC,
|
||||||
|
|
||||||
|
/* Bad magic number in vb2_private_key_unpack() */
|
||||||
|
VB2_ERROR_UNPACK_PRIVATE_KEY_MAGIC,
|
||||||
|
|
||||||
|
/* Bad common header in vb2_private_key_unpack() */
|
||||||
|
VB2_ERROR_UNPACK_PRIVATE_KEY_HEADER,
|
||||||
|
|
||||||
|
/* Bad key data in vb2_private_key_unpack() */
|
||||||
|
VB2_ERROR_UNPACK_PRIVATE_KEY_DATA,
|
||||||
|
|
||||||
|
/* Bad struct version in vb2_private_key_unpack() */
|
||||||
|
VB2_ERROR_UNPACK_PRIVATE_KEY_STRUCT_VERSION,
|
||||||
|
|
||||||
|
/* Unable to allocate buffer in vb2_private_key_unpack() */
|
||||||
|
VB2_ERROR_UNPACK_PRIVATE_KEY_ALLOC,
|
||||||
|
|
||||||
|
/* Unable to unpack RSA key in vb2_private_key_unpack() */
|
||||||
|
VB2_ERROR_UNPACK_PRIVATE_KEY_RSA,
|
||||||
|
|
||||||
|
/* Unable to set description in vb2_private_key_unpack() */
|
||||||
|
VB2_ERROR_UNPACK_PRIVATE_KEY_DESC,
|
||||||
|
|
||||||
|
/* Bad bare hash key in vb2_private_key_unpack() */
|
||||||
|
VB2_ERROR_UNPACK_PRIVATE_KEY_HASH,
|
||||||
|
|
||||||
|
/* Unable to create RSA data in vb2_private_key_write() */
|
||||||
|
VB2_ERROR_PRIVATE_KEY_WRITE_RSA,
|
||||||
|
|
||||||
|
/* Unable to allocate packed key buffer in vb2_private_key_write() */
|
||||||
|
VB2_ERROR_PRIVATE_KEY_WRITE_ALLOC,
|
||||||
|
|
||||||
|
/* Unable to write file in vb2_private_key_write() */
|
||||||
|
VB2_ERROR_PRIVATE_KEY_WRITE_FILE,
|
||||||
|
|
||||||
|
/* Bad algorithm in vb2_private_key_hash() */
|
||||||
|
VB2_ERROR_PRIVATE_KEY_HASH,
|
||||||
|
|
||||||
|
/* Unable to determine key size in vb2_public_key_alloc() */
|
||||||
|
VB2_ERROR_PUBLIC_KEY_ALLOC_SIZE,
|
||||||
|
|
||||||
|
/* Unable to allocate buffer in vb2_public_key_alloc() */
|
||||||
|
VB2_ERROR_PUBLIC_KEY_ALLOC,
|
||||||
|
|
||||||
|
/* Unable to set public key description */
|
||||||
|
VB2_ERROR_PUBLIC_KEY_SET_DESC,
|
||||||
|
|
||||||
|
/* Unable to read key data in vb2_public_key_read_keyb() */
|
||||||
|
VB2_ERROR_READ_KEYB_DATA,
|
||||||
|
|
||||||
|
/* Wrong amount of data read in vb2_public_key_read_keyb() */
|
||||||
|
VB2_ERROR_READ_KEYB_SIZE,
|
||||||
|
|
||||||
|
/* Unable to allocate key buffer in vb2_public_key_read_keyb() */
|
||||||
|
VB2_ERROR_READ_KEYB_ALLOC,
|
||||||
|
|
||||||
|
/* Error unpacking RSA arrays in vb2_public_key_read_keyb() */
|
||||||
|
VB2_ERROR_READ_KEYB_UNPACK,
|
||||||
|
|
||||||
|
/* Unable to read key data in vb2_packed_key_read() */
|
||||||
|
VB2_ERROR_READ_PACKED_KEY_DATA,
|
||||||
|
|
||||||
|
/* Bad key data in vb2_packed_key_read() */
|
||||||
|
VB2_ERROR_READ_PACKED_KEY,
|
||||||
|
|
||||||
|
/* Unable to determine key size in vb2_public_key_pack() */
|
||||||
|
VB2_ERROR_PUBLIC_KEY_PACK_SIZE,
|
||||||
|
|
||||||
|
/* Bad hash algorithm in vb2_public_key_hash() */
|
||||||
|
VB2_ERROR_PUBLIC_KEY_HASH,
|
||||||
|
|
||||||
|
/* Bad key size in vb2_copy_packed_key() */
|
||||||
|
VB2_ERROR_COPY_KEY_SIZE,
|
||||||
|
|
||||||
|
/* Unable to convert back to vb1 crypto algorithm */
|
||||||
|
VB2_ERROR_VB1_CRYPTO_ALGORITHM,
|
||||||
|
|
||||||
|
/* Unable to allocate packed key */
|
||||||
|
VB2_ERROR_PACKED_KEY_ALLOC,
|
||||||
|
|
||||||
|
/* Unable to copy packed key */
|
||||||
|
VB2_ERROR_PACKED_KEY_COPY,
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* Errors generated by host library signature functions
|
||||||
|
*/
|
||||||
|
VB2_ERROR_HOST_SIG = VB2_ERROR_HOST_BASE + 0x030000,
|
||||||
|
|
||||||
|
/* Bad hash algorithm in vb2_digest_info() */
|
||||||
|
VB2_ERROR_DIGEST_INFO,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Unable to determine signature size for key algorithm in
|
||||||
|
* vb2_sig_size_for_key().
|
||||||
|
*/
|
||||||
|
VB2_ERROR_SIG_SIZE_FOR_KEY,
|
||||||
|
|
||||||
|
/* Bad signature size in vb2_sign_data() */
|
||||||
|
VB2_SIGN_DATA_SIG_SIZE,
|
||||||
|
|
||||||
|
/* Unable to get digest info in vb2_sign_data() */
|
||||||
|
VB2_SIGN_DATA_DIGEST_INFO,
|
||||||
|
|
||||||
|
/* Unable to get digest size in vb2_sign_data() */
|
||||||
|
VB2_SIGN_DATA_DIGEST_SIZE,
|
||||||
|
|
||||||
|
/* Unable to allocate digest buffer in vb2_sign_data() */
|
||||||
|
VB2_SIGN_DATA_DIGEST_ALLOC,
|
||||||
|
|
||||||
|
/* Unable to initialize digest in vb2_sign_data() */
|
||||||
|
VB2_SIGN_DATA_DIGEST_INIT,
|
||||||
|
|
||||||
|
/* Unable to extend digest in vb2_sign_data() */
|
||||||
|
VB2_SIGN_DATA_DIGEST_EXTEND,
|
||||||
|
|
||||||
|
/* Unable to finalize digest in vb2_sign_data() */
|
||||||
|
VB2_SIGN_DATA_DIGEST_FINALIZE,
|
||||||
|
|
||||||
|
/* RSA encrypt failed in vb2_sign_data() */
|
||||||
|
VB2_SIGN_DATA_RSA_ENCRYPT,
|
||||||
|
|
||||||
|
/* Not enough buffer space to hold signature in vb2_sign_object() */
|
||||||
|
VB2_SIGN_OBJECT_OVERFLOW,
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* Errors generated by host library keyblock functions
|
||||||
|
*/
|
||||||
|
VB2_ERROR_HOST_KEYBLOCK = VB2_ERROR_HOST_BASE + 0x040000,
|
||||||
|
|
||||||
|
/* Unable to determine signature sizes for vb2_create_keyblock() */
|
||||||
|
VB2_KEYBLOCK_CREATE_SIG_SIZE,
|
||||||
|
|
||||||
|
/* Unable to pack data key for vb2_create_keyblock() */
|
||||||
|
VB2_KEYBLOCK_CREATE_DATA_KEY,
|
||||||
|
|
||||||
|
/* Unable to allocate buffer in vb2_create_keyblock() */
|
||||||
|
VB2_KEYBLOCK_CREATE_ALLOC,
|
||||||
|
|
||||||
|
/* Unable to sign keyblock in vb2_create_keyblock() */
|
||||||
|
VB2_KEYBLOCK_CREATE_SIGN,
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* Errors generated by host library firmware preamble functions
|
||||||
|
*/
|
||||||
|
VB2_ERROR_HOST_FW_PREAMBLE = VB2_ERROR_HOST_BASE + 0x050000,
|
||||||
|
|
||||||
|
/* Unable to determine signature sizes for vb2_create_fw_preamble() */
|
||||||
|
VB2_FW_PREAMBLE_CREATE_SIG_SIZE,
|
||||||
|
|
||||||
|
/* Unable to allocate buffer in vb2_create_fw_preamble() */
|
||||||
|
VB2_FW_PREAMBLE_CREATE_ALLOC,
|
||||||
|
|
||||||
|
/* Unable to sign preamble in vb2_create_fw_preamble() */
|
||||||
|
VB2_FW_PREAMBLE_CREATE_SIGN,
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* Errors generated by unit test functions
|
||||||
|
*/
|
||||||
|
VB2_ERROR_UNIT_TEST = VB2_ERROR_HOST_BASE + 0x060000,
|
||||||
|
|
||||||
|
/* Unable to open an input file needed for a unit test */
|
||||||
|
VB2_ERROR_TEST_INPUT_FILE,
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* Highest non-zero error generated inside vboot library. Note that
|
||||||
|
* error codes passed through vboot when it calls external APIs may
|
||||||
|
* still be outside this range.
|
||||||
|
*/
|
||||||
|
VB2_ERROR_MAX = VB2_ERROR_BASE + 0x1fffffff,
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* VBOOT_2_RETURN_CODES_H_ */
|
||||||
80
firmware/coreboot/3rdparty/vboot/firmware/2lib/include/2rsa.h
vendored
Normal file
80
firmware/coreboot/3rdparty/vboot/firmware/2lib/include/2rsa.h
vendored
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
/* Copyright (c) 2014 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef VBOOT_REFERENCE_2RSA_H_
|
||||||
|
#define VBOOT_REFERENCE_2RSA_H_
|
||||||
|
|
||||||
|
#include "2crypto.h"
|
||||||
|
#include "2struct.h"
|
||||||
|
|
||||||
|
struct vb2_workbuf;
|
||||||
|
|
||||||
|
/* Public key structure in RAM */
|
||||||
|
struct vb2_public_key {
|
||||||
|
uint32_t arrsize; /* Length of n[] and rr[] in number of uint32_t */
|
||||||
|
uint32_t n0inv; /* -1 / n[0] mod 2^32 */
|
||||||
|
const uint32_t *n; /* Modulus as little endian array */
|
||||||
|
const uint32_t *rr; /* R^2 as little endian array */
|
||||||
|
enum vb2_signature_algorithm sig_alg; /* Signature algorithm */
|
||||||
|
enum vb2_hash_algorithm hash_alg; /* Hash algorithm */
|
||||||
|
const char *desc; /* Description */
|
||||||
|
uint32_t version; /* Key version */
|
||||||
|
const struct vb2_id *id; /* Key ID */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert vb2_crypto_algorithm to vb2_signature_algorithm.
|
||||||
|
*
|
||||||
|
* @param algorithm Crypto algorithm (vb2_crypto_algorithm)
|
||||||
|
*
|
||||||
|
* @return The signature algorithm for that crypto algorithm, or
|
||||||
|
* VB2_SIG_INVALID if the crypto algorithm or its corresponding signature
|
||||||
|
* algorithm is invalid or not supported.
|
||||||
|
*/
|
||||||
|
enum vb2_signature_algorithm vb2_crypto_to_signature(uint32_t algorithm);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the size of a RSA signature
|
||||||
|
*
|
||||||
|
* @param sig_alg Signature algorithm
|
||||||
|
* @return The size of the signature in bytes, or 0 if error.
|
||||||
|
*/
|
||||||
|
uint32_t vb2_rsa_sig_size(enum vb2_signature_algorithm sig_alg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the size of a pre-processed RSA public key.
|
||||||
|
*
|
||||||
|
* @param sig_alg Signature algorithm
|
||||||
|
* @return The size of the preprocessed key in bytes, or 0 if error.
|
||||||
|
*/
|
||||||
|
uint32_t vb2_packed_key_size(enum vb2_signature_algorithm sig_alg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check pkcs 1.5 padding bytes
|
||||||
|
*
|
||||||
|
* @param sig Signature to verify
|
||||||
|
* @param key Key to take signature and hash algorithms from
|
||||||
|
* @return VB2_SUCCESS, or non-zero if error.
|
||||||
|
*/
|
||||||
|
int vb2_check_padding(const uint8_t *sig, const struct vb2_public_key *key);
|
||||||
|
|
||||||
|
/* Size of work buffer sufficient for vb2_rsa_verify_digest() worst case */
|
||||||
|
#define VB2_VERIFY_RSA_DIGEST_WORKBUF_BYTES (3 * 1024)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify a RSA PKCS1.5 signature against an expected hash digest.
|
||||||
|
*
|
||||||
|
* @param key Key to use in signature verification
|
||||||
|
* @param sig Signature to verify (destroyed in process)
|
||||||
|
* @param digest Digest of signed data
|
||||||
|
* @param wb Work buffer
|
||||||
|
* @return VB2_SUCCESS, or non-zero if error.
|
||||||
|
*/
|
||||||
|
int vb2_rsa_verify_digest(const struct vb2_public_key *key,
|
||||||
|
uint8_t *sig,
|
||||||
|
const uint8_t *digest,
|
||||||
|
const struct vb2_workbuf *wb);
|
||||||
|
|
||||||
|
#endif /* VBOOT_REFERENCE_2RSA_H_ */
|
||||||
219
firmware/coreboot/3rdparty/vboot/firmware/2lib/include/2secdata.h
vendored
Normal file
219
firmware/coreboot/3rdparty/vboot/firmware/2lib/include/2secdata.h
vendored
Normal file
@@ -0,0 +1,219 @@
|
|||||||
|
/* Copyright (c) 2014 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.
|
||||||
|
*
|
||||||
|
* Secure non-volatile storage routines
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef VBOOT_REFERENCE_VBOOT_SECDATA_H_
|
||||||
|
#define VBOOT_REFERENCE_VBOOT_SECDATA_H_
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Firmware version space */
|
||||||
|
|
||||||
|
/* Expected value of vb2_secdata.version */
|
||||||
|
#define VB2_SECDATA_VERSION 2
|
||||||
|
|
||||||
|
/* Flags for firmware space */
|
||||||
|
enum vb2_secdata_flags {
|
||||||
|
/*
|
||||||
|
* Last boot was developer mode. TPM ownership is cleared when
|
||||||
|
* transitioning to/from developer mode. Set/cleared by
|
||||||
|
* vb2_check_dev_switch().
|
||||||
|
*/
|
||||||
|
VB2_SECDATA_FLAG_LAST_BOOT_DEVELOPER = (1 << 0),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Virtual developer mode switch is on. Set/cleared by the
|
||||||
|
* keyboard-controlled dev screens in recovery mode. Cleared by
|
||||||
|
* vb2_check_dev_switch().
|
||||||
|
*/
|
||||||
|
VB2_SECDATA_FLAG_DEV_MODE = (1 << 1),
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Secure data area (firmware space) */
|
||||||
|
struct vb2_secdata {
|
||||||
|
/* Struct version, for backwards compatibility */
|
||||||
|
uint8_t struct_version;
|
||||||
|
|
||||||
|
/* Flags; see vb2_secdata_flags */
|
||||||
|
uint8_t flags;
|
||||||
|
|
||||||
|
/* Firmware versions */
|
||||||
|
uint32_t fw_versions;
|
||||||
|
|
||||||
|
/* Reserved for future expansion */
|
||||||
|
uint8_t reserved[3];
|
||||||
|
|
||||||
|
/* CRC; must be last field in struct */
|
||||||
|
uint8_t crc8;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
/* Which param to get/set for vb2_secdata_get() / vb2_secdata_set() */
|
||||||
|
enum vb2_secdata_param {
|
||||||
|
/* Flags; see vb2_secdata_flags */
|
||||||
|
VB2_SECDATA_FLAGS = 0,
|
||||||
|
|
||||||
|
/* Firmware versions */
|
||||||
|
VB2_SECDATA_VERSIONS,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Kernel version space */
|
||||||
|
|
||||||
|
/* Kernel space - KERNEL_NV_INDEX, locked with physical presence. */
|
||||||
|
#define VB2_SECDATAK_VERSION 2
|
||||||
|
#define VB2_SECDATAK_UID 0x4752574c /* 'GRWL' */
|
||||||
|
|
||||||
|
struct vb2_secdatak {
|
||||||
|
/* 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];
|
||||||
|
|
||||||
|
/* CRC; must be last field in struct */
|
||||||
|
uint8_t crc8;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
/* Which param to get/set for vb2_secdatak_get() / vb2_secdatak_set() */
|
||||||
|
enum vb2_secdatak_param {
|
||||||
|
/* Kernel versions */
|
||||||
|
VB2_SECDATAK_VERSIONS = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Firmware version space functions */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check the CRC of the secure storage context.
|
||||||
|
*
|
||||||
|
* Use this if reading from secure storage may be flaky, and you want to retry
|
||||||
|
* reading it several times.
|
||||||
|
*
|
||||||
|
* This may be called before vb2_context_init().
|
||||||
|
*
|
||||||
|
* @param ctx Context pointer
|
||||||
|
* @return VB2_SUCCESS, or non-zero error code if error.
|
||||||
|
*/
|
||||||
|
int vb2_secdata_check_crc(const struct vb2_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create fresh data in the secure storage context.
|
||||||
|
*
|
||||||
|
* Use this only when initializing the secure storage context on a new machine
|
||||||
|
* the first time it boots. Do NOT simply use this if vb2_secdata_check_crc()
|
||||||
|
* (or any other API in this library) fails; that could allow the secure data
|
||||||
|
* to be rolled back to an insecure state.
|
||||||
|
*
|
||||||
|
* This may be called before vb2_context_init().
|
||||||
|
*/
|
||||||
|
int vb2_secdata_create(struct vb2_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the secure storage context and verify its CRC.
|
||||||
|
*
|
||||||
|
* This must be called before vb2_secdata_get() or vb2_secdata_set().
|
||||||
|
*
|
||||||
|
* @param ctx Context pointer
|
||||||
|
* @return VB2_SUCCESS, or non-zero error code if error.
|
||||||
|
*/
|
||||||
|
int vb2_secdata_init(struct vb2_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a secure storage value.
|
||||||
|
*
|
||||||
|
* @param ctx Context pointer
|
||||||
|
* @param param Parameter to read
|
||||||
|
* @param dest Destination for value
|
||||||
|
* @return VB2_SUCCESS, or non-zero error code if error.
|
||||||
|
*/
|
||||||
|
int vb2_secdata_get(struct vb2_context *ctx,
|
||||||
|
enum vb2_secdata_param param,
|
||||||
|
uint32_t *dest);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a secure storage value.
|
||||||
|
*
|
||||||
|
* @param ctx Context pointer
|
||||||
|
* @param param Parameter to write
|
||||||
|
* @param value New value
|
||||||
|
* @return VB2_SUCCESS, or non-zero error code if error.
|
||||||
|
*/
|
||||||
|
int vb2_secdata_set(struct vb2_context *ctx,
|
||||||
|
enum vb2_secdata_param param,
|
||||||
|
uint32_t value);
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Kernel version space functions.
|
||||||
|
*
|
||||||
|
* These are separate functions so that they don't bloat the size of the early
|
||||||
|
* boot code which uses the firmware version space functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check the CRC of the kernel version secure storage context.
|
||||||
|
*
|
||||||
|
* Use this if reading from secure storage may be flaky, and you want to retry
|
||||||
|
* reading it several times.
|
||||||
|
*
|
||||||
|
* This may be called before vb2_context_init().
|
||||||
|
*
|
||||||
|
* @param ctx Context pointer
|
||||||
|
* @return VB2_SUCCESS, or non-zero error code if error.
|
||||||
|
*/
|
||||||
|
int vb2_secdatak_check_crc(const struct vb2_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create fresh data in the secure storage context.
|
||||||
|
*
|
||||||
|
* Use this only when initializing the secure storage context on a new machine
|
||||||
|
* the first time it boots. Do NOT simply use this if vb2_secdatak_check_crc()
|
||||||
|
* (or any other API in this library) fails; that could allow the secure data
|
||||||
|
* to be rolled back to an insecure state.
|
||||||
|
*
|
||||||
|
* This may be called before vb2_context_init().
|
||||||
|
*/
|
||||||
|
int vb2_secdatak_create(struct vb2_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the secure storage context and verify its CRC.
|
||||||
|
*
|
||||||
|
* This must be called before vb2_secdatak_get() or vb2_secdatak_set().
|
||||||
|
*
|
||||||
|
* @param ctx Context pointer
|
||||||
|
* @return VB2_SUCCESS, or non-zero error code if error.
|
||||||
|
*/
|
||||||
|
int vb2_secdatak_init(struct vb2_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a secure storage value.
|
||||||
|
*
|
||||||
|
* @param ctx Context pointer
|
||||||
|
* @param param Parameter to read
|
||||||
|
* @param dest Destination for value
|
||||||
|
* @return VB2_SUCCESS, or non-zero error code if error.
|
||||||
|
*/
|
||||||
|
int vb2_secdatak_get(struct vb2_context *ctx,
|
||||||
|
enum vb2_secdatak_param param,
|
||||||
|
uint32_t *dest);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a secure storage value.
|
||||||
|
*
|
||||||
|
* @param ctx Context pointer
|
||||||
|
* @param param Parameter to write
|
||||||
|
* @param value New value
|
||||||
|
* @return VB2_SUCCESS, or non-zero error code if error.
|
||||||
|
*/
|
||||||
|
int vb2_secdatak_set(struct vb2_context *ctx,
|
||||||
|
enum vb2_secdatak_param param,
|
||||||
|
uint32_t value);
|
||||||
|
|
||||||
|
#endif /* VBOOT_REFERENCE_VBOOT_2SECDATA_H_ */
|
||||||
232
firmware/coreboot/3rdparty/vboot/firmware/2lib/include/2sha.h
vendored
Normal file
232
firmware/coreboot/3rdparty/vboot/firmware/2lib/include/2sha.h
vendored
Normal file
@@ -0,0 +1,232 @@
|
|||||||
|
/* Copyright (c) 2014 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.
|
||||||
|
*
|
||||||
|
* These APIs may be called by external firmware as well as vboot. External
|
||||||
|
* firmware must NOT include this header file directly; instead, define
|
||||||
|
* NEED_VB2_SHA_LIBRARY and include vb2api.h. This is permissible because the
|
||||||
|
* SHA library routines below don't interact with the rest of vboot.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef VBOOT_REFERENCE_2SHA_H_
|
||||||
|
#define VBOOT_REFERENCE_2SHA_H_
|
||||||
|
|
||||||
|
#include "2crypto.h"
|
||||||
|
|
||||||
|
/* Hash algorithms may be disabled individually to save code space */
|
||||||
|
|
||||||
|
#ifndef VB2_SUPPORT_SHA1
|
||||||
|
#define VB2_SUPPORT_SHA1 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef VB2_SUPPORT_SHA256
|
||||||
|
#define VB2_SUPPORT_SHA256 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef VB2_SUPPORT_SHA512
|
||||||
|
#define VB2_SUPPORT_SHA512 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* These are set to the biggest values among the supported hash algorithms.
|
||||||
|
* They have to be updated as we add new hash algorithms */
|
||||||
|
#define VB2_MAX_DIGEST_SIZE VB2_SHA512_DIGEST_SIZE
|
||||||
|
#define VB2_MAX_BLOCK_SIZE VB2_SHA512_BLOCK_SIZE
|
||||||
|
#define VB2_INVALID_ALG_NAME "INVALID"
|
||||||
|
|
||||||
|
#define VB2_SHA1_DIGEST_SIZE 20
|
||||||
|
#define VB2_SHA1_BLOCK_SIZE 64
|
||||||
|
#define VB2_SHA1_ALG_NAME "SHA1"
|
||||||
|
|
||||||
|
/* Context structs for hash algorithms */
|
||||||
|
|
||||||
|
struct vb2_sha1_context {
|
||||||
|
uint32_t count;
|
||||||
|
uint32_t state[5];
|
||||||
|
#if defined(HAVE_ENDIAN_H) && defined(HAVE_LITTLE_ENDIAN)
|
||||||
|
union {
|
||||||
|
uint8_t b[VB2_SHA1_BLOCK_SIZE];
|
||||||
|
uint32_t w[VB2_SHA1_BLOCK_SIZE / sizeof(uint32_t)];
|
||||||
|
} buf;
|
||||||
|
#else
|
||||||
|
uint8_t buf[VB2_SHA1_BLOCK_SIZE];
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#define VB2_SHA256_DIGEST_SIZE 32
|
||||||
|
#define VB2_SHA256_BLOCK_SIZE 64
|
||||||
|
#define VB2_SHA256_ALG_NAME "SHA256"
|
||||||
|
|
||||||
|
struct vb2_sha256_context {
|
||||||
|
uint32_t h[8];
|
||||||
|
uint32_t total_size;
|
||||||
|
uint32_t size;
|
||||||
|
uint8_t block[2 * VB2_SHA256_BLOCK_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define VB2_SHA512_DIGEST_SIZE 64
|
||||||
|
#define VB2_SHA512_BLOCK_SIZE 128
|
||||||
|
#define VB2_SHA512_ALG_NAME "SHA512"
|
||||||
|
|
||||||
|
struct vb2_sha512_context {
|
||||||
|
uint64_t h[8];
|
||||||
|
uint32_t total_size;
|
||||||
|
uint32_t size;
|
||||||
|
uint8_t block[2 * VB2_SHA512_BLOCK_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Hash algorithm independent digest context; includes all of the above. */
|
||||||
|
struct vb2_digest_context {
|
||||||
|
/* Context union for all algorithms */
|
||||||
|
union {
|
||||||
|
#if VB2_SUPPORT_SHA1
|
||||||
|
struct vb2_sha1_context sha1;
|
||||||
|
#endif
|
||||||
|
#if VB2_SUPPORT_SHA256
|
||||||
|
struct vb2_sha256_context sha256;
|
||||||
|
#endif
|
||||||
|
#if VB2_SUPPORT_SHA512
|
||||||
|
struct vb2_sha512_context sha512;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Current hash algorithm */
|
||||||
|
enum vb2_hash_algorithm hash_alg;
|
||||||
|
|
||||||
|
/* 1 if digest is computed with vb2ex_hwcrypto routines, else 0 */
|
||||||
|
int using_hwcrypto;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize a hash context.
|
||||||
|
*
|
||||||
|
* @param ctx Hash context
|
||||||
|
*/
|
||||||
|
void vb2_sha1_init(struct vb2_sha1_context *ctx);
|
||||||
|
void vb2_sha256_init(struct vb2_sha256_context *ctx);
|
||||||
|
void vb2_sha512_init(struct vb2_sha512_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update (extend) a hash.
|
||||||
|
*
|
||||||
|
* @param ctx Hash context
|
||||||
|
* @param data Data to hash
|
||||||
|
* @param size Length of data in bytes
|
||||||
|
*/
|
||||||
|
void vb2_sha1_update(struct vb2_sha1_context *ctx,
|
||||||
|
const uint8_t *data,
|
||||||
|
uint32_t size);
|
||||||
|
void vb2_sha256_update(struct vb2_sha256_context *ctx,
|
||||||
|
const uint8_t *data,
|
||||||
|
uint32_t size);
|
||||||
|
void vb2_sha512_update(struct vb2_sha512_context *ctx,
|
||||||
|
const uint8_t *data,
|
||||||
|
uint32_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finalize a hash digest.
|
||||||
|
*
|
||||||
|
* @param ctx Hash context
|
||||||
|
* @param digest Destination for hash; must be VB_SHA*_DIGEST_SIZE bytes
|
||||||
|
*/
|
||||||
|
void vb2_sha1_finalize(struct vb2_sha1_context *ctx, uint8_t *digest);
|
||||||
|
void vb2_sha256_finalize(struct vb2_sha256_context *ctx, uint8_t *digest);
|
||||||
|
void vb2_sha512_finalize(struct vb2_sha512_context *ctx, uint8_t *digest);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hash-extend data
|
||||||
|
*
|
||||||
|
* @param from Hash to be extended. It has to be the hash size.
|
||||||
|
* @param by Block to be extended by. It has to be the hash block size.
|
||||||
|
* @param to Destination for extended data
|
||||||
|
*/
|
||||||
|
void vb2_sha256_extend(const uint8_t *from, const uint8_t *by, uint8_t *to);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert vb2_crypto_algorithm to vb2_hash_algorithm.
|
||||||
|
*
|
||||||
|
* @param algorithm Crypto algorithm (vb2_crypto_algorithm)
|
||||||
|
*
|
||||||
|
* @return The hash algorithm for that crypto algorithm, or VB2_HASH_INVALID if
|
||||||
|
* the crypto algorithm or its corresponding hash algorithm is invalid or not
|
||||||
|
* supported.
|
||||||
|
*/
|
||||||
|
enum vb2_hash_algorithm vb2_crypto_to_hash(uint32_t algorithm);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the size of the digest for a hash algorithm.
|
||||||
|
*
|
||||||
|
* @param hash_alg Hash algorithm
|
||||||
|
* @return The size of the digest, or 0 if error.
|
||||||
|
*/
|
||||||
|
int vb2_digest_size(enum vb2_hash_algorithm hash_alg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the block size of a hash algorithm.
|
||||||
|
*
|
||||||
|
* @param hash_alg Hash algorithm
|
||||||
|
* @return The block size of the algorithm, or 0 if error.
|
||||||
|
*/
|
||||||
|
int vb2_hash_block_size(enum vb2_hash_algorithm alg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the name of a hash algorithm
|
||||||
|
*
|
||||||
|
* @param alg Hash algorithm ID
|
||||||
|
* @return String containing a hash name or VB2_INVALID_ALG_NAME
|
||||||
|
* if <alg> is invalid.
|
||||||
|
*/
|
||||||
|
const char *vb2_get_hash_algorithm_name(enum vb2_hash_algorithm alg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize a digest context for doing block-style digesting.
|
||||||
|
*
|
||||||
|
* @param dc Digest context
|
||||||
|
* @param hash_alg Hash algorithm
|
||||||
|
* @return VB2_SUCCESS, or non-zero on error.
|
||||||
|
*/
|
||||||
|
int vb2_digest_init(struct vb2_digest_context *dc,
|
||||||
|
enum vb2_hash_algorithm hash_alg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extend a digest's hash with another block of data.
|
||||||
|
*
|
||||||
|
* @param dc Digest context
|
||||||
|
* @param buf Data to hash
|
||||||
|
* @param size Length of data in bytes
|
||||||
|
* @return VB2_SUCCESS, or non-zero on error.
|
||||||
|
*/
|
||||||
|
int vb2_digest_extend(struct vb2_digest_context *dc,
|
||||||
|
const uint8_t *buf,
|
||||||
|
uint32_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finalize a digest and store the result.
|
||||||
|
*
|
||||||
|
* The destination digest should be at least vb2_digest_size(algorithm).
|
||||||
|
*
|
||||||
|
* @param dc Digest context
|
||||||
|
* @param digest Destination for digest
|
||||||
|
* @param digest_size Length of digest buffer in bytes.
|
||||||
|
* @return VB2_SUCCESS, or non-zero on error.
|
||||||
|
*/
|
||||||
|
int vb2_digest_finalize(struct vb2_digest_context *dc,
|
||||||
|
uint8_t *digest,
|
||||||
|
uint32_t digest_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the digest of a buffer and store the result.
|
||||||
|
*
|
||||||
|
* @param buf Data to hash
|
||||||
|
* @param size Length of data in bytes
|
||||||
|
* @param hash_alg Hash algorithm
|
||||||
|
* @param digest Destination for digest
|
||||||
|
* @param digest_size Length of digest buffer in bytes.
|
||||||
|
* @return VB2_SUCCESS, or non-zero on error.
|
||||||
|
*/
|
||||||
|
int vb2_digest_buffer(const uint8_t *buf,
|
||||||
|
uint32_t size,
|
||||||
|
enum vb2_hash_algorithm hash_alg,
|
||||||
|
uint8_t *digest,
|
||||||
|
uint32_t digest_size);
|
||||||
|
|
||||||
|
#endif /* VBOOT_REFERENCE_2SHA_H_ */
|
||||||
373
firmware/coreboot/3rdparty/vboot/firmware/2lib/include/2struct.h
vendored
Normal file
373
firmware/coreboot/3rdparty/vboot/firmware/2lib/include/2struct.h
vendored
Normal file
@@ -0,0 +1,373 @@
|
|||||||
|
/* Copyright (c) 2014 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.
|
||||||
|
*
|
||||||
|
* Data structure definitions for verified boot, for on-disk / in-eeprom
|
||||||
|
* data.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef VBOOT_REFERENCE_VBOOT_2STRUCT_H_
|
||||||
|
#define VBOOT_REFERENCE_VBOOT_2STRUCT_H_
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "2crypto.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Key block flags.
|
||||||
|
*
|
||||||
|
*The following flags set where the key is valid. Not used by firmware
|
||||||
|
* verification; only kernel verification.
|
||||||
|
*/
|
||||||
|
#define VB2_KEY_BLOCK_FLAG_DEVELOPER_0 0x01 /* Developer switch off */
|
||||||
|
#define VB2_KEY_BLOCK_FLAG_DEVELOPER_1 0x02 /* Developer switch on */
|
||||||
|
#define VB2_KEY_BLOCK_FLAG_RECOVERY_0 0x04 /* Not recovery mode */
|
||||||
|
#define VB2_KEY_BLOCK_FLAG_RECOVERY_1 0x08 /* Recovery mode */
|
||||||
|
#define VB2_GBB_HWID_DIGEST_SIZE 32
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
|
||||||
|
/* Flags for vb2_shared_data.flags */
|
||||||
|
enum vb2_shared_data_flags {
|
||||||
|
/* User has explicitly and physically requested recovery */
|
||||||
|
VB2_SD_FLAG_MANUAL_RECOVERY = (1 << 0),
|
||||||
|
|
||||||
|
/* Developer mode is enabled */
|
||||||
|
/* TODO: should have been VB2_SD_FLAG_DEV_MODE_ENABLED */
|
||||||
|
VB2_SD_DEV_MODE_ENABLED = (1 << 1),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO: might be nice to add flags for why dev mode is enabled - via
|
||||||
|
* gbb, virtual dev switch, or forced on for testing.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Kernel keyblock was verified by signature (not just hash) */
|
||||||
|
VB2_SD_FLAG_KERNEL_SIGNED = (1 << 2),
|
||||||
|
|
||||||
|
/* Software sync needs to update EC-RO, EC-RW, or PD-RW respectively */
|
||||||
|
VB2_SD_FLAG_ECSYNC_EC_RO = (1 << 3),
|
||||||
|
VB2_SD_FLAG_ECSYNC_EC_RW = (1 << 4),
|
||||||
|
VB2_SD_FLAG_ECSYNC_PD_RW = (1 << 5),
|
||||||
|
|
||||||
|
/* Software sync says EC / PD running RW */
|
||||||
|
VB2_SD_FLAG_ECSYNC_EC_IN_RW = (1 << 6),
|
||||||
|
VB2_SD_FLAG_ECSYNC_PD_IN_RW = (1 << 7),
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Flags for vb2_shared_data.status */
|
||||||
|
enum vb2_shared_data_status {
|
||||||
|
/* Reinitialized NV data due to invalid checksum */
|
||||||
|
VB2_SD_STATUS_NV_REINIT = (1 << 0),
|
||||||
|
|
||||||
|
/* NV data has been initialized */
|
||||||
|
VB2_SD_STATUS_NV_INIT = (1 << 1),
|
||||||
|
|
||||||
|
/* Secure data initialized */
|
||||||
|
VB2_SD_STATUS_SECDATA_INIT = (1 << 2),
|
||||||
|
|
||||||
|
/* Chose a firmware slot */
|
||||||
|
VB2_SD_STATUS_CHOSE_SLOT = (1 << 3),
|
||||||
|
|
||||||
|
/* Secure data kernel version space initialized */
|
||||||
|
VB2_SD_STATUS_SECDATAK_INIT = (1 << 4),
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Data shared between vboot API calls. Stored at the start of the work
|
||||||
|
* buffer.
|
||||||
|
*/
|
||||||
|
struct vb2_shared_data {
|
||||||
|
/* Flags; see enum vb2_shared_data_flags */
|
||||||
|
uint32_t flags;
|
||||||
|
|
||||||
|
/* Flags from GBB header */
|
||||||
|
uint32_t gbb_flags;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reason we are in recovery mode this boot (enum vb2_nv_recovery), or
|
||||||
|
* 0 if we aren't.
|
||||||
|
*/
|
||||||
|
uint32_t recovery_reason;
|
||||||
|
|
||||||
|
/* Firmware slot used last boot (0=A, 1=B) */
|
||||||
|
uint32_t last_fw_slot;
|
||||||
|
|
||||||
|
/* Result of last boot (enum vb2_fw_result) */
|
||||||
|
uint32_t last_fw_result;
|
||||||
|
|
||||||
|
/* Firmware slot used this boot */
|
||||||
|
uint32_t fw_slot;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Version for this slot (top 16 bits = key, lower 16 bits = firmware).
|
||||||
|
*
|
||||||
|
* TODO: Make this a union to allow getting/setting those versions
|
||||||
|
* separately?
|
||||||
|
*/
|
||||||
|
uint32_t fw_version;
|
||||||
|
|
||||||
|
/* Version stored in secdata (must be <= fw_version to boot). */
|
||||||
|
uint32_t fw_version_secdata;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Status flags for this boot; see enum vb2_shared_data_status. Status
|
||||||
|
* is "what we've done"; flags above are "decisions we've made".
|
||||||
|
*/
|
||||||
|
uint32_t status;
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* Data from kernel verification stage.
|
||||||
|
*
|
||||||
|
* TODO: shouldn't be part of the main struct, since that needlessly
|
||||||
|
* uses more memory during firmware verification.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Version for the current kernel (top 16 bits = key, lower 16 bits =
|
||||||
|
* kernel preamble).
|
||||||
|
*
|
||||||
|
* TODO: Make this a union to allow getting/setting those versions
|
||||||
|
* separately?
|
||||||
|
*/
|
||||||
|
uint32_t kernel_version;
|
||||||
|
|
||||||
|
/* Kernel version from secdatak (must be <= kernel_version to boot) */
|
||||||
|
uint32_t kernel_version_secdatak;
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* Temporary variables used during firmware verification. These don't
|
||||||
|
* really need to persist through to the OS, but there's nowhere else
|
||||||
|
* we can put them.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Root key offset and size from GBB header */
|
||||||
|
uint32_t gbb_rootkey_offset;
|
||||||
|
uint32_t gbb_rootkey_size;
|
||||||
|
|
||||||
|
/* HWID digest from GBB header */
|
||||||
|
uint8_t gbb_hwid_digest[VB2_GBB_HWID_DIGEST_SIZE];
|
||||||
|
|
||||||
|
/* Offset of preamble from start of vblock */
|
||||||
|
uint32_t vblock_preamble_offset;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Offset and size of packed data key in work buffer. Size is 0 if
|
||||||
|
* data key is not stored in the work buffer.
|
||||||
|
*/
|
||||||
|
uint32_t workbuf_data_key_offset;
|
||||||
|
uint32_t workbuf_data_key_size;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Offset and size of firmware preamble in work buffer. Size is 0 if
|
||||||
|
* preamble is not stored in the work buffer.
|
||||||
|
*/
|
||||||
|
uint32_t workbuf_preamble_offset;
|
||||||
|
uint32_t workbuf_preamble_size;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Offset and size of hash context in work buffer. Size is 0 if
|
||||||
|
* hash context is not stored in the work buffer.
|
||||||
|
*/
|
||||||
|
uint32_t workbuf_hash_offset;
|
||||||
|
uint32_t workbuf_hash_size;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Current tag we're hashing
|
||||||
|
*
|
||||||
|
* For new structs, this is the offset of the vb2_signature struct
|
||||||
|
* in the work buffer.
|
||||||
|
*
|
||||||
|
* TODO: rename to workbuf_hash_sig_offset when vboot1 structs are
|
||||||
|
* deprecated.
|
||||||
|
*/
|
||||||
|
uint32_t hash_tag;
|
||||||
|
|
||||||
|
/* Amount of data we still expect to hash */
|
||||||
|
uint32_t hash_remaining_size;
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* Temporary variables used during kernel verification. These don't
|
||||||
|
* really need to persist through to the OS, but there's nowhere else
|
||||||
|
* we can put them.
|
||||||
|
*
|
||||||
|
* TODO: make a union with the firmware verification temp variables,
|
||||||
|
* or make both of them workbuf-allocated sub-structs, so that we can
|
||||||
|
* overlap them so kernel variables don't bloat firmware verification
|
||||||
|
* stage memory requirements.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Vboot1 shared data header. This data should eventually get folded
|
||||||
|
* directly into the kernel portion of this struct.
|
||||||
|
*/
|
||||||
|
struct VbSharedDataHeader *vbsd;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Offset and size of packed kernel key in work buffer. Size is 0 if
|
||||||
|
* subkey is not stored in the work buffer. Note that kernel key may
|
||||||
|
* be inside the firmware preamble.
|
||||||
|
*/
|
||||||
|
uint32_t workbuf_kernel_key_offset;
|
||||||
|
uint32_t workbuf_kernel_key_size;
|
||||||
|
|
||||||
|
/* GBB data and size */
|
||||||
|
struct vb2_gbb_header *gbb;
|
||||||
|
uint32_t gbb_size;
|
||||||
|
|
||||||
|
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
|
||||||
|
/* Signature at start of the GBB
|
||||||
|
* Note that if you compile in the signature as is, you are likely to break any
|
||||||
|
* tools that search for the signature. */
|
||||||
|
#define VB2_GBB_SIGNATURE "$GBB"
|
||||||
|
#define VB2_GBB_SIGNATURE_SIZE 4
|
||||||
|
#define VB2_GBB_XOR_CHARS "****"
|
||||||
|
/* TODO: can we write a macro to produce this at compile time? */
|
||||||
|
#define VB2_GBB_XOR_SIGNATURE { 0x0e, 0x6d, 0x68, 0x68 }
|
||||||
|
|
||||||
|
/* VB2 GBB struct version */
|
||||||
|
#define VB2_GBB_MAJOR_VER 1
|
||||||
|
#define VB2_GBB_MINOR_VER 2
|
||||||
|
/* v1.2 - added fields for sha256 digest of the HWID */
|
||||||
|
|
||||||
|
/* Flags for vb2_gbb_header.flags */
|
||||||
|
enum vb2_gbb_flag {
|
||||||
|
/*
|
||||||
|
* Reduce the dev screen delay to 2 sec from 30 sec to speed up
|
||||||
|
* factory.
|
||||||
|
*/
|
||||||
|
VB2_GBB_FLAG_DEV_SCREEN_SHORT_DELAY = (1 << 0),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* BIOS should load option ROMs from arbitrary PCI devices. We'll never
|
||||||
|
* enable this ourselves because it executes non-verified code, but if
|
||||||
|
* a customer wants to void their warranty and set this flag in the
|
||||||
|
* read-only flash, they should be able to do so.
|
||||||
|
*
|
||||||
|
* (TODO: Currently not supported. Mark as deprecated/unused?)
|
||||||
|
*/
|
||||||
|
VB2_GBB_FLAG_LOAD_OPTION_ROMS = (1 << 1),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The factory flow may need the BIOS to boot a non-ChromeOS kernel if
|
||||||
|
* the dev-switch is on. This flag allows that.
|
||||||
|
*
|
||||||
|
* (TODO: Currently not supported. Mark as deprecated/unused?)
|
||||||
|
*/
|
||||||
|
VB2_GBB_FLAG_ENABLE_ALTERNATE_OS = (1 << 2),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Force dev switch on, regardless of physical/keyboard dev switch
|
||||||
|
* position.
|
||||||
|
*/
|
||||||
|
VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON = (1 << 3),
|
||||||
|
|
||||||
|
/* Allow booting from USB in dev mode even if dev_boot_usb=0. */
|
||||||
|
VB2_GBB_FLAG_FORCE_DEV_BOOT_USB = (1 << 4),
|
||||||
|
|
||||||
|
/* Disable firmware rollback protection. */
|
||||||
|
VB2_GBB_FLAG_DISABLE_FW_ROLLBACK_CHECK = (1 << 5),
|
||||||
|
|
||||||
|
/* Allow Enter key to trigger dev->tonorm screen transition */
|
||||||
|
VB2_GBB_FLAG_ENTER_TRIGGERS_TONORM = (1 << 6),
|
||||||
|
|
||||||
|
/* Allow booting Legacy OSes in dev mode even if dev_boot_legacy=0. */
|
||||||
|
VB2_GBB_FLAG_FORCE_DEV_BOOT_LEGACY = (1 << 7),
|
||||||
|
|
||||||
|
/* Allow booting using alternate keys for FAFT servo testing */
|
||||||
|
VB2_GBB_FLAG_FAFT_KEY_OVERIDE = (1 << 8),
|
||||||
|
|
||||||
|
/* Disable EC software sync */
|
||||||
|
VB2_GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC = (1 << 9),
|
||||||
|
|
||||||
|
/* Default to booting legacy OS when dev screen times out */
|
||||||
|
VB2_GBB_FLAG_DEFAULT_DEV_BOOT_LEGACY = (1 << 10),
|
||||||
|
|
||||||
|
/* Disable PD software sync */
|
||||||
|
VB2_GBB_FLAG_DISABLE_PD_SOFTWARE_SYNC = (1 << 11),
|
||||||
|
|
||||||
|
/* Disable shutdown on lid closed */
|
||||||
|
VB2_GBB_FLAG_DISABLE_LID_SHUTDOWN = (1 << 12),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allow full fastboot capability in firmware even if
|
||||||
|
* dev_boot_fastboot_full_cap=0.
|
||||||
|
*/
|
||||||
|
VB2_GBB_FLAG_FORCE_DEV_BOOT_FASTBOOT_FULL_CAP = (1 << 13),
|
||||||
|
|
||||||
|
/* Recovery mode always assumes manual recovery, even if EC_IN_RW=1 */
|
||||||
|
VB2_GBB_FLAG_FORCE_MANUAL_RECOVERY = (1 << 14),
|
||||||
|
|
||||||
|
/* Disable FWMP */
|
||||||
|
VB2_GBB_FLAG_DISABLE_FWMP = (1 << 15),
|
||||||
|
|
||||||
|
/* Enable USB Device Controller */
|
||||||
|
VB2_GBB_FLAG_ENABLE_UDC = (1 << 16),
|
||||||
|
};
|
||||||
|
|
||||||
|
struct vb2_gbb_header {
|
||||||
|
/* Fields present in version 1.1 */
|
||||||
|
uint8_t signature[VB2_GBB_SIGNATURE_SIZE]; /* VB2_GBB_SIGNATURE */
|
||||||
|
uint16_t major_version; /* See VB2_GBB_MAJOR_VER */
|
||||||
|
uint16_t minor_version; /* See VB2_GBB_MINOR_VER */
|
||||||
|
uint32_t header_size; /* Size of GBB header in bytes */
|
||||||
|
uint32_t flags; /* Flags (see enum vb2_gbb_flag) */
|
||||||
|
|
||||||
|
/* Offsets (from start of header) and sizes (in bytes) of components */
|
||||||
|
uint32_t hwid_offset; /* HWID */
|
||||||
|
uint32_t hwid_size;
|
||||||
|
uint32_t rootkey_offset; /* Root key */
|
||||||
|
uint32_t rootkey_size;
|
||||||
|
uint32_t bmpfv_offset; /* BMP FV; deprecated in current FW */
|
||||||
|
uint32_t bmpfv_size;
|
||||||
|
uint32_t recovery_key_offset; /* Recovery key */
|
||||||
|
uint32_t recovery_key_size;
|
||||||
|
|
||||||
|
/* Added in version 1.2 */
|
||||||
|
uint8_t hwid_digest[VB2_GBB_HWID_DIGEST_SIZE]; /* SHA-256 of HWID */
|
||||||
|
|
||||||
|
/* Pad to match EXPECETED_VB2_GBB_HEADER_SIZE. Initialize to 0. */
|
||||||
|
uint8_t pad[48];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
/* The GBB is used outside of vboot_reference, so this size is important. */
|
||||||
|
#define EXPECTED_VB2_GBB_HEADER_SIZE 128
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Root key hash for Ryu devices only. Contains the hash of the root key.
|
||||||
|
* This will be embedded somewhere inside the RO part of the firmware, so that
|
||||||
|
* it can verify the GBB contains only the official root key.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define RYU_ROOT_KEY_HASH_MAGIC "RtKyHash"
|
||||||
|
#define RYU_ROOT_KEY_HASH_MAGIC_INVCASE "rTkYhASH"
|
||||||
|
#define RYU_ROOT_KEY_HASH_MAGIC_SIZE 8
|
||||||
|
|
||||||
|
#define RYU_ROOT_KEY_HASH_VERSION_MAJOR 1
|
||||||
|
#define RYU_ROOT_KEY_HASH_VERSION_MINOR 0
|
||||||
|
|
||||||
|
struct vb2_ryu_root_key_hash {
|
||||||
|
/* Magic number (RYU_ROOT_KEY_HASH_MAGIC) */
|
||||||
|
uint8_t magic[RYU_ROOT_KEY_HASH_MAGIC_SIZE];
|
||||||
|
|
||||||
|
/* Version of this struct */
|
||||||
|
uint16_t header_version_major;
|
||||||
|
uint16_t header_version_minor;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Length of this struct, in bytes, including any variable length data
|
||||||
|
* which follows (there is none, yet).
|
||||||
|
*/
|
||||||
|
uint32_t struct_size;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SHA-256 hash digest of the entire root key section from the GBB. If
|
||||||
|
* all 0 bytes, all root keys will be treated as if matching.
|
||||||
|
*/
|
||||||
|
uint8_t root_key_hash_digest[32];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define EXPECTED_VB2_RYU_ROOT_KEY_HASH_SIZE 48
|
||||||
|
|
||||||
|
#endif /* VBOOT_REFERENCE_VBOOT_2STRUCT_H_ */
|
||||||
27
firmware/coreboot/3rdparty/vboot/firmware/2lib/include/2sysincludes.h
vendored
Normal file
27
firmware/coreboot/3rdparty/vboot/firmware/2lib/include/2sysincludes.h
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
/* Copyright (c) 2014 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* System includes for vboot reference library. With few exceptions, this is
|
||||||
|
* the ONLY place in firmware/ where system headers may be included via
|
||||||
|
* #include <...>, so that there's only one place that needs to be fixed up for
|
||||||
|
* platforms which don't have all the system includes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef VBOOT_REFERENCE_2_SYSINCLUDES_H_
|
||||||
|
#define VBOOT_REFERENCE_2_SYSINCLUDES_H_
|
||||||
|
|
||||||
|
#include <inttypes.h> /* For PRIu64 */
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#if defined(HAVE_ENDIAN_H) && defined(HAVE_LITTLE_ENDIAN)
|
||||||
|
#include <byteswap.h>
|
||||||
|
#include <memory.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* VBOOT_REFERENCE_2_SYSINCLUDES_H_ */
|
||||||
21
firmware/coreboot/3rdparty/vboot/firmware/2lib/include/2tpm_bootmode.h
vendored
Normal file
21
firmware/coreboot/3rdparty/vboot/firmware/2lib/include/2tpm_bootmode.h
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
/* Copyright 2015 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.
|
||||||
|
*
|
||||||
|
* Functions for updating the TPM state with the status of boot path.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef VBOOT_REFERENCE_2TPM_BOOTMODE_H_
|
||||||
|
#define VBOOT_REFERENCE_2TPM_BOOTMODE_H_
|
||||||
|
|
||||||
|
#include "2api.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return digest indicating the boot state
|
||||||
|
*
|
||||||
|
* @param ctx Vboot context
|
||||||
|
* @return Pointer to sha1 digest of size VB2_SHA1_DIGEST_SIZE
|
||||||
|
*/
|
||||||
|
const uint8_t *vb2_get_boot_state_digest(struct vb2_context *ctx);
|
||||||
|
|
||||||
|
#endif /* VBOOT_REFERENCE_2TPM_BOOTMODE_H_ */
|
||||||
47
firmware/coreboot/3rdparty/vboot/firmware/README
vendored
Normal file
47
firmware/coreboot/3rdparty/vboot/firmware/README
vendored
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
|
||||||
|
Here's what's what in the firmware/ directory.
|
||||||
|
|
||||||
|
bdb/
|
||||||
|
|
||||||
|
Code for managing Boot Descriptor Blocks (BDB).
|
||||||
|
|
||||||
|
include/
|
||||||
|
lib/
|
||||||
|
|
||||||
|
These are the original structures and APIs used in the earliest
|
||||||
|
Chromebooks and continuing through 2014. It never had a version as such to
|
||||||
|
begin with, but we now refer to this implementation as "vboot1" or
|
||||||
|
"vboot version 1.0".
|
||||||
|
|
||||||
|
linktest/
|
||||||
|
stub/
|
||||||
|
|
||||||
|
These are stubs used to link the vboot1 libraries into host-side test
|
||||||
|
executables so we can run some tests on the build machine instead of a
|
||||||
|
Chromebook.
|
||||||
|
|
||||||
|
2lib/
|
||||||
|
|
||||||
|
In 2014 we began work on a new vboot API. The first step was just a
|
||||||
|
refactoring and renaming of the verification API. The public functions and
|
||||||
|
external headers that are exported for use by the Chrome OS firmware (or
|
||||||
|
anything else that wants to use vboot) live in here. The internal
|
||||||
|
structures and implementations go elsewhere.
|
||||||
|
|
||||||
|
lib20/
|
||||||
|
|
||||||
|
This is an early implementation of the public (2lib/) API. It is
|
||||||
|
binary-compatible with vboot1, so although the interface details are
|
||||||
|
different, any existing on-device structures or signatures created by the
|
||||||
|
vboot1 tools can be validated using this implementation.
|
||||||
|
|
||||||
|
This was deployed slightly before it was ready. That's not a problem,
|
||||||
|
thanks to the binary compatibility, but this directory will be abandoned
|
||||||
|
Real Soon Now, except for the product support branches.
|
||||||
|
|
||||||
|
lib21/
|
||||||
|
|
||||||
|
This is where the current development of the second-generation vboot API
|
||||||
|
is taking place. It uses the public (2lib/) API, but will NOT be binary
|
||||||
|
compatible with vboot1 structs. Because of the early release of the lib20
|
||||||
|
stuff, we're actually calling this lib21.
|
||||||
27
firmware/coreboot/3rdparty/vboot/firmware/bdb/LICENSE
vendored
Normal file
27
firmware/coreboot/3rdparty/vboot/firmware/bdb/LICENSE
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
30
firmware/coreboot/3rdparty/vboot/firmware/bdb/README
vendored
Normal file
30
firmware/coreboot/3rdparty/vboot/firmware/bdb/README
vendored
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
Boot Descriptor Block (BDB) library and utilities
|
||||||
|
|
||||||
|
Building:
|
||||||
|
---------
|
||||||
|
The host-side library and utilities requires OpenSSL.
|
||||||
|
|
||||||
|
Do 'make runtests' to ensure everything is working.
|
||||||
|
|
||||||
|
Generating a BDB:
|
||||||
|
-----------------
|
||||||
|
Edit the options in bdb_create.c. Then 'make bdb'.
|
||||||
|
|
||||||
|
In the next release, this will take a config file rather than
|
||||||
|
requiring recompilation each time. Also, the BDB header and data will
|
||||||
|
be signed in two separate steps, so that the private BDB key is not
|
||||||
|
required each time.
|
||||||
|
|
||||||
|
Revision History:
|
||||||
|
-----------------
|
||||||
|
v0.1.2 24-Nov-2015 Add support for RSA-3072B keys and signatures.
|
||||||
|
Add dump_rsa utility and 'make testkeys' to create
|
||||||
|
new keys.
|
||||||
|
Use a RSA-3072B (exponent 3) key for the subkey so
|
||||||
|
the exponent 3 code gets tested.
|
||||||
|
|
||||||
|
v0.1.1 17-Nov-2015 Add support for ECDSA-521 data types. Note that
|
||||||
|
only the data types are supported; there is not a
|
||||||
|
C implementation for ECDSA.
|
||||||
|
|
||||||
|
v0.1.0 15-Sep-2015 Initial version.
|
||||||
450
firmware/coreboot/3rdparty/vboot/firmware/bdb/bdb.c
vendored
Normal file
450
firmware/coreboot/3rdparty/vboot/firmware/bdb/bdb.c
vendored
Normal file
@@ -0,0 +1,450 @@
|
|||||||
|
/* Copyright 2015 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.
|
||||||
|
*
|
||||||
|
* Boot descriptor block firmware functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "2sysincludes.h"
|
||||||
|
#include "2common.h"
|
||||||
|
#include "2sha.h"
|
||||||
|
#include "bdb.h"
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if string contains a null terminator.
|
||||||
|
*
|
||||||
|
* Bytes after the null terminator do not need to be null.
|
||||||
|
*
|
||||||
|
* @param s String to check
|
||||||
|
* @param size Size of string buffer in characters
|
||||||
|
* @return 1 if string has a null terminator, 0 if not
|
||||||
|
*/
|
||||||
|
int string_has_null(const char *s, size_t size)
|
||||||
|
{
|
||||||
|
for (; size; size--) {
|
||||||
|
if (*s++ == 0)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bdb_check_header(const struct bdb_header *p, size_t size)
|
||||||
|
{
|
||||||
|
if (size < sizeof(*p) || size < p->struct_size)
|
||||||
|
return BDB_ERROR_BUF_SIZE;
|
||||||
|
|
||||||
|
if (p->struct_magic != BDB_HEADER_MAGIC)
|
||||||
|
return BDB_ERROR_STRUCT_MAGIC;
|
||||||
|
|
||||||
|
if (p->struct_major_version != BDB_HEADER_VERSION_MAJOR)
|
||||||
|
return BDB_ERROR_STRUCT_VERSION;
|
||||||
|
|
||||||
|
/* Note that minor version doesn't matter yet */
|
||||||
|
|
||||||
|
if (p->struct_size < sizeof(*p))
|
||||||
|
return BDB_ERROR_STRUCT_SIZE;
|
||||||
|
|
||||||
|
if (p->oem_area_0_size & 3)
|
||||||
|
return BDB_ERROR_OEM_AREA_SIZE; /* Not 32-bit aligned */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure the BDB is at least big enough for us. At this point, all
|
||||||
|
* the caller may have loaded is this header We'll check if there's
|
||||||
|
* space for everything else after we load it.
|
||||||
|
*/
|
||||||
|
if (p->bdb_size < sizeof(*p))
|
||||||
|
return BDB_ERROR_BDB_SIZE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The rest of the fields don't matter yet; we'll check them when we
|
||||||
|
* check the BDB itself.
|
||||||
|
*/
|
||||||
|
return BDB_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bdb_check_key(const struct bdb_key *p, size_t size)
|
||||||
|
{
|
||||||
|
size_t expect_key_size = 0;
|
||||||
|
|
||||||
|
if (size < sizeof(*p) || size < p->struct_size)
|
||||||
|
return BDB_ERROR_BUF_SIZE;
|
||||||
|
|
||||||
|
if (p->struct_magic != BDB_KEY_MAGIC)
|
||||||
|
return BDB_ERROR_STRUCT_MAGIC;
|
||||||
|
|
||||||
|
if (p->struct_major_version != BDB_KEY_VERSION_MAJOR)
|
||||||
|
return BDB_ERROR_STRUCT_VERSION;
|
||||||
|
|
||||||
|
/* Note that minor version doesn't matter yet */
|
||||||
|
|
||||||
|
if (!string_has_null(p->description, sizeof(p->description)))
|
||||||
|
return BDB_ERROR_DESCRIPTION;
|
||||||
|
|
||||||
|
/* We currently only support SHA-256 */
|
||||||
|
if (p->hash_alg != BDB_HASH_ALG_SHA256)
|
||||||
|
return BDB_ERROR_HASH_ALG;
|
||||||
|
|
||||||
|
/* Make sure signature algorithm and size are correct */
|
||||||
|
switch (p->sig_alg) {
|
||||||
|
case BDB_SIG_ALG_RSA4096:
|
||||||
|
expect_key_size = BDB_RSA4096_KEY_DATA_SIZE;
|
||||||
|
break;
|
||||||
|
case BDB_SIG_ALG_ECSDSA521:
|
||||||
|
expect_key_size = BDB_ECDSA521_KEY_DATA_SIZE;
|
||||||
|
break;
|
||||||
|
case BDB_SIG_ALG_RSA3072B:
|
||||||
|
expect_key_size = BDB_RSA3072B_KEY_DATA_SIZE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return BDB_ERROR_SIG_ALG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p->struct_size < sizeof(*p) + expect_key_size)
|
||||||
|
return BDB_ERROR_STRUCT_SIZE;
|
||||||
|
|
||||||
|
return BDB_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bdb_check_sig(const struct bdb_sig *p, size_t size)
|
||||||
|
{
|
||||||
|
size_t expect_sig_size = 0;
|
||||||
|
|
||||||
|
if (size < sizeof(*p) || size < p->struct_size)
|
||||||
|
return BDB_ERROR_BUF_SIZE;
|
||||||
|
|
||||||
|
if (p->struct_magic != BDB_SIG_MAGIC)
|
||||||
|
return BDB_ERROR_STRUCT_MAGIC;
|
||||||
|
|
||||||
|
if (p->struct_major_version != BDB_SIG_VERSION_MAJOR)
|
||||||
|
return BDB_ERROR_STRUCT_VERSION;
|
||||||
|
|
||||||
|
/* Note that minor version doesn't matter yet */
|
||||||
|
|
||||||
|
if (!string_has_null(p->description, sizeof(p->description)))
|
||||||
|
return BDB_ERROR_DESCRIPTION;
|
||||||
|
|
||||||
|
/* We currently only support SHA-256 */
|
||||||
|
if (p->hash_alg != BDB_HASH_ALG_SHA256)
|
||||||
|
return BDB_ERROR_HASH_ALG;
|
||||||
|
|
||||||
|
/* Make sure signature algorithm and size are correct */
|
||||||
|
switch (p->sig_alg) {
|
||||||
|
case BDB_SIG_ALG_RSA4096:
|
||||||
|
expect_sig_size = BDB_RSA4096_SIG_SIZE;
|
||||||
|
break;
|
||||||
|
case BDB_SIG_ALG_ECSDSA521:
|
||||||
|
expect_sig_size = BDB_ECDSA521_SIG_SIZE;
|
||||||
|
break;
|
||||||
|
case BDB_SIG_ALG_RSA3072B:
|
||||||
|
expect_sig_size = BDB_RSA3072B_SIG_SIZE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return BDB_ERROR_SIG_ALG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p->struct_size < sizeof(*p) + expect_sig_size)
|
||||||
|
return BDB_ERROR_STRUCT_SIZE;
|
||||||
|
|
||||||
|
return BDB_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bdb_check_data(const struct bdb_data *p, size_t size)
|
||||||
|
{
|
||||||
|
size_t need_size;
|
||||||
|
|
||||||
|
if (size < sizeof(*p) || size < p->signed_size)
|
||||||
|
return BDB_ERROR_BUF_SIZE;
|
||||||
|
|
||||||
|
if (p->struct_magic != BDB_DATA_MAGIC)
|
||||||
|
return BDB_ERROR_STRUCT_MAGIC;
|
||||||
|
|
||||||
|
if (p->struct_major_version != BDB_DATA_VERSION_MAJOR)
|
||||||
|
return BDB_ERROR_STRUCT_VERSION;
|
||||||
|
|
||||||
|
/* Note that minor version doesn't matter yet */
|
||||||
|
|
||||||
|
if (!string_has_null(p->description, sizeof(p->description)))
|
||||||
|
return BDB_ERROR_DESCRIPTION;
|
||||||
|
|
||||||
|
if (p->struct_size < sizeof(*p))
|
||||||
|
return BDB_ERROR_STRUCT_SIZE;
|
||||||
|
|
||||||
|
if (p->hash_entry_size < sizeof(struct bdb_hash))
|
||||||
|
return BDB_ERROR_HASH_ENTRY_SIZE;
|
||||||
|
|
||||||
|
/* Calculate expected size */
|
||||||
|
need_size = p->struct_size + p->num_hashes * p->hash_entry_size;
|
||||||
|
|
||||||
|
/* Make sure OEM area size doesn't cause wraparound */
|
||||||
|
if (need_size + p->oem_area_1_size < need_size)
|
||||||
|
return BDB_ERROR_OEM_AREA_SIZE;
|
||||||
|
if (p->oem_area_1_size & 3)
|
||||||
|
return BDB_ERROR_OEM_AREA_SIZE; /* Not 32-bit aligned */
|
||||||
|
need_size += p->oem_area_1_size;
|
||||||
|
|
||||||
|
if (p->signed_size < need_size)
|
||||||
|
return BDB_ERROR_SIGNED_SIZE;
|
||||||
|
|
||||||
|
return BDB_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
const struct bdb_header *bdb_get_header(const void *buf)
|
||||||
|
{
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t bdb_size_of(const void *buf)
|
||||||
|
{
|
||||||
|
return bdb_get_header(buf)->bdb_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct bdb_key *bdb_get_bdbkey(const void *buf)
|
||||||
|
{
|
||||||
|
const struct bdb_header *h = bdb_get_header(buf);
|
||||||
|
const uint8_t *b8 = buf;
|
||||||
|
|
||||||
|
/* BDB key follows header */
|
||||||
|
return (const struct bdb_key *)(b8 + h->struct_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
const void *bdb_get_oem_area_0(const void *buf)
|
||||||
|
{
|
||||||
|
const struct bdb_key *k = bdb_get_bdbkey(buf);
|
||||||
|
const uint8_t *b8 = (const uint8_t *)k;
|
||||||
|
|
||||||
|
/* OEM area 0 follows BDB key */
|
||||||
|
return b8 + k->struct_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct bdb_key *bdb_get_datakey(const void *buf)
|
||||||
|
{
|
||||||
|
const struct bdb_header *h = bdb_get_header(buf);
|
||||||
|
const uint8_t *b8 = bdb_get_oem_area_0(buf);
|
||||||
|
|
||||||
|
/* datakey follows OEM area 0 */
|
||||||
|
return (const struct bdb_key *)(b8 + h->oem_area_0_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
ptrdiff_t bdb_offset_of_datakey(const void *buf)
|
||||||
|
{
|
||||||
|
return vb2_offset_of(buf, bdb_get_datakey(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct bdb_sig *bdb_get_header_sig(const void *buf)
|
||||||
|
{
|
||||||
|
const struct bdb_header *h = bdb_get_header(buf);
|
||||||
|
const uint8_t *b8 = bdb_get_oem_area_0(buf);
|
||||||
|
|
||||||
|
/* Header signature starts after signed data */
|
||||||
|
return (const struct bdb_sig *)(b8 + h->signed_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
ptrdiff_t bdb_offset_of_header_sig(const void *buf)
|
||||||
|
{
|
||||||
|
return vb2_offset_of(buf, bdb_get_header_sig(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct bdb_data *bdb_get_data(const void *buf)
|
||||||
|
{
|
||||||
|
const struct bdb_sig *s = bdb_get_header_sig(buf);
|
||||||
|
const uint8_t *b8 = (const uint8_t *)s;
|
||||||
|
|
||||||
|
/* Data follows header signature */
|
||||||
|
return (const struct bdb_data *)(b8 + s->struct_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
ptrdiff_t bdb_offset_of_data(const void *buf)
|
||||||
|
{
|
||||||
|
return vb2_offset_of(buf, bdb_get_data(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
const void *bdb_get_oem_area_1(const void *buf)
|
||||||
|
{
|
||||||
|
const struct bdb_data *p = bdb_get_data(buf);
|
||||||
|
const uint8_t *b8 = (const uint8_t *)p;
|
||||||
|
|
||||||
|
/* OEM area 1 follows BDB data */
|
||||||
|
return b8 + p->struct_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const void *bdb_get_hash(const void *buf)
|
||||||
|
{
|
||||||
|
const struct bdb_data *data = bdb_get_data(buf);
|
||||||
|
const uint8_t *b8 = bdb_get_oem_area_1(buf);
|
||||||
|
|
||||||
|
/* Hashes follow OEM area 0 */
|
||||||
|
return b8 + data->oem_area_1_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct bdb_hash *bdb_get_hash_by_type(const void *buf,
|
||||||
|
enum bdb_data_type type)
|
||||||
|
{
|
||||||
|
const struct bdb_data *data = bdb_get_data(buf);
|
||||||
|
const uint8_t *b8 = bdb_get_hash(buf);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Search for a matching hash */
|
||||||
|
for (i = 0; i < data->num_hashes; i++, b8 += data->hash_entry_size) {
|
||||||
|
const struct bdb_hash *h = (const struct bdb_hash *)b8;
|
||||||
|
|
||||||
|
if (h->type == type)
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct bdb_hash *bdb_get_hash_by_index(const void *buf, int index)
|
||||||
|
{
|
||||||
|
const struct bdb_data *data = bdb_get_data(buf);
|
||||||
|
const uint8_t *p = bdb_get_hash(buf);
|
||||||
|
const struct bdb_hash *h = NULL;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Search for a matching hash */
|
||||||
|
for (i = 0; i < data->num_hashes; i++, p += data->hash_entry_size) {
|
||||||
|
if (i == index) {
|
||||||
|
h = (const struct bdb_hash *)p;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct bdb_sig *bdb_get_data_sig(const void *buf)
|
||||||
|
{
|
||||||
|
const struct bdb_data *data = bdb_get_data(buf);
|
||||||
|
const uint8_t *b8 = (const uint8_t *)data;
|
||||||
|
|
||||||
|
/* Data signature starts after signed data */
|
||||||
|
return (const struct bdb_sig *)(b8 + data->signed_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
int bdb_verify_sig(const struct bdb_key *key,
|
||||||
|
const struct bdb_sig *sig,
|
||||||
|
const uint8_t *digest)
|
||||||
|
{
|
||||||
|
/* Key and signature algorithms must match */
|
||||||
|
if (key->sig_alg != sig->sig_alg)
|
||||||
|
return BDB_ERROR_SIG_ALG;
|
||||||
|
|
||||||
|
switch (key->sig_alg) {
|
||||||
|
case BDB_SIG_ALG_RSA4096:
|
||||||
|
if (bdb_rsa4096_verify(key->key_data, sig->sig_data, digest))
|
||||||
|
return BDB_ERROR_VERIFY_SIG;
|
||||||
|
break;
|
||||||
|
case BDB_SIG_ALG_ECSDSA521:
|
||||||
|
if (bdb_ecdsa521_verify(key->key_data, sig->sig_data, digest))
|
||||||
|
return BDB_ERROR_VERIFY_SIG;
|
||||||
|
break;
|
||||||
|
case BDB_SIG_ALG_RSA3072B:
|
||||||
|
if (bdb_rsa3072b_verify(key->key_data, sig->sig_data, digest))
|
||||||
|
return BDB_ERROR_VERIFY_SIG;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return BDB_ERROR_VERIFY_SIG;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BDB_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bdb_verify(const void *buf, size_t size, const uint8_t *bdb_key_digest)
|
||||||
|
{
|
||||||
|
const uint8_t *end = (const uint8_t *)buf + size;
|
||||||
|
const struct bdb_header *h;
|
||||||
|
const struct bdb_key *bdbkey, *datakey;
|
||||||
|
const struct bdb_sig *sig;
|
||||||
|
const struct bdb_data *data;
|
||||||
|
const void *oem;
|
||||||
|
uint8_t digest[BDB_SHA256_DIGEST_SIZE];
|
||||||
|
int bdb_digest_mismatch = -1;
|
||||||
|
|
||||||
|
/* Make sure buffer doesn't wrap around address space */
|
||||||
|
if (end < (const uint8_t *)buf)
|
||||||
|
return BDB_ERROR_BUF_SIZE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check header now that we've actually loaded it. We can't guarantee
|
||||||
|
* this is the same header which was checked before.
|
||||||
|
*/
|
||||||
|
h = bdb_get_header(buf);
|
||||||
|
if (bdb_check_header(h, size))
|
||||||
|
return BDB_ERROR_HEADER;
|
||||||
|
|
||||||
|
/* Sanity-check BDB key */
|
||||||
|
bdbkey = bdb_get_bdbkey(buf);
|
||||||
|
if (bdb_check_key(bdbkey, end - (const uint8_t *)bdbkey))
|
||||||
|
return BDB_ERROR_BDBKEY;
|
||||||
|
|
||||||
|
/* Calculate BDB key digest and compare with expected */
|
||||||
|
if (vb2_digest_buffer((uint8_t *)bdbkey, bdbkey->struct_size,
|
||||||
|
VB2_HASH_SHA256, digest, BDB_SHA256_DIGEST_SIZE))
|
||||||
|
return BDB_ERROR_DIGEST;
|
||||||
|
|
||||||
|
if (bdb_key_digest)
|
||||||
|
bdb_digest_mismatch = memcmp(digest,
|
||||||
|
bdb_key_digest, sizeof(digest));
|
||||||
|
|
||||||
|
/* Make sure OEM area 0 fits */
|
||||||
|
oem = bdb_get_oem_area_0(buf);
|
||||||
|
if (h->oem_area_0_size > end - (const uint8_t *)oem)
|
||||||
|
return BDB_ERROR_OEM_AREA_0;
|
||||||
|
|
||||||
|
/* Sanity-check datakey */
|
||||||
|
datakey = bdb_get_datakey(buf);
|
||||||
|
if (bdb_check_key(datakey, end - (const uint8_t *)datakey))
|
||||||
|
return BDB_ERROR_DATAKEY;
|
||||||
|
|
||||||
|
/* Make sure enough data was signed, and the signed data fits */
|
||||||
|
if (h->oem_area_0_size + datakey->struct_size > h->signed_size ||
|
||||||
|
h->signed_size > end - (const uint8_t *)oem)
|
||||||
|
return BDB_ERROR_BDB_SIGNED_SIZE;
|
||||||
|
|
||||||
|
/* Sanity-check header signature */
|
||||||
|
sig = bdb_get_header_sig(buf);
|
||||||
|
if (bdb_check_sig(sig, end - (const uint8_t *)sig))
|
||||||
|
return BDB_ERROR_HEADER_SIG;
|
||||||
|
|
||||||
|
/* Make sure it signed the right amount of data */
|
||||||
|
if (sig->signed_size != h->signed_size)
|
||||||
|
return BDB_ERROR_HEADER_SIG;
|
||||||
|
|
||||||
|
/* Calculate header digest and compare with expected signature */
|
||||||
|
if (vb2_digest_buffer((uint8_t *)oem, h->signed_size,
|
||||||
|
VB2_HASH_SHA256, digest, BDB_SHA256_DIGEST_SIZE))
|
||||||
|
return BDB_ERROR_DIGEST;
|
||||||
|
if (bdb_verify_sig(bdbkey, sig, digest))
|
||||||
|
return BDB_ERROR_HEADER_SIG;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sanity-check data struct. This also checks that OEM area 1 and the
|
||||||
|
* hashes fit in the remaining buffer.
|
||||||
|
*/
|
||||||
|
data = bdb_get_data(buf);
|
||||||
|
if (bdb_check_data(data, end - (const uint8_t *)data))
|
||||||
|
return BDB_ERROR_DATA;
|
||||||
|
|
||||||
|
/* Sanity-check data signature */
|
||||||
|
sig = bdb_get_data_sig(buf);
|
||||||
|
if (bdb_check_sig(sig, end - (const uint8_t *)sig))
|
||||||
|
return BDB_ERROR_DATA_CHECK_SIG;
|
||||||
|
if (sig->signed_size != data->signed_size)
|
||||||
|
return BDB_ERROR_DATA_SIGNED_SIZE;
|
||||||
|
|
||||||
|
/* Calculate data digest and compare with expected signature */
|
||||||
|
if (vb2_digest_buffer((uint8_t *)data, data->signed_size,
|
||||||
|
VB2_HASH_SHA256, digest, BDB_SHA256_DIGEST_SIZE))
|
||||||
|
return BDB_ERROR_DIGEST;
|
||||||
|
if (bdb_verify_sig(datakey, sig, digest))
|
||||||
|
return BDB_ERROR_DATA_SIG;
|
||||||
|
|
||||||
|
/* Return success or success-other-than-BDB-key-mismatch */
|
||||||
|
return bdb_digest_mismatch ? BDB_GOOD_OTHER_THAN_KEY : BDB_SUCCESS;
|
||||||
|
}
|
||||||
232
firmware/coreboot/3rdparty/vboot/firmware/bdb/bdb.h
vendored
Normal file
232
firmware/coreboot/3rdparty/vboot/firmware/bdb/bdb.h
vendored
Normal file
@@ -0,0 +1,232 @@
|
|||||||
|
/* Copyright 2015 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.
|
||||||
|
*
|
||||||
|
* Boot descriptor block firmware functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef VBOOT_REFERENCE_BDB_H_
|
||||||
|
#define VBOOT_REFERENCE_BDB_H_
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "bdb_struct.h"
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/*
|
||||||
|
Expected calling sequence:
|
||||||
|
|
||||||
|
Load and check just the header
|
||||||
|
bdb_check_header(buf, size);
|
||||||
|
|
||||||
|
Load and verify the entire BDB
|
||||||
|
bdb_verify(buf, size, bdb_key_hash, dev_mode_flag);
|
||||||
|
|
||||||
|
Check RW datakey version. If normal boot from primary BDB, roll forward
|
||||||
|
|
||||||
|
Check data version. If normal boot from primary BDB, roll forward
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Codes for functions returning numeric error codes */
|
||||||
|
|
||||||
|
enum bdb_return_code {
|
||||||
|
/* Success */
|
||||||
|
BDB_SUCCESS = 0,
|
||||||
|
|
||||||
|
/* BDB key did not match hash, but other than that the BDB was
|
||||||
|
* fully verified. */
|
||||||
|
BDB_GOOD_OTHER_THAN_KEY = 1,
|
||||||
|
|
||||||
|
/* Function is not implemented, thus supposed to be not called */
|
||||||
|
BDB_ERROR_NOT_IMPLEMENTED,
|
||||||
|
|
||||||
|
/* Other errors */
|
||||||
|
BDB_ERROR_UNKNOWN = 100,
|
||||||
|
|
||||||
|
/* Buffer size too small or wraps around */
|
||||||
|
BDB_ERROR_BUF_SIZE,
|
||||||
|
|
||||||
|
/* Bad fields in structures */
|
||||||
|
BDB_ERROR_STRUCT_MAGIC,
|
||||||
|
BDB_ERROR_STRUCT_VERSION,
|
||||||
|
BDB_ERROR_STRUCT_SIZE,
|
||||||
|
BDB_ERROR_SIGNED_SIZE,
|
||||||
|
BDB_ERROR_BDB_SIZE,
|
||||||
|
BDB_ERROR_OEM_AREA_SIZE,
|
||||||
|
BDB_ERROR_HASH_ENTRY_SIZE,
|
||||||
|
BDB_ERROR_HASH_ALG,
|
||||||
|
BDB_ERROR_SIG_ALG,
|
||||||
|
BDB_ERROR_DESCRIPTION,
|
||||||
|
|
||||||
|
/* Bad components of BDB in bdb_verify() */
|
||||||
|
BDB_ERROR_HEADER,
|
||||||
|
BDB_ERROR_BDBKEY,
|
||||||
|
BDB_ERROR_OEM_AREA_0,
|
||||||
|
BDB_ERROR_DATAKEY,
|
||||||
|
BDB_ERROR_BDB_SIGNED_SIZE,
|
||||||
|
BDB_ERROR_HEADER_SIG,
|
||||||
|
BDB_ERROR_DATA,
|
||||||
|
BDB_ERROR_DATA_SIG,
|
||||||
|
BDB_ERROR_DATA_CHECK_SIG,
|
||||||
|
BDB_ERROR_DATA_SIGNED_SIZE,
|
||||||
|
|
||||||
|
/* Other errors in bdb_verify() */
|
||||||
|
BDB_ERROR_DIGEST, /* Error calculating digest */
|
||||||
|
BDB_ERROR_VERIFY_SIG, /* Error verifying signature */
|
||||||
|
|
||||||
|
/* Errors in vba_bdb_init */
|
||||||
|
BDB_ERROR_TRY_OTHER_SLOT,
|
||||||
|
BDB_ERROR_RECOVERY_REQUEST,
|
||||||
|
|
||||||
|
BDB_ERROR_NVM_INIT,
|
||||||
|
BDB_ERROR_NVM_WRITE,
|
||||||
|
BDB_ERROR_NVM_RW_HMAC,
|
||||||
|
BDB_ERROR_NVM_RW_INVALID_HMAC,
|
||||||
|
BDB_ERROR_NVM_INVALID_PARAMETER,
|
||||||
|
BDB_ERROR_NVM_INVALID_SECRET,
|
||||||
|
BDB_ERROR_NVM_RW_MAGIC,
|
||||||
|
BDB_ERROR_NVM_STRUCT_SIZE,
|
||||||
|
BDB_ERROR_NVM_WRITE_VERIFY,
|
||||||
|
BDB_ERROR_NVM_STRUCT_VERSION,
|
||||||
|
BDB_ERROR_NVM_VBE_READ,
|
||||||
|
BDB_ERROR_NVM_RW_BUFFER_SMALL,
|
||||||
|
BDB_ERROR_DECRYPT_BUC,
|
||||||
|
BDB_ERROR_ENCRYPT_BUC,
|
||||||
|
BDB_ERROR_WRITE_BUC,
|
||||||
|
|
||||||
|
BDB_ERROR_SECRET_TYPE,
|
||||||
|
BDB_ERROR_SECRET_BUC,
|
||||||
|
BDB_ERROR_SECRET_BOOT_VERIFIED,
|
||||||
|
BDB_ERROR_SECRET_BOOT_PATH,
|
||||||
|
BDB_ERROR_SECRET_BDB,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Functions */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sanity-check BDB structures.
|
||||||
|
*
|
||||||
|
* This checks for known version numbers, magic numbers, algorithms, etc. and
|
||||||
|
* ensures the sizes are consistent with those parameters.
|
||||||
|
*
|
||||||
|
* @param p Pointer to structure to check
|
||||||
|
* @param size Size of structure buffer
|
||||||
|
* @return 0 if success, non-zero error code if error.
|
||||||
|
*/
|
||||||
|
int bdb_check_header(const struct bdb_header *p, size_t size);
|
||||||
|
int bdb_check_key(const struct bdb_key *p, size_t size);
|
||||||
|
int bdb_check_sig(const struct bdb_sig *p, size_t size);
|
||||||
|
int bdb_check_data(const struct bdb_data *p, size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify the entire BDB
|
||||||
|
*
|
||||||
|
* @param buf Data to hash
|
||||||
|
* @param size Size of data in bytes
|
||||||
|
* @param bdb_key_digest Pointer to expected digest for BDB key.
|
||||||
|
* Must be BDB_SHA256_DIGEST_SIZE bytes long.
|
||||||
|
* If it's NULL, digest match will be skipped
|
||||||
|
* (and it'll be treated as 'mismatch').
|
||||||
|
*
|
||||||
|
* @return 0 if success, non-zero error code if error. Note that error code
|
||||||
|
* BDB_GOOD_OTHER_THAN_KEY may still indicate an acceptable BDB if the Boot
|
||||||
|
* Verified fuse has not been set, or in developer mode.
|
||||||
|
*/
|
||||||
|
int bdb_verify(const void *buf, size_t size, const uint8_t *bdb_key_digest);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Functions to extract things from a verified BDB buffer.
|
||||||
|
*
|
||||||
|
* Do not call these externally until after bdb_verify()! These methods
|
||||||
|
* assume data structures have already been verified.
|
||||||
|
*
|
||||||
|
* @param buf Pointer to BDB buffer
|
||||||
|
* @param type Data type, for bdb_get_hash()
|
||||||
|
* @return A pointer to the requested data, or NULL if error / not present.
|
||||||
|
*/
|
||||||
|
const struct bdb_header *bdb_get_header(const void *buf);
|
||||||
|
const struct bdb_key *bdb_get_bdbkey(const void *buf);
|
||||||
|
const void *bdb_get_oem_area_0(const void *buf);
|
||||||
|
const struct bdb_key *bdb_get_datakey(const void *buf);
|
||||||
|
const struct bdb_sig *bdb_get_header_sig(const void *buf);
|
||||||
|
const struct bdb_data *bdb_get_data(const void *buf);
|
||||||
|
const void *bdb_get_oem_area_1(const void *buf);
|
||||||
|
const struct bdb_hash *bdb_get_hash_by_type(const void *buf,
|
||||||
|
enum bdb_data_type type);
|
||||||
|
const struct bdb_hash *bdb_get_hash_by_index(const void *buf, int index);
|
||||||
|
const struct bdb_sig *bdb_get_data_sig(const void *buf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Functions to calculate size of BDB components
|
||||||
|
*
|
||||||
|
* @param buf Pointer to BDB buffer
|
||||||
|
* @return Size of the component
|
||||||
|
*/
|
||||||
|
uint32_t bdb_size_of(const void *buf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Functions to calculate offset of BDB components
|
||||||
|
*
|
||||||
|
* @param buf Pointer to BDB buffer
|
||||||
|
* @return Offset of the component
|
||||||
|
*/
|
||||||
|
ptrdiff_t bdb_offset_of_datakey(const void *buf);
|
||||||
|
ptrdiff_t bdb_offset_of_header_sig(const void *buf);
|
||||||
|
ptrdiff_t bdb_offset_of_data(const void *buf);
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Functions probably provided by the caller */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate a SHA-256 digest of a buffer.
|
||||||
|
*
|
||||||
|
* @param digest Pointer to the digest buffer. Must be
|
||||||
|
* BDB_SHA256_DIGEST_SIZE bytes long.
|
||||||
|
* @param buf Data to hash
|
||||||
|
* @param size Size of data in bytes
|
||||||
|
* @return 0 if success, non-zero error code if error.
|
||||||
|
*/
|
||||||
|
int bdb_sha256(void *digest, const void *buf, size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify a RSA-4096 signed digest
|
||||||
|
*
|
||||||
|
* @param key_data Key data to use (BDB_RSA4096_KEY_DATA_SIZE bytes)
|
||||||
|
* @param sig_data Signature to verify (BDB_RSA4096_SIG_SIZE bytes)
|
||||||
|
* @param digest Digest of signed data (BDB_SHA256_DIGEST bytes)
|
||||||
|
* @return 0 if success, non-zero error code if error.
|
||||||
|
*/
|
||||||
|
int bdb_rsa4096_verify(const uint8_t *key_data,
|
||||||
|
const uint8_t *sig,
|
||||||
|
const uint8_t *digest);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify a RSA-3072B signed digest
|
||||||
|
*
|
||||||
|
* @param key_data Key data to use (BDB_RSA3072B_KEY_DATA_SIZE bytes)
|
||||||
|
* @param sig_data Signature to verify (BDB_RSA3072B_SIG_SIZE bytes)
|
||||||
|
* @param digest Digest of signed data (BDB_SHA256_DIGEST bytes)
|
||||||
|
* @return 0 if success, non-zero error code if error.
|
||||||
|
*/
|
||||||
|
int bdb_rsa3072b_verify(const uint8_t *key_data,
|
||||||
|
const uint8_t *sig,
|
||||||
|
const uint8_t *digest);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify a ECDSA-521 signed digest
|
||||||
|
*
|
||||||
|
* @param key_data Key data to use (BDB_ECDSA521_KEY_DATA_SIZE bytes)
|
||||||
|
* @param sig_data Signature to verify (BDB_ECDSA521_SIG_SIZE bytes)
|
||||||
|
* @param digest Digest of signed data (BDB_SHA256_DIGEST bytes)
|
||||||
|
* @return 0 if success, non-zero error code if error.
|
||||||
|
*/
|
||||||
|
int bdb_ecdsa521_verify(const uint8_t *key_data,
|
||||||
|
const uint8_t *sig,
|
||||||
|
const uint8_t *digest);
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
#endif /* VBOOT_REFERENCE_BDB_H_ */
|
||||||
194
firmware/coreboot/3rdparty/vboot/firmware/bdb/bdb_api.h
vendored
Normal file
194
firmware/coreboot/3rdparty/vboot/firmware/bdb/bdb_api.h
vendored
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
/* Copyright 2016 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef VBOOT_REFERENCE_FIRMWARE_BDB_BDB_API_H
|
||||||
|
#define VBOOT_REFERENCE_FIRMWARE_BDB_BDB_API_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "vboot_register.h"
|
||||||
|
#include "nvm.h"
|
||||||
|
#include "secrets.h"
|
||||||
|
#include "bdb_flag.h"
|
||||||
|
|
||||||
|
struct vba_context {
|
||||||
|
/* Indicate which slot is being tried: 0 - primary, 1 - secondary */
|
||||||
|
uint8_t slot;
|
||||||
|
|
||||||
|
/* Defined by VBA_CONTEXT_FLAG_* in bdb_flag.h */
|
||||||
|
uint32_t flags;
|
||||||
|
|
||||||
|
/* BDB */
|
||||||
|
uint8_t *bdb;
|
||||||
|
|
||||||
|
/* Secrets */
|
||||||
|
struct bdb_secrets *secrets;
|
||||||
|
|
||||||
|
/* NVM-RW buffer */
|
||||||
|
struct nvmrw nvmrw;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize vboot process
|
||||||
|
*
|
||||||
|
* @param ctx
|
||||||
|
* @return enum bdb_return_code
|
||||||
|
*/
|
||||||
|
int vba_bdb_init(struct vba_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finalize vboot process
|
||||||
|
*
|
||||||
|
* @param ctx
|
||||||
|
* @return enum bdb_return_code
|
||||||
|
*/
|
||||||
|
int vba_bdb_finalize(struct vba_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log failed boot attempt and reset the chip
|
||||||
|
*
|
||||||
|
* @param ctx
|
||||||
|
*/
|
||||||
|
void vba_bdb_fail(struct vba_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update kernel and its data key version in NVM
|
||||||
|
*
|
||||||
|
* This is the function called from SP-RW, which receives a kernel version
|
||||||
|
* from an AP-RW after successful verification of a kernel.
|
||||||
|
*
|
||||||
|
* It checks whether the version in NVM-RW is older than the reported version
|
||||||
|
* or not. If so, it updates the version in NVM-RW.
|
||||||
|
*
|
||||||
|
* @param ctx
|
||||||
|
* @param kernel_data_key_version
|
||||||
|
* @param kernel_version
|
||||||
|
* @return BDB_SUCCESS or BDB_ERROR_*
|
||||||
|
*/
|
||||||
|
int vba_update_kernel_version(struct vba_context *ctx,
|
||||||
|
uint32_t kernel_data_key_version,
|
||||||
|
uint32_t kernel_version);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write new boot unlock code to NVM-RW
|
||||||
|
*
|
||||||
|
* @param ctx
|
||||||
|
* @param new_buc New BUC to be written
|
||||||
|
* @return BDB_SUCCESS or BDB_ERROR_*
|
||||||
|
*/
|
||||||
|
int vba_update_buc(struct vba_context *ctx, uint8_t *new_buc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Derive a secret
|
||||||
|
*
|
||||||
|
* This derives a new secret from a secret passed from SP-RO.
|
||||||
|
*
|
||||||
|
* @param ctx
|
||||||
|
* @param type Type of secret to derive
|
||||||
|
* @param buf Buffer containing data to derive secret from
|
||||||
|
* @param buf_size Size of <buf>
|
||||||
|
* @return BDB_SUCCESS or BDB_ERROR_*
|
||||||
|
*/
|
||||||
|
int vba_derive_secret(struct vba_context *ctx, enum bdb_secret_type type,
|
||||||
|
uint8_t *wsr, const uint8_t *buf, uint32_t buf_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear a secret
|
||||||
|
*
|
||||||
|
* @param ctx
|
||||||
|
* @param type Type of secret to clear
|
||||||
|
* @return BDB_SUCCESS or BDB_ERROR_*
|
||||||
|
*/
|
||||||
|
int vba_clear_secret(struct vba_context *ctx, enum bdb_secret_type type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extend secrets for SP-RO
|
||||||
|
*
|
||||||
|
* @param ctx struct vba_context
|
||||||
|
* @param bdb BDB
|
||||||
|
* @param wsr Pointer to working secret register contents
|
||||||
|
* @param extend Function to be called for extending a secret
|
||||||
|
* @return BDB_SUCCESS or BDB_ERROR_*
|
||||||
|
*/
|
||||||
|
typedef void (*f_extend)(const uint8_t *from, const uint8_t *by, uint8_t *to);
|
||||||
|
int vba_extend_secrets_ro(struct vba_context *ctx, const uint8_t *bdb,
|
||||||
|
uint8_t *wsr, f_extend extend);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get vboot register value
|
||||||
|
*
|
||||||
|
* Implemented by each chip
|
||||||
|
*
|
||||||
|
* @param type Type of register to get
|
||||||
|
* @return Register value
|
||||||
|
*/
|
||||||
|
uint32_t vbe_get_vboot_register(enum vboot_register type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set vboot register value
|
||||||
|
*
|
||||||
|
* Implemented by each chip
|
||||||
|
*
|
||||||
|
* @param type Type of register to set
|
||||||
|
* @param val Value to set
|
||||||
|
*/
|
||||||
|
void vbe_set_vboot_register(enum vboot_register type, uint32_t val);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the SoC
|
||||||
|
*
|
||||||
|
* Implemented by each chip. This is different from reboot (a.k.a. board reset,
|
||||||
|
* cold reset).
|
||||||
|
*/
|
||||||
|
void vbe_reset(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read contents from Non-Volatile Memory
|
||||||
|
*
|
||||||
|
* Implemented by each chip.
|
||||||
|
*
|
||||||
|
* @param type Type of NVM
|
||||||
|
* @param buf Buffer where the data will be read to
|
||||||
|
* @param size Size of data to read
|
||||||
|
* @return Zero if success or non-zero otherwise
|
||||||
|
*/
|
||||||
|
int vbe_read_nvm(enum nvm_type type, uint8_t *buf, uint32_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write contents to Non-Volatile Memory
|
||||||
|
*
|
||||||
|
* Implemented by each chip.
|
||||||
|
*
|
||||||
|
* @param type Type of NVM
|
||||||
|
* @param buf Buffer where the data will be written from
|
||||||
|
* @param size Size of data to write
|
||||||
|
* @return Zero if success or non-zero otherwise
|
||||||
|
*/
|
||||||
|
int vbe_write_nvm(enum nvm_type type, void *buf, uint32_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encrypt data by AES-256
|
||||||
|
*
|
||||||
|
* @param msg Message to be encrypted
|
||||||
|
* @param len Length of <msg> in bytes
|
||||||
|
* @param key Key used for encryption
|
||||||
|
* @param out Buffer where encrypted message is stored
|
||||||
|
* @return BDB_SUCCESS or BDB_ERROR_*
|
||||||
|
*/
|
||||||
|
int vbe_aes256_encrypt(const uint8_t *msg, uint32_t len, const uint8_t *key,
|
||||||
|
uint8_t *out);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decrypt data by AES-256
|
||||||
|
*
|
||||||
|
* @param msg Message to be decrypted
|
||||||
|
* @param len Length of <msg> in bytes
|
||||||
|
* @param key Key used for decryption
|
||||||
|
* @param out Buffer where decrypted message is stored
|
||||||
|
* @return BDB_SUCCESS or BDB_ERROR_*
|
||||||
|
*/
|
||||||
|
int vbe_aes256_decrypt(const uint8_t *msg, uint32_t len, const uint8_t *key,
|
||||||
|
uint8_t *out);
|
||||||
|
|
||||||
|
#endif
|
||||||
15
firmware/coreboot/3rdparty/vboot/firmware/bdb/bdb_flag.h
vendored
Normal file
15
firmware/coreboot/3rdparty/vboot/firmware/bdb/bdb_flag.h
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
/* Copyright 2016 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef VBOOT_REFERENCE_FIRMWARE_BDB_BDB_FLAG_H
|
||||||
|
#define VBOOT_REFERENCE_FIRMWARE_BDB_BDB_FLAG_H
|
||||||
|
|
||||||
|
/* Indicate whether BDB key is verified */
|
||||||
|
#define VBA_CONTEXT_FLAG_BDB_KEY_EFUSED (1 << 0)
|
||||||
|
|
||||||
|
/* Indicate whether kernel data key is verified */
|
||||||
|
#define VBA_CONTEXT_FLAG_KERNEL_DATA_KEY_VERIFIED (1 << 1)
|
||||||
|
|
||||||
|
#endif
|
||||||
268
firmware/coreboot/3rdparty/vboot/firmware/bdb/bdb_struct.h
vendored
Normal file
268
firmware/coreboot/3rdparty/vboot/firmware/bdb/bdb_struct.h
vendored
Normal file
@@ -0,0 +1,268 @@
|
|||||||
|
/* Copyright (c) 2015 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.
|
||||||
|
*
|
||||||
|
* Boot descriptor block structures
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef VBOOT_REFERENCE_BDB_STRUCT_H_
|
||||||
|
#define VBOOT_REFERENCE_BDB_STRUCT_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/* Size of SHA256 digest in bytes */
|
||||||
|
#define BDB_SHA256_DIGEST_SIZE 32
|
||||||
|
|
||||||
|
/* Size of RSA4096 key data in bytes */
|
||||||
|
#define BDB_RSA4096_KEY_DATA_SIZE 1032
|
||||||
|
|
||||||
|
/* Size of RSA4096 signature in bytes */
|
||||||
|
#define BDB_RSA4096_SIG_SIZE 512
|
||||||
|
|
||||||
|
/* Size of ECDSA521 key data in bytes = ceil(521/8) * 2 */
|
||||||
|
#define BDB_ECDSA521_KEY_DATA_SIZE 132
|
||||||
|
|
||||||
|
/* Size of ECDSA521 signature in bytes = ceil(521/8) * 2 */
|
||||||
|
#define BDB_ECDSA521_SIG_SIZE 132
|
||||||
|
|
||||||
|
/* Size of RSA3072B key data in bytes */
|
||||||
|
#define BDB_RSA3072B_KEY_DATA_SIZE 776
|
||||||
|
|
||||||
|
/* Size of RSA3072B signature in bytes */
|
||||||
|
#define BDB_RSA3072B_SIG_SIZE 384
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Header for BDB */
|
||||||
|
|
||||||
|
/* Magic number for bdb_header.struct_magic */
|
||||||
|
#define BDB_HEADER_MAGIC 0x30426442
|
||||||
|
|
||||||
|
/* Current version of bdb_header struct */
|
||||||
|
#define BDB_HEADER_VERSION_MAJOR 1
|
||||||
|
#define BDB_HEADER_VERSION_MINOR 0
|
||||||
|
|
||||||
|
/* Expected size of bdb_header struct in bytes */
|
||||||
|
#define BDB_HEADER_EXPECTED_SIZE 32
|
||||||
|
|
||||||
|
struct bdb_header {
|
||||||
|
/* Magic number to identify struct = BDB_HEADER_MAGIC. */
|
||||||
|
uint32_t struct_magic;
|
||||||
|
|
||||||
|
/* Structure version = BDB_HEADER_VERSION{MAJOR,MINOR} */
|
||||||
|
uint8_t struct_major_version;
|
||||||
|
uint8_t struct_minor_version;
|
||||||
|
|
||||||
|
/* Size of structure in bytes */
|
||||||
|
uint16_t struct_size;
|
||||||
|
|
||||||
|
/* Recommended address in SP SRAM to load BDB. Set to -1 to use
|
||||||
|
* default address. */
|
||||||
|
uint64_t bdb_load_address;
|
||||||
|
|
||||||
|
/* Size of the entire BDB in bytes */
|
||||||
|
uint32_t bdb_size;
|
||||||
|
|
||||||
|
/* Number of bytes following the BDB key which are signed by the BDB
|
||||||
|
* header signature. */
|
||||||
|
uint32_t signed_size;
|
||||||
|
|
||||||
|
/* Size of OEM area 0 in bytes, or 0 if not present */
|
||||||
|
uint32_t oem_area_0_size;
|
||||||
|
|
||||||
|
/* Reserved; set 0 */
|
||||||
|
uint8_t reserved0[8];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Public key structure for BDB */
|
||||||
|
|
||||||
|
/* Magic number for bdb_key.struct_magic */
|
||||||
|
#define BDB_KEY_MAGIC 0x73334256
|
||||||
|
|
||||||
|
/* Current version of bdb_key struct */
|
||||||
|
#define BDB_KEY_VERSION_MAJOR 1
|
||||||
|
#define BDB_KEY_VERSION_MINOR 0
|
||||||
|
|
||||||
|
/* Supported hash algorithms */
|
||||||
|
enum bdb_hash_alg {
|
||||||
|
BDB_HASH_ALG_INVALID = 0, /* Not used; invalid */
|
||||||
|
BDB_HASH_ALG_SHA256 = 2, /* SHA-256 */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Supported signature algorithms */
|
||||||
|
enum bdb_sig_alg {
|
||||||
|
BDB_SIG_ALG_INVALID = 0, /* Not used; invalid */
|
||||||
|
BDB_SIG_ALG_RSA4096 = 3, /* RSA-4096, exponent 65537 */
|
||||||
|
BDB_SIG_ALG_ECSDSA521 = 5, /* ECDSA-521 */
|
||||||
|
BDB_SIG_ALG_RSA3072B = 7, /* RSA_3072, exponent 3 */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Expected size of bdb_key struct in bytes, not counting variable-length key
|
||||||
|
* data at end.
|
||||||
|
*/
|
||||||
|
#define BDB_KEY_EXPECTED_SIZE 80
|
||||||
|
|
||||||
|
struct bdb_key {
|
||||||
|
/* Magic number to identify struct = BDB_KEY_MAGIC. */
|
||||||
|
uint32_t struct_magic;
|
||||||
|
|
||||||
|
/* Structure version = BDB_KEY_VERSION{MAJOR,MINOR} */
|
||||||
|
uint8_t struct_major_version;
|
||||||
|
uint8_t struct_minor_version;
|
||||||
|
|
||||||
|
/* Size of structure in bytes, including variable-length key data */
|
||||||
|
uint16_t struct_size;
|
||||||
|
|
||||||
|
/* Hash algorithm (enum bdb_hash_alg) */
|
||||||
|
uint8_t hash_alg;
|
||||||
|
|
||||||
|
/* Signature algorithm (enum bdb_sig_alg) */
|
||||||
|
uint8_t sig_alg;
|
||||||
|
|
||||||
|
/* Reserved; set 0 */
|
||||||
|
uint8_t reserved0[2];
|
||||||
|
|
||||||
|
/* Key version */
|
||||||
|
uint32_t key_version;
|
||||||
|
|
||||||
|
/* Description; null-terminated ASCII */
|
||||||
|
char description[128];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Key data. Variable-length; size is struct_size -
|
||||||
|
* offset_of(bdb_key, key_data).
|
||||||
|
*/
|
||||||
|
uint8_t key_data[0];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Signature structure for BDB */
|
||||||
|
|
||||||
|
/* Magic number for bdb_sig.struct_magic */
|
||||||
|
#define BDB_SIG_MAGIC 0x6b334256
|
||||||
|
|
||||||
|
/* Current version of bdb_sig struct */
|
||||||
|
#define BDB_SIG_VERSION_MAJOR 1
|
||||||
|
#define BDB_SIG_VERSION_MINOR 0
|
||||||
|
|
||||||
|
struct bdb_sig {
|
||||||
|
/* Magic number to identify struct = BDB_SIG_MAGIC. */
|
||||||
|
uint32_t struct_magic;
|
||||||
|
|
||||||
|
/* Structure version = BDB_SIG_VERSION{MAJOR,MINOR} */
|
||||||
|
uint8_t struct_major_version;
|
||||||
|
uint8_t struct_minor_version;
|
||||||
|
|
||||||
|
/* Size of structure in bytes, including variable-length signature
|
||||||
|
* data. */
|
||||||
|
uint16_t struct_size;
|
||||||
|
|
||||||
|
/* Hash algorithm used for this signature (enum bdb_hash_alg) */
|
||||||
|
uint8_t hash_alg;
|
||||||
|
|
||||||
|
/* Signature algorithm (enum bdb_sig_alg) */
|
||||||
|
uint8_t sig_alg;
|
||||||
|
|
||||||
|
/* Reserved; set 0 */
|
||||||
|
uint8_t reserved0[2];
|
||||||
|
|
||||||
|
/* Number of bytes of data signed by this signature */
|
||||||
|
uint32_t signed_size;
|
||||||
|
|
||||||
|
/* Description; null-terminated ASCII */
|
||||||
|
char description[128];
|
||||||
|
|
||||||
|
/* Signature data. Variable-length; size is struct_size -
|
||||||
|
* offset_of(bdb_sig, sig_data). */
|
||||||
|
uint8_t sig_data[0];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Data structure for BDB */
|
||||||
|
|
||||||
|
/* Magic number for bdb_data.struct_magic */
|
||||||
|
#define BDB_DATA_MAGIC 0x31426442
|
||||||
|
|
||||||
|
/* Current version of bdb_sig struct */
|
||||||
|
#define BDB_DATA_VERSION_MAJOR 1
|
||||||
|
#define BDB_DATA_VERSION_MINOR 0
|
||||||
|
|
||||||
|
struct bdb_data {
|
||||||
|
/* Magic number to identify struct = BDB_DATA_MAGIC. */
|
||||||
|
uint32_t struct_magic;
|
||||||
|
|
||||||
|
/* Structure version = BDB_DATA_VERSION{MAJOR,MINOR} */
|
||||||
|
uint8_t struct_major_version;
|
||||||
|
uint8_t struct_minor_version;
|
||||||
|
|
||||||
|
/* Size of structure in bytes, NOT including hashes which follow. */
|
||||||
|
uint16_t struct_size;
|
||||||
|
|
||||||
|
/* Version of data (RW firmware) contained */
|
||||||
|
uint32_t data_version;
|
||||||
|
|
||||||
|
/* Size of OEM area 1 in bytes, or 0 if not present */
|
||||||
|
uint32_t oem_area_1_size;
|
||||||
|
|
||||||
|
/* Number of hashes which follow */
|
||||||
|
uint8_t num_hashes;
|
||||||
|
|
||||||
|
/* Size of each hash entry in bytes */
|
||||||
|
uint8_t hash_entry_size;
|
||||||
|
|
||||||
|
/* Reserved; set 0 */
|
||||||
|
uint8_t reserved0[2];
|
||||||
|
|
||||||
|
/* Number of bytes of data signed by the datakey, including this
|
||||||
|
* header */
|
||||||
|
uint32_t signed_size;
|
||||||
|
|
||||||
|
/* Reserved; set 0 */
|
||||||
|
uint8_t reserved1[8];
|
||||||
|
|
||||||
|
/* Description; null-terminated ASCII */
|
||||||
|
char description[128];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
/* Type of data for bdb_hash.type */
|
||||||
|
enum bdb_data_type {
|
||||||
|
/* Types of data for boot descriptor blocks */
|
||||||
|
BDB_DATA_SP_RW = 1, /* SP-RW firmware */
|
||||||
|
BDB_DATA_AP_RW = 2, /* AP-RW firmware */
|
||||||
|
BDB_DATA_MCU = 3, /* MCU firmware */
|
||||||
|
|
||||||
|
/* Types of data for kernel descriptor blocks */
|
||||||
|
BDB_DATA_KERNEL = 128, /* Kernel */
|
||||||
|
BDB_DATA_CMD_LINE = 129, /* Command line */
|
||||||
|
BDB_DATA_HEADER16 = 130, /* 16-bit vmlinuz header */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Hash entries which follow the structure */
|
||||||
|
struct bdb_hash {
|
||||||
|
/* Offset of data from start of partition */
|
||||||
|
uint64_t offset;
|
||||||
|
|
||||||
|
/* Size of data in bytes */
|
||||||
|
uint32_t size;
|
||||||
|
|
||||||
|
/* Partition number containing data */
|
||||||
|
uint8_t partition;
|
||||||
|
|
||||||
|
/* Type of data; enum bdb_data_type */
|
||||||
|
uint8_t type;
|
||||||
|
|
||||||
|
/* Reserved; set 0 */
|
||||||
|
uint8_t reserved0[2];
|
||||||
|
|
||||||
|
/* Address in RAM to load data. -1 means use default. */
|
||||||
|
uint64_t load_address;
|
||||||
|
|
||||||
|
/* SHA-256 hash digest */
|
||||||
|
uint8_t digest[BDB_SHA256_DIGEST_SIZE];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
#endif /* VBOOT_REFERENCE_BDB_STRUCT_H_ */
|
||||||
|
|
||||||
200
firmware/coreboot/3rdparty/vboot/firmware/bdb/dump_rsa.c
vendored
Normal file
200
firmware/coreboot/3rdparty/vboot/firmware/bdb/dump_rsa.c
vendored
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
/* Copyright (c) 2010 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* C port of DumpPublicKey.java from the Android Open source project with
|
||||||
|
* support for additional RSA key sizes. (platform/system/core,git/libmincrypt
|
||||||
|
* /tools/DumpPublicKey.java). Uses the OpenSSL X509 and BIGNUM library.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <openssl/pem.h>
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Command line tool to extract RSA public keys from X.509 certificates and
|
||||||
|
* output a pre-processed version of keys for use by RSA verification routines.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int check(RSA *key)
|
||||||
|
{
|
||||||
|
int public_exponent = BN_get_word(key->e);
|
||||||
|
int modulus = BN_num_bits(key->n);
|
||||||
|
|
||||||
|
if (public_exponent != 65537 && public_exponent != 3) {
|
||||||
|
fprintf(stderr, "WARNING: Non-standard public exponent %d.\n",
|
||||||
|
public_exponent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modulus != 1024 && modulus != 2048 && modulus != 3072 &&
|
||||||
|
modulus != 4096 && modulus != 8192) {
|
||||||
|
fprintf(stderr, "WARNING: Non-standard modulus length = %d.\n",
|
||||||
|
modulus);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pre-processes and outputs RSA public key to standard output.
|
||||||
|
*/
|
||||||
|
void output(RSA *key)
|
||||||
|
{
|
||||||
|
BIGNUM *N;
|
||||||
|
BIGNUM *Big1 = NULL, *Big2 = NULL, *Big32 = NULL, *BigMinus1 = NULL;
|
||||||
|
BIGNUM *B = NULL;
|
||||||
|
BIGNUM *N0inv= NULL, *R = NULL, *RR = NULL, *RRTemp = NULL;
|
||||||
|
BIGNUM *NnumBits = NULL;
|
||||||
|
BIGNUM *n = NULL, *rr = NULL;
|
||||||
|
BN_CTX *bn_ctx = BN_CTX_new();
|
||||||
|
uint32_t n0invout;
|
||||||
|
int nwords, i;
|
||||||
|
|
||||||
|
N = key->n;
|
||||||
|
/* Output size of RSA key in 32-bit words */
|
||||||
|
nwords = BN_num_bits(N) / 32;
|
||||||
|
if (-1 == write(1, &nwords, sizeof(nwords)))
|
||||||
|
goto failure;
|
||||||
|
|
||||||
|
/* Initialize BIGNUMs */
|
||||||
|
Big1 = BN_new();
|
||||||
|
Big2 = BN_new();
|
||||||
|
Big32 = BN_new();
|
||||||
|
BigMinus1 = BN_new();
|
||||||
|
N0inv= BN_new();
|
||||||
|
R = BN_new();
|
||||||
|
RR = BN_new();
|
||||||
|
RRTemp = BN_new();
|
||||||
|
NnumBits = BN_new();
|
||||||
|
n = BN_new();
|
||||||
|
rr = BN_new();
|
||||||
|
|
||||||
|
BN_set_word(Big1, 1L);
|
||||||
|
BN_set_word(Big2, 2L);
|
||||||
|
BN_set_word(Big32, 32L);
|
||||||
|
BN_sub(BigMinus1, Big1, Big2);
|
||||||
|
|
||||||
|
B = BN_new();
|
||||||
|
BN_exp(B, Big2, Big32, bn_ctx); /* B = 2^32 */
|
||||||
|
|
||||||
|
/* Calculate and output N0inv = -1 / N[0] mod 2^32 */
|
||||||
|
BN_mod_inverse(N0inv, N, B, bn_ctx);
|
||||||
|
BN_sub(N0inv, B, N0inv);
|
||||||
|
n0invout = BN_get_word(N0inv);
|
||||||
|
if (-1 == write(1, &n0invout, sizeof(n0invout)))
|
||||||
|
goto failure;
|
||||||
|
|
||||||
|
/* Calculate R = 2^(# of key bits) */
|
||||||
|
BN_set_word(NnumBits, BN_num_bits(N));
|
||||||
|
BN_exp(R, Big2, NnumBits, bn_ctx);
|
||||||
|
|
||||||
|
/* Calculate RR = R^2 mod N */
|
||||||
|
BN_copy(RR, R);
|
||||||
|
BN_mul(RRTemp, RR, R, bn_ctx);
|
||||||
|
BN_mod(RR, RRTemp, N, bn_ctx);
|
||||||
|
|
||||||
|
/* Write out modulus as little endian array of integers. */
|
||||||
|
for (i = 0; i < nwords; ++i) {
|
||||||
|
uint32_t nout;
|
||||||
|
|
||||||
|
BN_mod(n, N, B, bn_ctx); /* n = N mod B */
|
||||||
|
nout = BN_get_word(n);
|
||||||
|
if (-1 == write(1, &nout, sizeof(nout)))
|
||||||
|
goto failure;
|
||||||
|
|
||||||
|
BN_rshift(N, N, 32); /* N = N/B */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write R^2 as little endian array of integers. */
|
||||||
|
for (i = 0; i < nwords; ++i) {
|
||||||
|
uint32_t rrout;
|
||||||
|
|
||||||
|
BN_mod(rr, RR, B, bn_ctx); /* rr = RR mod B */
|
||||||
|
rrout = BN_get_word(rr);
|
||||||
|
if (-1 == write(1, &rrout, sizeof(rrout)))
|
||||||
|
goto failure;
|
||||||
|
|
||||||
|
BN_rshift(RR, RR, 32); /* RR = RR/B */
|
||||||
|
}
|
||||||
|
|
||||||
|
failure:
|
||||||
|
/* Free BIGNUMs. */
|
||||||
|
BN_free(Big1);
|
||||||
|
BN_free(Big2);
|
||||||
|
BN_free(Big32);
|
||||||
|
BN_free(BigMinus1);
|
||||||
|
BN_free(N0inv);
|
||||||
|
BN_free(R);
|
||||||
|
BN_free(RRTemp);
|
||||||
|
BN_free(NnumBits);
|
||||||
|
BN_free(n);
|
||||||
|
BN_free(rr);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
int cert_mode = 0;
|
||||||
|
FILE* fp;
|
||||||
|
X509* cert = NULL;
|
||||||
|
RSA* pubkey = NULL;
|
||||||
|
EVP_PKEY* key;
|
||||||
|
char *progname;
|
||||||
|
|
||||||
|
if (argc != 3 ||
|
||||||
|
(strcmp(argv[1], "-cert") && strcmp(argv[1], "-pub"))) {
|
||||||
|
progname = strrchr(argv[0], '/');
|
||||||
|
if (progname)
|
||||||
|
progname++;
|
||||||
|
else
|
||||||
|
progname = argv[0];
|
||||||
|
fprintf(stderr, "Usage: %s <-cert | -pub> <file>\n", progname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(argv[1], "-cert"))
|
||||||
|
cert_mode = 1;
|
||||||
|
|
||||||
|
fp = fopen(argv[2], "r");
|
||||||
|
|
||||||
|
if (!fp) {
|
||||||
|
fprintf(stderr, "Couldn't open file %s!\n", argv[2]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cert_mode) {
|
||||||
|
/* Read the certificate */
|
||||||
|
if (!PEM_read_X509(fp, &cert, NULL, NULL)) {
|
||||||
|
fprintf(stderr, "Couldn't read certificate.\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the public key from the certificate. */
|
||||||
|
key = X509_get_pubkey(cert);
|
||||||
|
|
||||||
|
/* Convert to a RSA_style key. */
|
||||||
|
if (!(pubkey = EVP_PKEY_get1_RSA(key))) {
|
||||||
|
fprintf(stderr, "Couldn't convert to RSA style key.\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Read the pubkey in .PEM format. */
|
||||||
|
if (!(pubkey = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL))) {
|
||||||
|
fprintf(stderr, "Couldn't read public key file.\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check(pubkey)) {
|
||||||
|
output(pubkey);
|
||||||
|
}
|
||||||
|
|
||||||
|
fail:
|
||||||
|
X509_free(cert);
|
||||||
|
RSA_free(pubkey);
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
17
firmware/coreboot/3rdparty/vboot/firmware/bdb/ecdsa.c
vendored
Normal file
17
firmware/coreboot/3rdparty/vboot/firmware/bdb/ecdsa.c
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
/* Copyright (c) 2015 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.
|
||||||
|
*
|
||||||
|
* Boot descriptor block firmware ECDSA stub
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "bdb.h"
|
||||||
|
|
||||||
|
int bdb_ecdsa521_verify(const uint8_t *key_data,
|
||||||
|
const uint8_t *sig,
|
||||||
|
const uint8_t *digest)
|
||||||
|
{
|
||||||
|
/* This is just a stub */
|
||||||
|
return BDB_ERROR_DIGEST;
|
||||||
|
}
|
||||||
419
firmware/coreboot/3rdparty/vboot/firmware/bdb/host.c
vendored
Normal file
419
firmware/coreboot/3rdparty/vboot/firmware/bdb/host.c
vendored
Normal file
@@ -0,0 +1,419 @@
|
|||||||
|
/* Copyright 2015 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.
|
||||||
|
*
|
||||||
|
* Host functions for signing
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "2sysincludes.h"
|
||||||
|
#include "2common.h"
|
||||||
|
#include "2sha.h"
|
||||||
|
#include "bdb.h"
|
||||||
|
#include "host.h"
|
||||||
|
|
||||||
|
char *strzcpy(char *dest, const char *src, size_t size)
|
||||||
|
{
|
||||||
|
strncpy(dest, src, size);
|
||||||
|
dest[size - 1] = 0;
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *read_file(const char *filename, uint32_t *size_ptr)
|
||||||
|
{
|
||||||
|
FILE *f;
|
||||||
|
uint8_t *buf;
|
||||||
|
long size;
|
||||||
|
|
||||||
|
*size_ptr = 0;
|
||||||
|
|
||||||
|
f = fopen(filename, "rb");
|
||||||
|
if (!f) {
|
||||||
|
fprintf(stderr, "Unable to open file %s\n", filename);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(f, 0, SEEK_END);
|
||||||
|
size = ftell(f);
|
||||||
|
rewind(f);
|
||||||
|
|
||||||
|
if (size < 0 || size > UINT32_MAX) {
|
||||||
|
fclose(f);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf = malloc(size);
|
||||||
|
if (!buf) {
|
||||||
|
fclose(f);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (1 != fread(buf, size, 1, f)) {
|
||||||
|
fprintf(stderr, "Unable to read file %s\n", filename);
|
||||||
|
fclose(f);
|
||||||
|
free(buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
*size_ptr = size;
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
int write_file(const char *filename, const void *buf, uint32_t size)
|
||||||
|
{
|
||||||
|
FILE *f = fopen(filename, "wb");
|
||||||
|
|
||||||
|
if (!f) {
|
||||||
|
fprintf(stderr, "Unable to open file %s\n", filename);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (1 != fwrite(buf, size, 1, f)) {
|
||||||
|
fprintf(stderr, "Unable to write to file %s\n", filename);
|
||||||
|
fclose(f);
|
||||||
|
unlink(filename); /* Delete any partial file */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct rsa_st *read_pem(const char *filename)
|
||||||
|
{
|
||||||
|
struct rsa_st *pem;
|
||||||
|
FILE *f;
|
||||||
|
|
||||||
|
/* Read private key */
|
||||||
|
f = fopen(filename, "rb");
|
||||||
|
if (!f) {
|
||||||
|
fprintf(stderr, "%s: unable to read key from %s\n",
|
||||||
|
__func__, filename);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pem = PEM_read_RSAPrivateKey(f, NULL, NULL, NULL);
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
return pem;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct bdb_key *bdb_create_key(const char *filename,
|
||||||
|
uint32_t key_version,
|
||||||
|
const char *desc)
|
||||||
|
{
|
||||||
|
uint32_t sig_alg;
|
||||||
|
size_t key_size = sizeof(struct bdb_key);
|
||||||
|
struct bdb_key *k;
|
||||||
|
uint8_t *kdata;
|
||||||
|
uint32_t kdata_size = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read key data. Somewhat lame assumption that we can determine the
|
||||||
|
* signature algorithm from the key size, but it's true right now.
|
||||||
|
*/
|
||||||
|
kdata = read_file(filename, &kdata_size);
|
||||||
|
if (kdata_size == BDB_RSA4096_KEY_DATA_SIZE) {
|
||||||
|
sig_alg = BDB_SIG_ALG_RSA4096;
|
||||||
|
} else if (kdata_size == BDB_RSA3072B_KEY_DATA_SIZE) {
|
||||||
|
sig_alg = BDB_SIG_ALG_RSA3072B;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "%s: bad key size from %s\n",
|
||||||
|
__func__, filename);
|
||||||
|
free(kdata);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
key_size += kdata_size;
|
||||||
|
|
||||||
|
/* Allocate buffer */
|
||||||
|
k = (struct bdb_key *)calloc(key_size, 1);
|
||||||
|
if (!k) {
|
||||||
|
free(kdata);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
k->struct_magic = BDB_KEY_MAGIC;
|
||||||
|
k->struct_major_version = BDB_KEY_VERSION_MAJOR;
|
||||||
|
k->struct_minor_version = BDB_KEY_VERSION_MINOR;
|
||||||
|
k->struct_size = key_size;
|
||||||
|
k->hash_alg = BDB_HASH_ALG_SHA256;
|
||||||
|
k->sig_alg = sig_alg;
|
||||||
|
k->key_version = key_version;
|
||||||
|
|
||||||
|
/* Copy description, if any */
|
||||||
|
if (desc)
|
||||||
|
strzcpy(k->description, desc, sizeof(k->description));
|
||||||
|
|
||||||
|
/* Copy key data */
|
||||||
|
memcpy(k->key_data, kdata, kdata_size);
|
||||||
|
free(kdata);
|
||||||
|
|
||||||
|
return k;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct bdb_sig *bdb_create_sig(const void *data,
|
||||||
|
size_t size,
|
||||||
|
struct rsa_st *key,
|
||||||
|
uint32_t sig_alg,
|
||||||
|
const char *desc)
|
||||||
|
{
|
||||||
|
static const uint8_t info[] = {
|
||||||
|
0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
|
||||||
|
0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
|
||||||
|
0x00, 0x04, 0x20
|
||||||
|
};
|
||||||
|
|
||||||
|
size_t sig_size = sizeof(struct bdb_sig);
|
||||||
|
uint8_t digest[sizeof(info) + BDB_SHA256_DIGEST_SIZE];
|
||||||
|
struct bdb_sig *sig;
|
||||||
|
|
||||||
|
if (size >= UINT32_MAX)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
switch(sig_alg) {
|
||||||
|
case BDB_SIG_ALG_RSA4096:
|
||||||
|
sig_size += BDB_RSA4096_SIG_SIZE;
|
||||||
|
break;
|
||||||
|
case BDB_SIG_ALG_RSA3072B:
|
||||||
|
sig_size += BDB_RSA3072B_SIG_SIZE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "%s: bad signature algorithm %d\n",
|
||||||
|
__func__, sig_alg);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate buffer */
|
||||||
|
sig = (struct bdb_sig *)calloc(sig_size, 1);
|
||||||
|
if (!sig)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
sig->struct_magic = BDB_SIG_MAGIC;
|
||||||
|
sig->struct_major_version = BDB_SIG_VERSION_MAJOR;
|
||||||
|
sig->struct_minor_version = BDB_SIG_VERSION_MINOR;
|
||||||
|
sig->struct_size = sig_size;
|
||||||
|
sig->hash_alg = BDB_HASH_ALG_SHA256;
|
||||||
|
sig->sig_alg = sig_alg;
|
||||||
|
sig->signed_size = size;
|
||||||
|
|
||||||
|
/* Copy description, if any */
|
||||||
|
if (desc)
|
||||||
|
strzcpy(sig->description, desc, sizeof(sig->description));
|
||||||
|
|
||||||
|
/* Calculate info-padded digest */
|
||||||
|
memcpy(digest, info, sizeof(info));
|
||||||
|
if (vb2_digest_buffer((uint8_t *)data, size,
|
||||||
|
VB2_HASH_SHA256,
|
||||||
|
digest + sizeof(info), BDB_SHA256_DIGEST_SIZE)) {
|
||||||
|
free(sig);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* RSA-encrypt the signature */
|
||||||
|
if (RSA_private_encrypt(sizeof(digest),
|
||||||
|
digest,
|
||||||
|
sig->sig_data,
|
||||||
|
key,
|
||||||
|
RSA_PKCS1_PADDING) == -1) {
|
||||||
|
free(sig);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return sig;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bdb_sign_datakey(uint8_t **bdb, struct rsa_st *key)
|
||||||
|
{
|
||||||
|
const struct bdb_header *header = bdb_get_header(*bdb);
|
||||||
|
const struct bdb_key *bdbkey = bdb_get_bdbkey(*bdb);
|
||||||
|
const void *oem = bdb_get_oem_area_0(*bdb);
|
||||||
|
const struct bdb_sig *sig = bdb_get_header_sig(*bdb);
|
||||||
|
struct bdb_sig *new_sig;
|
||||||
|
uint8_t *new_bdb, *src, *dst;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
new_sig = bdb_create_sig(oem, header->signed_size,
|
||||||
|
key, bdbkey->sig_alg, NULL);
|
||||||
|
new_bdb = calloc(1, header->bdb_size
|
||||||
|
+ (new_sig->struct_size - sig->struct_size));
|
||||||
|
if (!new_bdb)
|
||||||
|
return BDB_ERROR_UNKNOWN;
|
||||||
|
|
||||||
|
/* copy up to sig */
|
||||||
|
src = *bdb;
|
||||||
|
dst = new_bdb;
|
||||||
|
len = bdb_offset_of_header_sig(*bdb);
|
||||||
|
memcpy(dst, src, len);
|
||||||
|
|
||||||
|
/* copy new sig */
|
||||||
|
src += len;
|
||||||
|
dst += len;
|
||||||
|
memcpy(dst, new_sig, new_sig->struct_size);
|
||||||
|
|
||||||
|
/* copy the rest */
|
||||||
|
src += sig->struct_size;
|
||||||
|
dst += new_sig->struct_size;
|
||||||
|
len = bdb_size_of(*bdb) - vb2_offset_of(*bdb, src);
|
||||||
|
memcpy(dst, src, len);
|
||||||
|
|
||||||
|
free(*bdb);
|
||||||
|
free(new_sig);
|
||||||
|
*bdb = new_bdb;
|
||||||
|
|
||||||
|
return BDB_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bdb_sign_data(uint8_t **bdb, struct rsa_st *key)
|
||||||
|
{
|
||||||
|
const struct bdb_key *datakey = bdb_get_datakey(*bdb);
|
||||||
|
const struct bdb_data *data = bdb_get_data(*bdb);
|
||||||
|
const uint64_t sig_offset = vb2_offset_of(*bdb, bdb_get_data_sig(*bdb));
|
||||||
|
struct bdb_sig *new_sig;
|
||||||
|
uint8_t *new_bdb;
|
||||||
|
|
||||||
|
new_sig = bdb_create_sig(data, data->signed_size,
|
||||||
|
key, datakey->sig_alg, NULL);
|
||||||
|
new_bdb = calloc(1, sig_offset + new_sig->struct_size);
|
||||||
|
if (!new_bdb)
|
||||||
|
return BDB_ERROR_UNKNOWN;
|
||||||
|
|
||||||
|
/* copy all data up to the data sig */
|
||||||
|
memcpy(new_bdb, *bdb, sig_offset);
|
||||||
|
|
||||||
|
/* copy the new signature */
|
||||||
|
memcpy(new_bdb + sig_offset, new_sig, new_sig->struct_size);
|
||||||
|
|
||||||
|
free(*bdb);
|
||||||
|
free(new_sig);
|
||||||
|
*bdb = new_bdb;
|
||||||
|
|
||||||
|
return BDB_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct bdb_header *bdb_create(struct bdb_create_params *p)
|
||||||
|
{
|
||||||
|
size_t bdb_size = 0;
|
||||||
|
size_t sig_size = sizeof(struct bdb_sig) + BDB_RSA4096_SIG_SIZE;
|
||||||
|
size_t hashes_size = sizeof(struct bdb_hash) * p->num_hashes;
|
||||||
|
uint8_t *buf, *bnext;
|
||||||
|
struct bdb_header *h;
|
||||||
|
struct bdb_sig *sig;
|
||||||
|
struct bdb_data *data;
|
||||||
|
const void *oem;
|
||||||
|
|
||||||
|
/* We can do some checks before we even allocate the buffer */
|
||||||
|
|
||||||
|
/* Make sure OEM sizes are aligned */
|
||||||
|
if ((p->oem_area_0_size & 3) || (p->oem_area_1_size & 3)) {
|
||||||
|
fprintf(stderr, "%s: OEM areas not 32-bit aligned\n",
|
||||||
|
__func__);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hash count must fit in uint8_t */
|
||||||
|
if (p->num_hashes > 255) {
|
||||||
|
fprintf(stderr, "%s: too many hashes\n", __func__);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculate BDB size */
|
||||||
|
bdb_size = sizeof(struct bdb_header);
|
||||||
|
bdb_size += p->bdbkey->struct_size;
|
||||||
|
bdb_size += p->oem_area_0_size;
|
||||||
|
bdb_size += p->datakey->struct_size;
|
||||||
|
bdb_size += sig_size;
|
||||||
|
bdb_size += sizeof(struct bdb_data);
|
||||||
|
bdb_size += p->oem_area_1_size;
|
||||||
|
bdb_size += sizeof(struct bdb_hash) * p->num_hashes;
|
||||||
|
bdb_size += sig_size;
|
||||||
|
|
||||||
|
/* Make sure it fits */
|
||||||
|
if (bdb_size > UINT32_MAX) {
|
||||||
|
fprintf(stderr, "%s: BDB size > UINT32_MAX\n", __func__);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate a buffer */
|
||||||
|
bnext = buf = calloc(bdb_size, 1);
|
||||||
|
if (!buf) {
|
||||||
|
fprintf(stderr, "%s: can't allocate buffer\n", __func__);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fill in the header */
|
||||||
|
h = (struct bdb_header *)bnext;
|
||||||
|
h->struct_magic = BDB_HEADER_MAGIC;
|
||||||
|
h->struct_major_version = BDB_HEADER_VERSION_MAJOR;
|
||||||
|
h->struct_minor_version = BDB_HEADER_VERSION_MINOR;
|
||||||
|
h->struct_size = sizeof(*h);
|
||||||
|
h->bdb_load_address = p->bdb_load_address;
|
||||||
|
h->bdb_size = bdb_size;
|
||||||
|
h->signed_size = p->oem_area_0_size + p->datakey->struct_size;
|
||||||
|
h->oem_area_0_size = p->oem_area_0_size;
|
||||||
|
bnext += h->struct_size;
|
||||||
|
|
||||||
|
/* Copy BDB key */
|
||||||
|
memcpy(bnext, p->bdbkey, p->bdbkey->struct_size);
|
||||||
|
bnext += p->bdbkey->struct_size;
|
||||||
|
|
||||||
|
/* Copy OEM area 0 */
|
||||||
|
oem = bnext;
|
||||||
|
if (p->oem_area_0_size) {
|
||||||
|
memcpy(bnext, p->oem_area_0, p->oem_area_0_size);
|
||||||
|
bnext += p->oem_area_0_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy datakey */
|
||||||
|
memcpy(bnext, p->datakey, p->datakey->struct_size);
|
||||||
|
bnext += p->datakey->struct_size;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create header signature using private BDB key.
|
||||||
|
*
|
||||||
|
* TODO: create the header signature in a totally separate step. That
|
||||||
|
* way, the private BDB key is not required each time a BDB is created.
|
||||||
|
*/
|
||||||
|
sig = bdb_create_sig(oem, h->signed_size, p->private_bdbkey,
|
||||||
|
p->bdbkey->sig_alg, p->header_sig_description);
|
||||||
|
memcpy(bnext, sig, sig->struct_size);
|
||||||
|
bnext += sig->struct_size;
|
||||||
|
|
||||||
|
/* Fill in the data */
|
||||||
|
data = (struct bdb_data *)bnext;
|
||||||
|
data->struct_magic = BDB_DATA_MAGIC;
|
||||||
|
data->struct_major_version = BDB_DATA_VERSION_MAJOR;
|
||||||
|
data->struct_minor_version = BDB_DATA_VERSION_MINOR;
|
||||||
|
data->struct_size = sizeof(struct bdb_data);
|
||||||
|
data->data_version = p->data_version;
|
||||||
|
data->oem_area_1_size = p->oem_area_1_size;
|
||||||
|
data->num_hashes = p->num_hashes;
|
||||||
|
data->hash_entry_size = sizeof(struct bdb_hash);
|
||||||
|
data->signed_size = data->struct_size + data->oem_area_1_size +
|
||||||
|
hashes_size;
|
||||||
|
if (p->data_description) {
|
||||||
|
strzcpy(data->description, p->data_description,
|
||||||
|
sizeof(data->description));
|
||||||
|
}
|
||||||
|
bnext += data->struct_size;
|
||||||
|
|
||||||
|
/* Copy OEM area 1 */
|
||||||
|
oem = bnext;
|
||||||
|
if (p->oem_area_1_size) {
|
||||||
|
memcpy(bnext, p->oem_area_1, p->oem_area_1_size);
|
||||||
|
bnext += p->oem_area_1_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy hashes */
|
||||||
|
memcpy(bnext, p->hash, hashes_size);
|
||||||
|
bnext += hashes_size;
|
||||||
|
|
||||||
|
/* Create data signature using private datakey */
|
||||||
|
sig = bdb_create_sig(data, data->signed_size, p->private_datakey,
|
||||||
|
p->datakey->sig_alg, p->data_sig_description);
|
||||||
|
memcpy(bnext, sig, sig->struct_size);
|
||||||
|
|
||||||
|
/* Return the BDB */
|
||||||
|
return h;
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user