diff --git a/common/utility_stub.c b/common/utility_stub.c index 101211296d..8d21897747 100644 --- a/common/utility_stub.c +++ b/common/utility_stub.c @@ -48,14 +48,23 @@ int SafeMemcmp(const void* s1, const void* s2, size_t n) { } void* StatefulMemcpy(MemcpyState* state, void* dst, int len) { - void* saved_ptr; if (len > state->remaining_len) { state->remaining_len = -1; return NULL; } - saved_ptr = state->remaining_buf; - Memcpy(dst, saved_ptr, len); + Memcpy(dst, state->remaining_buf, len); state->remaining_buf += len; state->remaining_len -= len; return dst; } + +const void* StatefulMemcpy_r(MemcpyState* state, const void* src, int len) { + if (len > state->remaining_len) { + state->remaining_len = -1; + return NULL; + } + Memcpy(state->remaining_buf, src, len); + state->remaining_buf += len; + state->remaining_len -= len; + return src; +} diff --git a/crypto/rsa.c b/crypto/rsa.c index d23be89c9b..c84ae4e8da 100644 --- a/crypto/rsa.c +++ b/crypto/rsa.c @@ -127,11 +127,11 @@ static void modpowF4(const RSAPublicKey *key, /* Verify a RSA PKCS1.5 signature against an expected hash. * Returns 0 on failure, 1 on success. */ -int RSA_verify(const RSAPublicKey *key, - const uint8_t *sig, - const int sig_len, - const uint8_t sig_type, - const uint8_t *hash) { +int RSAVerify(const RSAPublicKey *key, + const uint8_t *sig, + const int sig_len, + const uint8_t sig_type, + const uint8_t *hash) { int i; uint8_t* buf; const uint8_t* padding; diff --git a/crypto/rsa_utility.c b/crypto/rsa_utility.c index ecb00a1bc3..e0071c16d4 100644 --- a/crypto/rsa_utility.c +++ b/crypto/rsa_utility.c @@ -79,7 +79,7 @@ int RSAVerifyBinary_f(const uint8_t* key_blob, return 0; /* Both can't be NULL or non-NULL. */ digest = DigestBuf(buf, len, algorithm); - success = RSA_verify(verification_key, sig, sig_size, algorithm, digest); + success = RSAVerify(verification_key, sig, sig_size, algorithm, digest); Free(digest); if (!key) diff --git a/include/firmware_image.h b/include/firmware_image.h index 9a6ad19d10..67250f36b9 100644 --- a/include/firmware_image.h +++ b/include/firmware_image.h @@ -25,12 +25,14 @@ typedef struct FirmwareImage { uint8_t magic[FIRMWARE_MAGIC_SIZE]; /* Key Header */ uint16_t header_len; /* Length of the header. */ - uint16_t sign_algorithm; /* Signature algorithm used by the signing key. */ - uint8_t* sign_key; /* Pre-processed public half of signing key. */ - uint16_t key_version; /* Key Version# for preventing rollbacks. */ + uint16_t firmware_sign_algorithm; /* Signature algorithm used by the signing + * key. */ + uint8_t* firmware_sign_key; /* Pre-processed public half of signing key. */ + uint16_t firmware_key_version; /* Key Version# for preventing rollbacks. */ uint8_t header_checksum[SHA512_DIGEST_SIZE]; /* SHA-512 hash of the header.*/ - uint8_t key_signature[RSA8192NUMBYTES]; /* Signature of the header above. */ + uint8_t firmware_key_signature[RSA8192NUMBYTES]; /* Signature of the header + * above. */ /* Firmware Preamble. */ uint16_t firmware_version; /* Firmware Version# for preventing rollbacks.*/ @@ -53,29 +55,38 @@ FirmwareImage* FirmwareImageNew(void); /* Deep free the contents of [fw]. */ void FirmwareImageFree(FirmwareImage* fw); -/* Read firmware data from file named [input_file].. +/* Read firmware data from file named [input_file]. * * Returns a filled up FirmwareImage structure on success, NULL on error. */ FirmwareImage* ReadFirmwareImage(const char* input_file); -/* Write firmware header from [image] to an open file pointed by the - * file descriptor [fd]. +/* Get firmware header binary blob from an [image]. + * + * Caller owns the returned pointer and must Free() it. */ -void WriteFirmwareHeader(int fd, FirmwareImage* image); +uint8_t* GetFirmwareHeaderBlob(const FirmwareImage* image); -/* Write firmware preamble from [image] to an open file pointed by the - * file descriptor [fd]. +/* Get firmware preamble binary blob from an [image]. + * + * Caller owns the returned pointer and must Free() it. */ -void WriteFirmwarePreamble(int fd, FirmwareImage* image); +uint8_t* GetFirmwarePreambleBlob(const FirmwareImage* image); +/* Get a verified firmware binary blob from an [image] and fill its + * length into blob_len. + * + * Caller owns the returned pointer and must Free() it. + */ +uint8_t* GetFirmwareBlob(const FirmwareImage* image, int* blob_len); /* Write firmware data from [image] into a file named [input_file]. * - * Return [image] on success, NULL on error. + * Return 1 on success, 0 on failure. */ -FirmwareImage* WriteFirmwareImage(const char* input_file, - FirmwareImage* image); +int WriteFirmwareImage(const char* input_file, + const FirmwareImage* image); + /* Pretty print the contents of [image]. Only headers and metadata information * is printed. @@ -173,7 +184,6 @@ int AddFirmwareKeySignature(FirmwareImage* image, const char* root_key_file); * * Return 1 on success, 0 on failure. */ -int AddFirmwareSignature(FirmwareImage* image, const char* signing_key_file, - int algorithm); +int AddFirmwareSignature(FirmwareImage* image, const char* signing_key_file); #endif /* VBOOT_REFERENCE_FIRMWARE_IMAGE_H_ */ diff --git a/include/firmware_utility.h b/include/firmware_utility.h index 72cbc85126..86e2ad216a 100644 --- a/include/firmware_utility.h +++ b/include/firmware_utility.h @@ -51,10 +51,10 @@ class FirmwareUtility { std::string root_key_file_; std::string root_key_pub_file_; int firmware_version_; - std::string sign_key_file_; - std::string sign_key_pub_file_; - int key_version_; - int sign_algorithm_; + std::string firmware_sign_key_file_; + std::string firmware_sign_key_pub_file_; + int firmware_key_version_; + int firmware_sign_algorithm_; std::string in_file_; std::string out_file_; bool is_generate_; // Are we generating a new image? diff --git a/include/kernel_image.h b/include/kernel_image.h index c65c614376..4fb79ac13d 100644 --- a/include/kernel_image.h +++ b/include/kernel_image.h @@ -74,22 +74,31 @@ void KernelImageFree(KernelImage* image); */ KernelImage* ReadKernelImage(const char* input_file); -/* Write kernel key header from [image] to an open file pointed by the - * file descriptor [fd]. +/* Get kernel header binary blob from an [image]. + * + * Caller owns the returned pointer and must Free() it. */ -void WriteKernelHeader(int fd, KernelImage* image); +uint8_t* GetKernelHeaderBlob(const KernelImage* image); -/* Write kernel config from [image] to an open file pointed by the - * file descriptor [fd]. +/* Get kernel config binary blob from an [image]. + * + * Caller owns the returned pointer and must Free() it. */ -void WriteKernelConfig(int fd, KernelImage* image); +uint8_t* GetKernelConfigBlob(const KernelImage* image); + +/* Get a verified kernel binary blob from an [image] and fill + * its length into blob_len. + * + * Caller owns the returned pointer and must Free() it. + */ +uint8_t* GetKernelBlob(const KernelImage* image, int* blob_len); /* Write kernel data from [image] to a file named [input_file]. * - * Return [image] on success, NULL on error. + * Return 1 on success, 0 on error. */ -KernelImage* WriteKernelImage(const char* input_file, - KernelImage* image); +int WriteKernelImage(const char* input_file, + const KernelImage* image); /* Pretty print the contents of [image]. Only headers and metadata information * is printed. @@ -194,7 +203,7 @@ int AddKernelKeySignature(KernelImage* image, const char* firmware_key_file); * * Return 1 on success, 0 on failure. */ -int AddKernelSignature(KernelImage* image, const char* kernel_sigining_key_file, - int algorithm); +int AddKernelSignature(KernelImage* image, + const char* kernel_sigining_key_file); #endif /* VBOOT_REFERENCE_KERNEL_IMAGE_H_ */ diff --git a/include/rsa.h b/include/rsa.h index 1969ab651d..8f2ede8a6a 100644 --- a/include/rsa.h +++ b/include/rsa.h @@ -28,7 +28,7 @@ typedef struct RSAPublicKey { /* Verify a RSA PKCS1.5 signature [sig] of [sig_type] and length [sig_len] * against an expected [hash] using [key]. Returns 0 on failure, 1 on success. */ -int RSA_verify(const RSAPublicKey *key, +int RSAVerify(const RSAPublicKey *key, const uint8_t* sig, const int sig_len, const uint8_t sig_type, diff --git a/include/signature_digest.h b/include/signature_digest.h index fcd72753a3..291c5994ab 100644 --- a/include/signature_digest.h +++ b/include/signature_digest.h @@ -13,4 +13,23 @@ */ uint8_t* prepend_digestinfo(int algorithm, uint8_t* digest); +/* Function that outputs the message digest of the contents of a buffer in a + * format that can be used as input to OpenSSL for an RSA signature. + * Needed until the stable OpenSSL release supports SHA-256/512 digests for + * RSA signatures. + * + * Returns DigestInfo || Digest where DigestInfo is the OID depending on the + * choice of the hash algorithm (see padding.c). Caller owns the returned + * pointer and must Free() it. + */ +uint8_t* SignatureDigest(const uint8_t* buf, int len, int algorithm); + +/* Calculates the signature on a buffer [buf] of length [len] using + * the private RSA key file from [key_file] and signature algorithm + * [algorithm]. + * + * Returns the signature. Caller owns the buffer and must Free() it. + */ +uint8_t* SignatureBuf(const uint8_t* buf, int len, const char* key_file, + int algorithm); #endif /* VBOOT_REFERENCE_SIGNATURE_DIGEST_H_ */ diff --git a/include/utility.h b/include/utility.h index 36182632d3..b26e247790 100644 --- a/include/utility.h +++ b/include/utility.h @@ -41,7 +41,7 @@ typedef struct MemcpyState { /* Copy [len] bytes into [dst] only if there's enough data to read according * to [state]. - * On success, return [dst] and update [state].. + * On success, return [dst] and update [state]. * On failure, return NULL, set remaining len in state to -1. * * Useful for iterating through a binary blob to populate a struct. After the @@ -49,5 +49,14 @@ typedef struct MemcpyState { */ void* StatefulMemcpy(MemcpyState* state, void* dst, int len); +/* Like StatefulMemcpy() but copies in the opposite direction, populating + * data from [src] into the buffer encapsulated in state [state]. + * On success, return [src] and update [state]. + * On failure, return NULL, set remaining_len in state to -1. + * + * Useful for iterating through a structure to populate a binary blob. After the + * first failure (buffer overrun), successive calls will always fail. + */ +const void* StatefulMemcpy_r(MemcpyState* state, const void* src, int len); #endif /* VBOOT_REFERENCE_UTILITY_H_ */ diff --git a/tests/Makefile b/tests/Makefile index 57fecd7bf1..6bdbae0ccf 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -7,30 +7,30 @@ CFLAGS = -Wall -DNDEBUG INCLUDES ?= -I../include/ TOP ?= ../ +FIRMWARE_LIBS = $(TOP)/crypto/libcrypto.a $(TOP)/common/libcommon.a 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 + $(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 sha_tests: sha_tests.c - $(CC) $(CFLAGS) $(INCLUDES) $< -o $@ $(LIBS) + $(CC) $(CFLAGS) $(INCLUDES) $^ -o $@ $(FIRMWARE_LIBS) -firmware_image_tests: firmware_image_tests.c $(LIBS) - $(CC) $(CFLAGS) $(INCLUDES) $< -o $@ $(LIBS) +firmware_image_tests: firmware_image_tests.c + $(CC) $(CFLAGS) $(INCLUDES) $< -o $@ $(LIBS) $(FIRMWARE_LIBS) -kernel_image_tests: kernel_image_tests.c $(LIBS) - $(CC) $(CFLAGS) $(INCLUDES) $< -o $@ $(LIBS) +kernel_image_tests: kernel_image_tests.c + $(CC) $(CFLAGS) $(INCLUDES) $< -o $@ $(LIBS) $(FIRMWARE_LIBS) -sha_benchmark: sha_benchmark.c timer_utils.c - $(CC) $(CFLAGS) $(INCLUDES) $^ -o $@ $(LIBS) +sha_benchmark: sha_benchmark.c timer_utils.c $(FIRMWARE_LIBS) + $(CC) $(CFLAGS) $(INCLUDES) $^ -o $@ -lrt rsa_padding_test: rsa_padding_test.c - $(CC) $(CFLAGS) $(INCLUDES) $^ -o $@ $(LIBS) + $(CC) $(CFLAGS) $(INCLUDES) $^ -o $@ $(LIBS) $(FIRMWARE_LIBS) rsa_verify_benchmark: rsa_verify_benchmark.c timer_utils.c - $(CC) $(CFLAGS) $(INCLUDES) $^ -o $@ $(LIBS) + $(CC) $(CFLAGS) $(INCLUDES) $^ -o $@ -lrt $(LIBS) $(FIRMWARE_LIBS) clean: rm -f sha_tests sha_benchmark rsa_verify_benchmark \ diff --git a/tests/firmware_image_tests.c b/tests/firmware_image_tests.c index ff7b509cd5..8bb16c6d49 100644 --- a/tests/firmware_image_tests.c +++ b/tests/firmware_image_tests.c @@ -31,8 +31,8 @@ int TEST_EQ(int result, int expected_result, char* testname) { } FirmwareImage* GenerateTestFirmwareImage(int algorithm, - uint8_t* sign_key, - int key_version, + uint8_t* firmware_sign_key, + int firmware_key_version, int firmware_version, int firmware_len) { FirmwareImage* image = FirmwareImageNew(); @@ -40,29 +40,30 @@ FirmwareImage* GenerateTestFirmwareImage(int algorithm, DigestContext ctx; Memcpy(image->magic, FIRMWARE_MAGIC, FIRMWARE_MAGIC_SIZE); - image->sign_algorithm = algorithm; - image->sign_key = (uint8_t*) Malloc( - RSAProcessedKeySize(image->sign_algorithm)); - Memcpy(image->sign_key, sign_key, RSAProcessedKeySize(image->sign_algorithm)); - image->key_version = key_version; + image->firmware_sign_algorithm = algorithm; + image->firmware_sign_key = (uint8_t*) Malloc( + RSAProcessedKeySize(image->firmware_sign_algorithm)); + Memcpy(image->firmware_sign_key, firmware_sign_key, + RSAProcessedKeySize(image->firmware_sign_algorithm)); + image->firmware_key_version = firmware_key_version; /* Update correct header length. */ image->header_len = (sizeof(image->header_len) + - sizeof(image->sign_algorithm) + - RSAProcessedKeySize(image->sign_algorithm) + - sizeof(image->key_version) + + sizeof(image->firmware_sign_algorithm) + + RSAProcessedKeySize(image->firmware_sign_algorithm) + + sizeof(image->firmware_key_version) + sizeof(image->header_checksum)); /* Calculate SHA-512 digest on header and populate header_checksum. */ DigestInit(&ctx, ROOT_SIGNATURE_ALGORITHM); DigestUpdate(&ctx, (uint8_t*) &image->header_len, sizeof(image->header_len)); - DigestUpdate(&ctx, (uint8_t*) &image->sign_algorithm, - sizeof(image->sign_algorithm)); - DigestUpdate(&ctx, image->sign_key, - RSAProcessedKeySize(image->sign_algorithm)); - DigestUpdate(&ctx, (uint8_t*) &image->key_version, - sizeof(image->key_version)); + DigestUpdate(&ctx, (uint8_t*) &image->firmware_sign_algorithm, + sizeof(image->firmware_sign_algorithm)); + DigestUpdate(&ctx, image->firmware_sign_key, + RSAProcessedKeySize(image->firmware_sign_algorithm)); + DigestUpdate(&ctx, (uint8_t*) &image->firmware_key_version, + sizeof(image->firmware_key_version)); header_checksum = DigestFinal(&ctx); Memcpy(image->header_checksum, header_checksum, SHA512_DIGEST_SIZE); Free(header_checksum); @@ -144,8 +145,8 @@ int VerifyFirmwareImageTamperTest(FirmwareImage* image, fprintf(stderr, "[[Tampering with root key signature...]]\n"); - image->key_signature[0] = 0xFF; - image->key_signature[1] = 0x00; + image->firmware_key_signature[0] = 0xFF; + image->firmware_key_signature[1] = 0x00; if (!TEST_EQ(VerifyFirmwareImage(root_key, image, DEV_MODE_ENABLED), VERIFY_FIRMWARE_SUCCESS, "FirmwareImage Root Signature Tamper Verification (Dev Mode)")) @@ -160,13 +161,13 @@ int VerifyFirmwareImageTamperTest(FirmwareImage* image, int main(int argc, char* argv[]) { uint32_t len; - uint8_t* sign_key_buf = NULL; + uint8_t* firmware_sign_key_buf = NULL; uint8_t* root_key_blob = NULL; uint8_t* firmware_blob = NULL; + int firmware_blob_len = 0; FirmwareImage* image = NULL; RSAPublicKey* root_key = NULL; int error_code = 1; - char* tmp_firmwareblob_file = ".tmpFirmwareBlob"; if(argc != 6) { fprintf(stderr, "Usage: %s " @@ -177,11 +178,11 @@ int main(int argc, char* argv[]) { /* Read verification keys and create a test image. */ root_key = RSAPublicKeyFromFile(argv[3]); root_key_blob = BufferFromFile(argv[3], &len); - sign_key_buf = BufferFromFile(argv[5], &len); - image = GenerateTestFirmwareImage(atoi(argv[1]), sign_key_buf, 1, + firmware_sign_key_buf = BufferFromFile(argv[5], &len); + image = GenerateTestFirmwareImage(atoi(argv[1]), firmware_sign_key_buf, 1, 1, 1000); - if (!root_key || !sign_key_buf || !image) { + if (!root_key || !firmware_sign_key_buf || !image) { error_code = 1; goto failure; } @@ -193,25 +194,13 @@ int main(int argc, char* argv[]) { goto failure; } - if (!AddFirmwareSignature(image, argv[4], image->sign_algorithm)) { + if (!AddFirmwareSignature(image, argv[4])) { fprintf(stderr, "Couldn't create firmware and preamble signature.\n"); error_code = 1; goto failure; } - - /* Generate a firmware binary blob from image. - * - * TODO(gauravsh): There should be a function to directly generate a binary - * blob buffer from a FirmwareImage instead of indirectly writing to a file - * and reading it into a buffer. - */ - if (!WriteFirmwareImage(tmp_firmwareblob_file, image)) { - fprintf(stderr, "Couldn't create a temporary firmware blob file.\n"); - error_code = 1; - goto failure; - } - firmware_blob = BufferFromFile(tmp_firmwareblob_file, &len); + firmware_blob = GetFirmwareBlob(image, &firmware_blob_len); /* Test Firmware blob verify operations. */ if (!VerifyFirmwareTest(firmware_blob, root_key_blob)) @@ -226,7 +215,7 @@ int main(int argc, char* argv[]) { failure: Free(firmware_blob); Free(image); - Free(sign_key_buf); + Free(firmware_sign_key_buf); Free(root_key_blob); Free(root_key); diff --git a/tests/kernel_image_tests.c b/tests/kernel_image_tests.c index 62ca560285..05dec73661 100644 --- a/tests/kernel_image_tests.c +++ b/tests/kernel_image_tests.c @@ -174,10 +174,10 @@ int main(int argc, char* argv[]) { uint8_t* kernel_sign_key_buf = NULL; uint8_t* firmware_key_blob = NULL; uint8_t* kernel_blob = NULL; + int kernel_blob_len = 0; KernelImage* image = NULL; RSAPublicKey* firmware_key = NULL; int error_code = 1; - char* tmp_kernelblob_file = ".tmpKernelBlob"; if(argc != 7) { fprintf(stderr, "Usage: %s " /* argv[1] */ @@ -217,24 +217,13 @@ int main(int argc, char* argv[]) { goto failure; } - if (!AddKernelSignature(image, argv[5], image->kernel_sign_algorithm)) { + if (!AddKernelSignature(image, argv[5])) { 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); + kernel_blob = GetKernelBlob(image, &kernel_blob_len); /* Test Kernel blob verify operations. */ if (!VerifyKernelTest(kernel_blob, firmware_key_blob)) diff --git a/tests/rsa_padding_test.c b/tests/rsa_padding_test.c index 7706ba8a18..429210bdc3 100644 --- a/tests/rsa_padding_test.c +++ b/tests/rsa_padding_test.c @@ -25,14 +25,14 @@ int main(int argc, char* argv[]) { } /* The first test signature is valid. */ - if (!RSA_verify(key, signatures[0], RSA1024NUMBYTES, 0, + if (!RSAVerify(key, signatures[0], RSA1024NUMBYTES, 0, test_message_sha1_hash)) { fprintf(stderr, "RSA Padding Test vector 0 FAILED!\n"); error = 255; /* Test failure. */ } /* All other signatures should fail verification. */ for (i = 1; i < sizeof(signatures) / sizeof(signatures[0]); i++) { - if (RSA_verify(key, signatures[i], RSA1024NUMBYTES, 0, + if (RSAVerify(key, signatures[i], RSA1024NUMBYTES, 0, test_message_sha1_hash)) { fprintf(stderr, "RSA Padding Test vector %d FAILED!\n", i); error = 255; /* Test failure. */ diff --git a/tests/rsa_verify_benchmark.c b/tests/rsa_verify_benchmark.c index e72c36fdc8..770afa6da7 100644 --- a/tests/rsa_verify_benchmark.c +++ b/tests/rsa_verify_benchmark.c @@ -64,7 +64,7 @@ int SpeedTestAlgorithm(int algorithm) { StartTimer(&ct); for (i = 0; i < NUM_OPERATIONS; i++) { - if (!RSA_verify(key, signature, sig_len, algorithm, digest)) + if (!RSAVerify(key, signature, sig_len, algorithm, digest)) fprintf(stderr, "Warning: Signature Check Failed.\n"); } StopTimer(&ct); diff --git a/utils/Makefile b/utils/Makefile index d0f8ea5980..14158fd2be 100644 --- a/utils/Makefile +++ b/utils/Makefile @@ -8,26 +8,25 @@ CFLAGS = -Wall -DNDEBUG INCLUDES ?= -I../include/ TOP ?= ../ -LIBS = -lcrypto +LIBS = firmware_image.o kernel_image.o signature_digest.o file_keys.o FIRMWARELIBS = $(TOP)/crypto/libcrypto.a $(TOP)/common/libcommon.a -all: dumpRSAPublicKey verify_data signature_digest firmware_utility \ - file_keys.o firmware_image.o kernel_image.o +all: dumpRSAPublicKey verify_data file_keys.o signature_digest.o firmware_image.o \ + kernel_image.o signature_digest.o firmware_utility dumpRSAPublicKey: dumpRSAPublicKey.c - $(CC) $(CFLAGS) $(LIBS) $< -o $@ + $(CC) $(CFLAGS) $< -o $@ -lcrypto -verify_data: verify_data.c file_keys.c - $(CC) $(CFLAGS) $(INCLUDES) $^ -o $@ $(FIRMWARELIBS) +verify_data: verify_data.c $(LIBS) $(FIRMWARELIBS) + $(CC) $(CFLAGS) $(INCLUDES) $< -o $@ $(LIBS) $(FIRMWARELIBS) -lcrypto -signature_digest: signature_digest.c - $(CC) $(CFLAGS) $(INCLUDES) $< -o $@ $(FIRMWARELIBS) +firmware_utility: firmware_utility.cc $(LIBS) $(FIRMWARELIBS) + $(CXX) $(CFLAGS) $(INCLUDES) -ggdb -D__STDC_LIMIT_MACROS $< \ + -o $@ $(FIRMWARELIBS) $(LIBS) -lcrypto -firmware_utility: firmware_utility.cc firmware_image.o file_keys.o - $(CXX) $(CFLAGS) $(INCLUDES) -ggdb -D__STDC_LIMIT_MACROS $^ \ - -o $@ $(FIRMWARELIBS) +signature_digest.o: signature_digest.c + $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ -# Used by tests. file_keys.o: file_keys.c $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ @@ -37,6 +36,5 @@ firmware_image.o: firmware_image.c kernel_image.o: kernel_image.c $(CC) $(CFLAGS) -ansi $(INCLUDES) -c $< -o $@ clean: - rm -f dumpRSAPublicKey verify_data signature_digest firmware_image.o \ - kernel_image.o file_keys.o firmware_utility - + rm -f dumpRSAPublicKey verify_data signature_digest firmware_utility \ + $(LIBS) diff --git a/utils/file_keys.c b/utils/file_keys.c index 98e878ae44..4eafd52452 100644 --- a/utils/file_keys.c +++ b/utils/file_keys.c @@ -17,6 +17,7 @@ #include "padding.h" #include "rsa_utility.h" +#include "signature_digest.h" #include "utility.h" uint8_t* BufferFromFile(const char* input_file, uint32_t* len) { diff --git a/utils/firmware_image.c b/utils/firmware_image.c index d5b054970c..0aa44f1fa2 100644 --- a/utils/firmware_image.c +++ b/utils/firmware_image.c @@ -18,6 +18,7 @@ #include "padding.h" #include "rsa_utility.h" #include "sha_utility.h" +#include "signature_digest.h" #include "utility.h" /* Macro to determine the size of a field structure in the FirmwareImage @@ -27,7 +28,7 @@ FirmwareImage* FirmwareImageNew(void) { FirmwareImage* image = (FirmwareImage*) Malloc(sizeof(FirmwareImage)); if (image) { - image->sign_key = NULL; + image->firmware_sign_key = NULL; image->preamble_signature = NULL; image->firmware_signature = NULL; image->firmware_data = NULL; @@ -37,10 +38,11 @@ FirmwareImage* FirmwareImageNew(void) { void FirmwareImageFree(FirmwareImage* image) { if (image) { - Free(image->sign_key); + Free(image->firmware_sign_key); Free(image->preamble_signature); Free(image->firmware_signature); Free(image->firmware_data); + Free(image); } } @@ -48,7 +50,7 @@ FirmwareImage* ReadFirmwareImage(const char* input_file) { uint32_t file_size; int image_len = 0; /* Total size of the firmware image. */ int header_len = 0; - int sign_key_len; + int firmware_sign_key_len; int signature_len; uint8_t* firmware_buf; MemcpyState st; @@ -64,46 +66,49 @@ FirmwareImage* ReadFirmwareImage(const char* input_file) { st.remaining_buf = firmware_buf; /* Read and compare magic bytes. */ - if (!StatefulMemcpy(&st, &image->magic, FIRMWARE_MAGIC_SIZE)) - goto parse_failure; - + StatefulMemcpy(&st, &image->magic, FIRMWARE_MAGIC_SIZE); if (SafeMemcmp(image->magic, FIRMWARE_MAGIC, FIRMWARE_MAGIC_SIZE)) { fprintf(stderr, "Wrong Firmware Magic.\n"); - goto parse_failure; + Free(firmware_buf); + return NULL; } - StatefulMemcpy(&st, &image->header_len, FIELD_LEN(header_len)); - StatefulMemcpy(&st, &image->sign_algorithm, FIELD_LEN(sign_algorithm)); + StatefulMemcpy(&st, &image->firmware_sign_algorithm, + FIELD_LEN(firmware_sign_algorithm)); /* Valid Algorithm? */ - if (image->sign_algorithm >= kNumAlgorithms) - goto parse_failure; + if (image->firmware_sign_algorithm >= kNumAlgorithms) { + Free(firmware_buf); + return NULL; + } /* Compute size of pre-processed RSA public key and signature. */ - sign_key_len = RSAProcessedKeySize(image->sign_algorithm); - signature_len = siglen_map[image->sign_algorithm]; - + firmware_sign_key_len = RSAProcessedKeySize(image->firmware_sign_algorithm); + signature_len = siglen_map[image->firmware_sign_algorithm]; /* Check whether the header length is correct. */ header_len = (FIELD_LEN(header_len) + - FIELD_LEN(sign_algorithm) + - sign_key_len + - FIELD_LEN(key_version) + + FIELD_LEN(firmware_sign_algorithm) + + firmware_sign_key_len + + FIELD_LEN(firmware_key_version) + 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; + Free(firmware_buf); + return NULL; } /* Read pre-processed public half of the sign key. */ - image->sign_key = (uint8_t*) Malloc(sign_key_len); - StatefulMemcpy(&st, image->sign_key, sign_key_len); - StatefulMemcpy(&st, &image->key_version, FIELD_LEN(key_version)); + image->firmware_sign_key = (uint8_t*) Malloc(firmware_sign_key_len); + StatefulMemcpy(&st, image->firmware_sign_key, firmware_sign_key_len); + StatefulMemcpy(&st, &image->firmware_key_version, + FIELD_LEN(firmware_key_version)); StatefulMemcpy(&st, image->header_checksum, FIELD_LEN(header_checksum)); /* Read key signature. */ - StatefulMemcpy(&st, image->key_signature, FIELD_LEN(key_signature)); + StatefulMemcpy(&st, image->firmware_key_signature, + FIELD_LEN(firmware_key_signature)); /* Read the firmware preamble. */ StatefulMemcpy(&st,&image->firmware_version, FIELD_LEN(firmware_version)); @@ -120,62 +125,141 @@ FirmwareImage* ReadFirmwareImage(const char* input_file) { image->firmware_data = (uint8_t*) Malloc(image->firmware_len); StatefulMemcpy(&st, image->firmware_data, image->firmware_len); - if(st.remaining_len != 0) /* Overrun or underrun. */ - goto parse_failure; - - Free(firmware_buf); - return image; - -parse_failure: - Free(firmware_buf); - return NULL; -} - -void WriteFirmwareHeader(int fd, FirmwareImage* image) { - int sign_key_len; - write(fd, &image->header_len, FIELD_LEN(header_len)); - write(fd, &image->sign_algorithm, FIELD_LEN(header_len)); - sign_key_len = (image->header_len - FIELD_LEN(header_len) - - FIELD_LEN(sign_algorithm) - - FIELD_LEN(key_version) - - FIELD_LEN(header_checksum)); - write(fd, image->sign_key, sign_key_len); - write(fd, &image->key_version, FIELD_LEN(key_version)); - write(fd, &image->header_checksum, FIELD_LEN(header_checksum)); -} - -void WriteFirmwarePreamble(int fd, FirmwareImage* image) { - write(fd, &image->firmware_version, - FIELD_LEN(firmware_version)); - write(fd, &image->firmware_len, FIELD_LEN(firmware_len)); - write(fd, image->preamble, FIELD_LEN(preamble)); -} - -FirmwareImage* WriteFirmwareImage(const char* input_file, - FirmwareImage* image) { - int fd; - int signature_len; - - if (!image) - return NULL; - if (-1 == (fd = creat(input_file, S_IRWXU))) { - fprintf(stderr, "Couldn't open file for writing.\n"); + if(st.remaining_len != 0) { /* Overrun or underrun. */ + Free(firmware_buf); return NULL; } - write(fd, image->magic, FIELD_LEN(magic)); - WriteFirmwareHeader(fd, image); - write(fd, image->key_signature, FIELD_LEN(key_signature)); - signature_len = siglen_map[image->sign_algorithm]; - WriteFirmwarePreamble(fd, image); - write(fd, image->preamble_signature, signature_len); - write(fd, image->firmware_signature, signature_len); - write(fd, image->firmware_data, image->firmware_len); - - close(fd); + Free(firmware_buf); return image; } +int GetFirmwareHeaderLen(const FirmwareImage* image) { + return (FIELD_LEN(header_len) + FIELD_LEN(header_len) + + RSAProcessedKeySize(image->firmware_sign_algorithm) + + FIELD_LEN(firmware_key_version) + FIELD_LEN(header_checksum)); +} + +uint8_t* GetFirmwareHeaderBlob(const FirmwareImage* image) { + uint8_t* header_blob = NULL; + MemcpyState st; + + header_blob = (uint8_t*) Malloc(GetFirmwareHeaderLen(image)); + st.remaining_len = GetFirmwareHeaderLen(image); + st.remaining_buf = header_blob; + + StatefulMemcpy_r(&st, &image->header_len, FIELD_LEN(header_len)); + StatefulMemcpy_r(&st, &image->firmware_sign_algorithm, FIELD_LEN(header_len)); + StatefulMemcpy_r(&st, image->firmware_sign_key, + RSAProcessedKeySize(image->firmware_sign_algorithm)); + StatefulMemcpy_r(&st, &image->firmware_key_version, + FIELD_LEN(firmware_key_version)); + StatefulMemcpy_r(&st, &image->header_checksum, FIELD_LEN(header_checksum)); + + if (st.remaining_len != 0) { /* Underrun or Overrun. */ + Free(header_blob); + return NULL; + } + return header_blob; +} + +int GetFirmwarePreambleLen(const FirmwareImage* image) { + return (FIELD_LEN(firmware_version) + FIELD_LEN(firmware_len) + + FIELD_LEN(preamble)); +} + +uint8_t* GetFirmwarePreambleBlob(const FirmwareImage* image) { + uint8_t* preamble_blob = NULL; + MemcpyState st; + + preamble_blob = (uint8_t*) Malloc(GetFirmwarePreambleLen(image)); + st.remaining_len = GetFirmwarePreambleLen(image); + st.remaining_buf = preamble_blob; + + StatefulMemcpy_r(&st, &image->firmware_version, FIELD_LEN(firmware_version)); + StatefulMemcpy_r(&st, &image->firmware_len, FIELD_LEN(firmware_len)); + StatefulMemcpy_r(&st, image->preamble, FIELD_LEN(preamble)); + + if (st.remaining_len != 0 ) { /* Underrun or Overrun. */ + Free(preamble_blob); + return NULL; + } + return preamble_blob; +} + + +uint8_t* GetFirmwareBlob(const FirmwareImage* image, int* blob_len) { + int firmware_signature_len; + uint8_t* firmware_blob = NULL; + uint8_t* header_blob = NULL; + uint8_t* preamble_blob = NULL; + MemcpyState st; + + if (!image) + return NULL; + + firmware_signature_len = siglen_map[image->firmware_sign_algorithm]; + *blob_len = (FIELD_LEN(magic) + + GetFirmwareHeaderLen(image) + + FIELD_LEN(firmware_key_signature) + + GetFirmwarePreambleLen(image) + + 2 * firmware_signature_len + + image->firmware_len); + firmware_blob = (uint8_t*) Malloc(*blob_len); + st.remaining_len = *blob_len; + st.remaining_buf = firmware_blob; + + header_blob = GetFirmwareHeaderBlob(image); + preamble_blob = GetFirmwarePreambleBlob(image); + + StatefulMemcpy_r(&st, image->magic, FIELD_LEN(magic)); + StatefulMemcpy_r(&st, header_blob, GetFirmwareHeaderLen(image)); + StatefulMemcpy_r(&st, image->firmware_key_signature, + FIELD_LEN(firmware_key_signature)); + StatefulMemcpy_r(&st, preamble_blob, GetFirmwarePreambleLen(image)); + StatefulMemcpy_r(&st, image->preamble_signature, firmware_signature_len); + StatefulMemcpy_r(&st, image->firmware_signature, firmware_signature_len); + StatefulMemcpy_r(&st, image->firmware_data, image->firmware_len); + + Free(preamble_blob); + Free(header_blob); + + if (st.remaining_len != 0) { /* Underrun or Overrun. */ + Free(firmware_blob); + return NULL; + } + return firmware_blob; +} + +int WriteFirmwareImage(const char* input_file, + const FirmwareImage* image) { + int fd; + uint8_t* firmware_blob; + int blob_len; + + if (!image) + return 0; + if (-1 == (fd = creat(input_file, S_IRWXU))) { + fprintf(stderr, "Couldn't open file for writing.\n"); + return 0; + } + + firmware_blob = GetFirmwareBlob(image, &blob_len); + if (!firmware_blob) { + fprintf(stderr, "Couldn't create firmware blob from FirmwareImage.\n"); + return 0; + } + if (blob_len != write(fd, firmware_blob, blob_len)) { + fprintf(stderr, "Couldn't write Firmware Image to file: %s\n", input_file); + Free(firmware_blob); + close(fd); + return 0; + } + Free(firmware_blob); + close(fd); + return 1; +} + void PrintFirmwareImage(const FirmwareImage* image) { if (!image) return; @@ -186,9 +270,9 @@ void PrintFirmwareImage(const FirmwareImage* image) { "Signature Algorithm = %s\n" "Key Version = %d\n\n", image->header_len, - image->sign_algorithm, - algo_strings[image->sign_algorithm], - image->key_version); + image->firmware_sign_algorithm, + algo_strings[image->firmware_sign_algorithm], + image->firmware_key_version); /* TODO(gauravsh): Output hash and key signature here? */ /* Print preamble. */ printf("Firmware Version = %d\n" @@ -213,31 +297,31 @@ int VerifyFirmwareHeader(const uint8_t* root_key_blob, const int dev_mode, int* algorithm, int* header_len) { - int sign_key_len; + int firmware_sign_key_len; int root_key_len; uint16_t hlen, algo; uint8_t* header_checksum = NULL; /* Base Offset for the header_checksum field. Actual offset is - * this + sign_key_len. */ + * this + firmware_sign_key_len. */ int base_header_checksum_offset = (FIELD_LEN(header_len) + - FIELD_LEN(sign_algorithm) + - FIELD_LEN(key_version)); + FIELD_LEN(firmware_sign_algorithm) + + FIELD_LEN(firmware_key_version)); root_key_len = RSAProcessedKeySize(ROOT_SIGNATURE_ALGORITHM); Memcpy(&hlen, header_blob, sizeof(hlen)); Memcpy(&algo, - header_blob + FIELD_LEN(sign_algorithm), + header_blob + FIELD_LEN(firmware_sign_algorithm), sizeof(algo)); if (algo >= kNumAlgorithms) return VERIFY_FIRMWARE_INVALID_ALGORITHM; *algorithm = (int) algo; - sign_key_len = RSAProcessedKeySize(*algorithm); + firmware_sign_key_len = RSAProcessedKeySize(*algorithm); /* Verify if header len is correct? */ if (hlen != (base_header_checksum_offset + - sign_key_len + + firmware_sign_key_len + FIELD_LEN(header_checksum))) return VERIFY_FIRMWARE_INVALID_IMAGE; @@ -248,7 +332,8 @@ int VerifyFirmwareHeader(const uint8_t* root_key_blob, *header_len - FIELD_LEN(header_checksum), SHA512_DIGEST_ALGORITHM); if (SafeMemcmp(header_checksum, - header_blob + (base_header_checksum_offset + sign_key_len), + header_blob + (base_header_checksum_offset + + firmware_sign_key_len), FIELD_LEN(header_checksum))) { Free(header_checksum); return VERIFY_FIRMWARE_INVALID_IMAGE; @@ -267,7 +352,7 @@ int VerifyFirmwareHeader(const uint8_t* root_key_blob, return 0; } -int VerifyFirmwarePreamble(RSAPublicKey* sign_key, +int VerifyFirmwarePreamble(RSAPublicKey* firmware_sign_key, const uint8_t* preamble_blob, int algorithm, int* firmware_len) { @@ -276,7 +361,7 @@ int VerifyFirmwarePreamble(RSAPublicKey* sign_key, preamble_len = (FIELD_LEN(firmware_version) + FIELD_LEN(firmware_len) + FIELD_LEN(preamble)); - if (!RSAVerifyBinary_f(NULL, sign_key, /* Key to use */ + if (!RSAVerifyBinary_f(NULL, firmware_sign_key, /* Key to use */ preamble_blob, /* Data to verify */ preamble_len, /* Length of data */ preamble_blob + preamble_len, /* Expected Signature */ @@ -289,12 +374,12 @@ int VerifyFirmwarePreamble(RSAPublicKey* sign_key, return 0; } -int VerifyFirmwareData(RSAPublicKey* sign_key, +int VerifyFirmwareData(RSAPublicKey* firmware_sign_key, const uint8_t* firmware_data_start, int firmware_len, int algorithm) { int signature_len = siglen_map[algorithm]; - if (!RSAVerifyBinary_f(NULL, sign_key, /* Key to use. */ + if (!RSAVerifyBinary_f(NULL, firmware_sign_key, /* Key to use. */ firmware_data_start + signature_len, /* Data to * verify */ firmware_len, /* Length of data. */ @@ -309,10 +394,10 @@ int VerifyFirmware(const uint8_t* root_key_blob, const int dev_mode) { int error_code; int algorithm; /* Signing key algorithm. */ - RSAPublicKey* sign_key; - int sign_key_len, signature_len, header_len, firmware_len; + RSAPublicKey* firmware_sign_key; + int firmware_sign_key_len, signature_len, header_len, firmware_len; const uint8_t* header_ptr; /* Pointer to header. */ - const uint8_t* sign_key_ptr; /* Pointer to signing key. */ + const uint8_t* firmware_sign_key_ptr; /* Pointer to signing key. */ const uint8_t* preamble_ptr; /* Pointer to preamble block. */ const uint8_t* firmware_ptr; /* Pointer to firmware signature/data. */ @@ -331,16 +416,18 @@ int VerifyFirmware(const uint8_t* root_key_blob, /* Parse signing key into RSAPublicKey structure since it is required multiple * times. */ - sign_key_len = RSAProcessedKeySize(algorithm); - sign_key_ptr = header_ptr + (FIELD_LEN(header_len) + - FIELD_LEN(sign_algorithm)); - sign_key = RSAPublicKeyFromBuf(sign_key_ptr, sign_key_len); + firmware_sign_key_len = RSAProcessedKeySize(algorithm); + firmware_sign_key_ptr = header_ptr + (FIELD_LEN(header_len) + + FIELD_LEN(firmware_sign_algorithm)); + firmware_sign_key = RSAPublicKeyFromBuf(firmware_sign_key_ptr, + firmware_sign_key_len); signature_len = siglen_map[algorithm]; /* Only continue if preamble verification succeeds. */ preamble_ptr = (header_ptr + header_len + - FIELD_LEN(key_signature)); - if ((error_code = VerifyFirmwarePreamble(sign_key, preamble_ptr, algorithm, + FIELD_LEN(firmware_key_signature)); + if ((error_code = VerifyFirmwarePreamble(firmware_sign_key, preamble_ptr, + algorithm, &firmware_len))) return error_code; /* AKA jump to recovery. */ @@ -351,7 +438,8 @@ int VerifyFirmware(const uint8_t* root_key_blob, FIELD_LEN(preamble) + signature_len); - if ((error_code = VerifyFirmwareData(sign_key, firmware_ptr, firmware_len, + if ((error_code = VerifyFirmwareData(firmware_sign_key, firmware_ptr, + firmware_len, algorithm))) return error_code; /* AKA jump to recovery. */ @@ -361,11 +449,11 @@ int VerifyFirmware(const uint8_t* root_key_blob, int VerifyFirmwareImage(const RSAPublicKey* root_key, const FirmwareImage* image, const int dev_mode) { - RSAPublicKey* sign_key; + RSAPublicKey* firmware_sign_key; uint8_t* header_digest = NULL; uint8_t* preamble_digest = NULL; uint8_t* firmware_digest = NULL; - int sign_key_size; + int firmware_sign_key_size; int signature_size; int error_code = 0; DigestContext ctx; @@ -384,17 +472,17 @@ int VerifyFirmwareImage(const RSAPublicKey* root_key, DigestInit(&ctx, ROOT_SIGNATURE_ALGORITHM); DigestUpdate(&ctx, (uint8_t*) &image->header_len, FIELD_LEN(header_len)); - DigestUpdate(&ctx, (uint8_t*) &image->sign_algorithm, - FIELD_LEN(sign_algorithm)); - DigestUpdate(&ctx, image->sign_key, - RSAProcessedKeySize(image->sign_algorithm)); - DigestUpdate(&ctx, (uint8_t*) &image->key_version, - FIELD_LEN(key_version)); + DigestUpdate(&ctx, (uint8_t*) &image->firmware_sign_algorithm, + FIELD_LEN(firmware_sign_algorithm)); + DigestUpdate(&ctx, image->firmware_sign_key, + RSAProcessedKeySize(image->firmware_sign_algorithm)); + DigestUpdate(&ctx, (uint8_t*) &image->firmware_key_version, + FIELD_LEN(firmware_key_version)); DigestUpdate(&ctx, image->header_checksum, FIELD_LEN(header_checksum)); header_digest = DigestFinal(&ctx); - if (!RSA_verify(root_key, image->key_signature, - FIELD_LEN(key_signature), + if (!RSAVerify(root_key, image->firmware_key_signature, + FIELD_LEN(firmware_key_signature), ROOT_SIGNATURE_ALGORITHM, header_digest)) { error_code = VERIFY_FIRMWARE_ROOT_SIGNATURE_FAILED; @@ -403,16 +491,16 @@ int VerifyFirmwareImage(const RSAPublicKey* root_key, } /* Get sign key to verify the rest of the firmware. */ - sign_key_size = RSAProcessedKeySize(image->sign_algorithm); - sign_key = RSAPublicKeyFromBuf(image->sign_key, - sign_key_size); - signature_size = siglen_map[image->sign_algorithm]; + firmware_sign_key_size = RSAProcessedKeySize(image->firmware_sign_algorithm); + firmware_sign_key = RSAPublicKeyFromBuf(image->firmware_sign_key, + firmware_sign_key_size); + signature_size = siglen_map[image->firmware_sign_algorithm]; - if (image->sign_algorithm >= kNumAlgorithms) + if (image->firmware_sign_algorithm >= kNumAlgorithms) return VERIFY_FIRMWARE_INVALID_ALGORITHM; /* Verify firmware preamble signature. */ - DigestInit(&ctx, image->sign_algorithm); + DigestInit(&ctx, image->firmware_sign_algorithm); DigestUpdate(&ctx, (uint8_t*) &image->firmware_version, FIELD_LEN(firmware_version)); DigestUpdate(&ctx, (uint8_t*) &image->firmware_len, @@ -420,8 +508,8 @@ int VerifyFirmwareImage(const RSAPublicKey* root_key, DigestUpdate(&ctx, (uint8_t*) &image->preamble, FIELD_LEN(preamble)); preamble_digest = DigestFinal(&ctx); - if (!RSA_verify(sign_key, image->preamble_signature, - signature_size, image->sign_algorithm, + if (!RSAVerify(firmware_sign_key, image->preamble_signature, + signature_size, image->firmware_sign_algorithm, preamble_digest)) { error_code = VERIFY_FIRMWARE_PREAMBLE_SIGNATURE_FAILED; goto verify_failure; @@ -430,9 +518,9 @@ int VerifyFirmwareImage(const RSAPublicKey* root_key, /* Verify firmware signature. */ firmware_digest = DigestBuf(image->firmware_data, image->firmware_len, - image->sign_algorithm); - if(!RSA_verify(sign_key, image->firmware_signature, - signature_size, image->sign_algorithm, + image->firmware_sign_algorithm); + if (!RSAVerify(firmware_sign_key, image->firmware_signature, + signature_size, image->firmware_sign_algorithm, firmware_digest)) { error_code = VERIFY_FIRMWARE_SIGNATURE_FAILED; goto verify_failure; @@ -450,64 +538,49 @@ const char* VerifyFirmwareErrorString(int error) { } int AddFirmwareKeySignature(FirmwareImage* image, const char* root_key_file) { - int tmp_hdr_fd; - char* tmp_hdr_file = ".tmpHdrFile"; + uint8_t* header_blob = NULL; uint8_t* signature; - - if(-1 == (tmp_hdr_fd = creat(tmp_hdr_file, S_IRWXU))) { - fprintf(stderr, "Could not open temporary file for writing " - "firmware header.\n"); + if (!image || !root_key_file) + return 0; + header_blob = GetFirmwareHeaderBlob(image); + if (!header_blob) + return 0; + if (!(signature = SignatureBuf(header_blob, + GetFirmwareHeaderLen(image), + root_key_file, + ROOT_SIGNATURE_ALGORITHM))) { + Free(header_blob); return 0; } - WriteFirmwareHeader(tmp_hdr_fd, image); - close(tmp_hdr_fd); - - if (!(signature = SignatureFile(tmp_hdr_file, root_key_file, - ROOT_SIGNATURE_ALGORITHM))) - return 0; - Memcpy(image->key_signature, signature, RSA8192NUMBYTES); + Memcpy(image->firmware_key_signature, signature, RSA8192NUMBYTES); + Free(header_blob); + Free(signature); return 1; } -int AddFirmwareSignature(FirmwareImage* image, const char* signing_key_file, - int algorithm) { - int tmp_preamble_fd; - char* tmp_preamble_file = ".tmpPreambleFile"; - int tmp_firmware_fd; - char* tmp_firmware_file = ".tmpFirmwareFile"; +int AddFirmwareSignature(FirmwareImage* image, const char* signing_key_file) { + uint8_t* preamble_blob; uint8_t* preamble_signature; uint8_t* firmware_signature; - int signature_len = siglen_map[algorithm]; + int signature_len = siglen_map[image->firmware_sign_algorithm]; - /* Write preamble to a file. */ - if(-1 == (tmp_preamble_fd = creat(tmp_preamble_file, S_IRWXU))) { - fprintf(stderr, "Could not open temporary file for writing " - "firmware preamble.\n"); + preamble_blob = GetFirmwarePreambleBlob(image); + if (!(preamble_signature = SignatureBuf(preamble_blob, + GetFirmwarePreambleLen(image), + signing_key_file, + image->firmware_sign_algorithm))) { + Free(preamble_blob); return 0; } - WriteFirmwarePreamble(tmp_preamble_fd, image); - close(tmp_preamble_fd); - if (!(preamble_signature = SignatureFile(tmp_preamble_file, signing_key_file, - algorithm))) - return 0; image->preamble_signature = (uint8_t*) Malloc(signature_len); Memcpy(image->preamble_signature, preamble_signature, signature_len); Free(preamble_signature); - if (-1 == (tmp_firmware_fd = creat(tmp_firmware_file, S_IRWXU))) { - fprintf(stderr, "Could not open temporary file for writing " - "firmware.\n"); + if (!(firmware_signature = SignatureBuf(image->firmware_data, + image->firmware_len, + signing_key_file, + image->firmware_sign_algorithm))) return 0; - } - write(tmp_firmware_fd, image->firmware_data, image->firmware_len); - close(tmp_firmware_fd); - - if (!(firmware_signature = SignatureFile(tmp_firmware_file, signing_key_file, - algorithm))) { - fprintf(stderr, "Could not open temporary file for writing " - "firmware.\n"); - return 0; - } image->firmware_signature = (uint8_t*) Malloc(signature_len); Memcpy(image->firmware_signature, firmware_signature, signature_len); Free(firmware_signature); diff --git a/utils/firmware_utility.cc b/utils/firmware_utility.cc index a25be2f1fc..2563fc86c6 100644 --- a/utils/firmware_utility.cc +++ b/utils/firmware_utility.cc @@ -33,8 +33,8 @@ FirmwareUtility::FirmwareUtility(): image_(NULL), root_key_pub_(NULL), firmware_version_(-1), - key_version_(-1), - sign_algorithm_(-1), + firmware_key_version_(-1), + firmware_sign_algorithm_(-1), is_generate_(false), is_verify_(false) { } @@ -54,11 +54,11 @@ void FirmwareUtility::PrintUsage(void) { "to use for verification.\n\n" "For \"--generate\", required OPTIONS are:\n" "--root_key \tPrivate root key file\n" - "--sign_key \tPrivate signing key file\n" - "--sign_key_pub \tPre-processed public signing" + "--firmware_sign_key \tPrivate signing key file\n" + "--firmware_sign_key_pub \tPre-processed public signing" " key\n" - "--sign_algorithm \tSigning algorithm to use\n" - "--key_version \tSigning Key Version#\n" + "--firmware_sign_algorithm \tSigning algorithm to use\n" + "--firmware_key_version \tSigning Key Version#\n" "--firmware_version \tFirmware Version#\n" "--in \t\t\tFirmware Image to sign\n" "--out \t\t\tOutput file for verified boot firmware image\n\n" @@ -74,10 +74,10 @@ bool FirmwareUtility::ParseCmdLineOptions(int argc, char* argv[]) { static struct option long_options[] = { {"root_key", 1, 0, 0}, {"root_key_pub", 1, 0, 0}, - {"sign_key", 1, 0, 0}, - {"sign_key_pub", 1, 0, 0}, - {"sign_algorithm", 1, 0, 0}, - {"key_version", 1, 0, 0}, + {"firmware_sign_key", 1, 0, 0}, + {"firmware_sign_key_pub", 1, 0, 0}, + {"firmware_sign_algorithm", 1, 0, 0}, + {"firmware_key_version", 1, 0, 0}, {"firmware_version", 1, 0, 0}, {"in", 1, 0, 0}, {"out", 1, 0, 0}, @@ -100,21 +100,21 @@ bool FirmwareUtility::ParseCmdLineOptions(int argc, char* argv[]) { case 1: // root_key_pub root_key_pub_file_ = optarg; break; - case 2: // sign_key - sign_key_file_ = optarg; + case 2: // firmware_sign_key + firmware_sign_key_file_ = optarg; break; - case 3: // sign_key_pub - sign_key_pub_file_ = optarg; + case 3: // firmware_sign_key_pub + firmware_sign_key_pub_file_ = optarg; break; - case 4: // sign_algorithm + case 4: // firmware_sign_algorithm errno = 0; // strtol() returns an error via errno - sign_algorithm_ = strtol(optarg, (char**) NULL, 10); + firmware_sign_algorithm_ = strtol(optarg, (char**) NULL, 10); if (errno) return false; break; - case 5: // key_version + case 5: // firmware_key_version errno = 0; - key_version_ = strtol(optarg, (char**) NULL, 10); + firmware_key_version_ = strtol(optarg, (char**) NULL, 10); if (errno) return false; break; @@ -153,7 +153,7 @@ void FirmwareUtility::OutputSignedImage(void) { } bool FirmwareUtility::GenerateSignedImage(void) { - uint32_t sign_key_pub_len; + uint32_t firmware_sign_key_pub_len; uint8_t* header_checksum; DigestContext ctx; image_ = FirmwareImageNew(); @@ -161,30 +161,31 @@ bool FirmwareUtility::GenerateSignedImage(void) { Memcpy(image_->magic, FIRMWARE_MAGIC, FIRMWARE_MAGIC_SIZE); // Copy pre-processed public signing key. - image_->sign_algorithm = (uint16_t) sign_algorithm_; - image_->sign_key = BufferFromFile(sign_key_pub_file_.c_str(), - &sign_key_pub_len); - if (!image_->sign_key) + image_->firmware_sign_algorithm = (uint16_t) firmware_sign_algorithm_; + image_->firmware_sign_key = BufferFromFile( + firmware_sign_key_pub_file_.c_str(), + &firmware_sign_key_pub_len); + if (!image_->firmware_sign_key) return false; - image_->key_version = key_version_; + image_->firmware_key_version = firmware_key_version_; // Update header length. image_->header_len = (sizeof(image_->header_len) + - sizeof(image_->sign_algorithm) + - sign_key_pub_len + - sizeof(image_->key_version) + + sizeof(image_->firmware_sign_algorithm) + + firmware_sign_key_pub_len + + sizeof(image_->firmware_key_version) + sizeof(image_->header_checksum)); // Calculate header checksum. DigestInit(&ctx, SHA512_DIGEST_ALGORITHM); DigestUpdate(&ctx, (uint8_t*) &image_->header_len, sizeof(image_->header_len)); - DigestUpdate(&ctx, (uint8_t*) &image_->sign_algorithm, - sizeof(image_->sign_algorithm)); - DigestUpdate(&ctx, image_->sign_key, - RSAProcessedKeySize(image_->sign_algorithm)); - DigestUpdate(&ctx, (uint8_t*) &image_->key_version, - sizeof(image_->key_version)); + DigestUpdate(&ctx, (uint8_t*) &image_->firmware_sign_algorithm, + sizeof(image_->firmware_sign_algorithm)); + DigestUpdate(&ctx, image_->firmware_sign_key, + RSAProcessedKeySize(image_->firmware_sign_algorithm)); + DigestUpdate(&ctx, (uint8_t*) &image_->firmware_key_version, + sizeof(image_->firmware_key_version)); header_checksum = DigestFinal(&ctx); Memcpy(image_->header_checksum, header_checksum, SHA512_DIGEST_SIZE); Free(header_checksum); @@ -199,13 +200,12 @@ bool FirmwareUtility::GenerateSignedImage(void) { if (!image_) return false; // Generate and add the signatures. - if(!AddFirmwareKeySignature(image_, root_key_file_.c_str())) { + if (!AddFirmwareKeySignature(image_, root_key_file_.c_str())) { cerr << "Couldn't write key signature to verified boot image.\n"; return false; } - if(!AddFirmwareSignature(image_, sign_key_file_.c_str(), - image_->sign_algorithm)) { + if (!AddFirmwareSignature(image_, firmware_sign_key_file_.c_str())) { cerr << "Couldn't write firmware signature to verified boot image.\n"; return false; } @@ -257,19 +257,20 @@ bool FirmwareUtility::CheckOptions(void) { cerr << "Invalid or no firmware version specified." << "\n"; return false; } - if (sign_key_file_.empty()) { + if (firmware_sign_key_file_.empty()) { cerr << "No signing key file specified." << "\n"; return false; } - if (sign_key_pub_file_.empty()) { + if (firmware_sign_key_pub_file_.empty()) { cerr << "No pre-processed public signing key file specified." << "\n"; return false; } - if (key_version_ <= 0 || key_version_ > UINT16_MAX) { + if (firmware_key_version_ <= 0 || firmware_key_version_ > UINT16_MAX) { cerr << "Invalid or no key version specified." << "\n"; return false; } - if (sign_algorithm_ < 0 || sign_algorithm_ >= kNumAlgorithms) { + if (firmware_sign_algorithm_ < 0 || + firmware_sign_algorithm_ >= kNumAlgorithms) { cerr << "Invalid or no signing key algorithm specified." << "\n"; return false; } diff --git a/utils/kernel_image.c b/utils/kernel_image.c index b5f07c2fae..06b340b4c7 100644 --- a/utils/kernel_image.c +++ b/utils/kernel_image.c @@ -17,6 +17,7 @@ #include "padding.h" #include "rsa_utility.h" #include "sha_utility.h" +#include "signature_digest.h" #include "utility.h" /* Macro to determine the size of a field structure in the KernelImage @@ -68,12 +69,12 @@ KernelImage* ReadKernelImage(const char* input_file) { st.remaining_buf = kernel_buf; /* Read and compare magic bytes. */ - if (!StatefulMemcpy(&st, &image->magic, KERNEL_MAGIC_SIZE)) - goto parse_failure; + StatefulMemcpy(&st, &image->magic, KERNEL_MAGIC_SIZE); if (SafeMemcmp(image->magic, KERNEL_MAGIC, KERNEL_MAGIC_SIZE)) { fprintf(stderr, "Wrong Kernel Magic.\n"); - goto parse_failure; + Free(kernel_buf); + return NULL; } StatefulMemcpy(&st, &image->header_version, FIELD_LEN(header_version)); StatefulMemcpy(&st, &image->header_len, FIELD_LEN(header_len)); @@ -83,12 +84,16 @@ KernelImage* ReadKernelImage(const char* input_file) { FIELD_LEN(kernel_sign_algorithm)); /* Valid Kernel Key signing algorithm. */ - if (image->firmware_sign_algorithm >= kNumAlgorithms) - goto parse_failure; + if (image->firmware_sign_algorithm >= kNumAlgorithms) { + Free(kernel_buf); + return NULL; + } /* Valid Kernel Signing Algorithm? */ - if (image->kernel_sign_algorithm >= kNumAlgorithms) - goto parse_failure; + if (image->kernel_sign_algorithm >= kNumAlgorithms) { + Free(kernel_buf); + return NULL; + } /* Compute size of pre-processed RSA public keys and signatures. */ firmware_sign_key_len = RSAProcessedKeySize(image->firmware_sign_algorithm); @@ -108,7 +113,8 @@ KernelImage* ReadKernelImage(const char* input_file) { if (header_len != image->header_len) { fprintf(stderr, "Header length mismatch. Got: %d, Expected: %d\n", image->header_len, header_len); - goto parse_failure; + Free(kernel_buf); + return NULL; } /* Read pre-processed public half of the kernel signing key. */ @@ -142,73 +148,150 @@ KernelImage* ReadKernelImage(const char* input_file) { 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"); + if(st.remaining_len != 0) { /* Overrun or underrun. */ + Free(kernel_buf); return NULL; } + Free(kernel_buf); + return image; +} +int GetKernelHeaderLen(const KernelImage* image) { + return (FIELD_LEN(header_version) + FIELD_LEN(header_len) + + FIELD_LEN(firmware_sign_algorithm) + + FIELD_LEN(kernel_sign_algorithm) + FIELD_LEN(kernel_key_version) + + RSAProcessedKeySize(image->kernel_sign_algorithm) + + FIELD_LEN(header_checksum)); +} + +uint8_t* GetKernelHeaderBlob(const KernelImage* image) { + uint8_t* header_blob = NULL; + MemcpyState st; + + header_blob = (uint8_t*) Malloc(GetKernelHeaderLen(image)); + st.remaining_len = GetKernelHeaderLen(image); + st.remaining_buf = header_blob; + + StatefulMemcpy_r(&st, &image->header_version, FIELD_LEN(header_version)); + StatefulMemcpy_r(&st, &image->header_len, FIELD_LEN(header_len)); + StatefulMemcpy_r(&st, &image->firmware_sign_algorithm, + FIELD_LEN(firmware_sign_algorithm)); + StatefulMemcpy_r(&st, &image->kernel_sign_algorithm, + FIELD_LEN(kernel_sign_algorithm)); + StatefulMemcpy_r(&st, &image->kernel_key_version, + FIELD_LEN(kernel_key_version)); + StatefulMemcpy_r(&st, image->kernel_sign_key, + RSAProcessedKeySize(image->kernel_sign_algorithm)); + StatefulMemcpy_r(&st, &image->header_checksum, FIELD_LEN(header_checksum)); + + if (st.remaining_len != 0) { /* Underrun or Overrun. */ + Free(header_blob); + return NULL; + } + return header_blob; +} + +int GetKernelConfigLen(const KernelImage* image) { + return (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)); +} + +uint8_t* GetKernelConfigBlob(const KernelImage* image) { + uint8_t* config_blob = NULL; + MemcpyState st; + + config_blob = (uint8_t*) Malloc(GetKernelConfigLen(image)); + st.remaining_len = GetKernelConfigLen(image); + st.remaining_buf = config_blob; + + StatefulMemcpy_r(&st, &image->kernel_version, FIELD_LEN(kernel_version)); + StatefulMemcpy_r(&st, image->options.version, FIELD_LEN(options.version)); + StatefulMemcpy_r(&st, &image->options.kernel_len, + FIELD_LEN(options.kernel_len)); + StatefulMemcpy_r(&st, &image->options.kernel_load_addr, + FIELD_LEN(options.kernel_load_addr)); + StatefulMemcpy_r(&st, &image->options.kernel_entry_addr, + FIELD_LEN(options.kernel_entry_addr)); + if (st.remaining_len != 0) { /* Overrun or Underrun. */ + Free(config_blob); + return NULL; + } + return config_blob; +} + +uint8_t* GetKernelBlob(const KernelImage* image, int* blob_len) { + int kernel_key_signature_len; + int kernel_signature_len; + uint8_t* kernel_blob = NULL; + uint8_t* header_blob = NULL; + uint8_t* config_blob = NULL; + MemcpyState st; + + if (!image) + return NULL; kernel_key_signature_len = siglen_map[image->firmware_sign_algorithm]; kernel_signature_len = siglen_map[image->kernel_sign_algorithm]; + *blob_len = (FIELD_LEN(magic) + + GetKernelHeaderLen(image) + + kernel_key_signature_len + + GetKernelConfigLen(image) + + 2 * kernel_signature_len + + image->options.kernel_len); + kernel_blob = (uint8_t*) Malloc(*blob_len); + st.remaining_len = *blob_len; + st.remaining_buf = kernel_blob; - 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); + header_blob = GetKernelHeaderBlob(image); + config_blob = GetKernelConfigBlob(image); + StatefulMemcpy_r(&st, image->magic, FIELD_LEN(magic)); + StatefulMemcpy_r(&st, header_blob, GetKernelHeaderLen(image)); + StatefulMemcpy_r(&st, image->kernel_key_signature, kernel_key_signature_len); + StatefulMemcpy_r(&st, config_blob, GetKernelConfigLen(image)); + StatefulMemcpy_r(&st, image->config_signature, kernel_signature_len); + StatefulMemcpy_r(&st, image->kernel_signature, kernel_signature_len); + StatefulMemcpy_r(&st, image->kernel_data, image->options.kernel_len); + + Free(config_blob); + Free(header_blob); + + if (st.remaining_len != 0) { /* Underrun or Overrun. */ + Free(kernel_blob); + return NULL; + } + return kernel_blob; +} + +int WriteKernelImage(const char* input_file, + const KernelImage* image) { + int fd; + uint8_t* kernel_blob; + int blob_len; + + if (!image) + return 0; + if (-1 == (fd = creat(input_file, S_IRWXU))) { + fprintf(stderr, "Couldn't open file for writing kernel image: %s\n", + input_file); + return 0; + } + kernel_blob = GetKernelBlob(image, &blob_len); + if (!kernel_blob) { + fprintf(stderr, "Couldn't create kernel blob from KernelImage.\n"); + return 0; + } + if (blob_len != write(fd, kernel_blob, blob_len)) { + fprintf(stderr, "Couldn't write Kernel Image to file: %s\n", + input_file); + + Free(kernel_blob); + close(fd); + return 0; + } + Free(kernel_blob); close(fd); - return image; + return 1; } void PrintKernelImage(const KernelImage* image) { @@ -478,7 +561,7 @@ int VerifyKernelImage(const RSAPublicKey* firmware_key, DigestUpdate(&ctx, image->header_checksum, FIELD_LEN(header_checksum)); header_digest = DigestFinal(&ctx); - if (!RSA_verify(firmware_key, image->kernel_key_signature, + if (!RSAVerify(firmware_key, image->kernel_key_signature, siglen_map[image->firmware_sign_algorithm], image->firmware_sign_algorithm, header_digest)) { @@ -507,9 +590,9 @@ int VerifyKernelImage(const RSAPublicKey* firmware_key, 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)) { + if (!RSAVerify(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; } @@ -518,7 +601,7 @@ int VerifyKernelImage(const RSAPublicKey* firmware_key, kernel_digest = DigestBuf(image->kernel_data, image->options.kernel_len, image->kernel_sign_algorithm); - if(!RSA_verify(kernel_sign_key, image->kernel_signature, + if (!RSAVerify(kernel_sign_key, image->kernel_signature, kernel_signature_size, image->kernel_sign_algorithm, kernel_digest)) { error_code = VERIFY_KERNEL_SIGNATURE_FAILED; @@ -537,63 +620,53 @@ const char* VerifyKernelErrorString(int error) { } int AddKernelKeySignature(KernelImage* image, const char* firmware_key_file) { - int tmp_hdr_fd; - char* tmp_hdr_file = ".tmpKernelHdrFile"; + uint8_t* header_blob = NULL; uint8_t* signature; int signature_len = siglen_map[image->firmware_sign_algorithm]; - - if(-1 == (tmp_hdr_fd = creat(tmp_hdr_file, S_IRWXU))) { - fprintf(stderr, "Could not open temporary file for writing " - "kernel header.\n"); + if (!image || !firmware_key_file) + return 0; + header_blob = GetKernelHeaderBlob(image); + if (!header_blob) + return 0; + if (!(signature = SignatureBuf(header_blob, + GetKernelHeaderLen(image), + firmware_key_file, + image->firmware_sign_algorithm))) { + Free(header_blob); 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); + Free(signature); + Free(header_blob); 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"; +int AddKernelSignature(KernelImage* image, + const char* kernel_signing_key_file) { + uint8_t* config_blob; uint8_t* config_signature; uint8_t* kernel_signature; - int signature_len = siglen_map[algorithm]; + int signature_len = siglen_map[image->kernel_sign_algorithm]; - /* 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"); + config_blob = GetKernelConfigBlob(image); + if (!(config_signature = SignatureBuf(config_blob, + GetKernelConfigLen(image), + kernel_signing_key_file, + image->kernel_sign_algorithm))) { + fprintf(stderr, "Could not compute signature on the kernel config.\n"); + Free(config_blob); 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))) { + if (!(kernel_signature = SignatureBuf(image->kernel_data, + image->options.kernel_len, + kernel_signing_key_file, + image->kernel_sign_algorithm))) { fprintf(stderr, "Could not compute signature on the kernel.\n"); return 0; } diff --git a/utils/signature_digest.c b/utils/signature_digest.c index 100f7ecbf6..96cc552976 100644 --- a/utils/signature_digest.c +++ b/utils/signature_digest.c @@ -1,17 +1,13 @@ /* 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 that outputs the message digest of the contents of a file in a - * format that can be used as input to OpenSSL for an RSA signature. - * Needed until the stable OpenSSL release supports SHA-256/512 digests for - * RSA signatures. - * Outputs DigestInfo || Digest where DigestInfo is the OID depending on the - * choice of the hash algorithm (see padding.c). - * */ #include "signature_digest.h" +#define OPENSSL_NO_SHA +#include +#include +#include #include #include @@ -20,49 +16,59 @@ #include "padding.h" #include "sha.h" #include "sha_utility.h" +#include "utility.h" uint8_t* PrependDigestInfo(int algorithm, uint8_t* digest) { const int digest_size = hash_size_map[algorithm]; const int digestinfo_size = digestinfo_size_map[algorithm]; const uint8_t* digestinfo = hash_digestinfo_map[algorithm]; - uint8_t* p = malloc(digestinfo_size + digest_size); - memcpy(p, digestinfo, digestinfo_size); - memcpy(p + digestinfo_size, digest, digest_size); + uint8_t* p = Malloc(digestinfo_size + digest_size); + Memcpy(p, digestinfo, digestinfo_size); + Memcpy(p + digestinfo_size, digest, digest_size); return p; } -int main(int argc, char* argv[]) { - int i, algorithm; - uint8_t* digest = NULL; - uint8_t* signature = NULL; +uint8_t* SignatureDigest(const uint8_t* buf, int len, int algorithm) { uint8_t* info_digest = NULL; + uint8_t* digest = NULL; - if (argc != 3) { - fprintf(stderr, "Usage: %s \n\n", - argv[0]); - fprintf(stderr, "where is the signature algorithm to use:\n"); - for(i = 0; i= kNumAlgorithms) { - fprintf(stderr, "Invalid Algorithm!\n"); - goto failure; + fprintf(stderr, "SignatureDigest() called with invalid algorithm!\n"); + } else if ((digest = DigestBuf(buf, len, algorithm))) { + info_digest = PrependDigestInfo(algorithm, digest); } - - if (!(digest = DigestFile(argv[2], algorithm))) - goto failure; - - info_digest = PrependDigestInfo(algorithm, digest); - write(1, info_digest, hash_size_map[algorithm] + - digestinfo_size_map[algorithm]); - -failure: - free(digest); - free(info_digest); - free(signature); - - return 0; + Free(digest); + return info_digest; +} + +uint8_t* SignatureBuf(const uint8_t* buf, int len, const char* key_file, + int algorithm) { + FILE* key_fp = NULL; + RSA* key = NULL; + uint8_t* signature = NULL; + uint8_t* signature_digest = SignatureDigest(buf, len, algorithm); + int signature_digest_len = (hash_size_map[algorithm] + + digestinfo_size_map[algorithm]); + key_fp = fopen(key_file, "r"); + if (!key_fp) { + fprintf(stderr, "SignatureBuf(): Couldn't open key file: %s\n", key_file); + return NULL; + } + if ((key = PEM_read_RSAPrivateKey(key_fp, NULL, NULL, NULL))) + signature = (uint8_t*) Malloc(siglen_map[algorithm]); + else + fprintf(stderr, "SignatureBuf(): Couldn't read private key from file: %s\n", + key_file); + if (signature) { + if (-1 == RSA_private_encrypt(signature_digest_len, /* Input length. */ + signature_digest, /* Input data. */ + signature, /* Output signature. */ + key, /* Key to use. */ + RSA_PKCS1_PADDING)) /* Padding to use. */ + fprintf(stderr, "SignatureBuf(): RSA_private_encrypt() failed.\n"); + } + if (key) + RSA_free(key); + Free(signature_digest); + return signature; } diff --git a/utils/verify_data.c b/utils/verify_data.c index 8a79d0f32a..4b0b785ad7 100644 --- a/utils/verify_data.c +++ b/utils/verify_data.c @@ -74,23 +74,22 @@ int main(int argc, char* argv[]) { return 0; } /* Length of the RSA Signature/RSA Key */ - sig_len = siglen_map[algorithm]; - if (!(key = RSAPublicKeyFromFile(argv[2]))) - goto failure; - if (!(signature = read_signature(argv[3], sig_len))) - goto failure; - if (!(digest = DigestFile(argv[4], algorithm))) - goto failure; - if(RSA_verify(key, signature, sig_len, algorithm, digest)) { - return_code = 0; - fprintf(stderr, "Signature Verification " - COL_GREEN "SUCCEEDED" COL_STOP "\n"); - } else { - fprintf(stderr, "Signature Verification " - COL_RED "FAILED" COL_STOP "\n"); + sig_len = siglen_map[algorithm]; + if ((key = RSAPublicKeyFromFile(argv[2])) && + (signature = read_signature(argv[3], sig_len)) && + (digest = DigestFile(argv[4], algorithm))) { + if (RSAVerify(key, signature, sig_len, algorithm, digest)) { + return_code = 0; + fprintf(stderr, "Signature Verification " + COL_GREEN "SUCCEEDED" COL_STOP "\n"); + } else { + fprintf(stderr, "Signature Verification " + COL_RED "FAILED" COL_STOP "\n"); + } } + else + return_code = -1; -failure: free(key); free(signature); free(digest);