clear-pkgs-linux-iot-lts2018/0027-rpmb-add-nvme-rpmb-fra...

165 lines
5.6 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Tomas Winkler <tomas.winkler@intel.com>
Date: Sat, 28 Apr 2018 22:01:32 +0300
Subject: [PATCH] rpmb: add nvme rpmb frame type
The NVMe RPMB frame differs in layout and endianity
from the one defined by JDEC.
Change-Id: Ifae77454e1bc8733eb1e5bcb2146dc198f94151d
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
drivers/char/rpmb/cdev.c | 26 ++++++++++++++++++-------
include/uapi/linux/rpmb.h | 41 +++++++++++++++++++++++++++++++++++++++
2 files changed, 60 insertions(+), 7 deletions(-)
diff --git a/drivers/char/rpmb/cdev.c b/drivers/char/rpmb/cdev.c
index bdac3894b111..028c7ecd2ac7 100644
--- a/drivers/char/rpmb/cdev.c
+++ b/drivers/char/rpmb/cdev.c
@@ -67,18 +67,28 @@ static int rpmb_release(struct inode *inode, struct file *fp)
return 0;
}
+static size_t rpmb_ioc_frames_len(struct rpmb_dev *rdev, size_t nframes)
+{
+ if (rdev->ops->type == RPMB_TYPE_NVME)
+ return rpmb_ioc_frames_len_nvme(nframes);
+ else
+ return rpmb_ioc_frames_len_jdec(nframes);
+}
+
/**
* rpmb_cmd_copy_from_user - copy rpmb command from the user space
*
+ * @rdev: rpmb device
* @cmd: internal cmd structure
* @ucmd: user space cmd structure
*
* Return: 0 on success, <0 on error
*/
-static int rpmb_cmd_copy_from_user(struct rpmb_cmd *cmd,
+static int rpmb_cmd_copy_from_user(struct rpmb_dev *rdev,
+ struct rpmb_cmd *cmd,
struct rpmb_ioc_cmd __user *ucmd)
{
- struct rpmb_frame *frames;
+ void *frames;
u64 frames_ptr;
if (get_user(cmd->flags, &ucmd->flags))
@@ -95,7 +105,7 @@ static int rpmb_cmd_copy_from_user(struct rpmb_cmd *cmd,
return -EFAULT;
frames = memdup_user(u64_to_user_ptr(frames_ptr),
- rpmb_ioc_frames_len_jdec(cmd->nframes));
+ rpmb_ioc_frames_len(rdev, cmd->nframes));
if (IS_ERR(frames))
return PTR_ERR(frames);
@@ -106,12 +116,14 @@ static int rpmb_cmd_copy_from_user(struct rpmb_cmd *cmd,
/**
* rpmb_cmd_copy_to_user - copy rpmb command to the user space
*
+ * @rdev: rpmb device
* @ucmd: user space cmd structure
* @cmd: internal cmd structure
*
* Return: 0 on success, <0 on error
*/
-static int rpmb_cmd_copy_to_user(struct rpmb_ioc_cmd __user *ucmd,
+static int rpmb_cmd_copy_to_user(struct rpmb_dev *rdev,
+ struct rpmb_ioc_cmd __user *ucmd,
struct rpmb_cmd *cmd)
{
u64 frames_ptr;
@@ -121,7 +133,7 @@ static int rpmb_cmd_copy_to_user(struct rpmb_ioc_cmd __user *ucmd,
/* some archs have issues with 64bit get_user */
if (copy_to_user(u64_to_user_ptr(frames_ptr), cmd->frames,
- rpmb_ioc_frames_len_jdec(cmd->nframes)))
+ rpmb_ioc_frames_len(rdev, cmd->nframes)))
return -EFAULT;
return 0;
@@ -167,7 +179,7 @@ static long rpmb_ioctl_seq_cmd(struct rpmb_dev *rdev,
ucmds = (struct rpmb_ioc_cmd __user *)ptr->cmds;
for (i = 0; i < ncmds; i++) {
- ret = rpmb_cmd_copy_from_user(&cmds[i], &ucmds[i]);
+ ret = rpmb_cmd_copy_from_user(rdev, &cmds[i], &ucmds[i]);
if (ret)
goto out;
}
@@ -177,7 +189,7 @@ static long rpmb_ioctl_seq_cmd(struct rpmb_dev *rdev,
goto out;
for (i = 0; i < ncmds; i++) {
- ret = rpmb_cmd_copy_to_user(&ucmds[i], &cmds[i]);
+ ret = rpmb_cmd_copy_to_user(rdev, &ucmds[i], &cmds[i]);
if (ret)
goto out;
}
diff --git a/include/uapi/linux/rpmb.h b/include/uapi/linux/rpmb.h
index d304701cd258..f41a28ea9765 100644
--- a/include/uapi/linux/rpmb.h
+++ b/include/uapi/linux/rpmb.h
@@ -68,6 +68,44 @@ struct rpmb_frame_jdec {
(sizeof(struct rpmb_frame_jdec) - \
offsetof(struct rpmb_frame_jdec, data))
+/**
+ * struct rpmb_frame_nvme - rpmb frame as defined by specs
+ *
+ * @key_mac : The authentication key or the message authentication
+ * code (MAC) depending on the request/response type.
+ * The MAC will be delivered in the last (or the only)
+ * block of data.
+ * @rpmb_target : RPMB target to access.
+ * @nonce : Random number generated by the host for the requests
+ * and copied to the response by the RPMB engine.
+ * @write_counter: Counter value for the total amount of the successful
+ * authenticated data write requests made by the host.
+ * @addr : Address of the data to be programmed to or read
+ * from the RPMB. Address is the serial number of
+ * the accessed block (half sector 256B).
+ * @block_count : Number of sctors (sectors, 512B) requested to be
+ * read/programmed. (In spec this field is named sector_count).
+ * @result : Includes information about the status of the write counter
+ * (valid, expired) and result of the access made to the RPMB.
+ * @req_resp : Defines the type of request and response to/from the memory.
+ * @data : variable sized payload 512 * block_count
+ */
+struct rpmb_frame_nvme {
+ __u8 key_mac[223];
+ __u8 rpmb_target;
+ __u8 nonce[16];
+ __le32 write_counter;
+ __le32 addr;
+ __le32 block_count;
+ __le16 result;
+ __le16 req_resp;
+ __u8 data[0];
+} __attribute__((packed));
+
+#define rpmb_nvme_hmac_data_len \
+ (sizeof(struct rpmb_frame_nvme) - \
+ offsetof(struct rpmb_frame_nvme, rpmb_target))
+
#define RPMB_PROGRAM_KEY 0x0001 /* Program RPMB Authentication Key */
#define RPMB_GET_WRITE_COUNTER 0x0002 /* Read RPMB write counter */
#define RPMB_WRITE_DATA 0x0003 /* Write data to RPMB partition */
@@ -142,6 +180,9 @@ struct rpmb_ioc_cmd {
#define rpmb_ioc_frames_len_jdec(_n) \
(((_n) ?: 1) * sizeof(struct rpmb_frame_jdec))
+#define rpmb_ioc_frames_len_nvme(_n) \
+ (sizeof(struct rpmb_frame_nvme) + (_n) * 512)
+
/**
* struct rpmb_ioc_seq_cmd - rpmb command sequence
*
--
https://clearlinux.org