[RFC PATCH 2/3] drivers: fpga: Add user-key encrypted FPGA Image loading support

Nava kishore Manne nava.kishore.manne at amd.com
Tue Nov 21 21:44:03 PST 2023


Adds parse_aes_key() callback to fpga_manager_ops, It will read the
AES key from firmware to support user-key encrypted bitstream loading.

Signed-off-by: Nava kishore Manne <nava.kishore.manne at amd.com>
---
 drivers/fpga/fpga-mgr.c       | 86 ++++++++++++++++++++++++++++++++---
 drivers/fpga/of-fpga-region.c | 10 ++++
 include/linux/fpga/fpga-mgr.h |  8 ++++
 3 files changed, 97 insertions(+), 7 deletions(-)

diff --git a/drivers/fpga/fpga-mgr.c b/drivers/fpga/fpga-mgr.c
index 06651389c592..c8e20e8f4b6f 100644
--- a/drivers/fpga/fpga-mgr.c
+++ b/drivers/fpga/fpga-mgr.c
@@ -83,6 +83,15 @@ static inline int fpga_mgr_parse_header(struct fpga_manager *mgr,
 	return 0;
 }
 
+static inline int fpga_mgr_parse_aes_key(struct fpga_manager *mgr,
+					 struct fpga_image_info *info,
+					 const char *buf, size_t count)
+{
+	if (mgr->mops->parse_aes_key)
+		return mgr->mops->parse_aes_key(mgr, info, buf, count);
+	return 0;
+}
+
 static inline int fpga_mgr_write_init(struct fpga_manager *mgr,
 				      struct fpga_image_info *info,
 				      const char *buf, size_t count)
@@ -559,6 +568,43 @@ static int fpga_mgr_firmware_load(struct fpga_manager *mgr,
 	return ret;
 }
 
+/**
+ * fpga_mgr_get_aes_key - request aes key form the firmware class
+ * @mgr:        fpga manager
+ * @info:       fpga image specific information
+ * @image_name: name of image file on the aes key firmware search path
+ *
+ *
+ * Request an aes key image using the firmware class, then Step the low level
+ * fpga manager through the device-specific steps. Update the state before each
+ * step to provide info on what step failed if there is a failure.
+ *
+ * Return: 0 on success, negative error code otherwise.
+ */
+static int fpga_mgr_get_aes_key(struct fpga_manager *mgr,
+				struct fpga_image_info *info,
+				const char *image_name,
+				const struct firmware *fw)
+{
+	struct device *dev = &mgr->dev;
+	int ret;
+
+	dev_info(dev, "Get Aes-key: %s to %s\n", image_name, mgr->name);
+
+	mgr->state = FPGA_MGR_STATE_FIRMWARE_REQ;
+
+	ret = request_firmware(&fw, image_name, dev);
+	if (ret) {
+		mgr->state = FPGA_MGR_STATE_FIRMWARE_REQ_ERR;
+		dev_err(dev, "Error requesting firmware %s\n", image_name);
+		return ret;
+	}
+
+	ret = fpga_mgr_parse_aes_key(mgr, info, fw->data, fw->size);
+
+	return ret;
+}
+
 /**
  * fpga_mgr_load - load FPGA from scatter/gather table, buffer, or firmware
  * @mgr:	fpga manager
@@ -571,15 +617,41 @@ static int fpga_mgr_firmware_load(struct fpga_manager *mgr,
  */
 int fpga_mgr_load(struct fpga_manager *mgr, struct fpga_image_info *info)
 {
+	const struct firmware *fw;
+	int ret;
+
 	info->header_size = mgr->mops->initial_header_size;
 
-	if (info->sgt)
-		return fpga_mgr_buf_load_sg(mgr, info, info->sgt);
-	if (info->buf && info->count)
-		return fpga_mgr_buf_load(mgr, info, info->buf, info->count);
-	if (info->firmware_name)
-		return fpga_mgr_firmware_load(mgr, info, info->firmware_name);
-	return -EINVAL;
+	if (info->encrypted_key_name) {
+		ret = fpga_mgr_get_aes_key(mgr, info,
+					   info->encrypted_key_name, fw);
+		if (ret)
+			return ret;
+
+		info->flags |= FPGA_MGR_USRKEY_ENCRYPTED_BITSTREAM;
+	}
+
+	if (info->sgt) {
+		ret = fpga_mgr_buf_load_sg(mgr, info, info->sgt);
+		if (ret)
+			goto free_fw;
+	} else if (info->buf && info->count) {
+		ret = fpga_mgr_buf_load(mgr, info, info->buf, info->count);
+		if (ret)
+			goto free_fw;
+	} else if (info->firmware_name) {
+		ret = fpga_mgr_firmware_load(mgr, info, info->firmware_name);
+		if (ret)
+			goto free_fw;
+	} else {
+		ret = -EINVAL;
+	}
+
+free_fw:
+	if (info->encrypted_key_name)
+		release_firmware(fw);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(fpga_mgr_load);
 
diff --git a/drivers/fpga/of-fpga-region.c b/drivers/fpga/of-fpga-region.c
index a6affd83f275..e9ddece4b82d 100644
--- a/drivers/fpga/of-fpga-region.c
+++ b/drivers/fpga/of-fpga-region.c
@@ -196,6 +196,7 @@ of_fpga_region_parse_ov(struct fpga_region *region,
 			struct device_node *overlay)
 {
 	struct device *dev = &region->dev;
+	const char *encrypted_key_name;
 	struct fpga_image_info *info;
 	const char *firmware_name;
 	int ret;
@@ -238,6 +239,15 @@ of_fpga_region_parse_ov(struct fpga_region *region,
 			return ERR_PTR(-ENOMEM);
 	}
 
+	if (!of_property_read_string(overlay, "encrypted-key-name",
+				     &encrypted_key_name)) {
+		info->encrypted_key_name = devm_kstrdup(dev,
+							encrypted_key_name,
+							GFP_KERNEL);
+		if (!info->encrypted_key_name)
+			return ERR_PTR(-ENOMEM);
+	}
+
 	of_property_read_u32(overlay, "region-unfreeze-timeout-us",
 			     &info->enable_timeout_us);
 
diff --git a/include/linux/fpga/fpga-mgr.h b/include/linux/fpga/fpga-mgr.h
index 54f63459efd6..303264d89922 100644
--- a/include/linux/fpga/fpga-mgr.h
+++ b/include/linux/fpga/fpga-mgr.h
@@ -71,12 +71,15 @@ enum fpga_mgr_states {
  * %FPGA_MGR_BITSTREAM_LSB_FIRST: SPI bitstream bit order is LSB first
  *
  * %FPGA_MGR_COMPRESSED_BITSTREAM: FPGA bitstream is compressed
+ *
+ * %FPGA_MGR_USRKEY_ENCRYPTED_BITSTREAM: indicates bitstream is encrypted with user-key
  */
 #define FPGA_MGR_PARTIAL_RECONFIG	BIT(0)
 #define FPGA_MGR_EXTERNAL_CONFIG	BIT(1)
 #define FPGA_MGR_ENCRYPTED_BITSTREAM	BIT(2)
 #define FPGA_MGR_BITSTREAM_LSB_FIRST	BIT(3)
 #define FPGA_MGR_COMPRESSED_BITSTREAM	BIT(4)
+#define FPGA_MGR_USRKEY_ENCRYPTED_BITSTREAM	BIT(5)
 
 /**
  * struct fpga_image_info - information specific to an FPGA image
@@ -86,6 +89,7 @@ enum fpga_mgr_states {
  * @config_complete_timeout_us: maximum time for FPGA to switch to operating
  *	   status in the write_complete op.
  * @firmware_name: name of FPGA image firmware file
+ * @encrypted_key_name: name of the FPGA image encrypted user-key file
  * @sgt: scatter/gather table containing FPGA image
  * @buf: contiguous buffer containing FPGA image
  * @count: size of buf
@@ -102,6 +106,7 @@ struct fpga_image_info {
 	u32 disable_timeout_us;
 	u32 config_complete_timeout_us;
 	char *firmware_name;
+	char *encrypted_key_name;
 	struct sg_table *sgt;
 	const char *buf;
 	size_t count;
@@ -172,6 +177,9 @@ struct fpga_manager_ops {
 	bool skip_header;
 	enum fpga_mgr_states (*state)(struct fpga_manager *mgr);
 	u64 (*status)(struct fpga_manager *mgr);
+	int (*parse_aes_key)(struct fpga_manager *mgr,
+			     struct fpga_image_info *info,
+			     const char *buf, size_t count);
 	int (*parse_header)(struct fpga_manager *mgr,
 			    struct fpga_image_info *info,
 			    const char *buf, size_t count);
-- 
2.25.1




More information about the linux-arm-kernel mailing list