accel/habanalabs/gaudi2: add signed dev info uAPI
authorMoti Haimovski <mhaimovski@habana.ai>
Sun, 12 Nov 2023 16:07:10 +0000 (18:07 +0200)
committerOded Gabbay <ogabbay@kernel.org>
Tue, 19 Dec 2023 09:09:43 +0000 (11:09 +0200)
User will provide a nonce via the INFO ioctl, and will retrieve
the signed device info generated using given nonce.

Signed-off-by: Moti Haimovski <mhaimovski@habana.ai>
Reviewed-by: Oded Gabbay <ogabbay@kernel.org>
Signed-off-by: Oded Gabbay <ogabbay@kernel.org>
drivers/accel/habanalabs/common/firmware_if.c
drivers/accel/habanalabs/common/habanalabs.h
drivers/accel/habanalabs/common/habanalabs_ioctl.c
include/linux/habanalabs/cpucp_if.h
include/uapi/drm/habanalabs_accel.h

index 9e9dfe013659f5562f3f988ac5f51d5ba596056f..3558a6a8e1925a8ae397ca1aa975aaeef297fb25 100644 (file)
@@ -3244,6 +3244,14 @@ int hl_fw_get_sec_attest_info(struct hl_device *hdev, struct cpucp_sec_attest_in
                                        HL_CPUCP_SEC_ATTEST_INFO_TINEOUT_USEC);
 }
 
+int hl_fw_get_dev_info_signed(struct hl_device *hdev,
+                             struct cpucp_dev_info_signed *dev_info_signed, u32 nonce)
+{
+       return hl_fw_get_sec_attest_data(hdev, CPUCP_PACKET_INFO_SIGNED_GET, dev_info_signed,
+                                        sizeof(struct cpucp_dev_info_signed), nonce,
+                                        HL_CPUCP_SEC_ATTEST_INFO_TINEOUT_USEC);
+}
+
 int hl_fw_send_generic_request(struct hl_device *hdev, enum hl_passthrough_type sub_opcode,
                                                dma_addr_t buff, u32 *size)
 {
index 7b0209e5bad615cdd30f8f8fa93179f1bfaca63f..dd3fe3ddc00a6257102a845e19364cb4b94624f1 100644 (file)
@@ -3964,6 +3964,8 @@ long hl_fw_get_max_power(struct hl_device *hdev);
 void hl_fw_set_max_power(struct hl_device *hdev);
 int hl_fw_get_sec_attest_info(struct hl_device *hdev, struct cpucp_sec_attest_info *sec_attest_info,
                                u32 nonce);
+int hl_fw_get_dev_info_signed(struct hl_device *hdev,
+                             struct cpucp_dev_info_signed *dev_info_signed, u32 nonce);
 int hl_set_voltage(struct hl_device *hdev, int sensor_index, u32 attr, long value);
 int hl_set_current(struct hl_device *hdev, int sensor_index, u32 attr, long value);
 int hl_set_power(struct hl_device *hdev, int sensor_index, u32 attr, long value);
index 8ef36effb95bc4071a5cceaaff3e68319040d71a..a92713e0e580174240823ce1a4350d5cb7af12f6 100644 (file)
@@ -19,6 +19,9 @@
 
 #include <asm/msr.h>
 
+/* make sure there is space for all the signed info */
+static_assert(sizeof(struct cpucp_info) <= SEC_DEV_INFO_BUF_SZ);
+
 static u32 hl_debug_struct_size[HL_DEBUG_OP_TIMESTAMP + 1] = {
        [HL_DEBUG_OP_ETR] = sizeof(struct hl_debug_params_etr),
        [HL_DEBUG_OP_ETF] = sizeof(struct hl_debug_params_etf),
@@ -719,6 +722,53 @@ free_sec_attest_info:
        return rc;
 }
 
+static int dev_info_signed(struct hl_fpriv *hpriv, struct hl_info_args *args)
+{
+       void __user *out = (void __user *) (uintptr_t) args->return_pointer;
+       struct cpucp_dev_info_signed *dev_info_signed;
+       struct hl_info_signed *info;
+       u32 max_size = args->return_size;
+       int rc;
+
+       if ((!max_size) || (!out))
+               return -EINVAL;
+
+       dev_info_signed = kzalloc(sizeof(*dev_info_signed), GFP_KERNEL);
+       if (!dev_info_signed)
+               return -ENOMEM;
+
+       info = kzalloc(sizeof(*info), GFP_KERNEL);
+       if (!info) {
+               rc = -ENOMEM;
+               goto free_dev_info_signed;
+       }
+
+       rc = hl_fw_get_dev_info_signed(hpriv->hdev,
+                                       dev_info_signed, args->sec_attest_nonce);
+       if (rc)
+               goto free_info;
+
+       info->nonce = le32_to_cpu(dev_info_signed->nonce);
+       info->info_sig_len = dev_info_signed->info_sig_len;
+       info->pub_data_len = le16_to_cpu(dev_info_signed->pub_data_len);
+       info->certificate_len = le16_to_cpu(dev_info_signed->certificate_len);
+       info->dev_info_len = sizeof(struct cpucp_info);
+       memcpy(&info->info_sig, &dev_info_signed->info_sig, sizeof(info->info_sig));
+       memcpy(&info->public_data, &dev_info_signed->public_data, sizeof(info->public_data));
+       memcpy(&info->certificate, &dev_info_signed->certificate, sizeof(info->certificate));
+       memcpy(&info->dev_info, &dev_info_signed->info, info->dev_info_len);
+
+       rc = copy_to_user(out, info, min_t(size_t, max_size, sizeof(*info))) ? -EFAULT : 0;
+
+free_info:
+       kfree(info);
+free_dev_info_signed:
+       kfree(dev_info_signed);
+
+       return rc;
+}
+
+
 static int eventfd_register(struct hl_fpriv *hpriv, struct hl_info_args *args)
 {
        int rc;
@@ -1089,6 +1139,9 @@ static int _hl_info_ioctl(struct hl_fpriv *hpriv, void *data,
        case HL_INFO_FW_GENERIC_REQ:
                return send_fw_generic_request(hdev, args);
 
+       case HL_INFO_DEV_SIGNED:
+               return dev_info_signed(hpriv, args);
+
        default:
                dev_err(dev, "Invalid request %d\n", args->op);
                rc = -EINVAL;
index 86ea7c63a0d297cfbf4e874ce3a4153f6f970b08..f316c8d0f3fc9f6317f2cf838474681da1e4eadf 100644 (file)
@@ -659,6 +659,12 @@ enum pq_init_status {
  *       number (nonce) provided by the host to prevent replay attacks.
  *       public key and certificate also provided as part of the FW response.
  *
+ * CPUCP_PACKET_INFO_SIGNED_GET -
+ *       Get the device information signed by the Trusted Platform device.
+ *       device info data is also hashed with some unique number (nonce) provided
+ *       by the host to prevent replay attacks. public key and certificate also
+ *       provided as part of the FW response.
+ *
  * CPUCP_PACKET_MONITOR_DUMP_GET -
  *       Get monitors registers dump from the CpuCP kernel.
  *       The CPU will put the registers dump in the a buffer allocated by the driver
@@ -733,7 +739,7 @@ enum cpucp_packet_id {
        CPUCP_PACKET_ENGINE_CORE_ASID_SET,      /* internal */
        CPUCP_PACKET_RESERVED2,                 /* not used */
        CPUCP_PACKET_SEC_ATTEST_GET,            /* internal */
-       CPUCP_PACKET_RESERVED3,                 /* not used */
+       CPUCP_PACKET_INFO_SIGNED_GET,           /* internal */
        CPUCP_PACKET_RESERVED4,                 /* not used */
        CPUCP_PACKET_MONITOR_DUMP_GET,          /* debugfs */
        CPUCP_PACKET_RESERVED5,                 /* not used */
index 347c7b62e60e557b6b4c454512b766d11d92e767..a512dc4cffd051fc7c6431cd01dd5e580fad84c4 100644 (file)
@@ -846,6 +846,7 @@ enum hl_server_type {
 #define HL_INFO_HW_ERR_EVENT                   36
 #define HL_INFO_FW_ERR_EVENT                   37
 #define HL_INFO_USER_ENGINE_ERR_EVENT          38
+#define HL_INFO_DEV_SIGNED                     40
 
 #define HL_INFO_VERSION_MAX_LEN                        128
 #define HL_INFO_CARD_NAME_MAX_LEN              16
@@ -1256,6 +1257,7 @@ struct hl_info_dev_memalloc_page_sizes {
 #define SEC_SIGNATURE_BUF_SZ   255     /* (256 - 1) 1 byte used for size */
 #define SEC_PUB_DATA_BUF_SZ    510     /* (512 - 2) 2 bytes used for size */
 #define SEC_CERTIFICATE_BUF_SZ 2046    /* (2048 - 2) 2 bytes used for size */
+#define SEC_DEV_INFO_BUF_SZ    5120
 
 /*
  * struct hl_info_sec_attest - attestation report of the boot
@@ -1290,6 +1292,32 @@ struct hl_info_sec_attest {
        __u8 pad0[2];
 };
 
+/*
+ * struct hl_info_signed - device information signed by a secured device.
+ * @nonce: number only used once. random number provided by host. this also passed to the quote
+ *         command as a qualifying data.
+ * @pub_data_len: length of the public data (bytes)
+ * @certificate_len: length of the certificate (bytes)
+ * @info_sig_len: length of the attestation signature (bytes)
+ * @public_data: public key info signed info data (outPublic + name + qualifiedName)
+ * @certificate: certificate for the signing key
+ * @info_sig: signature of the info + nonce data.
+ * @dev_info_len: length of device info (bytes)
+ * @dev_info: device info as byte array.
+ */
+struct hl_info_signed {
+       __u32 nonce;
+       __u16 pub_data_len;
+       __u16 certificate_len;
+       __u8 info_sig_len;
+       __u8 public_data[SEC_PUB_DATA_BUF_SZ];
+       __u8 certificate[SEC_CERTIFICATE_BUF_SZ];
+       __u8 info_sig[SEC_SIGNATURE_BUF_SZ];
+       __u16 dev_info_len;
+       __u8 dev_info[SEC_DEV_INFO_BUF_SZ];
+       __u8 pad[2];
+};
+
 /**
  * struct hl_page_fault_info - page fault information.
  * @timestamp: timestamp of page fault.