linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [patch 0/6] Add MMC password protection (lock/unlock) support V4
@ 2006-01-31 20:16 Carlos Aguiar
  2006-01-31 20:16 ` [patch 1/6] " Carlos Aguiar
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Carlos Aguiar @ 2006-01-31 20:16 UTC (permalink / raw)
  To: linux-kernel, Linux-omap-open-source@linux.omap.com
  Cc: linux, David Brownell, Tony Lindgren, Russell King,
	Aguiar Carlos (EXT-INdT/Manaus),
	Lizardo Anderson (EXT-INdT/Manaus),
	Anderson Briglia

Hi all,

New in this version:

- The remaining MMC password operations previously executed by key
  retention functions (change password, unlock card and assign password)
  were implemented using the sysfs mechanism.
- Added the host MMC lock/unlock capability support for OMAP platform.
- Added verbose debugging messages

This series of patches add support for MultiMediaCard (MMC) password
protection, as described in the MMC Specification v4.1. This feature is
supported by all compliant MMC cards, and used by some devices such as
Symbian OS cell phones to optionally protect MMC cards with a password.

By default, a MMC 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 the card can be normally used for operations like
block I/O.

Password management and caching is done through the "Kernel Key
Retention Service" mechanism and the sysfs filesystem. A new sysfs
attribute was added to the MMC driver for unlocking the card, assigning
a password to an unlocked card, change a card's password, remove the
password and check locked/unlocked status.

A sample text-mode reference UI written in shell script (using the
keyctl command from the keyutils package), can be found at:

http://www.indt.org.br/10le/mmc_pwd/mmc_reference_ui-20060130.tar.bz2

TODO:

- Password caching: when inserting a locked card, the driver should try
  to unlock it with the currently stored password (if any), and if it
  fails, revoke the key containing it and fallback to the normal "no
  password present" situation.

Known Issue:

- Some cards have an incorrect behaviour (hardware bug?) regarding
  password acceptance: if an affected card has password <pwd>, it
  accepts <pwd><xxx> as the correct password too, where <xxx> is any
  sequence of characters, of any length. In other words, on these cards
  only the first <password length> bytes need to match the correct
  password.


We would like to ask you to test these patches. We believe they are
ready to be included on the kernel source.

Comments and suggestions are welcome.
--
Anderson Briglia,
Anderson Lizardo,
Carlos Eduardo Aguiar
Embedded Linux Lab - 10LE
Nokia Institute of Technology - INdT
Manaus - Brazil

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [patch 1/6] Add MMC password protection (lock/unlock) support V4
  2006-01-31 20:16 [patch 0/6] Add MMC password protection (lock/unlock) support V4 Carlos Aguiar
@ 2006-01-31 20:16 ` Carlos Aguiar
  2006-01-31 20:16 ` [patch 2/6] " Carlos Aguiar
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Carlos Aguiar @ 2006-01-31 20:16 UTC (permalink / raw)
  To: linux-kernel, Linux-omap-open-source@linux.omap.com
  Cc: linux, David Brownell, Tony Lindgren, Russell King,
	Aguiar Carlos (EXT-INdT/Manaus),
	Lizardo Anderson (EXT-INdT/Manaus),
	Anderson Briglia

[-- Attachment #1: mmc_ignore_locked.diff --]
[-- Type: text/plain, Size: 4809 bytes --]

When a card is locked, only commands from the "basic" and "lock card" classes
are accepted. To be able to use the other commands, the card must be unlocked
first.

This patch prevents the block driver from trying to run privileged class
commands on locked MMC cards, which will fail anyway.

Signed-off-by: Anderson Briglia <anderson.briglia@indt.org.br>
Signed-off-by: Anderson Lizardo <anderson.lizardo@indt.org.br>
Signed-off-by: Carlos Eduardo Aguiar <carlos.aguiar@indt.org.br>
Signed-off-by: David Brownell <david-b@pacbell.net>

Index: linux-omap-2.6.git/drivers/mmc/mmc_sysfs.c
===================================================================
--- linux-omap-2.6.git.orig/drivers/mmc/mmc_sysfs.c	2006-01-31 15:17:45.000000000 -0400
+++ linux-omap-2.6.git/drivers/mmc/mmc_sysfs.c	2006-01-31 15:22:07.000000000 -0400
@@ -16,6 +16,7 @@
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
+#include <linux/mmc/protocol.h>
 
 #include "mmc.h"
 
@@ -69,13 +70,22 @@ static void mmc_release_card(struct devi
 }
 
 /*
- * This currently matches any MMC driver to any MMC card - drivers
- * themselves make the decision whether to drive this card in their
- * probe method.  However, we force "bad" cards to fail.
+ * This currently matches any MMC driver to any MMC card - drivers themselves
+ * make the decision whether to drive this card in their probe method.
+ * However, we force "bad" cards to fail.
+ *
+ * We also fail for all locked cards; drivers expect to be able to do block
+ * I/O still on probe(), which is not possible while the card is locked.
+ * Device probing must be triggered sometime later to make the card available
+ * to the block driver.
  */
 static int mmc_bus_match(struct device *dev, struct device_driver *drv)
 {
 	struct mmc_card *card = dev_to_mmc_card(dev);
+	if (mmc_card_lockable(card) && mmc_card_locked(card)) {
+		dev_dbg(&card->dev, "card is locked; binding is deferred\n");
+		return 0;
+	}
 	return !mmc_card_bad(card);
 }
 
Index: linux-omap-2.6.git/include/linux/mmc/card.h
===================================================================
--- linux-omap-2.6.git.orig/include/linux/mmc/card.h	2006-01-31 15:17:45.000000000 -0400
+++ linux-omap-2.6.git/include/linux/mmc/card.h	2006-01-31 15:22:07.000000000 -0400
@@ -61,6 +61,7 @@ struct mmc_card {
 #define MMC_STATE_BAD		(1<<2)		/* unrecognised device */
 #define MMC_STATE_SDCARD	(1<<3)		/* is an SD card */
 #define MMC_STATE_READONLY	(1<<4)		/* card is read-only */
+#define MMC_STATE_LOCKED	(1<<5)		/* card is currently locked */
 	u32			raw_cid[4];	/* raw card CID */
 	u32			raw_csd[4];	/* raw card CSD */
 	u32			raw_scr[2];	/* raw card SCR */
@@ -74,12 +75,18 @@ struct mmc_card {
 #define mmc_card_bad(c)		((c)->state & MMC_STATE_BAD)
 #define mmc_card_sd(c)		((c)->state & MMC_STATE_SDCARD)
 #define mmc_card_readonly(c)	((c)->state & MMC_STATE_READONLY)
+#define mmc_card_locked(c)	((c)->state & MMC_STATE_LOCKED)
+#define mmc_card_clear_locked(c)	((c)->state &= ~MMC_STATE_LOCKED)
+
+#define mmc_card_lockable(c)    (((c)->csd.cmdclass & CCC_LOCK_CARD) && \
+				((c)->host->caps & MMC_CAP_LOCK_UNLOCK))
 
 #define mmc_card_set_present(c)	((c)->state |= MMC_STATE_PRESENT)
 #define mmc_card_set_dead(c)	((c)->state |= MMC_STATE_DEAD)
 #define mmc_card_set_bad(c)	((c)->state |= MMC_STATE_BAD)
 #define mmc_card_set_sd(c)	((c)->state |= MMC_STATE_SDCARD)
 #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
+#define mmc_card_set_locked(c)	((c)->state |= MMC_STATE_LOCKED)
 
 #define mmc_card_name(c)	((c)->cid.prod_name)
 #define mmc_card_id(c)		((c)->dev.bus_id)
Index: linux-omap-2.6.git/include/linux/mmc/host.h
===================================================================
--- linux-omap-2.6.git.orig/include/linux/mmc/host.h	2006-01-31 15:17:45.000000000 -0400
+++ linux-omap-2.6.git/include/linux/mmc/host.h	2006-01-31 15:22:07.000000000 -0400
@@ -85,6 +85,8 @@ struct mmc_host {
 	unsigned long		caps;		/* Host capabilities */
 
 #define MMC_CAP_4_BIT_DATA	(1 << 0)	/* Can the host do 4 bit transfers */
+#define MMC_CAP_LOCK_UNLOCK	(1 << 1)	/* Host password support capability */
+
 
 	/* host specific block data */
 	unsigned int		max_seg_size;	/* see blk_queue_max_segment_size */
Index: linux-omap-2.6.git/drivers/mmc/mmc.c
===================================================================
--- linux-omap-2.6.git.orig/drivers/mmc/mmc.c	2006-01-31 15:17:45.000000000 -0400
+++ linux-omap-2.6.git/drivers/mmc/mmc.c	2006-01-31 15:22:07.000000000 -0400
@@ -828,6 +828,11 @@ static void mmc_discover_cards(struct mm
 			list_add(&card->node, &host->cards);
 		}
 
+		if (cmd.resp[0] & R1_CARD_IS_LOCKED)
+			mmc_card_set_locked(card);
+		else
+			mmc_card_clear_locked(card);
+
 		card->state &= ~MMC_STATE_DEAD;
 
 		if (host->mode == MMC_MODE_SD) {

--

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [patch 2/6] Add MMC password protection (lock/unlock) support V4
  2006-01-31 20:16 [patch 0/6] Add MMC password protection (lock/unlock) support V4 Carlos Aguiar
  2006-01-31 20:16 ` [patch 1/6] " Carlos Aguiar
@ 2006-01-31 20:16 ` Carlos Aguiar
  2006-01-31 20:16 ` [patch 3/6] " Carlos Aguiar
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Carlos Aguiar @ 2006-01-31 20:16 UTC (permalink / raw)
  To: linux-kernel, Linux-omap-open-source@linux.omap.com
  Cc: linux, David Brownell, Tony Lindgren, Russell King,
	Aguiar Carlos (EXT-INdT/Manaus),
	Lizardo Anderson (EXT-INdT/Manaus),
	Anderson Briglia

[-- Attachment #1: mmc_lock_unlock.diff --]
[-- Type: text/plain, Size: 6166 bytes --]

Implement card lock/unlock operation, using the MMC_LOCK_UNLOCK command.

Signed-off-by: Anderson Briglia <anderson.briglia@indt.org.br>
Signed-off-by: Anderson Lizardo <anderson.lizardo@indt.org.br>
Signed-off-by: Carlos Eduardo Aguiar <carlos.aguiar@indt.org.br>

Index: linux-omap-2.6.git/drivers/mmc/mmc.c
===================================================================
--- linux-omap-2.6.git.orig/drivers/mmc/mmc.c	2006-01-31 15:22:07.000000000 -0400
+++ linux-omap-2.6.git/drivers/mmc/mmc.c	2006-01-31 15:22:21.000000000 -0400
@@ -4,6 +4,8 @@
  *  Copyright (C) 2003-2004 Russell King, All Rights Reserved.
  *  SD support Copyright (C) 2004 Ian Molton, All Rights Reserved.
  *  SD support Copyright (C) 2005 Pierre Ossman, All Rights Reserved.
+ *  MMC password protection (C) 2005 Instituto Nokia de Tecnologia (INdT),
+ *     All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -20,6 +22,7 @@
 #include <linux/err.h>
 #include <asm/scatterlist.h>
 #include <linux/scatterlist.h>
+#include <linux/key.h>
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
@@ -1011,10 +1014,14 @@ static void mmc_check_cards(struct mmc_h
 		cmd.flags = MMC_RSP_R1;
 
 		err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
-		if (err == MMC_ERR_NONE)
+		if (err != MMC_ERR_NONE) {
+			mmc_card_set_dead(card);
 			continue;
-
-		mmc_card_set_dead(card);
+		}
+		if (cmd.resp[0] & R1_CARD_IS_LOCKED)
+			mmc_card_set_locked(card);
+		else
+			mmc_card_clear_locked(card);
 	}
 }
 
@@ -1108,6 +1115,135 @@ static void mmc_setup(struct mmc_host *h
 		mmc_read_scrs(host);
 }
 
+/* Calculate the minimal blksz_bits to hold x bytes. */
+static inline int blksz_bits(unsigned x)
+{
+	return fls(x-1);
+}
+
+/**
+ *	mmc_lock_unlock - send LOCK_UNLOCK command to a specific card.
+ *	@card: card to which the LOCK_UNLOCK command should be sent
+ *	@key: key containing the MMC password
+ *	@mode: LOCK_UNLOCK mode
+ *
+ */
+int mmc_lock_unlock(struct mmc_card *card, struct key *key, int mode)
+{
+	struct mmc_request mrq;
+	struct mmc_command cmd;
+	struct mmc_data data;
+	struct scatterlist sg;
+	struct mmc_key_payload *mpayload;
+	unsigned long erase_timeout;
+	int err, data_size;
+	u8 *data_buf;
+
+	mpayload = NULL;
+	data_size = 1;
+	if (mode != MMC_LOCK_MODE_ERASE) {
+		mpayload = rcu_dereference(key->payload.data);
+		data_size = 2 + mpayload->datalen;
+	}
+
+	data_buf = kmalloc(data_size, GFP_KERNEL);
+	if (!data_buf)
+		return -ENOMEM;
+	memset(data_buf, 0, data_size);
+
+	data_buf[0] = mode;
+	if (mode != MMC_LOCK_MODE_ERASE) {
+		data_buf[1] = mpayload->datalen;
+		memcpy(data_buf + 2, mpayload->data, mpayload->datalen);
+	}
+
+	err = mmc_card_claim_host(card);
+	if (err != MMC_ERR_NONE) {
+		mmc_card_set_dead(card);
+		goto out;
+	}
+
+	memset(&cmd, 0, sizeof(struct mmc_command));
+
+	cmd.opcode = MMC_SET_BLOCKLEN;
+	cmd.arg = data_size;
+	cmd.flags = MMC_RSP_R1;
+	err = mmc_wait_for_cmd(card->host, &cmd, CMD_RETRIES);
+	if (err != MMC_ERR_NONE) {
+		mmc_card_set_dead(card);
+		goto error;
+	}
+
+	memset(&cmd, 0, sizeof(struct mmc_command));
+
+	cmd.opcode = MMC_LOCK_UNLOCK;
+	cmd.arg = 0;
+	cmd.flags = MMC_RSP_R1B;
+
+	memset(&data, 0, sizeof(struct mmc_data));
+
+	data.timeout_ns = card->csd.tacc_ns * 10;
+	data.timeout_clks = card->csd.tacc_clks * 10;
+	data.blksz_bits = blksz_bits(data_size);
+	data.blocks = 1;
+	data.flags = MMC_DATA_WRITE;
+	data.sg = &sg;
+	data.sg_len = 1;
+
+	memset(&mrq, 0, sizeof(struct mmc_request));
+
+	mrq.cmd = &cmd;
+	mrq.data = &data;
+
+	sg_init_one(&sg, data_buf, data_size);
+	err = mmc_wait_for_req(card->host, &mrq);
+	if (err != MMC_ERR_NONE) {
+		if(err != MMC_ERR_INVALID)
+			mmc_card_set_dead(card);
+		goto error;
+	}
+
+	memset(&cmd, 0, sizeof(struct mmc_command));
+
+	cmd.opcode = MMC_SEND_STATUS;
+	cmd.arg = card->rca << 16;
+	cmd.flags = MMC_RSP_R1;
+
+	/* set timeout for forced erase operation to 3 min. (see MMC spec) */
+	erase_timeout = jiffies + 180 * HZ;
+	do {
+		/* we cannot use "retries" here because the
+		 * R1_LOCK_UNLOCK_FAILED bit is cleared by subsequent reads to
+		 * the status register, hiding the error condition */
+		err = mmc_wait_for_cmd(card->host, &cmd, 0);
+		if (err != MMC_ERR_NONE)
+			break;
+		/* the other modes don't need timeout checking */
+		if (mode != MMC_LOCK_MODE_ERASE)
+			continue;
+		if (time_after(jiffies, erase_timeout)) {
+			dev_dbg(&card->dev, "forced erase timed out\n");
+			err = MMC_ERR_TIMEOUT;
+			break;
+		}
+	} while (!(cmd.resp[0] & R1_READY_FOR_DATA));
+	if (cmd.resp[0] & R1_LOCK_UNLOCK_FAILED) {
+		dev_dbg(&card->dev, "LOCK_UNLOCK operation failed\n");
+		err = MMC_ERR_FAILED;
+	}
+
+error:
+	mmc_check_cards(card->host);
+	mmc_deselect_cards(card->host);
+	mmc_card_release_host(card);
+out:
+	kfree(data_buf);
+
+	return err;
+}
+
+EXPORT_SYMBOL(mmc_lock_unlock);
+
 
 /**
  *	mmc_detect_change - process change of state on a MMC socket
Index: linux-omap-2.6.git/include/linux/mmc/card.h
===================================================================
--- linux-omap-2.6.git.orig/include/linux/mmc/card.h	2006-01-31 15:22:07.000000000 -0400
+++ linux-omap-2.6.git/include/linux/mmc/card.h	2006-01-31 15:22:21.000000000 -0400
@@ -116,4 +116,8 @@ static inline int mmc_card_claim_host(st
 
 #define mmc_card_release_host(c)	mmc_release_host((c)->host)
 
+struct key;
+
+extern int mmc_lock_unlock(struct mmc_card *card, struct key *key, int mode);
+
 #endif
Index: linux-omap-2.6.git/include/linux/mmc/protocol.h
===================================================================
--- linux-omap-2.6.git.orig/include/linux/mmc/protocol.h	2006-01-31 15:17:45.000000000 -0400
+++ linux-omap-2.6.git/include/linux/mmc/protocol.h	2006-01-31 15:22:21.000000000 -0400
@@ -243,5 +243,13 @@ struct _mmc_csd {
 #define SD_BUS_WIDTH_1      0
 #define SD_BUS_WIDTH_4      2
 
+/*
+ * MMC_LOCK_UNLOCK modes
+ */
+#define MMC_LOCK_MODE_ERASE	(1<<3)
+#define MMC_LOCK_MODE_UNLOCK	(0<<2)
+#define MMC_LOCK_MODE_CLR_PWD	(1<<1)
+#define MMC_LOCK_MODE_SET_PWD	(1<<0)
+
 #endif  /* MMC_MMC_PROTOCOL_H */
 

--

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [patch 3/6] Add MMC password protection (lock/unlock) support V4
  2006-01-31 20:16 [patch 0/6] Add MMC password protection (lock/unlock) support V4 Carlos Aguiar
  2006-01-31 20:16 ` [patch 1/6] " Carlos Aguiar
  2006-01-31 20:16 ` [patch 2/6] " Carlos Aguiar
@ 2006-01-31 20:16 ` Carlos Aguiar
  2006-01-31 20:16 ` [patch 4/6] " Carlos Aguiar
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Carlos Aguiar @ 2006-01-31 20:16 UTC (permalink / raw)
  To: linux-kernel, Linux-omap-open-source@linux.omap.com
  Cc: linux, David Brownell, Tony Lindgren, Russell King,
	Aguiar Carlos (EXT-INdT/Manaus),
	Lizardo Anderson (EXT-INdT/Manaus),
	Anderson Briglia

[-- Attachment #1: mmc_key_retention.diff --]
[-- Type: text/plain, Size: 4916 bytes --]

Implement key retention operations.

Signed-off-by: Anderson Briglia <anderson.briglia@indt.org.br>
Signed-off-by: Anderson Lizardo <anderson.lizardo@indt.org.br>
Signed-off-by: Carlos Eduardo Aguiar <carlos.aguiar@indt.org.br>

Index: linux-omap-2.6.git/drivers/mmc/Kconfig
===================================================================
--- linux-omap-2.6.git.orig/drivers/mmc/Kconfig	2006-01-31 15:17:45.000000000 -0400
+++ linux-omap-2.6.git/drivers/mmc/Kconfig	2006-01-31 15:22:25.000000000 -0400
@@ -19,6 +19,19 @@ config MMC_DEBUG
 	  This is an option for use by developers; most people should
 	  say N here.  This enables MMC core and driver debugging.
 
+config MMC_PASSWORDS
+	boolean "MMC card lock/unlock passwords (EXPERIMENTAL)"
+	depends on MMC && EXPERIMENTAL
+	select KEYS
+	help
+	  Say Y here to enable the use of passwords to lock and unlock
+	  MMC cards.  This uses the access key retention support, using
+	  request_key to look up the key associated with each card.
+
+	  For example, if you have an MMC card that was locked using
+	  Symbian OS on your cell phone, you won't be able to read it
+	  on Linux without this support.
+
 config MMC_BLOCK
 	tristate "MMC block device driver"
 	depends on MMC
Index: linux-omap-2.6.git/drivers/mmc/mmc.h
===================================================================
--- linux-omap-2.6.git.orig/drivers/mmc/mmc.h	2006-01-31 15:17:45.000000000 -0400
+++ linux-omap-2.6.git/drivers/mmc/mmc.h	2006-01-31 15:22:25.000000000 -0400
@@ -18,4 +18,12 @@ struct mmc_host *mmc_alloc_host_sysfs(in
 int mmc_add_host_sysfs(struct mmc_host *host);
 void mmc_remove_host_sysfs(struct mmc_host *host);
 void mmc_free_host_sysfs(struct mmc_host *host);
+
+/* core-internal data */
+extern struct key_type mmc_key_type;
+struct mmc_key_payload {
+	struct rcu_head	rcu;		/* RCU destructor */
+	unsigned short	datalen;	/* length of this data */
+	char		data[0];	/* actual data */
+};
 #endif
Index: linux-omap-2.6.git/drivers/mmc/mmc_sysfs.c
===================================================================
--- linux-omap-2.6.git.orig/drivers/mmc/mmc_sysfs.c	2006-01-31 15:22:07.000000000 -0400
+++ linux-omap-2.6.git/drivers/mmc/mmc_sysfs.c	2006-01-31 15:22:25.000000000 -0400
@@ -2,6 +2,8 @@
  *  linux/drivers/mmc/mmc_sysfs.c
  *
  *  Copyright (C) 2003 Russell King, All Rights Reserved.
+ *  MMC password protection (C) 2005 Instituto Nokia de Tecnologia (INdT),
+ *     All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -13,6 +15,7 @@
 #include <linux/init.h>
 #include <linux/device.h>
 #include <linux/idr.h>
+#include <linux/key.h>
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
@@ -265,6 +268,71 @@ static struct class mmc_host_class = {
 static DEFINE_IDR(mmc_host_idr);
 static DEFINE_SPINLOCK(mmc_host_lock);
 
+#ifdef  CONFIG_MMC_PASSWORDS
+
+#define MMC_KEYLEN_MAXBYTES 32
+
+int mmc_key_instantiate(struct key *key, const void *data, size_t datalen)
+{
+	struct mmc_key_payload *mpayload, *zap;
+	int ret;
+
+	zap = NULL;
+	ret = -EINVAL;
+	if (datalen <= 0 || datalen > MMC_KEYLEN_MAXBYTES || !data) {
+		DBG("Invalid data\n");
+		goto error;
+	}
+
+	ret = key_payload_reserve(key, datalen);
+	if (ret < 0) {
+		DBG("ret = %d\n", ret);
+		goto error;
+	}
+
+	ret = -ENOMEM;
+	mpayload = kmalloc(sizeof(*mpayload) + datalen, GFP_KERNEL);
+	if (!mpayload) {
+		DBG("Unable to allocate mpayload structure\n");
+		goto error;
+	}
+	mpayload->datalen = datalen;
+	memcpy(mpayload->data, data, datalen);
+
+	rcu_assign_pointer(key->payload.data, mpayload);
+
+	/* ret = 0 if there is no error */
+	ret = 0;
+
+error:
+	return ret;
+}
+
+int mmc_key_match(const struct key *key, const void *description)
+{
+	return strcmp(key->description, description) == 0;
+}
+
+/*
+ * dispose of the data dangling from the corpse of a mmc key
+ */
+void mmc_key_destroy(struct key *key)
+{
+	struct mmc_key_payload *mpayload = key->payload.data;
+
+	kfree(mpayload);
+}
+
+struct key_type mmc_key_type = {
+	.name		= "mmc",
+	.def_datalen	= MMC_KEYLEN_MAXBYTES,
+	.instantiate	= mmc_key_instantiate,
+	.match		= mmc_key_match,
+	.destroy	= mmc_key_destroy,
+};
+
+#endif
+
 /*
  * Internal function. Allocate a new MMC host.
  */
@@ -335,6 +403,15 @@ static int __init mmc_init(void)
 		ret = class_register(&mmc_host_class);
 		if (ret)
 			bus_unregister(&mmc_bus_type);
+#ifdef	CONFIG_MMC_PASSWORDS
+		else {
+			ret = register_key_type(&mmc_key_type);
+			if (ret) {
+				class_unregister(&mmc_host_class);
+				bus_unregister(&mmc_bus_type);
+			}
+		}
+#endif
 	}
 	return ret;
 }
@@ -343,6 +420,9 @@ static void __exit mmc_exit(void)
 {
 	class_unregister(&mmc_host_class);
 	bus_unregister(&mmc_bus_type);
+#ifdef	CONFIG_MMC_PASSWORDS
+	unregister_key_type(&mmc_key_type);
+#endif
 }
 
 module_init(mmc_init);

--

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [patch 4/6] Add MMC password protection (lock/unlock) support V4
  2006-01-31 20:16 [patch 0/6] Add MMC password protection (lock/unlock) support V4 Carlos Aguiar
                   ` (2 preceding siblings ...)
  2006-01-31 20:16 ` [patch 3/6] " Carlos Aguiar
@ 2006-01-31 20:16 ` Carlos Aguiar
  2006-01-31 20:16 ` [patch 5/6] " Carlos Aguiar
  2006-01-31 20:16 ` [patch 6/6] " Carlos Aguiar
  5 siblings, 0 replies; 7+ messages in thread
From: Carlos Aguiar @ 2006-01-31 20:16 UTC (permalink / raw)
  To: linux-kernel, Linux-omap-open-source@linux.omap.com
  Cc: linux, David Brownell, Tony Lindgren, Russell King,
	Aguiar Carlos (EXT-INdT/Manaus),
	Lizardo Anderson (EXT-INdT/Manaus),
	Anderson Briglia

[-- Attachment #1: mmc_sysfs.diff --]
[-- Type: text/plain, Size: 4720 bytes --]

Implement MMC password force erase, remove password, change password,
unlock card and assign password operations. It uses the sysfs mechanism
to send commands to the MMC subsystem. 

Signed-off-by: Anderson Briglia <anderson.briglia@indt.org.br>
Signed-off-by: Anderson Lizardo <anderson.lizardo@indt.org.br>
Signed-off-by: Carlos Eduardo Aguiar <carlos.aguiar@indt.org.br>

Index: linux-omap-2.6.git/drivers/mmc/mmc_sysfs.c
===================================================================
--- linux-omap-2.6.git.orig/drivers/mmc/mmc_sysfs.c	2006-01-31 15:22:25.000000000 -0400
+++ linux-omap-2.6.git/drivers/mmc/mmc_sysfs.c	2006-01-31 15:22:29.000000000 -0400
@@ -16,6 +16,7 @@
 #include <linux/device.h>
 #include <linux/idr.h>
 #include <linux/key.h>
+#include <linux/err.h>
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
@@ -23,6 +24,12 @@
 
 #include "mmc.h"
 
+#ifdef CONFIG_MMC_DEBUG
+#define DBG(x...)	printk(KERN_DEBUG x)
+#else
+#define DBG(x...)	do { } while (0)
+#endif
+
 #define dev_to_mmc_card(d)	container_of(d, struct mmc_card, dev)
 #define to_mmc_driver(d)	container_of(d, struct mmc_driver, drv)
 #define cls_dev_to_mmc_host(d)	container_of(d, struct mmc_host, class_dev)
@@ -64,6 +71,101 @@ static struct device_attribute mmc_dev_a
 
 static struct device_attribute mmc_dev_attr_scr = MMC_ATTR_RO(scr);
 
+#ifdef	CONFIG_MMC_PASSWORDS
+
+static ssize_t
+mmc_lockable_show(struct device *dev, struct device_attribute *att, char *buf)
+{
+	struct mmc_card *card = dev_to_mmc_card(dev);
+
+	if (!mmc_card_lockable(card))
+		return sprintf(buf, "unsupported\n");
+	else
+		return sprintf(buf, "%slocked\n", mmc_card_locked(card) ?
+			"" : "un");
+}
+
+/*
+ * implement MMC password functions: force erase, remove password, change
+ * password, unlock card and assign password.
+ */
+static ssize_t
+mmc_lockable_store(struct device *dev, struct device_attribute *att,
+	const char *data, size_t len)
+{
+	struct mmc_card *card = dev_to_mmc_card(dev);
+
+	if (!mmc_card_lockable(card))
+		return -EINVAL;
+
+	if (mmc_card_locked(card) && !strncmp(data, "erase", 5)) {
+		/* forced erase only works while card is locked */
+		mmc_lock_unlock(card, NULL, MMC_LOCK_MODE_ERASE);
+		return len;
+	} else if (!mmc_card_locked(card) && !strncmp(data, "remove", 6)) {
+		/* remove password only works while card is unlocked */
+		struct key *mmc_key = request_key(&mmc_key_type, "mmc:key",
+				"remove");
+
+		if (!IS_ERR(mmc_key)) {
+			int err = mmc_lock_unlock(card, mmc_key,
+					MMC_LOCK_MODE_CLR_PWD);
+			if (!err)
+				return len;
+		} else
+			DBG("request_key returned error %ld\n",
+					PTR_ERR(mmc_key));
+	} else if (!mmc_card_locked(card) && !strncmp(data, "change", 6)) {
+			/* change */
+			struct key *mmc_key = request_key(&mmc_key_type,
+					"mmc:key", "change");
+			if (!IS_ERR(mmc_key)) {
+				int err = mmc_lock_unlock(card, mmc_key,
+						MMC_LOCK_MODE_SET_PWD);
+				if (!err)
+					return len;
+			} else
+				DBG("request_key returned error %ld\n",
+						PTR_ERR(mmc_key));
+	} else if (mmc_card_locked(card) && !strncmp(data, "unlock", 6)) {
+			/* unlock */
+			struct key *mmc_key = request_key(&mmc_key_type,
+					"mmc:key", "unlock");
+			if (!IS_ERR(mmc_key)) {
+				int err = mmc_lock_unlock(card, mmc_key,
+						MMC_LOCK_MODE_UNLOCK);
+				if (err)
+					DBG("Wrong password\n");
+				device_release_driver(dev);
+				device_attach(dev);
+				if (!err)
+					return len;
+			} else
+				DBG("request_key returned error %ld\n",
+						PTR_ERR(mmc_key));
+	} else if (!mmc_card_locked(card) && !strncmp(data, "assign", 6)) {
+			/* assign */
+			struct key *mmc_key = request_key(&mmc_key_type,
+					"mmc:key", "assign");
+			if (!IS_ERR(mmc_key)) {
+			int err = mmc_lock_unlock(card, mmc_key,
+					MMC_LOCK_MODE_SET_PWD);
+			if (!err)
+				return len;
+			} else
+				DBG("request_key returned error %ld\n",
+						PTR_ERR(mmc_key));
+	}
+
+	return -EINVAL;
+}
+
+static struct device_attribute mmc_dev_attr_lockable =
+	__ATTR(lockable, S_IWUSR | S_IRUGO,
+		 mmc_lockable_show, mmc_lockable_store);
+
+#endif
+
 
 static void mmc_release_card(struct device *dev)
 {
@@ -233,6 +335,11 @@ int mmc_register_card(struct mmc_card *c
 			if (ret)
 				device_del(&card->dev);
 		}
+#ifdef CONFIG_MMC_PASSWORDS
+		ret = device_create_file(&card->dev, &mmc_dev_attr_lockable);
+		if (ret)
+			device_del(&card->dev);
+#endif
 	}
 	return ret;
 }
@@ -246,7 +353,9 @@ void mmc_remove_card(struct mmc_card *ca
 	if (mmc_card_present(card)) {
 		if (mmc_card_sd(card))
 			device_remove_file(&card->dev, &mmc_dev_attr_scr);
-
+#ifdef CONFIG_MMC_PASSWORDS
+		device_remove_file(&card->dev, &mmc_dev_attr_lockable);
+#endif
 		device_del(&card->dev);
 	}
 

--

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [patch 5/6] Add MMC password protection (lock/unlock) support V4
  2006-01-31 20:16 [patch 0/6] Add MMC password protection (lock/unlock) support V4 Carlos Aguiar
                   ` (3 preceding siblings ...)
  2006-01-31 20:16 ` [patch 4/6] " Carlos Aguiar
@ 2006-01-31 20:16 ` Carlos Aguiar
  2006-01-31 20:16 ` [patch 6/6] " Carlos Aguiar
  5 siblings, 0 replies; 7+ messages in thread
From: Carlos Aguiar @ 2006-01-31 20:16 UTC (permalink / raw)
  To: linux-kernel, Linux-omap-open-source@linux.omap.com
  Cc: linux, David Brownell, Tony Lindgren, Russell King,
	Aguiar Carlos (EXT-INdT/Manaus),
	Lizardo Anderson (EXT-INdT/Manaus),
	Anderson Briglia

[-- Attachment #1: mmc_omap_blklen.diff --]
[-- Type: text/plain, Size: 1192 bytes --]

The MMC_LOCK_UNLOCK command requires the block length to be exactly the
password length + 2 bytes, but hardware-specific drivers force a "power of 2"
block size.

This patch sends the exact block size (password + 2 bytes) to the host. OMAP
specific.

Signed-off-by: Anderson Briglia <anderson.briglia@indt.org.br>
Signed-off-by: Anderson Lizardo <anderson.lizardo@indt.org.br>
Signed-off-by: Carlos Eduardo Aguiar <carlos.aguiar@indt.org.br>

Index: linux-omap-2.6.git/drivers/mmc/omap.c
===================================================================
--- linux-omap-2.6.git.orig/drivers/mmc/omap.c	2006-01-31 15:17:44.000000000 -0400
+++ linux-omap-2.6.git/drivers/mmc/omap.c	2006-01-31 15:22:33.000000000 -0400
@@ -888,8 +888,12 @@ mmc_omap_prepare_data(struct mmc_omap_ho
 		return;
 	}
 
-
-	block_size = 1 << data->blksz_bits;
+	/*  password protection: we need to send the exact block size to the
+	 *  card (password + 2), not a 2-exponent. */
+	if (req->cmd->opcode == MMC_LOCK_UNLOCK)
+		block_size = data->sg[0].length;
+	else
+		block_size = 1 << data->blksz_bits;
 
 	OMAP_MMC_WRITE(host->base, NBLK, data->blocks - 1);
 	OMAP_MMC_WRITE(host->base, BLEN, block_size - 1);

--

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [patch 6/6] Add MMC password protection (lock/unlock) support V4
  2006-01-31 20:16 [patch 0/6] Add MMC password protection (lock/unlock) support V4 Carlos Aguiar
                   ` (4 preceding siblings ...)
  2006-01-31 20:16 ` [patch 5/6] " Carlos Aguiar
@ 2006-01-31 20:16 ` Carlos Aguiar
  5 siblings, 0 replies; 7+ messages in thread
From: Carlos Aguiar @ 2006-01-31 20:16 UTC (permalink / raw)
  To: linux-kernel, Linux-omap-open-source@linux.omap.com
  Cc: linux, David Brownell, Tony Lindgren, Russell King,
	Aguiar Carlos (EXT-INdT/Manaus),
	Lizardo Anderson (EXT-INdT/Manaus),
	Anderson Briglia

[-- Attachment #1: mmc_omap_cap.diff --]
[-- Type: text/plain, Size: 808 bytes --]

Patch to add the host MMC lock/unlock capability support for OMAP platform.

Signed-off-by: Anderson Briglia <anderson.briglia@indt.org.br>
Signed-off-by: Anderson Lizardo <anderson.lizardo@indt.org.br>
Signed-off-by: Carlos Eduardo Aguiar <carlos.aguiar@indt.org.br>

Index: linux-omap-2.6.git/drivers/mmc/omap.c
===================================================================
--- linux-omap-2.6.git.orig/drivers/mmc/omap.c	2006-01-31 15:22:33.000000000 -0400
+++ linux-omap-2.6.git/drivers/mmc/omap.c	2006-01-31 15:22:36.000000000 -0400
@@ -1235,6 +1235,9 @@ static int __init mmc_omap_probe(struct 
 
 	 if (minfo->wire4)
 		 mmc->caps |= MMC_CAP_4_BIT_DATA;
+	
+	/* Sets the lock/unlock capability */
+	host->mmc->caps |= MMC_CAP_LOCK_UNLOCK;
 
 	mmc->ops = &mmc_omap_ops;
 	mmc->f_min = 400000;

--

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2006-01-31 21:03 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-01-31 20:16 [patch 0/6] Add MMC password protection (lock/unlock) support V4 Carlos Aguiar
2006-01-31 20:16 ` [patch 1/6] " Carlos Aguiar
2006-01-31 20:16 ` [patch 2/6] " Carlos Aguiar
2006-01-31 20:16 ` [patch 3/6] " Carlos Aguiar
2006-01-31 20:16 ` [patch 4/6] " Carlos Aguiar
2006-01-31 20:16 ` [patch 5/6] " Carlos Aguiar
2006-01-31 20:16 ` [patch 6/6] " Carlos Aguiar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).