Skip to content

Commit

Permalink
Bluetooth: btintel: Functions to send firmware header / payload
Browse files Browse the repository at this point in the history
New generation controllers supports ECDSA secure boot engine.
This patch adds,

1) function to send ECDSA header

2) function to download complete firmware for new generation Intel
   controllers

Signed-off-by: Kiran K <kiran.k@intel.com>
Signed-off-by: Amit K Bag <amit.k.bag@intel.com>
Signed-off-by: Raghuram Hegde <raghuram.hegde@intel.com>
Reviewed-by: Chethan T N <chethan.tumkur.narayan@intel.com>
Reviewed-by: Srivatsa Ravishankar <ravishankar.srivatsa@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
  • Loading branch information
Kiran K authored and Marcel Holtmann committed Sep 14, 2020
1 parent 57375be commit 81ebea5
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 2 deletions.
119 changes: 117 additions & 2 deletions drivers/bluetooth/btintel.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,11 @@

#define VERSION "0.1"

#define BDADDR_INTEL (&(bdaddr_t) {{0x00, 0x8b, 0x9e, 0x19, 0x03, 0x00}})
#define RSA_HEADER_LEN 644
#define BDADDR_INTEL (&(bdaddr_t){{0x00, 0x8b, 0x9e, 0x19, 0x03, 0x00}})
#define RSA_HEADER_LEN 644
#define CSS_HEADER_OFFSET 8
#define ECDSA_OFFSET 644
#define ECDSA_HEADER_LEN 320

int btintel_check_bdaddr(struct hci_dev *hdev)
{
Expand Down Expand Up @@ -801,6 +804,41 @@ static int btintel_sfi_rsa_header_secure_send(struct hci_dev *hdev,
return err;
}

static int btintel_sfi_ecdsa_header_secure_send(struct hci_dev *hdev,
const struct firmware *fw)
{
int err;

/* Start the firmware download transaction with the Init fragment
* represented by the 128 bytes of CSS header.
*/
err = btintel_secure_send(hdev, 0x00, 128, fw->data + 644);
if (err < 0) {
bt_dev_err(hdev, "Failed to send firmware header (%d)", err);
return err;
}

/* Send the 96 bytes of public key information from the firmware
* as the PKey fragment.
*/
err = btintel_secure_send(hdev, 0x03, 96, fw->data + 644 + 128);
if (err < 0) {
bt_dev_err(hdev, "Failed to send firmware pkey (%d)", err);
return err;
}

/* Send the 96 bytes of signature information from the firmware
* as the Sign fragment
*/
err = btintel_secure_send(hdev, 0x02, 96, fw->data + 644 + 224);
if (err < 0) {
bt_dev_err(hdev, "Failed to send firmware signature (%d)",
err);
return err;
}
return 0;
}

static int btintel_download_firmware_payload(struct hci_dev *hdev,
const struct firmware *fw,
u32 *boot_param, size_t offset)
Expand Down Expand Up @@ -873,6 +911,83 @@ int btintel_download_firmware(struct hci_dev *hdev,
}
EXPORT_SYMBOL_GPL(btintel_download_firmware);

int btintel_download_firmware_newgen(struct hci_dev *hdev,
const struct firmware *fw, u32 *boot_param,
u8 hw_variant, u8 sbe_type)
{
int err;
u32 css_header_ver;

/* iBT hardware variants 0x0b, 0x0c, 0x11, 0x12, 0x13, 0x14 support
* only RSA secure boot engine. Hence, the corresponding sfi file will
* have RSA header of 644 bytes followed by Command Buffer.
*
* iBT hardware variants 0x17, 0x18 onwards support both RSA and ECDSA
* secure boot engine. As a result, the corresponding sfi file will
* have RSA header of 644, ECDSA header of 320 bytes followed by
* Command Buffer.
*
* CSS Header byte positions 0x08 to 0x0B represent the CSS Header
* version: RSA(0x00010000) , ECDSA (0x00020000)
*/
css_header_ver = get_unaligned_le32(fw->data + CSS_HEADER_OFFSET);
if (css_header_ver != 0x00010000) {
bt_dev_err(hdev, "Invalid CSS Header version");
return -EINVAL;
}

if (hw_variant <= 0x14) {
if (sbe_type != 0x00) {
bt_dev_err(hdev, "Invalid SBE type for hardware variant (%d)",
hw_variant);
return -EINVAL;
}

err = btintel_sfi_rsa_header_secure_send(hdev, fw);
if (err)
return err;

err = btintel_download_firmware_payload(hdev, fw, boot_param, RSA_HEADER_LEN);
if (err)
return err;
} else if (hw_variant >= 0x17) {
/* Check if CSS header for ECDSA follows the RSA header */
if (fw->data[ECDSA_OFFSET] != 0x06)
return -EINVAL;

/* Check if the CSS Header version is ECDSA(0x00020000) */
css_header_ver = get_unaligned_le32(fw->data + ECDSA_OFFSET + CSS_HEADER_OFFSET);
if (css_header_ver != 0x00020000) {
bt_dev_err(hdev, "Invalid CSS Header version");
return -EINVAL;
}

if (sbe_type == 0x00) {
err = btintel_sfi_rsa_header_secure_send(hdev, fw);
if (err)
return err;

err = btintel_download_firmware_payload(hdev, fw,
boot_param,
RSA_HEADER_LEN + ECDSA_HEADER_LEN);
if (err)
return err;
} else if (sbe_type == 0x01) {
err = btintel_sfi_ecdsa_header_secure_send(hdev, fw);
if (err)
return err;

err = btintel_download_firmware_payload(hdev, fw,
boot_param,
RSA_HEADER_LEN + ECDSA_HEADER_LEN);
if (err)
return err;
}
}
return 0;
}
EXPORT_SYMBOL_GPL(btintel_download_firmware_newgen);

void btintel_reset_to_bootloader(struct hci_dev *hdev)
{
struct intel_reset params;
Expand Down
12 changes: 12 additions & 0 deletions drivers/bluetooth/btintel.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,10 @@ int btintel_read_boot_params(struct hci_dev *hdev,
struct intel_boot_params *params);
int btintel_download_firmware(struct hci_dev *dev, const struct firmware *fw,
u32 *boot_param);
int btintel_download_firmware_newgen(struct hci_dev *hdev,
const struct firmware *fw,
u32 *boot_param, u8 hw_variant,
u8 sbe_type);
void btintel_reset_to_bootloader(struct hci_dev *hdev);
int btintel_read_debug_features(struct hci_dev *hdev,
struct intel_debug_features *features);
Expand Down Expand Up @@ -270,6 +274,14 @@ static inline int btintel_download_firmware(struct hci_dev *dev,
return -EOPNOTSUPP;
}

static inline int btintel_download_firmware_newgen(struct hci_dev *hdev,
const struct firmware *fw,
u32 *boot_param,
u8 hw_variant, u8 sbe_type)
{
return -EOPNOTSUPP;
}

static inline void btintel_reset_to_bootloader(struct hci_dev *hdev)
{
}
Expand Down

0 comments on commit 81ebea5

Please sign in to comment.