mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-11-24 02:05:01 +00:00
Vboot Reference: Refactor Code.
This CL does the following: 1) It adds a SignatureBuf function which uses the OpenSSL library to generate RSA signature. This is more robust than the previous way of invoking the command line "openssl" utility and capturing its output. No more unnecessary temporary files for signature operations. 2) It adds functions that allow direct manipulation of binary verified Firmware and Kernel Image blobs in memory. 3) It changes the structure field members for FirmwareImage to make it consistent with KernelImage. Now it's clearer which key is used when. 4) Minor bug fixes and slightly improved API for dealing verified boot firmware and kernel images. 5) Renames the RSA_verify function to prevent conflicts with OpenSSL since it's linked into the firmware utility binary. Review URL: http://codereview.chromium.org/661353
This commit is contained in:
@@ -48,14 +48,23 @@ int SafeMemcmp(const void* s1, const void* s2, size_t n) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void* StatefulMemcpy(MemcpyState* state, void* dst, int len) {
|
void* StatefulMemcpy(MemcpyState* state, void* dst, int len) {
|
||||||
void* saved_ptr;
|
|
||||||
if (len > state->remaining_len) {
|
if (len > state->remaining_len) {
|
||||||
state->remaining_len = -1;
|
state->remaining_len = -1;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
saved_ptr = state->remaining_buf;
|
Memcpy(dst, state->remaining_buf, len);
|
||||||
Memcpy(dst, saved_ptr, len);
|
|
||||||
state->remaining_buf += len;
|
state->remaining_buf += len;
|
||||||
state->remaining_len -= len;
|
state->remaining_len -= len;
|
||||||
return dst;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
10
crypto/rsa.c
10
crypto/rsa.c
@@ -127,11 +127,11 @@ static void modpowF4(const RSAPublicKey *key,
|
|||||||
/* Verify a RSA PKCS1.5 signature against an expected hash.
|
/* Verify a RSA PKCS1.5 signature against an expected hash.
|
||||||
* Returns 0 on failure, 1 on success.
|
* Returns 0 on failure, 1 on success.
|
||||||
*/
|
*/
|
||||||
int RSA_verify(const RSAPublicKey *key,
|
int RSAVerify(const RSAPublicKey *key,
|
||||||
const uint8_t *sig,
|
const uint8_t *sig,
|
||||||
const int sig_len,
|
const int sig_len,
|
||||||
const uint8_t sig_type,
|
const uint8_t sig_type,
|
||||||
const uint8_t *hash) {
|
const uint8_t *hash) {
|
||||||
int i;
|
int i;
|
||||||
uint8_t* buf;
|
uint8_t* buf;
|
||||||
const uint8_t* padding;
|
const uint8_t* padding;
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ int RSAVerifyBinary_f(const uint8_t* key_blob,
|
|||||||
return 0; /* Both can't be NULL or non-NULL. */
|
return 0; /* Both can't be NULL or non-NULL. */
|
||||||
|
|
||||||
digest = DigestBuf(buf, len, algorithm);
|
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);
|
Free(digest);
|
||||||
if (!key)
|
if (!key)
|
||||||
|
|||||||
@@ -25,12 +25,14 @@ typedef struct FirmwareImage {
|
|||||||
uint8_t magic[FIRMWARE_MAGIC_SIZE];
|
uint8_t magic[FIRMWARE_MAGIC_SIZE];
|
||||||
/* Key Header */
|
/* Key Header */
|
||||||
uint16_t header_len; /* Length of the header. */
|
uint16_t header_len; /* Length of the header. */
|
||||||
uint16_t sign_algorithm; /* Signature algorithm used by the signing key. */
|
uint16_t firmware_sign_algorithm; /* Signature algorithm used by the signing
|
||||||
uint8_t* sign_key; /* Pre-processed public half of signing key. */
|
* key. */
|
||||||
uint16_t key_version; /* Key Version# for preventing rollbacks. */
|
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 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. */
|
/* Firmware Preamble. */
|
||||||
uint16_t firmware_version; /* Firmware Version# for preventing rollbacks.*/
|
uint16_t firmware_version; /* Firmware Version# for preventing rollbacks.*/
|
||||||
@@ -53,29 +55,38 @@ FirmwareImage* FirmwareImageNew(void);
|
|||||||
/* Deep free the contents of [fw]. */
|
/* Deep free the contents of [fw]. */
|
||||||
void FirmwareImageFree(FirmwareImage* 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.
|
* Returns a filled up FirmwareImage structure on success, NULL on error.
|
||||||
*/
|
*/
|
||||||
FirmwareImage* ReadFirmwareImage(const char* input_file);
|
FirmwareImage* ReadFirmwareImage(const char* input_file);
|
||||||
|
|
||||||
/* Write firmware header from [image] to an open file pointed by the
|
/* Get firmware header binary blob from an [image].
|
||||||
* file descriptor [fd].
|
*
|
||||||
|
* 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
|
/* Get firmware preamble binary blob from an [image].
|
||||||
* file descriptor [fd].
|
*
|
||||||
|
* 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].
|
/* 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,
|
int WriteFirmwareImage(const char* input_file,
|
||||||
FirmwareImage* image);
|
const FirmwareImage* image);
|
||||||
|
|
||||||
|
|
||||||
/* Pretty print the contents of [image]. Only headers and metadata information
|
/* Pretty print the contents of [image]. Only headers and metadata information
|
||||||
* is printed.
|
* is printed.
|
||||||
@@ -173,7 +184,6 @@ int AddFirmwareKeySignature(FirmwareImage* image, const char* root_key_file);
|
|||||||
*
|
*
|
||||||
* Return 1 on success, 0 on failure.
|
* Return 1 on success, 0 on failure.
|
||||||
*/
|
*/
|
||||||
int AddFirmwareSignature(FirmwareImage* image, const char* signing_key_file,
|
int AddFirmwareSignature(FirmwareImage* image, const char* signing_key_file);
|
||||||
int algorithm);
|
|
||||||
|
|
||||||
#endif /* VBOOT_REFERENCE_FIRMWARE_IMAGE_H_ */
|
#endif /* VBOOT_REFERENCE_FIRMWARE_IMAGE_H_ */
|
||||||
|
|||||||
@@ -51,10 +51,10 @@ class FirmwareUtility {
|
|||||||
std::string root_key_file_;
|
std::string root_key_file_;
|
||||||
std::string root_key_pub_file_;
|
std::string root_key_pub_file_;
|
||||||
int firmware_version_;
|
int firmware_version_;
|
||||||
std::string sign_key_file_;
|
std::string firmware_sign_key_file_;
|
||||||
std::string sign_key_pub_file_;
|
std::string firmware_sign_key_pub_file_;
|
||||||
int key_version_;
|
int firmware_key_version_;
|
||||||
int sign_algorithm_;
|
int firmware_sign_algorithm_;
|
||||||
std::string in_file_;
|
std::string in_file_;
|
||||||
std::string out_file_;
|
std::string out_file_;
|
||||||
bool is_generate_; // Are we generating a new image?
|
bool is_generate_; // Are we generating a new image?
|
||||||
|
|||||||
@@ -74,22 +74,31 @@ void KernelImageFree(KernelImage* image);
|
|||||||
*/
|
*/
|
||||||
KernelImage* ReadKernelImage(const char* input_file);
|
KernelImage* ReadKernelImage(const char* input_file);
|
||||||
|
|
||||||
/* Write kernel key header from [image] to an open file pointed by the
|
/* Get kernel header binary blob from an [image].
|
||||||
* file descriptor [fd].
|
*
|
||||||
|
* 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
|
/* Get kernel config binary blob from an [image].
|
||||||
* file descriptor [fd].
|
*
|
||||||
|
* 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].
|
/* 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,
|
int WriteKernelImage(const char* input_file,
|
||||||
KernelImage* image);
|
const KernelImage* image);
|
||||||
|
|
||||||
/* Pretty print the contents of [image]. Only headers and metadata information
|
/* Pretty print the contents of [image]. Only headers and metadata information
|
||||||
* is printed.
|
* is printed.
|
||||||
@@ -194,7 +203,7 @@ int AddKernelKeySignature(KernelImage* image, const char* firmware_key_file);
|
|||||||
*
|
*
|
||||||
* Return 1 on success, 0 on failure.
|
* Return 1 on success, 0 on failure.
|
||||||
*/
|
*/
|
||||||
int AddKernelSignature(KernelImage* image, const char* kernel_sigining_key_file,
|
int AddKernelSignature(KernelImage* image,
|
||||||
int algorithm);
|
const char* kernel_sigining_key_file);
|
||||||
|
|
||||||
#endif /* VBOOT_REFERENCE_KERNEL_IMAGE_H_ */
|
#endif /* VBOOT_REFERENCE_KERNEL_IMAGE_H_ */
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ typedef struct RSAPublicKey {
|
|||||||
/* Verify a RSA PKCS1.5 signature [sig] of [sig_type] and length [sig_len]
|
/* 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.
|
* 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 uint8_t* sig,
|
||||||
const int sig_len,
|
const int sig_len,
|
||||||
const uint8_t sig_type,
|
const uint8_t sig_type,
|
||||||
|
|||||||
@@ -13,4 +13,23 @@
|
|||||||
*/
|
*/
|
||||||
uint8_t* prepend_digestinfo(int algorithm, uint8_t* digest);
|
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_ */
|
#endif /* VBOOT_REFERENCE_SIGNATURE_DIGEST_H_ */
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ typedef struct MemcpyState {
|
|||||||
|
|
||||||
/* Copy [len] bytes into [dst] only if there's enough data to read according
|
/* Copy [len] bytes into [dst] only if there's enough data to read according
|
||||||
* to [state].
|
* 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.
|
* On failure, return NULL, set remaining len in state to -1.
|
||||||
*
|
*
|
||||||
* Useful for iterating through a binary blob to populate a struct. After the
|
* 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);
|
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_ */
|
#endif /* VBOOT_REFERENCE_UTILITY_H_ */
|
||||||
|
|||||||
@@ -7,30 +7,30 @@ CFLAGS = -Wall -DNDEBUG
|
|||||||
INCLUDES ?= -I../include/
|
INCLUDES ?= -I../include/
|
||||||
TOP ?= ../
|
TOP ?= ../
|
||||||
|
|
||||||
|
FIRMWARE_LIBS = $(TOP)/crypto/libcrypto.a $(TOP)/common/libcommon.a
|
||||||
LIBS = $(TOP)/utils/kernel_image.o $(TOP)/utils/firmware_image.o \
|
LIBS = $(TOP)/utils/kernel_image.o $(TOP)/utils/firmware_image.o \
|
||||||
$(TOP)/crypto/libcrypto.a $(TOP)/common/libcommon.a \
|
$(TOP)/utils/file_keys.o $(TOP)/utils/signature_digest.o -lcrypto
|
||||||
$(TOP)/utils/file_keys.o -lrt
|
|
||||||
|
|
||||||
tests: firmware_image_tests kernel_image_tests sha_tests sha_benchmark \
|
tests: firmware_image_tests kernel_image_tests sha_tests sha_benchmark \
|
||||||
rsa_verify_benchmark rsa_padding_test
|
rsa_verify_benchmark rsa_padding_test
|
||||||
|
|
||||||
sha_tests: sha_tests.c
|
sha_tests: sha_tests.c
|
||||||
$(CC) $(CFLAGS) $(INCLUDES) $< -o $@ $(LIBS)
|
$(CC) $(CFLAGS) $(INCLUDES) $^ -o $@ $(FIRMWARE_LIBS)
|
||||||
|
|
||||||
firmware_image_tests: firmware_image_tests.c $(LIBS)
|
firmware_image_tests: firmware_image_tests.c
|
||||||
$(CC) $(CFLAGS) $(INCLUDES) $< -o $@ $(LIBS)
|
$(CC) $(CFLAGS) $(INCLUDES) $< -o $@ $(LIBS) $(FIRMWARE_LIBS)
|
||||||
|
|
||||||
kernel_image_tests: kernel_image_tests.c $(LIBS)
|
kernel_image_tests: kernel_image_tests.c
|
||||||
$(CC) $(CFLAGS) $(INCLUDES) $< -o $@ $(LIBS)
|
$(CC) $(CFLAGS) $(INCLUDES) $< -o $@ $(LIBS) $(FIRMWARE_LIBS)
|
||||||
|
|
||||||
sha_benchmark: sha_benchmark.c timer_utils.c
|
sha_benchmark: sha_benchmark.c timer_utils.c $(FIRMWARE_LIBS)
|
||||||
$(CC) $(CFLAGS) $(INCLUDES) $^ -o $@ $(LIBS)
|
$(CC) $(CFLAGS) $(INCLUDES) $^ -o $@ -lrt
|
||||||
|
|
||||||
rsa_padding_test: rsa_padding_test.c
|
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
|
rsa_verify_benchmark: rsa_verify_benchmark.c timer_utils.c
|
||||||
$(CC) $(CFLAGS) $(INCLUDES) $^ -o $@ $(LIBS)
|
$(CC) $(CFLAGS) $(INCLUDES) $^ -o $@ -lrt $(LIBS) $(FIRMWARE_LIBS)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f sha_tests sha_benchmark rsa_verify_benchmark \
|
rm -f sha_tests sha_benchmark rsa_verify_benchmark \
|
||||||
|
|||||||
@@ -31,8 +31,8 @@ int TEST_EQ(int result, int expected_result, char* testname) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
FirmwareImage* GenerateTestFirmwareImage(int algorithm,
|
FirmwareImage* GenerateTestFirmwareImage(int algorithm,
|
||||||
uint8_t* sign_key,
|
uint8_t* firmware_sign_key,
|
||||||
int key_version,
|
int firmware_key_version,
|
||||||
int firmware_version,
|
int firmware_version,
|
||||||
int firmware_len) {
|
int firmware_len) {
|
||||||
FirmwareImage* image = FirmwareImageNew();
|
FirmwareImage* image = FirmwareImageNew();
|
||||||
@@ -40,29 +40,30 @@ FirmwareImage* GenerateTestFirmwareImage(int algorithm,
|
|||||||
DigestContext ctx;
|
DigestContext ctx;
|
||||||
|
|
||||||
Memcpy(image->magic, FIRMWARE_MAGIC, FIRMWARE_MAGIC_SIZE);
|
Memcpy(image->magic, FIRMWARE_MAGIC, FIRMWARE_MAGIC_SIZE);
|
||||||
image->sign_algorithm = algorithm;
|
image->firmware_sign_algorithm = algorithm;
|
||||||
image->sign_key = (uint8_t*) Malloc(
|
image->firmware_sign_key = (uint8_t*) Malloc(
|
||||||
RSAProcessedKeySize(image->sign_algorithm));
|
RSAProcessedKeySize(image->firmware_sign_algorithm));
|
||||||
Memcpy(image->sign_key, sign_key, RSAProcessedKeySize(image->sign_algorithm));
|
Memcpy(image->firmware_sign_key, firmware_sign_key,
|
||||||
image->key_version = key_version;
|
RSAProcessedKeySize(image->firmware_sign_algorithm));
|
||||||
|
image->firmware_key_version = firmware_key_version;
|
||||||
|
|
||||||
/* Update correct header length. */
|
/* Update correct header length. */
|
||||||
image->header_len = (sizeof(image->header_len) +
|
image->header_len = (sizeof(image->header_len) +
|
||||||
sizeof(image->sign_algorithm) +
|
sizeof(image->firmware_sign_algorithm) +
|
||||||
RSAProcessedKeySize(image->sign_algorithm) +
|
RSAProcessedKeySize(image->firmware_sign_algorithm) +
|
||||||
sizeof(image->key_version) +
|
sizeof(image->firmware_key_version) +
|
||||||
sizeof(image->header_checksum));
|
sizeof(image->header_checksum));
|
||||||
|
|
||||||
/* Calculate SHA-512 digest on header and populate header_checksum. */
|
/* Calculate SHA-512 digest on header and populate header_checksum. */
|
||||||
DigestInit(&ctx, ROOT_SIGNATURE_ALGORITHM);
|
DigestInit(&ctx, ROOT_SIGNATURE_ALGORITHM);
|
||||||
DigestUpdate(&ctx, (uint8_t*) &image->header_len,
|
DigestUpdate(&ctx, (uint8_t*) &image->header_len,
|
||||||
sizeof(image->header_len));
|
sizeof(image->header_len));
|
||||||
DigestUpdate(&ctx, (uint8_t*) &image->sign_algorithm,
|
DigestUpdate(&ctx, (uint8_t*) &image->firmware_sign_algorithm,
|
||||||
sizeof(image->sign_algorithm));
|
sizeof(image->firmware_sign_algorithm));
|
||||||
DigestUpdate(&ctx, image->sign_key,
|
DigestUpdate(&ctx, image->firmware_sign_key,
|
||||||
RSAProcessedKeySize(image->sign_algorithm));
|
RSAProcessedKeySize(image->firmware_sign_algorithm));
|
||||||
DigestUpdate(&ctx, (uint8_t*) &image->key_version,
|
DigestUpdate(&ctx, (uint8_t*) &image->firmware_key_version,
|
||||||
sizeof(image->key_version));
|
sizeof(image->firmware_key_version));
|
||||||
header_checksum = DigestFinal(&ctx);
|
header_checksum = DigestFinal(&ctx);
|
||||||
Memcpy(image->header_checksum, header_checksum, SHA512_DIGEST_SIZE);
|
Memcpy(image->header_checksum, header_checksum, SHA512_DIGEST_SIZE);
|
||||||
Free(header_checksum);
|
Free(header_checksum);
|
||||||
@@ -144,8 +145,8 @@ int VerifyFirmwareImageTamperTest(FirmwareImage* image,
|
|||||||
|
|
||||||
|
|
||||||
fprintf(stderr, "[[Tampering with root key signature...]]\n");
|
fprintf(stderr, "[[Tampering with root key signature...]]\n");
|
||||||
image->key_signature[0] = 0xFF;
|
image->firmware_key_signature[0] = 0xFF;
|
||||||
image->key_signature[1] = 0x00;
|
image->firmware_key_signature[1] = 0x00;
|
||||||
if (!TEST_EQ(VerifyFirmwareImage(root_key, image, DEV_MODE_ENABLED),
|
if (!TEST_EQ(VerifyFirmwareImage(root_key, image, DEV_MODE_ENABLED),
|
||||||
VERIFY_FIRMWARE_SUCCESS,
|
VERIFY_FIRMWARE_SUCCESS,
|
||||||
"FirmwareImage Root Signature Tamper Verification (Dev Mode)"))
|
"FirmwareImage Root Signature Tamper Verification (Dev Mode)"))
|
||||||
@@ -160,13 +161,13 @@ int VerifyFirmwareImageTamperTest(FirmwareImage* image,
|
|||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
uint8_t* sign_key_buf = NULL;
|
uint8_t* firmware_sign_key_buf = NULL;
|
||||||
uint8_t* root_key_blob = NULL;
|
uint8_t* root_key_blob = NULL;
|
||||||
uint8_t* firmware_blob = NULL;
|
uint8_t* firmware_blob = NULL;
|
||||||
|
int firmware_blob_len = 0;
|
||||||
FirmwareImage* image = NULL;
|
FirmwareImage* image = NULL;
|
||||||
RSAPublicKey* root_key = NULL;
|
RSAPublicKey* root_key = NULL;
|
||||||
int error_code = 1;
|
int error_code = 1;
|
||||||
char* tmp_firmwareblob_file = ".tmpFirmwareBlob";
|
|
||||||
|
|
||||||
if(argc != 6) {
|
if(argc != 6) {
|
||||||
fprintf(stderr, "Usage: %s <algorithm> <root key> <processed root pubkey>"
|
fprintf(stderr, "Usage: %s <algorithm> <root key> <processed root pubkey>"
|
||||||
@@ -177,11 +178,11 @@ int main(int argc, char* argv[]) {
|
|||||||
/* Read verification keys and create a test image. */
|
/* Read verification keys and create a test image. */
|
||||||
root_key = RSAPublicKeyFromFile(argv[3]);
|
root_key = RSAPublicKeyFromFile(argv[3]);
|
||||||
root_key_blob = BufferFromFile(argv[3], &len);
|
root_key_blob = BufferFromFile(argv[3], &len);
|
||||||
sign_key_buf = BufferFromFile(argv[5], &len);
|
firmware_sign_key_buf = BufferFromFile(argv[5], &len);
|
||||||
image = GenerateTestFirmwareImage(atoi(argv[1]), sign_key_buf, 1,
|
image = GenerateTestFirmwareImage(atoi(argv[1]), firmware_sign_key_buf, 1,
|
||||||
1, 1000);
|
1, 1000);
|
||||||
|
|
||||||
if (!root_key || !sign_key_buf || !image) {
|
if (!root_key || !firmware_sign_key_buf || !image) {
|
||||||
error_code = 1;
|
error_code = 1;
|
||||||
goto failure;
|
goto failure;
|
||||||
}
|
}
|
||||||
@@ -193,25 +194,13 @@ int main(int argc, char* argv[]) {
|
|||||||
goto failure;
|
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");
|
fprintf(stderr, "Couldn't create firmware and preamble signature.\n");
|
||||||
error_code = 1;
|
error_code = 1;
|
||||||
goto failure;
|
goto failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
firmware_blob = GetFirmwareBlob(image, &firmware_blob_len);
|
||||||
/* 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);
|
|
||||||
|
|
||||||
/* Test Firmware blob verify operations. */
|
/* Test Firmware blob verify operations. */
|
||||||
if (!VerifyFirmwareTest(firmware_blob, root_key_blob))
|
if (!VerifyFirmwareTest(firmware_blob, root_key_blob))
|
||||||
@@ -226,7 +215,7 @@ int main(int argc, char* argv[]) {
|
|||||||
failure:
|
failure:
|
||||||
Free(firmware_blob);
|
Free(firmware_blob);
|
||||||
Free(image);
|
Free(image);
|
||||||
Free(sign_key_buf);
|
Free(firmware_sign_key_buf);
|
||||||
Free(root_key_blob);
|
Free(root_key_blob);
|
||||||
Free(root_key);
|
Free(root_key);
|
||||||
|
|
||||||
|
|||||||
@@ -174,10 +174,10 @@ int main(int argc, char* argv[]) {
|
|||||||
uint8_t* kernel_sign_key_buf = NULL;
|
uint8_t* kernel_sign_key_buf = NULL;
|
||||||
uint8_t* firmware_key_blob = NULL;
|
uint8_t* firmware_key_blob = NULL;
|
||||||
uint8_t* kernel_blob = NULL;
|
uint8_t* kernel_blob = NULL;
|
||||||
|
int kernel_blob_len = 0;
|
||||||
KernelImage* image = NULL;
|
KernelImage* image = NULL;
|
||||||
RSAPublicKey* firmware_key = NULL;
|
RSAPublicKey* firmware_key = NULL;
|
||||||
int error_code = 1;
|
int error_code = 1;
|
||||||
char* tmp_kernelblob_file = ".tmpKernelBlob";
|
|
||||||
|
|
||||||
if(argc != 7) {
|
if(argc != 7) {
|
||||||
fprintf(stderr, "Usage: %s <firmware signing algorithm> " /* argv[1] */
|
fprintf(stderr, "Usage: %s <firmware signing algorithm> " /* argv[1] */
|
||||||
@@ -217,24 +217,13 @@ int main(int argc, char* argv[]) {
|
|||||||
goto failure;
|
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");
|
fprintf(stderr, "Couldn't create firmware and preamble signature.\n");
|
||||||
error_code = 1;
|
error_code = 1;
|
||||||
goto failure;
|
goto failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Generate a firmware binary blob from image.
|
kernel_blob = GetKernelBlob(image, &kernel_blob_len);
|
||||||
*
|
|
||||||
* 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. */
|
/* Test Kernel blob verify operations. */
|
||||||
if (!VerifyKernelTest(kernel_blob, firmware_key_blob))
|
if (!VerifyKernelTest(kernel_blob, firmware_key_blob))
|
||||||
|
|||||||
@@ -25,14 +25,14 @@ int main(int argc, char* argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* The first test signature is valid. */
|
/* 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)) {
|
test_message_sha1_hash)) {
|
||||||
fprintf(stderr, "RSA Padding Test vector 0 FAILED!\n");
|
fprintf(stderr, "RSA Padding Test vector 0 FAILED!\n");
|
||||||
error = 255; /* Test failure. */
|
error = 255; /* Test failure. */
|
||||||
}
|
}
|
||||||
/* All other signatures should fail verification. */
|
/* All other signatures should fail verification. */
|
||||||
for (i = 1; i < sizeof(signatures) / sizeof(signatures[0]); i++) {
|
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)) {
|
test_message_sha1_hash)) {
|
||||||
fprintf(stderr, "RSA Padding Test vector %d FAILED!\n", i);
|
fprintf(stderr, "RSA Padding Test vector %d FAILED!\n", i);
|
||||||
error = 255; /* Test failure. */
|
error = 255; /* Test failure. */
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ int SpeedTestAlgorithm(int algorithm) {
|
|||||||
|
|
||||||
StartTimer(&ct);
|
StartTimer(&ct);
|
||||||
for (i = 0; i < NUM_OPERATIONS; i++) {
|
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");
|
fprintf(stderr, "Warning: Signature Check Failed.\n");
|
||||||
}
|
}
|
||||||
StopTimer(&ct);
|
StopTimer(&ct);
|
||||||
|
|||||||
@@ -8,26 +8,25 @@ CFLAGS = -Wall -DNDEBUG
|
|||||||
INCLUDES ?= -I../include/
|
INCLUDES ?= -I../include/
|
||||||
TOP ?= ../
|
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
|
FIRMWARELIBS = $(TOP)/crypto/libcrypto.a $(TOP)/common/libcommon.a
|
||||||
|
|
||||||
all: dumpRSAPublicKey verify_data signature_digest firmware_utility \
|
all: dumpRSAPublicKey verify_data file_keys.o signature_digest.o firmware_image.o \
|
||||||
file_keys.o firmware_image.o kernel_image.o
|
kernel_image.o signature_digest.o firmware_utility
|
||||||
|
|
||||||
dumpRSAPublicKey: dumpRSAPublicKey.c
|
dumpRSAPublicKey: dumpRSAPublicKey.c
|
||||||
$(CC) $(CFLAGS) $(LIBS) $< -o $@
|
$(CC) $(CFLAGS) $< -o $@ -lcrypto
|
||||||
|
|
||||||
verify_data: verify_data.c file_keys.c
|
verify_data: verify_data.c $(LIBS) $(FIRMWARELIBS)
|
||||||
$(CC) $(CFLAGS) $(INCLUDES) $^ -o $@ $(FIRMWARELIBS)
|
$(CC) $(CFLAGS) $(INCLUDES) $< -o $@ $(LIBS) $(FIRMWARELIBS) -lcrypto
|
||||||
|
|
||||||
signature_digest: signature_digest.c
|
firmware_utility: firmware_utility.cc $(LIBS) $(FIRMWARELIBS)
|
||||||
$(CC) $(CFLAGS) $(INCLUDES) $< -o $@ $(FIRMWARELIBS)
|
$(CXX) $(CFLAGS) $(INCLUDES) -ggdb -D__STDC_LIMIT_MACROS $< \
|
||||||
|
-o $@ $(FIRMWARELIBS) $(LIBS) -lcrypto
|
||||||
|
|
||||||
firmware_utility: firmware_utility.cc firmware_image.o file_keys.o
|
signature_digest.o: signature_digest.c
|
||||||
$(CXX) $(CFLAGS) $(INCLUDES) -ggdb -D__STDC_LIMIT_MACROS $^ \
|
$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
|
||||||
-o $@ $(FIRMWARELIBS)
|
|
||||||
|
|
||||||
# Used by tests.
|
|
||||||
file_keys.o: file_keys.c
|
file_keys.o: file_keys.c
|
||||||
$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
|
$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
|
||||||
|
|
||||||
@@ -37,6 +36,5 @@ firmware_image.o: firmware_image.c
|
|||||||
kernel_image.o: kernel_image.c
|
kernel_image.o: kernel_image.c
|
||||||
$(CC) $(CFLAGS) -ansi $(INCLUDES) -c $< -o $@
|
$(CC) $(CFLAGS) -ansi $(INCLUDES) -c $< -o $@
|
||||||
clean:
|
clean:
|
||||||
rm -f dumpRSAPublicKey verify_data signature_digest firmware_image.o \
|
rm -f dumpRSAPublicKey verify_data signature_digest firmware_utility \
|
||||||
kernel_image.o file_keys.o firmware_utility
|
$(LIBS)
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
#include "padding.h"
|
#include "padding.h"
|
||||||
#include "rsa_utility.h"
|
#include "rsa_utility.h"
|
||||||
|
#include "signature_digest.h"
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
|
|
||||||
uint8_t* BufferFromFile(const char* input_file, uint32_t* len) {
|
uint8_t* BufferFromFile(const char* input_file, uint32_t* len) {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include "padding.h"
|
#include "padding.h"
|
||||||
#include "rsa_utility.h"
|
#include "rsa_utility.h"
|
||||||
#include "sha_utility.h"
|
#include "sha_utility.h"
|
||||||
|
#include "signature_digest.h"
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
|
|
||||||
/* Macro to determine the size of a field structure in the FirmwareImage
|
/* Macro to determine the size of a field structure in the FirmwareImage
|
||||||
@@ -27,7 +28,7 @@
|
|||||||
FirmwareImage* FirmwareImageNew(void) {
|
FirmwareImage* FirmwareImageNew(void) {
|
||||||
FirmwareImage* image = (FirmwareImage*) Malloc(sizeof(FirmwareImage));
|
FirmwareImage* image = (FirmwareImage*) Malloc(sizeof(FirmwareImage));
|
||||||
if (image) {
|
if (image) {
|
||||||
image->sign_key = NULL;
|
image->firmware_sign_key = NULL;
|
||||||
image->preamble_signature = NULL;
|
image->preamble_signature = NULL;
|
||||||
image->firmware_signature = NULL;
|
image->firmware_signature = NULL;
|
||||||
image->firmware_data = NULL;
|
image->firmware_data = NULL;
|
||||||
@@ -37,10 +38,11 @@ FirmwareImage* FirmwareImageNew(void) {
|
|||||||
|
|
||||||
void FirmwareImageFree(FirmwareImage* image) {
|
void FirmwareImageFree(FirmwareImage* image) {
|
||||||
if (image) {
|
if (image) {
|
||||||
Free(image->sign_key);
|
Free(image->firmware_sign_key);
|
||||||
Free(image->preamble_signature);
|
Free(image->preamble_signature);
|
||||||
Free(image->firmware_signature);
|
Free(image->firmware_signature);
|
||||||
Free(image->firmware_data);
|
Free(image->firmware_data);
|
||||||
|
Free(image);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,7 +50,7 @@ FirmwareImage* ReadFirmwareImage(const char* input_file) {
|
|||||||
uint32_t file_size;
|
uint32_t file_size;
|
||||||
int image_len = 0; /* Total size of the firmware image. */
|
int image_len = 0; /* Total size of the firmware image. */
|
||||||
int header_len = 0;
|
int header_len = 0;
|
||||||
int sign_key_len;
|
int firmware_sign_key_len;
|
||||||
int signature_len;
|
int signature_len;
|
||||||
uint8_t* firmware_buf;
|
uint8_t* firmware_buf;
|
||||||
MemcpyState st;
|
MemcpyState st;
|
||||||
@@ -64,46 +66,49 @@ FirmwareImage* ReadFirmwareImage(const char* input_file) {
|
|||||||
st.remaining_buf = firmware_buf;
|
st.remaining_buf = firmware_buf;
|
||||||
|
|
||||||
/* Read and compare magic bytes. */
|
/* Read and compare magic bytes. */
|
||||||
if (!StatefulMemcpy(&st, &image->magic, FIRMWARE_MAGIC_SIZE))
|
StatefulMemcpy(&st, &image->magic, FIRMWARE_MAGIC_SIZE);
|
||||||
goto parse_failure;
|
|
||||||
|
|
||||||
if (SafeMemcmp(image->magic, FIRMWARE_MAGIC, FIRMWARE_MAGIC_SIZE)) {
|
if (SafeMemcmp(image->magic, FIRMWARE_MAGIC, FIRMWARE_MAGIC_SIZE)) {
|
||||||
fprintf(stderr, "Wrong Firmware Magic.\n");
|
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->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? */
|
/* Valid Algorithm? */
|
||||||
if (image->sign_algorithm >= kNumAlgorithms)
|
if (image->firmware_sign_algorithm >= kNumAlgorithms) {
|
||||||
goto parse_failure;
|
Free(firmware_buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Compute size of pre-processed RSA public key and signature. */
|
/* Compute size of pre-processed RSA public key and signature. */
|
||||||
sign_key_len = RSAProcessedKeySize(image->sign_algorithm);
|
firmware_sign_key_len = RSAProcessedKeySize(image->firmware_sign_algorithm);
|
||||||
signature_len = siglen_map[image->sign_algorithm];
|
signature_len = siglen_map[image->firmware_sign_algorithm];
|
||||||
|
|
||||||
|
|
||||||
/* Check whether the header length is correct. */
|
/* Check whether the header length is correct. */
|
||||||
header_len = (FIELD_LEN(header_len) +
|
header_len = (FIELD_LEN(header_len) +
|
||||||
FIELD_LEN(sign_algorithm) +
|
FIELD_LEN(firmware_sign_algorithm) +
|
||||||
sign_key_len +
|
firmware_sign_key_len +
|
||||||
FIELD_LEN(key_version) +
|
FIELD_LEN(firmware_key_version) +
|
||||||
FIELD_LEN(header_checksum));
|
FIELD_LEN(header_checksum));
|
||||||
if (header_len != image->header_len) {
|
if (header_len != image->header_len) {
|
||||||
fprintf(stderr, "Header length mismatch. Got: %d Expected: %d\n",
|
fprintf(stderr, "Header length mismatch. Got: %d Expected: %d\n",
|
||||||
image->header_len, header_len);
|
image->header_len, header_len);
|
||||||
goto parse_failure;
|
Free(firmware_buf);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read pre-processed public half of the sign key. */
|
/* Read pre-processed public half of the sign key. */
|
||||||
image->sign_key = (uint8_t*) Malloc(sign_key_len);
|
image->firmware_sign_key = (uint8_t*) Malloc(firmware_sign_key_len);
|
||||||
StatefulMemcpy(&st, image->sign_key, sign_key_len);
|
StatefulMemcpy(&st, image->firmware_sign_key, firmware_sign_key_len);
|
||||||
StatefulMemcpy(&st, &image->key_version, FIELD_LEN(key_version));
|
StatefulMemcpy(&st, &image->firmware_key_version,
|
||||||
|
FIELD_LEN(firmware_key_version));
|
||||||
StatefulMemcpy(&st, image->header_checksum, FIELD_LEN(header_checksum));
|
StatefulMemcpy(&st, image->header_checksum, FIELD_LEN(header_checksum));
|
||||||
|
|
||||||
/* Read key signature. */
|
/* 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. */
|
/* Read the firmware preamble. */
|
||||||
StatefulMemcpy(&st,&image->firmware_version, FIELD_LEN(firmware_version));
|
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);
|
image->firmware_data = (uint8_t*) Malloc(image->firmware_len);
|
||||||
StatefulMemcpy(&st, image->firmware_data, image->firmware_len);
|
StatefulMemcpy(&st, image->firmware_data, image->firmware_len);
|
||||||
|
|
||||||
if(st.remaining_len != 0) /* Overrun or underrun. */
|
if(st.remaining_len != 0) { /* Overrun or underrun. */
|
||||||
goto parse_failure;
|
Free(firmware_buf);
|
||||||
|
|
||||||
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");
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
write(fd, image->magic, FIELD_LEN(magic));
|
Free(firmware_buf);
|
||||||
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);
|
|
||||||
return image;
|
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) {
|
void PrintFirmwareImage(const FirmwareImage* image) {
|
||||||
if (!image)
|
if (!image)
|
||||||
return;
|
return;
|
||||||
@@ -186,9 +270,9 @@ void PrintFirmwareImage(const FirmwareImage* image) {
|
|||||||
"Signature Algorithm = %s\n"
|
"Signature Algorithm = %s\n"
|
||||||
"Key Version = %d\n\n",
|
"Key Version = %d\n\n",
|
||||||
image->header_len,
|
image->header_len,
|
||||||
image->sign_algorithm,
|
image->firmware_sign_algorithm,
|
||||||
algo_strings[image->sign_algorithm],
|
algo_strings[image->firmware_sign_algorithm],
|
||||||
image->key_version);
|
image->firmware_key_version);
|
||||||
/* TODO(gauravsh): Output hash and key signature here? */
|
/* TODO(gauravsh): Output hash and key signature here? */
|
||||||
/* Print preamble. */
|
/* Print preamble. */
|
||||||
printf("Firmware Version = %d\n"
|
printf("Firmware Version = %d\n"
|
||||||
@@ -213,31 +297,31 @@ int VerifyFirmwareHeader(const uint8_t* root_key_blob,
|
|||||||
const int dev_mode,
|
const int dev_mode,
|
||||||
int* algorithm,
|
int* algorithm,
|
||||||
int* header_len) {
|
int* header_len) {
|
||||||
int sign_key_len;
|
int firmware_sign_key_len;
|
||||||
int root_key_len;
|
int root_key_len;
|
||||||
uint16_t hlen, algo;
|
uint16_t hlen, algo;
|
||||||
uint8_t* header_checksum = NULL;
|
uint8_t* header_checksum = NULL;
|
||||||
|
|
||||||
/* Base Offset for the header_checksum field. Actual offset is
|
/* 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) +
|
int base_header_checksum_offset = (FIELD_LEN(header_len) +
|
||||||
FIELD_LEN(sign_algorithm) +
|
FIELD_LEN(firmware_sign_algorithm) +
|
||||||
FIELD_LEN(key_version));
|
FIELD_LEN(firmware_key_version));
|
||||||
|
|
||||||
|
|
||||||
root_key_len = RSAProcessedKeySize(ROOT_SIGNATURE_ALGORITHM);
|
root_key_len = RSAProcessedKeySize(ROOT_SIGNATURE_ALGORITHM);
|
||||||
Memcpy(&hlen, header_blob, sizeof(hlen));
|
Memcpy(&hlen, header_blob, sizeof(hlen));
|
||||||
Memcpy(&algo,
|
Memcpy(&algo,
|
||||||
header_blob + FIELD_LEN(sign_algorithm),
|
header_blob + FIELD_LEN(firmware_sign_algorithm),
|
||||||
sizeof(algo));
|
sizeof(algo));
|
||||||
if (algo >= kNumAlgorithms)
|
if (algo >= kNumAlgorithms)
|
||||||
return VERIFY_FIRMWARE_INVALID_ALGORITHM;
|
return VERIFY_FIRMWARE_INVALID_ALGORITHM;
|
||||||
*algorithm = (int) algo;
|
*algorithm = (int) algo;
|
||||||
sign_key_len = RSAProcessedKeySize(*algorithm);
|
firmware_sign_key_len = RSAProcessedKeySize(*algorithm);
|
||||||
|
|
||||||
/* Verify if header len is correct? */
|
/* Verify if header len is correct? */
|
||||||
if (hlen != (base_header_checksum_offset +
|
if (hlen != (base_header_checksum_offset +
|
||||||
sign_key_len +
|
firmware_sign_key_len +
|
||||||
FIELD_LEN(header_checksum)))
|
FIELD_LEN(header_checksum)))
|
||||||
return VERIFY_FIRMWARE_INVALID_IMAGE;
|
return VERIFY_FIRMWARE_INVALID_IMAGE;
|
||||||
|
|
||||||
@@ -248,7 +332,8 @@ int VerifyFirmwareHeader(const uint8_t* root_key_blob,
|
|||||||
*header_len - FIELD_LEN(header_checksum),
|
*header_len - FIELD_LEN(header_checksum),
|
||||||
SHA512_DIGEST_ALGORITHM);
|
SHA512_DIGEST_ALGORITHM);
|
||||||
if (SafeMemcmp(header_checksum,
|
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))) {
|
FIELD_LEN(header_checksum))) {
|
||||||
Free(header_checksum);
|
Free(header_checksum);
|
||||||
return VERIFY_FIRMWARE_INVALID_IMAGE;
|
return VERIFY_FIRMWARE_INVALID_IMAGE;
|
||||||
@@ -267,7 +352,7 @@ int VerifyFirmwareHeader(const uint8_t* root_key_blob,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int VerifyFirmwarePreamble(RSAPublicKey* sign_key,
|
int VerifyFirmwarePreamble(RSAPublicKey* firmware_sign_key,
|
||||||
const uint8_t* preamble_blob,
|
const uint8_t* preamble_blob,
|
||||||
int algorithm,
|
int algorithm,
|
||||||
int* firmware_len) {
|
int* firmware_len) {
|
||||||
@@ -276,7 +361,7 @@ int VerifyFirmwarePreamble(RSAPublicKey* sign_key,
|
|||||||
preamble_len = (FIELD_LEN(firmware_version) +
|
preamble_len = (FIELD_LEN(firmware_version) +
|
||||||
FIELD_LEN(firmware_len) +
|
FIELD_LEN(firmware_len) +
|
||||||
FIELD_LEN(preamble));
|
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_blob, /* Data to verify */
|
||||||
preamble_len, /* Length of data */
|
preamble_len, /* Length of data */
|
||||||
preamble_blob + preamble_len, /* Expected Signature */
|
preamble_blob + preamble_len, /* Expected Signature */
|
||||||
@@ -289,12 +374,12 @@ int VerifyFirmwarePreamble(RSAPublicKey* sign_key,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int VerifyFirmwareData(RSAPublicKey* sign_key,
|
int VerifyFirmwareData(RSAPublicKey* firmware_sign_key,
|
||||||
const uint8_t* firmware_data_start,
|
const uint8_t* firmware_data_start,
|
||||||
int firmware_len,
|
int firmware_len,
|
||||||
int algorithm) {
|
int algorithm) {
|
||||||
int signature_len = siglen_map[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
|
firmware_data_start + signature_len, /* Data to
|
||||||
* verify */
|
* verify */
|
||||||
firmware_len, /* Length of data. */
|
firmware_len, /* Length of data. */
|
||||||
@@ -309,10 +394,10 @@ int VerifyFirmware(const uint8_t* root_key_blob,
|
|||||||
const int dev_mode) {
|
const int dev_mode) {
|
||||||
int error_code;
|
int error_code;
|
||||||
int algorithm; /* Signing key algorithm. */
|
int algorithm; /* Signing key algorithm. */
|
||||||
RSAPublicKey* sign_key;
|
RSAPublicKey* firmware_sign_key;
|
||||||
int sign_key_len, signature_len, header_len, firmware_len;
|
int firmware_sign_key_len, signature_len, header_len, firmware_len;
|
||||||
const uint8_t* header_ptr; /* Pointer to header. */
|
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* preamble_ptr; /* Pointer to preamble block. */
|
||||||
const uint8_t* firmware_ptr; /* Pointer to firmware signature/data. */
|
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
|
/* Parse signing key into RSAPublicKey structure since it is required multiple
|
||||||
* times. */
|
* times. */
|
||||||
sign_key_len = RSAProcessedKeySize(algorithm);
|
firmware_sign_key_len = RSAProcessedKeySize(algorithm);
|
||||||
sign_key_ptr = header_ptr + (FIELD_LEN(header_len) +
|
firmware_sign_key_ptr = header_ptr + (FIELD_LEN(header_len) +
|
||||||
FIELD_LEN(sign_algorithm));
|
FIELD_LEN(firmware_sign_algorithm));
|
||||||
sign_key = RSAPublicKeyFromBuf(sign_key_ptr, sign_key_len);
|
firmware_sign_key = RSAPublicKeyFromBuf(firmware_sign_key_ptr,
|
||||||
|
firmware_sign_key_len);
|
||||||
signature_len = siglen_map[algorithm];
|
signature_len = siglen_map[algorithm];
|
||||||
|
|
||||||
/* Only continue if preamble verification succeeds. */
|
/* Only continue if preamble verification succeeds. */
|
||||||
preamble_ptr = (header_ptr + header_len +
|
preamble_ptr = (header_ptr + header_len +
|
||||||
FIELD_LEN(key_signature));
|
FIELD_LEN(firmware_key_signature));
|
||||||
if ((error_code = VerifyFirmwarePreamble(sign_key, preamble_ptr, algorithm,
|
if ((error_code = VerifyFirmwarePreamble(firmware_sign_key, preamble_ptr,
|
||||||
|
algorithm,
|
||||||
&firmware_len)))
|
&firmware_len)))
|
||||||
return error_code; /* AKA jump to recovery. */
|
return error_code; /* AKA jump to recovery. */
|
||||||
|
|
||||||
@@ -351,7 +438,8 @@ int VerifyFirmware(const uint8_t* root_key_blob,
|
|||||||
FIELD_LEN(preamble) +
|
FIELD_LEN(preamble) +
|
||||||
signature_len);
|
signature_len);
|
||||||
|
|
||||||
if ((error_code = VerifyFirmwareData(sign_key, firmware_ptr, firmware_len,
|
if ((error_code = VerifyFirmwareData(firmware_sign_key, firmware_ptr,
|
||||||
|
firmware_len,
|
||||||
algorithm)))
|
algorithm)))
|
||||||
return error_code; /* AKA jump to recovery. */
|
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,
|
int VerifyFirmwareImage(const RSAPublicKey* root_key,
|
||||||
const FirmwareImage* image,
|
const FirmwareImage* image,
|
||||||
const int dev_mode) {
|
const int dev_mode) {
|
||||||
RSAPublicKey* sign_key;
|
RSAPublicKey* firmware_sign_key;
|
||||||
uint8_t* header_digest = NULL;
|
uint8_t* header_digest = NULL;
|
||||||
uint8_t* preamble_digest = NULL;
|
uint8_t* preamble_digest = NULL;
|
||||||
uint8_t* firmware_digest = NULL;
|
uint8_t* firmware_digest = NULL;
|
||||||
int sign_key_size;
|
int firmware_sign_key_size;
|
||||||
int signature_size;
|
int signature_size;
|
||||||
int error_code = 0;
|
int error_code = 0;
|
||||||
DigestContext ctx;
|
DigestContext ctx;
|
||||||
@@ -384,17 +472,17 @@ int VerifyFirmwareImage(const RSAPublicKey* root_key,
|
|||||||
DigestInit(&ctx, ROOT_SIGNATURE_ALGORITHM);
|
DigestInit(&ctx, ROOT_SIGNATURE_ALGORITHM);
|
||||||
DigestUpdate(&ctx, (uint8_t*) &image->header_len,
|
DigestUpdate(&ctx, (uint8_t*) &image->header_len,
|
||||||
FIELD_LEN(header_len));
|
FIELD_LEN(header_len));
|
||||||
DigestUpdate(&ctx, (uint8_t*) &image->sign_algorithm,
|
DigestUpdate(&ctx, (uint8_t*) &image->firmware_sign_algorithm,
|
||||||
FIELD_LEN(sign_algorithm));
|
FIELD_LEN(firmware_sign_algorithm));
|
||||||
DigestUpdate(&ctx, image->sign_key,
|
DigestUpdate(&ctx, image->firmware_sign_key,
|
||||||
RSAProcessedKeySize(image->sign_algorithm));
|
RSAProcessedKeySize(image->firmware_sign_algorithm));
|
||||||
DigestUpdate(&ctx, (uint8_t*) &image->key_version,
|
DigestUpdate(&ctx, (uint8_t*) &image->firmware_key_version,
|
||||||
FIELD_LEN(key_version));
|
FIELD_LEN(firmware_key_version));
|
||||||
DigestUpdate(&ctx, image->header_checksum,
|
DigestUpdate(&ctx, image->header_checksum,
|
||||||
FIELD_LEN(header_checksum));
|
FIELD_LEN(header_checksum));
|
||||||
header_digest = DigestFinal(&ctx);
|
header_digest = DigestFinal(&ctx);
|
||||||
if (!RSA_verify(root_key, image->key_signature,
|
if (!RSAVerify(root_key, image->firmware_key_signature,
|
||||||
FIELD_LEN(key_signature),
|
FIELD_LEN(firmware_key_signature),
|
||||||
ROOT_SIGNATURE_ALGORITHM,
|
ROOT_SIGNATURE_ALGORITHM,
|
||||||
header_digest)) {
|
header_digest)) {
|
||||||
error_code = VERIFY_FIRMWARE_ROOT_SIGNATURE_FAILED;
|
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. */
|
/* Get sign key to verify the rest of the firmware. */
|
||||||
sign_key_size = RSAProcessedKeySize(image->sign_algorithm);
|
firmware_sign_key_size = RSAProcessedKeySize(image->firmware_sign_algorithm);
|
||||||
sign_key = RSAPublicKeyFromBuf(image->sign_key,
|
firmware_sign_key = RSAPublicKeyFromBuf(image->firmware_sign_key,
|
||||||
sign_key_size);
|
firmware_sign_key_size);
|
||||||
signature_size = siglen_map[image->sign_algorithm];
|
signature_size = siglen_map[image->firmware_sign_algorithm];
|
||||||
|
|
||||||
if (image->sign_algorithm >= kNumAlgorithms)
|
if (image->firmware_sign_algorithm >= kNumAlgorithms)
|
||||||
return VERIFY_FIRMWARE_INVALID_ALGORITHM;
|
return VERIFY_FIRMWARE_INVALID_ALGORITHM;
|
||||||
|
|
||||||
/* Verify firmware preamble signature. */
|
/* Verify firmware preamble signature. */
|
||||||
DigestInit(&ctx, image->sign_algorithm);
|
DigestInit(&ctx, image->firmware_sign_algorithm);
|
||||||
DigestUpdate(&ctx, (uint8_t*) &image->firmware_version,
|
DigestUpdate(&ctx, (uint8_t*) &image->firmware_version,
|
||||||
FIELD_LEN(firmware_version));
|
FIELD_LEN(firmware_version));
|
||||||
DigestUpdate(&ctx, (uint8_t*) &image->firmware_len,
|
DigestUpdate(&ctx, (uint8_t*) &image->firmware_len,
|
||||||
@@ -420,8 +508,8 @@ int VerifyFirmwareImage(const RSAPublicKey* root_key,
|
|||||||
DigestUpdate(&ctx, (uint8_t*) &image->preamble,
|
DigestUpdate(&ctx, (uint8_t*) &image->preamble,
|
||||||
FIELD_LEN(preamble));
|
FIELD_LEN(preamble));
|
||||||
preamble_digest = DigestFinal(&ctx);
|
preamble_digest = DigestFinal(&ctx);
|
||||||
if (!RSA_verify(sign_key, image->preamble_signature,
|
if (!RSAVerify(firmware_sign_key, image->preamble_signature,
|
||||||
signature_size, image->sign_algorithm,
|
signature_size, image->firmware_sign_algorithm,
|
||||||
preamble_digest)) {
|
preamble_digest)) {
|
||||||
error_code = VERIFY_FIRMWARE_PREAMBLE_SIGNATURE_FAILED;
|
error_code = VERIFY_FIRMWARE_PREAMBLE_SIGNATURE_FAILED;
|
||||||
goto verify_failure;
|
goto verify_failure;
|
||||||
@@ -430,9 +518,9 @@ int VerifyFirmwareImage(const RSAPublicKey* root_key,
|
|||||||
/* Verify firmware signature. */
|
/* Verify firmware signature. */
|
||||||
firmware_digest = DigestBuf(image->firmware_data,
|
firmware_digest = DigestBuf(image->firmware_data,
|
||||||
image->firmware_len,
|
image->firmware_len,
|
||||||
image->sign_algorithm);
|
image->firmware_sign_algorithm);
|
||||||
if(!RSA_verify(sign_key, image->firmware_signature,
|
if (!RSAVerify(firmware_sign_key, image->firmware_signature,
|
||||||
signature_size, image->sign_algorithm,
|
signature_size, image->firmware_sign_algorithm,
|
||||||
firmware_digest)) {
|
firmware_digest)) {
|
||||||
error_code = VERIFY_FIRMWARE_SIGNATURE_FAILED;
|
error_code = VERIFY_FIRMWARE_SIGNATURE_FAILED;
|
||||||
goto verify_failure;
|
goto verify_failure;
|
||||||
@@ -450,64 +538,49 @@ const char* VerifyFirmwareErrorString(int error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int AddFirmwareKeySignature(FirmwareImage* image, const char* root_key_file) {
|
int AddFirmwareKeySignature(FirmwareImage* image, const char* root_key_file) {
|
||||||
int tmp_hdr_fd;
|
uint8_t* header_blob = NULL;
|
||||||
char* tmp_hdr_file = ".tmpHdrFile";
|
|
||||||
uint8_t* signature;
|
uint8_t* signature;
|
||||||
|
if (!image || !root_key_file)
|
||||||
if(-1 == (tmp_hdr_fd = creat(tmp_hdr_file, S_IRWXU))) {
|
return 0;
|
||||||
fprintf(stderr, "Could not open temporary file for writing "
|
header_blob = GetFirmwareHeaderBlob(image);
|
||||||
"firmware header.\n");
|
if (!header_blob)
|
||||||
|
return 0;
|
||||||
|
if (!(signature = SignatureBuf(header_blob,
|
||||||
|
GetFirmwareHeaderLen(image),
|
||||||
|
root_key_file,
|
||||||
|
ROOT_SIGNATURE_ALGORITHM))) {
|
||||||
|
Free(header_blob);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
WriteFirmwareHeader(tmp_hdr_fd, image);
|
Memcpy(image->firmware_key_signature, signature, RSA8192NUMBYTES);
|
||||||
close(tmp_hdr_fd);
|
Free(header_blob);
|
||||||
|
Free(signature);
|
||||||
if (!(signature = SignatureFile(tmp_hdr_file, root_key_file,
|
|
||||||
ROOT_SIGNATURE_ALGORITHM)))
|
|
||||||
return 0;
|
|
||||||
Memcpy(image->key_signature, signature, RSA8192NUMBYTES);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int AddFirmwareSignature(FirmwareImage* image, const char* signing_key_file,
|
int AddFirmwareSignature(FirmwareImage* image, const char* signing_key_file) {
|
||||||
int algorithm) {
|
uint8_t* preamble_blob;
|
||||||
int tmp_preamble_fd;
|
|
||||||
char* tmp_preamble_file = ".tmpPreambleFile";
|
|
||||||
int tmp_firmware_fd;
|
|
||||||
char* tmp_firmware_file = ".tmpFirmwareFile";
|
|
||||||
uint8_t* preamble_signature;
|
uint8_t* preamble_signature;
|
||||||
uint8_t* firmware_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. */
|
preamble_blob = GetFirmwarePreambleBlob(image);
|
||||||
if(-1 == (tmp_preamble_fd = creat(tmp_preamble_file, S_IRWXU))) {
|
if (!(preamble_signature = SignatureBuf(preamble_blob,
|
||||||
fprintf(stderr, "Could not open temporary file for writing "
|
GetFirmwarePreambleLen(image),
|
||||||
"firmware preamble.\n");
|
signing_key_file,
|
||||||
|
image->firmware_sign_algorithm))) {
|
||||||
|
Free(preamble_blob);
|
||||||
return 0;
|
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);
|
image->preamble_signature = (uint8_t*) Malloc(signature_len);
|
||||||
Memcpy(image->preamble_signature, preamble_signature, signature_len);
|
Memcpy(image->preamble_signature, preamble_signature, signature_len);
|
||||||
Free(preamble_signature);
|
Free(preamble_signature);
|
||||||
|
|
||||||
if (-1 == (tmp_firmware_fd = creat(tmp_firmware_file, S_IRWXU))) {
|
if (!(firmware_signature = SignatureBuf(image->firmware_data,
|
||||||
fprintf(stderr, "Could not open temporary file for writing "
|
image->firmware_len,
|
||||||
"firmware.\n");
|
signing_key_file,
|
||||||
|
image->firmware_sign_algorithm)))
|
||||||
return 0;
|
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);
|
image->firmware_signature = (uint8_t*) Malloc(signature_len);
|
||||||
Memcpy(image->firmware_signature, firmware_signature, signature_len);
|
Memcpy(image->firmware_signature, firmware_signature, signature_len);
|
||||||
Free(firmware_signature);
|
Free(firmware_signature);
|
||||||
|
|||||||
@@ -33,8 +33,8 @@ FirmwareUtility::FirmwareUtility():
|
|||||||
image_(NULL),
|
image_(NULL),
|
||||||
root_key_pub_(NULL),
|
root_key_pub_(NULL),
|
||||||
firmware_version_(-1),
|
firmware_version_(-1),
|
||||||
key_version_(-1),
|
firmware_key_version_(-1),
|
||||||
sign_algorithm_(-1),
|
firmware_sign_algorithm_(-1),
|
||||||
is_generate_(false),
|
is_generate_(false),
|
||||||
is_verify_(false) {
|
is_verify_(false) {
|
||||||
}
|
}
|
||||||
@@ -54,11 +54,11 @@ void FirmwareUtility::PrintUsage(void) {
|
|||||||
"to use for verification.\n\n"
|
"to use for verification.\n\n"
|
||||||
"For \"--generate\", required OPTIONS are:\n"
|
"For \"--generate\", required OPTIONS are:\n"
|
||||||
"--root_key <privkeyfile>\tPrivate root key file\n"
|
"--root_key <privkeyfile>\tPrivate root key file\n"
|
||||||
"--sign_key <privkeyfile>\tPrivate signing key file\n"
|
"--firmware_sign_key <privkeyfile>\tPrivate signing key file\n"
|
||||||
"--sign_key_pub <pubkeyfile>\tPre-processed public signing"
|
"--firmware_sign_key_pub <pubkeyfile>\tPre-processed public signing"
|
||||||
" key\n"
|
" key\n"
|
||||||
"--sign_algorithm <algoid>\tSigning algorithm to use\n"
|
"--firmware_sign_algorithm <algoid>\tSigning algorithm to use\n"
|
||||||
"--key_version <version#>\tSigning Key Version#\n"
|
"--firmware_key_version <version#>\tSigning Key Version#\n"
|
||||||
"--firmware_version <version#>\tFirmware Version#\n"
|
"--firmware_version <version#>\tFirmware Version#\n"
|
||||||
"--in <infile>\t\t\tFirmware Image to sign\n"
|
"--in <infile>\t\t\tFirmware Image to sign\n"
|
||||||
"--out <outfile>\t\t\tOutput file for verified boot firmware image\n\n"
|
"--out <outfile>\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[] = {
|
static struct option long_options[] = {
|
||||||
{"root_key", 1, 0, 0},
|
{"root_key", 1, 0, 0},
|
||||||
{"root_key_pub", 1, 0, 0},
|
{"root_key_pub", 1, 0, 0},
|
||||||
{"sign_key", 1, 0, 0},
|
{"firmware_sign_key", 1, 0, 0},
|
||||||
{"sign_key_pub", 1, 0, 0},
|
{"firmware_sign_key_pub", 1, 0, 0},
|
||||||
{"sign_algorithm", 1, 0, 0},
|
{"firmware_sign_algorithm", 1, 0, 0},
|
||||||
{"key_version", 1, 0, 0},
|
{"firmware_key_version", 1, 0, 0},
|
||||||
{"firmware_version", 1, 0, 0},
|
{"firmware_version", 1, 0, 0},
|
||||||
{"in", 1, 0, 0},
|
{"in", 1, 0, 0},
|
||||||
{"out", 1, 0, 0},
|
{"out", 1, 0, 0},
|
||||||
@@ -100,21 +100,21 @@ bool FirmwareUtility::ParseCmdLineOptions(int argc, char* argv[]) {
|
|||||||
case 1: // root_key_pub
|
case 1: // root_key_pub
|
||||||
root_key_pub_file_ = optarg;
|
root_key_pub_file_ = optarg;
|
||||||
break;
|
break;
|
||||||
case 2: // sign_key
|
case 2: // firmware_sign_key
|
||||||
sign_key_file_ = optarg;
|
firmware_sign_key_file_ = optarg;
|
||||||
break;
|
break;
|
||||||
case 3: // sign_key_pub
|
case 3: // firmware_sign_key_pub
|
||||||
sign_key_pub_file_ = optarg;
|
firmware_sign_key_pub_file_ = optarg;
|
||||||
break;
|
break;
|
||||||
case 4: // sign_algorithm
|
case 4: // firmware_sign_algorithm
|
||||||
errno = 0; // strtol() returns an error via errno
|
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)
|
if (errno)
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
case 5: // key_version
|
case 5: // firmware_key_version
|
||||||
errno = 0;
|
errno = 0;
|
||||||
key_version_ = strtol(optarg, (char**) NULL, 10);
|
firmware_key_version_ = strtol(optarg, (char**) NULL, 10);
|
||||||
if (errno)
|
if (errno)
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
@@ -153,7 +153,7 @@ void FirmwareUtility::OutputSignedImage(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool FirmwareUtility::GenerateSignedImage(void) {
|
bool FirmwareUtility::GenerateSignedImage(void) {
|
||||||
uint32_t sign_key_pub_len;
|
uint32_t firmware_sign_key_pub_len;
|
||||||
uint8_t* header_checksum;
|
uint8_t* header_checksum;
|
||||||
DigestContext ctx;
|
DigestContext ctx;
|
||||||
image_ = FirmwareImageNew();
|
image_ = FirmwareImageNew();
|
||||||
@@ -161,30 +161,31 @@ bool FirmwareUtility::GenerateSignedImage(void) {
|
|||||||
Memcpy(image_->magic, FIRMWARE_MAGIC, FIRMWARE_MAGIC_SIZE);
|
Memcpy(image_->magic, FIRMWARE_MAGIC, FIRMWARE_MAGIC_SIZE);
|
||||||
|
|
||||||
// Copy pre-processed public signing key.
|
// Copy pre-processed public signing key.
|
||||||
image_->sign_algorithm = (uint16_t) sign_algorithm_;
|
image_->firmware_sign_algorithm = (uint16_t) firmware_sign_algorithm_;
|
||||||
image_->sign_key = BufferFromFile(sign_key_pub_file_.c_str(),
|
image_->firmware_sign_key = BufferFromFile(
|
||||||
&sign_key_pub_len);
|
firmware_sign_key_pub_file_.c_str(),
|
||||||
if (!image_->sign_key)
|
&firmware_sign_key_pub_len);
|
||||||
|
if (!image_->firmware_sign_key)
|
||||||
return false;
|
return false;
|
||||||
image_->key_version = key_version_;
|
image_->firmware_key_version = firmware_key_version_;
|
||||||
|
|
||||||
// Update header length.
|
// Update header length.
|
||||||
image_->header_len = (sizeof(image_->header_len) +
|
image_->header_len = (sizeof(image_->header_len) +
|
||||||
sizeof(image_->sign_algorithm) +
|
sizeof(image_->firmware_sign_algorithm) +
|
||||||
sign_key_pub_len +
|
firmware_sign_key_pub_len +
|
||||||
sizeof(image_->key_version) +
|
sizeof(image_->firmware_key_version) +
|
||||||
sizeof(image_->header_checksum));
|
sizeof(image_->header_checksum));
|
||||||
|
|
||||||
// Calculate header checksum.
|
// Calculate header checksum.
|
||||||
DigestInit(&ctx, SHA512_DIGEST_ALGORITHM);
|
DigestInit(&ctx, SHA512_DIGEST_ALGORITHM);
|
||||||
DigestUpdate(&ctx, (uint8_t*) &image_->header_len,
|
DigestUpdate(&ctx, (uint8_t*) &image_->header_len,
|
||||||
sizeof(image_->header_len));
|
sizeof(image_->header_len));
|
||||||
DigestUpdate(&ctx, (uint8_t*) &image_->sign_algorithm,
|
DigestUpdate(&ctx, (uint8_t*) &image_->firmware_sign_algorithm,
|
||||||
sizeof(image_->sign_algorithm));
|
sizeof(image_->firmware_sign_algorithm));
|
||||||
DigestUpdate(&ctx, image_->sign_key,
|
DigestUpdate(&ctx, image_->firmware_sign_key,
|
||||||
RSAProcessedKeySize(image_->sign_algorithm));
|
RSAProcessedKeySize(image_->firmware_sign_algorithm));
|
||||||
DigestUpdate(&ctx, (uint8_t*) &image_->key_version,
|
DigestUpdate(&ctx, (uint8_t*) &image_->firmware_key_version,
|
||||||
sizeof(image_->key_version));
|
sizeof(image_->firmware_key_version));
|
||||||
header_checksum = DigestFinal(&ctx);
|
header_checksum = DigestFinal(&ctx);
|
||||||
Memcpy(image_->header_checksum, header_checksum, SHA512_DIGEST_SIZE);
|
Memcpy(image_->header_checksum, header_checksum, SHA512_DIGEST_SIZE);
|
||||||
Free(header_checksum);
|
Free(header_checksum);
|
||||||
@@ -199,13 +200,12 @@ bool FirmwareUtility::GenerateSignedImage(void) {
|
|||||||
if (!image_)
|
if (!image_)
|
||||||
return false;
|
return false;
|
||||||
// Generate and add the signatures.
|
// 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";
|
cerr << "Couldn't write key signature to verified boot image.\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!AddFirmwareSignature(image_, sign_key_file_.c_str(),
|
if (!AddFirmwareSignature(image_, firmware_sign_key_file_.c_str())) {
|
||||||
image_->sign_algorithm)) {
|
|
||||||
cerr << "Couldn't write firmware signature to verified boot image.\n";
|
cerr << "Couldn't write firmware signature to verified boot image.\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -257,19 +257,20 @@ bool FirmwareUtility::CheckOptions(void) {
|
|||||||
cerr << "Invalid or no firmware version specified." << "\n";
|
cerr << "Invalid or no firmware version specified." << "\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (sign_key_file_.empty()) {
|
if (firmware_sign_key_file_.empty()) {
|
||||||
cerr << "No signing key file specified." << "\n";
|
cerr << "No signing key file specified." << "\n";
|
||||||
return false;
|
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";
|
cerr << "No pre-processed public signing key file specified." << "\n";
|
||||||
return false;
|
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";
|
cerr << "Invalid or no key version specified." << "\n";
|
||||||
return false;
|
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";
|
cerr << "Invalid or no signing key algorithm specified." << "\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include "padding.h"
|
#include "padding.h"
|
||||||
#include "rsa_utility.h"
|
#include "rsa_utility.h"
|
||||||
#include "sha_utility.h"
|
#include "sha_utility.h"
|
||||||
|
#include "signature_digest.h"
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
|
|
||||||
/* Macro to determine the size of a field structure in the KernelImage
|
/* 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;
|
st.remaining_buf = kernel_buf;
|
||||||
|
|
||||||
/* Read and compare magic bytes. */
|
/* Read and compare magic bytes. */
|
||||||
if (!StatefulMemcpy(&st, &image->magic, KERNEL_MAGIC_SIZE))
|
StatefulMemcpy(&st, &image->magic, KERNEL_MAGIC_SIZE);
|
||||||
goto parse_failure;
|
|
||||||
|
|
||||||
if (SafeMemcmp(image->magic, KERNEL_MAGIC, KERNEL_MAGIC_SIZE)) {
|
if (SafeMemcmp(image->magic, KERNEL_MAGIC, KERNEL_MAGIC_SIZE)) {
|
||||||
fprintf(stderr, "Wrong Kernel Magic.\n");
|
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_version, FIELD_LEN(header_version));
|
||||||
StatefulMemcpy(&st, &image->header_len, FIELD_LEN(header_len));
|
StatefulMemcpy(&st, &image->header_len, FIELD_LEN(header_len));
|
||||||
@@ -83,12 +84,16 @@ KernelImage* ReadKernelImage(const char* input_file) {
|
|||||||
FIELD_LEN(kernel_sign_algorithm));
|
FIELD_LEN(kernel_sign_algorithm));
|
||||||
|
|
||||||
/* Valid Kernel Key signing algorithm. */
|
/* Valid Kernel Key signing algorithm. */
|
||||||
if (image->firmware_sign_algorithm >= kNumAlgorithms)
|
if (image->firmware_sign_algorithm >= kNumAlgorithms) {
|
||||||
goto parse_failure;
|
Free(kernel_buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Valid Kernel Signing Algorithm? */
|
/* Valid Kernel Signing Algorithm? */
|
||||||
if (image->kernel_sign_algorithm >= kNumAlgorithms)
|
if (image->kernel_sign_algorithm >= kNumAlgorithms) {
|
||||||
goto parse_failure;
|
Free(kernel_buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Compute size of pre-processed RSA public keys and signatures. */
|
/* Compute size of pre-processed RSA public keys and signatures. */
|
||||||
firmware_sign_key_len = RSAProcessedKeySize(image->firmware_sign_algorithm);
|
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) {
|
if (header_len != image->header_len) {
|
||||||
fprintf(stderr, "Header length mismatch. Got: %d, Expected: %d\n",
|
fprintf(stderr, "Header length mismatch. Got: %d, Expected: %d\n",
|
||||||
image->header_len, header_len);
|
image->header_len, header_len);
|
||||||
goto parse_failure;
|
Free(kernel_buf);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read pre-processed public half of the kernel signing key. */
|
/* 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);
|
image->kernel_data = (uint8_t*) Malloc(image->options.kernel_len);
|
||||||
StatefulMemcpy(&st, image->kernel_data, image->options.kernel_len);
|
StatefulMemcpy(&st, image->kernel_data, image->options.kernel_len);
|
||||||
|
|
||||||
if(st.remaining_len != 0) /* Overrun or underrun. */
|
if(st.remaining_len != 0) { /* Overrun or underrun. */
|
||||||
goto parse_failure;
|
Free(kernel_buf);
|
||||||
|
|
||||||
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;
|
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_key_signature_len = siglen_map[image->firmware_sign_algorithm];
|
||||||
kernel_signature_len = siglen_map[image->kernel_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));
|
header_blob = GetKernelHeaderBlob(image);
|
||||||
WriteKernelHeader(fd, image);
|
config_blob = GetKernelConfigBlob(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);
|
|
||||||
|
|
||||||
|
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);
|
close(fd);
|
||||||
return image;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintKernelImage(const KernelImage* image) {
|
void PrintKernelImage(const KernelImage* image) {
|
||||||
@@ -478,7 +561,7 @@ int VerifyKernelImage(const RSAPublicKey* firmware_key,
|
|||||||
DigestUpdate(&ctx, image->header_checksum,
|
DigestUpdate(&ctx, image->header_checksum,
|
||||||
FIELD_LEN(header_checksum));
|
FIELD_LEN(header_checksum));
|
||||||
header_digest = DigestFinal(&ctx);
|
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],
|
siglen_map[image->firmware_sign_algorithm],
|
||||||
image->firmware_sign_algorithm,
|
image->firmware_sign_algorithm,
|
||||||
header_digest)) {
|
header_digest)) {
|
||||||
@@ -507,9 +590,9 @@ int VerifyKernelImage(const RSAPublicKey* firmware_key,
|
|||||||
DigestUpdate(&ctx, (uint8_t*) &image->options.kernel_entry_addr,
|
DigestUpdate(&ctx, (uint8_t*) &image->options.kernel_entry_addr,
|
||||||
FIELD_LEN(options.kernel_entry_addr));
|
FIELD_LEN(options.kernel_entry_addr));
|
||||||
config_digest = DigestFinal(&ctx);
|
config_digest = DigestFinal(&ctx);
|
||||||
if (!RSA_verify(kernel_sign_key, image->config_signature,
|
if (!RSAVerify(kernel_sign_key, image->config_signature,
|
||||||
kernel_signature_size, image->kernel_sign_algorithm,
|
kernel_signature_size, image->kernel_sign_algorithm,
|
||||||
config_digest)) {
|
config_digest)) {
|
||||||
error_code = VERIFY_KERNEL_CONFIG_SIGNATURE_FAILED;
|
error_code = VERIFY_KERNEL_CONFIG_SIGNATURE_FAILED;
|
||||||
goto verify_failure;
|
goto verify_failure;
|
||||||
}
|
}
|
||||||
@@ -518,7 +601,7 @@ int VerifyKernelImage(const RSAPublicKey* firmware_key,
|
|||||||
kernel_digest = DigestBuf(image->kernel_data,
|
kernel_digest = DigestBuf(image->kernel_data,
|
||||||
image->options.kernel_len,
|
image->options.kernel_len,
|
||||||
image->kernel_sign_algorithm);
|
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_signature_size, image->kernel_sign_algorithm,
|
||||||
kernel_digest)) {
|
kernel_digest)) {
|
||||||
error_code = VERIFY_KERNEL_SIGNATURE_FAILED;
|
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 AddKernelKeySignature(KernelImage* image, const char* firmware_key_file) {
|
||||||
int tmp_hdr_fd;
|
uint8_t* header_blob = NULL;
|
||||||
char* tmp_hdr_file = ".tmpKernelHdrFile";
|
|
||||||
uint8_t* signature;
|
uint8_t* signature;
|
||||||
int signature_len = siglen_map[image->firmware_sign_algorithm];
|
int signature_len = siglen_map[image->firmware_sign_algorithm];
|
||||||
|
if (!image || !firmware_key_file)
|
||||||
if(-1 == (tmp_hdr_fd = creat(tmp_hdr_file, S_IRWXU))) {
|
return 0;
|
||||||
fprintf(stderr, "Could not open temporary file for writing "
|
header_blob = GetKernelHeaderBlob(image);
|
||||||
"kernel header.\n");
|
if (!header_blob)
|
||||||
|
return 0;
|
||||||
|
if (!(signature = SignatureBuf(header_blob,
|
||||||
|
GetKernelHeaderLen(image),
|
||||||
|
firmware_key_file,
|
||||||
|
image->firmware_sign_algorithm))) {
|
||||||
|
Free(header_blob);
|
||||||
return 0;
|
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);
|
image->kernel_key_signature = Malloc(signature_len);
|
||||||
Memcpy(image->kernel_key_signature, signature, signature_len);
|
Memcpy(image->kernel_key_signature, signature, signature_len);
|
||||||
|
Free(signature);
|
||||||
|
Free(header_blob);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int AddKernelSignature(KernelImage* image, const char* kernel_signing_key_file,
|
int AddKernelSignature(KernelImage* image,
|
||||||
int algorithm) {
|
const char* kernel_signing_key_file) {
|
||||||
int tmp_config_fd;
|
uint8_t* config_blob;
|
||||||
char* tmp_config_file = ".tmpConfigFile";
|
|
||||||
int tmp_kernel_fd;
|
|
||||||
char* tmp_kernel_file = ".tmpKernelFile";
|
|
||||||
uint8_t* config_signature;
|
uint8_t* config_signature;
|
||||||
uint8_t* kernel_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. */
|
config_blob = GetKernelConfigBlob(image);
|
||||||
if(-1 == (tmp_config_fd = creat(tmp_config_file, S_IRWXU))) {
|
if (!(config_signature = SignatureBuf(config_blob,
|
||||||
fprintf(stderr, "Could not open temporary file for writing "
|
GetKernelConfigLen(image),
|
||||||
"kernel config.\n");
|
kernel_signing_key_file,
|
||||||
|
image->kernel_sign_algorithm))) {
|
||||||
|
fprintf(stderr, "Could not compute signature on the kernel config.\n");
|
||||||
|
Free(config_blob);
|
||||||
return 0;
|
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);
|
image->config_signature = (uint8_t*) Malloc(signature_len);
|
||||||
Memcpy(image->config_signature, config_signature, signature_len);
|
Memcpy(image->config_signature, config_signature, signature_len);
|
||||||
Free(config_signature);
|
Free(config_signature);
|
||||||
|
|
||||||
if (-1 == (tmp_kernel_fd = creat(tmp_kernel_file, S_IRWXU))) {
|
if (!(kernel_signature = SignatureBuf(image->kernel_data,
|
||||||
fprintf(stderr, "Could not open temporary file for writing "
|
image->options.kernel_len,
|
||||||
"kernel.\n");
|
kernel_signing_key_file,
|
||||||
return 0;
|
image->kernel_sign_algorithm))) {
|
||||||
}
|
|
||||||
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");
|
fprintf(stderr, "Could not compute signature on the kernel.\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,13 @@
|
|||||||
/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
|
/* 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
|
* Use of this source code is governed by a BSD-style license that can be
|
||||||
* found in the LICENSE file.
|
* 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"
|
#include "signature_digest.h"
|
||||||
|
#define OPENSSL_NO_SHA
|
||||||
|
#include <openssl/engine.h>
|
||||||
|
#include <openssl/pem.h>
|
||||||
|
#include <openssl/rsa.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -20,49 +16,59 @@
|
|||||||
#include "padding.h"
|
#include "padding.h"
|
||||||
#include "sha.h"
|
#include "sha.h"
|
||||||
#include "sha_utility.h"
|
#include "sha_utility.h"
|
||||||
|
#include "utility.h"
|
||||||
|
|
||||||
uint8_t* PrependDigestInfo(int algorithm, uint8_t* digest) {
|
uint8_t* PrependDigestInfo(int algorithm, uint8_t* digest) {
|
||||||
const int digest_size = hash_size_map[algorithm];
|
const int digest_size = hash_size_map[algorithm];
|
||||||
const int digestinfo_size = digestinfo_size_map[algorithm];
|
const int digestinfo_size = digestinfo_size_map[algorithm];
|
||||||
const uint8_t* digestinfo = hash_digestinfo_map[algorithm];
|
const uint8_t* digestinfo = hash_digestinfo_map[algorithm];
|
||||||
uint8_t* p = malloc(digestinfo_size + digest_size);
|
uint8_t* p = Malloc(digestinfo_size + digest_size);
|
||||||
memcpy(p, digestinfo, digestinfo_size);
|
Memcpy(p, digestinfo, digestinfo_size);
|
||||||
memcpy(p + digestinfo_size, digest, digest_size);
|
Memcpy(p + digestinfo_size, digest, digest_size);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
uint8_t* SignatureDigest(const uint8_t* buf, int len, int algorithm) {
|
||||||
int i, algorithm;
|
|
||||||
uint8_t* digest = NULL;
|
|
||||||
uint8_t* signature = NULL;
|
|
||||||
uint8_t* info_digest = NULL;
|
uint8_t* info_digest = NULL;
|
||||||
|
uint8_t* digest = NULL;
|
||||||
|
|
||||||
if (argc != 3) {
|
|
||||||
fprintf(stderr, "Usage: %s <algorithm> <input file>\n\n",
|
|
||||||
argv[0]);
|
|
||||||
fprintf(stderr, "where <algorithm> is the signature algorithm to use:\n");
|
|
||||||
for(i = 0; i<kNumAlgorithms; i++)
|
|
||||||
fprintf(stderr, "\t%d for %s\n", i, algo_strings[i]);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
algorithm = atoi(argv[1]);
|
|
||||||
if (algorithm >= kNumAlgorithms) {
|
if (algorithm >= kNumAlgorithms) {
|
||||||
fprintf(stderr, "Invalid Algorithm!\n");
|
fprintf(stderr, "SignatureDigest() called with invalid algorithm!\n");
|
||||||
goto failure;
|
} else if ((digest = DigestBuf(buf, len, algorithm))) {
|
||||||
|
info_digest = PrependDigestInfo(algorithm, digest);
|
||||||
}
|
}
|
||||||
|
Free(digest);
|
||||||
if (!(digest = DigestFile(argv[2], algorithm)))
|
return info_digest;
|
||||||
goto failure;
|
}
|
||||||
|
|
||||||
info_digest = PrependDigestInfo(algorithm, digest);
|
uint8_t* SignatureBuf(const uint8_t* buf, int len, const char* key_file,
|
||||||
write(1, info_digest, hash_size_map[algorithm] +
|
int algorithm) {
|
||||||
digestinfo_size_map[algorithm]);
|
FILE* key_fp = NULL;
|
||||||
|
RSA* key = NULL;
|
||||||
failure:
|
uint8_t* signature = NULL;
|
||||||
free(digest);
|
uint8_t* signature_digest = SignatureDigest(buf, len, algorithm);
|
||||||
free(info_digest);
|
int signature_digest_len = (hash_size_map[algorithm] +
|
||||||
free(signature);
|
digestinfo_size_map[algorithm]);
|
||||||
|
key_fp = fopen(key_file, "r");
|
||||||
return 0;
|
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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,22 +75,21 @@ int main(int argc, char* argv[]) {
|
|||||||
}
|
}
|
||||||
/* Length of the RSA Signature/RSA Key */
|
/* Length of the RSA Signature/RSA Key */
|
||||||
sig_len = siglen_map[algorithm];
|
sig_len = siglen_map[algorithm];
|
||||||
if (!(key = RSAPublicKeyFromFile(argv[2])))
|
if ((key = RSAPublicKeyFromFile(argv[2])) &&
|
||||||
goto failure;
|
(signature = read_signature(argv[3], sig_len)) &&
|
||||||
if (!(signature = read_signature(argv[3], sig_len)))
|
(digest = DigestFile(argv[4], algorithm))) {
|
||||||
goto failure;
|
if (RSAVerify(key, signature, sig_len, algorithm, digest)) {
|
||||||
if (!(digest = DigestFile(argv[4], algorithm)))
|
return_code = 0;
|
||||||
goto failure;
|
fprintf(stderr, "Signature Verification "
|
||||||
if(RSA_verify(key, signature, sig_len, algorithm, digest)) {
|
COL_GREEN "SUCCEEDED" COL_STOP "\n");
|
||||||
return_code = 0;
|
} else {
|
||||||
fprintf(stderr, "Signature Verification "
|
fprintf(stderr, "Signature Verification "
|
||||||
COL_GREEN "SUCCEEDED" COL_STOP "\n");
|
COL_RED "FAILED" COL_STOP "\n");
|
||||||
} else {
|
}
|
||||||
fprintf(stderr, "Signature Verification "
|
|
||||||
COL_RED "FAILED" COL_STOP "\n");
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
return_code = -1;
|
||||||
|
|
||||||
failure:
|
|
||||||
free(key);
|
free(key);
|
||||||
free(signature);
|
free(signature);
|
||||||
free(digest);
|
free(digest);
|
||||||
|
|||||||
Reference in New Issue
Block a user