mmc_rpmb.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775
  1. /* Copyright Statement:
  2. *
  3. * This software/firmware and related documentation ("MediaTek Software") are
  4. * protected under relevant copyright laws. The information contained herein
  5. * is confidential and proprietary to MediaTek Inc. and/or its licensors.
  6. * Without the prior written permission of MediaTek inc. and/or its licensors,
  7. * any reproduction, modification, use or disclosure of MediaTek Software,
  8. * and information contained herein, in whole or in part, shall be strictly prohibited.
  9. */
  10. /* MediaTek Inc. (C) 2018. All rights reserved.
  11. *
  12. * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
  13. * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
  14. * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
  15. * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
  18. * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
  19. * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
  20. * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
  21. * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
  22. * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
  23. * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
  24. * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
  25. * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
  26. * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
  27. * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
  28. * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
  29. * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
  30. *
  31. * The following software/firmware and/or related documentation ("MediaTek Software")
  32. * have been modified by MediaTek Inc. All revisions are subject to any receiver\'s
  33. * applicable license agreements with MediaTek Inc.
  34. */
  35. #include "msdc.h"
  36. #include "mmc_rpmb.h"
  37. #include "memory_layout.h"
  38. #define RPMB_KEY_DUMP 0
  39. #if defined(MMC_MSDC_DRV_LK)
  40. extern int32_t rpmb_hmac(uint32_t pattern, uint32_t size);
  41. extern int32_t rpmb_init(void);
  42. u32 *shared_msg_addr =(u32 *)(LK_HMAC_BASE+0x40);
  43. u32 *shared_hmac_addr = (u32 *)(LK_HMAC_BASE+0xCE0);
  44. #include <stdlib.h>
  45. #include <arch/arm/mmu.h>
  46. #include <arch/ops.h>
  47. //For arch_clean_invalidate_cache_range() is defined in bootable/bootloader/include/arch/ops.h
  48. #endif
  49. #ifndef swab16
  50. #define swab16(x) \
  51. ((u16)( \
  52. (((u16)(x) & (u16)0x00ffU) << 8) | \
  53. (((u16)(x) & (u16)0xff00U) >> 8) ))
  54. #endif
  55. #ifndef swab32
  56. #define swab32(x) \
  57. ((u32)( \
  58. (((u32)(x) & (u32)0x000000ffUL) << 24) | \
  59. (((u32)(x) & (u32)0x0000ff00UL) << 8) | \
  60. (((u32)(x) & (u32)0x00ff0000UL) >> 8) | \
  61. (((u32)(x) & (u32)0xff000000UL) >> 24) ))
  62. #endif
  63. #ifndef cpu_to_be16
  64. #define cpu_to_be16(x) ({ u16 _x = x; swab16(_x); })
  65. #endif
  66. #ifndef cpu_to_be32
  67. #define cpu_to_be32(x) ({ u32 _x = x; swab32(_x); })
  68. #endif
  69. #ifndef be16_to_cpu
  70. #define be16_to_cpu(x) cpu_to_be16(x)
  71. #endif
  72. #ifndef be32_to_cpu
  73. #define be32_to_cpu(x) cpu_to_be32(x)
  74. #endif
  75. static const char * const rpmb_err_msg[] = {
  76. "",
  77. "General failure",
  78. "Authentication failure",
  79. "Counter failure",
  80. "Address failure",
  81. "Write failure",
  82. "Read failure",
  83. "Authentication key not yet programmed",
  84. };
  85. #if defined(MMC_MSDC_DRV_LK) && !defined(MTK_UFS_SUPPORT)
  86. /*
  87. * CVE-2020-0436
  88. * Increase the write count to prevent DOS attack
  89. */
  90. #define MMC_DUMMY_WRITE_RPMB
  91. static void mmc_dummy_rpmb_write();
  92. extern bool emmc_boot;
  93. int init_rpmb_sharemem(void)
  94. {
  95. uint32_t start, size;
  96. int ret = 0;
  97. /* map shared memory for rpmb */
  98. start = ROUNDDOWN((uint32_t)LK_HMAC_BASE, PAGE_SIZE);
  99. size = PAGE_SIZE;
  100. arch_mmu_map((uint64_t)start, (uint32_t)start,
  101. MMU_MEMORY_TYPE_NORMAL_WRITE_BACK | MMU_MEMORY_AP_P_RW_U_NA,
  102. ROUNDUP(size, PAGE_SIZE));
  103. ret = rpmb_init();
  104. if (ret) {
  105. msdc_pr_err("[%s]: RPMB rpmb_init error, ret = %d \n", __func__, ret);
  106. return ret;
  107. }
  108. #ifdef MMC_DUMMY_WRITE_RPMB
  109. if (emmc_boot)
  110. mmc_dummy_rpmb_write();
  111. #endif
  112. return 0;
  113. }
  114. #endif
  115. static int mmc_rpmb_pre_frame(struct mmc_rpmb_req *rpmb_req)
  116. {
  117. struct mmc_rpmb_cfg *rpmb_cfg = rpmb_req->rpmb_cfg;
  118. u8 *data_frame = rpmb_req->data_frame;
  119. #if defined(MMC_MSDC_DRV_LK)
  120. u32 wc;
  121. #endif
  122. u16 blks = rpmb_cfg->blk_cnt;
  123. u16 addr;
  124. u16 type;
  125. u8 *nonce = rpmb_cfg->nonce;
  126. memset(data_frame, 0, 512 * blks);
  127. type = cpu_to_be16(rpmb_cfg->type);
  128. memcpy(data_frame + RPMB_TYPE_BEG, &type, 2);
  129. if (rpmb_cfg->type == RPMB_PROGRAM_KEY) {
  130. memcpy(data_frame + RPMB_MAC_BEG, rpmb_cfg->mac, RPMB_SZ_MAC);
  131. } else if (rpmb_cfg->type == RPMB_GET_WRITE_COUNTER ||
  132. rpmb_cfg->type == RPMB_READ_DATA) {
  133. /*
  134. * One package prepared
  135. * This request needs Nonce and type
  136. * If is data read, then also need addr
  137. */
  138. if (rpmb_cfg->type == RPMB_READ_DATA) {
  139. addr = cpu_to_be16(rpmb_cfg->addr);
  140. memcpy(data_frame + RPMB_ADDR_BEG, &addr, 2);
  141. }
  142. /* convert Nonce code */
  143. memcpy(data_frame + RPMB_NONCE_BEG, nonce, RPMB_SZ_NONCE);
  144. #if defined(MMC_MSDC_DRV_LK)
  145. } else if (rpmb_cfg->type == RPMB_WRITE_DATA) {
  146. addr = cpu_to_be16(rpmb_cfg->addr);
  147. memcpy(data_frame + RPMB_ADDR_BEG, &addr, 2);
  148. wc = cpu_to_be32(rpmb_cfg->wc);
  149. memcpy(data_frame + RPMB_WCOUNTER_BEG, &wc, 4);
  150. blks = cpu_to_be16(rpmb_cfg->blk_cnt);
  151. memcpy(data_frame + RPMB_BLKS_BEG, &blks, 2);
  152. #endif
  153. }
  154. return 0;
  155. }
  156. static int mmc_rpmb_post_frame(struct mmc_rpmb_req *rpmb_req)
  157. {
  158. struct mmc_rpmb_cfg *rpmb_cfg = rpmb_req->rpmb_cfg;
  159. u8 *data_frame = rpmb_req->data_frame;
  160. u16 result;
  161. memcpy(&result, data_frame + RPMB_RES_BEG, 2);
  162. rpmb_cfg->result = cpu_to_be16(result);
  163. if (rpmb_cfg->type == RPMB_GET_WRITE_COUNTER ||
  164. rpmb_cfg->type == RPMB_WRITE_DATA) {
  165. rpmb_cfg->wc = cpu_to_be32(*(u32 *)&data_frame[RPMB_WCOUNTER_BEG]);
  166. msdc_pr_info("%s, rpmb_cfg->wc = %x\n", __func__, rpmb_cfg->wc);
  167. }
  168. if (rpmb_cfg->type == RPMB_GET_WRITE_COUNTER ||
  169. rpmb_cfg->type == RPMB_READ_DATA) {
  170. /* nonce copy */
  171. memcpy(rpmb_cfg->nonce, data_frame + RPMB_NONCE_BEG, RPMB_SZ_NONCE);
  172. }
  173. if (rpmb_cfg->mac) {
  174. /*
  175. * To do. compute if mac is legal or not. Current we don't do this since we just perform get wc to check if we need set key.
  176. */
  177. #if defined(MMC_MSDC_DRV_LK)
  178. memcpy(rpmb_cfg->mac, data_frame + RPMB_MAC_BEG, RPMB_SZ_MAC);
  179. #endif
  180. }
  181. return 0;
  182. }
  183. static int mmc_rpmb_send_command(struct mmc_card *card, u8 *data_frame, u16 blks, u16 type, u8 req_type)
  184. {
  185. struct mmc_host *host = card->host;
  186. int err;
  187. /*
  188. * Auto CMD23 and CMD25 or CMD18
  189. */
  190. if ((req_type == RPMB_REQ && type == RPMB_WRITE_DATA) ||
  191. (req_type == RPMB_REQ && type == RPMB_PROGRAM_KEY))
  192. msdc_set_reliable_write(host, 1);
  193. else
  194. msdc_set_reliable_write(host, 0);
  195. msdc_set_autocmd(host, MSDC_AUTOCMD23, 1);
  196. if (req_type == RPMB_REQ)
  197. err = mmc_block_write(0, 0, blks, (unsigned long *) data_frame);
  198. else
  199. err = mmc_block_read(0, 0, blks, (unsigned long *) data_frame);
  200. msdc_set_autocmd(host, MSDC_AUTOCMD23, 0);
  201. if (err)
  202. msdc_pr_err("%s: CMD%s failed. (%d)\n", __func__, ((req_type==RPMB_REQ) ? "25":"18"), err);
  203. return err;
  204. }
  205. static int mmc_rpmb_start_req(struct mmc_card *card, struct mmc_rpmb_req *rpmb_req)
  206. {
  207. int err = 0;
  208. u16 blks = rpmb_req->rpmb_cfg->blk_cnt;
  209. u16 type = rpmb_req->rpmb_cfg->type;
  210. u8 *data_frame = rpmb_req->data_frame;
  211. /*
  212. * STEP 1: send request to RPMB partition
  213. */
  214. if (type == RPMB_WRITE_DATA)
  215. err = mmc_rpmb_send_command(card, data_frame, blks, type, RPMB_REQ);
  216. else
  217. err = mmc_rpmb_send_command(card, data_frame, 1, type, RPMB_REQ);
  218. if (err) {
  219. msdc_pr_err("%s step 1, request failed (%d)\n", __func__, err);
  220. goto out;
  221. }
  222. /*
  223. * STEP 2: check write result
  224. * Only for WRITE_DATA or Program key
  225. */
  226. memset(data_frame, 0, 512 * blks);
  227. if (type == RPMB_WRITE_DATA || type == RPMB_PROGRAM_KEY) {
  228. data_frame[RPMB_TYPE_BEG + 1] = RPMB_RESULT_READ;
  229. err = mmc_rpmb_send_command(card, data_frame, 1, RPMB_RESULT_READ, RPMB_REQ);
  230. if (err) {
  231. msdc_pr_err("%s step 2, request result failed (%d)\n", __func__, err);
  232. goto out;
  233. }
  234. }
  235. /*
  236. * STEP 3: get response from RPMB partition
  237. */
  238. data_frame[RPMB_TYPE_BEG] = 0;
  239. data_frame[RPMB_TYPE_BEG + 1] = type;
  240. if (type == RPMB_READ_DATA)
  241. err = mmc_rpmb_send_command(card, data_frame, blks, type, RPMB_RESP);
  242. else
  243. err = mmc_rpmb_send_command(card, data_frame, 1, type, RPMB_RESP);
  244. if (err) {
  245. msdc_pr_err("%s step 3, response failed (%d)\n", __func__, err);
  246. }
  247. out:
  248. return err;
  249. }
  250. int mmc_rpmb_check_result(u16 result)
  251. {
  252. if (result) {
  253. msdc_pr_err("%s %s %s\n", __func__, rpmb_err_msg[result & 0x7],
  254. (result & 0x80) ? "Write counter has expired" : "");
  255. }
  256. return result;
  257. }
  258. int mmc_rpmb_get_wc(u32 *wc, int *rpmb_result)
  259. {
  260. struct mmc_card *card = mmc_get_card(0);
  261. struct mmc_rpmb_cfg rpmb_cfg;
  262. struct mmc_rpmb_req rpmb_req;
  263. u8 *ext_csd = &card->raw_ext_csd[0];
  264. u8 rpmb_frame[512];
  265. u8 nonce[16];
  266. u8 val;
  267. int ret = 0;
  268. memset(&rpmb_cfg, 0, sizeof(struct mmc_rpmb_cfg));
  269. memset(nonce, 0, 16);
  270. rpmb_cfg.type = RPMB_GET_WRITE_COUNTER;
  271. rpmb_cfg.result = 0;
  272. rpmb_cfg.blk_cnt = 1;
  273. rpmb_cfg.addr = 0;
  274. rpmb_cfg.wc = 0;
  275. rpmb_cfg.nonce = nonce;
  276. rpmb_cfg.data = NULL;
  277. rpmb_cfg.mac = NULL;
  278. /*
  279. * 1. Switch to RPMB partition.
  280. */
  281. val = (ext_csd[EXT_CSD_PART_CFG] & ~0x7) | (EXT_CSD_PART_CFG_RPMB_PART & 0x7);
  282. ret = mmc_set_part_config(card, val);
  283. if (ret) {
  284. msdc_pr_err("%s, mmc_set_part_config failed!! (%x)\n", __func__, ret);
  285. return ret;
  286. }
  287. msdc_pr_info("%s, mmc_set_part_config done!!\n", __func__);
  288. rpmb_req.rpmb_cfg = &rpmb_cfg;
  289. rpmb_req.data_frame = rpmb_frame;
  290. /*
  291. * 2. Prepare get wc data frame.
  292. */
  293. ret = mmc_rpmb_pre_frame(&rpmb_req);
  294. /*
  295. * 3. CMD 23 and followed CMD25/18 procedure.
  296. */
  297. ret = mmc_rpmb_start_req(card, &rpmb_req);
  298. if (ret) {
  299. msdc_pr_err("%s, mmc_rpmb_part_ops failed!! (%x)\n", __func__, ret);
  300. return ret;
  301. }
  302. ret = mmc_rpmb_post_frame(&rpmb_req);
  303. msdc_pr_info("%s, rpmb_req.result=%x\n", __func__, rpmb_cfg.result);
  304. #if defined(MMC_MSDC_DRV_LK)
  305. memcpy(shared_msg_addr, rpmb_frame + RPMB_DATA_BEG, 284);
  306. arch_clean_invalidate_cache_range((addr_t) LK_HMAC_BASE, 4096);
  307. ret = rpmb_hmac(0, 284);
  308. if (ret) {
  309. msdc_pr_err("%s, rpmb_hmac error.\n", __func__);
  310. }
  311. if (memcmp(rpmb_frame + RPMB_MAC_BEG, shared_hmac_addr, 32) != 0) {
  312. msdc_pr_err("%s, compare hmac error!!\n", __func__);
  313. return ret;
  314. }
  315. #endif
  316. //ret = be16_to_cpu(rpmb_req.result);
  317. /*
  318. * 4. Check result.
  319. */
  320. *rpmb_result = mmc_rpmb_check_result(rpmb_cfg.result);
  321. *wc = rpmb_cfg.wc;
  322. return ret;
  323. }
  324. #if CFG_RPMB_KEY_PROGRAMED_IN_KERNEL
  325. int mmc_rpmb_set_key(u8 *key, int *rpmb_result)
  326. {
  327. struct mmc_host *host = mmc_get_host(0);
  328. struct mmc_card *card = mmc_get_card(0);
  329. struct mmc_rpmb_cfg rpmb_cfg;
  330. struct mmc_rpmb_req rpmb_req;
  331. u8 *ext_csd = &card->raw_ext_csd[0];
  332. u16 result = 0;
  333. u8 rpmb_frame[512];
  334. u8 val;
  335. int ret;
  336. u32 wc;
  337. int i;
  338. *rpmb_result = 0;
  339. ret = mmc_rpmb_get_wc(&wc, rpmb_result);
  340. #if RPMB_KEY_DUMP
  341. printf("rpmb key=\n");
  342. for (i=0;i<32;i++)
  343. printf("0x%x, ", key[i]);
  344. printf("\n");
  345. #endif
  346. /* if any errors, return it */
  347. if (ret) {
  348. printf("%s, get wc failed!! (%d)\n", __func__, ret);
  349. return ret;
  350. }
  351. if (*rpmb_result != 7) {
  352. print("mmc rpmb key already programmed!!\n");
  353. return ret;
  354. }
  355. print("mmc rpmb key will be programmed in kernel, skip now!\n" );
  356. return ret;
  357. }
  358. #else
  359. int mmc_rpmb_set_key(u8 *key)
  360. {
  361. struct mmc_card *card = mmc_get_card(0);
  362. struct mmc_rpmb_cfg rpmb_cfg;
  363. struct mmc_rpmb_req rpmb_req;
  364. u8 *ext_csd = &card->raw_ext_csd[0];
  365. u8 rpmb_frame[512];
  366. u8 val;
  367. int ret, rpmb_result = 0;
  368. u32 wc;
  369. #if RPMB_KEY_DUMP
  370. int i;
  371. #endif
  372. ret = mmc_rpmb_get_wc(&wc, &rpmb_result);
  373. #if RPMB_KEY_DUMP
  374. msdc_pr_info("rpmb key=\n");
  375. for (i = 0; i < 32; i++)
  376. msdc_pr_info("0x%x, ", key[i]);
  377. #endif
  378. /* if any errors, return it */
  379. if (ret) {
  380. msdc_pr_err("%s, get wc failed!! (%d)\n", __func__, ret);
  381. return ret;
  382. }
  383. if (rpmb_result != 7) {
  384. msdc_pr_err("mmc rpmb key is already programmed!!\n");
  385. return ret;
  386. }
  387. memset(&rpmb_cfg, 0, sizeof(struct mmc_rpmb_cfg));
  388. rpmb_cfg.type = RPMB_PROGRAM_KEY;
  389. rpmb_cfg.result = 0;
  390. rpmb_cfg.blk_cnt = 1;
  391. rpmb_cfg.addr = 0;
  392. rpmb_cfg.wc = 0;
  393. rpmb_cfg.nonce = NULL;
  394. rpmb_cfg.data = NULL;
  395. rpmb_cfg.mac = key;
  396. /*
  397. * 1. Switch to RPMB partition.
  398. */
  399. val = (ext_csd[EXT_CSD_PART_CFG] & ~0x7) | (EXT_CSD_PART_CFG_RPMB_PART & 0x7);
  400. ret = mmc_set_part_config(card, val);
  401. if (ret) {
  402. msdc_pr_err("%s, mmc_set_part_config failed!! (%x)\n", __func__, ret);
  403. return ret;
  404. }
  405. rpmb_req.rpmb_cfg = &rpmb_cfg;
  406. rpmb_req.data_frame = rpmb_frame;
  407. /*
  408. * 2. Prepare program key data frame.
  409. */
  410. ret = mmc_rpmb_pre_frame(&rpmb_req);
  411. /*
  412. * 3. CMD 23 and followed CMD25/18 procedure.
  413. */
  414. ret = mmc_rpmb_start_req(card, &rpmb_req);
  415. if (ret) {
  416. msdc_pr_err("%s, mmc_rpmb_part_ops failed!! (%x)\n", __func__, ret);
  417. return ret;
  418. }
  419. ret = mmc_rpmb_post_frame(&rpmb_req);
  420. msdc_pr_info("%s, rpmb_req.result=%x\n", __func__, rpmb_cfg.result);
  421. //ret = be16_to_cpu(rpmb_req.result);
  422. /*
  423. * 4. Check result.
  424. */
  425. ret = mmc_rpmb_check_result(rpmb_cfg.result);
  426. if (ret == 0)
  427. msdc_pr_info("RPMB key is successfully programmed!!\n");
  428. return ret;
  429. }
  430. #endif
  431. u32 mmc_rpmb_get_size(void)
  432. {
  433. struct mmc_card *card = mmc_get_card(0);
  434. u8 *ext_csd = &card->raw_ext_csd[0];
  435. return ext_csd[EXT_CSD_RPMB_SIZE_MULT] * 128 * 1024;
  436. }
  437. //get ext_csd[222]
  438. u32 mmc_rpmb_get_rel_wr_sec_c(void)
  439. {
  440. struct mmc_card *card = mmc_get_card(0);
  441. u8 *ext_csd = &card->raw_ext_csd[0];
  442. printf("RPMB rel_wr_sec=%d\n", ext_csd[EXT_CSD_REL_WR_SEC_C]);
  443. return ext_csd[EXT_CSD_REL_WR_SEC_C];
  444. }
  445. #if defined(MMC_MSDC_DRV_LK)
  446. #define RPMB_DUMMY_SIZE 256
  447. /*
  448. * Make sure the write count is incremented at every boot time.
  449. * to prevent linux kernel Replay Attacks.
  450. */
  451. static void mmc_dummy_rpmb_write()
  452. {
  453. int ret = 0;
  454. u8 data_buf[RPMB_DUMMY_SIZE] = {0};
  455. ret = mmc_rpmb_read_data(0x0, data_buf, RPMB_DUMMY_SIZE);
  456. if (ret) {
  457. msdc_pr_err("[%s] mmc_dummy_rpmb_read failed\n", __func__);
  458. return;
  459. }
  460. ret = mmc_rpmb_write_data(0x0, data_buf, RPMB_DUMMY_SIZE);
  461. if (ret)
  462. msdc_pr_err("[%s] mmc_dummy_rpmb_write failed\n", __func__);
  463. }
  464. int mmc_rpmb_read_data(u32 blkAddr, u32 *buf, u32 bufLen)
  465. {
  466. struct mmc_card *card = mmc_get_card(0);
  467. struct mmc_rpmb_cfg rpmb_cfg;
  468. struct mmc_rpmb_req rpmb_req;
  469. u32 blkLen;
  470. u32 left_size = bufLen;
  471. u32 tran_size;
  472. u8 *ext_csd = &card->raw_ext_csd[0];
  473. u8 rpmb_frame[512];
  474. u8 nonce[16];
  475. u8 val;
  476. u32 ret = 0, i;
  477. /*
  478. * 1. Switch to RPMB partition.
  479. */
  480. val = (ext_csd[EXT_CSD_PART_CFG] & ~0x7) | (EXT_CSD_PART_CFG_RPMB_PART & 0x7);
  481. ret = mmc_set_part_config(card, val);
  482. if (ret) {
  483. msdc_pr_err("%s, mmc_set_part_config failed!! (%x)\n", __func__, ret);
  484. return ret;
  485. }
  486. msdc_pr_info("%s, mmc_set_part_config done!!\n", __func__);
  487. blkLen = (bufLen % RPMB_SZ_DATA) ? (bufLen / RPMB_SZ_DATA + 1) : (bufLen / RPMB_SZ_DATA);
  488. for (i = 0; i < blkLen; i++) {
  489. memset(&rpmb_cfg, 0, sizeof(struct mmc_rpmb_cfg));
  490. memset(nonce, 0, 16);
  491. rpmb_cfg.type = RPMB_READ_DATA;
  492. rpmb_cfg.result = 0;
  493. rpmb_cfg.blk_cnt = 1;
  494. rpmb_cfg.addr = blkAddr + i;
  495. rpmb_cfg.wc = 0;
  496. rpmb_cfg.nonce = nonce;
  497. rpmb_cfg.data = NULL;
  498. rpmb_cfg.mac = NULL;
  499. rpmb_req.rpmb_cfg = &rpmb_cfg;
  500. rpmb_req.data_frame = rpmb_frame;
  501. /*
  502. * 2. Prepare read data frame.
  503. */
  504. ret = mmc_rpmb_pre_frame(&rpmb_req);
  505. /*
  506. * 3. CMD 23 and followed CMD25/18 procedure.
  507. */
  508. ret = mmc_rpmb_start_req(card, &rpmb_req);
  509. if (ret) {
  510. msdc_pr_err("%s, mmc_rpmb_start_req failed!! (%x)\n", __func__, ret);
  511. return ret;
  512. }
  513. ret = mmc_rpmb_post_frame(&rpmb_req);
  514. msdc_pr_info("%s, rpmb_req.result=%x\n", __func__, rpmb_cfg.result);
  515. //ret = be16_to_cpu(rpmb_req.result);
  516. /*
  517. * 4. Authenticate hmac.
  518. */
  519. memcpy(shared_msg_addr, rpmb_frame + RPMB_DATA_BEG, 284);
  520. arch_clean_invalidate_cache_range((addr_t) LK_HMAC_BASE, 4096);
  521. ret = rpmb_hmac(0, 284);
  522. if (ret) {
  523. msdc_pr_err("%s, rpmb_hmac error.\n", __func__);
  524. }
  525. if (memcmp(rpmb_frame + RPMB_MAC_BEG, shared_hmac_addr, 32) != 0) {
  526. msdc_pr_err("%s, compare hmac error!!\n", __func__);
  527. return ret;
  528. }
  529. /*
  530. * 5. Authenticate nonce.
  531. */
  532. if (memcmp(nonce, rpmb_cfg.nonce, RPMB_SZ_NONCE) != 0) {
  533. msdc_pr_err("%s, compare nonce error!!\n", __func__);
  534. return ret;
  535. }
  536. /*
  537. * 6. Check result.
  538. */
  539. if (mmc_rpmb_check_result(rpmb_cfg.result))
  540. return ret;
  541. if (left_size >= RPMB_SZ_DATA)
  542. tran_size = RPMB_SZ_DATA;
  543. else
  544. tran_size = left_size;
  545. memcpy((u8 *)buf + i * RPMB_SZ_DATA, rpmb_frame + RPMB_DATA_BEG, tran_size);
  546. left_size -= tran_size;
  547. }
  548. return ret;
  549. }
  550. int mmc_rpmb_write_data(u32 blkAddr, u32 *buf, u32 bufLen)
  551. {
  552. struct mmc_card *card = mmc_get_card(0);
  553. struct mmc_rpmb_cfg rpmb_cfg;
  554. struct mmc_rpmb_req rpmb_req;
  555. u32 blkLen;
  556. u32 left_size = bufLen;
  557. u32 tran_size;
  558. u8 rpmb_frame[512];
  559. int ret = 0, rpmb_result = 0;
  560. u32 wc;
  561. u32 i;
  562. blkLen = (bufLen % RPMB_SZ_DATA) ? (bufLen / RPMB_SZ_DATA + 1) : (bufLen / RPMB_SZ_DATA);
  563. for (i = 0; i < blkLen; i++) {
  564. ret = mmc_rpmb_get_wc(&wc, &rpmb_result);
  565. /* if any errors, return it */
  566. if (ret) {
  567. msdc_pr_err("%s, get wc failed!! (%d)\n", __func__, ret);
  568. return ret;
  569. }
  570. memset(&rpmb_cfg, 0, sizeof(struct mmc_rpmb_cfg));
  571. rpmb_cfg.type = RPMB_WRITE_DATA;
  572. rpmb_cfg.result = 0;
  573. rpmb_cfg.blk_cnt = 1;
  574. rpmb_cfg.addr = blkAddr + i;
  575. rpmb_cfg.wc = wc;
  576. rpmb_cfg.nonce = NULL;
  577. rpmb_cfg.data = (u8 *)buf;
  578. rpmb_cfg.mac = NULL;
  579. rpmb_req.rpmb_cfg = &rpmb_cfg;
  580. rpmb_req.data_frame = rpmb_frame;
  581. /*
  582. * 1. Prepare write data frame.
  583. */
  584. ret = mmc_rpmb_pre_frame(&rpmb_req);
  585. if (left_size >= RPMB_SZ_DATA)
  586. tran_size = RPMB_SZ_DATA;
  587. else
  588. tran_size = left_size;
  589. memcpy(rpmb_frame + RPMB_DATA_BEG, (u8 *)buf + i * RPMB_SZ_DATA, tran_size);
  590. /*
  591. * 2. Compute hmac.
  592. */
  593. memcpy(shared_msg_addr, rpmb_frame + RPMB_DATA_BEG, 284);
  594. arch_clean_invalidate_cache_range((addr_t) LK_HMAC_BASE, 4096);
  595. ret = rpmb_hmac(0, 284);
  596. if (ret)
  597. msdc_pr_err("%s, rpmb_hmac error!!\n", __func__);
  598. memcpy(rpmb_frame + RPMB_MAC_BEG, shared_hmac_addr, 32);
  599. /*
  600. * 3. CMD 23 and followed CMD25/18 procedure.
  601. */
  602. ret = mmc_rpmb_start_req(card, &rpmb_req);
  603. if (ret) {
  604. msdc_pr_err("%s, mmc_rpmb_part_ops failed!! (%x)\n", __func__, ret);
  605. return ret;
  606. }
  607. ret = mmc_rpmb_post_frame(&rpmb_req);
  608. msdc_pr_info("%s, rpmb_req.result=%x\n", __func__, rpmb_cfg.result);
  609. /*
  610. * 4. Check result.
  611. */
  612. ret = mmc_rpmb_check_result(rpmb_cfg.result);
  613. if (ret)
  614. msdc_pr_err("%s, check result error!!\n", __func__);
  615. left_size -= tran_size;
  616. }
  617. return ret;
  618. }
  619. #endif