diff options
31 files changed, 1 insertions, 5113 deletions
diff --git a/Android.mk b/Android.mk deleted file mode 100644 index 6d10718..0000000 --- a/Android.mk +++ /dev/null @@ -1,101 +0,0 @@ -# -# Copyright (C) 2016 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -LOCAL_PATH := $(my-dir) - -bvb_common_cflags := \ - -D_FILE_OFFSET_BITS=64 \ - -D_POSIX_C_SOURCE=199309L \ - -Wa,--noexecstack \ - -Werror \ - -Wall \ - -Wextra \ - -Wformat=2 \ - -Wno-psabi \ - -Wno-unused-parameter \ - -ffunction-sections \ - -fstack-protector-strong \ - -fvisibility=hidden -bvb_common_cppflags := \ - -Wnon-virtual-dtor \ - -fno-strict-aliasing -bvb_common_ldflags := \ - -Wl,--gc-sections - -include $(CLEAR_VARS) -LOCAL_SRC_FILES := bvbtool -LOCAL_MODULE_CLASS := EXECUTABLES -LOCAL_IS_HOST_MODULE := true -LOCAL_MODULE := bvbtool -include $(BUILD_PREBUILT) - -include $(CLEAR_VARS) -LOCAL_MODULE := libbvb_refimpl -LOCAL_MODULE_HOST_OS := linux -LOCAL_MODULE_CLASS := STATIC_LIBRARIES -LOCAL_CLANG := true -LOCAL_CFLAGS := $(bvb_common_cflags) -fno-stack-protector -DBVB_ENABLE_DEBUG -DBVB_REFIMPL_COMPILATION -LOCAL_LDFLAGS := $(bvb_common_ldflags) -LOCAL_C_INCLUDES := -LOCAL_SRC_FILES := \ - refimpl/bvb_property.c \ - refimpl/bvb_rsa.c \ - refimpl/bvb_sha256.c \ - refimpl/bvb_sha512.c \ - refimpl/bvb_util.c \ - refimpl/bvb_verify.c -include $(BUILD_HOST_STATIC_LIBRARY) - -include $(CLEAR_VARS) -LOCAL_MODULE := libbvb_refimpl_sysdeps -LOCAL_MODULE_HOST_OS := linux -LOCAL_MODULE_CLASS := STATIC_LIBRARIES -LOCAL_CLANG := true -LOCAL_CFLAGS := $(bvb_common_cflags) -DBVB_ENABLE_DEBUG -DBVB_REFIMPL_COMPILATION -LOCAL_LDFLAGS := $(bvb_common_ldflags) -LOCAL_C_INCLUDES := -LOCAL_SRC_FILES := \ - refimpl/bvb_sysdeps_stub.c -include $(BUILD_HOST_STATIC_LIBRARY) - -include $(CLEAR_VARS) -LOCAL_MODULE := libbvb_refimpl_unittest -LOCAL_MODULE_HOST_OS := linux -LOCAL_CPP_EXTENSION := .cc -LOCAL_CLANG := true -LOCAL_CFLAGS := $(bvb_common_cflags) -LOCAL_CPPFLAGS := $(bvb_common_cppflags) -LOCAL_LDFLAGS := $(bvb_common_ldflags) -LOCAL_C_INCLUDES := $(LOCAL_PATH)/refimpl external/gtest/include -LOCAL_STATIC_LIBRARIES := \ - libbvb_refimpl \ - libbvb_refimpl_sysdeps \ - libgmock_host \ - libgtest_host -LOCAL_SHARED_LIBRARIES := \ - libchrome -LOCAL_SRC_FILES := \ - bvb_util_unittest.cc \ - bvb_verify_unittest.cc \ - bvbtool_unittest.cc -LOCAL_LDLIBS_linux := -lrt -include $(BUILD_HOST_NATIVE_TEST) - -include $(CLEAR_VARS) -LOCAL_SRC_FILES := bvb_refimpl_symbols_test -LOCAL_MODULE_TAGS := debug -LOCAL_ADDITIONAL_DEPENDENCIES := libbvb_refimpl -include $(BUILD_HOST_PREBUILT) diff --git a/DEAD_REPO_MOVED_TO_external_bvb b/DEAD_REPO_MOVED_TO_external_bvb new file mode 100644 index 0000000..1e2637a --- /dev/null +++ b/DEAD_REPO_MOVED_TO_external_bvb @@ -0,0 +1 @@ +Code that used to be in this repository has been moved to external/bvb. @@ -1,139 +0,0 @@ -This directory contains the specification for the Brillo Verified Boot -boot image, a reference implementation for verified boot and A/B -selection to be used in boot loaders, and a tool for generating and -signing boot images. - --- FILES AND DIRECTORIES - - refimpl/ - - The reference implementation for boot image verification and A/B - selection is in the refimpl sub-directory. - - Part of this code is considered internal to the reference - implementation and should not be used outside it. This includes the - bvb_rsa.[ch] and bvb_sha.[ch] files. - - System dependencies expected to be provided by the platform is - defined in bvb_sysdeps.h. If the platform provides the standard C - runtime bvb_sysdeps_stub.c can be used. - - Android.mk - - Build instructions for building the reference implementation and - associated unit tests. - - bvb_util_unittest.cc, bvb_verify_unittest.cc, bvb_unittest_util.h - - Unit tests for the reference implementation. - - bvbtool_unittest.cc - - Unit tests for bvbtool. - - bvbtool - - A tool written in Python for working with Brillo boot images. - - test/ - - Contains test data used in unit tests. - --- AUDIENCE AND PORTABILITY NOTES - -This code is intended to be used in bootloaders in devices running -Brillo. The suggested approach is to copy the appropriate header and C -files mentioned in the previous section into the boot loader and -integrate as appropriate. - -The reference implementation will evolve over time so integration -should be as non-invasive as possible. The intention is to keep the -API of the reference implementation stable however it will be broken -if necessary. - -As for portability, the reference implementation is intended to be -highly portable, work on both little- and big-endian architectures and -32- and 64-bit. It's also intended to work in non-standard -environments without the standard C library and runtime. - -If the BVB_ENABLE_DEBUG preprocessor symbol is set, the code will -include useful debug information and run-time checks. Production -builds should not use this. - -The preprocessor symbol BVB_REFIMPL_COMPILATION should be set when -compiling the code. The code must be compiled into a separate library. - -Applications using the compiled library must only include the -refimpl/bvb_refimpl.h file (which will include all public interfaces) -and must not have the BVB_REFIMPL_COMPILATION preprocessor symbol -set. This is to ensure that internal code that may be change in the -future (for example refimpl/bvb_sha.[ch] and refimpl/bvb_rsa.[ch]) -will not be visible to application code. - --- COMPATIBILITY NOTES - -The Brillo Boot Image structure (as defined in refimpl/bvb_boot_image.h) -guarantees forwards- and backwards-compatibility provided the major -version does not change. - -When backwards-compatible changes are made - for example, when a new -field is added to BvbBootImageHeader - the minor version will be -bumped. At the same time, the reference implementation will also be -modified to test for the appropriate minor version before attempting -to access the newly added field. This ensures that version 1.N of the -reference implementation is able to read an old boot image header -produced with version 1.M where N > M. - -The usual scenario is that the code parsing the BvbBootImageHeader -rarely changes (it's usually in the firmware of a device and this -firmware is rarely updated if ever), let's say it's fixed at version -1.N. At the same time, the version of the bvbtool used to produce the -boot image is rolling forward and is at version 1.M where M > N. The -problem with this scenario is that version 1.M may easily and -inadvertently introduce a seemingly compatible change that isn't. For -example, consider if a new verification algorithm is added - in this -case version 1.N of the reference implementation will fail at -verification time when validating the |algorithm_field| of a 1.M image -if it's set to the new algorithm. - -The best approach for dealing with this problem is to always used a -pinned version of bvbtool (say, use version 1.N to generate images -targeted for devices running version 1.N) for generating and signing -images but sometimes this is not always possible nor -desirable. Therefore, to avoid this compatibility problem, bvbtool is -designed to always take such input as a command-line argument so it -can be kept constant by the caller. In other words, as long as you -keep your command-line options passed to the bvb tool the same, images -produced by newer versions of bvb will continue to work on the same -version of the reference implementation. - --- BUILD SYSTEM INTEGRATION NOTES - -Brillo Verified Boot is enabled by the BOARD_BVB_ENABLE variable - - BOARD_BVB_ENABLE := true - -By default, the algorithm SHA256_RSA4096 is used with a test key from -this directory. This can be overriden by the BOARD_BVB_ALGORITHM and -BOARD_BVB_KEY_PATH variables to use e.g. RSA-4096: - - BOARD_BVB_ALGORITHM := SHA512_RSA4096 - BOARD_BVB_KEY_PATH := /path/to/rsa_key_4096bits.pem - -Remember that the public part of this key needs to be embedded in the -bootloader of the device expected to process resulting images. Use -'bvbtool extract_public_key' to do this. - -To prevent rollback attakcs, the rollback index should be increased on -a regular basis. The rollback index can be set with the -BOARD_BVB_ROLLBACK_INDEX variable: - - BOARD_BVB_ROLLBACK_INDEX := 5 - -If this is not set, the rollback index defaults to 0. - -Additionally, the variables BOARD_BVB_MAKE_BOOT_IMAGE_ARGS, -BOARD_BVB_SIGN_BOOT_IMAGE_ARGS, and BOARD_BVB_ADD_IMAGE_HASHES_ARGS -can be used to specify additional options passed to respectively -'bvbtool make_boot_image', 'bvbtool sign_boot_image', and 'bvbtool -add_image_hashes'. diff --git a/bvb_refimpl_symbols_test b/bvb_refimpl_symbols_test deleted file mode 100755 index 6c29871..0000000 --- a/bvb_refimpl_symbols_test +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/bash - -# -# Copyright (C) 2016 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This shell-script checks the symbols in libbvb_refimpl.a and fails -# if a reference not starting with bvb_ is referenced. It's intended -# to catch mistakes where the standard C library is inadvertently -# used. - -set -e - -SYMBOLS_FILE=$(mktemp /tmp/libbvb_refimpl_symbols.XXXXXXXXXX) - -trap "rm -f '${SYMBOLS_FILE}'" EXIT - -readelf --symbols --wide "${ANDROID_HOST_OUT}/obj/STATIC_LIBRARIES/libbvb_refimpl_intermediates/libbvb_refimpl.a" | \ - awk '$7 == "UND" && $8 != "" {print $8}' | \ - grep -v ^bvb_ | \ - sort -u > "${SYMBOLS_FILE}" - -# If this file is non-empty, it means that the library is using -# symbols not starting with "bvb_". -if [ -s "${SYMBOLS_FILE}" ] ; then - echo "ERROR: $0: Unexpected symbols in libbvb_refimpl:" >&2 - cat "${SYMBOLS_FILE}" >&2 - exit 1 -fi diff --git a/bvb_unittest_util.h b/bvb_unittest_util.h deleted file mode 100644 index 30951a9..0000000 --- a/bvb_unittest_util.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef BVB_UNITTEST_UTIL_H_ -#define BVB_UNITTEST_UTIL_H_ - -#include <inttypes.h> - -#include <gtest/gtest.h> - -#include <base/files/file_util.h> -#include <base/strings/string_util.h> -#include <base/strings/stringprintf.h> - -/* Utility macro to run the command expressed by the printf()-style string - * |command_format| using the system(3) utility function. Will assert unless - * the command exits normally with exit status |expected_exit_status|. - */ -#define EXPECT_COMMAND(expected_exit_status, command_format, ...) do { \ - int rc = system(base::StringPrintf(command_format, ## __VA_ARGS__).c_str()); \ - EXPECT_TRUE(WIFEXITED(rc)); \ - EXPECT_EQ(WEXITSTATUS(rc), expected_exit_status); \ -} while (0); - -/* Base-class used for unit test. */ -class BaseBvbToolTest : public ::testing::Test { -public: - BaseBvbToolTest() {} - -protected: - virtual ~BaseBvbToolTest() {} - - /* Generates a Brillo Boot Image, using bvbtoool. The generated boot - * image will written to disk, see the |boot_image_path| variable - * for its path and |boot_image_| for the content. - */ - void GenerateBootImage(const std::string& algorithm, - const std::string& kernel_cmdline, - uint64_t rollback_index, - const base::FilePath& key_path, - const std::string& additional_options = "") { - boot_image_path_ = testdir_.Append("boot_brillo.img"); - EXPECT_COMMAND(0, - "./bvbtool make_boot_image" - " --kernel %s" - " --initrd %s" - " --kernel_cmdline \"%s\"" - " --rollback_index %" PRIu64 - " %s " - " --output %s", - base::FilePath("test/dummy_kernel.bin").value().c_str(), - base::FilePath("test/dummy_initrd.bin").value().c_str(), - kernel_cmdline.c_str(), - rollback_index, - additional_options.c_str(), - boot_image_path_.value().c_str()); - if (algorithm != "") { - EXPECT_COMMAND(0, - "./bvbtool sign_boot_image --key %s" - " --image %s --algorithm %s", - key_path.value().c_str(), - boot_image_path_.value().c_str(), - algorithm.c_str()); - } - int64_t file_size; - ASSERT_TRUE(base::GetFileSize(boot_image_path_, &file_size)); - boot_image_.resize(file_size); - ASSERT_TRUE(base::ReadFile(boot_image_path_, - reinterpret_cast<char*>(boot_image_.data()), - boot_image_.size())); - } - - /* Create temporary directory to stash images in. */ - virtual void SetUp() override { - base::FilePath ret; - char* buf = strdup("/tmp/bvb-refimpl-tests.XXXXXX"); - ASSERT_TRUE(mkdtemp(buf) != nullptr); - testdir_ = base::FilePath(buf); - free(buf); - } - - /* Nuke temporary directory. */ - virtual void TearDown() override { - ASSERT_EQ(0U, testdir_.value().find("/tmp/bvb-refimpl-tests")); - ASSERT_TRUE(base::DeleteFile(testdir_, true /* recursive */)); - } - - /* Temporary directory created in SetUp(). */ - base::FilePath testdir_; - - /* Path to boot image generated with GenerateBootImage(). */ - base::FilePath boot_image_path_; - - /* Contents of the image generated with GenerateBootImage(). */ - std::vector<uint8_t> boot_image_; -}; - -#endif /* BVB_UNITTEST_UTIL_H_ */ diff --git a/bvb_util_unittest.cc b/bvb_util_unittest.cc deleted file mode 100644 index 4ef9955..0000000 --- a/bvb_util_unittest.cc +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <string.h> - -#include <gtest/gtest.h> - -#include "bvb_refimpl.h" - -TEST(UtilTest, BootImageHeaderByteswap) -{ - BvbBootImageHeader h; - BvbBootImageHeader s; - uint32_t n32; - uint64_t n64; - - n32 = 0x11223344; - n64 = 0x1122334455667788; - - h.header_version_major = htobe32(n32); n32++; - h.header_version_minor = htobe32(n32); n32++; - h.authentication_data_block_size = htobe64(n64); n64++; - h.auxilary_data_block_size = htobe64(n64); n64++; - h.payload_data_block_size = htobe64(n64); n64++; - h.algorithm_type = htobe32(n32); n32++; - h.hash_offset = htobe64(n64); n64++; - h.hash_size = htobe64(n64); n64++; - h.signature_offset = htobe64(n64); n64++; - h.signature_size = htobe64(n64); n64++; - h.public_key_offset = htobe64(n64); n64++; - h.public_key_size = htobe64(n64); n64++; - h.properties_offset = htobe64(n64); n64++; - h.properties_size = htobe64(n64); n64++; - h.rollback_index = htobe64(n64); n64++; - h.kernel_offset = htobe64(n64); n64++; - h.kernel_size = htobe64(n64); n64++; - h.initrd_offset = htobe64(n64); n64++; - h.initrd_size = htobe64(n64); n64++; - h.kernel_addr = htobe64(n64); n64++; - h.initrd_addr = htobe64(n64); n64++; - - bvb_boot_image_header_to_host_byte_order(&h, &s); - - n32 = 0x11223344; - n64 = 0x1122334455667788; - - EXPECT_EQ(n32, s.header_version_major); n32++; - EXPECT_EQ(n32, s.header_version_minor); n32++; - EXPECT_EQ(n64, s.authentication_data_block_size); n64++; - EXPECT_EQ(n64, s.auxilary_data_block_size); n64++; - EXPECT_EQ(n64, s.payload_data_block_size); n64++; - EXPECT_EQ(n32, s.algorithm_type); n32++; - EXPECT_EQ(n64, s.hash_offset); n64++; - EXPECT_EQ(n64, s.hash_size); n64++; - EXPECT_EQ(n64, s.signature_offset); n64++; - EXPECT_EQ(n64, s.signature_size); n64++; - EXPECT_EQ(n64, s.public_key_offset); n64++; - EXPECT_EQ(n64, s.public_key_size); n64++; - EXPECT_EQ(n64, s.properties_offset); n64++; - EXPECT_EQ(n64, s.properties_size); n64++; - EXPECT_EQ(n64, s.rollback_index); n64++; - EXPECT_EQ(n64, s.kernel_offset); n64++; - EXPECT_EQ(n64, s.kernel_size); n64++; - EXPECT_EQ(n64, s.initrd_offset); n64++; - EXPECT_EQ(n64, s.initrd_size); n64++; - EXPECT_EQ(n64, s.kernel_addr); n64++; - EXPECT_EQ(n64, s.initrd_addr); n64++; - - // If new fields are added, the following will fail. This is to - // remind that byteswapping code (in bvb_util.c) and unittests for - // this should be updated. - static_assert(offsetof(BvbBootImageHeader, reserved) == 4256, - "Remember to unittest byteswapping of newly added fields"); -} - -TEST(UtilTest, RSAPublicKeyHeaderByteswap) -{ - BvbRSAPublicKeyHeader h; - BvbRSAPublicKeyHeader s; - uint32_t n32; - uint64_t n64; - - n32 = 0x11223344; - n64 = 0x1122334455667788; - - h.key_num_bits = htobe32(n32); n32++; - h.n0inv = htobe32(n32); n32++; - - bvb_rsa_public_key_header_to_host_byte_order(&h, &s); - - n32 = 0x11223344; - n64 = 0x1122334455667788; - - EXPECT_EQ(n32, s.key_num_bits); n32++; - EXPECT_EQ(n32, s.n0inv); n32++; -} - -TEST(UtilTest, SafeAddition) { - uint64_t value; - uint64_t pow2_60 = 1ULL << 60; - - value = 2; - EXPECT_NE(0, bvb_safe_add_to(&value, 5)); - EXPECT_EQ(7UL, value); - - /* These should not overflow */ - value = 1*pow2_60; - EXPECT_NE(0, bvb_safe_add_to(&value, 2*pow2_60)); - EXPECT_EQ(3*pow2_60, value); - value = 7*pow2_60; - EXPECT_NE(0, bvb_safe_add_to(&value, 8*pow2_60)); - EXPECT_EQ(15*pow2_60, value); - value = 9*pow2_60; - EXPECT_NE(0, bvb_safe_add_to(&value, 3*pow2_60)); - EXPECT_EQ(12*pow2_60, value); - value = 0xfffffffffffffffcUL; - EXPECT_NE(0, bvb_safe_add_to(&value, 2)); - EXPECT_EQ(0xfffffffffffffffeUL, value); - - /* These should overflow. */ - value = 8*pow2_60; - EXPECT_EQ(0, bvb_safe_add_to(&value, 8*pow2_60)); - value = 0xfffffffffffffffcUL; - EXPECT_EQ(0, bvb_safe_add_to(&value, 4)); -} diff --git a/bvb_verify_unittest.cc b/bvb_verify_unittest.cc deleted file mode 100644 index fb71777..0000000 --- a/bvb_verify_unittest.cc +++ /dev/null @@ -1,467 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <iostream> - -#include <endian.h> -#include <inttypes.h> -#include <string.h> - -#include <base/files/file_util.h> -#include <base/strings/string_util.h> -#include <base/strings/stringprintf.h> - -#include "bvb_unittest_util.h" -#include "bvb_refimpl.h" - -class VerifyTest : public BaseBvbToolTest { -public: - VerifyTest() {} - -protected: - - // Helper function for ModificationDetection test. Modifies - // boot_image_ in a number of places in the sub-array at |offset| of - // size |length| and checks that bvb_verify_boot_image() returns - // |expected_result|. - bool test_modification(BvbVerifyResult expected_result, - size_t offset, size_t length); - -}; - -TEST_F(VerifyTest, BootImageStructSize) { - EXPECT_EQ(8192UL, sizeof(BvbBootImageHeader)); -} - -TEST_F(VerifyTest, CheckSHA256RSA2048) { - GenerateBootImage("SHA256_RSA2048", "", 0, - base::FilePath("test/testkey_rsa2048.pem")); - EXPECT_EQ(BVB_VERIFY_RESULT_OK, - bvb_verify_boot_image(boot_image_.data(), boot_image_.size(), - NULL, NULL)); -} - -TEST_F(VerifyTest, CheckSHA256RSA4096) { - GenerateBootImage("SHA256_RSA4096", "", 0 - , base::FilePath("test/testkey_rsa4096.pem")); - EXPECT_EQ(BVB_VERIFY_RESULT_OK, - bvb_verify_boot_image(boot_image_.data(), boot_image_.size(), - NULL, NULL)); -} - -TEST_F(VerifyTest, CheckSHA256RSA8192) { - GenerateBootImage("SHA256_RSA8192", "", 0, - base::FilePath("test/testkey_rsa8192.pem")); - EXPECT_EQ(BVB_VERIFY_RESULT_OK, - bvb_verify_boot_image(boot_image_.data(), boot_image_.size(), - NULL, NULL)); -} - -TEST_F(VerifyTest, CheckSHA512RSA2048) { - GenerateBootImage("SHA512_RSA2048", "", 0, - base::FilePath("test/testkey_rsa2048.pem")); - EXPECT_EQ(BVB_VERIFY_RESULT_OK, - bvb_verify_boot_image(boot_image_.data(), boot_image_.size(), - NULL, NULL)); -} - -TEST_F(VerifyTest, CheckSHA512RSA4096) { - GenerateBootImage("SHA512_RSA4096", "", 0, - base::FilePath("test/testkey_rsa4096.pem")); - EXPECT_EQ(BVB_VERIFY_RESULT_OK, - bvb_verify_boot_image(boot_image_.data(), boot_image_.size(), - NULL, NULL)); -} - -TEST_F(VerifyTest, CheckSHA512RSA8192) { - GenerateBootImage("SHA512_RSA8192", "", 0, - base::FilePath("test/testkey_rsa8192.pem")); - EXPECT_EQ(BVB_VERIFY_RESULT_OK, - bvb_verify_boot_image(boot_image_.data(), boot_image_.size(), - NULL, NULL)); -} - -TEST_F(VerifyTest, CheckBiggerLength) { - GenerateBootImage("SHA256_RSA2048", "", 0, - base::FilePath("test/testkey_rsa2048.pem")); - // Check that it's OK if we pass a bigger length than what the - // header indicates. - EXPECT_EQ(BVB_VERIFY_RESULT_OK, - bvb_verify_boot_image(boot_image_.data(), - boot_image_.size() + 8192, - NULL, NULL)); -} - -TEST_F(VerifyTest, CheckUnsigned) { - GenerateBootImage("", "", 0, base::FilePath("")); - EXPECT_EQ(BVB_VERIFY_RESULT_OK_NOT_SIGNED, - bvb_verify_boot_image(boot_image_.data(), boot_image_.size(), - NULL, NULL)); -} - -TEST_F(VerifyTest, BadMagic) { - GenerateBootImage("SHA256_RSA2048", "", 0, - base::FilePath("test/testkey_rsa2048.pem")); - boot_image_[0] = 'A'; - EXPECT_EQ(BVB_VERIFY_RESULT_INVALID_BOOT_IMAGE_HEADER, - bvb_verify_boot_image(boot_image_.data(), boot_image_.size(), - NULL, NULL)); -} - - -TEST_F(VerifyTest, MajorVersionCheck) { - GenerateBootImage("SHA256_RSA2048", "", 0, - base::FilePath("test/testkey_rsa2048.pem")); - - BvbBootImageHeader *h = - reinterpret_cast<BvbBootImageHeader*>(boot_image_.data()); - h->header_version_major = htobe32(1 + be32toh(h->header_version_major)); - EXPECT_EQ(BVB_VERIFY_RESULT_INVALID_BOOT_IMAGE_HEADER, - bvb_verify_boot_image(boot_image_.data(), boot_image_.size(), - NULL, NULL)); -} - - -TEST_F(VerifyTest, MinorVersionCheck) { - GenerateBootImage("", "", 0, base::FilePath("")); - - BvbBootImageHeader *h = - reinterpret_cast<BvbBootImageHeader*>(boot_image_.data()); - h->header_version_minor = htobe32(1 + be32toh(h->header_version_minor)); - EXPECT_EQ(BVB_VERIFY_RESULT_OK_NOT_SIGNED, - bvb_verify_boot_image(boot_image_.data(), boot_image_.size(), - NULL, NULL)); -} - -TEST_F(VerifyTest, BlockSizesAddUpToLessThanLength) { - GenerateBootImage("SHA256_RSA2048", "", 0, - base::FilePath("test/testkey_rsa2048.pem")); - - BvbBootImageHeader *h = - reinterpret_cast<BvbBootImageHeader*>(boot_image_.data()); - BvbBootImageHeader backup = *h; - - // Check that the sum of the three block lengths is less than passed - // in size. Use a size that's a multiple of 64 to avoid failure on - // earlier check. - uint64_t size = boot_image_.size() & (~0x3f); - - h->authentication_data_block_size = htobe64(size); - EXPECT_EQ(BVB_VERIFY_RESULT_INVALID_BOOT_IMAGE_HEADER, - bvb_verify_boot_image(boot_image_.data(), boot_image_.size(), - NULL, NULL)); - *h = backup; - - h->auxilary_data_block_size = htobe64(size); - EXPECT_EQ(BVB_VERIFY_RESULT_INVALID_BOOT_IMAGE_HEADER, - bvb_verify_boot_image(boot_image_.data(), boot_image_.size(), - NULL, NULL)); - *h = backup; - - h->payload_data_block_size = htobe64(size); - EXPECT_EQ(BVB_VERIFY_RESULT_INVALID_BOOT_IMAGE_HEADER, - bvb_verify_boot_image(boot_image_.data(), boot_image_.size(), - NULL, NULL)); - *h = backup; - - // Overflow checks - choose overflow candidate so it's a multiple of - // 64 otherwise we'll fail on an earlier check. - size = 0xffffffffffffffc0UL; - - h->authentication_data_block_size = htobe64(size); - EXPECT_EQ(BVB_VERIFY_RESULT_INVALID_BOOT_IMAGE_HEADER, - bvb_verify_boot_image(boot_image_.data(), boot_image_.size(), - NULL, NULL)); - *h = backup; - - h->auxilary_data_block_size = htobe64(size); - EXPECT_EQ(BVB_VERIFY_RESULT_INVALID_BOOT_IMAGE_HEADER, - bvb_verify_boot_image(boot_image_.data(), boot_image_.size(), - NULL, NULL)); - *h = backup; - - h->payload_data_block_size = htobe64(size); - EXPECT_EQ(BVB_VERIFY_RESULT_INVALID_BOOT_IMAGE_HEADER, - bvb_verify_boot_image(boot_image_.data(), boot_image_.size(), - NULL, NULL)); - *h = backup; - - EXPECT_EQ(BVB_VERIFY_RESULT_OK, - bvb_verify_boot_image(boot_image_.data(), boot_image_.size(), - NULL, NULL)); -} - -TEST_F(VerifyTest, BlockSizesMultipleOf64) { - GenerateBootImage("SHA256_RSA2048", "", 0, - base::FilePath("test/testkey_rsa2048.pem")); - - BvbBootImageHeader *h = - reinterpret_cast<BvbBootImageHeader*>(boot_image_.data()); - BvbBootImageHeader backup = *h; - - h->authentication_data_block_size = - htobe32(be32toh(h->authentication_data_block_size) - 32); - EXPECT_EQ(BVB_VERIFY_RESULT_INVALID_BOOT_IMAGE_HEADER, - bvb_verify_boot_image(boot_image_.data(), boot_image_.size() - 32, - NULL, NULL)); - *h = backup; - - h->auxilary_data_block_size = - htobe32(be32toh(h->auxilary_data_block_size) - 32); - EXPECT_EQ(BVB_VERIFY_RESULT_INVALID_BOOT_IMAGE_HEADER, - bvb_verify_boot_image(boot_image_.data(), boot_image_.size() - 32, - NULL, NULL)); - *h = backup; - - EXPECT_EQ(BVB_VERIFY_RESULT_OK, - bvb_verify_boot_image(boot_image_.data(), boot_image_.size(), - NULL, NULL)); -} - -TEST_F(VerifyTest, HashOutOfBounds) { - GenerateBootImage("SHA256_RSA2048", "", 0, - base::FilePath("test/testkey_rsa2048.pem")); - - BvbBootImageHeader *h = - reinterpret_cast<BvbBootImageHeader*>(boot_image_.data()); - - // Check we catch when hash data goes out of bounds. - h->hash_offset = htobe64(4); - h->hash_size = htobe64(be64toh(h->authentication_data_block_size)); - EXPECT_EQ(BVB_VERIFY_RESULT_INVALID_BOOT_IMAGE_HEADER, - bvb_verify_boot_image(boot_image_.data(), boot_image_.size(), - NULL, NULL)); - - // Overflow checks. - h->hash_offset = htobe64(4); - h->hash_size = htobe64(0xfffffffffffffffeUL); - EXPECT_EQ(BVB_VERIFY_RESULT_INVALID_BOOT_IMAGE_HEADER, - bvb_verify_boot_image(boot_image_.data(), boot_image_.size(), - NULL, NULL)); -} - -TEST_F(VerifyTest, SignatureOutOfBounds) { - GenerateBootImage("SHA256_RSA2048", "", 0, - base::FilePath("test/testkey_rsa2048.pem")); - - BvbBootImageHeader *h = - reinterpret_cast<BvbBootImageHeader*>(boot_image_.data()); - - // Check we catch when signature data goes out of bounds. - h->signature_offset = htobe64(4); - h->signature_size = htobe64(be64toh(h->authentication_data_block_size)); - EXPECT_EQ(BVB_VERIFY_RESULT_INVALID_BOOT_IMAGE_HEADER, - bvb_verify_boot_image(boot_image_.data(), boot_image_.size(), - NULL, NULL)); - - // Overflow checks. - h->signature_offset = htobe64(4); - h->signature_size = htobe64(0xfffffffffffffffeUL); - EXPECT_EQ(BVB_VERIFY_RESULT_INVALID_BOOT_IMAGE_HEADER, - bvb_verify_boot_image(boot_image_.data(), boot_image_.size(), - NULL, NULL)); -} - -TEST_F(VerifyTest, PublicKeyOutOfBounds) { - GenerateBootImage("SHA256_RSA2048", "", 0, - base::FilePath("test/testkey_rsa2048.pem")); - - BvbBootImageHeader *h = - reinterpret_cast<BvbBootImageHeader*>(boot_image_.data()); - - // Check we catch when public key data goes out of bounds. - h->public_key_offset = htobe64(4); - h->public_key_size = htobe64(be64toh(h->auxilary_data_block_size)); - EXPECT_EQ(BVB_VERIFY_RESULT_INVALID_BOOT_IMAGE_HEADER, - bvb_verify_boot_image(boot_image_.data(), boot_image_.size(), - NULL, NULL)); - - // Overflow checks. - h->public_key_offset = htobe64(4); - h->public_key_size = htobe64(0xfffffffffffffffeUL); - EXPECT_EQ(BVB_VERIFY_RESULT_INVALID_BOOT_IMAGE_HEADER, - bvb_verify_boot_image(boot_image_.data(), boot_image_.size(), - NULL, NULL)); -} - -TEST_F(VerifyTest, KernelOutOfBounds) { - GenerateBootImage("SHA256_RSA2048", "", 0, - base::FilePath("test/testkey_rsa2048.pem")); - - BvbBootImageHeader *h = - reinterpret_cast<BvbBootImageHeader*>(boot_image_.data()); - - // Check we catch when kernel data goes out of bounds. - h->kernel_offset = htobe64(4); - h->kernel_size = htobe64(be64toh(h->payload_data_block_size)); - EXPECT_EQ(BVB_VERIFY_RESULT_INVALID_BOOT_IMAGE_HEADER, - bvb_verify_boot_image(boot_image_.data(), boot_image_.size(), - NULL, NULL)); - - // Overflow checks. - h->kernel_offset = htobe64(4); - h->kernel_size = htobe64(0xfffffffffffffffeUL); - EXPECT_EQ(BVB_VERIFY_RESULT_INVALID_BOOT_IMAGE_HEADER, - bvb_verify_boot_image(boot_image_.data(), boot_image_.size(), - NULL, NULL)); -} - -TEST_F(VerifyTest, InitrdOutOfBounds) { - GenerateBootImage("SHA256_RSA2048", "", 0, - base::FilePath("test/testkey_rsa2048.pem")); - - BvbBootImageHeader *h = - reinterpret_cast<BvbBootImageHeader*>(boot_image_.data()); - - // Check we catch when initrd data goes out of bounds. - h->initrd_offset = htobe64(4); - h->initrd_size = htobe64(be64toh(h->payload_data_block_size)); - EXPECT_EQ(BVB_VERIFY_RESULT_INVALID_BOOT_IMAGE_HEADER, - bvb_verify_boot_image(boot_image_.data(), boot_image_.size(), - NULL, NULL)); - - // Overflow checks. - h->initrd_offset = htobe64(4); - h->initrd_size = htobe64(0xfffffffffffffffeUL); - EXPECT_EQ(BVB_VERIFY_RESULT_INVALID_BOOT_IMAGE_HEADER, - bvb_verify_boot_image(boot_image_.data(), boot_image_.size(), - NULL, NULL)); -} - -TEST_F(VerifyTest, InvalidAlgorithmField) { - GenerateBootImage("SHA256_RSA2048", "", 0, - base::FilePath("test/testkey_rsa2048.pem")); - - BvbBootImageHeader *h = - reinterpret_cast<BvbBootImageHeader*>(boot_image_.data()); - BvbBootImageHeader backup = *h; - - // Check we bail on unknown algorithm. - h->algorithm_type = htobe32(_BVB_ALGORITHM_NUM_TYPES); - EXPECT_EQ(BVB_VERIFY_RESULT_INVALID_BOOT_IMAGE_HEADER, - bvb_verify_boot_image(boot_image_.data(), boot_image_.size(), - NULL, NULL)); - *h = backup; - EXPECT_EQ(BVB_VERIFY_RESULT_OK, - bvb_verify_boot_image(boot_image_.data(), boot_image_.size(), - NULL, NULL)); -} - -TEST_F(VerifyTest, PublicKeyBlockTooSmall) { - GenerateBootImage("SHA256_RSA2048", "", 0, - base::FilePath("test/testkey_rsa2048.pem")); - - BvbBootImageHeader *h = - reinterpret_cast<BvbBootImageHeader*>(boot_image_.data()); - BvbBootImageHeader backup = *h; - - // Check we bail if the auxilary data block is too small. - uint64_t change = be64toh(h->auxilary_data_block_size) - 64; - h->auxilary_data_block_size = htobe64(change); - EXPECT_EQ(BVB_VERIFY_RESULT_INVALID_BOOT_IMAGE_HEADER, - bvb_verify_boot_image(boot_image_.data(), - boot_image_.size() - change, - NULL, NULL)); - *h = backup; - EXPECT_EQ(BVB_VERIFY_RESULT_OK, - bvb_verify_boot_image(boot_image_.data(), boot_image_.size(), - NULL, NULL)); -} - -bool VerifyTest::test_modification(BvbVerifyResult expected_result, - size_t offset, size_t length) { - uint8_t *d = reinterpret_cast<uint8_t*>(boot_image_.data()); - const int kNumCheckpoints = 16; - - // Test |kNumCheckpoints| modifications in the start, middle, and - // end of given sub-array. - for (int n = 0; n <= kNumCheckpoints; n++) { - size_t o = std::min(length*n/kNumCheckpoints, length - 1) + offset; - d[o] ^= 0x80; - BvbVerifyResult result = bvb_verify_boot_image(boot_image_.data(), - boot_image_.size(), - NULL, NULL); - d[o] ^= 0x80; - if (result != expected_result) - return false; - } - - return true; -} - -TEST_F(VerifyTest, ModificationDetection) { - GenerateBootImage("SHA256_RSA2048", "", 0, - base::FilePath("test/testkey_rsa2048.pem")); - - EXPECT_EQ(BVB_VERIFY_RESULT_OK, - bvb_verify_boot_image(boot_image_.data(), boot_image_.size(), - NULL, NULL)); - - BvbBootImageHeader h; - bvb_boot_image_header_to_host_byte_order( - reinterpret_cast<BvbBootImageHeader*>(boot_image_.data()), &h); - - size_t header_block_offset = 0; - size_t authentication_block_offset = header_block_offset + sizeof(BvbBootImageHeader); - size_t auxilary_block_offset = authentication_block_offset + h.authentication_data_block_size; - size_t payload_block_offset = auxilary_block_offset + h.auxilary_data_block_size; - - // Ensure we detect modification of the header data block. Do this - // in a field that's not validated so INVALID_BOOT_IMAGE_HEADER - // isn't returned. - EXPECT_TRUE(test_modification(BVB_VERIFY_RESULT_HASH_MISMATCH, - offsetof(BvbBootImageHeader, kernel_cmdline), - BVB_KERNEL_CMDLINE_MAX_LEN)); - // Also check the |reserved| field. - EXPECT_TRUE(test_modification(BVB_VERIFY_RESULT_HASH_MISMATCH, - offsetof(BvbBootImageHeader, reserved), - sizeof(BvbBootImageHeader().reserved))); - - // Ensure we detect modifications in the auxilary data block. - EXPECT_TRUE(test_modification(BVB_VERIFY_RESULT_HASH_MISMATCH, - auxilary_block_offset, - h.auxilary_data_block_size)); - - // Ensure we detect modifications in the payload key data block. - EXPECT_TRUE(test_modification(BVB_VERIFY_RESULT_HASH_MISMATCH, - payload_block_offset, - h.payload_data_block_size)); - - // Modifications in the hash part of the Authentication data block - // should also yield HASH_MISMATCH. This is because the hash check - // compares the calculated hash against the stored hash. - EXPECT_TRUE(test_modification(BVB_VERIFY_RESULT_HASH_MISMATCH, - authentication_block_offset + h.hash_offset, - h.hash_size)); - - // Modifications in the signature part of the Authentication data - // block, should not cause a hash mismatch ... but will cause a - // signature mismatch. - EXPECT_TRUE(test_modification(BVB_VERIFY_RESULT_SIGNATURE_MISMATCH, - authentication_block_offset + - h.signature_offset, - h.signature_size)); - - // Mofications outside the hash and signature parts of the - // Authentication data block are not detected. This is because it's - // not part of the hash calculation. - uint64_t offset = h.signature_offset + h.signature_size; - ASSERT_LT(h.hash_offset, h.signature_offset); - ASSERT_LT(offset + 1, h.authentication_data_block_size); - EXPECT_TRUE(test_modification(BVB_VERIFY_RESULT_OK, - authentication_block_offset + offset, - h.authentication_data_block_size - offset)); -} diff --git a/bvbtool b/bvbtool deleted file mode 100755 index d91069d..0000000 --- a/bvbtool +++ /dev/null @@ -1,1083 +0,0 @@ -#!/usr/bin/env python - -# Copyright 2016, The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -"""Command-line tool for working with Brillo Verified Boot images.""" - -import argparse -import hashlib -import os -import struct -import subprocess -import sys - -import Crypto.PublicKey.RSA - -# Keep in sync with bvb_boot_image_header.h. -BVB_VERSION_MAJOR = 1 -BVB_VERSION_MINOR = 0 - - -class Algorithm(object): - """Contains details about an algorithm. - - See the bvb_boot_image_header.h file for more details about - algorithms. - - The constant |ALGORITHMS| is a dictionary from human-readable - names (e.g 'SHA256_RSA2048') to instances of this class. - - Attributes: - algorithm_type: Integer code corresponding to |BvbAlgorithmType|. - hash_num_bytes: Number of bytes used to store the hash. - signature_num_bytes: Number of bytes used to store the signature. - public_key_num_bytes: Number of bytes used to store the public key. - padding: Padding used for signature, if any. - """ - - def __init__(self, algorithm_type, hash_num_bytes, signature_num_bytes, - public_key_num_bytes, padding): - self.algorithm_type = algorithm_type - self.hash_num_bytes = hash_num_bytes - self.signature_num_bytes = signature_num_bytes - self.public_key_num_bytes = public_key_num_bytes - self.padding = padding - -# This must be kept in sync with bvb_verify.h. -ALGORITHMS = { - 'NONE': Algorithm( - algorithm_type=0, # BVB_ALGORITHM_TYPE_NONE - hash_num_bytes=0, - signature_num_bytes=0, - public_key_num_bytes=0, - padding=[]), - 'SHA256_RSA2048': Algorithm( - algorithm_type=1, # BVB_ALGORITHM_TYPE_SHA256_RSA2048 - hash_num_bytes=32, - signature_num_bytes=256, - public_key_num_bytes=8 + 2*2048/8, - padding=[ - # PKCS1-v1_5 padding - 0x00, 0x01] + [0xff]*202 + [0x00] + [ - # ASN.1 header - 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, - 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, - 0x00, 0x04, 0x20, - ]), - 'SHA256_RSA4096': Algorithm( - algorithm_type=2, # BVB_ALGORITHM_TYPE_SHA256_RSA4096 - hash_num_bytes=32, - signature_num_bytes=512, - public_key_num_bytes=8 + 2*4096/8, - padding=[ - # PKCS1-v1_5 padding - 0x00, 0x01] + [0xff]*458 + [0x00] + [ - # ASN.1 header - 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, - 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, - 0x00, 0x04, 0x20, - ]), - 'SHA256_RSA8192': Algorithm( - algorithm_type=3, # BVB_ALGORITHM_TYPE_SHA256_RSA8192 - hash_num_bytes=32, - signature_num_bytes=1024, - public_key_num_bytes=8 + 2*8192/8, - padding=[ - # PKCS1-v1_5 padding - 0x00, 0x01] + [0xff]*970 + [0x00] + [ - # ASN.1 header - 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, - 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, - 0x00, 0x04, 0x20, - ]), - 'SHA512_RSA2048': Algorithm( - algorithm_type=4, # BVB_ALGORITHM_TYPE_SHA512_RSA2048 - hash_num_bytes=64, - signature_num_bytes=256, - public_key_num_bytes=8 + 2*2048/8, - padding=[ - # PKCS1-v1_5 padding - 0x00, 0x01] + [0xff]*170 + [0x00] + [ - # ASN.1 header - 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, - 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, - 0x00, 0x04, 0x40 - ]), - 'SHA512_RSA4096': Algorithm( - algorithm_type=5, # BVB_ALGORITHM_TYPE_SHA512_RSA4096 - hash_num_bytes=64, - signature_num_bytes=512, - public_key_num_bytes=8 + 2*4096/8, - padding=[ - # PKCS1-v1_5 padding - 0x00, 0x01] + [0xff]*426 + [0x00] + [ - # ASN.1 header - 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, - 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, - 0x00, 0x04, 0x40 - ]), - 'SHA512_RSA8192': Algorithm( - algorithm_type=6, # BVB_ALGORITHM_TYPE_SHA512_RSA8192 - hash_num_bytes=64, - signature_num_bytes=1024, - public_key_num_bytes=8 + 2*8192/8, - padding=[ - # PKCS1-v1_5 padding - 0x00, 0x01] + [0xff]*938 + [0x00] + [ - # ASN.1 header - 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, - 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, - 0x00, 0x04, 0x40 - ]), -} - - -def round_to_multiple(number, size): - """Rounds a number up to nearest multiple of another number. - - Args: - number: The number to round up. - size: The multiple to round up to. - - Returns: - If |number| is a multiple of |size|, returns |number|, otherwise - returns |number| + |size|. - """ - remainder = number % size - if remainder == 0: - return number - return number + size - remainder - - -def round_to_pow2(number): - """Rounds a number up to the next power of 2. - - Args: - number: The number to round up. - - Returns: - If |number| is already a power of 2 then |number| is - returned. Otherwise the smallest power of 2 greater than |number| - is returned. - """ - return 2**((number - 1).bit_length()) - - -def write_long(output, num_bits, value): - """Writes a long to an output stream using a given amount of bits. - - This number is written big-endian, e.g. with the most significant - bit first. - - Arguments: - output: The object to write the output to. - num_bits: The number of bits to write, e.g. 2048. - value: The value to write. - """ - for bit_pos in range(num_bits, 0, -8): - octet = (value >> (bit_pos - 8)) & 0xff - output.write(struct.pack('!B', octet)) - - -def egcd(a, b): - """Calculate greatest common divisor of two numbers. - - This implementation uses a recursive version of the extended - Euclidian algorithm. - - Arguments: - a: First number. - b: Second number. - - Returns: - A tuple (gcd, x, y) that where |gcd| is the greatest common - divisor of |a| and |b| and |a|*|x| + |b|*|y| = |gcd|. - """ - if a == 0: - return (b, 0, 1) - else: - g, y, x = egcd(b % a, a) - return (g, x - (b // a) * y, y) - - -def modinv(a, m): - """Calculate modular multiplicative inverse of |a| modulo |m|. - - This calculates the number |x| such that |a| * |x| == 1 (modulo - |m|). This number only exists if |a| and |m| are co-prime - |None| - is returned if this isn't true. - - Arguments: - a: The number to calculate a modular inverse of. - m: The modulo to use. - - Returns: - The modular multiplicative inverse of |a| and |m| or |None| if - these numbers are not co-prime. - """ - gcd, x, _ = egcd(a, m) - if gcd != 1: - return None # modular inverse does not exist - else: - return x % m - - -def parse_number(string): - """Parse a string as a number. - - This is just a short-hand for int(string, 0) suitable for use in the - |type| parameter of |ArgumentParser|'s add_argument() function. An - improvement to just using type=int is that this function supports - numbers in other bases, e.g. "0x1234". - - Arguments: - string: The string to parse. - - Returns: - The parsed integer. - - Raises: - ValueError: If the number could not be parsed. - """ - return int(string, 0) - - -def write_rsa_key(output, key): - """Writes a public RSA key in |BvBRSAPublicKeyHeader| format. - - This writes the |BvBRSAPublicKeyHeader| as well as the two large - numbers (|key_num_bits| bits long) following it. - - Arguments: - output: The object to write the output to. - key: A Crypto.PublicKey.RSA object. - """ - # key.e is exponent - # key.n is modulus - key_num_bits = key.size() + 1 - # Calculate n0inv = -1/n[0] (mod 2^32) - b = 2L**32 - n0inv = b - modinv(key.n, b) - # Calculate rr = r^2 (mod N), where r = 2^(# of key bits) - r = 2L**key.n.bit_length() - rrmodn = r * r % key.n - output.write(struct.pack('!II', key_num_bits, n0inv)) - write_long(output, key_num_bits, key.n) - write_long(output, key_num_bits, rrmodn) - - -def lookup_algorithm_by_type(alg_type): - """Looks up algorithm by type. - - Arguments: - alg_type: The integer representing the type. - - Returns: - A tuple with the algorithm name and an |Algorithm| instance. - - Raises: - Exception: If the algorithm cannot be found - """ - for alg_name in ALGORITHMS: - alg_data = ALGORITHMS[alg_name] - if alg_data.algorithm_type == alg_type: - return (alg_name, alg_data) - raise Exception('Unknown algorithm type %d' % alg_type) - - -def add_property(encoded_props, key, value): - """Helper function to add a key/value pair to a bytearray. - - The encoding specified in the |BvbPropertyHeader| in - bvb_boot_image_header.h is used. - - Arguments: - encoded_props: A bytearray to append to. - key: The key to write. - value: The value to write. - """ - encoded_props.extend(struct.pack('!QQ', len(key), len(value))) - encoded_props.extend(key) - encoded_props.append(0) - encoded_props.extend(value) - encoded_props.append(0) - num_bytes = 2 * 8 + len(key) + len(value) + 2 - padding_bytes = (8 - num_bytes) & 7 - for _ in range(padding_bytes): - encoded_props.append(0) - - -class BvbIntegrityFooter(object): - """A class for parsing and writing Integrity Footers. - - Integrity footers are stored at the end of filesystems where - dm-verity hashes have been added with the 'add_image_hashes' - command. - - Attributes: - magic: Magic for identifying the footer, see |MAGIC|. - version_major: The major version of bvbtool that wrote the footer. - version_minor: The minor version of bvbtool that wrote the footer. - dm_verity_version: dm-verity version used. - image_size: Size of the image, after rounding up to |block_size|. - tree_offset: Offset of the hash tree in the file. - tree_size: Size of the tree. - data_block_size: Data block size - hash_block_size: Hash block size - hash_algorithm: Hash algorithm used. - salt_hex: Salt used, as a hex-string - root_hash_hex: Root hash, as a hex-string. - """ - - MAGIC = 'BVBi' - SIZE = 4096 - RESERVED = 1968 - FORMAT_STRING = ('!4s2L' # magic, 2 x version - 'L' # dm-verity version used - 'Q' # image size (bytes) - 'Q' # tree offset (bytes) - 'Q' # tree size (bytes) - 'L' # data block size (bytes) - 'L' # hash block size (bytes) - '32s' # hash algorithm used - '1024s' # salt, as a hex string - '1024s' + # root hash, as a hex string - str(RESERVED) + 'x') # padding for reserved bytes - - def __init__(self, data=None): - """Initializes a new footer object. - - Arguments: - data: If not None, must be a bytearray of size 4096. - - Raises: - LookupError: If the given footer is malformed. - struct.error: If the given data has no footer. - """ - assert struct.calcsize(self.FORMAT_STRING) == self.SIZE - - if data: - (self.magic, self.version_major, self.version_minor, - self.dm_verity_version, self.image_size, self.tree_offset, - self.tree_size, self.data_block_size, self.hash_block_size, - self.hash_algorithm, self.salt_hex, - self.root_hash_hex) = struct.unpack(self.FORMAT_STRING, data) - if self.magic != self.MAGIC: - raise LookupError('Given data does not look like a Brillo ' - 'integrity footer.') - # Nuke NUL-bytes at the end. - self.hash_algorithm = self.hash_algorithm.split('\0', 1)[0] - self.salt_hex = self.salt_hex.split('\0', 1)[0] - self.root_hash_hex = self.root_hash_hex.split('\0', 1)[0] - else: - self.magic = self.MAGIC - self.version_major = BVB_VERSION_MAJOR - self.version_minor = BVB_VERSION_MINOR - self.dm_verity_version = 0 - self.image_size = 0 - self.tree_offset = 0 - self.tree_size = 0 - self.data_block_size = 0 - self.hash_block_size = 0 - self.hash_algorithm = '' - self.salt_hex = '' - self.root_hash_hex = '' - - def save(self, output): - """Serializes the header (4096 bytes) to disk. - - Arguments: - output: The object to write the output to. - """ - output.write(struct.pack( - self.FORMAT_STRING, self.magic, self.version_major, self.version_minor, - self.dm_verity_version, self.image_size, self.tree_offset, - self.tree_size, self.data_block_size, self.hash_block_size, - self.hash_algorithm, self.salt_hex, self.root_hash_hex)) - - -class BvbHeader(object): - """A class for parsing and writing Brillo Verified Boot headers. - - Attributes: - The attributes correspond to the |BvBBootImageHeader| struct - defined in bvb_boot_image_header.h. - """ - - SIZE = 8192 - - # Keep in sync with |reserved| field of |BvbBootImageHeader|. - RESERVED = 3936 - - # Keep in sync with |BvbBootImageHeader|. - FORMAT_STRING = ('!4s2L' # magic, 2 x version - '3Q' # 3 x block size - 'L' # algorithm type - '2Q' # offset, size (hash) - '2Q' # offset, size (signature) - '2Q' # offset, size (public key) - '2Q' # offset, size (properties) - 'Q' # rollback_index - '2Q' # offset, size (kernel) - '2Q' # offset, size (initrd) - 'Q' # kernel load address - 'Q' # initrd load address - '4096s' + # cmdline - str(RESERVED) + 'x') # padding for reserved bytes - - def __init__(self, data=None): - """Initializes a new header object. - - Arguments: - data: If not None, must be a bytearray of size 8192. - - Raises: - Exception: If the given data is malformed. - """ - assert struct.calcsize(self.FORMAT_STRING) == self.SIZE - - if data: - (self.magic, self.header_version_major, self.header_version_minor, - self.authentication_data_block_size, self.auxilary_data_block_size, - self.payload_data_block_size, self.algorithm_type, self.hash_offset, - self.hash_size, self.signature_offset, self.signature_size, - self.public_key_offset, self.public_key_size, self.properties_offset, - self.properties_size, self.rollback_index, self.kernel_offset, - self.kernel_size, self.initrd_offset, self.initrd_size, - self.kernel_address, self.initrd_address, - self.kernel_cmdline) = struct.unpack(self.FORMAT_STRING, data) - # Nuke NUL-bytes at the end of the string. - self.kernel_cmdline = self.kernel_cmdline.split('\0', 1)[0] - if self.magic != 'BVB0': - raise Exception('Given image does not look like a Brillo boot image') - else: - self.magic = 'BVB0' - self.header_version_major = BVB_VERSION_MAJOR - self.header_version_minor = BVB_VERSION_MINOR - self.authentication_data_block_size = 0 - self.auxilary_data_block_size = 0 - self.payload_data_block_size = 0 - self.algorithm_type = 0 - self.hash_offset = 0 - self.hash_size = 0 - self.signature_offset = 0 - self.signature_size = 0 - self.public_key_offset = 0 - self.public_key_size = 0 - self.properties_offset = 0 - self.properties_size = 0 - self.rollback_index = 0 - self.kernel_offset = 0 - self.kernel_size = 0 - self.initrd_offset = 0 - self.initrd_size = 0 - self.kernel_address = 0 - self.initrd_address = 0 - self.kernel_cmdline = '' - - def save(self, output): - """Serializes the header (8192 bytes) to disk. - - Arguments: - output: The object to write the output to. - """ - output.write(struct.pack( - self.FORMAT_STRING, self.magic, self.header_version_major, - self.header_version_minor, self.authentication_data_block_size, - self.auxilary_data_block_size, self.payload_data_block_size, - self.algorithm_type, self.hash_offset, self.hash_size, - self.signature_offset, self.signature_size, self.public_key_offset, - self.public_key_size, self.properties_offset, self.properties_size, - self.rollback_index, self.kernel_offset, self.kernel_size, - self.initrd_offset, self.initrd_size, self.kernel_address, - self.initrd_address, self.kernel_cmdline)) - - -class BvbTool(object): - """Object for bvbtool.""" - - def __init__(self): - """Initiailzes the object.""" - parser = argparse.ArgumentParser(usage="""bvbtool COMMAND [<args>] - -Commands: - version Prints out version of bvbtool. - make_boot_image Make boot image. - sign_boot_image Sign boot image. - info_boot_image Show information about boot image. - add_image_hashes Add hashes for integrity-checking to image. - info_image_hashes Show information about integrity-checking hashes. - extract_public_key Extract public key. - -""") - parser.add_argument('COMMAND', help='The command to run') - args = parser.parse_args(sys.argv[1:2]) - if not hasattr(self, args.COMMAND): - print 'Unrecognized command' - parser.print_help() - sys.exit(1) - getattr(self, args.COMMAND)() - - def version(self): - """Implements the 'version' command.""" - print '%d.%d' % (BVB_VERSION_MAJOR, BVB_VERSION_MINOR) - - def info_boot_image(self): - """Implements the 'info_boot_image' command.""" - parser = argparse.ArgumentParser( - prog='bvbtool info_boot_image', - description='Show information about Brillo boot image.') - parser.add_argument('--image', - help='Brillo boot image to use', - type=argparse.FileType('rb'), - required=True) - parser.add_argument('--output', - help='Write info to file', - type=argparse.FileType('wt'), - default=sys.stdout) - args = parser.parse_args(sys.argv[2:]) - - h = BvbHeader(args.image.read(BvbHeader.SIZE)) - - (alg_name, _) = lookup_algorithm_by_type(h.algorithm_type) - - o = args.output - o.write('Boot Image version: %d.%d\n' % - (h.header_version_major, h.header_version_minor)) - o.write('Header Block: %d bytes\n' % BvbHeader.SIZE) - o.write('Authentication Block: %d bytes\n' % - h.authentication_data_block_size) - o.write('Auxilary Block: %d bytes\n' % h.auxilary_data_block_size) - o.write('Payload Block: %d bytes\n' % h.payload_data_block_size) - o.write('Algorithm: %s\n' % alg_name) - o.write('Rollback Index: %d\n' % h.rollback_index) - o.write('Kernel: %d bytes\n' % h.kernel_size) - o.write('Initrd: %d bytes\n' % h.initrd_size) - o.write('Kernel Load Address: 0x%08x\n' % h.kernel_address) - o.write('Initrd Load Address: 0x%08x\n' % h.initrd_address) - o.write('Kernel Cmdline: %s\n' % h.kernel_cmdline) - - # Print properties. - o.write('Properties:\n') - authentication_block_offset = BvbHeader.SIZE - auxilary_block_offset = ( - authentication_block_offset + h.authentication_data_block_size) - prop_start_offset = auxilary_block_offset + h.properties_offset - prop_end_offset = prop_start_offset + h.properties_size - args.image.seek(prop_start_offset) - num_printed = 0 - while args.image.tell() < prop_end_offset: - (key_len, value_len) = struct.unpack('!2Q', args.image.read(16)) - num_bytes = key_len + value_len + 2 - padding_bytes = (8 - num_bytes) & 7 - prop_data = args.image.read(num_bytes + padding_bytes) - key = prop_data[0:key_len] - # Avoid printing large property values (e.g. blobs). - if value_len >= 256: - o.write(' %s: (%d bytes)\n' % (key, value_len)) - else: - value = prop_data[key_len + 1:key_len + 1 + value_len] - o.write(' %s: %s\n' % (key, repr(value))) - num_printed += 1 - if num_printed == 0: - o.write(' (none)\n') - - def make_boot_image(self): - """Implements the 'make_boot_image' command.""" - parser = argparse.ArgumentParser(prog='bvbtool make_boot_image', - description='Make Brillo boot image.') - - parser.add_argument('--kernel', - help='Path to kernel', - type=argparse.FileType('rb')) #, required=True) - parser.add_argument('--initrd', - help='Path to ramdisk', - type=argparse.FileType('rb')) - parser.add_argument('--kernel_address', - help='Kernel load address', - type=parse_number, - default=0x10008000) - parser.add_argument('--initrd_address', - help='Ramdisk load address', - type=parse_number, - default=0x11000000) - parser.add_argument('--kernel_cmdline', - help='Kernel command-line', - default='') - parser.add_argument('--rootfs_with_hashes', - help='Setup dm-verity for given rootfs', - type=argparse.FileType('rb')) - parser.add_argument('--rollback_index', - help='Rollback Index', - type=parse_number, - default=0) - parser.add_argument('--prop', - help='Add property', - metavar='KEY:VALUE', - action='append') - parser.add_argument('--prop_from_file', - help='Add property from file', - metavar='KEY:PATH', - action='append') - parser.add_argument('--output', - help='Output file name', - type=argparse.FileType('wb'), - required=True) - args = parser.parse_args(sys.argv[2:]) - - h = BvbHeader() - - # Write header data block and leave ample room for hash, signature - # and public key. - h.authentication_data_block_size = 4096 - h.kernel_offset = 0 - h.kernel_size = os.fstat(args.kernel.fileno()).st_size - h.initrd_offset = 0 - h.initrd_size = 0 - if args.initrd: - h.initrd_offset = h.kernel_offset + h.kernel_size - h.initrd_size = os.fstat(args.initrd.fileno()).st_size - h.payload_data_block_size = h.kernel_size + h.initrd_size - - # Generate properties blob. - encoded_props = bytearray() - if args.prop: - for prop in args.prop: - idx = prop.find(':') - if idx == -1: - sys.stderr.write('Malformed --property value %s.\n', prop) - sys.exit(1) - key = prop[0:idx] - value = prop[(idx + 1):] - add_property(encoded_props, key, value) - if args.prop_from_file: - for prop in args.prop_from_file: - idx = prop.find(':') - if idx == -1: - sys.stderr.write('Malformed --property value %s.\n', prop) - sys.exit(1) - key = prop[0:idx] - file_path = prop[(idx + 1):] - value = open(file_path, 'rb').read() - add_property(encoded_props, key, value) - - # We'll store the properties at offset 0 in the Auxiliary data - # block. Make sure it's big enough to hold the biggest - # possible key. - h.auxilary_data_block_size = round_to_multiple( - len(encoded_props) + 4096, 64) - h.properties_offset = 0 - h.properties_size = len(encoded_props) - - h.rollback_index = args.rollback_index - h.kernel_address = args.kernel_address - h.initrd_address = args.initrd_address - h.kernel_cmdline = args.kernel_cmdline - - # Setup dm-verity, if requested. - if args.rootfs_with_hashes: - args.rootfs_with_hashes.seek(0, os.SEEK_END) - image_size = args.rootfs_with_hashes.tell() - args.rootfs_with_hashes.seek(image_size - BvbIntegrityFooter.SIZE) - f = BvbIntegrityFooter(args.rootfs_with_hashes.read( - BvbIntegrityFooter.SIZE)) - c = 'dm="1 vroot none ro 1,' - c += '0 ' # start - c += '%d ' % (f.image_size / 512) # size (# sectors) - c += 'verity %d ' % f.dm_verity_version # type and version - c += 'PARTUUID=$(ANDROID_SYSTEM_PARTUUID) ' # data_dev - c += 'PARTUUID=$(ANDROID_SYSTEM_PARTUUID) ' # hash_dev - c += '%d ' % f.data_block_size # data_block - c += '%d ' % f.hash_block_size # hash_block - c += '%d ' % (f.image_size / f.data_block_size) # #blocks - c += '%d ' % (f.image_size / f.data_block_size) # hash_offset - c += '%s ' % f.hash_algorithm # hash_alg - c += '%s ' % f.root_hash_hex # root_digest - c += '%s' % f.salt_hex # salt - c += '"' - if h.kernel_cmdline: - c += ' ' - h.kernel_cmdline = c + h.kernel_cmdline - - # Save the header. - h.save(args.output) - - # Write Authentication data block, as zeroes. - args.output.write(struct.pack(str(h.authentication_data_block_size) + 'x')) - - # Write Auxilary data block. First properties, then pad with zeroes. - args.output.write(encoded_props) - args.output.write(struct.pack(str(h.auxilary_data_block_size - len( - encoded_props)) + 'x')) - - # Write Payload data block: kernel and initrd - args.output.write(args.kernel.read()) - if args.initrd: - args.output.write(args.initrd.read()) - - def sign_boot_image(self): - """Implements the 'sign_boot_image' command.""" - parser = argparse.ArgumentParser(prog='bvbtool sign_boot_image', - description='Sign Brillo boot image.') - group = parser.add_argument_group() - group.add_argument('--show_algorithms', - help='Show avaiable algorithms', - action='store_true') - group = parser.add_argument_group() - group.add_argument('--image', - help='Brillo boot image to sign', - type=argparse.FileType('rab+')) - group.add_argument('--key', help='Path to RSA private key file') - group.add_argument('--algorithm', help='Algorithm to use') - args = parser.parse_args(sys.argv[2:]) - - if args.show_algorithms: - algs = [] - for alg_name in ALGORITHMS: - if alg_name != 'NONE': - algs.append(alg_name) - algs.sort() - for alg in algs: - print alg - sys.exit(0) - - # Support 'NONE' to avoid conditionals in build systems if - # signing is not needed (this way they can always execute - # 'bvbtool sign_boot_image --algorithm NONE') - if args.algorithm == 'NONE': - sys.exit(0) - - if not args.algorithm: - sys.stderr.write('Option --algorithm is required.\n') - sys.exit(1) - if not args.image: - sys.stderr.write('Option --image is required.\n') - sys.exit(1) - if not args.key: - sys.stderr.write('Option --key is required.\n') - sys.exit(1) - - try: - alg = ALGORITHMS[args.algorithm] - except IndexError: - sys.stderr.write('Unknown algorithm %s.\n' % args.algorithm) - sys.exit(1) - - h = BvbHeader(args.image.read(BvbHeader.SIZE)) - - if h.properties_offset != 0: - # This is just an implementation limitation which can be lifted later. - sys.stderr.write('Only support images with props at the top.\n') - sys.exit(1) - - if h.authentication_data_block_size < ( - alg.hash_num_bytes + alg.signature_num_bytes): - sys.stderr.write('Insufficient room for storing hash and signature.\n') - sys.exit(1) - - if h.auxilary_data_block_size < alg.public_key_num_bytes: - sys.stderr.write('Insufficient room for storing public key.\n') - sys.exit(1) - - authentication_data_block_offset = BvbHeader.SIZE - auxilary_data_block_offset = ( - authentication_data_block_offset + h.authentication_data_block_size) - - # Update header with hash type/offset/size, signature - # type/offset/size, and public key size. - h.algorithm_type = alg.algorithm_type - # Hash offset and size (in Authentication data block). - h.hash_offset = 0 - h.hash_size = alg.hash_num_bytes - # Signature offset and size - it's stored right after the hash - # (in Authentication data block). - h.signature_offset = alg.hash_num_bytes - h.signature_size = alg.signature_num_bytes - # Public key offset and size - follows properties (in Auxilary data block). - h.public_key_offset = h.properties_size - h.public_key_size = alg.public_key_num_bytes - - # Extract public key and insert it into "Auxilary data" block. - key = Crypto.PublicKey.RSA.importKey(open(args.key).read()) - args.image.seek(auxilary_data_block_offset + h.properties_size) - write_rsa_key(args.image, key) - - # Save the updated header. - args.image.seek(0) - h.save(args.image) - - # Calculate the hash. - if args.algorithm[0:6] == 'SHA256': - ha = hashlib.sha256() - elif args.algorithm[0:6] == 'SHA512': - ha = hashlib.sha512() - else: - sys.stderr.write('Unsupported algorithm.\n') - sys.exit(1) - args.image.seek(0) - ha.update(args.image.read(BvbHeader.SIZE)) - args.image.seek(auxilary_data_block_offset) - ha.update(args.image.read(h.auxilary_data_block_size)) - ha.update(args.image.read(h.payload_data_block_size)) - # Write the hash - args.image.seek(authentication_data_block_offset) - binary_hash = ha.digest() - args.image.write(binary_hash) - - # Calculate the signature. - p = subprocess.Popen( - ['openssl', 'rsautl', '-sign', '-inkey', args.key, '-raw'], - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - padding_and_hash = str(bytearray(alg.padding)) + binary_hash - (pout, perr) = p.communicate(padding_and_hash) - retcode = p.wait() - if retcode != 0: - sys.stderr.write('Error signing: %s\n' % perr) - sys.exit(1) - # Write the signature. - args.image.seek(authentication_data_block_offset + alg.hash_num_bytes) - args.image.write(pout) - - def extract_public_key(self): - """Implements the 'extract_public_key' command.""" - parser = argparse.ArgumentParser( - prog='bvbtool extract_public_key', - description= - 'Extract public key and dump it in the format used by Brillo.') - parser.add_argument('--key', - help='Path to RSA private key file', - required=True) - parser.add_argument('--output', - help='Output file name', - type=argparse.FileType('wb'), - required=True) - args = parser.parse_args(sys.argv[2:]) - - key = Crypto.PublicKey.RSA.importKey(open(args.key).read()) - write_rsa_key(args.output, key) - - def info_image_hashes(self): - """Implements the 'info_boot_image' command.""" - parser = argparse.ArgumentParser( - prog='bvbtool info_image_hashes', - description='Show information about integrity-checking hashes.') - parser.add_argument('--image', - help='Brillo boot image to use', - type=argparse.FileType('rb'), - required=True) - parser.add_argument('--output', - help='Write info to file', - type=argparse.FileType('wt'), - default=sys.stdout) - args = parser.parse_args(sys.argv[2:]) - - args.image.seek(0, os.SEEK_END) - image_size = args.image.tell() - args.image.seek(image_size - BvbIntegrityFooter.SIZE) - footer = BvbIntegrityFooter(args.image.read(BvbIntegrityFooter.SIZE)) - - o = args.output - o.write('Footer version: %d.%d\n' % - (footer.version_major, footer.version_minor)) - o.write('Version of dm-verity: %d\n' % footer.dm_verity_version) - o.write('Image Size: %d bytes\n' % footer.image_size) - o.write('Tree Offset: %d\n' % footer.tree_offset) - o.write('Tree Size: %d bytes\n' % footer.tree_size) - o.write('Data Block Size: %d bytes\n' % footer.data_block_size) - o.write('Hash Block Size: %d bytes\n' % footer.hash_block_size) - o.write('Hash Algorithm: %s\n' % footer.hash_algorithm) - o.write('Salt: %s\n' % footer.salt_hex) - o.write('Root Hash: %s\n' % footer.root_hash_hex) - - def add_image_hashes(self): - """Implements the 'add_image_hashes' command. - - See https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity for - more information about dm-verity and these hashes. - """ - parser = argparse.ArgumentParser( - prog='bvbtool add_hashes_to_image', - description='Add hashes for integrity-checking to image.') - parser.add_argument('--image', - help='Brillo boot image to add hashes to', - type=argparse.FileType('rab+')) - parser.add_argument('--hash', - help='Hash algorithm to use (default: sha1)', - default='sha1') - parser.add_argument('--salt', help='Salt in hex (default: /dev/urandom)') - parser.add_argument('--block_size', - help='Block size (default: 4096)', - type=parse_number, - default=4096) - args = parser.parse_args(sys.argv[2:]) - - # If there's already a footer of ours, truncate it. This way - # 'bvbtool add_hashes_to_image' is idempotent modulo salts. - args.image.seek(0, os.SEEK_END) - image_size = args.image.tell() - args.image.seek(image_size - BvbIntegrityFooter.SIZE) - try: - footer = BvbIntegrityFooter(args.image.read(BvbIntegrityFooter.SIZE)) - # Existing footer found. Just truncate. - image_size = footer.image_size - args.image.truncate(image_size) - except (LookupError, struct.error): - pass - - # Ensure image is multiple of block_size - rounded_image_size = round_to_multiple(image_size, args.block_size) - if rounded_image_size > image_size: - args.image.write('\0' * (rounded_image_size - image_size)) - image_size = rounded_image_size - - tree_offset = image_size - - digest_size = len(hashlib.new(name=args.hash).digest()) - digest_padding = round_to_pow2(digest_size) - digest_size - - if args.salt: - salt = args.salt.decode('hex') - else: - if args.salt is None: - # If salt is not explicitly specified, choose a hash - # that's the same size as the hash size. - hash_size = digest_size - salt = open('/dev/urandom').read(hash_size) - else: - salt = '' - - # Hashes are stored upside down so we need to calcuate hash - # offsets in advance. - (hash_level_offsets, tree_size) = calc_hash_level_offsets( - image_size, args.block_size, digest_size + digest_padding) - - # Make room for the tree. - args.image.truncate(image_size + tree_size) - - # Generate the tree. - root_hash = generate_hash_tree(args.image, image_size, args.block_size, - args.hash, salt, digest_padding, tree_offset, - hash_level_offsets) - - # Write footer with the root hash and other information. - footer = BvbIntegrityFooter() - footer.dm_verity_version = 1 - footer.image_size = image_size - footer.tree_offset = tree_offset - footer.tree_size = tree_size - footer.data_block_size = args.block_size - footer.hash_block_size = args.block_size - footer.hash_algorithm = args.hash - footer.salt_hex = salt.encode('hex') - footer.root_hash_hex = root_hash.encode('hex') - args.image.seek(tree_offset + tree_size) - footer.save(args.image) - - -def calc_hash_level_offsets(image_size, block_size, digest_size): - """Calculate the offsets of all the hash-levels in a Merkle-tree. - - Arguments: - image_size: The size of the image to calculate a Merkle-tree for. - block_size: The block size, e.g. 4096. - digest_size: The size of each hash, e.g. 32 for SHA-256. - - Returns: - A tuple where the first argument is an array of offsets and the - second is size of the tree, in bytes. - """ - level_offsets = [] - level_sizes = [] - tree_size = 0 - - num_levels = 0 - size = image_size - while size > block_size: - num_blocks = (size + block_size - 1) / block_size - level_size = round_to_multiple(num_blocks * digest_size, block_size) - - level_sizes.append(level_size) - tree_size += level_size - num_levels += 1 - - size = level_size - - for n in range(0, num_levels): - offset = 0 - for m in range(n + 1, num_levels): - offset += level_sizes[m] - level_offsets.append(offset) - - return (level_offsets, tree_size) - - -def generate_hash_tree(image, image_size, block_size, hash_alg_name, salt, - digest_padding, tree_offset, hash_level_offsets): - """Generates a Merkle-tree for a file. - - Args: - image: The image, as a file. - image_size: The size of the image. - block_size: The block size, e.g. 4096. - hash_alg_name: The hash algorithm, e.g. 'sha256' or 'sha1'. - salt: The salt to use. - digest_padding: The padding for each digest. - tree_offset: The offset of where to store the Merkle tree in |image|. - hash_level_offsets: The offsets from calc_hash_level_offsets(). - - Returns: - The top-level hash. - """ - hash_src_offset = 0 - hash_src_size = image_size - level_num = 0 - while hash_src_size > block_size: - level_output = '' - image.seek(hash_src_offset) - remaining = hash_src_size - while remaining > 0: - hasher = hashlib.new(name=hash_alg_name, string=salt) - data = image.read(min(remaining, block_size)) - assert data - remaining -= len(data) - hasher.update(data) - if len(data) < block_size: - hasher.update('\0' * (block_size - len(data))) - level_output += hasher.digest() - if digest_padding > 0: - level_output += '\0' * digest_padding - - padding_needed = (round_to_multiple( - len(level_output), block_size) - len(level_output)) - level_output += '\0' * padding_needed - - hash_dest_offset = hash_level_offsets[level_num] + tree_offset - - image.seek(hash_dest_offset) - image.write(level_output) - - hash_src_offset = hash_dest_offset - hash_src_size = len(level_output) - - level_num += 1 - - hasher = hashlib.new(name=hash_alg_name, string=salt) - hasher.update(level_output) - return hasher.digest() - - -if __name__ == '__main__': - BvbTool() diff --git a/bvbtool_unittest.cc b/bvbtool_unittest.cc deleted file mode 100644 index 975691a..0000000 --- a/bvbtool_unittest.cc +++ /dev/null @@ -1,404 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <iostream> - -#include <endian.h> -#include <inttypes.h> -#include <string.h> - -#include <base/files/file_util.h> -#include <base/strings/string_util.h> -#include <base/strings/stringprintf.h> - -#include "bvb_unittest_util.h" -#include "bvb_refimpl.h" - -class BvbToolTest : public BaseBvbToolTest { -public: - BvbToolTest() {} -}; - -// This test ensure that the version is increased in both -// bvb_boot_image.h and the bvb tool. -TEST_F(BvbToolTest, BvbVersionInSync) -{ - base::FilePath path = testdir_.Append("version.txt"); - EXPECT_COMMAND(0, - "./bvbtool version > %s", - path.value().c_str()); - std::string printed_version; - ASSERT_TRUE(base::ReadFileToString(path, &printed_version)); - base::TrimWhitespaceASCII(printed_version, base::TRIM_ALL, &printed_version); - std::string expected_version = base::StringPrintf("%d.%d", - BVB_MAJOR_VERSION, - BVB_MINOR_VERSION); - EXPECT_EQ(printed_version, expected_version); -} - -TEST_F(BvbToolTest, ExtractPublicKey) -{ - GenerateBootImage("SHA256_RSA2048", "", 0, - base::FilePath("test/testkey_rsa2048.pem")); - - base::FilePath public_key_path = testdir_.Append("public_key.bin"); - EXPECT_COMMAND(0, - "./bvbtool extract_public_key --key test/testkey_rsa2048.pem" - " --output %s", - public_key_path.value().c_str()); - - std::string key_data; - ASSERT_TRUE(base::ReadFileToString(public_key_path, &key_data)); - - BvbBootImageHeader h; - bvb_boot_image_header_to_host_byte_order( - reinterpret_cast<BvbBootImageHeader*>(boot_image_.data()), &h); - uint8_t *d = reinterpret_cast<uint8_t*>(boot_image_.data()); - size_t auxilary_data_block_offset = - sizeof(BvbBootImageHeader) + h.authentication_data_block_size; - EXPECT_GT(h.auxilary_data_block_size, key_data.size()); - EXPECT_EQ(0, memcmp(key_data.data(), - d + auxilary_data_block_offset + h.public_key_offset, - key_data.size())); -} - -TEST_F(BvbToolTest, PayloadsAreCorrect) -{ - GenerateBootImage("SHA256_RSA2048", "", 0, - base::FilePath("test/testkey_rsa2048.pem")); - - BvbBootImageHeader h; - bvb_boot_image_header_to_host_byte_order( - reinterpret_cast<BvbBootImageHeader*>(boot_image_.data()), &h); - - uint8_t *d = reinterpret_cast<uint8_t*>(boot_image_.data()) + - sizeof(BvbBootImageHeader) + - h.authentication_data_block_size + - h.auxilary_data_block_size; - - // Check that the kernel and initrd images are inserted correctly. - for (int n = 0; n < 2; n++) { - std::string paths[2] = {"test/dummy_kernel.bin", - "test/dummy_initrd.bin"}; - base::FilePath path(paths[n]); - - int64_t file_size; - std::vector<uint8_t> file_data; - ASSERT_TRUE(base::GetFileSize(path, &file_size)); - file_data.resize(file_size); - ASSERT_TRUE(base::ReadFile(path, - reinterpret_cast<char*>(file_data.data()), - file_data.size())); - - switch (n) { - case 0: - // kernel - EXPECT_EQ(65536U, file_data.size()); - EXPECT_EQ(file_data.size(), h.kernel_size); - EXPECT_EQ(0, memcmp(file_data.data(), - d + h.kernel_offset, - file_data.size())); - break; - case 1: - // initrd - EXPECT_EQ(131072U, file_data.size()); - EXPECT_EQ(file_data.size(), h.initrd_size); - EXPECT_EQ(0, memcmp(file_data.data(), - d + h.initrd_offset, - file_data.size())); - break; - default: - ASSERT_TRUE(false); - break; - } - } -} - -TEST_F(BvbToolTest, CheckCmdline) -{ - std::string cmdline("init=/sbin/init ro x y z"); - GenerateBootImage("SHA256_RSA2048", cmdline, 0, - base::FilePath("test/testkey_rsa2048.pem")); - - BvbBootImageHeader h; - bvb_boot_image_header_to_host_byte_order( - reinterpret_cast<BvbBootImageHeader*>(boot_image_.data()), &h); - - EXPECT_EQ(0, ::strcmp(cmdline.c_str(), - reinterpret_cast<const char*>(h.kernel_cmdline))); -} - -TEST_F(BvbToolTest, CheckAddresses) -{ - GenerateBootImage("SHA256_RSA2048", "", 0, - base::FilePath("test/testkey_rsa2048.pem"), - "--kernel_addr 0x42 --initrd_addr 43"); - - BvbBootImageHeader h; - bvb_boot_image_header_to_host_byte_order( - reinterpret_cast<BvbBootImageHeader*>(boot_image_.data()), &h); - - EXPECT_EQ(0x42U, h.kernel_addr); - EXPECT_EQ(43U, h.initrd_addr); -} - -TEST_F(BvbToolTest, CheckProperties) -{ - GenerateBootImage("SHA256_RSA2048", "", 0, - base::FilePath("test/testkey_rsa2048.pem"), - "--prop foo:brillo " - "--prop bar:chromeos " - "--prop prisoner:24601 " - "--prop hexnumber:0xcafe " - "--prop hexnumber_capital:0xCAFE " - "--prop large_hexnumber:0xfedcba9876543210 " - "--prop larger_than_uint64:0xfedcba98765432101 " - "--prop almost_a_number:423x " - "--prop_from_file blob:test/small_blob.bin " - ); - - BvbBootImageHeader h; - bvb_boot_image_header_to_host_byte_order( - reinterpret_cast<BvbBootImageHeader*>(boot_image_.data()), &h); - - EXPECT_EQ(BVB_VERIFY_RESULT_OK, - bvb_verify_boot_image(boot_image_.data(), boot_image_.size(), - nullptr, nullptr)); - - const char *s; - size_t len; - uint64_t val; - - // Basic. - s = bvb_lookup_property(boot_image_.data(), boot_image_.size(), - "foo", 0, &len); - EXPECT_EQ(0, strcmp(s, "brillo")); - EXPECT_EQ(6U, len); - s = bvb_lookup_property(boot_image_.data(), boot_image_.size(), - "bar", 0, &len); - EXPECT_EQ(0, strcmp(s, "chromeos")); - EXPECT_EQ(8U, len); - s = bvb_lookup_property(boot_image_.data(), boot_image_.size(), - "non-existant", 0, &len); - EXPECT_EQ(0U, len); - EXPECT_EQ(NULL, s); - - // Numbers. - EXPECT_NE(0, bvb_lookup_property_uint64( - boot_image_.data(), boot_image_.size(), "prisoner", 0, &val)); - EXPECT_EQ(24601U, val); - - EXPECT_NE(0, bvb_lookup_property_uint64( - boot_image_.data(), boot_image_.size(), "hexnumber", 0, &val)); - EXPECT_EQ(0xcafeU, val); - - EXPECT_NE(0, bvb_lookup_property_uint64( - boot_image_.data(), boot_image_.size(), "hexnumber_capital", 0, &val)); - EXPECT_EQ(0xcafeU, val); - - EXPECT_NE(0, bvb_lookup_property_uint64( - boot_image_.data(), boot_image_.size(), "large_hexnumber", 0, &val)); - EXPECT_EQ(0xfedcba9876543210U, val); - - // We could catch overflows and return an error ... but we currently don't. - EXPECT_NE(0, bvb_lookup_property_uint64( - boot_image_.data(), boot_image_.size(), "larger_than_uint64", 0, &val)); - EXPECT_EQ(0xedcba98765432101U, val); - - // Number-parsing failures. - EXPECT_EQ(0, bvb_lookup_property_uint64( - boot_image_.data(), boot_image_.size(), "foo", 0, &val)); - - EXPECT_EQ(0, bvb_lookup_property_uint64( - boot_image_.data(), boot_image_.size(), "almost_a_number", 0, &val)); - - // Blobs. - // - // test/small_blob.bin is 21 byte file full of NUL-bytes except for - // the string "brillo ftw!" at index 2 and '\n' at the last byte. - s = bvb_lookup_property(boot_image_.data(), boot_image_.size(), - "blob", 0, &len); - EXPECT_EQ(21U, len); - EXPECT_EQ(0, memcmp(s, "\0\0", 2)); - EXPECT_EQ(0, memcmp(s + 2, "brillo ftw!", 11)); - EXPECT_EQ(0, memcmp(s + 13, "\0\0\0\0\0\0\0", 7)); - EXPECT_EQ('\n', s[20]); -} - -TEST_F(BvbToolTest, CheckRollbackIndex) -{ - uint64_t rollback_index = 42; - GenerateBootImage("SHA256_RSA2048", "", rollback_index, - base::FilePath("test/testkey_rsa2048.pem")); - - BvbBootImageHeader h; - bvb_boot_image_header_to_host_byte_order( - reinterpret_cast<BvbBootImageHeader*>(boot_image_.data()), &h); - - EXPECT_EQ(rollback_index, h.rollback_index); -} - -TEST_F(BvbToolTest, CheckPubkeyReturned) -{ - GenerateBootImage("SHA256_RSA2048", "", 0, - base::FilePath("test/testkey_rsa2048.pem")); - - const uint8_t* pubkey = NULL; - size_t pubkey_length = 0; - - EXPECT_EQ(BVB_VERIFY_RESULT_OK, - bvb_verify_boot_image(boot_image_.data(), boot_image_.size(), - &pubkey, &pubkey_length)); - - BvbBootImageHeader h; - bvb_boot_image_header_to_host_byte_order( - reinterpret_cast<BvbBootImageHeader*>(boot_image_.data()), &h); - - EXPECT_EQ(pubkey_length, h.public_key_size); - - const uint8_t* expected_pubkey = boot_image_.data() + - sizeof(BvbBootImageHeader) + - h.authentication_data_block_size + - h.public_key_offset; - EXPECT_EQ(pubkey, expected_pubkey); -} - -TEST_F(BvbToolTest, Info) -{ - GenerateBootImage("SHA256_RSA2048", "foobar=cmdline test=42", 0, - base::FilePath("test/testkey_rsa2048.pem"), - "--prop foo:brillo " - "--prop bar:chromeos " - "--prop prisoner:24601 " - "--prop hexnumber:0xcafe " - "--prop hexnumber_capital:0xCAFE " - "--prop large_hexnumber:0xfedcba9876543210 " - "--prop larger_than_uint64:0xfedcba98765432101 " - "--prop almost_a_number:423x " - "--prop_from_file blob:test/small_blob.bin " - "--prop_from_file large_blob:test/dummy_kernel.bin"); - - base::FilePath info_path = testdir_.Append("info_output.txt"); - EXPECT_COMMAND(0, - "./bvbtool info_boot_image --image %s --output %s", - boot_image_path_.value().c_str(), - info_path.value().c_str()); - - std::string info_data; - ASSERT_TRUE(base::ReadFileToString(info_path, &info_data)); - - ASSERT_EQ( - "Boot Image version: 1.0\n" - "Header Block: 8192 bytes\n" - "Authentication Block: 4096 bytes\n" - "Auxilary Block: 70080 bytes\n" - "Payload Block: 196608 bytes\n" - "Algorithm: SHA256_RSA2048\n" - "Rollback Index: 0\n" - "Kernel: 65536 bytes\n" - "Initrd: 131072 bytes\n" - "Kernel Load Address: 0x10008000\n" - "Initrd Load Address: 0x11000000\n" - "Kernel Cmdline: foobar=cmdline test=42\n" - "Properties:\n" - " foo: 'brillo'\n" - " bar: 'chromeos'\n" - " prisoner: '24601'\n" - " hexnumber: '0xcafe'\n" - " hexnumber_capital: '0xCAFE'\n" - " large_hexnumber: '0xfedcba9876543210'\n" - " larger_than_uint64: '0xfedcba98765432101'\n" - " almost_a_number: '423x'\n" - " blob: '\\x00\\x00brillo " - "ftw!\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\n'\n" - " large_blob: (65536 bytes)\n", - info_data); -} - -TEST_F(BvbToolTest, ImageHashes) { - // test/dummy_rootfs.bin is a 1,049,600 byte (1025 Kib) file. - EXPECT_COMMAND( - 0, "cp test/dummy_rootfs.bin %s/rootfs.bin", testdir_.value().c_str()); - EXPECT_COMMAND( - 0, - "./bvbtool add_image_hashes --salt d00df00d --image %s/rootfs.bin", - testdir_.value().c_str()); - - // We don't want to impose the requirement of having the - // veritysetup(1) command available on builders but leave it here so - // it can be manually enabled when making changes. - // - // (The fact that we end up with the correct root hash and tree size - // demonstrates correctness sufficiently well.) - if (false) { - EXPECT_COMMAND(0, - "veritysetup --no-superblock --format=1 --hash=sha1 " - "--data-block-size=4096 --hash-block-size=4096 " - "--salt=d00df00d " - "--data-blocks=257 " - "--hash-offset=1052672 " - "verify " - "%s/rootfs.bin %s/rootfs.bin " - "d0e3b9865f45fc66c1a64796dae1666647103f72", - testdir_.value().c_str(), - testdir_.value().c_str()); - } - - base::FilePath info_path = testdir_.Append("info_output.txt"); - EXPECT_COMMAND( - 0, - "./bvbtool info_image_hashes --image %s/rootfs.bin --output %s", - testdir_.value().c_str(), - info_path.value().c_str()); - - std::string info_data; - ASSERT_TRUE(base::ReadFileToString(info_path, &info_data)); - - // Note that image size is rounded up to block size (4096). - ASSERT_EQ( - "Footer version: 1.0\n" - "Version of dm-verity: 1\n" - "Image Size: 1052672 bytes\n" - "Tree Offset: 1052672\n" - "Tree Size: 16384 bytes\n" - "Data Block Size: 4096 bytes\n" - "Hash Block Size: 4096 bytes\n" - "Hash Algorithm: sha1\n" - "Salt: d00df00d\n" - "Root Hash: d0e3b9865f45fc66c1a64796dae1666647103f72\n", - info_data); - - // Check that bvbtool injects the directives for setting up the - // rootfs for the given integrity-checked file system BEFORE the - // user-supplied command-line. - GenerateBootImage("SHA256_RSA2048", - "some_option=42", - 0, - base::FilePath("test/testkey_rsa2048.pem"), - base::StringPrintf("--rootfs_with_hashes %s/rootfs.bin", - testdir_.value().c_str())); - BvbBootImageHeader h; - bvb_boot_image_header_to_host_byte_order( - reinterpret_cast<BvbBootImageHeader*>(boot_image_.data()), &h); - - EXPECT_EQ( - "dm=\"1 vroot none ro 1," - "0 2056 verity 1 PARTUUID=$(ANDROID_SYSTEM_PARTUUID) " - "PARTUUID=$(ANDROID_SYSTEM_PARTUUID) 4096 4096 257 257 sha1 " - "d0e3b9865f45fc66c1a64796dae1666647103f72 d00df00d\" " - "some_option=42", - std::string(reinterpret_cast<const char*>(h.kernel_cmdline))); -} diff --git a/refimpl/bvb_boot_image_header.h b/refimpl/bvb_boot_image_header.h deleted file mode 100644 index 8f90e5e..0000000 --- a/refimpl/bvb_boot_image_header.h +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#if !defined (BVB_INSIDE_BVB_REFIMPL_H) && !defined (BVB_REFIMPL_COMPILATION) -#error "Never include this file directly, include bvb_refimpl.h instead." -#endif - -#ifndef BVB_BOOT_IMAGE_HEADER_H_ -#define BVB_BOOT_IMAGE_HEADER_H_ - -#include "bvb_sysdeps.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Size of the Brillo boot image header. */ -#define BVB_BOOT_IMAGE_HEADER_SIZE 8192 - -/* Magic for the Brillo boot image header. */ -#define BVB_MAGIC "BVB0" -#define BVB_MAGIC_LEN 4 - -/* The current MAJOR and MINOR versions used - keep in sync with bvbtool. */ -#define BVB_MAJOR_VERSION 1 -#define BVB_MINOR_VERSION 0 - -/* Maximum number of bytes in the kernel command-line before substitution. */ -#define BVB_KERNEL_CMDLINE_MAX_LEN 4096 - -/* Algorithms that can be used in the Brillo boot image for - * verification. An algorithm consists of a hash type and a signature - * type. - * - * The data used to calculate the hash is the four blocks mentioned in - * the documentation for |BvbBootImageHeader| except for the data in - * the "Authentication data" block. - * - * For signatures with RSA keys, PKCS v1.5 padding is used. The public - * key data is stored in the auxilary data block, see - * |BvbRSAPublicKeyHeader| for the serialization format. - * - * Each algorithm type is described below: - * - * BVB_ALGORITHM_TYPE_NONE: There is no hash, no signature of the - * data, and no public key. The data cannot be verified. The fields - * |hash_size|, |signature_size|, and |public_key_size| must be zero. - * - * BVB_ALGORITHM_TYPE_SHA256_RSA2048: The hash function used is - * SHA-256, resulting in 32 bytes of hash digest data. This hash is - * signed with a 2048-bit RSA key. The field |hash_size| must be 32, - * |signature_size| must be 256, and the public key data must have - * |key_num_bits| set to 2048. - * - * BVB_ALGORITHM_TYPE_SHA256_RSA4096: Like above, but only with - * a 4096-bit RSA key and |signature_size| set to 512. - * - * BVB_ALGORITHM_TYPE_SHA256_RSA8192: Like above, but only with - * a 8192-bit RSA key and |signature_size| set to 1024. - * - * BVB_ALGORITHM_TYPE_SHA512_RSA2048: The hash function used is - * SHA-512, resulting in 64 bytes of hash digest data. This hash is - * signed with a 2048-bit RSA key. The field |hash_size| must be 64, - * |signature_size| must be 256, and the public key data must have - * |key_num_bits| set to 2048. - * - * BVB_ALGORITHM_TYPE_SHA512_RSA4096: Like above, but only with - * a 4096-bit RSA key and |signature_size| set to 512. - * - * BVB_ALGORITHM_TYPE_SHA512_RSA8192: Like above, but only with - * a 8192-bit RSA key and |signature_size| set to 1024. - */ -typedef enum { - BVB_ALGORITHM_TYPE_NONE, - BVB_ALGORITHM_TYPE_SHA256_RSA2048, - BVB_ALGORITHM_TYPE_SHA256_RSA4096, - BVB_ALGORITHM_TYPE_SHA256_RSA8192, - BVB_ALGORITHM_TYPE_SHA512_RSA2048, - BVB_ALGORITHM_TYPE_SHA512_RSA4096, - BVB_ALGORITHM_TYPE_SHA512_RSA8192, - _BVB_ALGORITHM_NUM_TYPES -} BvbAlgorithmType; - -/* The header for a serialized RSA public key. - * - * The size of the key is given by |key_num_bits|, for example 2048 - * for a RSA-2048 key. By definition, a RSA public key is the pair (n, - * e) where |n| is the modulus (which can be represented in - * |key_num_bits| bits) and |e| is the public exponent. The exponent - * is not stored since it's assumed to always be 65537. - * - * To optimize verification, the key block includes two precomputed - * values, |n0inv| (fits in 32 bits) and |rr| and can always be - * represented in |key_num_bits|. - - * The value |n0inv| is the value -1/n[0] (mod 2^32). The value |rr| - * is (2^key_num_bits)^2 (mod n). - * - * Following this header is |key_num_bits| bits of |n|, then - * |key_num_bits| bits of |rr|. Both values are stored with most - * significant bit first. Each serialized number takes up - * |key_num_bits|/8 bytes. - * - * All fields in this struct are stored in network byte order when - * serialized. To generate a copy with fields swapped to native byte - * order, use the function bvb_rsa_public_key_header_to_host_byte_order(). - * - * The bvb_RSAVerify() function expects a key in this serialized - * format. - * - * The 'bvbtool extract_public_key' command can be used to generate a - * serialized RSA public key. - */ -typedef struct BvbRSAPublicKeyHeader { - uint32_t key_num_bits; - uint32_t n0inv; -} __attribute__((packed)) BvbRSAPublicKeyHeader; - -/* The header for a serialized property. - * - * Following this header is |key_num_bytes| bytes of key data, - * followed by a NUL byte, then |value_num_bytes| bytes of value data, - * followed by a NUL byte and then enough padding to make the combined - * size a multiple of 8. - * - * Headers with keys beginning with "brillo." are reserved for use in - * the Brillo project and must not be used by others. Well-known - * headers include - * - * brillo.device_tree: The property value is a device-tree blob. - */ -typedef struct BvbPropertyHeader { - uint64_t key_num_bytes; - uint64_t value_num_bytes; -} __attribute__((packed)) BvbPropertyHeader; - -/* Binary format for header of the boot image used in Brillo. - * - * The Brillo boot image consists of four blocks: - * - * +-----------------------------------------+ - * | Header data - fixed size | - * +-----------------------------------------+ - * | Authentication data - variable size | - * +-----------------------------------------+ - * | Auxilary data - variable size | - * +-----------------------------------------+ - * | Payload data - variable size | - * +-----------------------------------------+ - * - * The "Header data" block is described by this struct and is always - * |BVB_BOOT_IMAGE_HEADER_SIZE| bytes long. - * - * The "Authentication data" block is |authentication_data_block_size| - * bytes long and contains the hash and signature used to authenticate - * the boot image. The type of the hash and signature is defined by - * the |algorithm_type| field. - * - * The "Auxilary data" is |auxilary_data_block_size| bytes long and - * contains the auxilary data including the public key used to make - * the signature and properties. - * - * The public key is at offset |public_key_offset| with size - * |public_key_size| in this block. The size of the public key data is - * defined by the |algorithm_type| field. The format of the public key - * data is described in the |BvbRSAPublicKeyHeader| struct. - * - * The properties starts at |properties_offset| from the beginning of - * the "Auxliary Data" block and take up |properties_size| bytes. Each - * property is stored as |BvbPropertyHeader| with key, NUL, value, - * NUL, and padding following. The number of properties can be - * determined by walking this data until |properties_size| is - * exhausted. - * - * The "Payload data" block is |payload_data_block_size| bytes - * long. This is where the kernel, initramfs, and other data is - * stored. - * - * The size of each of the "Authentication data" and "Auxilary data" - * blocks must be divisible by 64. This is to ensure proper alignment. - * - * Properties are free-form key/value pairs stored in a part of the - * boot partition subject to the same integrity checks as the rest of - * the boot partition. See the documentation for |BvbPropertyHeader| - * for well-known properties. See bvb_property_lookup() and - * bvb_property_lookup_uint64() for convenience functions to look up - * property values. - * - * This struct is versioned, see the |header_version_major| and - * |header_version_minor| fields. Compatibility is guaranteed only - * within the same major version. - * - * All fields are stored in network byte order when serialized. To - * generate a copy with fields swapped to native byte order, use the - * function bvb_boot_image_header_to_host_byte_order(). - * - * Before reading and/or using any of this data, you MUST verify it - * using bvb_verify_boot_image() and reject it unless it's signed by a - * known good public key. - */ -typedef struct BvbBootImageHeader { - /* 0: Four bytes equal to "BVB0" (BVB_MAGIC). */ - uint8_t magic[BVB_MAGIC_LEN]; - /* 4: The major version of the boot image header. */ - uint32_t header_version_major; - /* 8: The minor version of the boot image header. */ - uint32_t header_version_minor; - - /* 12: The size of the signature block. */ - uint64_t authentication_data_block_size; - /* 20: The size of the public key block. */ - uint64_t auxilary_data_block_size; - /* 28: The size of the payload block. */ - uint64_t payload_data_block_size; - - /* 36: The verification algorithm used, see |BvbAlgorithmType| enum. */ - uint32_t algorithm_type; - - /* 40: Offset into the "Authentication data" block of hash data. */ - uint64_t hash_offset; - /* 48: Length of the hash data. */ - uint64_t hash_size; - - /* 56: Offset into the "Authentication data" block of signature data. */ - uint64_t signature_offset; - /* 64: Length of the signature data. */ - uint64_t signature_size; - - /* 72: Offset into the "Auxilary data" block of public key data. */ - uint64_t public_key_offset; - /* 80: Length of the public key data. */ - uint64_t public_key_size; - - /* 88: Offset into the "Auxilary data" block of property data. */ - uint64_t properties_offset; - /* 96: Length of property data. */ - uint64_t properties_size; - - /* 104: The rollback index which can be used to prevent rollback to - * older versions. - */ - uint64_t rollback_index; - - /* 112: Offset into the "Payload data" block of kernel image. */ - uint64_t kernel_offset; - /* 120: Length of the kernel image. */ - uint64_t kernel_size; - - /* 128: Offset into the "Payload data" block of initial ramdisk. */ - uint64_t initrd_offset; - /* 136: Length of the initial ramdisk. */ - uint64_t initrd_size; - - /* 144: Physical kernel load address. */ - uint64_t kernel_addr; - - /* 152: Physical initial ramdisk load address. */ - uint64_t initrd_addr; - - /* 160: The NUL-terminated kernel command-line string, passed to the - * Linux kernel. - * - * Limited substitution will be performed by the boot loader - the - * following variables are supported: - * - * $(ANDROID_SYSTEM_PARTUUID) - this place-holder will be replaced - * with the image UUID/GUID of the corresponding system_X image of - * the booted slot (where _X is the slot to boot). - * - * $(ANDROID_BOOT_PARTUUID) - this place-holder will be replaced - * with the image UUID/GUID of the boot image of the booted slot. - * - * For example, the snippet "root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)" - * in this field can be used to instruct the Linux kernel to use the - * system image in the booted slot as the root filesystem. - */ - uint8_t kernel_cmdline[BVB_KERNEL_CMDLINE_MAX_LEN]; - - /* 4256: Padding to ensure struct is size BVB_BOOT_IMAGE_HEADER_SIZE - * bytes. This must be set to zeroes. - */ - uint8_t reserved[3936]; -} __attribute__((packed)) BvbBootImageHeader; - -#ifdef __cplusplus -} -#endif - -#endif /* BVB_BOOT_IMAGE_HEADER_H_ */ diff --git a/refimpl/bvb_property.c b/refimpl/bvb_property.c deleted file mode 100644 index 8b3ac3d..0000000 --- a/refimpl/bvb_property.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "bvb_boot_image_header.h" -#include "bvb_util.h" - -const char* bvb_lookup_property(const uint8_t* image_data, size_t image_size, - const char* key, size_t key_size, - size_t* out_value_size) { - const BvbBootImageHeader *header = NULL; - const char* ret = NULL; - const uint8_t* image_end; - const uint8_t* prop_start; - const uint8_t* prop_end; - const uint8_t* p; - - if (out_value_size != NULL) - *out_value_size = 0; - - if (image_data == NULL) { - bvb_debug("image_data is NULL\n."); - goto out; - } - - if (key == NULL) { - bvb_debug("key is NULL\n."); - goto out; - } - - if (image_size < sizeof(BvbBootImageHeader)) { - bvb_debug("Length is smaller than header.\n"); - goto out; - } - - // Ensure magic is correct. - if (bvb_memcmp(image_data, BVB_MAGIC, BVB_MAGIC_LEN) != 0) { - bvb_debug("Magic is incorrect.\n"); - goto out; - } - - if (key_size == 0) - key_size = bvb_strlen(key); - - // Careful, not byteswapped - also ensure it's aligned properly. - bvb_assert_word_aligned(image_data); - header = (const BvbBootImageHeader *) image_data; - image_end = image_data + image_size; - - prop_start = image_data + sizeof(BvbBootImageHeader) + - bvb_be64toh(header->authentication_data_block_size) + - bvb_be64toh(header->properties_offset); - - prop_end = prop_start + bvb_be64toh(header->properties_size); - - if (prop_start < image_data || prop_start > image_end || - prop_end < image_data || prop_end > image_end || - prop_end < prop_start) { - bvb_debug("Properties not inside passed-in data.\n"); - goto out; - } - - for (p = prop_start; p < prop_end; ) { - const BvbPropertyHeader *ph = (const BvbPropertyHeader *) p; - bvb_assert_word_aligned(ph); - uint64_t key_nb = bvb_be64toh(ph->key_num_bytes); - uint64_t value_nb = bvb_be64toh(ph->value_num_bytes); - uint64_t total = sizeof(BvbPropertyHeader) + 2 /* NUL bytes */ - + key_nb + value_nb; - uint64_t remainder = total % 8; - - if (remainder != 0) - total += 8 - remainder; - - if (total + p < prop_start || total + p > prop_end) { - bvb_debug("Invalid data in properties array.\n"); - goto out; - } - if (p[sizeof(BvbPropertyHeader) + key_nb] != 0) { - bvb_debug("No terminating NUL byte in key.\n"); - goto out; - } - if (p[sizeof(BvbPropertyHeader) + key_nb + 1 + value_nb] != 0) { - bvb_debug("No terminating NUL byte in value.\n"); - goto out; - } - if (key_size == key_nb) { - if (bvb_memcmp(p + sizeof(BvbPropertyHeader), key, key_size) == 0) { - ret = (const char *) (p + sizeof(BvbPropertyHeader) + key_nb + 1); - if (out_value_size != NULL) - *out_value_size = value_nb; - goto out; - } - } - p += total; - } - -out: - return ret; -} - -int bvb_lookup_property_uint64(const uint8_t* image_data, size_t image_size, - const char* key, size_t key_size, - uint64_t* out_value) { - const char *value; - int ret = 0; - uint64_t parsed_val; - int base; - int n; - - value = bvb_lookup_property(image_data, image_size, key, key_size, NULL); - if (value == NULL) - goto out; - - base = 10; - if (bvb_memcmp(value, "0x", 2) == 0) { - base = 16; - value += 2; - } - - parsed_val = 0; - for (n = 0; value[n] != '\0'; n++) { - int c = value[n]; - int digit; - - parsed_val *= base; - - switch (base) { - case 10: - if (c >= '0' && c <= '9') { - digit = c - '0'; - } else { - bvb_debug("Invalid digit.\n"); - goto out; - } - break; - - case 16: - if (c >= '0' && c <= '9') { - digit = c - '0'; - } else if (c >= 'a' && c <= 'f') { - digit = c - 'a' + 10; - } else if (c >= 'A' && c <= 'F') { - digit = c - 'A' + 10; - } else { - bvb_debug("Invalid digit.\n"); - goto out; - } - break; - - default: - goto out; - } - - parsed_val += digit; - } - - ret = 1; - if (out_value != NULL) - *out_value = parsed_val; - -out: - return ret; -} diff --git a/refimpl/bvb_property.h b/refimpl/bvb_property.h deleted file mode 100644 index d105e3e..0000000 --- a/refimpl/bvb_property.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#if !defined (BVB_INSIDE_BVB_REFIMPL_H) && !defined (BVB_REFIMPL_COMPILATION) -#error "Never include this file directly, include bvb_refimpl.h instead." -#endif - -#ifndef BVB_PROPERTY_H_ -#define BVB_PROPERTY_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "bvb_boot_image_header.h" - -/* Convenience function for looking up the value for a property with - * name |key| in a Brillo boot image. If |key| is NUL-terminated, - * |key_size| may be set to 0. - * - * The |image_data| parameter must be a pointer to a Brillo Boot Image - * of size |image_size|. - * - * This function returns a pointer to the value inside the passed-in - * image or NULL if not found. Note that the value is always - * guaranteed to be followed by a NUL byte. - * - * If the value was found and |out_value_size| is not NULL, the size - * of the value is returned there. - * - * This function is O(n) in number of properties so if you need to - * look up a lot of values, you may want to build a more efficient - * lookup-table by manually walking all properties yourself. - * - * Before using this function, you MUST verify |image_data| with - * bvb_verify_boot_image() and reject it unless it's signed by a known - * good public key. - */ -const char* bvb_lookup_property(const uint8_t* image_data, size_t image_size, - const char* key, size_t key_size, - size_t* out_value_size); - -/* Like bvb_lookup_property() but parses the value as an unsigned - * 64-bit integer. Both decimal and hexadecimal representations - * (e.g. "0x2a") are supported. Returns 0 on failure and non-zero on - * success. On success, the parsed value is returned in |out_value|. - */ -int bvb_lookup_property_uint64(const uint8_t* image_data, size_t image_size, - const char* key, size_t key_size, - uint64_t* out_value); - -#ifdef __cplusplus -} -#endif - -#endif /* BVB_PROPERTY_H_ */ diff --git a/refimpl/bvb_refimpl.h b/refimpl/bvb_refimpl.h deleted file mode 100644 index e65ad09..0000000 --- a/refimpl/bvb_refimpl.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef BVB_REFIMPL_H_ -#define BVB_REFIMPL_H_ - -/* The BVB_INSIDE_BVB_REFIMPL_H preprocessor symbol is used to enforce - * library users to include only this file. All public interfaces, and - * only public interfaces, must be included here. - */ - -#define BVB_INSIDE_BVB_REFIMPL_H -#include "bvb_boot_image_header.h" -#include "bvb_property.h" -#include "bvb_sysdeps.h" -#include "bvb_util.h" -#include "bvb_verify.h" -#undef BVB_INSIDE_BVB_REFIMPL_H - -#endif /* BVB_REFIMPL_H_ */ diff --git a/refimpl/bvb_rsa.c b/refimpl/bvb_rsa.c deleted file mode 100644 index 50517b8..0000000 --- a/refimpl/bvb_rsa.c +++ /dev/null @@ -1,276 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* Copyright (c) 2011 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 "bvb_rsa.h" -#include "bvb_sha.h" -#include "bvb_util.h" - -typedef struct Key { - unsigned int len; /* Length of n[] in number of uint32_t */ - uint32_t n0inv; /* -1 / n[0] mod 2^32 */ - uint32_t* n; /* modulus as little endian array */ - uint32_t* rr; /* R^2 as little endian array */ -} Key; - -Key* parse_key_data(const uint8_t* data, size_t length) { - BvbRSAPublicKeyHeader h; - Key* key = NULL; - size_t expected_length; - unsigned int i; - const uint8_t* n; - const uint8_t *rr; - - bvb_rsa_public_key_header_to_host_byte_order( - (const BvbRSAPublicKeyHeader *) data, &h); - - if (!(h.key_num_bits == 2048 || - h.key_num_bits == 4096 || - h.key_num_bits == 8192)) { - bvb_debug("Unexpected key length.\n"); - goto fail; - } - - expected_length = sizeof(BvbRSAPublicKeyHeader) + 2*h.key_num_bits/8; - if (length != expected_length) { - bvb_debug("Key does not match expected length.\n"); - goto fail; - } - - n = data + sizeof(BvbRSAPublicKeyHeader); - rr = data + sizeof(BvbRSAPublicKeyHeader) + h.key_num_bits/8; - - // Store n and rr following the key header so we only have to do one - // allocation. - key = (Key *) (bvb_malloc(sizeof(Key) + 2*h.key_num_bits/8)); - if (key == NULL) - goto fail; - - key->len = h.key_num_bits/32; - key->n0inv = h.n0inv; - key->n = (uint32_t *) (key + 1); // Skip ahead sizeof(Key) bytes. - key->rr = key->n + key->len; - - // Crypto-code below (modpowF4() and friends) expects the key in - // little-endian format (rather than the format we're storing the - // key in), so convert it. - for (i = 0; i < key->len; i++) { - key->n[i] = bvb_be32toh(((uint32_t *) n)[key->len - i - 1]); - key->rr[i] = bvb_be32toh(((uint32_t *) rr)[key->len - i - 1]); - } - return key; - -fail: - if (key != NULL) - bvb_free(key); - return NULL; -} - -void free_parsed_key(Key* key) { - bvb_free(key); -} - -/* a[] -= mod */ -static void subM(const Key* key, uint32_t* a) { - int64_t A = 0; - uint32_t i; - for (i = 0; i < key->len; ++i) { - A += (uint64_t)a[i] - key->n[i]; - a[i] = (uint32_t)A; - A >>= 32; - } -} - -/* return a[] >= mod */ -static int geM(const Key* key, uint32_t *a) { - uint32_t i; - for (i = key->len; 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 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->len; ++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 Key* key, - uint32_t* c, - uint32_t* a, - uint32_t* b) { - uint32_t i; - for (i = 0; i < key->len; ++i) { - c[i] = 0; - } - for (i = 0; i < key->len; ++i) { - montMulAdd(key, c, a[i], b); - } -} - -/* In-place public exponentiation. (65537} - * Input and output big-endian byte array in inout. - */ -static void modpowF4(const Key *key, - uint8_t* inout) { - uint32_t* a = (uint32_t*) bvb_malloc(key->len * sizeof(uint32_t)); - uint32_t* aR = (uint32_t*) bvb_malloc(key->len * sizeof(uint32_t)); - uint32_t* aaR = (uint32_t*) bvb_malloc(key->len * sizeof(uint32_t)); - if (a == NULL || aR == NULL || aaR == NULL) - goto out; - - 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->len; ++i) { - uint32_t tmp = - (inout[((key->len - 1 - i) * 4) + 0] << 24) | - (inout[((key->len - 1 - i) * 4) + 1] << 16) | - (inout[((key->len - 1 - i) * 4) + 2] << 8) | - (inout[((key->len - 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 (geM(key, aaa)) { - subM(key, aaa); - } - - /* Convert to bigendian byte array */ - for (i = (int)key->len - 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); - } - -out: - if (a != NULL) - bvb_free(a); - if (aR != NULL) - bvb_free(aR); - if (aaR != NULL) - bvb_free(aaR); -} - -/* Verify a RSA PKCS1.5 signature against an expected hash. - * Returns 0 on failure, 1 on success. - */ -int bvb_rsa_verify(const uint8_t* key, size_t key_num_bytes, - const uint8_t* sig, size_t sig_num_bytes, - const uint8_t* hash, size_t hash_num_bytes, - const uint8_t* padding, size_t padding_num_bytes) { - uint8_t* buf = NULL; - Key* parsed_key = NULL; - int success = 0; - - if (key == NULL || sig == NULL || hash == NULL || padding == NULL) { - bvb_debug("Invalid input.\n"); - goto out; - } - - parsed_key = parse_key_data(key, key_num_bytes); - if (parsed_key == NULL) { - bvb_debug("Error parsing key.\n"); - goto out; - } - - if (sig_num_bytes != (parsed_key->len * sizeof(uint32_t))) { - bvb_debug("Signature length does not match key length.\n"); - goto out; - } - - if (padding_num_bytes != sig_num_bytes - hash_num_bytes) { - bvb_debug("Padding length does not match hash and signature lengths.\n"); - goto out; - } - - buf = (uint8_t *) bvb_malloc(sig_num_bytes); - if (buf == NULL) { - bvb_debug("Error allocating %d bytes.\n", (int) sig_num_bytes); - goto out; - } - bvb_memcpy(buf, sig, sig_num_bytes); - - modpowF4(parsed_key, buf); - - /* Check padding bytes. - * - * Even though there are probably no timing issues here, we use - * bvb_safe_memcmp() just to be on the safe side. - */ - if (bvb_safe_memcmp(buf, padding, padding_num_bytes)) { - bvb_debug("Padding check failed.\n"); - goto out; - } - - /* Check hash. */ - if (bvb_safe_memcmp(buf + padding_num_bytes, hash, hash_num_bytes)) { - bvb_debug("Hash check failed.\n"); - goto out; - } - - success = 1; - -out: - if (parsed_key != NULL) - free_parsed_key(parsed_key); - if (buf != NULL) - bvb_free(buf); - return success; -} diff --git a/refimpl/bvb_rsa.h b/refimpl/bvb_rsa.h deleted file mode 100644 index 417ee35..0000000 --- a/refimpl/bvb_rsa.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* Copyright (c) 2011 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. - */ - -#ifdef BVB_INSIDE_BVB_REFIMPL_H -#error "You can't include bvb_rsa.h in the public header bvb_refimpl.h." -#endif - -#ifndef BVB_REFIMPL_COMPILATION -#error "Never include this file, it may only be used from internal bvb code." -#endif - -#ifndef BVB_RSA_H_ -#define BVB_RSA_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "bvb_sysdeps.h" - -/* Size of a RSA-2048 signature. */ -#define BVB_RSA2048_NUM_BYTES 256 - -/* Size of a RSA-4096 signature. */ -#define BVB_RSA4096_NUM_BYTES 512 - -/* Size of a RSA-8192 signature. */ -#define BVB_RSA8192_NUM_BYTES 1024 - -/* Using the key given by |key_header|, verify a RSA signature |sig| - * of length |sig_num_bytes| against an expected |hash| of length - * |hash_num_bytes|. The padding to expect must be passed in using - * |padding| of length |padding_num_bytes|. - * - * The data in |key| must match the format defined in - * |BvbRSAPublicKeyHeader|, including the two large numbers - * following. The |key_num_bytes| must be the size of the entire - * serialized key. - * - * Returns zero if verification fails, non-zero otherwise. - */ -int bvb_rsa_verify(const uint8_t* key, size_t key_num_bytes, - const uint8_t* sig, size_t sig_num_bytes, - const uint8_t* hash, size_t hash_num_bytes, - const uint8_t* padding, size_t padding_num_bytes); - -#ifdef __cplusplus -} -#endif - -#endif /* BVB_RSA_H_ */ diff --git a/refimpl/bvb_sha.h b/refimpl/bvb_sha.h deleted file mode 100644 index 8f8efd7..0000000 --- a/refimpl/bvb_sha.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -#ifdef BVB_INSIDE_BVB_REFIMPL_H -#error "You can't include bvb_sha.h in the public header bvb_refimpl.h." -#endif - -#ifndef BVB_REFIMPL_COMPILATION -#error "Never include this file, it may only be used from internal bvb code." -#endif - -#ifndef BVB_SHA_H_ -#define BVB_SHA_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "bvb_sysdeps.h" - -/* Size in bytes of a SHA-256 digest. */ -#define BVB_SHA256_DIGEST_SIZE 32 - -/* Block size in bytes of a SHA-256 digest. */ -#define BVB_SHA256_BLOCK_SIZE 64 - -/* Size in bytes of a SHA-512 digest. */ -#define BVB_SHA512_DIGEST_SIZE 64 - -/* Block size in bytes of a SHA-512 digest. */ -#define BVB_SHA512_BLOCK_SIZE 128 - -/* Data structure used for SHA-256. */ -typedef struct { - uint32_t h[8]; - uint32_t tot_len; - uint32_t len; - uint8_t block[2 * BVB_SHA256_BLOCK_SIZE]; - uint8_t buf[BVB_SHA256_DIGEST_SIZE]; /* Used for storing the final digest. */ -} BvbSHA256Ctx; - -/* Data structure used for SHA-512. */ -typedef struct { - uint64_t h[8]; - uint32_t tot_len; - uint32_t len; - uint8_t block[2 * BVB_SHA512_BLOCK_SIZE]; - uint8_t buf[BVB_SHA512_DIGEST_SIZE]; /* Used for storing the final digest. */ -} BvbSHA512Ctx; - -/* Initializes the SHA-256 context. */ -void bvb_sha256_init(BvbSHA256Ctx* ctx); - -/* Updates the SHA-256 context with |len| bytes from |data|. */ -void bvb_sha256_update(BvbSHA256Ctx* ctx, const uint8_t* data, uint32_t len); - -/* Returns the SHA-256 digest. */ -uint8_t* bvb_sha256_final(BvbSHA256Ctx* ctx); - -/* Initializes the SHA-512 context. */ -void bvb_sha512_init(BvbSHA512Ctx* ctx); - -/* Updates the SHA-512 context with |len| bytes from |data|. */ -void bvb_sha512_update(BvbSHA512Ctx* ctx, const uint8_t* data, uint32_t len); - -/* Returns the SHA-512 digest. */ -uint8_t* bvb_sha512_final(BvbSHA512Ctx* ctx); - -#ifdef __cplusplus -} -#endif - -#endif /* BVB_SHA_H_ */ diff --git a/refimpl/bvb_sha256.c b/refimpl/bvb_sha256.c deleted file mode 100644 index 53e5f6b..0000000 --- a/refimpl/bvb_sha256.c +++ /dev/null @@ -1,310 +0,0 @@ -/* 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 "bvb_sha.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 bvb_sha256_init(BvbSHA256Ctx *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->len = 0; - ctx->tot_len = 0; -} - - -static void SHA256_transform(BvbSHA256Ctx* ctx, const uint8_t* message, - unsigned int block_nb) { - 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 bvb_sha256_update(BvbSHA256Ctx* ctx, const uint8_t* data, uint32_t len) { - unsigned int block_nb; - unsigned int new_len, rem_len, tmp_len; - const uint8_t *shifted_data; - - tmp_len = BVB_SHA256_BLOCK_SIZE - ctx->len; - rem_len = len < tmp_len ? len : tmp_len; - - bvb_memcpy(&ctx->block[ctx->len], data, rem_len); - - if (ctx->len + len < BVB_SHA256_BLOCK_SIZE) { - ctx->len += len; - return; - } - - new_len = len - rem_len; - block_nb = new_len / BVB_SHA256_BLOCK_SIZE; - - shifted_data = data + rem_len; - - SHA256_transform(ctx, ctx->block, 1); - SHA256_transform(ctx, shifted_data, block_nb); - - rem_len = new_len % BVB_SHA256_BLOCK_SIZE; - - bvb_memcpy(ctx->block, &shifted_data[block_nb << 6], - rem_len); - - ctx->len = rem_len; - ctx->tot_len += (block_nb + 1) << 6; -} - -uint8_t* bvb_sha256_final(BvbSHA256Ctx* ctx) { - unsigned int block_nb; - unsigned int pm_len; - unsigned int len_b; -#ifndef UNROLL_LOOPS - int i; -#endif - - block_nb = (1 + ((BVB_SHA256_BLOCK_SIZE - 9) - < (ctx->len % BVB_SHA256_BLOCK_SIZE))); - - len_b = (ctx->tot_len + ctx->len) << 3; - pm_len = block_nb << 6; - - bvb_memset(ctx->block + ctx->len, 0, pm_len - ctx->len); - ctx->block[ctx->len] = 0x80; - UNPACK32(len_b, ctx->block + pm_len - 4); - - SHA256_transform(ctx, ctx->block, block_nb); - -#ifndef UNROLL_LOOPS - for (i = 0 ; i < 8; i++) { - UNPACK32(ctx->h[i], &ctx->buf[i << 2]); - } -#else - UNPACK32(ctx->h[0], &ctx->buf[ 0]); - UNPACK32(ctx->h[1], &ctx->buf[ 4]); - UNPACK32(ctx->h[2], &ctx->buf[ 8]); - UNPACK32(ctx->h[3], &ctx->buf[12]); - UNPACK32(ctx->h[4], &ctx->buf[16]); - UNPACK32(ctx->h[5], &ctx->buf[20]); - UNPACK32(ctx->h[6], &ctx->buf[24]); - UNPACK32(ctx->h[7], &ctx->buf[28]); -#endif /* !UNROLL_LOOPS */ - - return ctx->buf; -} diff --git a/refimpl/bvb_sha512.c b/refimpl/bvb_sha512.c deleted file mode 100644 index 0f1b385..0000000 --- a/refimpl/bvb_sha512.c +++ /dev/null @@ -1,333 +0,0 @@ -/* 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 "bvb_sha.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 bvb_sha512_init(BvbSHA512Ctx *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->len = 0; - ctx->tot_len = 0; -} - - -static void SHA512_transform(BvbSHA512Ctx* ctx, const uint8_t* message, - unsigned int block_nb) { - 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 bvb_sha512_update(BvbSHA512Ctx* ctx, const uint8_t* data, - uint32_t len) { - unsigned int block_nb; - unsigned int new_len, rem_len, tmp_len; - const uint8_t* shifted_data; - - tmp_len = BVB_SHA512_BLOCK_SIZE - ctx->len; - rem_len = len < tmp_len ? len : tmp_len; - - bvb_memcpy(&ctx->block[ctx->len], data, rem_len); - - if (ctx->len + len < BVB_SHA512_BLOCK_SIZE) { - ctx->len += len; - return; - } - - new_len = len - rem_len; - block_nb = new_len / BVB_SHA512_BLOCK_SIZE; - - shifted_data = data + rem_len; - - SHA512_transform(ctx, ctx->block, 1); - SHA512_transform(ctx, shifted_data, block_nb); - - rem_len = new_len % BVB_SHA512_BLOCK_SIZE; - - bvb_memcpy(ctx->block, &shifted_data[block_nb << 7], - rem_len); - - ctx->len = rem_len; - ctx->tot_len += (block_nb + 1) << 7; -} - -uint8_t* bvb_sha512_final(BvbSHA512Ctx* ctx) -{ - unsigned int block_nb; - unsigned int pm_len; - unsigned int len_b; - -#ifndef UNROLL_LOOPS_SHA512 - int i; -#endif - - block_nb = 1 + ((BVB_SHA512_BLOCK_SIZE - 17) - < (ctx->len % BVB_SHA512_BLOCK_SIZE)); - - len_b = (ctx->tot_len + ctx->len) << 3; - pm_len = block_nb << 7; - - bvb_memset(ctx->block + ctx->len, 0, pm_len - ctx->len); - ctx->block[ctx->len] = 0x80; - UNPACK32(len_b, ctx->block + pm_len - 4); - - SHA512_transform(ctx, ctx->block, block_nb); - -#ifdef UNROLL_LOOPS_SHA512 - UNPACK64(ctx->h[0], &ctx->buf[ 0]); - UNPACK64(ctx->h[1], &ctx->buf[ 8]); - UNPACK64(ctx->h[2], &ctx->buf[16]); - UNPACK64(ctx->h[3], &ctx->buf[24]); - UNPACK64(ctx->h[4], &ctx->buf[32]); - UNPACK64(ctx->h[5], &ctx->buf[40]); - UNPACK64(ctx->h[6], &ctx->buf[48]); - UNPACK64(ctx->h[7], &ctx->buf[56]); -#else - for (i = 0 ; i < 8; i++) - UNPACK64(ctx->h[i], &ctx->buf[i << 3]); -#endif /* UNROLL_LOOPS_SHA512 */ - - return ctx->buf; -} diff --git a/refimpl/bvb_sysdeps.h b/refimpl/bvb_sysdeps.h deleted file mode 100644 index a1f924e..0000000 --- a/refimpl/bvb_sysdeps.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#if !defined (BVB_INSIDE_BVB_REFIMPL_H) && !defined (BVB_REFIMPL_COMPILATION) -#error "Never include this file directly, include bvb_refimpl.h instead." -#endif - -#ifndef BVB_SYSDEPS_H_ -#define BVB_SYSDEPS_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/* Change these includes to match your platform to bring in the - * equivalent types available in a normal C runtime, as well as - * printf()-format specifiers such as PRIx64. - */ -#include <stddef.h> -#include <stdint.h> -#include <inttypes.h> - -#ifdef BVB_ENABLE_DEBUG -/* Aborts the program if |expr| is false. - * - * This has no effect unless BVB_ENABLE_DEBUG is defined. - */ -#define bvb_assert(expr) do { if (!(expr)) { \ - bvb_error("assert fail: %s at %s:%d\n", \ - #expr, __FILE__, __LINE__); }} while(0) -#else -#define bvb_assert(expr) -#endif - -/* Size in bytes used for word-alignment. - * - * Change this to match your architecture - must be a power of two. - */ -#define BVB_WORD_ALIGNMENT_SIZE 8 - -/* Aborts the program if |addr| is not word-aligned. - * - * This has no effect unless BVB_ENABLE_DEBUG is defined. - */ -#define bvb_assert_word_aligned(addr) \ - bvb_assert((((uintptr_t) addr) & (BVB_WORD_ALIGNMENT_SIZE-1)) == 0) - -/* Compare |n| bytes in |src1| and |src2|. - * - * Returns an integer less than, equal to, or greater than zero if the - * first |n| bytes of |src1| is found, respectively, to be less than, - * to match, or be greater than the first |n| bytes of |src2|. */ -int bvb_memcmp(const void* src1, const void* src2, size_t n); - -/* Copy |n| bytes from |src| to |dest|. */ -void* bvb_memcpy(void* dest, const void* src, size_t n); - -/* Set |n| bytes starting at |s| to |c|. Returns |dest|. */ -void* bvb_memset(void* dest, const int c, size_t n); - -/* Compare |n| bytes starting at |s1| with |s2| and return 0 if they - * match, 1 if they don't. Returns 0 if |n|==0, since no bytes - * mismatched. - * - * Time taken to perform the comparison is only dependent on |n| and - * not on the relationship of the match between |s1| and |s2|. - * - * Note that unlike bvb_memcmp(), this only indicates inequality, not - * whether |s1| is less than or greater than |s2|. - */ -int bvb_safe_memcmp(const void* s1, const void* s2, size_t n); - -#ifdef BVB_ENABLE_DEBUG -/* printf()-style function, used for diagnostics. - * - * This has no effect unless BVB_ENABLE_DEBUG is defined. - */ -void bvb_debug(const char* format, ...) __attribute__((format(printf, 1, 2))); -#else -static inline void bvb_debug(const char* format, ...) - __attribute__((format(printf, 1, 2))); -static inline void bvb_debug(const char* format, ...) {} -#endif - -/* Prints out a message (defined by |format|, printf()-style) and - * aborts the program or reboots the device. - * - * Unlike bvb_debug(), this function does not depend on BVB_ENABLE_DEBUG. - */ -void bvb_error(const char* format, ...) __attribute__((format(printf, 1, 2))); - -/* Allocates |size| bytes. Returns NULL if no memory is available, - * otherwise a pointer to the allocated memory. - * - * The memory is not initialized. - * - * The pointer returned is guaranteed to be word-aligned. - * - * The memory should be freed with bvb_free() when you are done with it. - */ -void* bvb_malloc(size_t size); - -/* Frees memory previously allocated with bvb_malloc(). */ -void bvb_free(void* ptr); - -/* Returns the lenght of |str|, excluding the terminating NUL-byte. */ -size_t bvb_strlen(const char* str); - -#ifdef __cplusplus -} -#endif - -#endif /* BVB_SYSDEPS_H_ */ diff --git a/refimpl/bvb_sysdeps_stub.c b/refimpl/bvb_sysdeps_stub.c deleted file mode 100644 index c7cd076..0000000 --- a/refimpl/bvb_sysdeps_stub.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <endian.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "bvb_sysdeps.h" - -int bvb_memcmp(const void* src1, const void* src2, size_t n) { - return memcmp(src1, src2, n); -} - -void* bvb_memcpy(void* dest, const void* src, size_t n) { - return memcpy(dest, src, (size_t)n); -} - -void* bvb_memset(void* dest, const int c, size_t n) { - return memset(dest, c, n); -} - -size_t bvb_strlen(const char* str) { - return strlen(str); -} - -int bvb_safe_memcmp(const void* s1, const void* s2, size_t n) { - const unsigned char* us1 = s1; - const unsigned char* us2 = s2; - int result = 0; - - if (0 == n) - return 0; - - /* - * Code snippet without data-dependent branch due to Nate Lawson - * (nate@root.org) of Root Labs. - */ - while (n--) - result |= *us1++ ^ *us2++; - - return result != 0; -} - -void bvb_error(const char* format, ...) { - va_list ap; - va_start(ap, format); - fprintf(stderr, "ERROR: "); - vfprintf(stderr, format, ap); - va_end(ap); - exit(1); -} - -#ifdef BVB_ENABLE_DEBUG -void bvb_debug(const char* format, ...) { - va_list ap; - va_start(ap, format); - fprintf(stderr, "DEBUG: "); - vfprintf(stderr, format, ap); - va_end(ap); -} -#endif - -void* bvb_malloc(size_t size) { - return malloc(size); -} - -void bvb_free(void* ptr) { - free(ptr); -} diff --git a/refimpl/bvb_util.c b/refimpl/bvb_util.c deleted file mode 100644 index fff8e96..0000000 --- a/refimpl/bvb_util.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -#include "bvb_util.h" - -uint32_t bvb_be32toh(uint32_t in) { - uint8_t* d = (uint8_t*) ∈ - uint32_t ret; - ret = ((uint32_t) d[0]) << 24; - ret |= ((uint32_t) d[1]) << 16; - ret |= ((uint32_t) d[2]) << 8; - ret |= ((uint32_t) d[3]); - return ret; -} - -uint64_t bvb_be64toh(uint64_t in) { - uint8_t* d = (uint8_t*) ∈ - uint64_t ret; - ret = ((uint64_t) d[0]) << 56; - ret |= ((uint64_t) d[1]) << 48; - ret |= ((uint64_t) d[2]) << 40; - ret |= ((uint64_t) d[3]) << 32; - ret |= ((uint64_t) d[4]) << 24; - ret |= ((uint64_t) d[5]) << 16; - ret |= ((uint64_t) d[6]) << 8; - ret |= ((uint64_t) d[7]); - return ret; -} - -void bvb_boot_image_header_to_host_byte_order(const BvbBootImageHeader* src, - BvbBootImageHeader* dest) { - bvb_memcpy(dest, src, sizeof(BvbBootImageHeader)); - - dest->header_version_major = bvb_be32toh(dest->header_version_major); - dest->header_version_minor = bvb_be32toh(dest->header_version_minor); - - dest->authentication_data_block_size = - bvb_be64toh(dest->authentication_data_block_size); - dest->auxilary_data_block_size = bvb_be64toh(dest->auxilary_data_block_size); - dest->payload_data_block_size = bvb_be64toh(dest->payload_data_block_size); - - dest->algorithm_type = bvb_be32toh(dest->algorithm_type); - - dest->hash_offset = bvb_be64toh(dest->hash_offset); - dest->hash_size = bvb_be64toh(dest->hash_size); - - dest->signature_offset = bvb_be64toh(dest->signature_offset); - dest->signature_size = bvb_be64toh(dest->signature_size); - - dest->public_key_offset = bvb_be64toh(dest->public_key_offset); - dest->public_key_size = bvb_be64toh(dest->public_key_size); - - dest->properties_offset = bvb_be64toh(dest->properties_offset); - dest->properties_size = bvb_be64toh(dest->properties_size); - - dest->rollback_index = bvb_be64toh(dest->rollback_index); - - dest->kernel_offset = bvb_be64toh(dest->kernel_offset); - dest->kernel_size = bvb_be64toh(dest->kernel_size); - - dest->initrd_offset = bvb_be64toh(dest->initrd_offset); - dest->initrd_size = bvb_be64toh(dest->initrd_size); - - dest->kernel_addr = bvb_be64toh(dest->kernel_addr); - dest->initrd_addr = bvb_be64toh(dest->initrd_addr); -} - -void bvb_rsa_public_key_header_to_host_byte_order( - const BvbRSAPublicKeyHeader* src, - BvbRSAPublicKeyHeader* dest) { - bvb_memcpy(dest, src, sizeof(BvbRSAPublicKeyHeader)); - - dest->key_num_bits = bvb_be32toh(dest->key_num_bits); - dest->n0inv = bvb_be32toh(dest->n0inv); -} - -int bvb_safe_add_to(uint64_t *value, uint64_t value_to_add) { - uint64_t original_value; - - bvb_assert(value != NULL); - - original_value = *value; - - *value += value_to_add; - if (*value < original_value) { - bvb_debug("%s: overflow: 0x%016" PRIx64 " + 0x%016" PRIx64 "\n", - __FUNCTION__, original_value, value_to_add); - return 0; - } - - return 1; -} - -int bvb_safe_add(uint64_t* out_result, uint64_t a, uint64_t b) { - uint64_t dummy; - if (out_result == NULL) - out_result = &dummy; - *out_result = a; - return bvb_safe_add_to(out_result, b); -} diff --git a/refimpl/bvb_util.h b/refimpl/bvb_util.h deleted file mode 100644 index 951ce83..0000000 --- a/refimpl/bvb_util.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#if !defined (BVB_INSIDE_BVB_REFIMPL_H) && !defined (BVB_REFIMPL_COMPILATION) -#error "Never include this file directly, include bvb_refimpl.h instead." -#endif - -#ifndef BVB_UTIL_H_ -#define BVB_UTIL_H_ - -#include "bvb_boot_image_header.h" -#include "bvb_sysdeps.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Converts a 32-bit unsigned integer from big-endian to host byte order. */ -uint32_t bvb_be32toh(uint32_t in); - -/* Converts a 64-bit unsigned integer from big-endian to host byte order. */ -uint64_t bvb_be64toh(uint64_t in); - -/* Adds |value_to_add| to |value| with overflow protection. - * - * Returns zero if the addition overflows, non-zero otherwise. In - * either case, |value| is always modified. - */ -int bvb_safe_add_to(uint64_t *value, uint64_t value_to_add); - -/* Adds |a| and |b| with overflow protection, returning the value in - * |out_result|. - * - * It's permissible to pass NULL for |out_result| if you just want to - * check that the addition would not overflow. - * - * Returns zero if the addition overflows, non-zero otherwise. - */ -int bvb_safe_add(uint64_t *out_result, uint64_t a, uint64_t b); - -/* Copies |src| to |dest|, byte-swapping fields in the process. */ -void bvb_boot_image_header_to_host_byte_order( - const BvbBootImageHeader* src, - BvbBootImageHeader* dest); - -/* Copies |header| to |dest|, byte-swapping fields in the process. */ -void bvb_rsa_public_key_header_to_host_byte_order( - const BvbRSAPublicKeyHeader* src, - BvbRSAPublicKeyHeader* dest); - -#ifdef __cplusplus -} -#endif - -#endif /* BVB_UTIL_H_ */ diff --git a/refimpl/bvb_verify.c b/refimpl/bvb_verify.c deleted file mode 100644 index dc05580..0000000 --- a/refimpl/bvb_verify.c +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "bvb_rsa.h" -#include "bvb_sha.h" -#include "bvb_util.h" -#include "bvb_verify.h" - -static const uint8_t padding_RSA2048_SHA256[BVB_RSA2048_NUM_BYTES - BVB_SHA256_DIGEST_SIZE] = { -0x00,0x01,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20 -}; - -static const uint8_t padding_RSA4096_SHA256[BVB_RSA4096_NUM_BYTES - BVB_SHA256_DIGEST_SIZE] = { -0x00,0x01,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20 -}; - -static const uint8_t padding_RSA8192_SHA256[BVB_RSA8192_NUM_BYTES - BVB_SHA256_DIGEST_SIZE] = { -0x00,0x01,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20 -}; - -static const uint8_t padding_RSA2048_SHA512[BVB_RSA2048_NUM_BYTES - BVB_SHA512_DIGEST_SIZE] = { -0x00,0x01,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x30,0x51,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0x04,0x40 -}; - -static const uint8_t padding_RSA4096_SHA512[BVB_RSA4096_NUM_BYTES - BVB_SHA512_DIGEST_SIZE] = { -0x00,0x01,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x30,0x51,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0x04,0x40 -}; - -static const uint8_t padding_RSA8192_SHA512[BVB_RSA8192_NUM_BYTES - BVB_SHA512_DIGEST_SIZE] = { -0x00,0x01,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x30,0x51,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0x04,0x40 -}; - -typedef struct { - const uint8_t *padding; - size_t padding_len; - size_t hash_len; -} BvbAlgorithmData; - -static BvbAlgorithmData algorithm_data[_BVB_ALGORITHM_NUM_TYPES] = { - /* BVB_ALGORITHM_TYPE_NONE */ - { - .padding = NULL, - .padding_len = 0, - .hash_len = 0 - }, - /* BVB_ALGORITHM_TYPE_SHA256_RSA2048 */ - { - .padding = padding_RSA2048_SHA256, - .padding_len = sizeof(padding_RSA2048_SHA256), - .hash_len = BVB_SHA256_DIGEST_SIZE - }, - /* BVB_ALGORITHM_TYPE_SHA256_RSA4096 */ - { - .padding = padding_RSA4096_SHA256, - .padding_len = sizeof(padding_RSA4096_SHA256), - .hash_len = BVB_SHA256_DIGEST_SIZE - }, - /* BVB_ALGORITHM_TYPE_SHA256_RSA8192 */ - { - .padding = padding_RSA8192_SHA256, - .padding_len = sizeof(padding_RSA8192_SHA256), - .hash_len = BVB_SHA256_DIGEST_SIZE - }, - /* BVB_ALGORITHM_TYPE_SHA512_RSA2048 */ - { - .padding = padding_RSA2048_SHA512, - .padding_len = sizeof(padding_RSA2048_SHA512), - .hash_len = BVB_SHA512_DIGEST_SIZE - }, - /* BVB_ALGORITHM_TYPE_SHA512_RSA4096 */ - { - .padding = padding_RSA4096_SHA512, - .padding_len = sizeof(padding_RSA4096_SHA512), - .hash_len = BVB_SHA512_DIGEST_SIZE - }, - /* BVB_ALGORITHM_TYPE_SHA512_RSA8192 */ - { - .padding = padding_RSA8192_SHA512, - .padding_len = sizeof(padding_RSA8192_SHA512), - .hash_len = BVB_SHA512_DIGEST_SIZE - }, -}; - -BvbVerifyResult bvb_verify_boot_image(const uint8_t* data, - size_t length, - const uint8_t** out_public_key_data, - size_t* out_public_key_length) { - BvbVerifyResult ret; - BvbBootImageHeader *h = NULL; - uint8_t* computed_hash; - BvbAlgorithmData* algorithm; - BvbSHA256Ctx sha256_ctx; - BvbSHA512Ctx sha512_ctx; - const uint8_t* header_block; - const uint8_t* authentication_block; - const uint8_t* auxilary_block; - const uint8_t* payload_block; - int verification_result; - - ret = BVB_VERIFY_RESULT_INVALID_BOOT_IMAGE_HEADER; - - if (out_public_key_data != NULL) - *out_public_key_data = NULL; - if (out_public_key_length != NULL) - *out_public_key_length = 0; - - /* Ensure magic is correct. */ - if (bvb_safe_memcmp(data, BVB_MAGIC, BVB_MAGIC_LEN) != 0) { - bvb_debug("Magic is incorrect.\n"); - goto out; - } - - /* Before we byteswap, ensure length is long enough. */ - if (length < sizeof(BvbBootImageHeader)) { - bvb_debug("Length is smaller than header.\n"); - goto out; - } - h = bvb_malloc(sizeof(BvbBootImageHeader)); - if (h == NULL) { - bvb_debug("Error allocating byteswapped header.\n"); - goto out; - } - bvb_boot_image_header_to_host_byte_order( - (const BvbBootImageHeader *) data, h); - - /* Ensure we don't attempt to access any fields if the major version - * is not supported. - */ - if (h->header_version_major > BVB_MAJOR_VERSION) { - bvb_debug("No support for version %d.\n", h->header_version_major); - goto out; - } - - /* Ensure inner block sizes are multiple of 64. */ - if ((h->authentication_data_block_size & 0x3f) != 0 || - (h->auxilary_data_block_size & 0x3f) != 0) { - bvb_debug("Block size is not a multiple of 64.\n"); - goto out; - } - - /* Ensure block sizes all add up to at least |length|. */ - uint64_t block_total = sizeof(BvbBootImageHeader); - if (!bvb_safe_add_to(&block_total, h->authentication_data_block_size) || - !bvb_safe_add_to(&block_total, h->auxilary_data_block_size) || - !bvb_safe_add_to(&block_total, h->payload_data_block_size)) { - bvb_debug("Overflow while computing size of boot image.\n"); - goto out; - } - if (block_total > length) { - bvb_debug("Block sizes add up to more than given length.\n"); - goto out; - } - - uintptr_t data_ptr = (uintptr_t) data; - /* Ensure passed in memory doesn't wrap. */ - if (!bvb_safe_add(NULL, (uint64_t) data_ptr, length)) { - bvb_debug("Boot image location and length mismatch.\n"); - goto out; - } - - /* Ensure hash and signature are entirely in the Authentication data block. */ - uint64_t hash_end; - if (!bvb_safe_add(&hash_end, h->hash_offset, h->hash_size) || - hash_end > h->authentication_data_block_size) { - bvb_debug("Hash is not entirely in its block.\n"); - goto out; - } - uint64_t signature_end; - if (!bvb_safe_add(&signature_end, h->signature_offset, h->signature_size) || - signature_end > h->authentication_data_block_size) { - bvb_debug("Signature is not entirely in its block.\n"); - goto out; - } - - /* Ensure public key is entirely in the Auxilary data block. */ - uint64_t pubkey_end; - if (!bvb_safe_add(&pubkey_end, h->public_key_offset, h->public_key_size) || - pubkey_end > h->auxilary_data_block_size) { - bvb_debug("Public key is not entirely in its block.\n"); - goto out; - } - - /* Ensure kernel and initramfs are entirely in the Payload data - * block. - */ - uint64_t kernel_end; - if (!bvb_safe_add(&kernel_end, h->kernel_offset, h->kernel_size) || - kernel_end > h->payload_data_block_size) { - bvb_debug("Kernel is not entirely in its block.\n"); - goto out; - } - if (h->initrd_size > 0) { - uint64_t initrd_end; - if (!bvb_safe_add(&initrd_end, h->initrd_offset, h->initrd_size) || - initrd_end > h->payload_data_block_size) { - bvb_debug("Initrd is not entirely in its block.\n"); - goto out; - } - } - - /* Ensure algorithm field is supported. */ - if (h->algorithm_type >= _BVB_ALGORITHM_NUM_TYPES) { - bvb_debug("Invalid or unknown algorithm.\n"); - goto out; - } - algorithm = &algorithm_data[h->algorithm_type]; - - /* Bail early if there's no hash or signature. */ - if (h->algorithm_type == BVB_ALGORITHM_TYPE_NONE) { - ret = BVB_VERIFY_RESULT_OK_NOT_SIGNED; - goto out; - } - - /* Bail if the embedded hash size doesn't match the chosen algorithm. */ - if (h->hash_size != algorithm->hash_len) { - bvb_debug("Embedded hash has wrong size.\n"); - goto out; - } - - /* No overflow checks needed from here-on after since all block - * sizes and offsets have been verified above. - */ - - header_block = data; - authentication_block = header_block + sizeof(BvbBootImageHeader); - auxilary_block = authentication_block + h->authentication_data_block_size; - payload_block = auxilary_block + h->auxilary_data_block_size; - - switch (h->algorithm_type) { - /* Explicit fall-through: */ - case BVB_ALGORITHM_TYPE_SHA256_RSA2048: - case BVB_ALGORITHM_TYPE_SHA256_RSA4096: - case BVB_ALGORITHM_TYPE_SHA256_RSA8192: - bvb_sha256_init(&sha256_ctx); - bvb_sha256_update(&sha256_ctx, header_block, - sizeof(BvbBootImageHeader)); - bvb_sha256_update(&sha256_ctx, auxilary_block, - h->auxilary_data_block_size); - bvb_sha256_update(&sha256_ctx, payload_block, - h->payload_data_block_size); - computed_hash = bvb_sha256_final(&sha256_ctx); - break; - /* Explicit fall-through: */ - case BVB_ALGORITHM_TYPE_SHA512_RSA2048: - case BVB_ALGORITHM_TYPE_SHA512_RSA4096: - case BVB_ALGORITHM_TYPE_SHA512_RSA8192: - bvb_sha512_init(&sha512_ctx); - bvb_sha512_update(&sha512_ctx, header_block, - sizeof(BvbBootImageHeader)); - bvb_sha512_update(&sha512_ctx, auxilary_block, - h->auxilary_data_block_size); - bvb_sha512_update(&sha512_ctx, payload_block, - h->payload_data_block_size); - computed_hash = bvb_sha512_final(&sha512_ctx); - break; - default: - bvb_debug("Unknown algorithm %d.\n", h->algorithm_type); - goto out; - } - - if (bvb_safe_memcmp(authentication_block + h->hash_offset, - computed_hash, h->hash_size) != 0) { - bvb_debug("Hash does not match!\n"); - ret = BVB_VERIFY_RESULT_HASH_MISMATCH; - goto out; - } - - verification_result = bvb_rsa_verify( - auxilary_block + h->public_key_offset, h->public_key_size, - authentication_block + h->signature_offset, h->signature_size, - authentication_block + h->hash_offset, h->hash_size, - algorithm->padding, algorithm->padding_len); - - if (verification_result == 0) { - ret = BVB_VERIFY_RESULT_SIGNATURE_MISMATCH; - goto out; - } - - if (out_public_key_data != NULL) - *out_public_key_data = auxilary_block + h->public_key_offset; - if (out_public_key_length != NULL) - *out_public_key_length = h->public_key_size; - - ret = BVB_VERIFY_RESULT_OK; - -out: - if (h != NULL) - bvb_free(h); - return ret; -} diff --git a/refimpl/bvb_verify.h b/refimpl/bvb_verify.h deleted file mode 100644 index 0cfd7ba..0000000 --- a/refimpl/bvb_verify.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#if !defined (BVB_INSIDE_BVB_REFIMPL_H) && !defined (BVB_REFIMPL_COMPILATION) -#error "Never include this file directly, include bvb_refimpl.h instead." -#endif - -#ifndef BVB_VERIFY_H_ -#define BVB_VERIFY_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "bvb_boot_image_header.h" - -/* Return codes used in bvb_verify_boot_image(). - * - * BVB_VERIFY_RESULT_OK is returned if the boot image header is valid, - * the hash is correct and the signature is correct. Keep in mind that - * you still need to check that you know the public key used to sign - * the image, see bvb_verify_boot_image() for details. - * - * BVB_VERIFY_RESULT_OK_NOT_SIGNED is returned if the boot image - * header is valid but there is no signature or hash. - * - * BVB_VERIFY_INVALID_BOOT_IMAGE_HEADER is returned if the header of - * the boot image is invalid, for example, invalid magic or - * inconsistent data. - * - * BVB_VERIFY_HASH_MISMATCH is returned if the hash stored in the - * "Authentication data" block does not match the calculated hash. - * - * BVB_VERIFY_SIGNATURE_MISMATCH is returned if the signature stored - * in the "Authentication data" block is invalid or doesn't match the - * public key stored in the boot image. - */ -typedef enum { - BVB_VERIFY_RESULT_OK, - BVB_VERIFY_RESULT_OK_NOT_SIGNED, - BVB_VERIFY_RESULT_INVALID_BOOT_IMAGE_HEADER, - BVB_VERIFY_RESULT_HASH_MISMATCH, - BVB_VERIFY_RESULT_SIGNATURE_MISMATCH, -} BvbVerifyResult; - -/* - * Checks that raw boot image at |data| of size |length| is a valid - * Brillo boot image. The complete contents of the boot image must be - * passed in. It's fine if |length| is bigger than the actual image, - * typically callers of this function will load the entire contents of - * the 'boot_a' or 'boot_b' partition and pass in its length (for - * example, 32 MiB). - * - * See the |BvbBootImageHeader| struct for information about the four - * blocks (header, authentication, auxilary, payload) that make up a - * boot image. - * - * If the function returns |BVB_VERIFY_RESULT_OK| and - * |out_public_key_data| is non-NULL, it will be set to point inside - * |data| for where the serialized public key data is stored and - * |out_public_key_length|, if non-NULL, will be set to the length of - * the public key data. - * - * See the |BvbVerifyResult| enum for possible return values. - * - * VERY IMPORTANT: - * - * 1. Even if |BVB_VERIFY_RESULT_OK| is returned, you still need to - * check that the public key embedded in the image matches a - * known key! You can use 'bvbtool extract_public_key' to extract - * the key at build time and compare it to what is returned in - * |out_public_key_data|. - * - * 2. You need to check the |rollback_index| field against a stored - * value in NVRAM and reject the boot image if the value in NVRAM - * is bigger than |rollback_index|. You must also update the - * value stored in NVRAM to the smallest value of - * |rollback_index| field from boot images in all bootable and - * authentic slots marked as GOOD. - */ -BvbVerifyResult bvb_verify_boot_image( - const uint8_t* data, size_t length, - const uint8_t** out_public_key_data, size_t* out_public_key_length); - -#ifdef __cplusplus -} -#endif - -#endif /* BVB_VERIFY_H_ */ diff --git a/test/dummy_initrd.bin b/test/dummy_initrd.bin Binary files differdeleted file mode 100644 index 6d13e99..0000000 --- a/test/dummy_initrd.bin +++ /dev/null diff --git a/test/dummy_kernel.bin b/test/dummy_kernel.bin Binary files differdeleted file mode 100644 index 3666773..0000000 --- a/test/dummy_kernel.bin +++ /dev/null diff --git a/test/dummy_rootfs.bin b/test/dummy_rootfs.bin Binary files differdeleted file mode 100644 index e2a36c2..0000000 --- a/test/dummy_rootfs.bin +++ /dev/null diff --git a/test/small_blob.bin b/test/small_blob.bin Binary files differdeleted file mode 100644 index d712de6..0000000 --- a/test/small_blob.bin +++ /dev/null diff --git a/test/testkey_rsa2048.pem b/test/testkey_rsa2048.pem deleted file mode 100644 index 867dcff..0000000 --- a/test/testkey_rsa2048.pem +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEowIBAAKCAQEAxlVR3TIkouAOvH79vaJTgFhpfvVKQIeVkFRZPVXK/zY0Gvrh -4JAqGjJoW/PfrQv5sdD36qtHH3a+G5hLZ6Ni+t/mtfjucxZfuLGC3kmJ1T3XqEKZ -gXXI2IR7vVSoImREvDQGEDyJwtHzLANlkbGg0cghVhWZSCAndO8BenalC2v94/rt -DfkPekH6dgU3Sf40T0sBSeSY94mOzTaqOR2pfV1rWlLRdWmo33zeHBv52Rlbt0dM -uXAureXWiHztkm5GCBC1dgM+CaxNtizNEgC91KcD0xuRCCM2WxH+r1lpszyIJDct -YbrFmVEYl/kjQpafhy7Nsk1fqSTyRdriZSYmTQIDAQABAoIBAQC+kJgaCuX8wYAn -SXWQ0fmdZlXnMNRpcF0a0pD0SAzGb1RdYBXMaXiqtyhiwc53PPxsCDdNecjayIMd -jJVXPTwLhTruOgMS/bp3gcgWwV34UHV4LJXGOGAE+jbS0hbDBMiudOYmj6RmVshp -z9G1zZCSQNMXHaWsEYkX59XpzzoB384nRul2QgEtwzUNR9XlpzgtJBLk3SACkvsN -mQ/DW8IWHXLg8vLn1LzVJ2e3B16H4MoE2TCHxqfMgr03IDRRJogkenQuQsFhevYT -o/mJyHSWavVgzMHG9I5m+eepF4Wyhj1Y4WyKAuMI+9dHAX/h7Lt8XFCQCh5DbkVG -zGr34sWBAoGBAOs7n7YZqNaaguovfIdRRsxxZr1yJAyDsr6w3yGImDZYju4c4WY9 -5esO2kP3FA4p0c7FhQF5oOb1rBuHEPp36cpL4aGeK87caqTfq63WZAujoTZpr9Lp -BRbkL7w/xG7jpQ/clpA8sHzHGQs/nelxoOtC7E118FiRgvD/jdhlMyL9AoGBANfX -vyoN1pplfT2xR8QOjSZ+Q35S/+SAtMuBnHx3l0qH2bbBjcvM1MNDWjnRDyaYhiRu -i+KA7tqfib09+XpB3g5D6Ov7ls/Ldx0S/VcmVWtia2HK8y8iLGtokoBZKQ5AaFX2 -iQU8+tC4h69GnJYQKqNwgCUzh8+gHX5Y46oDiTmRAoGAYpOx8lX+czB8/Da6MNrW -mIZNT8atZLEsDs2ANEVRxDSIcTCZJId7+m1W+nRoaycLTWNowZ1+2ErLvR10+AGY -b7Ys79Wg9idYaY9yGn9lnZsMzAiuLeyIvXcSqgjvAKlVWrhOQFOughvNWvFl85Yy -oWSCMlPiTLtt7CCsCKsgKuECgYBgdIp6GZsIfkgclKe0hqgvRoeU4TR3gcjJlM9A -lBTo+pKhaBectplx9RxR8AnsPobbqwcaHnIfAuKDzjk5mEvKZjClnFXF4HAHbyAF -nRzZEy9XkWFhc80T5rRpZO7C7qdxmu2aiKixM3V3L3/0U58qULEDbubHMw9bEhAT -PudI8QKBgHEEiMm/hr9T41hbQi/LYanWnlFw1ue+osKuF8bXQuxnnHNuFT/c+9/A -vWhgqG6bOEHu+p/IPrYm4tBMYlwsyh4nXCyGgDJLbLIfzKwKAWCtH9LwnyDVhOow -GH9shdR+sW3Ew97xef02KAH4VlNANEmBV4sQNqWWvsYrcFm2rOdL ------END RSA PRIVATE KEY----- diff --git a/test/testkey_rsa4096.pem b/test/testkey_rsa4096.pem deleted file mode 100644 index 26db5c3..0000000 --- a/test/testkey_rsa4096.pem +++ /dev/null @@ -1,51 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -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 ------END RSA PRIVATE KEY----- diff --git a/test/testkey_rsa8192.pem b/test/testkey_rsa8192.pem deleted file mode 100644 index a383428..0000000 --- a/test/testkey_rsa8192.pem +++ /dev/null @@ -1,99 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -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 ------END RSA PRIVATE KEY----- |