From 447da1297977eec3d58507f4447581e6e86953e3 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Sat, 28 Apr 2018 22:01:32 +0300 Subject: [PATCH 027/728] 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 --- 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 * -- 2.19.2