From: Kiran K Date: Sat, 28 Feb 2026 09:12:31 +0000 (+0530) Subject: Bluetooth: btintel: Add support for hybrid signature for ScP2 onwards X-Git-Tag: ceph-for-7.1-rc4~263^2~12^2~36 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=21b51648f3f48d3623d3a1c434356c96e8fc15c1;p=ceph-client.git Bluetooth: btintel: Add support for hybrid signature for ScP2 onwards If FW image has hybrid signature (ECDSA and LMS) then send CSS header, ECDSA public key, ECDSA signature, LMS public key, LMS signature and command buffer to device. Signed-off-by: Kiran K Signed-off-by: Luiz Augusto von Dentz --- diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c index ab146894ba4e..39e16dcca0ce 100644 --- a/drivers/bluetooth/btintel.c +++ b/drivers/bluetooth/btintel.c @@ -35,6 +35,19 @@ enum { DSM_SET_RESET_METHOD = 3, }; +/* Hybrid ECDSA + LMS */ +#define BTINTEL_RSA_HEADER_VER 0x00010000 +#define BTINTEL_ECDSA_HEADER_VER 0x00020000 +#define BTINTEL_HYBRID_HEADER_VER 0x00069700 +#define BTINTEL_ECDSA_OFFSET 128 +#define BTINTEL_CSS_HEADER_SIZE 128 +#define BTINTEL_ECDSA_PUB_KEY_SIZE 96 +#define BTINTEL_ECDSA_SIG_SIZE 96 +#define BTINTEL_LMS_OFFSET 320 +#define BTINTEL_LMS_PUB_KEY_SIZE 52 +#define BTINTEL_LMS_SIG_SIZE 1744 +#define BTINTEL_CMD_BUFFER_OFFSET 2116 + #define BTINTEL_BT_DOMAIN 0x12 #define BTINTEL_SAR_LEGACY 0 #define BTINTEL_SAR_INC_PWR 1 @@ -510,8 +523,8 @@ int btintel_version_info_tlv(struct hci_dev *hdev, return -EINVAL; } - /* Secure boot engine type should be either 1 (ECDSA) or 0 (RSA) */ - if (version->sbe_type > 0x01) { + /* Secure boot engine type can be 0 (RSA), 1 (ECDSA), 2 (LMS), 3 (ECDSA + LMS) */ + if (version->sbe_type > 0x03) { bt_dev_err(hdev, "Unsupported Intel secure boot engine type (0x%x)", version->sbe_type); return -EINVAL; @@ -1030,6 +1043,48 @@ static int btintel_sfi_ecdsa_header_secure_send(struct hci_dev *hdev, return 0; } +static int btintel_sfi_hybrid_header_secure_send(struct hci_dev *hdev, + const struct firmware *fw) +{ + int err; + + err = btintel_secure_send(hdev, 0x00, BTINTEL_CSS_HEADER_SIZE, fw->data); + if (err < 0) { + bt_dev_err(hdev, "Failed to send firmware CSS header (%d)", err); + return err; + } + + err = btintel_secure_send(hdev, 0x03, BTINTEL_ECDSA_PUB_KEY_SIZE, + fw->data + BTINTEL_ECDSA_OFFSET); + if (err < 0) { + bt_dev_err(hdev, "Failed to send firmware ECDSA pkey (%d)", err); + return err; + } + + err = btintel_secure_send(hdev, 0x02, BTINTEL_ECDSA_SIG_SIZE, + fw->data + BTINTEL_ECDSA_OFFSET + BTINTEL_ECDSA_PUB_KEY_SIZE); + if (err < 0) { + bt_dev_err(hdev, "Failed to send firmware ECDSA signature (%d)", err); + return err; + } + + err = btintel_secure_send(hdev, 0x05, BTINTEL_LMS_PUB_KEY_SIZE, + fw->data + BTINTEL_LMS_OFFSET); + if (err < 0) { + bt_dev_err(hdev, "Failed to send firmware LMS pkey (%d)", err); + return err; + } + + err = btintel_secure_send(hdev, 0x04, BTINTEL_LMS_SIG_SIZE, + fw->data + BTINTEL_LMS_OFFSET + BTINTEL_LMS_PUB_KEY_SIZE); + if (err < 0) { + bt_dev_err(hdev, "Failed to send firmware LMS signature (%d)", err); + return err; + } + + return 0; +} + static int btintel_download_firmware_payload(struct hci_dev *hdev, const struct firmware *fw, size_t offset) @@ -1203,11 +1258,12 @@ static int btintel_download_fw_tlv(struct hci_dev *hdev, * Command Buffer. * * CSS Header byte positions 0x08 to 0x0B represent the CSS Header - * version: RSA(0x00010000) , ECDSA (0x00020000) + * version: RSA(0x00010000) , ECDSA (0x00020000) , HYBRID (0x00069700) */ css_header_ver = get_unaligned_le32(fw->data + CSS_HEADER_OFFSET); - if (css_header_ver != 0x00010000) { - bt_dev_err(hdev, "Invalid CSS Header version"); + if (css_header_ver != BTINTEL_RSA_HEADER_VER && + css_header_ver != BTINTEL_HYBRID_HEADER_VER) { + bt_dev_err(hdev, "Invalid CSS Header version: 0x%8.8x", css_header_ver); return -EINVAL; } @@ -1225,15 +1281,15 @@ static int btintel_download_fw_tlv(struct hci_dev *hdev, err = btintel_download_firmware_payload(hdev, fw, RSA_HEADER_LEN); if (err) return err; - } else if (hw_variant >= 0x17) { + } else if (hw_variant >= 0x17 && css_header_ver == BTINTEL_RSA_HEADER_VER) { /* 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"); + if (css_header_ver != BTINTEL_ECDSA_HEADER_VER) { + bt_dev_err(hdev, "Invalid CSS Header version: 0x%8.8x", css_header_ver); return -EINVAL; } @@ -1256,6 +1312,14 @@ static int btintel_download_fw_tlv(struct hci_dev *hdev, if (err) return err; } + } else if (hw_variant >= 0x20 && css_header_ver == BTINTEL_HYBRID_HEADER_VER) { + err = btintel_sfi_hybrid_header_secure_send(hdev, fw); + if (err) + return err; + + err = btintel_download_firmware_payload(hdev, fw, BTINTEL_CMD_BUFFER_OFFSET); + if (err) + return err; } return 0; }