diff mbox series

[09/10] mmc-utils: Secure Write Protect Mode Read

Message ID 20250407082833.108616-10-avri.altman@sandisk.com
State New
Headers show
Series mmc-utils: Secure Write Protect Mode Enhancements | expand

Commit Message

Avri Altman April 7, 2025, 8:28 a.m. UTC
From: Avri Altman <avri.altman@wdc.com>

Reads the status of the secure write protect mode.  Specifically, it
returns the values of SECURE_WP_MODE_ENABLE and SECURE_WP_MODE_CONFIG
registers.  Those registers are available via rpmb Authenticated Device
Configuration Read request.

Signed-off-by: Avri Altman <avri.altman@wdc.com>
---
 mmc.c      | 11 +++++++
 mmc_cmds.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 mmc_cmds.h |  1 +
 3 files changed, 96 insertions(+)
diff mbox series

Patch

diff --git a/mmc.c b/mmc.c
index 578b00c..36cfe90 100644
--- a/mmc.c
+++ b/mmc.c
@@ -240,6 +240,17 @@  static struct Command commands[] = {
 		  "    mmc rpmb secure-wp-enable /dev/block/mmcblk0 /dev/mmcblk0rpmb -",
 	  NULL
 	},
+	{ do_rpmb_sec_wp_en_read, -2,
+	  "rpmb secure-wp-en-read", "<device> <rpmb device> [key file]\n"
+		  "Reads the status of the SECURE_WP_EN & SECURE_WP_MASK fields.\n"
+		  "You can specify '-' instead of key\n"
+		  "Example:\n"
+		  "    echo -n AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHH | \\\n"
+		  "    mmc rpmb secure-wp-en-read /dev/mmcblk0 /dev/mmcblk0rpmb -\n"
+		  "or read without verification\n"
+		  "  $ mmc rpmb secure-wp-en-read /dev/mmcblk0 /dev/mmcblk0rpmb",
+	  NULL
+	},
 	{ do_cache_en, -1,
 	  "cache enable", "<device>\n"
 		"Enable the eMMC cache feature on <device>.\n"
diff --git a/mmc_cmds.c b/mmc_cmds.c
index 2ef4252..d7e4bca 100644
--- a/mmc_cmds.c
+++ b/mmc_cmds.c
@@ -2100,6 +2100,7 @@  enum rpmb_op_type {
 	MMC_RPMB_WRITE     = 0x03,
 	MMC_RPMB_READ      = 0x04,
 	MMC_RPMB_CONF_WRITE = 0x06,
+	MMC_RPMB_CONF_READ = 0x07,
 
 	/* For internal usage only, do not use it directly */
 	MMC_RPMB_READ_RESP = 0x05
@@ -2237,6 +2238,7 @@  static int do_rpmb_op(int fd, const struct rpmb_frame *frame_in,
 
 		break;
 	case MMC_RPMB_READ_CNT:
+	case MMC_RPMB_CONF_READ:
 		if (out_cnt != 1) {
 			err = -EINVAL;
 			goto out;
@@ -2588,6 +2590,81 @@  out:
 	return ret;
 }
 
+static int rpmb_auth_read(int nargs, char **argv, char *usage)
+{
+	int ret, dev_fd;
+	struct rpmb_frame frame_in = {
+		.req_resp    = htobe16(MMC_RPMB_CONF_READ),
+	}, frame_out = {};
+	unsigned char key[32] = {};
+
+	if (nargs != 3 && nargs != 4) {
+		fprintf(stderr, "%s", usage);
+		return EXIT_FAILURE;
+	}
+
+	if (!secure_wp_supported(argv[1])) {
+		fprintf(stderr, "secure wp not supported %s", argv[1]);
+		return EXIT_FAILURE;
+	}
+
+	dev_fd = open(argv[2], O_RDWR);
+	if (dev_fd < 0) {
+		perror("device open");
+		return EXIT_FAILURE;
+	}
+
+	if (nargs == 4) {
+		ret = rpmb_get_key(argv[3], &frame_in, key, false);
+		if (ret) {
+			printf("failed to read and apply key %d\n", ret);
+			goto out;
+		}
+	}
+
+	/* Execute RPMB op */
+	ret = do_rpmb_op(dev_fd, &frame_in, &frame_out, 1);
+	if (ret != 0) {
+		perror("RPMB ioctl failed");
+		goto out;
+	}
+
+	/* Check RPMB response */
+	if (frame_out.result != 0) {
+		printf("RPMB operation failed, retcode 0x%04x\n", be16toh(frame_out.result));
+		goto out;
+	}
+
+	close(dev_fd);
+
+	/* verify data against key */
+	if (nargs == 4) {
+		unsigned char mac[32] = {};
+		hmac_sha256_ctx ctx;
+
+		hmac_sha256_init(&ctx, key, sizeof(key));
+		hmac_sha256_update(&ctx, frame_out.data,
+				   sizeof(frame_out) - offsetof(struct rpmb_frame, data));
+
+		hmac_sha256_final(&ctx, mac, sizeof(mac));
+
+		/* Compare calculated MAC and MAC from last frame */
+		if (memcmp(mac, frame_out.key_mac, sizeof(mac))) {
+			printf("RPMB MAC mismatch\n");
+			return EXIT_FAILURE;
+		}
+	}
+
+	printf("SECURE_WP_MODE_ENABLE: 0x%02x]\n", frame_out.data[255]);
+	printf("SECURE_WP_MODE_CONFIG: 0x%02x]\n", frame_out.data[254]);
+
+	return 0;
+
+out:
+	close(dev_fd);
+	return ret;
+}
+
 int do_rpmb_sec_wp_enable(int nargs, char **argv)
 {
 	char *usage = "Usage: mmc rpmb secure-wp-mode-on </path/to/mmcblkx> </path/to/mmcblkXrpmb> </path/to/key>\n";
@@ -2616,6 +2693,13 @@  int do_rpmb_sec_wp_mode_clear(int nargs, char **argv)
 	return rpmb_auth_write(nargs, argv, 2, 0, usage);
 }
 
+int do_rpmb_sec_wp_en_read(int nargs, char **argv)
+{
+	char *usage = "Usage: mmc rpmb secure-wp-enable-read <path/to/mmcblk0> </path/to/mmcblkXrpmb> [/path/to/key]\n";
+
+	return rpmb_auth_read(nargs, argv, usage);
+}
+
 int do_rpmb_write_block(int nargs, char **argv)
 {
 	int ret, dev_fd, data_fd;
diff --git a/mmc_cmds.h b/mmc_cmds.h
index 61fe337..d83fb57 100644
--- a/mmc_cmds.h
+++ b/mmc_cmds.h
@@ -43,6 +43,7 @@  int do_rpmb_sec_wp_enable(int nargs, char **argv);
 int do_rpmb_sec_wp_disable(int nargs, char **argv);
 int do_rpmb_sec_wp_mode_set(int nargs, char **argv);
 int do_rpmb_sec_wp_mode_clear(int nargs, char **argv);
+int do_rpmb_sec_wp_en_read(int nargs, char **argv);
 int do_cache_en(int nargs, char **argv);
 int do_cache_dis(int nargs, char **argv);
 int do_ffu(int nargs, char **argv);