Index: src/platform/vboot_reference/utils/kernel_image.c |
diff --git a/src/platform/vboot_reference/utils/kernel_image.c b/src/platform/vboot_reference/utils/kernel_image.c |
index b5f07c2fae9226f5008b85e7877fbcb342d848db..06b340b4c709737205919c205fa552bc14d79bbf 100644 |
--- a/src/platform/vboot_reference/utils/kernel_image.c |
+++ b/src/platform/vboot_reference/utils/kernel_image.c |
@@ -17,6 +17,7 @@ |
#include "padding.h" |
#include "rsa_utility.h" |
#include "sha_utility.h" |
+#include "signature_digest.h" |
#include "utility.h" |
/* Macro to determine the size of a field structure in the KernelImage |
@@ -68,12 +69,12 @@ KernelImage* ReadKernelImage(const char* input_file) { |
st.remaining_buf = kernel_buf; |
/* Read and compare magic bytes. */ |
- if (!StatefulMemcpy(&st, &image->magic, KERNEL_MAGIC_SIZE)) |
- goto parse_failure; |
+ StatefulMemcpy(&st, &image->magic, KERNEL_MAGIC_SIZE); |
if (SafeMemcmp(image->magic, KERNEL_MAGIC, KERNEL_MAGIC_SIZE)) { |
fprintf(stderr, "Wrong Kernel Magic.\n"); |
- goto parse_failure; |
+ Free(kernel_buf); |
+ return NULL; |
} |
StatefulMemcpy(&st, &image->header_version, FIELD_LEN(header_version)); |
StatefulMemcpy(&st, &image->header_len, FIELD_LEN(header_len)); |
@@ -83,12 +84,16 @@ KernelImage* ReadKernelImage(const char* input_file) { |
FIELD_LEN(kernel_sign_algorithm)); |
/* Valid Kernel Key signing algorithm. */ |
- if (image->firmware_sign_algorithm >= kNumAlgorithms) |
- goto parse_failure; |
+ if (image->firmware_sign_algorithm >= kNumAlgorithms) { |
+ Free(kernel_buf); |
+ return NULL; |
+ } |
/* Valid Kernel Signing Algorithm? */ |
- if (image->kernel_sign_algorithm >= kNumAlgorithms) |
- goto parse_failure; |
+ if (image->kernel_sign_algorithm >= kNumAlgorithms) { |
+ Free(kernel_buf); |
+ return NULL; |
+ } |
/* Compute size of pre-processed RSA public keys and signatures. */ |
firmware_sign_key_len = RSAProcessedKeySize(image->firmware_sign_algorithm); |
@@ -108,7 +113,8 @@ KernelImage* ReadKernelImage(const char* input_file) { |
if (header_len != image->header_len) { |
fprintf(stderr, "Header length mismatch. Got: %d, Expected: %d\n", |
image->header_len, header_len); |
- goto parse_failure; |
+ Free(kernel_buf); |
+ return NULL; |
} |
/* Read pre-processed public half of the kernel signing key. */ |
@@ -142,73 +148,150 @@ KernelImage* ReadKernelImage(const char* input_file) { |
image->kernel_data = (uint8_t*) Malloc(image->options.kernel_len); |
StatefulMemcpy(&st, image->kernel_data, image->options.kernel_len); |
- if(st.remaining_len != 0) /* Overrun or underrun. */ |
- goto parse_failure; |
- |
+ if(st.remaining_len != 0) { /* Overrun or underrun. */ |
+ Free(kernel_buf); |
+ return NULL; |
+ } |
Free(kernel_buf); |
return image; |
+} |
-parse_failure: |
- Free(kernel_buf); |
- return NULL; |
+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)); |
} |
-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)); |
+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; |
} |
-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, |
+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)); |
- write(fd, &image->options.kernel_entry_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; |
} |
-KernelImage* WriteKernelImage(const char* input_file, |
- KernelImage* image) { |
- int fd; |
+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; |
- if (-1 == (fd = creat(input_file, |
- S_IRUSR | S_IWUSR))) { /* Owner has R/W permissions. */ |
- fprintf(stderr, "Couldn't open file for writing.\n"); |
+ kernel_key_signature_len = siglen_map[image->firmware_sign_algorithm]; |
+ kernel_signature_len = siglen_map[image->kernel_sign_algorithm]; |
+ *blob_len = (FIELD_LEN(magic) + |
+ GetKernelHeaderLen(image) + |
+ kernel_key_signature_len + |
+ GetKernelConfigLen(image) + |
+ 2 * kernel_signature_len + |
+ image->options.kernel_len); |
+ kernel_blob = (uint8_t*) Malloc(*blob_len); |
+ st.remaining_len = *blob_len; |
+ st.remaining_buf = kernel_blob; |
+ |
+ header_blob = GetKernelHeaderBlob(image); |
+ config_blob = GetKernelConfigBlob(image); |
+ |
+ StatefulMemcpy_r(&st, image->magic, FIELD_LEN(magic)); |
+ StatefulMemcpy_r(&st, header_blob, GetKernelHeaderLen(image)); |
+ StatefulMemcpy_r(&st, image->kernel_key_signature, kernel_key_signature_len); |
+ StatefulMemcpy_r(&st, config_blob, GetKernelConfigLen(image)); |
+ StatefulMemcpy_r(&st, image->config_signature, kernel_signature_len); |
+ StatefulMemcpy_r(&st, image->kernel_signature, kernel_signature_len); |
+ StatefulMemcpy_r(&st, image->kernel_data, image->options.kernel_len); |
+ |
+ Free(config_blob); |
+ Free(header_blob); |
+ |
+ if (st.remaining_len != 0) { /* Underrun or Overrun. */ |
+ Free(kernel_blob); |
return NULL; |
} |
+ return kernel_blob; |
+} |
- kernel_key_signature_len = siglen_map[image->firmware_sign_algorithm]; |
- kernel_signature_len = siglen_map[image->kernel_sign_algorithm]; |
+int WriteKernelImage(const char* input_file, |
+ const KernelImage* image) { |
+ int fd; |
+ uint8_t* kernel_blob; |
+ int blob_len; |
- write(fd, image->magic, FIELD_LEN(magic)); |
- WriteKernelHeader(fd, image); |
- write(fd, image->kernel_key_signature, kernel_key_signature_len); |
- WriteKernelConfig(fd, image); |
- write(fd, image->config_signature, kernel_signature_len); |
- write(fd, image->kernel_signature, kernel_signature_len); |
- write(fd, image->kernel_data, image->options.kernel_len); |
+ if (!image) |
+ return 0; |
+ if (-1 == (fd = creat(input_file, S_IRWXU))) { |
+ fprintf(stderr, "Couldn't open file for writing kernel image: %s\n", |
+ input_file); |
+ return 0; |
+ } |
+ kernel_blob = GetKernelBlob(image, &blob_len); |
+ if (!kernel_blob) { |
+ fprintf(stderr, "Couldn't create kernel blob from KernelImage.\n"); |
+ return 0; |
+ } |
+ if (blob_len != write(fd, kernel_blob, blob_len)) { |
+ fprintf(stderr, "Couldn't write Kernel Image to file: %s\n", |
+ input_file); |
+ Free(kernel_blob); |
+ close(fd); |
+ return 0; |
+ } |
+ Free(kernel_blob); |
close(fd); |
- return image; |
+ return 1; |
} |
void PrintKernelImage(const KernelImage* image) { |
@@ -478,7 +561,7 @@ int VerifyKernelImage(const RSAPublicKey* firmware_key, |
DigestUpdate(&ctx, image->header_checksum, |
FIELD_LEN(header_checksum)); |
header_digest = DigestFinal(&ctx); |
- if (!RSA_verify(firmware_key, image->kernel_key_signature, |
+ if (!RSAVerify(firmware_key, image->kernel_key_signature, |
siglen_map[image->firmware_sign_algorithm], |
image->firmware_sign_algorithm, |
header_digest)) { |
@@ -507,9 +590,9 @@ int VerifyKernelImage(const RSAPublicKey* firmware_key, |
DigestUpdate(&ctx, (uint8_t*) &image->options.kernel_entry_addr, |
FIELD_LEN(options.kernel_entry_addr)); |
config_digest = DigestFinal(&ctx); |
- if (!RSA_verify(kernel_sign_key, image->config_signature, |
- kernel_signature_size, image->kernel_sign_algorithm, |
- config_digest)) { |
+ if (!RSAVerify(kernel_sign_key, image->config_signature, |
+ kernel_signature_size, image->kernel_sign_algorithm, |
+ config_digest)) { |
error_code = VERIFY_KERNEL_CONFIG_SIGNATURE_FAILED; |
goto verify_failure; |
} |
@@ -518,7 +601,7 @@ int VerifyKernelImage(const RSAPublicKey* firmware_key, |
kernel_digest = DigestBuf(image->kernel_data, |
image->options.kernel_len, |
image->kernel_sign_algorithm); |
- if(!RSA_verify(kernel_sign_key, image->kernel_signature, |
+ if (!RSAVerify(kernel_sign_key, image->kernel_signature, |
kernel_signature_size, image->kernel_sign_algorithm, |
kernel_digest)) { |
error_code = VERIFY_KERNEL_SIGNATURE_FAILED; |
@@ -537,63 +620,53 @@ const char* VerifyKernelErrorString(int error) { |
} |
int AddKernelKeySignature(KernelImage* image, const char* firmware_key_file) { |
- int tmp_hdr_fd; |
- char* tmp_hdr_file = ".tmpKernelHdrFile"; |
+ uint8_t* header_blob = NULL; |
uint8_t* signature; |
int signature_len = siglen_map[image->firmware_sign_algorithm]; |
- |
- if(-1 == (tmp_hdr_fd = creat(tmp_hdr_file, S_IRWXU))) { |
- fprintf(stderr, "Could not open temporary file for writing " |
- "kernel header.\n"); |
+ if (!image || !firmware_key_file) |
return 0; |
- } |
- WriteKernelHeader(tmp_hdr_fd, image); |
- close(tmp_hdr_fd); |
- if (!(signature = SignatureFile(tmp_hdr_file, firmware_key_file, |
- image->firmware_sign_algorithm))) |
+ header_blob = GetKernelHeaderBlob(image); |
+ if (!header_blob) |
+ return 0; |
+ if (!(signature = SignatureBuf(header_blob, |
+ GetKernelHeaderLen(image), |
+ firmware_key_file, |
+ image->firmware_sign_algorithm))) { |
+ Free(header_blob); |
return 0; |
+ } |
image->kernel_key_signature = Malloc(signature_len); |
Memcpy(image->kernel_key_signature, signature, signature_len); |
+ Free(signature); |
+ Free(header_blob); |
return 1; |
} |
-int AddKernelSignature(KernelImage* image, const char* kernel_signing_key_file, |
- int algorithm) { |
- int tmp_config_fd; |
- char* tmp_config_file = ".tmpConfigFile"; |
- int tmp_kernel_fd; |
- char* tmp_kernel_file = ".tmpKernelFile"; |
+int AddKernelSignature(KernelImage* image, |
+ const char* kernel_signing_key_file) { |
+ uint8_t* config_blob; |
uint8_t* config_signature; |
uint8_t* kernel_signature; |
- int signature_len = siglen_map[algorithm]; |
- |
- /* Write config to a file. */ |
- if(-1 == (tmp_config_fd = creat(tmp_config_file, S_IRWXU))) { |
- fprintf(stderr, "Could not open temporary file for writing " |
- "kernel config.\n"); |
+ int signature_len = siglen_map[image->kernel_sign_algorithm]; |
+ |
+ config_blob = GetKernelConfigBlob(image); |
+ if (!(config_signature = SignatureBuf(config_blob, |
+ GetKernelConfigLen(image), |
+ kernel_signing_key_file, |
+ image->kernel_sign_algorithm))) { |
+ fprintf(stderr, "Could not compute signature on the kernel config.\n"); |
+ Free(config_blob); |
return 0; |
} |
- WriteKernelConfig(tmp_config_fd, image); |
- close(tmp_config_fd); |
- if (!(config_signature = SignatureFile(tmp_config_file, |
- kernel_signing_key_file, |
- algorithm))) |
- return 0; |
+ |
image->config_signature = (uint8_t*) Malloc(signature_len); |
Memcpy(image->config_signature, config_signature, signature_len); |
Free(config_signature); |
- if (-1 == (tmp_kernel_fd = creat(tmp_kernel_file, S_IRWXU))) { |
- fprintf(stderr, "Could not open temporary file for writing " |
- "kernel.\n"); |
- return 0; |
- } |
- write(tmp_kernel_fd, image->kernel_data, image->options.kernel_len); |
- close(tmp_kernel_fd); |
- |
- if (!(kernel_signature = SignatureFile(tmp_kernel_file, |
- kernel_signing_key_file, |
- algorithm))) { |
+ if (!(kernel_signature = SignatureBuf(image->kernel_data, |
+ image->options.kernel_len, |
+ kernel_signing_key_file, |
+ image->kernel_sign_algorithm))) { |
fprintf(stderr, "Could not compute signature on the kernel.\n"); |
return 0; |
} |