Skip to contentSkip to conversation

Add password protected lock/unlock support for SD/MMC

PATCH RESEND In review Al Cooper 3 participants 14 messages Jun 5, 2015 – Sep 1, 2015 MMC, SD and SDIO

lore
Share & tools
lore

Al Cooper

author
#0 lore raw

v3 cover Add password protected lock/unlock support for SD/MMC

This set of patches adds support for password protected locking and unlocking of MMC and SD devices. It uses the LOCK/UNLOCK command (CMD42) available in both the MMC and SD command sets.

Some of this code was based on a patch set submitted in 2006 by Anderson Briglia "Add MMC Password Protection (lock/unlock)". This patch set never made it into mainline.

By default, a card with no password assigned is always in "unlocked" state. After password assignment, in the next power cycle the card switches to a "locked" state where only the "basic" and "lock card" command classes are accepted by the card. Only after unlocking it with the correct password can the card be used for normal operations like block I/O.

Password management and caching is done through the "Kernel Key Retention Service" mechanism and the sysfs filesystem. Two new sysfs attributes were added. The "lock" attribute is used to lock, unlock, assign a password, clear a password and force erase a card. The "unlock_retry" attribute is used to retry an unlock that failed during boot because the rootfs was not yet available with the password.

The user space software needed to test this new feature is available on GitHub at:
https://github.com/alcooper/mmc-password-utils
See the README for a detailed description of the user space layer and how to use this feature.

Changed for V3:
- Ported the V2 patch set submitted Aug. 2013 to the latest mainline

    (v4.1-rc4).

- Created a GitHub project for the user space layer.
- Change the lock command (CMD42) to round up the data buffer size to 512 for SD but leave exact size for eMMC based on the SD and eMMC specs.

Changed for V2:
The V2 changes were not functional and were just general cleanup.
- Use stub functions to reduce the number of CONFIG ifdefs.
- Add static to a few functions that were local.
- Use pr_warn instead of pr_warning.
- Improve a few variable names and messages.

Abbas Raza (1):
According to SD Physical Layer Specifications: Locked cards respond to
(and execute) all commands in the "basic" command class (class 0), ACMD41, CMD16 and "lock card" command class. Thus, the host is allowed to reset, initialize, select, query for status, etc., but not to access data on the card.

Al Cooper (7):
mmc: lock: Use the kernel "KEYS" subsystem to get a card's password
mmc: lock: Add low level LOCK_UNLOCK command
mmc: lock: Add function to unlock a password locked card
mmc: lock: Add card lock/unlock maintenance commands
mmc: lock: Change SD init functionality to handle locked SD cards
mmc: lock: Prevent partition table read for locked cards.
mmc: lock: Change MMC init to handle locked cards.

 drivers/mmc/card/block.c   |  14 ++++
 drivers/mmc/core/Kconfig   |   8 +++
 drivers/mmc/core/core.c    | 120 +++++++++++++++++++++++++++++++++
 drivers/mmc/core/core.h    |  14 +++-
 drivers/mmc/core/mmc.c     | 123 ++++++++++++++++++++++++++++++++++
 drivers/mmc/core/mmc_ops.c | 150 +++++++++++++++++++++++++++++++++++++++++
 drivers/mmc/core/mmc_ops.h |  13 ++++
 drivers/mmc/core/sd.c      | 161 +++++++++++++++++++++++++++++++--------------
 include/linux/mmc/card.h   |   6 ++
 9 files changed, 560 insertions(+), 49 deletions(-)
Signature · 1 line
1.9.0.138.g2de3478
author
#1 lore raw

PATCH v3 1/8 mmc: lock: Use the kernel "KEYS" subsystem to get a card's password

Use the kernel "KEYS" subsystem to get a password for a card based on the card's CID. This code was based on a patch set submitted by Anderson Briglia in 2006.

---
 drivers/mmc/core/Kconfig |  8 ++++
 drivers/mmc/core/core.c  | 97 ++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/mmc/core/core.h  | 10 ++++-
 3 files changed, 114 insertions(+), 1 deletion(-)
drivers/mmc/core/Kconfig +8 -0
index 9ebee72..1d073cd 100644
@@ -11,3 +11,11 @@ config MMC_CLKGATE
 	  support handling this in order for it to be of any use.
 
 	  If unsure, say N.
+
+config MMC_LOCK
+	bool "MMC/SD password based card lock/unlock"
+	select KEYS
+	help
+	  This will add the ability to lock/unlock SD and MMC cards.
+
+	  If unsure, say N.
drivers/mmc/core/core.c +97 -0

123 lines not on this page · raw message

drivers/mmc/core/core.h +9 -1
index cfba3c0..b91bc3e 100644
@@ -89,5 +89,13 @@ void mmc_init_context_info(struct mmc_host *host);
 
 int mmc_execute_tuning(struct mmc_card *card);
 
-#endif
+/* Lock/Unlock functionality */
+#define MMC_PASSWORD_MAX 16
+struct mmc_password {
+	char password[MMC_PASSWORD_MAX];
+	int length;
+};
+int mmc_unlock_card(struct mmc_card *card);
+int mmc_get_password(struct mmc_card *card, struct mmc_password *password);
 
+#endif
Signature · 1 line
1.9.0.138.g2de3478
author
#2 lore raw

PATCH v3 2/8 mmc: lock: Add low level LOCK_UNLOCK command

In reply to Al Cooper

Add support for the LOCK_UNLOCK command. This command can lock, unlock, set password, clear password and force erase SD and MMC cards.

---
 drivers/mmc/core/core.c    |   5 +-
 drivers/mmc/core/mmc_ops.c | 150 +++++++++++++++++++++++++++++++++++++++++++++
 drivers/mmc/core/mmc_ops.h |  13 ++++
 include/linux/mmc/card.h   |   5 ++
 4 files changed, 169 insertions(+), 4 deletions(-)
drivers/mmc/core/core.c +1 -4
index f7d7ad9..4b0d26e 100644
@@ -2716,11 +2716,8 @@ static int mmc_key_instantiate(struct key *key,
 	char *payload;
 
 	if (prep->datalen <= 0 || prep->datalen > MMC_PASSWORD_MAX ||
-	    !prep->data) {
-		pr_warn("Invalid data\n");
+	    !prep->data)
 		return  -EINVAL;
-	}
-
 	payload = kmalloc(prep->datalen, GFP_KERNEL);
 	if (!payload)
 		return -ENOMEM;
drivers/mmc/core/mmc_ops.c +150 -0

159 lines not on this page · raw message

drivers/mmc/core/mmc_ops.h +13 -0
index 6f4b00e..92c9790 100644
@@ -12,6 +12,15 @@
 #ifndef _MMC_MMC_OPS_H
 #define _MMC_MMC_OPS_H
 
+/*
+ * MMC_LOCK_UNLOCK modes
+ */
+#define MMC_LOCK_MODE_ERASE	(1<<3)
+#define MMC_LOCK_MODE_LOCK	(1<<2)
+#define MMC_LOCK_MODE_UNLOCK	(0<<2)
+#define MMC_LOCK_MODE_CLR_PWD	(1<<1)
+#define MMC_LOCK_MODE_SET_PWD	(1<<0)
+
 int mmc_select_card(struct mmc_card *card);
 int mmc_deselect_cards(struct mmc_host *host);
 int mmc_set_dsr(struct mmc_host *host);
@@ -27,6 +36,10 @@ int mmc_spi_set_crc(struct mmc_host *host, int use_crc);
 int mmc_bus_test(struct mmc_card *card, u8 bus_width);
 int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status);
 int mmc_can_ext_csd(struct mmc_card *card);
+#ifdef CONFIG_MMC_LOCK
+int mmc_lock_unlock(struct mmc_card *card, struct mmc_password *password,
+		    int mode);
+#endif
 
 #endif
 
include/linux/mmc/card.h +5 -0
index 19f0175..0c510b4 100644
@@ -262,6 +262,7 @@ struct mmc_card {
 #define MMC_CARD_REMOVED	(1<<4)		/* card has been removed */
 #define MMC_STATE_DOING_BKOPS	(1<<5)		/* card is doing BKOPS */
 #define MMC_STATE_SUSPENDED	(1<<6)		/* card is suspended */
+#define MMC_STATE_LOCKED	(1<<7)		/* card is currently locked */
 	unsigned int		quirks; 	/* card quirks */
 #define MMC_QUIRK_LENIENT_FN0	(1<<0)		/* allow SDIO FN0 writes outside of the VS CCCR range */
 #define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1)	/* use func->cur_blksize */
@@ -427,6 +428,8 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)
 #define mmc_card_removed(c)	((c) && ((c)->state & MMC_CARD_REMOVED))
 #define mmc_card_doing_bkops(c)	((c)->state & MMC_STATE_DOING_BKOPS)
 #define mmc_card_suspended(c)	((c)->state & MMC_STATE_SUSPENDED)
+#define mmc_card_locked(c)	((c)->state & MMC_STATE_LOCKED)
+#define mmc_card_lockable(c)	((c)->csd.cmdclass & CCC_LOCK_CARD)
 
 #define mmc_card_set_present(c)	((c)->state |= MMC_STATE_PRESENT)
 #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
@@ -437,6 +440,8 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)
 #define mmc_card_clr_doing_bkops(c)	((c)->state &= ~MMC_STATE_DOING_BKOPS)
 #define mmc_card_set_suspended(c) ((c)->state |= MMC_STATE_SUSPENDED)
 #define mmc_card_clr_suspended(c) ((c)->state &= ~MMC_STATE_SUSPENDED)
+#define mmc_card_set_locked(c)	((c)->state |= MMC_STATE_LOCKED)
+#define mmc_card_clear_locked(c) ((c)->state &= ~MMC_STATE_LOCKED)
 
 /*
  * Quirk add/remove for MMC products.
Signature · 1 line
1.9.0.138.g2de3478
author
#3 lore raw

PATCH v3 3/8 mmc: lock: Add function to unlock a password locked card

In reply to Al Cooper

This function will try to get a password for the card and use the password to unlock it. It will leave the card state flag set appropriately.

---
 drivers/mmc/core/core.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)
drivers/mmc/core/core.c +26 -0
index 4b0d26e..61f1f78 100644
@@ -2777,6 +2777,27 @@ static inline void mmc_unregister_key_type(void)
 	unregister_key_type(&key_type_mmc);
 }
 
+int mmc_unlock_card(struct mmc_card *card)
+{
+	int stat;
+	struct mmc_password password;
+
+	mmc_card_set_locked(card);
+	stat = mmc_get_password(card, &password);
+	if (stat) {
+		pr_warn("%s: Cannot find matching key\n",
+			mmc_hostname(card->host));
+		return stat;
+	}
+	stat = mmc_lock_unlock(card, &password, MMC_LOCK_MODE_UNLOCK);
+	if (stat)
+		pr_warn("%s: Password failed to unlock card\n",
+			mmc_hostname(card->host));
+	else
+		mmc_card_clear_locked(card);
+	return stat;
+}
+
 #else /* CONFIG_MMC_LOCK */
 
 int mmc_get_password(struct mmc_card *card, struct mmc_password *password)
@@ -2793,6 +2814,11 @@ static inline void mmc_unregister_key_type(void)
 {
 }
 
+int mmc_unlock_card(struct mmc_card *card)
+{
+	return -ENOKEY;
+}
+
 #endif /* CONFIG_MMC_LOCK */
 
 static int __init mmc_init(void)
Signature · 1 line
1.9.0.138.g2de3478
author
#4 lore raw

PATCH v3 4/8 mmc: lock: Add card lock/unlock maintenance commands

In reply to Al Cooper

Create a sysfs interface that allows a user to manage an inserted cards lock state. The sysfs attribute "lock" will be added to the device's sysfs directory. The following commands are supported:
"setpw" - Set the cards password
"clearpw" - Clear the cards password

"lock"    - Lock the card
"unlock"  - Unlock the card
"erase"   - Force erase the card, clear the password and unlock it

Commands that require a password will request the password through the kernels KEYS subsystem.

---
 drivers/mmc/core/mmc.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 81 insertions(+)
drivers/mmc/core/mmc.c +81 -0
index f36c76f..8e94eb8 100644
@@ -697,6 +697,84 @@ static int mmc_compare_ext_csds(struct mmc_card *card, unsigned bus_width)
 	return err;
 }
 
+#ifdef CONFIG_MMC_LOCK
+
+ssize_t mmc_lock_show(struct device *dev, struct device_attribute *att,
+			  char *buf)
+{
+	struct mmc_card *card = mmc_dev_to_card(dev);
+
+	if (!mmc_card_lockable(card))
+		return sprintf(buf, "unsupported\n");
+	else
+		return sprintf(buf, "%slocked\n", mmc_card_locked(card) ?
+			       "" : "un");
+}
+
+
+static struct lock_cmd {
+	const char *name;
+	int io_cmd;
+	int locked_required;
+	int need_pw;
+} lock_cmds[] = {
+	{ "erase", MMC_LOCK_MODE_ERASE,  true,  false },
+	{ "clrpw", MMC_LOCK_MODE_CLR_PWD, false, true },
+	{ "setpw", MMC_LOCK_MODE_SET_PWD, false, true },
+	{ "lock", MMC_LOCK_MODE_LOCK, false,  true },
+	{ "unlock", MMC_LOCK_MODE_UNLOCK, true,  true },
+};
+
+/*
+ * implement MMC password functions: force erase, set password,
+ * clear password, lock and unlock.
+ */
+ssize_t mmc_lock_store(struct device *dev, struct device_attribute *att,
+			   const char *data, size_t len)
+{
+	struct mmc_card *card = mmc_dev_to_card(dev);
+	int res = -EINVAL;
+	int x;
+	struct mmc_password password;
+
+	mmc_claim_host(card->host);
+	if (!mmc_card_lockable(card))
+		goto out;
+	for (x = 0; x < ARRAY_SIZE(lock_cmds); x++) {
+		if (sysfs_streq(data, lock_cmds[x].name))
+			break;
+	}
+	if (x >= ARRAY_SIZE(lock_cmds))
+		goto out;
+
+	if ((lock_cmds[x].locked_required && !mmc_card_locked(card)) ||
+	    (!lock_cmds[x].locked_required && mmc_card_locked(card))) {
+		dev_warn(dev, "%s requires %slocked card\n",
+			 lock_cmds[x].name,
+			 lock_cmds[x].locked_required ? "" : "un");
+		goto out;
+	}
+	if (lock_cmds[x].need_pw) {
+		res = mmc_get_password(card, &password);
+		if (res)
+			goto out;
+	}
+	res = mmc_lock_unlock(card, &password, lock_cmds[x].io_cmd);
+out:
+	mmc_release_host(card->host);
+	if (res == 0)
+		return len;
+	else
+		return res;
+}
+
+static DEVICE_ATTR(lock, S_IWUSR | S_IRUGO,
+		   mmc_lock_show, mmc_lock_store);
+
+
+#endif /* CONFIG_MMC_LOCK */
+
+
 MMC_DEV_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1],
 	card->raw_cid[2], card->raw_cid[3]);
 MMC_DEV_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1],
@@ -751,6 +829,9 @@ static struct attribute *mmc_std_attrs[] = {
 	&dev_attr_enhanced_area_size.attr,
 	&dev_attr_raw_rpmb_size_mult.attr,
 	&dev_attr_rel_sectors.attr,
+#ifdef CONFIG_MMC_LOCK
+	&dev_attr_lock.attr,
+#endif /* CONFIG_MMC_LOCK */
 	NULL,
 };
 ATTRIBUTE_GROUPS(mmc_std);
Signature · 1 line
1.9.0.138.g2de3478
author
#5 lore raw

PATCH v3 5/8 mmc: lock: Change SD init functionality to handle locked SD cards

In reply to Al Cooper

- Change mmc_sd_init_card() to check for a locked card and, if found, try to get a password using the kernel KEYS subsystem, unlock the card and continue. The unlock can fail due to a bad password, no password or during boot when the rootfs that holds the password is not yet available. To handle this, mmc_sd_init_card() will send just the early init commands before trying to unlock and, on unlock failure, skip the later init commands (which would fail on a locked card). mmc_sd_init_card() will also handle the retry case, trigger via sysfs, where it will skip the already issued early init commands, try again to unlock the card and if successful issue the previously skipped later init commands. These changes allow a card that failed unlock to still come up to the point that the block device and sysfs for the device is created. This allows the sysfs to be used to issue LOCK maintenance commands or to trigger a retry, presumably after the password has be made available by user space.

- Add sysfs attribute "unlock_retry" that will try again to unlock and fully init the card.

- Add sysfs attribute "lock" to enable sysfs LOCK maintenance commands

---
 drivers/mmc/core/core.h  |   4 ++
 drivers/mmc/core/sd.c    | 161 +++++++++++++++++++++++++++++++++--------------
 include/linux/mmc/card.h |   1 +
 3 files changed, 118 insertions(+), 48 deletions(-)
drivers/mmc/core/core.h +4 -0
index b91bc3e..6b9c972 100644
@@ -97,5 +97,9 @@ struct mmc_password {
 };
 int mmc_unlock_card(struct mmc_card *card);
 int mmc_get_password(struct mmc_card *card, struct mmc_password *password);
+ssize_t mmc_lock_show(struct device *dev, struct device_attribute *att,
+		char *buf);
+ssize_t mmc_lock_store(struct device *dev, struct device_attribute *att,
+		const char *data, size_t len);
 
 #endif
drivers/mmc/core/sd.c +113 -48

206 lines not on this page · raw message

include/linux/mmc/card.h +1 -0
index 0c510b4..38d5572 100644
@@ -288,6 +288,7 @@ struct mmc_card {
 	u32			raw_cid[4];	/* raw card CID */
 	u32			raw_csd[4];	/* raw card CSD */
 	u32			raw_scr[2];	/* raw card SCR */
+	u32			raw_ocr;	/* raw card OCR */
 	struct mmc_cid		cid;		/* card identification */
 	struct mmc_csd		csd;		/* card specific */
 	struct mmc_ext_csd	ext_csd;	/* mmc v4 extended card specific */
Signature · 1 line
1.9.0.138.g2de3478
author
#6 lore raw

PATCH v3 6/8 mmc: lock: Prevent partition table read for locked cards.

In reply to Al Cooper

Change the MMC block layer to avoid reading the partition table when the card is locked because read commands will fail.

---
 drivers/mmc/card/block.c | 7 +++++++
 1 file changed, 7 insertions(+)
drivers/mmc/card/block.c +7 -0
index 60f7141..5650748 100644
@@ -2147,6 +2147,13 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
 		md->disk->flags |= GENHD_FL_NO_PART_SCAN;
 
 	/*
+	 * If the card is locked, reads will fail so prevent partition
+	 * table scan
+	 */
+	if (mmc_card_locked(card))
+		md->disk->flags |= GENHD_FL_NO_PART_SCAN;
+
+	/*
 	 * As discussed on lkml, GENHD_FL_REMOVABLE should:
 	 *
 	 * - be set for removable media with permanent block devices
Signature · 1 line
1.9.0.138.g2de3478
author
#7 lore raw

PATCH v3 7/8 mmc: lock: Change MMC init to handle locked cards.

In reply to Al Cooper

- Change mmc_init_card() to check for a locked card and, if found, try to get a password using the kernel KEYS subsystem, unlock the card and continue. Unlike SD cards, MMC cards support all initialization commands when locked so the init sequence can be completed on a locked card and the card can be used without further init after being unlocked. If the unlock fails, the card state will be marked as "locked" which will prevent the block layer from reading the partition table.

- Add sysfs attribute "unlock_retry" that will try again to unlock the card. If the unlock succeeds, the cards "locked" state will be cleared and the block layer restarted which will now read the partition table.

---
 drivers/mmc/core/mmc.c | 46 ++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 44 insertions(+), 2 deletions(-)
drivers/mmc/core/mmc.c +44 -2
index 8e94eb8..2c953c5 100644
@@ -768,10 +768,37 @@ out:
 		return res;
 }
 
-static DEVICE_ATTR(lock, S_IWUSR | S_IRUGO,
-		   mmc_lock_show, mmc_lock_store);
+static ssize_t mmc_unlock_retry_store(struct device *dev,
+				      struct device_attribute *att,
+				      const char *data, size_t len)
+{
+	struct mmc_card *card = mmc_dev_to_card(dev);
+	struct mmc_host *host = card->host;
+	int err;
 
+	BUG_ON(!card);
+	BUG_ON(!host);
 
+	mmc_claim_host(host);
+	if (!mmc_card_locked(card)) {
+		mmc_release_host(host);
+		return len;
+	}
+	err = mmc_unlock_card(card);
+	mmc_release_host(host);
+	if (err < 0)
+		return err;
+	device_release_driver(dev);
+	err = device_attach(dev);
+	if (err < 0)
+		return err;
+	return len;
+}
+
+static DEVICE_ATTR(lock, S_IWUSR | S_IRUGO,
+		   mmc_lock_show, mmc_lock_store);
+static DEVICE_ATTR(unlock_retry, S_IWUSR,
+		   NULL, mmc_unlock_retry_store);
 #endif /* CONFIG_MMC_LOCK */
 
 
@@ -831,6 +858,7 @@ static struct attribute *mmc_std_attrs[] = {
 	&dev_attr_rel_sectors.attr,
 #ifdef CONFIG_MMC_LOCK
 	&dev_attr_lock.attr,
+	&dev_attr_unlock_retry.attr,
 #endif /* CONFIG_MMC_LOCK */
 	NULL,
 };
@@ -1279,6 +1307,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 	int err;
 	u32 cid[4];
 	u32 rocr;
+	u32 status;
 
 	BUG_ON(!host);
 	WARN_ON(!host->claimed);
@@ -1568,6 +1597,19 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 		}
 	}
 
+	/* If card is locked, try to unlock it */
+	err = mmc_send_status(card, &status);
+	if (err)
+		goto free_card;
+	if (status & R1_CARD_IS_LOCKED) {
+		pr_info("%s: card is locked.\n", mmc_hostname(card->host));
+		err = mmc_unlock_card(card);
+		if (err != 0) {
+			pr_warn("%s: Card unlock failed.\n",
+				mmc_hostname(card->host));
+		}
+	}
+
 	if (!oldcard)
 		host->card = card;
 
Signature · 1 line
1.9.0.138.g2de3478
author
#8 lore raw

PATCH v3 8/8 According to SD Physical Layer Specifications: Locked cards respond to (and execute) all commands in the "basic" command class (class 0), ACMD41, CMD16 and "lock card" command class. Thus, the host is allowed to reset, initialize, select, query for status, etc., but not to access data on the card.

In reply to Al Cooper

From: Abbas Raza <[email protected]>

But when a locked card is inserted into system having no key added for this card, following errors are observed until the card is removed

[   36.955193] mmc0: card is locked.
[   36.959746] mmc (null): Error, request_key -2
[   36.964622] mmc0: Cannot find matching key
[   36.968765] mmc0: Card unlock failed.
[   36.972717] mmc0: new SDHC card at address 0002
[   36.977747] mmcblk0: mmc0:0002 00000 7.41 GiB
[   36.989596] mmcblk0: timed out sending r/w cmd command, card status 0x2400900
[   36.999630] mmcblk0: timed out sending r/w cmd command, card status 0x2400900
[   37.009604] mmcblk0: timed out sending r/w cmd command, card status 0x2400900
[   37.019574] mmcblk0: timed out sending r/w cmd command, card status 0x2400900
[   37.029548] mmcblk0: timed out sending r/w cmd command, card status 0x2400900
[   37.039514] mmcblk0: timed out sending r/w cmd command, card status 0x2400900
[   37.046729] end_request: I/O error, dev mmcblk0, sector 15556480
[   37.052813] Buffer I/O error on device mmcblk0, logical block 1944560
[   37.062139] mmcblk0: timed out sending r/w cmd command, card status 0x2400900
[   37.072106] mmcblk0: timed out sending r/w cmd command, card status 0x2400900
[   37.082072] mmcblk0: timed out sending r/w cmd command, card status 0x2400900
.............
[   46.249273] mmcblk0: timed out sending r/w cmd command, card status 0x2400900
[   46.259247] mmcblk0: timed out sending r/w cmd command, card status 0x2400900
[   46.269215] mmcblk0: timed out sending r/w cmd command, card status 0x2400900
[   46.279183] mmcblk0: timed out sending r/w cmd command, card status 0x2400900
[   46.289151] mmcblk0: timed out sending r/w cmd command, card status 0x2400900

As a workaround, skip all the regular block io operations if the card is locked. One can unlock the card after system boot by following below steps
1) Add key for this card.
2) Unlock the card using sysfs attribute 'unlock_retry' for this card.

Cc Al Cooper <[email protected]>
Cc Chris Ball <[email protected]>
---
 drivers/mmc/card/block.c | 7 +++++++
 1 file changed, 7 insertions(+)
drivers/mmc/card/block.c +7 -0
index 5650748..79c8861 100644
@@ -2026,6 +2026,13 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
 		/* claim host only for the first request */
 		mmc_get_card(card);
 
+	if (mmc_card_locked(card)) {
+		if (req)
+			blk_end_request_all(req, 0);
+		ret = 0;
+		goto out;
+	}
+
 	ret = mmc_blk_part_switch(card, md);
 	if (ret) {
 		if (req) {
Signature · 1 line
1.9.0.138.g2de3478
#9 lore raw
In reply to Al Cooper

Hi Al,

Let me start by apologizing for the long delay in feedback.

Quoted 7 lines · Al Cooper

This set of patches adds support for password protected locking and unlocking of MMC and SD devices. It uses the LOCK/UNLOCK command (CMD42) available in both the MMC and SD command sets.

Some of this code was based on a patch set submitted in 2006 by Anderson Briglia "Add MMC Password Protection (lock/unlock)". This patch set never made it into mainline.

I lot have happened since 2006 and I don't know the history to why this was rejected. Was it just that nobody cares to review it or something else?

Quoted 8 lines

By default, a card with no password assigned is always in "unlocked" state. After password assignment, in the next power cycle the card switches to a "locked" state where only the "basic" and "lock card" command classes are accepted by the card. Only after unlocking it with the correct password can the card be used for normal operations like block I/O.

Quoted 6 lines

Password management and caching is done through the "Kernel Key Retention Service" mechanism and the sysfs filesystem. Two new sysfs attributes were added. The "lock" attribute is used to lock, unlock, assign a password, clear a password and force erase a card. The "unlock_retry" attribute is used to retry an unlock that failed during boot because the rootfs was not yet available with the password.

The rootfs issue makes this a bit complicated to handle. I think this can be simplified, perhaps by allowing user-space to trigger a mmc_rescan() to be run for a particular mmc host.

Quoted 1 line

From a power management point of view I think that would be preferred,

as else you might be leaving a locked card powered forever.

Quoted 6 lines

The user space software needed to test this new feature is available on GitHub at:
https://github.com/alcooper/mmc-password-utils
See the README for a detailed description of the user space layer and how to use this feature.

Really nice that you maintain such utility. If this feature enters mainline, it would nice to merge this into Chris' mmc-utils.

Quoted 45 lines

Changed for V3:
- Ported the V2 patch set submitted Aug. 2013 to the latest mainline

    (v4.1-rc4).

- Created a GitHub project for the user space layer.
- Change the lock command (CMD42) to round up the data buffer size to 512 for SD but leave exact size for eMMC based on the SD and eMMC specs.

Changed for V2:
The V2 changes were not functional and were just general cleanup.
- Use stub functions to reduce the number of CONFIG ifdefs.
- Add static to a few functions that were local.
- Use pr_warn instead of pr_warning.
- Improve a few variable names and messages.

Abbas Raza (1):
According to SD Physical Layer Specifications: Locked cards respond to
(and execute) all commands in the "basic" command class (class 0), ACMD41, CMD16 and "lock card" command class. Thus, the host is allowed to reset, initialize, select, query for status, etc., but not to access data on the card.

Al Cooper (7):
mmc: lock: Use the kernel "KEYS" subsystem to get a card's password
mmc: lock: Add low level LOCK_UNLOCK command
mmc: lock: Add function to unlock a password locked card
mmc: lock: Add card lock/unlock maintenance commands
mmc: lock: Change SD init functionality to handle locked SD cards
mmc: lock: Prevent partition table read for locked cards.
mmc: lock: Change MMC init to handle locked cards.

 drivers/mmc/card/block.c   |  14 ++++
 drivers/mmc/core/Kconfig   |   8 +++
 drivers/mmc/core/core.c    | 120 +++++++++++++++++++++++++++++++++
 drivers/mmc/core/core.h    |  14 +++-
 drivers/mmc/core/mmc.c     | 123 ++++++++++++++++++++++++++++++++++
 drivers/mmc/core/mmc_ops.c | 150 +++++++++++++++++++++++++++++++++++++++++
 drivers/mmc/core/mmc_ops.h |  13 ++++
 drivers/mmc/core/sd.c      | 161 +++++++++++++++++++++++++++++++--------------
 include/linux/mmc/card.h   |   6 ++
 9 files changed, 560 insertions(+), 49 deletions(-)
Quoted 3 lines

--
1.9.0.138.g2de3478

This is just an initial review and before I spend more time going into the details, I want to understand *why* we want this feature. Could you elaborate on what use cases you see and whether you already know someone actively using this?

Quoted 1 line

From a code quality point of view, it overall looks okay, but let me

get back to the details once we discussed the above a bit.

Moreover, I would like to encourage other MMC developers to give there overall opinion about this feature.

Kind regards
Uffe

#10 lore raw

Hi Ulf Hansson,

One use case is whenever any host controller tries for specification compliance or certification, there are defined test cases for each spec version.
If mmc/sd subsystem can validate most of them, if not all, out of tree, it would be of great advantage for users.

I have performed recently this compliance testing for v3.0 host spec and found some features missing like lock/unlock, register programming, erase etc.

These patches should defintely help linux get compliant atleast for SD Host Spec.

Defined Host Controller Test Specification is available from SD Card Association. www.sdcard.org

Hope this helps,

Regards,
Suneel

Quoted 115 lines · Ulf Hansson

Hi Al,

Let me start by apologizing for the long delay in feedback.

Quoted 7 lines · Al Cooper

This set of patches adds support for password protected locking and unlocking of MMC and SD devices. It uses the LOCK/UNLOCK command (CMD42) available in both the MMC and SD command sets.

Some of this code was based on a patch set submitted in 2006 by Anderson Briglia "Add MMC Password Protection (lock/unlock)". This patch set never made it into mainline.

I lot have happened since 2006 and I don't know the history to why this was rejected. Was it just that nobody cares to review it or something else?

Quoted 8 lines

By default, a card with no password assigned is always in "unlocked" state. After password assignment, in the next power cycle the card switches to a "locked" state where only the "basic" and "lock card" command classes are accepted by the card. Only after unlocking it with the correct password can the card be used for normal operations like block I/O.

Quoted 6 lines

Password management and caching is done through the "Kernel Key Retention Service" mechanism and the sysfs filesystem. Two new sysfs attributes were added. The "lock" attribute is used to lock, unlock, assign a password, clear a password and force erase a card. The "unlock_retry" attribute is used to retry an unlock that failed during boot because the rootfs was not yet available with the password.

The rootfs issue makes this a bit complicated to handle. I think this can be simplified, perhaps by allowing user-space to trigger a mmc_rescan() to be run for a particular mmc host.

From a power management point of view I think that would be preferred, as else you might be leaving a locked card powered forever.

Quoted 6 lines

The user space software needed to test this new feature is available on GitHub at:
https://github.com/alcooper/mmc-password-utils
See the README for a detailed description of the user space layer and how to use this feature.

Really nice that you maintain such utility. If this feature enters mainline, it would nice to merge this into Chris' mmc-utils.

Quoted 45 lines

Changed for V3:
- Ported the V2 patch set submitted Aug. 2013 to the latest mainline

    (v4.1-rc4).

- Created a GitHub project for the user space layer.
- Change the lock command (CMD42) to round up the data buffer size to 512 for SD but leave exact size for eMMC based on the SD and eMMC specs.

Changed for V2:
The V2 changes were not functional and were just general cleanup.
- Use stub functions to reduce the number of CONFIG ifdefs.
- Add static to a few functions that were local.
- Use pr_warn instead of pr_warning.
- Improve a few variable names and messages.

Abbas Raza (1):
According to SD Physical Layer Specifications: Locked cards respond to
(and execute) all commands in the "basic" command class (class 0), ACMD41, CMD16 and "lock card" command class. Thus, the host is allowed to reset, initialize, select, query for status, etc., but not to access data on the card.

Al Cooper (7):
mmc: lock: Use the kernel "KEYS" subsystem to get a card's password
mmc: lock: Add low level LOCK_UNLOCK command
mmc: lock: Add function to unlock a password locked card
mmc: lock: Add card lock/unlock maintenance commands
mmc: lock: Change SD init functionality to handle locked SD cards
mmc: lock: Prevent partition table read for locked cards.
mmc: lock: Change MMC init to handle locked cards.

 drivers/mmc/card/block.c   |  14 ++++
 drivers/mmc/core/Kconfig   |   8 +++
 drivers/mmc/core/core.c    | 120 +++++++++++++++++++++++++++++++++
 drivers/mmc/core/core.h    |  14 +++-
 drivers/mmc/core/mmc.c     | 123 ++++++++++++++++++++++++++++++++++
 drivers/mmc/core/mmc_ops.c | 150 +++++++++++++++++++++++++++++++++++++++++
 drivers/mmc/core/mmc_ops.h |  13 ++++
 drivers/mmc/core/sd.c      | 161 +++++++++++++++++++++++++++++++--------------
 include/linux/mmc/card.h   |   6 ++
 9 files changed, 560 insertions(+), 49 deletions(-)
Quoted 3 lines

--
1.9.0.138.g2de3478

This is just an initial review and before I spend more time going into the details, I want to understand *why* we want this feature. Could you elaborate on what use cases you see and whether you already know someone actively using this?

From a code quality point of view, it overall looks okay, but let me get back to the details once we discussed the above a bit.

Moreover, I would like to encourage other MMC developers to give there overall opinion about this feature.

Kind regards
Uffe
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#11 lore raw
In reply to Ulf Hansson
Quoted 9 lines · Ulf Hansson

Hi Al,

Let me start by apologizing for the long delay in feedback.

Quoted 4 lines · Al Cooper

This set of patches adds support for password protected locking and unlocking of MMC and SD devices. It uses the LOCK/UNLOCK command (CMD42) available in both the MMC and SD command sets.

Quoted 7 lines
Quoted 3 lines

Some of this code was based on a patch set submitted in 2006 by Anderson Briglia "Add MMC Password Protection (lock/unlock)". This patch set never made it into mainline.

I lot have happened since 2006 and I don't know the history to why this was rejected. Was it just that nobody cares to review it or something else?

It was never rejected, it just didn't get enough review interest.

Quoted 15 lines
Quoted 8 lines

By default, a card with no password assigned is always in "unlocked" state. After password assignment, in the next power cycle the card switches to a "locked" state where only the "basic" and "lock card" command classes are accepted by the card. Only after unlocking it with the correct password can the card be used for normal operations like block I/O.

Quoted 6 lines

Password management and caching is done through the "Kernel Key Retention Service" mechanism and the sysfs filesystem. Two new sysfs attributes were added. The "lock" attribute is used to lock, unlock, assign a password, clear a password and force erase a card. The "unlock_retry" attribute is used to retry an unlock that failed during boot because the rootfs was not yet available with the password.

Quoted 3 lines

The rootfs issue makes this a bit complicated to handle. I think this can be simplified, perhaps by allowing user-space to trigger a mmc_rescan() to be run for a particular mmc host.

The "unlock_retry" attribute in sysfs allows user-space to trigger an unlock retry
for a locked card.

Quoted 4 lines

From a power management point of view I think that would be preferred, as else you might be leaving a locked card powered forever.

Since a locked device is allowed to come up partially, all the power management seems to work correctly. I tested suspend and verified that the power to the SD card was turned off. This should also allow the eMMC SLEEP_AWAKE command (CMD5) to work on locked eMMC devices.

Quoted 9 lines
Quoted 6 lines

The user space software needed to test this new feature is available on GitHub at:
https://github.com/alcooper/mmc-password-utils
See the README for a detailed description of the user space layer and how to use this feature.

Really nice that you maintain such utility. If this feature enters mainline, it would nice to merge this into Chris' mmc-utils.

I agree and Chris has recently accepted other features I've added to mmc-utils.

Quoted 5 lines

This is just an initial review and before I spend more time going into the details, I want to understand *why* we want this feature. Could you elaborate on what use cases you see and whether you already know someone actively using this?

The reason I added this functionality is for the Settop Box industry. There's a trend to use SD cards for Time-Shift-Buffering of video and it's nice to be able to
lock the card to prevent the SD card and it's video from being used in another system. There are a few very big Settop Box companies interested in doing this. SanDisk is now creating a special class of SD card, called a Video Buffer Card, with extended write cycles just for this purpose. SanDisk is also extending the CMD42 (LOCK_UNLOCK) command and expects to have the extensions in the next version of the SD Physical Layer Specification.

The other use would be to allow a user to password protect their SD card to keep sensitive information safe.

As far as others currently using the patches, I got the following email last year:

| Y Garcia <[email protected]>
|
| 6/19/14
| to me
|
| Hi Alan,
|
| I successful built the kernel with SD/MMC lock support and I also

included keyutils package in rootfs but now I need
|
| a user space script or helper example to deal with password and "keyutil" utility.

|
| Can you be so kind to once again give me a hint on this regard?
|
| I've been study/searching without any luck.
|
|
| Regards,
|
| Thanks in advance for your support.
|
| Yamil.

I also got an email about 2 years ago asking if it was OK to use the my first version of the patchset, but I can't find the email.

Also, the last patch in the set I submitted was from from Abbas Raza <[email protected]> who must be doing something with the patches to have found the issue.

Quoted 9 lines

From a code quality point of view, it overall looks okay, but let me get back to the details once we discussed the above a bit.

Moreover, I would like to encourage other MMC developers to give there overall opinion about this feature.

Kind regards
Uffe

Thanks.
Al

#12 lore raw

[...]

Quoted 6 lines
Quoted 4 lines

I lot have happened since 2006 and I don't know the history to why this was rejected. Was it just that nobody cares to review it or something else?

It was never rejected, it just didn't get enough review interest.

Okay, I will do my best to make sure we get consensus in how to proceed then.

[...]

Quoted 10 lines
Quoted 4 lines

The rootfs issue makes this a bit complicated to handle. I think this can be simplified, perhaps by allowing user-space to trigger a mmc_rescan() to be run for a particular mmc host.

The "unlock_retry" attribute in sysfs allows user-space to trigger an unlock retry
for a locked card.

Quoted 1 line
Quoted 8 lines
Quoted 3 lines

From a power management point of view I think that would be preferred, as else you might be leaving a locked card powered forever.

Since a locked device is allowed to come up partially, all the power management seems to work correctly. I tested suspend and verified that the power to the SD card was turned off. This should also allow the eMMC SLEEP_AWAKE command (CMD5) to work on locked eMMC devices.

I see your point, I just feel it's becoming complex and fragile. Still, it seems this feature is important also for non-removable cards and these are only enumerated once during the boot.

I need to think a bit more on this.

[...]

Quoted 47 lines
Quoted 5 lines

This is just an initial review and before I spend more time going into the details, I want to understand *why* we want this feature. Could you elaborate on what use cases you see and whether you already know someone actively using this?

The reason I added this functionality is for the Settop Box industry. There's a trend to use SD cards for Time-Shift-Buffering of video and it's nice to be able to
lock the card to prevent the SD card and it's video from being used in another system. There are a few very big Settop Box companies interested in doing this. SanDisk is now creating a special class of SD card, called a Video Buffer Card, with extended write cycles just for this purpose. SanDisk is also extending the CMD42 (LOCK_UNLOCK) command and expects to have the extensions in the next version of the SD Physical Layer Specification.

The other use would be to allow a user to password protect their SD card to keep sensitive information safe.

As far as others currently using the patches, I got the following email last year:

| Y Garcia <[email protected]>
|
| 6/19/14
| to me
|
| Hi Alan,
|
| I successful built the kernel with SD/MMC lock support and I also

included keyutils package in rootfs but now I need
|
| a user space script or helper example to deal with password and "keyutil" utility.

|
| Can you be so kind to once again give me a hint on this regard?
|
| I've been study/searching without any luck.
|
|
| Regards,
|
| Thanks in advance for your support.
|
| Yamil.
Quoted 7 lines

I also got an email about 2 years ago asking if it was OK to use the my first version of the patchset, but I can't find the email.

Also, the last patch in the set I submitted was from from Abbas Raza <[email protected]> who must be doing something with the patches to have found the issue.

Thanks for the info. I am okay going forward with this patchset, though I think it's a bit late (my fault) for 4.3. Could you perhaps repost once 4.3 rc1 is out!?

Kind regards
Uffe

#13 lore raw
Quoted 3 lines · Ulf Hansson

Thanks for the info. I am okay going forward with this patchset, though I think it's a bit late (my fault) for 4.3. Could you perhaps repost once 4.3 rc1 is out!?

Thanks!
I'll re-post after 4.3 rc1.

Al