diff options
| author | Komal Seelam <kseelam@qti.qualcomm.com> | 2014-08-08 18:49:38 +0530 |
|---|---|---|
| committer | Akash Patel <c_akashp@qca.qualcomm.com> | 2014-08-13 11:31:07 -0700 |
| commit | f5754cb4dd955f3c1ef330c07022182e3215c42a (patch) | |
| tree | ea292ca90eea80e9184cb882798134b2a93c3748 | |
| parent | ebfbe4dec45cbdd4194c49cd94167e65072ce526 (diff) | |
qcacld: FR: Secure Firmware Download
Driver has to compute the SHA-256 hash for each FW bin.
Driver stores sha256 hash of each bin in global static variable.
Download FW bin if the computed hash matches with stored hash of
respective FW bin else bail out.
If Stored Hash entries are NULL, download fw in non-secure mode.
Host Driver will be secured by OEM.
CRs-Fixed: 707238
Change-Id: Iac7c2270246dfdaf37d008305fe62108d7fd775d
| -rw-r--r-- | CORE/SERVICES/BMI/ol_fw.c | 81 | ||||
| -rw-r--r-- | CORE/SERVICES/BMI/ol_fw.h | 9 |
2 files changed, 90 insertions, 0 deletions
diff --git a/CORE/SERVICES/BMI/ol_fw.c b/CORE/SERVICES/BMI/ol_fw.c index fadc666469f5..055956d9be90 100644 --- a/CORE/SERVICES/BMI/ol_fw.c +++ b/CORE/SERVICES/BMI/ol_fw.c @@ -54,6 +54,8 @@ #include <net/cnss.h> #endif +static struct hash_fw fw_hash; + #ifdef HIF_PCI static u_int32_t refclk_speed_to_hz[] = { 48000000, /* SOC_REFCLK_48_MHZ */ @@ -356,6 +358,63 @@ exit: return status; } +static int ol_check_fw_hash(const u8* data, u32 data_size, ATH_BIN_FILE file) +{ + u8 *hash = NULL; + u8 digest[SHA256_DIGEST_SIZE]; + u8 temp[SHA256_DIGEST_SIZE] = {}; + int ret = 0; + + switch(file) { + case ATH_BOARD_DATA_FILE: + hash = fw_hash.bdwlan; + break; + case ATH_OTP_FILE: + hash = fw_hash.otp; + break; + case ATH_FIRMWARE_FILE: +#ifdef QCA_WIFI_FTM + if (vos_get_conparam() == VOS_FTM_MODE) { + hash = fw_hash.utf; + break; + } +#endif + hash = fw_hash.qwlan; + default: + break; + } + + if (!hash) { + pr_err("No entry for file:%d Download FW in non-secure mode\n", file); + goto end; + } + + if (!OS_MEMCMP(hash, temp, SHA256_DIGEST_SIZE)) { + pr_err("Download FW in non-secure mode:%d\n", file); + goto end; + } + +#ifdef CONFIG_CNSS + ret = cnss_get_sha_hash(data, data_size, "sha256", digest); + + if (ret) { + pr_err("Sha256 Hash computation fialed err:%d\n", ret); + goto end; + } + + if (OS_MEMCMP(hash, digest, SHA256_DIGEST_SIZE) != 0) { + pr_err("Hash Mismatch"); + vos_trace_hex_dump(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + digest, SHA256_DIGEST_SIZE); + vos_trace_hex_dump(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + hash, SHA256_DIGEST_SIZE); + ret = A_ERROR; + } +#endif +end: + return ret; +} + static int __ol_transfer_bin_file(struct ol_softc *scn, ATH_BIN_FILE file, u_int32_t address, bool compressed) { @@ -370,6 +429,9 @@ static int __ol_transfer_bin_file(struct ol_softc *scn, ATH_BIN_FILE file, int bin_off, bin_len; SIGN_HEADER_T *sign_header; #endif + u8 *fw_ptr; + u32 fw_size; + int ret; if (scn->enablesinglebinary && file != ATH_BOARD_DATA_FILE) { @@ -521,6 +583,25 @@ static int __ol_transfer_bin_file(struct ol_softc *scn, ATH_BIN_FILE file, fw_entry_size = fw_entry->size; tempEeprom = NULL; + fw_size = fw_entry->size; + fw_ptr = OS_MALLOC(scn->sc_osdev, fw_size, GFP_ATOMIC); + + if (!fw_ptr) { + pr_err("Failed to allocate fw_ptr memory\n"); + status = A_ERROR; + goto end; + } + OS_MEMCPY(fw_ptr, fw_entry->data, fw_size); + + if (ol_check_fw_hash(fw_ptr, fw_size, file)) { + pr_err("Hash Check failed for file:%s\n", filename); + status = A_ERROR; + OS_FREE(fw_ptr); + goto end; + } + + OS_FREE(fw_ptr); + if (file == ATH_BOARD_DATA_FILE) { u_int32_t board_ext_address; diff --git a/CORE/SERVICES/BMI/ol_fw.h b/CORE/SERVICES/BMI/ol_fw.h index c52db71d2927..918034518af5 100644 --- a/CORE/SERVICES/BMI/ol_fw.h +++ b/CORE/SERVICES/BMI/ol_fw.h @@ -86,6 +86,15 @@ #define TOTAL_DUMP_SIZE 0x00200000 #define PCIE_READ_LIMIT 0x00005000 +#define SHA256_DIGEST_SIZE 32 + +struct hash_fw { + u8 qwlan[SHA256_DIGEST_SIZE]; + u8 otp[SHA256_DIGEST_SIZE]; + u8 bdwlan[SHA256_DIGEST_SIZE]; + u8 utf[SHA256_DIGEST_SIZE]; +}; + int ol_target_coredump(void *instance, void* memoryBlock, u_int32_t blockLength); int ol_diag_read(struct ol_softc *scn, u_int8_t* buffer, |
