diff --git a/tests/Makefile b/tests/Makefile index 8b0d3a5a4e..19a0940241 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -11,8 +11,9 @@ FIRMWARE_LIBS = $(TOP)/crypto/libcrypto.a $(TOP)/common/libcommon.a LIBS = $(TOP)/utils/kernel_image.o $(TOP)/utils/firmware_image.o \ $(TOP)/utils/file_keys.o $(TOP)/utils/signature_digest.o -lcrypto -tests: firmware_image_tests kernel_image_tests sha_tests sha_benchmark \ - rsa_verify_benchmark rsa_padding_test +tests: firmware_image_tests verify_firmware_fuzz_driver \ + kernel_image_tests verify_kernel_fuzz_driver \ + sha_tests sha_benchmark rsa_verify_benchmark rsa_padding_test sha_tests: sha_tests.c $(CC) $(CFLAGS) $(INCLUDES) $^ -o $@ $(FIRMWARE_LIBS) @@ -20,9 +21,15 @@ sha_tests: sha_tests.c firmware_image_tests: firmware_image_tests.c $(CC) $(CFLAGS) $(INCLUDES) $< -o $@ $(LIBS) $(FIRMWARE_LIBS) +verify_firmware_fuzz_driver: verify_firmware_fuzz_driver.c + $(CC) $(CFLAGS) $(INCLUDES) $< -o $@ $(LIBS) $(FIRMWARE_LIBS) + kernel_image_tests: kernel_image_tests.c $(CC) $(CFLAGS) $(INCLUDES) $< -o $@ $(LIBS) $(FIRMWARE_LIBS) +verify_kernel_fuzz_driver: verify_kernel_fuzz_driver.c + $(CC) $(CFLAGS) $(INCLUDES) $< -o $@ $(LIBS) $(FIRMWARE_LIBS) + sha_benchmark: sha_benchmark.c timer_utils.c $(FIRMWARE_LIBS) $(CC) $(CFLAGS) $(INCLUDES) $^ -o $@ -lrt @@ -34,4 +41,5 @@ rsa_verify_benchmark: rsa_verify_benchmark.c timer_utils.c clean: rm -f sha_tests sha_benchmark rsa_verify_benchmark \ - firmware_image_tests kernel_image_tests rsa_padding_test + firmware_image_tests kernel_image_tests rsa_padding_test \ + verify_firmware_fuzz_driver verify_kernel_fuzz_driver diff --git a/tests/gen_fuzz_test_cases.sh b/tests/gen_fuzz_test_cases.sh new file mode 100755 index 0000000000..fc97f4b1ae --- /dev/null +++ b/tests/gen_fuzz_test_cases.sh @@ -0,0 +1,68 @@ +#!/bin/bash + +# Copyright (c) 2010 The Chromium OS Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Generate test cases for use for the RSA verify benchmark. + +TESTCASE_DIR=fuzz_testcases +TESTKEY_DIR=testkeys +UTIL_DIR=../utils/ +TEST_FILE=test_file +TEST_FILE_SIZE=1000000 + +hash_algos=( sha1 sha256 sha512 ) +key_lengths=( 1024 2048 4096 8192 ) + +# Generate public key signatures and digest on an input file for +# various combinations of message digest algorithms and RSA key sizes. +function generate_fuzzing_images { + echo "Generating signed firmware test image..." + # Generate a test verified boot firmware image and copy root public key. + ${UTIL_DIR}/firmware_utility --generate \ + --in $1 \ + --root_key ${TESTKEY_DIR}/key_rsa8192.pem \ + --firmware_sign_key ${TESTKEY_DIR}/key_rsa4096.pem \ + --firmware_sign_key_pub ${TESTKEY_DIR}/key_rsa4096.keyb \ + --firmware_sign_algorithm 8 \ + --firmware_key_version 1 \ + --firmware_version 1 \ + --out ${TESTCASE_DIR}/firmware.signed + cp ${TESTKEY_DIR}/key_rsa8192.keyb ${TESTCASE_DIR}/root_key.keyb + + echo "Generating signed kernel test image..." + # Generate a test verified boot kernel image and copy firmware public key. + ${UTIL_DIR}/kernel_utility --generate \ + --in $1 \ + --firmware_key ${TESTKEY_DIR}/key_rsa4096.pem \ + --kernel_key ${TESTKEY_DIR}/key_rsa1024.pem \ + --kernel_key_pub ${TESTKEY_DIR}/key_rsa1024.keyb \ + --firmware_sign_algorithm 8 \ + --kernel_sign_algorithm 2 \ + --kernel_key_version 1 \ + --kernel_version 1 \ + --out ${TESTCASE_DIR}/kernel.signed + cp ${TESTKEY_DIR}/key_rsa4096.keyb ${TESTCASE_DIR}/firmware_key.keyb +} + +function pre_work { + # Generate a file with random bytes for signature tests. + echo "Generating test file..." + dd if=/dev/urandom of=${TESTCASE_DIR}/${TEST_FILE} bs=${TEST_FILE_SIZE} \ + count=1 +} + +if [ ! -d ${TESTKEY_DIR} ] +then + echo "You must run gen_test_keys.sh to generate test keys first." + exit 1 +fi + +if [ ! -d ${TESTCASE_DIR} ] +then + mkdir ${TESTCASE_DIR} +fi + +pre_work +generate_fuzzing_images ${TESTCASE_DIR}/$TEST_FILE diff --git a/tests/verify_firmware_fuzz_driver.c b/tests/verify_firmware_fuzz_driver.c new file mode 100644 index 0000000000..224fdb585f --- /dev/null +++ b/tests/verify_firmware_fuzz_driver.c @@ -0,0 +1,57 @@ +/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Utility for aiding fuzz testing of firmware image verification code. + */ + +#include + +#include "file_keys.h" +#include "firmware_image.h" +#include "utility.h" + +int VerifySignedFirmware(const char* image_file, + const char* root_key_file) { + int error, error_code = 0; + uint64_t len; + uint8_t* firmware_blob = BufferFromFile(image_file, &len); + uint8_t* root_key_blob = BufferFromFile(root_key_file, &len); + + if (!root_key_blob) { + fprintf(stderr, "Couldn't read pre-processed public root key.\n"); + error_code = 1; + } + + if (!error_code && !firmware_blob) { + fprintf(stderr, "Couldn't read firmware image or malformed image.\n"); + error_code = 1; + } + + if (!error_code && (error = VerifyFirmware(root_key_blob, firmware_blob, + 0))) { /* Trusted Mode. */ + fprintf(stderr, "%s\n", VerifyFirmwareErrorString(error)); + error_code = 1; + } + Free(root_key_blob); + Free(firmware_blob); + if (error_code) + return 0; + else + return 1; +} + +int main(int argc, char* argv[]) { + if (argc != 3) { + fprintf(stderr, "Usage: %s \n", argv[0]); + return -1; + } + if (VerifySignedFirmware(argv[1], argv[2])) { + fprintf(stderr, "Verification SUCCESS!\n"); + return 0; + } + else { + fprintf(stderr, "Verification FAILURE!\n"); + return -1; + } +} diff --git a/tests/verify_kernel_fuzz_driver.c b/tests/verify_kernel_fuzz_driver.c new file mode 100644 index 0000000000..102726388e --- /dev/null +++ b/tests/verify_kernel_fuzz_driver.c @@ -0,0 +1,56 @@ +/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Utility for aiding fuzz testing of kernel image verification code. + */ + +#include + +#include "file_keys.h" +#include "kernel_image.h" +#include "utility.h" + +int VerifySignedKernel(const char* image_file, + const char* firmware_key_file) { + int error, error_code = 0; + uint64_t len; + uint8_t* kernel_blob = BufferFromFile(image_file, &len); + uint8_t* firmware_key_blob = BufferFromFile(firmware_key_file, &len); + + if (!firmware_key_blob) { + fprintf(stderr, "Couldn't read pre-processed public firmware key.\n"); + error_code = 1; + } + + if (!error_code && !kernel_blob) { + fprintf(stderr, "Couldn't read kernel image or malformed image.\n"); + error_code = 1; + } + + if (!error_code && (error = VerifyKernel(firmware_key_blob, kernel_blob, + 0))) { /* Trusted Mode. */ + fprintf(stderr, "%s\n", VerifyKernelErrorString(error)); + error_code = 1; + } + Free(firmware_key_blob); + Free(kernel_blob); + if (error_code) + return 0; + return 1; +} + +int main(int argc, char* argv[]) { + if (argc != 3) { + fprintf(stderr, "Usage: %s \n", argv[0]); + return -1; + } + if (VerifySignedKernel(argv[1], argv[2])) { + fprintf(stderr, "Verification SUCCESS!\n"); + return 0; + } + else { + fprintf(stderr, "Verification FAILURE!\n"); + return -1; + } +} diff --git a/utils/kernel_image.c b/utils/kernel_image.c index a1b943f83a..81aa06fdae 100644 --- a/utils/kernel_image.c +++ b/utils/kernel_image.c @@ -404,6 +404,7 @@ int VerifyKernelHeader(const uint8_t* firmware_key_blob, kernel_sign_key_len), FIELD_LEN(header_checksum))) { Free(header_checksum); + fprintf(stderr, "VerifyKernelHeader: Invalid header hash\n"); return VERIFY_KERNEL_INVALID_IMAGE; } Free(header_checksum); diff --git a/utils/kernel_utility.cc b/utils/kernel_utility.cc index 8c4ae90887..03d4037a5e 100644 --- a/utils/kernel_utility.cc +++ b/utils/kernel_utility.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// Utility for manipulating verified boot firmware images. +// Utility for manipulating verified boot kernel images. // #include "kernel_utility.h" @@ -55,7 +55,7 @@ KernelUtility::~KernelUtility() { void KernelUtility::PrintUsage(void) { cerr << "Utility to generate/verify a verified boot kernel image\n\n" - "Usage: firmware_utility <--generate|--verify> [OPTIONS]\n\n" + "Usage: kernel_utility <--generate|--verify> [OPTIONS]\n\n" "For \"--verify\", required OPTIONS are:\n" "--in \t\t\tVerified boot kernel image to verify.\n" "--firmware_key_pub \tPre-processed public firmware key " @@ -227,7 +227,11 @@ bool KernelUtility::GenerateSignedImage(void) { sizeof(image_->header_version)); DigestUpdate(&ctx, reinterpret_cast(&image_->header_len), sizeof(image_->header_len)); - DigestUpdate(&ctx, reinterpret_cast(&image_->kernel_sign_algorithm), + DigestUpdate(&ctx, + reinterpret_cast(&image_->firmware_sign_algorithm), + sizeof(image_->firmware_sign_algorithm)); + DigestUpdate(&ctx, + reinterpret_cast(&image_->kernel_sign_algorithm), sizeof(image_->kernel_sign_algorithm)); DigestUpdate(&ctx, reinterpret_cast(&image_->kernel_key_version), sizeof(image_->kernel_key_version)); @@ -248,12 +252,12 @@ bool KernelUtility::GenerateSignedImage(void) { return false; // Generate and add the signatures. if (!AddKernelKeySignature(image_, firmware_key_file_.c_str())) { - cerr << "Couldn't write key signature to verified boot image.\n"; + cerr << "Couldn't write key signature to verified boot kernel image.\n"; return false; } if (!AddKernelSignature(image_, kernel_key_file_.c_str())) { - cerr << "Couldn't write firmware signature to verified boot image.\n"; + cerr << "Couldn't write firmware signature to verified boot kernel image.\n"; return false; } return true; @@ -270,7 +274,7 @@ bool KernelUtility::VerifySignedImage(void) { } if (!image_) { - cerr << "Couldn't read firmware image or malformed image.\n"; + cerr << "Couldn't read kernel image or malformed image.\n"; return false; } if (!(error = VerifyKernelImage(firmware_key_pub_, image_, 0)))