Rockchip Increases SD Card Encryption and Decryption Function

Keywords: git

Customer requirements:

Encrypted SD cards can only be used in fixed machines, and the machine can not read cards other than encryption cards.

 

Solutions:

1. How to identify the encryption card:

There are CSR registers in the SD card protocol, where bit25 is the card_is_lock flag

If it's 1, it's locked.

 

 

 

Decision Card Encryption Code:

@@ -993,15 +1033,33 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
 	 * Select card, as all following commands rely on that.
 	 */
 	if (!mmc_host_is_spi(host)) {
-		err = mmc_select_card(card);
+		err = mmc_select_card_with_resp(card,resp);//When sending the pick-up card, the response data is retrieved, and the response data format is R1.
+		printk("zztest---mmc_host_is_spi ok\n");
 		if (err)
 			goto free_card;
+		printk("---respis %x\n",resp[0]);
+		if(resp[0]&0x02000000){	//If lock's flag bit is 1, the password is passed in and decrypted		
+			printk("---sdcard is locked, clear lock---\n");
+			err = mmc_unlock_card(card,host);
+			if(err)
+				goto free_card;
+		}else{
+			//Normally, the next step is to set up the card, where the customer needs to report the error back directly.
+			printk("---sdcard is normal,dont setup it---\n");
+			err = -110;
+			goto free_card;
+		}
+		printk("zztest---mmc_clear_card ok\n");
 	}

 

2. How to decrypt:

SD card protocol refers to the lock and unlock command of SD card:

Bit3 is the erase mark

Bit2 is unlock, lock flag, 0unlock, 1lock

Bit1 is a password clearance flag and 1 is a password clearance flag.

Bit0 sets a password flag and a password for 1

PWDS_LEN is the password length

Password data is password data

3. Decrypt code:

int mmc_unlock_card(struct mmc_card *mmc,struct mmc_host *host)
+{
+	
+	struct mmc_request mrq = {NULL};
+	struct mmc_command cmd = {0};
+	struct mmc_data data = {0};
+	struct scatterlist sg;
+	int i ;
+	u8 *data_buf;
+	int err = 0;
+	
+	printk("mmc_unlock_emmc\n");
+	data_buf = kmalloc(512, GFP_KERNEL);
+	if (!data_buf)
+		return -ENOMEM;
+	//Pass in decryption Command + password
+	data_buf[0] = 0x00;
+	data_buf[1] = 0x08;
+	data_buf[2] = 'C';
+	data_buf[3] = 'h';
+	data_buf[4] = 'a';
+	data_buf[5] = 'n';
+	data_buf[6] = 'g';
+	data_buf[7] = 'h';
+	data_buf[8] = 'u';
+	data_buf[9] = 'a';
+	
+	if (mmc_set_blocklen(mmc, 512)){
+		printk("mmc_set_blocklen failed!\n");
+		return 0;
+	}
+	
+	mrq.cmd = &cmd;
+	mrq.data = &data;
+	
+	cmd.opcode = MMC_LOCK_UNLOCK;
+	cmd.arg = 0;//
+	cmd.flags = MMC_RSP_R1B | MMC_CMD_ADTC;;
+	cmd.retries = 3;
+	
+	data.blocks = 1;
+	data.blksz = 512;
+	data.flags = MMC_DATA_WRITE;
+
+	data.sg = &sg;
+	data.sg_len = 1;
+	sg_init_one(&sg, data_buf, 512);
+ 
+	mmc_set_data_timeout(&data,mmc);
+	mmc_wait_for_req(host, &mrq);
+	printk("zztest---mmc_set_data_timeout is OK\n");
+	kfree(data_buf);
+
+	for(i=0;i<4;i++){
+		printk("--rep_data is %d\n",cmd.resp[i]);
+	}
+	if (cmd.error)
+		return cmd.error;
+	if (data.error)
+		return data.error;
+	return err;	
+
+}

 

Complete code modification:

diff --git a/drivers/mmc/core/bus.h b/drivers/mmc/core/bus.h
old mode 100644
new mode 100755
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
old mode 100644
new mode 100755
index 5f46756..fc138f5
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -620,6 +620,7 @@ out:
 	return err;
 }
 
+
 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],
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
old mode 100644
new mode 100755
index 07fb48d..b6aff49
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -93,6 +93,40 @@ int mmc_deselect_cards(struct mmc_host *host)
 	return _mmc_select_card(host, NULL);
 }
 
+static int _mmc_select_card_with_resp(struct mmc_host *host, struct mmc_card *card,u32 *buf)
+{
+	int err;
+	struct mmc_command cmd = {0};
+
+	BUG_ON(!host);
+
+	cmd.opcode = MMC_SELECT_CARD;
+
+	if (card) {
+		cmd.arg = card->rca << 16;
+		cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
+	} else {
+		cmd.arg = 0;
+		cmd.flags = MMC_RSP_NONE | MMC_CMD_AC;
+	}
+
+	err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
+	if (err)
+		return err;
+
+	memcpy(buf, cmd.resp, sizeof(u32) * 4);
+	return 0;
+}
+
+
+int mmc_select_card_with_resp(struct mmc_card *card,u32 *buf)
+{
+	BUG_ON(!card);
+
+	return _mmc_select_card_with_resp(card->host, card,buf);
+}
+
+
 int mmc_go_idle(struct mmc_host *host)
 {
 	int err;
@@ -305,6 +339,197 @@ mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host,
 	return 0;
 }
 
+struct mmc_pwd{
+	u8 mode;
+	u8 pwd_len;
+	u8 pwd_data;
+};
+
+
+int mmc_lock_card(struct mmc_card* mmc ,struct mmc_host *host)
+{
+
+	struct mmc_request mrq = {NULL};
+	struct mmc_command cmd = {0};
+	struct mmc_data data = {0};
+	struct scatterlist sg;
+	u8 *data_buf;
+	int err = 0;
+	
+	printk("mmc_lock_emmc\n");
+	data_buf = kmalloc(512, GFP_KERNEL);
+	if (!data_buf)
+		return -ENOMEM;
+	
+	data_buf[0] = 0x01;
+	data_buf[1] = 0x08;
+	data_buf[2] = 'C';
+	data_buf[3] = 'h';
+	data_buf[4] = 'a';
+	data_buf[5] = 'n';
+	data_buf[6] = 'g';
+	data_buf[7] = 'h';
+	data_buf[8] = 'u';
+	data_buf[9] = 'a';
+	
+	if (mmc_set_blocklen(mmc, 512)){
+		printk("mmc_set_blocklen failed!\n");
+		return 0;
+	}
+	printk("zztest---mmc_set_blocklen OK\n");
+	
+	mrq.cmd = &cmd;
+	mrq.data = &data;
+	
+	cmd.opcode = MMC_LOCK_UNLOCK;
+	cmd.arg = 0;//
+	cmd.flags = MMC_RSP_R1B | MMC_CMD_ADTC;;
+	cmd.retries = 3;
+	
+	data.blocks = 1;
+	data.blksz = 512;
+	data.flags = MMC_DATA_WRITE;
+
+	data.sg = &sg;
+	data.sg_len = 1;
+	sg_init_one(&sg, data_buf, 512);
+ 
+	mmc_set_data_timeout(&data,mmc);
+	mmc_wait_for_req(host, &mrq);
+	
+	kfree(data_buf);
+	
+	if (cmd.error)
+		return cmd.error;
+	if (data.error)
+		return data.error;
+	return err;	
+}
+EXPORT_SYMBOL_GPL(mmc_lock_card);
+
+
+int mmc_unlock_card(struct mmc_card *mmc,struct mmc_host *host)
+{
+	
+	struct mmc_request mrq = {NULL};
+	struct mmc_command cmd = {0};
+	struct mmc_data data = {0};
+	struct scatterlist sg;
+	//u32 rep_data[4]={0};
+	int i ;
+	u8 *data_buf;
+	int err = 0;
+	
+	printk("mmc_unlock_emmc\n");
+	data_buf = kmalloc(512, GFP_KERNEL);
+	if (!data_buf)
+		return -ENOMEM;
+	
+	data_buf[0] = 0x00;
+	data_buf[1] = 0x08;
+	data_buf[2] = 'C';
+	data_buf[3] = 'h';
+	data_buf[4] = 'a';
+	data_buf[5] = 'n';
+	data_buf[6] = 'g';
+	data_buf[7] = 'h';
+	data_buf[8] = 'u';
+	data_buf[9] = 'a';
+	
+	if (mmc_set_blocklen(mmc, 512)){
+		printk("mmc_set_blocklen failed!\n");
+		return 0;
+	}
+	printk("zztest---mmc_set_blocklen OK\n");
+	
+	mrq.cmd = &cmd;
+	mrq.data = &data;
+	
+	cmd.opcode = MMC_LOCK_UNLOCK;
+	cmd.arg = 0;//
+	cmd.flags = MMC_RSP_R1B | MMC_CMD_ADTC;;
+	cmd.retries = 3;
+	
+	data.blocks = 1;
+	data.blksz = 512;
+	data.flags = MMC_DATA_WRITE;
+
+	data.sg = &sg;
+	data.sg_len = 1;
+	sg_init_one(&sg, data_buf, 512);
+ 
+	mmc_set_data_timeout(&data,mmc);
+	mmc_wait_for_req(host, &mrq);
+	printk("zztest---mmc_set_data_timeout is OK\n");
+	kfree(data_buf);
+
+	for(i=0;i<4;i++){
+		printk("--rep_data is %d\n",cmd.resp[i]);
+	}
+	if (cmd.error)
+		return cmd.error;
+	if (data.error)
+		return data.error;
+	return err;	
+
+}
+EXPORT_SYMBOL_GPL(mmc_unlock_card);
+
+struct mmc_pwd_clear{
+	u8 mode;
+};
+
+int mmc_clear_card(struct mmc_card *mmc,struct mmc_host *host)
+{
+	
+	struct mmc_request mrq = {NULL};
+	struct mmc_command cmd = {0};
+	struct mmc_data data = {0};
+	struct scatterlist sg;
+	u8 *data_buf;
+	int err = 0;
+	
+	printk("mmc_clear_emmc\n");
+		
+	data_buf = kmalloc(512, GFP_KERNEL);
+	if (!data_buf)
+		return -ENOMEM;
+
+	data_buf[0] = 0x08;
+	if (mmc_set_blocklen(mmc, 512)){
+		printk("mmc_set_blocklen failed!\n");
+		return 0;
+	}
+	printk("zztest---mmc_set_blocklen OK\n");
+	
+	mrq.cmd = &cmd;
+	mrq.data = &data;
+	cmd.opcode = MMC_LOCK_UNLOCK;
+	cmd.arg = 0;//
+	cmd.flags = MMC_RSP_R1| MMC_CMD_ADTC;
+	cmd.retries = 3;
+	
+	data.blocks = 1;
+	data.blksz = 512;
+	data.flags = MMC_DATA_WRITE;
+ 
+	data.sg = &sg;
+	data.sg_len = 1;
+ 
+	mmc_set_data_timeout(&data,mmc);
+	printk("zztest---mmc_set_data_timeout is OK\n");
+	sg_init_one(&sg, data_buf, 512);
+	mmc_wait_for_req(host, &mrq);
+	
+	kfree(data_buf);
+	if (cmd.error)
+		return cmd.error;
+	if (data.error)
+		return data.error;
+	return err;	
+}
+
+
 int mmc_send_csd(struct mmc_card *card, u32 *csd)
 {
 	int ret, i;
diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h
old mode 100644
new mode 100755
index 40f6648..ce78697
--- a/drivers/mmc/core/mmc_ops.h
+++ b/drivers/mmc/core/mmc_ops.h
@@ -27,5 +27,9 @@ 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_switch_status_error(struct mmc_host *host, u32 status);
+int mmc_lock_card(struct mmc_card* mmc ,struct mmc_host *host);
+int mmc_unlock_card(struct mmc_card* mmc ,struct mmc_host *host);
+int mmc_clear_card(struct mmc_card *mmc,struct mmc_host *host);
+int mmc_select_card_with_resp(struct mmc_card *card,u32 *buf);
 #endif
 
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
old mode 100644
new mode 100755
index b03fbd8..7cb29e7
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -676,6 +676,41 @@ out:
 	return err;
 }
 
+
+static ssize_t name_show(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	struct mmc_card *card = mmc_dev_to_card(dev);
+	struct mmc_host *host = card->host;	
+	int ret ;
+	if((card != NULL)&&(host != NULL)){
+		ret = mmc_lock_card(card,host);
+	}
+	if(ret)
+		printk("zztest--mmc_lock_card error\n");
+	return sprintf(buf, "%s\n", card->cid.prod_name);
+}
+
+static ssize_t oemid_show(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	struct mmc_card *card = mmc_dev_to_card(dev);
+	struct mmc_host *host = card->host;	
+	int ret ;
+	if((card != NULL)&&(host != NULL)){
+		ret = mmc_unlock_card(card,host);
+	}
+	//mmc_select_card(card,host);
+	if(ret)
+		printk("zztest--mmc_bus_test error\n");
+	return sprintf(buf, "%d\n", card->cid.oemid);
+}
+
+static DEVICE_ATTR(oemid, S_IRUGO, oemid_show, NULL);
+static DEVICE_ATTR(name, S_IRUGO, name_show, NULL);
+
 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],
@@ -687,8 +722,8 @@ MMC_DEV_ATTR(preferred_erase_size, "%u\n", card->pref_erase << 9);
 MMC_DEV_ATTR(fwrev, "0x%x\n", card->cid.fwrev);
 MMC_DEV_ATTR(hwrev, "0x%x\n", card->cid.hwrev);
 MMC_DEV_ATTR(manfid, "0x%06x\n", card->cid.manfid);
-MMC_DEV_ATTR(name, "%s\n", card->cid.prod_name);
-MMC_DEV_ATTR(oemid, "0x%04x\n", card->cid.oemid);
+//MMC_DEV_ATTR(name, "%s\n", card->cid.prod_name);
+//MMC_DEV_ATTR(oemid, "0x%04x\n", card->cid.oemid);
 MMC_DEV_ATTR(serial, "0x%08x\n", card->cid.serial);
 
 
@@ -939,10 +974,12 @@ void mmc_sd_go_highspeed(struct mmc_card *card)
  * In the case of a resume, "oldcard" will contain the card
  * we're trying to reinitialise.
  */
+
 static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
 	struct mmc_card *oldcard)
 {
 	struct mmc_card *card;
+	u32 resp[4]={0};
 	int err;
 	u32 cid[4];
 	u32 rocr = 0;
@@ -954,6 +991,7 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
 	if (err)
 		return err;
 
+	printk("zztest---mmc_sd_get_cid ok\n");
 	if (oldcard) {
 		if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0)
 			return -ENOENT;
@@ -977,12 +1015,14 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
 	 */
 	if (!mmc_host_is_spi(host)) {
 		err = mmc_send_relative_addr(host, &card->rca);
+		printk("zztest--mmc_send_relative_addr\n");
 		if (err)
 			goto free_card;
 	}
 
 	if (!oldcard) {
 		err = mmc_sd_get_csd(host, card);
+		printk("zztest--mmc_sd_get_csd\n");
 		if (err)
 			goto free_card;
 
@@ -993,15 +1033,33 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
 	 * Select card, as all following commands rely on that.
 	 */
 	if (!mmc_host_is_spi(host)) {
-		err = mmc_select_card(card);
+		err = mmc_select_card_with_resp(card,resp);
+		printk("zztest---mmc_host_is_spi ok\n");
 		if (err)
 			goto free_card;
+		printk("zztest---mmc_clear_card ok\n");
+		printk("---respis %x\n",resp[0]);
+		if(resp[0]&0x02000000){			
+			printk("---sdcard is locked, clear lock---\n");
+			err = mmc_unlock_card(card,host);
+			if(err)
+				goto free_card;
+		}else{
+			//Customer requirements, unconventional operations
+			printk("---sdcard is normal,dont setup it---\n");
+			err = -110;
+			goto free_card;
+		}
+		printk("zztest---mmc_clear_card ok\n");
 	}
 
+	
 	err = mmc_sd_setup_card(host, card, oldcard != NULL);
-	if (err)
+	if (err)	
 		goto free_card;
+		
 
+	printk("zztest---mmc_sd_setup_card ok\n");
 	/* Initialization sequence for UHS-I cards */
 	if (rocr & SD_ROCR_S18A) {
 		err = mmc_sd_init_uhs_card(card);
@@ -1295,6 +1353,7 @@ int mmc_attach_sd(struct mmc_host *host)
 		err = mmc_spi_read_ocr(host, 0, &ocr);
 		if (err)
 			goto err;
+		printk("zztest----mmc_spi_read_ocr ok\n");
 	}
 
 	rocr = mmc_select_voltage(host, ocr);
@@ -1306,7 +1365,7 @@ int mmc_attach_sd(struct mmc_host *host)
 		err = -EINVAL;
 		goto err;
 	}
-
+	printk("zztest----mmc_select_voltage ok\n");
 	/*
 	 * Detect and init the card.
 	 */
@@ -1314,6 +1373,7 @@ int mmc_attach_sd(struct mmc_host *host)
 	if (err)
 		goto err;
 
+	printk("zztest----mmc_sd_init_card ok\n");
 	mmc_release_host(host);
 	err = mmc_add_card(host->card);
 	mmc_claim_host(host);

 

 

Reference blog:

https://blog.csdn.net/g_salamander/article/details/14167055

https://blog.csdn.net/Code_DZhangTeng/article/details/79504643

 

 

 

 

 

 

 

Posted by jon23d on Tue, 30 Jul 2019 21:20:35 -0700