mirror of
				https://github.com/Telecominfraproject/OpenCellular.git
				synced 2025-10-31 10:28:01 +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
	 David Hendricks
					David Hendricks