| Index: src/platform/vboot_reference/utils/firmware_image.c
|
| diff --git a/src/platform/vboot_reference/utils/firmware_image.c b/src/platform/vboot_reference/utils/firmware_image.c
|
| index a197708427c4e7053bcd6e22941f3d40b18131e7..a598f5447ba04c9230571e8081d09c39d8072fbc 100644
|
| --- a/src/platform/vboot_reference/utils/firmware_image.c
|
| +++ b/src/platform/vboot_reference/utils/firmware_image.c
|
| @@ -190,7 +190,7 @@ uint8_t* GetFirmwareHeaderBlob(const FirmwareImage* image) {
|
| return header_blob;
|
| }
|
|
|
| -int GetFirmwarePreambleLen(const FirmwareImage* image) {
|
| +int GetFirmwarePreambleLen(void) {
|
| return (FIELD_LEN(firmware_version) + FIELD_LEN(firmware_len) +
|
| FIELD_LEN(preamble));
|
| }
|
| @@ -199,8 +199,8 @@ 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);
|
| + preamble_blob = (uint8_t*) Malloc(GetFirmwarePreambleLen());
|
| + st.remaining_len = GetFirmwarePreambleLen();
|
| st.remaining_buf = preamble_blob;
|
|
|
| StatefulMemcpy_r(&st, &image->firmware_version, FIELD_LEN(firmware_version));
|
| @@ -229,7 +229,7 @@ uint8_t* GetFirmwareBlob(const FirmwareImage* image, uint64_t* blob_len) {
|
| *blob_len = (FIELD_LEN(magic) +
|
| GetFirmwareHeaderLen(image) +
|
| FIELD_LEN(firmware_key_signature) +
|
| - GetFirmwarePreambleLen(image) +
|
| + GetFirmwarePreambleLen() +
|
| 2 * firmware_signature_len +
|
| image->firmware_len);
|
| firmware_blob = (uint8_t*) Malloc(*blob_len);
|
| @@ -243,7 +243,7 @@ uint8_t* GetFirmwareBlob(const FirmwareImage* image, uint64_t* blob_len) {
|
| 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, preamble_blob, GetFirmwarePreambleLen());
|
| 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);
|
| @@ -405,23 +405,36 @@ int VerifyFirmwarePreamble(RSAPublicKey* firmware_sign_key,
|
| }
|
|
|
| int VerifyFirmwareData(RSAPublicKey* firmware_sign_key,
|
| + const uint8_t* preamble_start,
|
| const uint8_t* firmware_data_start,
|
| int firmware_len,
|
| int algorithm) {
|
| int signature_len = siglen_map[algorithm];
|
| - if (!RSAVerifyBinary_f(NULL, firmware_sign_key, /* Key to use. */
|
| - firmware_data_start + signature_len, /* Data to
|
| - * verify */
|
| - firmware_len, /* Length of data. */
|
| - firmware_data_start, /* Expected Signature */
|
| - algorithm))
|
| + uint8_t* digest;
|
| + DigestContext ctx;
|
| +
|
| + /* Since the firmware signature is over the preamble and the firmware data,
|
| + * which does not form a contiguous region of memory, we calculate the
|
| + * message digest ourselves. */
|
| + DigestInit(&ctx, algorithm);
|
| + DigestUpdate(&ctx, preamble_start, GetFirmwarePreambleLen());
|
| + DigestUpdate(&ctx, firmware_data_start + signature_len, firmware_len);
|
| + digest = DigestFinal(&ctx);
|
| + if (!RSAVerifyBinaryWithDigest_f(
|
| + NULL, firmware_sign_key, /* Key to use. */
|
| + digest, /* Digest of the data to verify. */
|
| + firmware_data_start, /* Expected Signature */
|
| + algorithm)) {
|
| + Free(digest);
|
| return VERIFY_FIRMWARE_SIGNATURE_FAILED;
|
| + }
|
| + Free(digest);
|
| return 0;
|
| }
|
|
|
| int VerifyFirmware(const uint8_t* root_key_blob,
|
| const uint8_t* firmware_blob) {
|
| - int error_code;
|
| + int error_code = 0;
|
| int algorithm; /* Signing key algorithm. */
|
| RSAPublicKey* firmware_sign_key = NULL;
|
| int firmware_sign_key_len, signature_len, header_len, firmware_len;
|
| @@ -464,10 +477,11 @@ int VerifyFirmware(const uint8_t* root_key_blob,
|
| }
|
| /* Only continue if firmware data verification succeeds. */
|
| firmware_ptr = (preamble_ptr +
|
| - GetFirmwarePreambleLen(NULL) +
|
| + GetFirmwarePreambleLen() +
|
| signature_len);
|
|
|
| - if ((error_code = VerifyFirmwareData(firmware_sign_key, firmware_ptr,
|
| + if ((error_code = VerifyFirmwareData(firmware_sign_key, preamble_ptr,
|
| + firmware_ptr,
|
| firmware_len,
|
| algorithm))) {
|
| RSAPublicKeyFree(firmware_sign_key);
|
| @@ -488,6 +502,7 @@ int VerifyFirmwareImage(const RSAPublicKey* root_key,
|
| int signature_size;
|
| int error_code = 0;
|
| DigestContext ctx;
|
| + DigestContext firmware_ctx;
|
|
|
| if (!image)
|
| return VERIFY_FIRMWARE_INVALID_IMAGE;
|
| @@ -546,10 +561,17 @@ int VerifyFirmwareImage(const RSAPublicKey* root_key,
|
| goto verify_failure;
|
| }
|
|
|
| - /* Verify firmware signature. */
|
| - firmware_digest = DigestBuf(image->firmware_data,
|
| - image->firmware_len,
|
| - image->firmware_sign_algorithm);
|
| + /* Verify firmware signature - firmware signature is on the contents
|
| + of firmware preamble + firmware_data. */
|
| + DigestInit(&firmware_ctx, image->firmware_sign_algorithm);
|
| + DigestUpdate(&firmware_ctx, (uint8_t*) &image->firmware_version,
|
| + FIELD_LEN(firmware_version));
|
| + DigestUpdate(&firmware_ctx, (uint8_t*) &image->firmware_len,
|
| + FIELD_LEN(firmware_len));
|
| + DigestUpdate(&firmware_ctx, (uint8_t*) &image->preamble,
|
| + FIELD_LEN(preamble));
|
| + DigestUpdate(&firmware_ctx, image->firmware_data, image->firmware_len);
|
| + firmware_digest = DigestFinal(&firmware_ctx);
|
| if (!RSAVerify(firmware_sign_key, image->firmware_signature,
|
| signature_size, image->firmware_sign_algorithm,
|
| firmware_digest)) {
|
| @@ -591,14 +613,17 @@ int AddFirmwareKeySignature(FirmwareImage* image, const char* root_key_file) {
|
| }
|
|
|
| int AddFirmwareSignature(FirmwareImage* image, const char* signing_key_file) {
|
| - uint8_t* preamble_blob;
|
| - uint8_t* preamble_signature;
|
| - uint8_t* firmware_signature;
|
| + uint8_t* preamble_blob = NULL;
|
| + uint8_t* preamble_signature = NULL;
|
| + uint8_t* firmware_signature = NULL;
|
| + uint8_t* firmware_buf = NULL;
|
| int signature_len = siglen_map[image->firmware_sign_algorithm];
|
|
|
| preamble_blob = GetFirmwarePreambleBlob(image);
|
| + if (!preamble_blob)
|
| + return 0;
|
| if (!(preamble_signature = SignatureBuf(preamble_blob,
|
| - GetFirmwarePreambleLen(image),
|
| + GetFirmwarePreambleLen(),
|
| signing_key_file,
|
| image->firmware_sign_algorithm))) {
|
| Free(preamble_blob);
|
| @@ -607,15 +632,27 @@ int AddFirmwareSignature(FirmwareImage* image, const char* signing_key_file) {
|
| image->preamble_signature = (uint8_t*) Malloc(signature_len);
|
| Memcpy(image->preamble_signature, preamble_signature, signature_len);
|
| Free(preamble_signature);
|
| -
|
| - if (!(firmware_signature = SignatureBuf(image->firmware_data,
|
| + /* Firmware signature must be calculated on preamble + firmware_data
|
| + * to avoid splicing attacks. */
|
| + firmware_buf = (uint8_t*) Malloc(GetFirmwarePreambleLen() +
|
| + image->firmware_len);
|
| + Memcpy(firmware_buf, preamble_blob, GetFirmwarePreambleLen());
|
| + Memcpy(firmware_buf + GetFirmwarePreambleLen(), image->firmware_data,
|
| + image->firmware_len);
|
| + if (!(firmware_signature = SignatureBuf(firmware_buf,
|
| + GetFirmwarePreambleLen() +
|
| image->firmware_len,
|
| signing_key_file,
|
| - image->firmware_sign_algorithm)))
|
| + image->firmware_sign_algorithm))) {
|
| + Free(preamble_blob);
|
| + Free(firmware_buf);
|
| return 0;
|
| + }
|
| image->firmware_signature = (uint8_t*) Malloc(signature_len);
|
| Memcpy(image->firmware_signature, firmware_signature, signature_len);
|
| Free(firmware_signature);
|
| + Free(firmware_buf);
|
| + Free(preamble_blob);
|
| return 1;
|
| }
|
|
|
|
|