/* 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 "cryptolib.h" #include "rollback_index.h" #include "tss_constants.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." }; uint64_t GetFirmwarePreambleLen(int algorithm) { return (FIELD_LEN(firmware_version) + FIELD_LEN(firmware_len) + FIELD_LEN(kernel_subkey_sign_algorithm) + RSAProcessedKeySize(algorithm) + FIELD_LEN(preamble)); } 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 firmware_sign_algorithm, uint64_t* firmware_len) { uint64_t len; int preamble_len; uint16_t firmware_version; uint16_t kernel_subkey_sign_algorithm; Memcpy(&firmware_version, preamble_blob, sizeof(firmware_version)); Memcpy(&kernel_subkey_sign_algorithm, preamble_blob + (FIELD_LEN(firmware_version) + FIELD_LEN(firmware_len)), FIELD_LEN(kernel_subkey_sign_algorithm)); if (kernel_subkey_sign_algorithm >= kNumAlgorithms) return VERIFY_FIRMWARE_INVALID_ALGORITHM; preamble_len = GetFirmwarePreambleLen(kernel_subkey_sign_algorithm); 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 */ firmware_sign_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, uint64_t firmware_len, int firmware_sign_algorithm) { int signature_len = siglen_map[firmware_sign_algorithm]; int preamble_len; uint16_t kernel_subkey_sign_algorithm; uint8_t* digest = NULL; const uint8_t* firmware_signature = NULL; DigestContext ctx; Memcpy(&kernel_subkey_sign_algorithm, preamble_start + (FIELD_LEN(firmware_version) + FIELD_LEN(firmware_len)), FIELD_LEN(kernel_subkey_sign_algorithm)); if (kernel_subkey_sign_algorithm >= kNumAlgorithms) return VERIFY_FIRMWARE_INVALID_ALGORITHM; preamble_len = GetFirmwarePreambleLen(kernel_subkey_sign_algorithm); /* 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, firmware_sign_algorithm); DigestUpdate(&ctx, preamble_start, preamble_len); DigestUpdate(&ctx, firmware_data, firmware_len); digest = DigestFinal(&ctx); /* Firmware signature is at the end of preamble and preamble signature. */ firmware_signature = preamble_start + preamble_len + signature_len; if (!RSAVerifyBinaryWithDigest_f( NULL, firmware_sign_key, /* Key to use. */ digest, /* Digest of the data to verify. */ firmware_signature, /* Expected Signature */ firmware_sign_algorithm)) { Free(digest); return VERIFY_FIRMWARE_SIGNATURE_FAILED; } Free(digest); return 0; } int VerifyFirmware(const uint8_t* root_key_blob, const uint8_t* verification_header_blob, const uint8_t* firmware_blob) { int error_code = 0; int firmware_sign_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. */ /* Note: All the offset calculations are based on struct FirmwareImage which * is defined in include/firmware_image_fw.h. */ /* Compare magic bytes. */ if (SafeMemcmp(verification_header_blob, FIRMWARE_MAGIC, FIRMWARE_MAGIC_SIZE)) { debug("Wrong Firmware Magic.\n"); return VERIFY_FIRMWARE_WRONG_MAGIC; } header_ptr = verification_header_blob + FIRMWARE_MAGIC_SIZE; /* Only continue if header verification succeeds. */ if ((error_code = VerifyFirmwareHeader(root_key_blob, header_ptr, &firmware_sign_algorithm, &header_len))) { debug("Couldn't verify Firmware header.\n"); return error_code; /* AKA jump to revovery. */ } /* Parse signing key into RSAPublicKey structure since it is required multiple * times. */ firmware_sign_key_len = RSAProcessedKeySize(firmware_sign_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[firmware_sign_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, firmware_sign_algorithm, &firmware_len))) { RSAPublicKeyFree(firmware_sign_key); debug("Couldn't verify Firmware preamble.\n"); return error_code; /* AKA jump to recovery. */ } if ((error_code = VerifyFirmwareData(firmware_sign_key, preamble_ptr, firmware_blob, firmware_len, firmware_sign_algorithm))) { RSAPublicKeyFree(firmware_sign_key); debug("Couldn't verify Firmware data.\n"); return error_code; /* AKA jump to recovery. */ } RSAPublicKeyFree(firmware_sign_key); return VERIFY_FIRMWARE_SUCCESS; /* Success! */ } uint32_t GetLogicalFirmwareVersion(uint8_t* verification_header_blob) { uint16_t firmware_key_version; uint16_t firmware_version; uint16_t firmware_sign_algorithm; int firmware_sign_key_len; Memcpy(&firmware_sign_algorithm, verification_header_blob + (FIELD_LEN(magic) + /* Offset to field. */ FIELD_LEN(header_len)), sizeof(firmware_sign_algorithm)); Memcpy(&firmware_key_version, verification_header_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, verification_header_blob + (FIELD_LEN(magic) + /* Offset to field. */ FIELD_LEN(header_len) + FIELD_LEN(firmware_sign_algorithm) + 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* verification_headerA, uint8_t* firmwareA, uint8_t* verification_headerB, 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. */ uint16_t version, key_version; /* Temporary variables */ /* Initialize the TPM since we'll be reading the rollback indices. */ SetupTPM(0, 0); /* 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(verification_headerA); firmwareB_lversion = GetLogicalFirmwareVersion(verification_headerB); min_lversion = Min(firmwareA_lversion, firmwareB_lversion); GetStoredVersions(FIRMWARE_VERSIONS, &key_version, &version); stored_lversion = CombineUint16Pair(key_version, version); /* Always try FirmwareA first. */ if (VERIFY_FIRMWARE_SUCCESS == VerifyFirmware(root_key_blob, verification_headerA, 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, verification_headerB, firmwareB)) { WriteStoredVersions(FIRMWARE_VERSIONS, (uint16_t) (min_lversion >> 16), (uint16_t) (min_lversion & 0xFFFF)); stored_lversion = min_lversion; /* Update stored version as it's used * later. */ } } } /* Lock Firmware TPM rollback indices from further writes. In this design, * this is done by setting the globalLock bit, which is cleared only by * TPM_Init at reboot. */ if (TPM_SUCCESS != LockFirmwareVersions()) { return VERIFY_FIRMWARE_TPM_ERROR; } /* 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, verification_headerB, firmwareB))) return BOOT_FIRMWARE_B_CONTINUE; } /* D'oh: No bootable firmware. */ return BOOT_FIRMWARE_RECOVERY_CONTINUE; }