Bluetooth: btintel: Functions to send firmware header / payload
authorKiran K <kiraank@gmail.com>
Mon, 14 Sep 2020 13:25:06 +0000 (18:55 +0530)
committerMarcel Holtmann <marcel@holtmann.org>
Mon, 14 Sep 2020 18:30:36 +0000 (20:30 +0200)
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>
drivers/bluetooth/btintel.c
drivers/bluetooth/btintel.h

index e99fc6e..88ce5f0 100644 (file)
 
 #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)
 {
@@ -801,6 +804,41 @@ done:
        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)
@@ -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;
index 829e1fc..09346ae 100644 (file)
@@ -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);
@@ -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)
 {
 }