/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * * Functions for verifying a verified boot firmware image. * (Firmware Portion) */ #include "firmware_image_fw.h" #include "padding.h" #include "rollback_index.h" #include "rsa_utility.h" #include "sha_utility.h" #include "utility.h" /* Macro to determine the size of a field structure in the FirmwareImage * structure. */ #define FIELD_LEN(field) (sizeof(((FirmwareImage*)0)->field)) char* kVerifyFirmwareErrors[VERIFY_FIRMWARE_MAX] = { "Success.", "Invalid Image.", "Root Key Signature Failed.", "Invalid Verification Algorithm.", "Preamble Signature Failed.", "Firmware Signature Failed.", "Wrong Firmware Magic.", "Invalid Firmware Header Checksum.", "Firmware Signing Key Rollback.", "Firmware Version Rollback." }; int VerifyFirmwareHeader(const uint8_t* root_key_blob, const uint8_t* header_blob, int* algorithm, int* header_len) { int firmware_sign_key_len; int root_key_len; uint16_t hlen, algo; uint8_t* header_checksum = NULL; /* Base Offset for the header_checksum field. Actual offset is * this + firmware_sign_key_len. */ int base_header_checksum_offset = (FIELD_LEN(header_len) + FIELD_LEN(firmware_sign_algorithm) + FIELD_LEN(firmware_key_version)); root_key_len = RSAProcessedKeySize(ROOT_SIGNATURE_ALGORITHM); Memcpy(&hlen, header_blob, sizeof(hlen)); Memcpy(&algo, header_blob + FIELD_LEN(firmware_sign_algorithm), sizeof(algo)); if (algo >= kNumAlgorithms) return VERIFY_FIRMWARE_INVALID_ALGORITHM; *algorithm = (int) algo; firmware_sign_key_len = RSAProcessedKeySize(*algorithm); /* Verify that header len is correct. */ if (hlen != (base_header_checksum_offset + firmware_sign_key_len + FIELD_LEN(header_checksum))) return VERIFY_FIRMWARE_INVALID_IMAGE; *header_len = (int) hlen; /* Verify if the hash of the header is correct. */ header_checksum = DigestBuf(header_blob, *header_len - FIELD_LEN(header_checksum), SHA512_DIGEST_ALGORITHM); if (SafeMemcmp(header_checksum, header_blob + (base_header_checksum_offset + firmware_sign_key_len), FIELD_LEN(header_checksum))) { Free(header_checksum); return VERIFY_FIRMWARE_WRONG_HEADER_CHECKSUM; } Free(header_checksum); /* Root key signature on the firmware signing key is always checked * irrespective of dev mode. */ if (!RSAVerifyBinary_f(root_key_blob, NULL, /* Key to use */ header_blob, /* Data to verify */ *header_len, /* Length of data */ header_blob + *header_len, /* Expected Signature */ ROOT_SIGNATURE_ALGORITHM)) return VERIFY_FIRMWARE_ROOT_SIGNATURE_FAILED; return 0; } int VerifyFirmwarePreamble(RSAPublicKey* firmware_sign_key, const uint8_t* preamble_blob, int algorithm, uint64_t* firmware_len) { uint64_t len; int preamble_len; uint16_t firmware_version; Memcpy(&firmware_version, preamble_blob, sizeof(firmware_version)); preamble_len = (FIELD_LEN(firmware_version) + FIELD_LEN(firmware_len) + FIELD_LEN(preamble)); if (!RSAVerifyBinary_f(NULL, firmware_sign_key, /* Key to use */ preamble_blob, /* Data to verify */ preamble_len, /* Length of data */ preamble_blob + preamble_len, /* Expected Signature */ algorithm)) return VERIFY_FIRMWARE_PREAMBLE_SIGNATURE_FAILED; Memcpy(&len, preamble_blob + FIELD_LEN(firmware_version), sizeof(len)); *firmware_len = len; return 0; } int VerifyFirmwareData(RSAPublicKey* firmware_sign_key, const uint8_t* preamble_start, const uint8_t* firmware_data_start, uint64_t firmware_len, int algorithm) { int signature_len = siglen_map[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, (FIELD_LEN(firmware_version) + FIELD_LEN(firmware_len) + FIELD_LEN(preamble))); 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 = 0; int algorithm; /* Signing key algorithm. */ RSAPublicKey* firmware_sign_key = NULL; int firmware_sign_key_len, signature_len, header_len; uint64_t firmware_len; const uint8_t* header_ptr = NULL; /* Pointer to header. */ const uint8_t* firmware_sign_key_ptr = NULL; /* Pointer to signing key. */ const uint8_t* preamble_ptr = NULL; /* Pointer to preamble block. */ const uint8_t* firmware_ptr = NULL; /* Pointer to firmware signature/data. */ /* Note: All the offset calculations are based on struct FirmwareImage which * is defined in include/firmware_image.h. */ /* Compare magic bytes. */ if (SafeMemcmp(firmware_blob, FIRMWARE_MAGIC, FIRMWARE_MAGIC_SIZE)) return VERIFY_FIRMWARE_WRONG_MAGIC; header_ptr = firmware_blob + FIRMWARE_MAGIC_SIZE; /* Only continue if header verification succeeds. */ if ((error_code = VerifyFirmwareHeader(root_key_blob, header_ptr, &algorithm, &header_len))) return error_code; /* AKA jump to revovery. */ /* Parse signing key into RSAPublicKey structure since it is required multiple * times. */ firmware_sign_key_len = RSAProcessedKeySize(algorithm); firmware_sign_key_ptr = header_ptr + (FIELD_LEN(header_len) + FIELD_LEN(firmware_sign_algorithm) + FIELD_LEN(firmware_key_version)); firmware_sign_key = RSAPublicKeyFromBuf(firmware_sign_key_ptr, firmware_sign_key_len); signature_len = siglen_map[algorithm]; /* Only continue if preamble verification succeeds. */ preamble_ptr = (header_ptr + header_len + FIELD_LEN(firmware_key_signature)); if ((error_code = VerifyFirmwarePreamble(firmware_sign_key, preamble_ptr, algorithm, &firmware_len))) { RSAPublicKeyFree(firmware_sign_key); debug("Couldn't verify Firmware preamble.\n"); return error_code; /* AKA jump to recovery. */ } /* Only continue if firmware data verification succeeds. */ firmware_ptr = (preamble_ptr + (FIELD_LEN(firmware_version) + /* Skip the preamble. */ FIELD_LEN(firmware_len) + FIELD_LEN(preamble)) + signature_len); if ((error_code = VerifyFirmwareData(firmware_sign_key, preamble_ptr, firmware_ptr, firmware_len, algorithm))) { RSAPublicKeyFree(firmware_sign_key); debug("Couldn't verify Firmware data.\n"); return error_code; /* AKA jump to recovery. */ } RSAPublicKeyFree(firmware_sign_key); return 0; /* Success! */ } uint32_t GetLogicalFirmwareVersion(uint8_t* firmware_blob) { uint16_t firmware_key_version; uint16_t firmware_version; uint16_t firmware_sign_algorithm; int firmware_sign_key_len; Memcpy(&firmware_sign_algorithm, firmware_blob + (FIELD_LEN(magic) + /* Offset to field. */ FIELD_LEN(header_len)), sizeof(firmware_sign_algorithm)); Memcpy(&firmware_key_version, firmware_blob + (FIELD_LEN(magic) + /* Offset to field. */ FIELD_LEN(header_len) + FIELD_LEN(firmware_sign_algorithm)), sizeof(firmware_key_version)); if (firmware_sign_algorithm >= kNumAlgorithms) return 0; firmware_sign_key_len = RSAProcessedKeySize(firmware_sign_algorithm); Memcpy(&firmware_version, firmware_blob + (FIELD_LEN(magic) + /* Offset to field. */ FIELD_LEN(header_len) + FIELD_LEN(firmware_key_version) + firmware_sign_key_len + FIELD_LEN(header_checksum) + FIELD_LEN(firmware_key_signature)), sizeof(firmware_version)); return CombineUint16Pair(firmware_key_version, firmware_version); } int VerifyFirmwareDriver_f(uint8_t* root_key_blob, uint8_t* firmwareA, uint8_t* firmwareB) { /* Contains the logical firmware version (32-bit) which is calculated as * (firmware_key_version << 16 | firmware_version) where * [firmware_key_version] [firmware_version] are both 16-bit. */ uint32_t firmwareA_lversion, firmwareB_lversion; uint8_t firmwareA_is_verified = 0; /* Whether firmwareA verify succeeded. */ uint32_t min_lversion; /* Minimum of firmware A and firmware lversion. */ uint32_t stored_lversion; /* Stored logical version in the TPM. */ /* Initialize the TPM since we'll be reading the rollback indices. */ SetupTPM(); /* We get the key versions by reading directly from the image blobs without * any additional (expensive) sanity checking on the blob since it's faster to * outright reject a firmware with an older firmware key version. A malformed * or corrupted firmware blob will still fail when VerifyFirmware() is called * on it. */ firmwareA_lversion = GetLogicalFirmwareVersion(firmwareA); firmwareB_lversion = GetLogicalFirmwareVersion(firmwareB); min_lversion = Min(firmwareA_lversion, firmwareB_lversion); stored_lversion = CombineUint16Pair(GetStoredVersion(FIRMWARE_KEY_VERSION), GetStoredVersion(FIRMWARE_VERSION)); /* Always try FirmwareA first. */ if (VERIFY_FIRMWARE_SUCCESS == VerifyFirmware(root_key_blob, firmwareA)) firmwareA_is_verified = 1; if (firmwareA_is_verified && (stored_lversion < firmwareA_lversion)) { /* Stored version may need to be updated but only if FirmwareB * is successfully verified and has a logical version greater than * the stored logical version. */ if (stored_lversion < firmwareB_lversion) { if (VERIFY_FIRMWARE_SUCCESS == VerifyFirmware(root_key_blob, firmwareB)) { WriteStoredVersion(FIRMWARE_KEY_VERSION, (uint16_t) (min_lversion >> 16)); WriteStoredVersion(FIRMWARE_VERSION, (uint16_t) (min_lversion & 0x00FFFF)); stored_lversion = min_lversion; /* Update stored version as it's used * later. */ } } } /* Lock Firmware TPM rollback indices from further writes. */ /* TODO(gauravsh): Figure out if these can be combined into one * 32-bit location since we seem to always use them together. This can help * us minimize the number of NVRAM writes/locks (which are limited over flash * memory lifetimes. */ LockStoredVersion(FIRMWARE_KEY_VERSION); LockStoredVersion(FIRMWARE_VERSION); /* Determine which firmware (if any) to jump to. * * We always attempt to jump to FirmwareA first. If verification of FirmwareA * fails, we try FirmwareB. In all cases, if the firmware successfully * verified but is a rollback, we jump to recovery. * * Note: This means that if FirmwareA verified successfully and is a * rollback, then no attempt is made to check FirmwareB. We still jump to * recovery. FirmwareB is only used as a backup in case FirmwareA gets * corrupted. Since newer firmware updates are always written to A, * the case where firmware A is verified but a rollback should not occur in * normal operation. */ if (firmwareA_is_verified) { if (stored_lversion <= firmwareA_lversion) return BOOT_FIRMWARE_A_CONTINUE; } else { /* If FirmwareA was not valid, then we skipped over the * check to update the rollback indices and a Verify of FirmwareB wasn't * attempted. * If FirmwareB is not a rollback, then we attempt to do the verification. */ if (stored_lversion <= firmwareB_lversion && (VERIFY_FIRMWARE_SUCCESS == VerifyFirmware(root_key_blob, firmwareB))) return BOOT_FIRMWARE_B_CONTINUE; } /* D'oh: No bootable firmware. */ return BOOT_FIRMWARE_RECOVERY_CONTINUE; }