| 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 e63529162ecc630ac3a9a13b9903900f61014eb4..f92a9f84e334a3fba8461bca5af8727a4474d3a8 100644
|
| --- a/src/platform/vboot_reference/utils/kernel_image.c
|
| +++ b/src/platform/vboot_reference/utils/kernel_image.c
|
| @@ -220,7 +220,7 @@ uint8_t* GetKernelHeaderBlob(const KernelImage* image) {
|
| return header_blob;
|
| }
|
|
|
| -int GetKernelConfigLen(const KernelImage* image) {
|
| +int GetKernelConfigLen() {
|
| return (FIELD_LEN(kernel_version) +
|
| FIELD_LEN(options.version) + FIELD_LEN(options.cmd_line) +
|
| FIELD_LEN(options.kernel_len) + FIELD_LEN(options.kernel_load_addr) +
|
| @@ -231,8 +231,8 @@ 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);
|
| + config_blob = (uint8_t*) Malloc(GetKernelConfigLen());
|
| + st.remaining_len = GetKernelConfigLen();
|
| st.remaining_buf = config_blob;
|
|
|
| StatefulMemcpy_r(&st, &image->kernel_version, FIELD_LEN(kernel_version));
|
| @@ -266,7 +266,7 @@ uint8_t* GetKernelBlob(const KernelImage* image, uint64_t* blob_len) {
|
| *blob_len = (FIELD_LEN(magic) +
|
| GetKernelHeaderLen(image) +
|
| kernel_key_signature_len +
|
| - GetKernelConfigLen(image) +
|
| + GetKernelConfigLen() +
|
| 2 * kernel_signature_len +
|
| image->options.kernel_len);
|
| kernel_blob = (uint8_t*) Malloc(*blob_len);
|
| @@ -279,7 +279,7 @@ uint8_t* GetKernelBlob(const KernelImage* image, uint64_t* blob_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, config_blob, GetKernelConfigLen());
|
| 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);
|
| @@ -453,7 +453,7 @@ int VerifyKernelConfig(RSAPublicKey* kernel_sign_key,
|
| int algorithm,
|
| int* kernel_len) {
|
| uint32_t len, config_len;
|
| - config_len = GetKernelConfigLen(NULL);
|
| + config_len = GetKernelConfigLen();
|
| if (!RSAVerifyBinary_f(NULL, kernel_sign_key, /* Key to use */
|
| config_blob, /* Data to verify */
|
| config_len, /* Length of data */
|
| @@ -470,17 +470,30 @@ int VerifyKernelConfig(RSAPublicKey* kernel_sign_key,
|
| }
|
|
|
| int VerifyKernelData(RSAPublicKey* kernel_sign_key,
|
| + const uint8_t* kernel_config_start,
|
| const uint8_t* kernel_data_start,
|
| int kernel_len,
|
| int algorithm) {
|
| int signature_len = siglen_map[algorithm];
|
| - if (!RSAVerifyBinary_f(NULL, kernel_sign_key, /* Key to use. */
|
| - kernel_data_start + signature_len, /* Data to
|
| - * verify */
|
| - kernel_len, /* Length of data. */
|
| - kernel_data_start, /* Expected Signature */
|
| - algorithm))
|
| + uint8_t* digest;
|
| + DigestContext ctx;
|
| +
|
| + /* Since the kernel signature is computed over the kernel version, options
|
| + * and data, which does not form a contiguous region of memory, we calculate
|
| + * the message digest ourselves. */
|
| + DigestInit(&ctx, algorithm);
|
| + DigestUpdate(&ctx, kernel_config_start, GetKernelConfigLen());
|
| + DigestUpdate(&ctx, kernel_data_start + signature_len, kernel_len);
|
| + digest = DigestFinal(&ctx);
|
| + if (!RSAVerifyBinaryWithDigest_f(
|
| + NULL, kernel_sign_key, /* Key to use. */
|
| + digest, /* Digest of the data to verify. */
|
| + kernel_data_start, /* Expected Signature */
|
| + algorithm)) {
|
| + Free(digest);
|
| return VERIFY_KERNEL_SIGNATURE_FAILED;
|
| + }
|
| + Free(digest);
|
| return 0;
|
| }
|
|
|
| @@ -536,10 +549,11 @@ int VerifyKernel(const uint8_t* firmware_key_blob,
|
| }
|
| /* Only continue if kernel data verification succeeds. */
|
| kernel_ptr = (config_ptr +
|
| - GetKernelConfigLen(NULL) + /* Skip config block/signature. */
|
| + GetKernelConfigLen() + /* Skip config block/signature. */
|
| kernel_signature_len);
|
|
|
| - if ((error_code = VerifyKernelData(kernel_sign_key, kernel_ptr, kernel_len,
|
| + if ((error_code = VerifyKernelData(kernel_sign_key, config_ptr, kernel_ptr,
|
| + kernel_len,
|
| kernel_sign_algorithm))) {
|
| RSAPublicKeyFree(kernel_sign_key);
|
| return error_code; /* AKA jump to recovery. */
|
| @@ -559,7 +573,7 @@ int VerifyKernelImage(const RSAPublicKey* firmware_key,
|
| int kernel_signature_size;
|
| int error_code = 0;
|
| DigestContext ctx;
|
| -
|
| + DigestContext kernel_ctx;
|
| if (!image)
|
| return VERIFY_KERNEL_INVALID_IMAGE;
|
|
|
| @@ -631,10 +645,23 @@ int VerifyKernelImage(const RSAPublicKey* firmware_key,
|
| goto verify_failure;
|
| }
|
|
|
| - /* Verify firmware signature. */
|
| - kernel_digest = DigestBuf(image->kernel_data,
|
| - image->options.kernel_len,
|
| - image->kernel_sign_algorithm);
|
| + /* Verify kernel signature - kernel signature is computed on the contents
|
| + of kernel version + kernel options + kernel_data. */
|
| + DigestInit(&kernel_ctx, image->kernel_sign_algorithm);
|
| + DigestUpdate(&kernel_ctx, (uint8_t*) &image->kernel_version,
|
| + FIELD_LEN(kernel_version));
|
| + DigestUpdate(&kernel_ctx, (uint8_t*) image->options.version,
|
| + FIELD_LEN(options.version));
|
| + DigestUpdate(&kernel_ctx, (uint8_t*) image->options.cmd_line,
|
| + FIELD_LEN(options.cmd_line));
|
| + DigestUpdate(&kernel_ctx, (uint8_t*) &image->options.kernel_len,
|
| + FIELD_LEN(options.kernel_len));
|
| + DigestUpdate(&kernel_ctx, (uint8_t*) &image->options.kernel_load_addr,
|
| + FIELD_LEN(options.kernel_load_addr));
|
| + DigestUpdate(&kernel_ctx, (uint8_t*) &image->options.kernel_entry_addr,
|
| + FIELD_LEN(options.kernel_entry_addr));
|
| + DigestUpdate(&kernel_ctx, image->kernel_data, image->options.kernel_len);
|
| + kernel_digest = DigestFinal(&kernel_ctx);
|
| if (!RSAVerify(kernel_sign_key, image->kernel_signature,
|
| kernel_signature_size, image->kernel_sign_algorithm,
|
| kernel_digest)) {
|
| @@ -682,33 +709,44 @@ int AddKernelSignature(KernelImage* image,
|
| uint8_t* config_blob = NULL;
|
| uint8_t* config_signature = NULL;
|
| uint8_t* kernel_signature = NULL;
|
| + uint8_t* kernel_buf;
|
| int signature_len = siglen_map[image->kernel_sign_algorithm];
|
|
|
| config_blob = GetKernelConfigBlob(image);
|
| if (!(config_signature = SignatureBuf(config_blob,
|
| - GetKernelConfigLen(image),
|
| + GetKernelConfigLen(),
|
| kernel_signing_key_file,
|
| image->kernel_sign_algorithm))) {
|
| fprintf(stderr, "Could not compute signature on the kernel config.\n");
|
| Free(config_blob);
|
| return 0;
|
| }
|
| - Free(config_blob);
|
|
|
| image->config_signature = (uint8_t*) Malloc(signature_len);
|
| Memcpy(image->config_signature, config_signature, signature_len);
|
| Free(config_signature);
|
| -
|
| - if (!(kernel_signature = SignatureBuf(image->kernel_data,
|
| + /* Kernel signature muse be calculated on the kernel version, options and
|
| + * kernel data to avoid splicing attacks. */
|
| + kernel_buf = (uint8_t*) Malloc(GetKernelConfigLen() +
|
| + image->options.kernel_len);
|
| + Memcpy(kernel_buf, config_blob, GetKernelConfigLen());
|
| + Memcpy(kernel_buf + GetKernelConfigLen(), image->kernel_data,
|
| + image->options.kernel_len);
|
| + if (!(kernel_signature = SignatureBuf(kernel_buf,
|
| + GetKernelConfigLen() +
|
| image->options.kernel_len,
|
| kernel_signing_key_file,
|
| image->kernel_sign_algorithm))) {
|
| + Free(config_blob);
|
| + Free(kernel_buf);
|
| fprintf(stderr, "Could not compute signature on the kernel.\n");
|
| return 0;
|
| }
|
| image->kernel_signature = (uint8_t*) Malloc(signature_len);
|
| Memcpy(image->kernel_signature, kernel_signature, signature_len);
|
| Free(kernel_signature);
|
| + Free(kernel_buf);
|
| + Free(config_blob);
|
| return 1;
|
| }
|
|
|
|
|