Vboot Reference: Add functions to verify signed kernel images.

BUG=670
TEST=Adds kernel_image_test which tests the new functions.

The kernel image verification pretty much exactly mirror the already existing firmware image verification functions except with a few different/additional fields in a signed kernel image. The firmware signing key is the root key equivalent for kernel images.

This CL also moves the image verification tests to a different script. There's some additional cleanup of the code that I will be submitting separately after this and another pending patches get LGTMed and land.

Review URL: http://codereview.chromium.org/660161
This commit is contained in:
Gaurav Shah
2010-02-28 19:18:24 -08:00
parent 8b95c70373
commit f67bcaa9a6
8 changed files with 1199 additions and 31 deletions

200
include/kernel_image.h Normal file
View File

@@ -0,0 +1,200 @@
/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*
* Data structure and API definitions for a verified boot kernel image.
*/
#ifndef VBOOT_REFERENCE_KERNEL_IMAGE_H_
#define VBOOT_REFERENCE_KERNEL_IMAGE_H_
#include <inttypes.h>
#include "rsa.h"
#include "sha.h"
#define KERNEL_MAGIC "CHROMEOS"
#define KERNEL_MAGIC_SIZE 8
/* Kernel config file options according to the Chrome OS drive map design. */
typedef struct kconfig_options {
uint32_t version[2]; /* Configuration file version. */
uint32_t kernel_len; /* Size of the kernel. */
uint64_t kernel_load_addr; /* Load address in memory for the kernel image */
uint64_t kernel_entry_addr; /* Address to jump to after kernel is loaded. */
} kconfig_options;
typedef struct KernelImage {
uint8_t magic[KERNEL_MAGIC_SIZE];
/* Key header */
uint16_t header_version; /* Header version. */
uint16_t header_len; /* Length of the header. */
uint16_t firmware_sign_algorithm; /* Signature algorithm used by the firmware
* signing key (used to sign this kernel
* header. */
uint16_t kernel_sign_algorithm; /* Signature algorithm used by the kernel
* signing key. */
uint16_t kernel_key_version; /* Key Version# for preventing rollbacks. */
uint8_t* kernel_sign_key; /* Pre-processed public half of signing key. */
/* TODO(gauravsh): Do we need a choice of digest algorithms for the header
* checksum? */
uint8_t header_checksum[SHA512_DIGEST_SIZE]; /* SHA-512 Crytographic hash of
* the concatenation of the
* header fields, i.e.
* [header_len,
* firmware_sign_algorithm,
* sign_algorithm, sign_key,
* key_version] */
uint8_t* kernel_key_signature; /* Signature of the header above. */
uint16_t kernel_version; /* Kernel Version# for preventing rollbacks. */
kconfig_options options; /* Other kernel/bootloader options. */
uint8_t* config_signature; /* Signature of the kernel config file. */
/* The kernel signature comes first as it may allow us to parallelize
* the kernel data fetch and RSA public key operation.
*/
uint8_t* kernel_signature; /* Signature on [kernel_data]. */
uint8_t* kernel_data; /* Actual kernel data. */
} KernelImage;
/* Allocate and return a new KernelImage structure. */
KernelImage* KernelImageNew(void);
/* Deep free the contents of [image]. */
void KernelImageFree(KernelImage* image);
/* Read kernel data from file named [input_file].
*
* Returns a filled up KernelImage on success, NULL on error.
*/
KernelImage* ReadKernelImage(const char* input_file);
/* Write kernel key header from [image] to an open file pointed by the
* file descriptor [fd].
*/
void WriteKernelHeader(int fd, KernelImage* image);
/* Write kernel config from [image] to an open file pointed by the
* file descriptor [fd].
*/
void WriteKernelConfig(int fd, KernelImage* image);
/* Write kernel data from [image] to a file named [input_file].
*
* Return [image] on success, NULL on error.
*/
KernelImage* WriteKernelImage(const char* input_file,
KernelImage* image);
/* Pretty print the contents of [image]. Only headers and metadata information
* is printed.
*/
void PrintKernelImage(const KernelImage* image);
/* Error Codes for VerifyFirmware. */
#define VERIFY_KERNEL_SUCCESS 0
#define VERIFY_KERNEL_INVALID_IMAGE 1
#define VERIFY_KERNEL_KEY_SIGNATURE_FAILED 2
#define VERIFY_KERNEL_INVALID_ALGORITHM 3
#define VERIFY_KERNEL_CONFIG_SIGNATURE_FAILED 4
#define VERIFY_KERNEL_SIGNATURE_FAILED 5
#define VERIFY_KERNEL_WRONG_MAGIC 6
#define VERIFY_KERNEL_MAX 7 /* Generic catch-all. */
char* kVerifyKernelErrors[VERIFY_KERNEL_MAX];
/* Checks for the sanity of the kernel header pointed by [kernel_header_blob].
* If [dev_mode] is enabled, also checks the firmware key signature using the
* pre-processed public firmware signing key [firmware_sign_key_blob].
*
* On success, put firmware signature algorithm in [firmware_algorithm],
* kernel signature algorithm in [kernel_algorithm], kernel header
* length in [header_len], and return 0.
* Else, return error code on failure.
*/
int VerifyFirmwareHeader(const uint8_t* firmware_sign_key_blob,
const uint8_t* kernel_header_blob,
const int dev_mode,
int* firmware_algorithm,
int* kernel_algorithm,
int* header_len);
/* Checks the kernel config (analogous to preamble for firmware) signature on
* kernel config pointed by [kernel_config_blob] using the signing key
* [kernel_sign_key].
*
* On success, put kernel length into [kernel_len], and return 0.
* Else, return error code on failure.
*/
int VerifyKernelConfig(RSAPublicKey* kernel_sign_key,
const uint8_t* kernel_config_blob,
int algorithm,
int* kernel_len);
/* Checks the signature on the kernel data at location [kernel_data_start].
* The length of the actual kernel data is kernel _len and it is assumed to
* be prepended with the signature whose size depends on the signature_algorithm
* [algorithm].
*
* Return 0 on success, error code on failure.
*/
int VerifyKernelData(RSAPublicKey* kernel_sign_key,
const uint8_t* kernel_data_start,
int kernel_len,
int algorithm);
/* Performs a chained verify of the kernel blob [kernel_blob]. If
* [dev_mode] is 0 [inactive], then the pre-processed public signing key
* [root_key_blob] is used to verify the signature of the signing key,
* else the check is skipped.
*
* TODO(gauravsh): Does the dev mode only effect the R/W firmware verification,
* or kernel verification, or both?
*
* Returns 0 on success, error code on failure.
*
* NOTE: The length of the kernel blob is derived from reading the fields
* in the first few bytes of the buffer. This might look risky but in firmware
* land, the start address of the kernel_blob will always be fixed depending
* on the memory map on the particular platform. In addition, the signature on
* length itself is checked early in the verification process for extra safety.
*/
int VerifyKernel(const uint8_t* signing_key_blob,
const uint8_t* kernel_blob,
const int dev_mode);
/* Performs a chained verify of the kernel [image]. If [dev_mode] is
* 0 (inactive), then the [firmware_signing_key] is used to verify the signature
* of the signing key, else the check is skipped.
*
* Returns 0 on success, error code on failure.
*/
int VerifyKernelImage(const RSAPublicKey* firmware_signing_key,
const KernelImage* image,
int dev_mode);
/* Maps error codes from VerifyKernel*() to error description. */
const char* VerifyKernelErrorString(int error);
/* Add a kernel signing key signature to the key header to a kernel image
* [image] using the private key in file [firmware_key_file].
*
* Return 1 on success, 0 on failure.
*/
int AddKernelKeySignature(KernelImage* image, const char* firmware_key_file);
/* Add a kernel and kernel config signature to a kernel image [image]
* using the private signing key in file [kernel_sigining_key_file].
*
* Return 1 on success, 0 on failure.
*/
int AddKernelSignature(KernelImage* image, const char* kernel_sigining_key_file,
int algorithm);
#endif /* VBOOT_REFERENCE_KERNEL_IMAGE_H_ */

View File

@@ -7,16 +7,20 @@ CFLAGS = -Wall -DNDEBUG
INCLUDES ?= -I../include/
TOP ?= ../
LIBS = $(TOP)/utils/firmware_image.o $(TOP)/crypto/libcrypto.a \
$(TOP)/common/libcommon.a $(TOP)/utils/file_keys.o -lrt
LIBS = $(TOP)/utils/kernel_image.o $(TOP)/utils/firmware_image.o \
$(TOP)/crypto/libcrypto.a $(TOP)/common/libcommon.a \
$(TOP)/utils/file_keys.o -lrt
tests: firmware_image_tests sha_tests sha_benchmark rsa_verify_benchmark \
rsa_padding_test
tests: firmware_image_tests kernel_image_tests sha_tests sha_benchmark \
rsa_verify_benchmark rsa_padding_test
sha_tests: sha_tests.c
$(CC) $(CFLAGS) $(INCLUDES) $< -o $@ $(LIBS)
firmware_image_tests: firmware_image_tests.c
firmware_image_tests: firmware_image_tests.c $(LIBS)
$(CC) $(CFLAGS) $(INCLUDES) $< -o $@ $(LIBS)
kernel_image_tests: kernel_image_tests.c $(LIBS)
$(CC) $(CFLAGS) $(INCLUDES) $< -o $@ $(LIBS)
sha_benchmark: sha_benchmark.c timer_utils.c
@@ -30,4 +34,4 @@ rsa_verify_benchmark: rsa_verify_benchmark.c timer_utils.c
clean:
rm -f sha_tests sha_benchmark rsa_verify_benchmark \
firmware_image_tests rsa_padding_test
firmware_image_tests kernel_image_tests rsa_padding_test

View File

@@ -14,13 +14,18 @@
#include "sha_utility.h"
#include "utility.h"
/* ANSI Color coding sequences. */
#define COL_GREEN "\e[1;32m"
#define COL_RED "\e[0;31m]"
#define COL_STOP "\e[m"
int TEST_EQ(int result, int expected_result, char* testname) {
if (result == expected_result) {
fprintf(stderr, "%s Test \e[1;32mSUCCEEDED\e[m\n", testname);
fprintf(stderr, "%s Test " COL_GREEN " PASSED\n" COL_STOP, testname);
return 1;
}
else {
fprintf(stderr, "%s Test \e[0;31mFAILED\e[m\n", testname);
fprintf(stderr, "%s Test " COL_RED " FAILED\n" COL_STOP, testname);
return 0;
}
}

257
tests/kernel_image_tests.c Normal file
View File

@@ -0,0 +1,257 @@
/* 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.
*
* Tests for kernel image library.
*/
#include <stdio.h>
#include <stdlib.h>
#include "file_keys.h"
#include "kernel_image.h"
#include "rsa_utility.h"
#include "sha_utility.h"
#include "utility.h"
/* ANSI Color coding sequences. */
#define COL_GREEN "\e[1;32m"
#define COL_RED "\e[0;31m"
#define COL_STOP "\e[m"
int TEST_EQ(int result, int expected_result, char* testname) {
if (result == expected_result) {
fprintf(stderr, "%s Test " COL_GREEN " PASSED\n" COL_STOP, testname);
return 1;
}
else {
fprintf(stderr, "%s Test " COL_RED " FAILED\n" COL_STOP, testname);
return 0;
}
}
KernelImage* GenerateTestKernelImage(int firmware_sign_algorithm,
int kernel_sign_algorithm,
uint8_t* kernel_sign_key,
int kernel_key_version,
int kernel_version,
int kernel_len) {
KernelImage* image = KernelImageNew();
uint8_t* header_checksum;
DigestContext ctx;
Memcpy(image->magic, KERNEL_MAGIC, KERNEL_MAGIC_SIZE);
image->header_version = 1;
image->firmware_sign_algorithm = firmware_sign_algorithm;
image->kernel_sign_algorithm = kernel_sign_algorithm;
image->kernel_key_version = kernel_key_version;
image->kernel_sign_key = (uint8_t*) Malloc(
RSAProcessedKeySize(image->kernel_sign_algorithm));
Memcpy(image->kernel_sign_key, kernel_sign_key,
RSAProcessedKeySize(image->kernel_sign_algorithm));
/* Update correct header length. */
image->header_len = (sizeof(image->header_version) +
sizeof(image->header_len) +
sizeof(image->firmware_sign_algorithm) +
sizeof(image->kernel_sign_algorithm) +
RSAProcessedKeySize(image->kernel_sign_algorithm) +
sizeof(image->kernel_key_version) +
sizeof(image->header_checksum));
/* Calculate SHA-512 digest on header and populate header_checksum. */
DigestInit(&ctx, SHA512_DIGEST_ALGORITHM);
DigestUpdate(&ctx, (uint8_t*) &image->header_version,
sizeof(image->header_version));
DigestUpdate(&ctx, (uint8_t*) &image->header_len,
sizeof(image->header_len));
DigestUpdate(&ctx, (uint8_t*) &image->firmware_sign_algorithm,
sizeof(image->firmware_sign_algorithm));
DigestUpdate(&ctx, (uint8_t*) &image->kernel_sign_algorithm,
sizeof(image->kernel_sign_algorithm));
DigestUpdate(&ctx, (uint8_t*) &image->kernel_key_version,
sizeof(image->kernel_key_version));
DigestUpdate(&ctx, image->kernel_sign_key,
RSAProcessedKeySize(image->kernel_sign_algorithm));
header_checksum = DigestFinal(&ctx);
Memcpy(image->header_checksum, header_checksum, SHA512_DIGEST_SIZE);
Free(header_checksum);
/* Populate kernel options and data with dummy data. */
image->kernel_version = kernel_version;
image->options.version[0] = 1;
image->options.version[1] = 1;
image->options.kernel_len = kernel_len;
image->options.kernel_load_addr = 0;
image->options.kernel_entry_addr = 0;
image->kernel_key_signature = image->kernel_signature = NULL;
image->kernel_data = Malloc(kernel_len);
Memset(image->kernel_data, 'F', kernel_len);
return image;
}
#define DEV_MODE_ENABLED 1
#define DEV_MODE_DISABLED 0
/* Normal Kernel Blob Verification Tests. */
int VerifyKernelTest(uint8_t* kernel_blob, uint8_t* firmware_key_blob) {
int success = 1;
if (!TEST_EQ(VerifyKernel(firmware_key_blob, kernel_blob, DEV_MODE_ENABLED),
VERIFY_KERNEL_SUCCESS,
"Normal Kernel Blob Verification (Dev Mode)"))
success = 0;
if (!TEST_EQ(VerifyKernel(firmware_key_blob, kernel_blob, DEV_MODE_DISABLED),
VERIFY_KERNEL_SUCCESS,
"Normal Kernel Blob Verification (Trusted)"))
success = 0;
return success;
}
/* Normal KernelImage Verification Tests. */
int VerifyKernelImageTest(KernelImage* image,
RSAPublicKey* firmware_key) {
int success = 1;
if (!TEST_EQ(VerifyKernelImage(firmware_key, image, DEV_MODE_ENABLED),
VERIFY_KERNEL_SUCCESS,
"Normal KernelImage Verification (Dev Mode)"))
success = 0;
if (!TEST_EQ(VerifyKernelImage(firmware_key, image, DEV_MODE_DISABLED),
VERIFY_KERNEL_SUCCESS,
"Normal KernelImage Verification (Trusted)"))
success = 0;
return success;
}
/* Tampered KernelImage Verification Tests. */
int VerifyKernelImageTamperTest(KernelImage* image,
RSAPublicKey* firmware_key) {
int success = 1;
fprintf(stderr, "[[Tampering with kernel config....]]\n");
image->options.kernel_load_addr = 0xFFFF;
if (!TEST_EQ(VerifyKernelImage(firmware_key, image, DEV_MODE_ENABLED),
VERIFY_KERNEL_CONFIG_SIGNATURE_FAILED,
"KernelImage Config Tamper Verification (Dev Mode)"))
success = 0;
if (!TEST_EQ(VerifyKernelImage(firmware_key, image, DEV_MODE_DISABLED),
VERIFY_KERNEL_CONFIG_SIGNATURE_FAILED,
"KernelImage Config Tamper Verification (Trusted)"))
success = 0;
image->options.kernel_load_addr = 0;
image->kernel_data[0] = 'T';
if (!TEST_EQ(VerifyKernelImage(firmware_key, image, DEV_MODE_ENABLED),
VERIFY_KERNEL_SIGNATURE_FAILED,
"KernelImage Tamper Verification (Dev Mode)"))
success = 0;
if (!TEST_EQ(VerifyKernelImage(firmware_key, image, DEV_MODE_DISABLED),
VERIFY_KERNEL_SIGNATURE_FAILED,
"KernelImage Tamper Verification (Trusted)"))
success = 0;
image->kernel_data[0] = 'F';
fprintf(stderr, "[[Tampering with kernel key signature...]]\n");
image->kernel_key_signature[0] = 0xFF;
image->kernel_key_signature[1] = 0x00;
if (!TEST_EQ(VerifyKernelImage(firmware_key, image, DEV_MODE_ENABLED),
VERIFY_KERNEL_SUCCESS,
"KernelImage Key Signature Tamper Verification (Dev Mode)"))
success = 0;
if (!TEST_EQ(VerifyKernelImage(firmware_key, image, DEV_MODE_DISABLED),
VERIFY_KERNEL_KEY_SIGNATURE_FAILED,
"KernelImage Key Signature Tamper Verification (Trusted)"))
success = 0;
return success;
}
int main(int argc, char* argv[]) {
uint32_t len;
uint8_t* kernel_sign_key_buf = NULL;
uint8_t* firmware_key_blob = NULL;
uint8_t* kernel_blob = NULL;
KernelImage* image = NULL;
RSAPublicKey* firmware_key = NULL;
int error_code = 1;
char* tmp_kernelblob_file = ".tmpKernelBlob";
if(argc != 7) {
fprintf(stderr, "Usage: %s <firmware signing algorithm> " /* argv[1] */
"<kernel signing algorithm> " /* argv[2] */
"<firmware key> " /* argv[3] */
"<processed firmware pubkey> " /* argv[4] */
"<kernel signing key> " /* argv[5] */
"<processed kernel signing key>\n", /* argv[6] */
argv[0]);
return -1;
}
/* Read verification keys and create a test image. */
firmware_key = RSAPublicKeyFromFile(argv[4]);
firmware_key_blob = BufferFromFile(argv[4], &len);
kernel_sign_key_buf = BufferFromFile(argv[6], &len);
if (!firmware_key || !kernel_sign_key_buf || !kernel_sign_key_buf) {
error_code = 1;
goto failure;
}
image = GenerateTestKernelImage(atoi(argv[1]),
atoi(argv[2]),
kernel_sign_key_buf,
1, /* Kernel Key Version */
1, /* Kernel Version */
1000); /* Kernel Size */
if (!image) {
error_code = 1;
goto failure;
}
/* Generate and populate signatures. */
if (!AddKernelKeySignature(image, argv[3])) {
fprintf(stderr, "Couldn't create key signature.\n");
error_code = 1;
goto failure;
}
if (!AddKernelSignature(image, argv[5], image->kernel_sign_algorithm)) {
fprintf(stderr, "Couldn't create firmware and preamble signature.\n");
error_code = 1;
goto failure;
}
/* Generate a firmware binary blob from image.
*
* TODO(gauravsh): Add a function to directly generate a binary
* blob buffer from a KernelImage instead of indirectly writing to a file
* and reading it into a buffer.
*/
if (!WriteKernelImage(tmp_kernelblob_file, image)) {
fprintf(stderr, "Couldn't create a temporary kernel blob file.\n");
error_code = 1;
goto failure;
}
kernel_blob = BufferFromFile(tmp_kernelblob_file, &len);
/* Test Kernel blob verify operations. */
if (!VerifyKernelTest(kernel_blob, firmware_key_blob))
error_code = 255;
/* Test KernelImage verify operations. */
if (!VerifyKernelImageTest(image, firmware_key))
error_code = 255;
if (!VerifyKernelImageTamperTest(image, firmware_key))
error_code = 255;
failure:
Free(kernel_blob);
KernelImageFree(image);
Free(kernel_sign_key_buf);
Free(firmware_key_blob);
Free(firmware_key);
return error_code;
}

View File

@@ -0,0 +1,100 @@
#!/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.
# Run verified boot firmware and kernel verification tests.
return_code=0
hash_algos=( sha1 sha256 sha512 )
key_lengths=( 1024 2048 4096 8192 )
TEST_FILE=test_file
TEST_FILE_SIZE=1000000
COL_RED='\E[31;1m'
COL_GREEN='\E[32;1m'
COL_YELLOW='\E[33;1m'
COL_BLUE='\E[34;1m'
COL_STOP='\E[0;m'
function test_firmware_verification {
algorithmcounter=0
for keylen in ${key_lengths[@]}
do
for hashalgo in ${hash_algos[@]}
do
echo -e "For Root key ${COL_YELLOW}RSA-$keylen/$hashalgo${COL_STOP}:"
cd ${UTIL_DIR} && ${TEST_DIR}/firmware_image_tests $algorithmcounter \
${TEST_DIR}/testkeys/key_rsa8192.pem \
${TEST_DIR}/testkeys/key_rsa8192.keyb \
${TEST_DIR}/testkeys/key_rsa${keylen}.pem \
${TEST_DIR}/testkeys/key_rsa${keylen}.keyb
if [ $? -ne 0 ]
then
return_code=255
fi
let algorithmcounter=algorithmcounter+1
done
done
}
function test_kernel_verification {
# Test for various combinations of firmware signing algorithm and
# kernel signing algorithm
firmware_algorithmcounter=0
kernel_algorithmcounter=0
for firmware_keylen in ${key_lengths[@]}
do
for firmware_hashalgo in ${hash_algos[@]}
do
let kernel_algorithmcounter=0
for kernel_keylen in ${key_lengths[@]}
do
for kernel_hashalgo in ${hash_algos[@]}
do
echo -e "For ${COL_YELLOW}Firmware signing algorithm \
RSA-${firmware_keylen}/${firmware_hashalgo}${COL_STOP} \
and ${COL_YELLOW}Kernel signing algorithm RSA-${kernel_keylen}/\
${kernel_hashalgo}${COL_STOP}"
cd ${UTIL_DIR} && ${TEST_DIR}/kernel_image_tests \
$firmware_algorithmcounter $kernel_algorithmcounter \
${TEST_DIR}/testkeys/key_rsa${firmware_keylen}.pem \
${TEST_DIR}/testkeys/key_rsa${firmware_keylen}.keyb \
${TEST_DIR}/testkeys/key_rsa${kernel_keylen}.pem \
${TEST_DIR}/testkeys/key_rsa${kernel_keylen}.keyb
if [ $? -ne 0 ]
then
return_code=255
fi
let kernel_algorithmcounter=kernel_algorithmcounter+1
done
done
let firmware_algorithmcounter=firmware_algorithmcounter+1
done
done
}
# Determine script directory.
if [[ $0 == '/'* ]];
then
SCRIPT_DIR="`dirname $0`"
elif [[ $0 == './'* ]];
then
SCRIPT_DIR="`pwd`"
else
SCRIPT_DIR="`pwd`"/"`dirname $0`"
fi
UTIL_DIR=`dirname ${SCRIPT_DIR}`/utils
KEY_DIR=${SCRIPT_DIR}/testkeys
TEST_DIR=${SCRIPT_DIR}/
echo
echo "Testing high-level firmware image verification..."
test_firmware_verification
echo
echo "Testing high-level kernel image verification..."
test_kernel_verification
exit $return_code

View File

@@ -4,8 +4,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# Run tests for cryptographic routine implementations - Message digests
# and RSA Signature verification.
# Run tests for RSA Signature verification.
return_code=0
hash_algos=( sha1 sha256 sha512 )
@@ -52,23 +51,6 @@ function test_signatures {
let algorithmcounter=algorithmcounter+1
done
done
}
function test_verification {
algorithmcounter=0
for keylen in ${key_lengths[@]}
do
for hashalgo in ${hash_algos[@]}
do
echo -e "For ${COL_YELLOW}RSA-$keylen and $hashalgo${COL_STOP}:"
cd ${UTIL_DIR} && ${TEST_DIR}/firmware_image_tests $algorithmcounter \
${TEST_DIR}/testkeys/key_rsa8192.pem \
${TEST_DIR}/testkeys/key_rsa8192.keyb \
${TEST_DIR}/testkeys/key_rsa${keylen}.pem \
${TEST_DIR}/testkeys/key_rsa${keylen}.keyb
let algorithmcounter=algorithmcounter+1
done
done
echo -e "Peforming ${COL_YELLOW}PKCS #1 v1.5 Padding Tests${COL_STOP}..."
${TEST_DIR}/rsa_padding_test ${TEST_DIR}/testkeys/rsa_padding_test_pubkey.keyb
}
@@ -107,8 +89,12 @@ echo "Testing signature verification..."
test_signatures
echo
echo "Testing high-level image verification..."
test_verification
echo "Testing high-level firmware image verification..."
test_firmware_verification
echo
echo "Testing high-level kernel image verification..."
test_kernel_verification
echo
echo "Cleaning up..."

View File

@@ -12,7 +12,7 @@ LIBS = -lcrypto
FIRMWARELIBS = $(TOP)/crypto/libcrypto.a $(TOP)/common/libcommon.a
all: dumpRSAPublicKey verify_data signature_digest firmware_utility \
file_keys.o firmware_image.o
file_keys.o firmware_image.o kernel_image.o
dumpRSAPublicKey: dumpRSAPublicKey.c
$(CC) $(CFLAGS) $(LIBS) $< -o $@
@@ -34,7 +34,9 @@ file_keys.o: file_keys.c
firmware_image.o: firmware_image.c
$(CC) $(CFLAGS) -ansi $(INCLUDES) -c $< -o $@
kernel_image.o: kernel_image.c
$(CC) $(CFLAGS) -ansi $(INCLUDES) -c $< -o $@
clean:
rm -f dumpRSAPublicKey verify_data signature_digest firmware_image.o \
file_keys.o firmware_utility
kernel_image.o file_keys.o firmware_utility

614
utils/kernel_image.c Normal file
View File

@@ -0,0 +1,614 @@
/* 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.
*
* Functions for generating and manipulating a verified boot kernel image.
*/
#include "kernel_image.h"
#include <fcntl.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "file_keys.h"
#include "padding.h"
#include "rsa_utility.h"
#include "sha_utility.h"
#include "utility.h"
/* Macro to determine the size of a field structure in the KernelImage
* structure. */
#define FIELD_LEN(field) (sizeof(((KernelImage*)0)->field))
KernelImage* KernelImageNew(void) {
KernelImage* image = (KernelImage*) Malloc(sizeof(KernelImage));
if (image) {
image->kernel_sign_key = NULL;
image->kernel_key_signature = NULL;
image->config_signature = NULL;
image->kernel_signature = NULL;
image->kernel_data = NULL;
}
return image;
}
void KernelImageFree(KernelImage* image) {
if (image) {
Free(image->kernel_sign_key);
Free(image->kernel_key_signature);
Free(image->config_signature);
Free(image->kernel_signature);
Free(image->kernel_data);
Free(image);
}
}
KernelImage* ReadKernelImage(const char* input_file) {
uint32_t file_size;
int image_len = 0; /* Total size of the kernel image. */
int header_len = 0;
int firmware_sign_key_len;
int kernel_key_signature_len;
int kernel_sign_key_len;
int kernel_signature_len;
uint8_t* kernel_buf;
MemcpyState st;
KernelImage* image = KernelImageNew();
if (!image)
return NULL;
kernel_buf = BufferFromFile(input_file, &file_size);
image_len = file_size;
st.remaining_len = image_len;
st.remaining_buf = kernel_buf;
/* Read and compare magic bytes. */
if (!StatefulMemcpy(&st, &image->magic, KERNEL_MAGIC_SIZE))
goto parse_failure;
if (SafeMemcmp(image->magic, KERNEL_MAGIC, KERNEL_MAGIC_SIZE)) {
fprintf(stderr, "Wrong Kernel Magic.\n");
goto parse_failure;
}
StatefulMemcpy(&st, &image->header_version, FIELD_LEN(header_version));
StatefulMemcpy(&st, &image->header_len, FIELD_LEN(header_len));
StatefulMemcpy(&st, &image->firmware_sign_algorithm,
FIELD_LEN(firmware_sign_algorithm));
StatefulMemcpy(&st, &image->kernel_sign_algorithm,
FIELD_LEN(kernel_sign_algorithm));
/* Valid Kernel Key signing algorithm. */
if (image->firmware_sign_algorithm >= kNumAlgorithms)
goto parse_failure;
/* Valid Kernel Signing Algorithm? */
if (image->kernel_sign_algorithm >= kNumAlgorithms)
goto parse_failure;
/* Compute size of pre-processed RSA public keys and signatures. */
firmware_sign_key_len = RSAProcessedKeySize(image->firmware_sign_algorithm);
/* TODO(gauravsh): Make siglen_map track the signature length in number
* of bytes rather than 32-bit words. */
kernel_key_signature_len = (siglen_map[image->firmware_sign_algorithm] *
sizeof(uint32_t));
kernel_sign_key_len = RSAProcessedKeySize(image->kernel_sign_algorithm);
kernel_signature_len = (siglen_map[image->kernel_sign_algorithm] *
sizeof(uint32_t));
/* Check whether key header length is correct. */
header_len = (FIELD_LEN(header_version) +
FIELD_LEN(header_len) +
FIELD_LEN(firmware_sign_algorithm) +
FIELD_LEN(kernel_sign_algorithm) +
FIELD_LEN(kernel_key_version) +
kernel_sign_key_len +
FIELD_LEN(header_checksum));
if (header_len != image->header_len) {
fprintf(stderr, "Header length mismatch. Got: %d, Expected: %d\n",
image->header_len, header_len);
goto parse_failure;
}
/* Read pre-processed public half of the kernel signing key. */
StatefulMemcpy(&st, &image->kernel_key_version,
FIELD_LEN(kernel_key_version));
image->kernel_sign_key = (uint8_t*) Malloc(kernel_sign_key_len);
StatefulMemcpy(&st, image->kernel_sign_key, kernel_sign_key_len);
StatefulMemcpy(&st, image->header_checksum, FIELD_LEN(header_checksum));
/* Read key signature. */
StatefulMemcpy(&st, image->kernel_key_signature,
FIELD_LEN(kernel_key_signature));
/* Read the kernel config. */
StatefulMemcpy(&st, &image->kernel_version, FIELD_LEN(kernel_version));
StatefulMemcpy(&st, &image->options.version, FIELD_LEN(options.version));
StatefulMemcpy(&st, &image->options.kernel_len,
FIELD_LEN(options.kernel_len));
StatefulMemcpy(&st, &image->options.kernel_load_addr,
FIELD_LEN(options.kernel_load_addr));
StatefulMemcpy(&st, &image->options.kernel_entry_addr,
FIELD_LEN(options.kernel_entry_addr));
/* Read kernel config signature. */
image->config_signature = (uint8_t*) Malloc(kernel_signature_len);
StatefulMemcpy(&st, image->config_signature, kernel_signature_len);
image->kernel_signature = (uint8_t*) Malloc(kernel_signature_len);
StatefulMemcpy(&st, image->kernel_signature, kernel_signature_len);
image->kernel_data = (uint8_t*) Malloc(image->options.kernel_len);
StatefulMemcpy(&st, image->kernel_data, image->options.kernel_len);
if(st.remaining_len != 0) /* Overrun or underrun. */
goto parse_failure;
Free(kernel_buf);
return image;
parse_failure:
Free(kernel_buf);
return NULL;
}
void WriteKernelHeader(int fd, KernelImage* image) {
int kernel_sign_key_len;
write(fd, &image->header_version, FIELD_LEN(header_version));
write(fd, &image->header_len, FIELD_LEN(header_len));
write(fd, &image->firmware_sign_algorithm,
FIELD_LEN(firmware_sign_algorithm));
write(fd, &image->kernel_sign_algorithm,
FIELD_LEN(kernel_sign_algorithm));
write(fd, &image->kernel_key_version, FIELD_LEN(kernel_key_version));
kernel_sign_key_len = (image->header_len -
FIELD_LEN(header_version) -
FIELD_LEN(header_len) -
FIELD_LEN(firmware_sign_algorithm) -
FIELD_LEN(kernel_sign_algorithm) -
FIELD_LEN(kernel_key_version) -
FIELD_LEN(header_checksum));
write(fd, image->kernel_sign_key, kernel_sign_key_len);
write(fd, &image->header_checksum, FIELD_LEN(header_checksum));
}
void WriteKernelConfig(int fd, KernelImage* image) {
write(fd, &image->kernel_version, FIELD_LEN(kernel_version));
write(fd, image->options.version, FIELD_LEN(options.version));
write(fd, &image->options.kernel_len, FIELD_LEN(options.kernel_len));
write(fd, &image->options.kernel_load_addr,
FIELD_LEN(options.kernel_load_addr));
write(fd, &image->options.kernel_entry_addr,
FIELD_LEN(options.kernel_entry_addr));
}
KernelImage* WriteKernelImage(const char* input_file,
KernelImage* image) {
int fd;
int kernel_key_signature_len;
int kernel_signature_len;
if (!image)
return NULL;
if (-1 == (fd = creat(input_file,
S_IRUSR | S_IWUSR))) { /* Owner has R/W permissions. */
fprintf(stderr, "Couldn't open file for writing.\n");
return NULL;
}
kernel_key_signature_len = (siglen_map[image->firmware_sign_algorithm] *
sizeof(uint32_t));
kernel_signature_len = (siglen_map[image->kernel_sign_algorithm] *
sizeof(uint32_t));
write(fd, image->magic, FIELD_LEN(magic));
WriteKernelHeader(fd, image);
write(fd, image->kernel_key_signature, kernel_key_signature_len);
WriteKernelConfig(fd, image);
write(fd, image->config_signature, kernel_signature_len);
write(fd, image->kernel_signature, kernel_signature_len);
write(fd, image->kernel_data, image->options.kernel_len);
close(fd);
return image;
}
void PrintKernelImage(const KernelImage* image) {
if (!image)
return;
/* Print header. */
printf("Header Length = %d\n"
"Firmware Signing key algorithm id = %d\n"
"Kernel Signing key algorithm id = %d\n"
"Kernel Signature Algorithm = %s\n"
"Kernel Key Version = %d\n\n",
image->header_len,
image->firmware_sign_algorithm,
image->kernel_sign_algorithm,
algo_strings[image->kernel_sign_algorithm],
image->kernel_key_version);
/* TODO(gauravsh): Output hash and key signature here? */
/* Print preamble. */
printf("Kernel Version = %d\n"
"Kernel Config Version = %d.%d\n"
"kernel Length = %d\n"
"Kernel Load Address = %" PRId64 "\n"
"Kernel Entry Address = %" PRId64 "\n\n",
image->kernel_version,
image->options.version[0], image->options.version[1],
image->options.kernel_len,
image->options.kernel_load_addr,
image->options.kernel_entry_addr);
/* TODO(gauravsh): Output kernel signature here? */
}
char* kVerifyKernelErrors[VERIFY_KERNEL_MAX] = {
"Success.",
"Invalid Image.",
"Kernel Key Signature Failed.",
"Invalid Kernel Verification Algorithm.",
"Config Signature Failed.",
"Kernel Signature Failed.",
"Wrong Kernel Magic.",
};
int VerifyKernelHeader(const uint8_t* firmware_key_blob,
const uint8_t* header_blob,
const int dev_mode,
int* firmware_algorithm,
int* kernel_algorithm,
int* kernel_header_len) {
int kernel_sign_key_len;
int firmware_sign_key_len;
uint16_t header_version, header_len;
uint16_t firmware_sign_algorithm, kernel_sign_algorithm;
uint8_t* header_checksum = NULL;
/* Base Offset for the header_checksum field. Actual offset is
* this + kernel_sign_key_len. */
int base_header_checksum_offset = (FIELD_LEN(header_version) +
FIELD_LEN(header_len) +
FIELD_LEN(firmware_sign_algorithm) +
FIELD_LEN(kernel_sign_algorithm) +
FIELD_LEN(kernel_key_version));
Memcpy(&header_version, header_blob, sizeof(header_version));
Memcpy(&header_len, header_blob + FIELD_LEN(header_version),
sizeof(header_len));
Memcpy(&firmware_sign_algorithm,
header_blob + (FIELD_LEN(header_version) +
FIELD_LEN(header_len)),
sizeof(firmware_sign_algorithm));
Memcpy(&kernel_sign_algorithm,
header_blob + (FIELD_LEN(header_version) +
FIELD_LEN(header_len) +
FIELD_LEN(firmware_sign_algorithm)),
sizeof(kernel_sign_algorithm));
/* TODO(gauravsh): Make this return two different error types depending
* on whether the firmware or kernel signing algorithm is invalid. */
if (firmware_sign_algorithm >= kNumAlgorithms)
return VERIFY_KERNEL_INVALID_ALGORITHM;
if (kernel_sign_algorithm >= kNumAlgorithms)
return VERIFY_KERNEL_INVALID_ALGORITHM;
*firmware_algorithm = (int) firmware_sign_algorithm;
*kernel_algorithm = (int) kernel_sign_algorithm;
kernel_sign_key_len = RSAProcessedKeySize(kernel_sign_algorithm);
firmware_sign_key_len = RSAProcessedKeySize(firmware_sign_algorithm);
/* Verify if header len is correct? */
if (header_len != (base_header_checksum_offset +
kernel_sign_key_len +
FIELD_LEN(header_checksum))) {
fprintf(stderr, "VerifyKernelHeader: Header length mismatch\n");
return VERIFY_KERNEL_INVALID_IMAGE;
}
*kernel_header_len = (int) header_len;
/* Verify if the hash of the header is correct. */
header_checksum = DigestBuf(header_blob,
header_len - FIELD_LEN(header_checksum),
SHA512_DIGEST_ALGORITHM);
if (SafeMemcmp(header_checksum,
header_blob + (base_header_checksum_offset +
kernel_sign_key_len),
FIELD_LEN(header_checksum))) {
Free(header_checksum);
return VERIFY_KERNEL_INVALID_IMAGE;
}
Free(header_checksum);
/* Verify kernel key signature unless we are in dev mode. */
if (!dev_mode) {
if (!RSAVerifyBinary_f(firmware_key_blob, NULL, /* Key to use */
header_blob, /* Data to verify */
header_len, /* Length of data */
header_blob + header_len, /* Expected Signature */
firmware_sign_algorithm))
return VERIFY_KERNEL_KEY_SIGNATURE_FAILED;
}
return 0;
}
int VerifyKernelConfig(RSAPublicKey* kernel_sign_key,
const uint8_t* config_blob,
int algorithm,
int* kernel_len) {
uint32_t len, config_len;
config_len = (FIELD_LEN(kernel_version) +
FIELD_LEN(options.version)+
FIELD_LEN(options.kernel_len) +
FIELD_LEN(options.kernel_load_addr) +
FIELD_LEN(options.kernel_entry_addr));
if (!RSAVerifyBinary_f(NULL, kernel_sign_key, /* Key to use */
config_blob, /* Data to verify */
config_len, /* Length of data */
config_blob + config_len, /* Expected Signature */
algorithm))
return VERIFY_KERNEL_CONFIG_SIGNATURE_FAILED;
Memcpy(&len, config_blob + (FIELD_LEN(kernel_version)+
FIELD_LEN(options.version)),
sizeof(len));
*kernel_len = (int) len;
return 0;
}
int VerifyKernelData(RSAPublicKey* kernel_sign_key,
const uint8_t* kernel_data_start,
int kernel_len,
int algorithm) {
int signature_len = siglen_map[algorithm] * sizeof(uint32_t);
if (!RSAVerifyBinary_f(NULL, kernel_sign_key, /* Key to use. */
kernel_data_start + signature_len, /* Data to
* verify */
kernel_len, /* Length of data. */
kernel_data_start, /* Expected Signature */
algorithm))
return VERIFY_KERNEL_SIGNATURE_FAILED;
return 0;
}
int VerifyKernel(const uint8_t* firmware_key_blob,
const uint8_t* kernel_blob,
const int dev_mode) {
int error_code;
int firmware_sign_algorithm; /* Firmware signing key algorithm. */
int kernel_sign_algorithm; /* Kernel Signing key algorithm. */
RSAPublicKey* kernel_sign_key;
int kernel_sign_key_len, kernel_key_signature_len, kernel_signature_len,
header_len, kernel_len;
const uint8_t* header_ptr; /* Pointer to header. */
const uint8_t* kernel_sign_key_ptr; /* Pointer to signing key. */
const uint8_t* config_ptr; /* Pointer to kernel config block. */
const uint8_t* kernel_ptr; /* Pointer to kernel signature/data. */
/* Note: All the offset calculations are based on struct FirmwareImage which
* is defined in include/firmware_image.h. */
/* Compare magic bytes. */
if (SafeMemcmp(kernel_blob, KERNEL_MAGIC, KERNEL_MAGIC_SIZE))
return VERIFY_KERNEL_WRONG_MAGIC;
header_ptr = kernel_blob + KERNEL_MAGIC_SIZE;
/* Only continue if header verification succeeds. */
if ((error_code = VerifyKernelHeader(firmware_key_blob, header_ptr, dev_mode,
&firmware_sign_algorithm,
&kernel_sign_algorithm, &header_len))) {
fprintf(stderr, "VerifyKernel: Kernel header verification failed.\n");
return error_code; /* AKA jump to recovery. */
}
/* Parse signing key into RSAPublicKey structure since it is required multiple
* times. */
kernel_sign_key_len = RSAProcessedKeySize(kernel_sign_algorithm);
kernel_sign_key_ptr = header_ptr + (FIELD_LEN(header_version) +
FIELD_LEN(header_len) +
FIELD_LEN(firmware_sign_algorithm) +
FIELD_LEN(kernel_sign_algorithm) +
FIELD_LEN(kernel_key_version));
kernel_sign_key = RSAPublicKeyFromBuf(kernel_sign_key_ptr,
kernel_sign_key_len);
kernel_signature_len = siglen_map[kernel_sign_algorithm] * sizeof(uint32_t);
kernel_key_signature_len = siglen_map[firmware_sign_algorithm] *
sizeof(uint32_t);
/* Only continue if config verification succeeds. */
config_ptr = (header_ptr + header_len + kernel_key_signature_len);
if ((error_code = VerifyKernelConfig(kernel_sign_key, config_ptr,
kernel_sign_algorithm,
&kernel_len)))
return error_code; /* AKA jump to recovery. */
/* Only continue if kernel data verification succeeds. */
kernel_ptr = (config_ptr +
FIELD_LEN(kernel_version) +
FIELD_LEN(options.version) +
FIELD_LEN(options.kernel_len) +
FIELD_LEN(options.kernel_entry_addr) +
FIELD_LEN(options.kernel_load_addr) +
kernel_signature_len);
if ((error_code = VerifyKernelData(kernel_sign_key, kernel_ptr, kernel_len,
kernel_sign_algorithm)))
return error_code; /* AKA jump to recovery. */
return 0; /* Success! */
}
int VerifyKernelImage(const RSAPublicKey* firmware_key,
const KernelImage* image,
const int dev_mode) {
RSAPublicKey* kernel_sign_key;
uint8_t* header_digest = NULL;
uint8_t* config_digest = NULL;
uint8_t* kernel_digest = NULL;
int kernel_sign_key_size;
int kernel_signature_size;
int error_code = 0;
DigestContext ctx;
if (!image)
return VERIFY_KERNEL_INVALID_IMAGE;
/* Verify kernel key signature on the key header if we
* are not in dev mode.
*
* TODO(gauravsh): Add additional sanity checks here for:
* 1) verifying the header length is correct.
* 2) header_checksum is correct.
*/
if (image->firmware_sign_algorithm >= kNumAlgorithms)
return VERIFY_KERNEL_INVALID_ALGORITHM;
if (image->kernel_sign_algorithm >= kNumAlgorithms)
return VERIFY_KERNEL_INVALID_ALGORITHM;
if (!dev_mode) {
DigestInit(&ctx, image->firmware_sign_algorithm);
DigestUpdate(&ctx, (uint8_t*) &image->header_version,
FIELD_LEN(header_version));
DigestUpdate(&ctx, (uint8_t*) &image->header_len,
FIELD_LEN(header_len));
DigestUpdate(&ctx, (uint8_t*) &image->firmware_sign_algorithm,
FIELD_LEN(firmware_sign_algorithm));
DigestUpdate(&ctx, (uint8_t*) &image->kernel_sign_algorithm,
FIELD_LEN(kernel_sign_algorithm));
DigestUpdate(&ctx, (uint8_t*) &image->kernel_key_version,
FIELD_LEN(kernel_key_version));
DigestUpdate(&ctx, image->kernel_sign_key,
RSAProcessedKeySize(image->kernel_sign_algorithm));
DigestUpdate(&ctx, image->header_checksum,
FIELD_LEN(header_checksum));
header_digest = DigestFinal(&ctx);
if (!RSA_verify(firmware_key, image->kernel_key_signature,
siglen_map[image->firmware_sign_algorithm] *
sizeof(uint32_t),
image->firmware_sign_algorithm,
header_digest)) {
fprintf(stderr, "VerifyKernelImage(): Key signature check failed.\n");
error_code = VERIFY_KERNEL_KEY_SIGNATURE_FAILED;
goto verify_failure;
}
}
/* Get kernel signing key to verify the rest of the kernel. */
kernel_sign_key_size = RSAProcessedKeySize(image->kernel_sign_algorithm);
kernel_sign_key = RSAPublicKeyFromBuf(image->kernel_sign_key,
kernel_sign_key_size);
kernel_signature_size = siglen_map[image->kernel_sign_algorithm] *
sizeof(uint32_t);
/* Verify kernel config signature. */
DigestInit(&ctx, image->kernel_sign_algorithm);
DigestUpdate(&ctx, (uint8_t*) &image->kernel_version,
FIELD_LEN(kernel_version));
DigestUpdate(&ctx, (uint8_t*) &image->options.version,
FIELD_LEN(options.version));
DigestUpdate(&ctx, (uint8_t*) &image->options.kernel_len,
FIELD_LEN(options.kernel_len));
DigestUpdate(&ctx, (uint8_t*) &image->options.kernel_load_addr,
FIELD_LEN(options.kernel_load_addr));
DigestUpdate(&ctx, (uint8_t*) &image->options.kernel_entry_addr,
FIELD_LEN(options.kernel_entry_addr));
config_digest = DigestFinal(&ctx);
if (!RSA_verify(kernel_sign_key, image->config_signature,
kernel_signature_size, image->kernel_sign_algorithm,
config_digest)) {
error_code = VERIFY_KERNEL_CONFIG_SIGNATURE_FAILED;
goto verify_failure;
}
/* Verify firmware signature. */
kernel_digest = DigestBuf(image->kernel_data,
image->options.kernel_len,
image->kernel_sign_algorithm);
if(!RSA_verify(kernel_sign_key, image->kernel_signature,
kernel_signature_size, image->kernel_sign_algorithm,
kernel_digest)) {
error_code = VERIFY_KERNEL_SIGNATURE_FAILED;
goto verify_failure;
}
verify_failure:
Free(kernel_digest);
Free(config_digest);
Free(header_digest);
return error_code;
}
const char* VerifyKernelErrorString(int error) {
return kVerifyKernelErrors[error];
}
int AddKernelKeySignature(KernelImage* image, const char* firmware_key_file) {
int tmp_hdr_fd;
char* tmp_hdr_file = ".tmpKernelHdrFile";
uint8_t* signature;
int signature_len = siglen_map[image->firmware_sign_algorithm] *
sizeof(uint32_t);
if(-1 == (tmp_hdr_fd = creat(tmp_hdr_file, S_IRWXU))) {
fprintf(stderr, "Could not open temporary file for writing "
"kernel header.\n");
return 0;
}
WriteKernelHeader(tmp_hdr_fd, image);
close(tmp_hdr_fd);
if (!(signature = SignatureFile(tmp_hdr_file, firmware_key_file,
image->firmware_sign_algorithm)))
return 0;
image->kernel_key_signature = Malloc(signature_len);
Memcpy(image->kernel_key_signature, signature, signature_len);
return 1;
}
int AddKernelSignature(KernelImage* image, const char* kernel_signing_key_file,
int algorithm) {
int tmp_config_fd;
char* tmp_config_file = ".tmpConfigFile";
int tmp_kernel_fd;
char* tmp_kernel_file = ".tmpKernelFile";
uint8_t* config_signature;
uint8_t* kernel_signature;
int signature_len = siglen_map[algorithm] * sizeof(uint32_t);
/* Write config to a file. */
if(-1 == (tmp_config_fd = creat(tmp_config_file, S_IRWXU))) {
fprintf(stderr, "Could not open temporary file for writing "
"kernel config.\n");
return 0;
}
WriteKernelConfig(tmp_config_fd, image);
close(tmp_config_fd);
if (!(config_signature = SignatureFile(tmp_config_file,
kernel_signing_key_file,
algorithm)))
return 0;
image->config_signature = (uint8_t*) Malloc(signature_len);
Memcpy(image->config_signature, config_signature, signature_len);
Free(config_signature);
if (-1 == (tmp_kernel_fd = creat(tmp_kernel_file, S_IRWXU))) {
fprintf(stderr, "Could not open temporary file for writing "
"kernel.\n");
return 0;
}
write(tmp_kernel_fd, image->kernel_data, image->options.kernel_len);
close(tmp_kernel_fd);
if (!(kernel_signature = SignatureFile(tmp_kernel_file,
kernel_signing_key_file,
algorithm))) {
fprintf(stderr, "Could not compute signature on the kernel.\n");
return 0;
}
image->kernel_signature = (uint8_t*) Malloc(signature_len);
Memcpy(image->kernel_signature, kernel_signature, signature_len);
Free(kernel_signature);
return 1;
}