diff mbox

[V2,1/7] mmc: lock: Use the kernel "KEYS" subsystem to get a card's password

Message ID 1377893665-26754-2-git-send-email-alcooperx@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Alan Cooper Aug. 30, 2013, 8:14 p.m. UTC
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.

Signed-off-by: Al Cooper <alcooperx@gmail.com>
---
 drivers/mmc/core/Kconfig |   8 ++++
 drivers/mmc/core/core.c  | 105 +++++++++++++++++++++++++++++++++++++++++++++++
 drivers/mmc/core/core.h  |  11 ++++-
 3 files changed, 123 insertions(+), 1 deletion(-)

Comments

Chris Ball Sept. 1, 2013, 6:53 p.m. UTC | #1
Hi Al,

On Fri, Aug 30 2013, Al Cooper wrote:
> --- a/drivers/mmc/core/Kconfig
> +++ b/drivers/mmc/core/Kconfig
> @@ -26,3 +26,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.

Is there a good reason to have this behind a Kconfig entry, rather
than just enabled for everyone?  I'm happy to just enable it if we
don't expect any downside.

Thanks,

- Chris.
Chris Ball Sept. 1, 2013, 9:08 p.m. UTC | #2
Hi,

On Sun, Sep 01 2013, Chris Ball wrote:
>> +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.
>
> Is there a good reason to have this behind a Kconfig entry, rather
> than just enabled for everyone?  I'm happy to just enable it if we
> don't expect any downside.

Well, I guess it's the dependency on the KEYS subsystem.  I can see
that some people would like to build embedded devices with MMC but
without KEYS.  It's a shame to have this code go entirely untested
by most of our users, though..

- Chris.
diff mbox

Patch

diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig
index 269d072..b0ba79d 100644
--- a/drivers/mmc/core/Kconfig
+++ b/drivers/mmc/core/Kconfig
@@ -26,3 +26,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.
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 49a5bca..4954d04 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -27,6 +27,7 @@ 
 #include <linux/fault-inject.h>
 #include <linux/random.h>
 #include <linux/slab.h>
+#include <linux/key-type.h>
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
@@ -2705,6 +2706,104 @@  void mmc_init_context_info(struct mmc_host *host)
 	init_waitqueue_head(&host->context_info.wait);
 }
 
+#ifdef CONFIG_MMC_LOCK
+
+static int mmc_key_instantiate(struct key *key,
+			       struct key_preparsed_payload *prep)
+{
+	char *payload;
+
+	if (prep->datalen <= 0 || prep->datalen > MMC_PASSWORD_MAX ||
+	    !prep->data) {
+		pr_warn("Invalid data\n");
+		return  -EINVAL;
+	}
+
+	payload = kmalloc(prep->datalen, GFP_KERNEL);
+	if (!payload)
+		return -ENOMEM;
+	memcpy(payload, prep->data, prep->datalen);
+	key->payload.data = payload;
+	key->datalen = prep->datalen;
+	return 0;
+}
+
+static int mmc_key_match(const struct key *key, const void *description)
+{
+	pr_debug("mmc_key_match: %s, %s\n",
+		 key->description, (char *)description);
+	return strcmp(key->description, description) == 0;
+}
+
+/*
+ * dispose of the data dangling from the corpse of a mmc key
+ */
+static void mmc_key_destroy(struct key *key)
+{
+	kfree(key->payload.data);
+}
+
+struct key_type key_type_mmc = {
+	.name		= "mmc",
+	.instantiate	= mmc_key_instantiate,
+	.match		= mmc_key_match,
+	.destroy	= mmc_key_destroy,
+};
+
+int mmc_get_password(struct mmc_card *card, struct mmc_password *password)
+{
+	struct key *mmc_key;
+	char key_desc[(sizeof(card->raw_cid) * 2) + 1];
+
+	/* Use the CID to uniquely identify the card */
+	snprintf(key_desc, sizeof(key_desc), "%08x%08x%08x%08x",
+		 card->raw_cid[0], card->raw_cid[1],
+		 card->raw_cid[2], card->raw_cid[3]);
+
+	mmc_key = request_key(&key_type_mmc, key_desc,
+			      "password");
+	if (IS_ERR(mmc_key)) {
+		dev_warn(&card->dev, "Error, request_key %ld\n",
+			 PTR_ERR(mmc_key));
+		return PTR_ERR(mmc_key);
+	}
+	dev_dbg(&card->dev, "Found matching key\n");
+	memcpy(&password->password, mmc_key->payload.data,
+	       mmc_key->datalen);
+	password->length = mmc_key->datalen;
+	key_put(mmc_key);
+
+	return 0;
+}
+
+static inline int mmc_register_key_type(void)
+{
+	return register_key_type(&key_type_mmc);
+}
+
+static inline void mmc_unregister_key_type(void)
+{
+	unregister_key_type(&key_type_mmc);
+}
+
+#else /* CONFIG_MMC_LOCK */
+
+int mmc_get_password(struct mmc_card *card, struct mmc_password *password)
+{
+	return -ENOKEY;
+}
+
+static inline int mmc_register_key_type(void)
+{
+	return 0;
+}
+
+static inline void mmc_unregister_key_type(void)
+{
+}
+
+#endif /* CONFIG_MMC_LOCK */
+
 static int __init mmc_init(void)
 {
 	int ret;
@@ -2725,8 +2824,13 @@  static int __init mmc_init(void)
 	if (ret)
 		goto unregister_host_class;
 
+	ret = mmc_register_key_type();
+	if (ret)
+		goto unregister_sdio_bus;
 	return 0;
 
+unregister_sdio_bus:
+	sdio_unregister_bus();
 unregister_host_class:
 	mmc_unregister_host_class();
 unregister_bus:
@@ -2739,6 +2843,7 @@  destroy_workqueue:
 
 static void __exit mmc_exit(void)
 {
+	mmc_unregister_key_type();
 	sdio_unregister_bus();
 	mmc_unregister_host_class();
 	mmc_unregister_bus();
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
index 5345d15..c64ec12 100644
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -81,5 +81,14 @@  void mmc_add_card_debugfs(struct mmc_card *card);
 void mmc_remove_card_debugfs(struct mmc_card *card);
 
 void mmc_init_context_info(struct mmc_host *host);
-#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