esp_efuse_api.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588
  1. // Copyright 2017-2018 Espressif Systems (Shanghai) PTE LTD
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. // http://www.apache.org/licenses/LICENSE-2.0
  7. //
  8. // Unless required by applicable law or agreed to in writing, software
  9. // distributed under the License is distributed on an "AS IS" BASIS,
  10. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. // See the License for the specific language governing permissions and
  12. // limitations under the License.
  13. #include "esp_efuse.h"
  14. #include "esp_efuse_utility.h"
  15. #include "soc/efuse_periph.h"
  16. #include "assert.h"
  17. #include "sdkconfig.h"
  18. #include "esp_efuse_table.h"
  19. const static char *TAG = "efuse";
  20. #if defined(BOOTLOADER_BUILD)
  21. #define EFUSE_LOCK_ACQUIRE_RECURSIVE()
  22. #define EFUSE_LOCK_RELEASE_RECURSIVE()
  23. #else
  24. #include <sys/lock.h>
  25. static _lock_t s_efuse_lock;
  26. #define EFUSE_LOCK_ACQUIRE_RECURSIVE() _lock_acquire_recursive(&s_efuse_lock)
  27. #define EFUSE_LOCK_RELEASE_RECURSIVE() _lock_release_recursive(&s_efuse_lock)
  28. #endif
  29. static int s_batch_writing_mode = 0;
  30. // Public API functions
  31. // read value from EFUSE, writing it into an array
  32. esp_err_t esp_efuse_read_field_blob(const esp_efuse_desc_t* field[], void* dst, size_t dst_size_bits)
  33. {
  34. EFUSE_LOCK_ACQUIRE_RECURSIVE();
  35. esp_err_t err = ESP_OK;
  36. if (field == NULL || dst == NULL || dst_size_bits == 0) {
  37. err = ESP_ERR_INVALID_ARG;
  38. } else {
  39. memset((uint8_t *)dst, 0, esp_efuse_utility_get_number_of_items(dst_size_bits, 8));
  40. err = esp_efuse_utility_process(field, dst, dst_size_bits, esp_efuse_utility_fill_buff);
  41. }
  42. EFUSE_LOCK_RELEASE_RECURSIVE();
  43. return err;
  44. }
  45. bool esp_efuse_read_field_bit(const esp_efuse_desc_t *field[])
  46. {
  47. uint8_t value = 0;
  48. esp_err_t err = esp_efuse_read_field_blob(field, &value, 1);
  49. assert(err == ESP_OK);
  50. return (err == ESP_OK) && value;
  51. }
  52. // read number of bits programmed as "1" in the particular field
  53. esp_err_t esp_efuse_read_field_cnt(const esp_efuse_desc_t* field[], size_t* out_cnt)
  54. {
  55. EFUSE_LOCK_ACQUIRE_RECURSIVE();
  56. esp_err_t err = ESP_OK;
  57. if (field == NULL || out_cnt == NULL) {
  58. err = ESP_ERR_INVALID_ARG;
  59. } else {
  60. *out_cnt = 0;
  61. err = esp_efuse_utility_process(field, out_cnt, 0, esp_efuse_utility_count_once);
  62. }
  63. EFUSE_LOCK_RELEASE_RECURSIVE();
  64. return err;
  65. }
  66. // write array to EFUSE
  67. esp_err_t esp_efuse_write_field_blob(const esp_efuse_desc_t* field[], const void* src, size_t src_size_bits)
  68. {
  69. EFUSE_LOCK_ACQUIRE_RECURSIVE();
  70. esp_err_t err = ESP_OK;
  71. if (field == NULL || src == NULL || src_size_bits == 0) {
  72. err = ESP_ERR_INVALID_ARG;
  73. } else {
  74. if (s_batch_writing_mode == 0) {
  75. esp_efuse_utility_reset();
  76. }
  77. err = esp_efuse_utility_process(field, (void*)src, src_size_bits, esp_efuse_utility_write_blob);
  78. if (s_batch_writing_mode == 0) {
  79. if (err == ESP_OK) {
  80. err = esp_efuse_utility_apply_new_coding_scheme();
  81. if (err == ESP_OK) {
  82. esp_efuse_utility_burn_efuses();
  83. }
  84. }
  85. esp_efuse_utility_reset();
  86. }
  87. }
  88. EFUSE_LOCK_RELEASE_RECURSIVE();
  89. return err;
  90. }
  91. // program cnt bits to "1"
  92. esp_err_t esp_efuse_write_field_cnt(const esp_efuse_desc_t* field[], size_t cnt)
  93. {
  94. EFUSE_LOCK_ACQUIRE_RECURSIVE();
  95. esp_err_t err = ESP_OK;
  96. if (field == NULL || cnt == 0) {
  97. err = ESP_ERR_INVALID_ARG;
  98. } else {
  99. if (s_batch_writing_mode == 0) {
  100. esp_efuse_utility_reset();
  101. }
  102. err = esp_efuse_utility_process(field, &cnt, 0, esp_efuse_utility_write_cnt);
  103. if (cnt != 0) {
  104. ESP_LOGE(TAG, "The required number of bits can not be set. [Not set %d]", cnt);
  105. err = ESP_ERR_EFUSE_CNT_IS_FULL;
  106. }
  107. if (err == ESP_OK_EFUSE_CNT) {
  108. err = ESP_OK;
  109. }
  110. if (s_batch_writing_mode == 0) {
  111. if (err == ESP_OK) {
  112. err = esp_efuse_utility_apply_new_coding_scheme();
  113. if (err == ESP_OK) {
  114. esp_efuse_utility_burn_efuses();
  115. }
  116. }
  117. esp_efuse_utility_reset();
  118. }
  119. }
  120. EFUSE_LOCK_RELEASE_RECURSIVE();
  121. return err;
  122. }
  123. esp_err_t esp_efuse_write_field_bit(const esp_efuse_desc_t* field[])
  124. {
  125. esp_err_t err;
  126. uint8_t existing = 0;
  127. const uint8_t one = 1;
  128. if (field == NULL || field[0]->bit_count != 1) {
  129. return ESP_ERR_INVALID_ARG;
  130. }
  131. /* Check existing value. esp_efuse_write_field_blob() also checks this, but will log an error */
  132. err = esp_efuse_read_field_blob(field, &existing, 1);
  133. if (err != ESP_OK || existing) {
  134. return err; // Error reading, or the bit is already written and we can no-op this
  135. }
  136. return esp_efuse_write_field_blob(field, &one, 1);
  137. }
  138. // get the length of the field in bits
  139. int esp_efuse_get_field_size(const esp_efuse_desc_t* field[])
  140. {
  141. int bits_counter = 0;
  142. if (field != NULL) {
  143. int i = 0;
  144. while (field[i] != NULL) {
  145. bits_counter += field[i]->bit_count;
  146. ++i;
  147. }
  148. }
  149. return bits_counter;
  150. }
  151. // reading efuse register.
  152. uint32_t esp_efuse_read_reg(esp_efuse_block_t blk, unsigned int num_reg)
  153. {
  154. EFUSE_LOCK_ACQUIRE_RECURSIVE();
  155. uint32_t ret_val = esp_efuse_utility_read_reg(blk, num_reg);
  156. EFUSE_LOCK_RELEASE_RECURSIVE();
  157. return ret_val;
  158. }
  159. // writing efuse register.
  160. esp_err_t esp_efuse_write_reg(esp_efuse_block_t blk, unsigned int num_reg, uint32_t val)
  161. {
  162. EFUSE_LOCK_ACQUIRE_RECURSIVE();
  163. if (s_batch_writing_mode == 0) {
  164. esp_efuse_utility_reset();
  165. }
  166. esp_err_t err = esp_efuse_utility_write_reg(blk, num_reg, val);
  167. if (s_batch_writing_mode == 0) {
  168. if (err == ESP_OK) {
  169. err = esp_efuse_utility_apply_new_coding_scheme();
  170. if (err == ESP_OK) {
  171. esp_efuse_utility_burn_efuses();
  172. }
  173. }
  174. esp_efuse_utility_reset();
  175. }
  176. EFUSE_LOCK_RELEASE_RECURSIVE();
  177. return err;
  178. }
  179. // This function reads the key from the efuse block, starting at the offset and the required size.
  180. esp_err_t esp_efuse_read_block(esp_efuse_block_t blk, void* dst_key, size_t offset_in_bits, size_t size_bits)
  181. {
  182. esp_err_t err = ESP_OK;
  183. if (blk == EFUSE_BLK0 || blk >= EFUSE_BLK_MAX || dst_key == NULL || size_bits == 0) {
  184. err = ESP_ERR_INVALID_ARG;
  185. } else {
  186. const esp_efuse_desc_t field_desc[] = {
  187. {blk, offset_in_bits, size_bits},
  188. };
  189. const esp_efuse_desc_t* field[] = {
  190. &field_desc[0],
  191. NULL
  192. };
  193. err = esp_efuse_read_field_blob(field, dst_key, size_bits);
  194. }
  195. return err;
  196. }
  197. // This function writes the key from the efuse block, starting at the offset and the required size.
  198. esp_err_t esp_efuse_write_block(esp_efuse_block_t blk, const void* src_key, size_t offset_in_bits, size_t size_bits)
  199. {
  200. esp_err_t err = ESP_OK;
  201. if (blk == EFUSE_BLK0 || blk >= EFUSE_BLK_MAX || src_key == NULL || size_bits == 0) {
  202. err = ESP_ERR_INVALID_ARG;
  203. } else {
  204. const esp_efuse_desc_t field_desc[] = {
  205. {blk, offset_in_bits, size_bits},
  206. };
  207. const esp_efuse_desc_t* field[] = {
  208. &field_desc[0],
  209. NULL
  210. };
  211. err = esp_efuse_write_field_blob(field, src_key, size_bits);
  212. }
  213. return err;
  214. }
  215. esp_err_t esp_efuse_batch_write_begin(void)
  216. {
  217. EFUSE_LOCK_ACQUIRE_RECURSIVE();
  218. assert(s_batch_writing_mode >= 0);
  219. if (++s_batch_writing_mode == 1) {
  220. esp_efuse_utility_reset();
  221. ESP_LOGI(TAG, "Batch mode of writing fields is enabled");
  222. };
  223. return ESP_OK;
  224. }
  225. esp_err_t esp_efuse_batch_write_cancel(void)
  226. {
  227. if (s_batch_writing_mode == 0) {
  228. ESP_LOGE(TAG, "Batch mode was not enabled");
  229. return ESP_ERR_INVALID_STATE;
  230. }
  231. if (--s_batch_writing_mode == 0) {
  232. esp_efuse_utility_reset();
  233. ESP_LOGI(TAG, "Batch mode of writing fields is cancelled");
  234. EFUSE_LOCK_RELEASE_RECURSIVE();
  235. }
  236. return ESP_OK;
  237. }
  238. esp_err_t esp_efuse_batch_write_commit(void)
  239. {
  240. if (s_batch_writing_mode == 0) {
  241. ESP_LOGE(TAG, "Batch mode was not enabled");
  242. return ESP_ERR_INVALID_STATE;
  243. }
  244. if (--s_batch_writing_mode == 0) {
  245. esp_err_t err = esp_efuse_utility_apply_new_coding_scheme();
  246. if (err == ESP_OK) {
  247. esp_efuse_utility_burn_efuses();
  248. ESP_LOGI(TAG, "Batch mode. Prepared fields are committed");
  249. } else {
  250. esp_efuse_utility_reset();
  251. }
  252. EFUSE_LOCK_RELEASE_RECURSIVE();
  253. return err;
  254. }
  255. return ESP_OK;
  256. }
  257. #ifndef CONFIG_IDF_TARGET_ESP32
  258. /**
  259. * @brief Keys and their attributes are packed into a structure
  260. */
  261. typedef struct {
  262. const esp_efuse_desc_t** key; /**< Key */
  263. const esp_efuse_desc_t** keypurpose; /**< Key purpose */
  264. const esp_efuse_desc_t** key_rd_dis; /**< Read protection of a key */
  265. const esp_efuse_desc_t** key_wr_dis; /**< Write protection of a key*/
  266. const esp_efuse_desc_t** keypurpose_wr_dis; /**< Write protection of a key purpose*/
  267. } esp_efuse_keys_t;
  268. typedef struct {
  269. const esp_efuse_desc_t** revoke;
  270. const esp_efuse_desc_t** revoke_wr_dis;
  271. } esp_efuse_revokes_t;
  272. const esp_efuse_keys_t s_table[EFUSE_BLK_KEY_MAX - EFUSE_BLK_KEY0] = {
  273. {ESP_EFUSE_KEY0, ESP_EFUSE_KEY_PURPOSE_0, ESP_EFUSE_RD_DIS_KEY0, ESP_EFUSE_WR_DIS_KEY0, ESP_EFUSE_WR_DIS_KEY0_PURPOSE},
  274. {ESP_EFUSE_KEY1, ESP_EFUSE_KEY_PURPOSE_1, ESP_EFUSE_RD_DIS_KEY1, ESP_EFUSE_WR_DIS_KEY1, ESP_EFUSE_WR_DIS_KEY1_PURPOSE},
  275. {ESP_EFUSE_KEY2, ESP_EFUSE_KEY_PURPOSE_2, ESP_EFUSE_RD_DIS_KEY2, ESP_EFUSE_WR_DIS_KEY2, ESP_EFUSE_WR_DIS_KEY2_PURPOSE},
  276. {ESP_EFUSE_KEY3, ESP_EFUSE_KEY_PURPOSE_3, ESP_EFUSE_RD_DIS_KEY3, ESP_EFUSE_WR_DIS_KEY3, ESP_EFUSE_WR_DIS_KEY3_PURPOSE},
  277. {ESP_EFUSE_KEY4, ESP_EFUSE_KEY_PURPOSE_4, ESP_EFUSE_RD_DIS_KEY4, ESP_EFUSE_WR_DIS_KEY4, ESP_EFUSE_WR_DIS_KEY4_PURPOSE},
  278. {ESP_EFUSE_KEY5, ESP_EFUSE_KEY_PURPOSE_5, ESP_EFUSE_RD_DIS_KEY5, ESP_EFUSE_WR_DIS_KEY5, ESP_EFUSE_WR_DIS_KEY5_PURPOSE},
  279. #if 0
  280. {ESP_EFUSE_KEY6, ESP_EFUSE_KEY_PURPOSE_6, ESP_EFUSE_RD_DIS_KEY6, ESP_EFUSE_WR_DIS_KEY6, ESP_EFUSE_WR_DIS_KEY6_PURPOSE},
  281. #endif
  282. };
  283. const esp_efuse_revokes_t s_revoke_table[] = {
  284. {ESP_EFUSE_SECURE_BOOT_KEY_REVOKE0, ESP_EFUSE_WR_DIS_SECURE_BOOT_KEY_REVOKE0},
  285. {ESP_EFUSE_SECURE_BOOT_KEY_REVOKE1, ESP_EFUSE_WR_DIS_SECURE_BOOT_KEY_REVOKE1},
  286. {ESP_EFUSE_SECURE_BOOT_KEY_REVOKE2, ESP_EFUSE_WR_DIS_SECURE_BOOT_KEY_REVOKE2},
  287. };
  288. #define ESP_EFUSE_CHK(ret) \
  289. do \
  290. { \
  291. if( ( err = (ret) ) != ESP_OK ) \
  292. goto err_exit; \
  293. } while( 0 )
  294. const esp_efuse_desc_t **esp_efuse_get_purpose_field(esp_efuse_block_t block)
  295. {
  296. switch(block) {
  297. case EFUSE_BLK_KEY0:
  298. return ESP_EFUSE_KEY_PURPOSE_0;
  299. case EFUSE_BLK_KEY1:
  300. return ESP_EFUSE_KEY_PURPOSE_1;
  301. case EFUSE_BLK_KEY2:
  302. return ESP_EFUSE_KEY_PURPOSE_2;
  303. case EFUSE_BLK_KEY3:
  304. return ESP_EFUSE_KEY_PURPOSE_3;
  305. case EFUSE_BLK_KEY4:
  306. return ESP_EFUSE_KEY_PURPOSE_4;
  307. case EFUSE_BLK_KEY5:
  308. return ESP_EFUSE_KEY_PURPOSE_5;
  309. default:
  310. return NULL;
  311. }
  312. }
  313. const esp_efuse_desc_t** esp_efuse_get_key(esp_efuse_block_t block)
  314. {
  315. if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX) {
  316. return NULL;
  317. }
  318. unsigned idx = block - EFUSE_BLK_KEY0;
  319. return s_table[idx].key;
  320. }
  321. bool esp_efuse_get_key_dis_read(esp_efuse_block_t block)
  322. {
  323. assert(block >= EFUSE_BLK_KEY0 && block < EFUSE_BLK_KEY_MAX);
  324. unsigned idx = block - EFUSE_BLK_KEY0;
  325. return esp_efuse_read_field_bit(s_table[idx].key_rd_dis);
  326. }
  327. esp_err_t esp_efuse_set_key_dis_read(esp_efuse_block_t block)
  328. {
  329. if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX) {
  330. return ESP_ERR_INVALID_ARG;
  331. }
  332. unsigned idx = block - EFUSE_BLK_KEY0;
  333. const uint8_t one = 1;
  334. return esp_efuse_write_field_blob(s_table[idx].key_rd_dis, &one, 1);
  335. }
  336. bool esp_efuse_get_key_dis_write(esp_efuse_block_t block)
  337. {
  338. assert(block >= EFUSE_BLK_KEY0 && block < EFUSE_BLK_KEY_MAX);
  339. unsigned idx = block - EFUSE_BLK_KEY0;
  340. return esp_efuse_read_field_bit(s_table[idx].key_wr_dis);
  341. }
  342. esp_err_t esp_efuse_set_key_dis_write(esp_efuse_block_t block)
  343. {
  344. if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX) {
  345. return ESP_ERR_INVALID_ARG;
  346. }
  347. unsigned idx = block - EFUSE_BLK_KEY0;
  348. const uint8_t one = 1;
  349. return esp_efuse_write_field_blob(s_table[idx].key_wr_dis, &one, 1);
  350. }
  351. esp_efuse_purpose_t esp_efuse_get_key_purpose(esp_efuse_block_t block)
  352. {
  353. if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX) {
  354. return ESP_EFUSE_KEY_PURPOSE_MAX;
  355. }
  356. unsigned idx = block - EFUSE_BLK_KEY0;
  357. uint8_t value = 0;
  358. esp_err_t err = esp_efuse_read_field_blob(s_table[idx].keypurpose, &value, s_table[idx].keypurpose[0]->bit_count);
  359. if (err != ESP_OK) {
  360. return ESP_EFUSE_KEY_PURPOSE_MAX;
  361. }
  362. return value;
  363. }
  364. esp_err_t esp_efuse_set_key_purpose(esp_efuse_block_t block, esp_efuse_purpose_t purpose)
  365. {
  366. if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX) {
  367. return ESP_ERR_INVALID_ARG;
  368. }
  369. unsigned idx = block - EFUSE_BLK_KEY0;
  370. return esp_efuse_write_field_blob(s_table[idx].keypurpose, &purpose, s_table[idx].keypurpose[0]->bit_count);
  371. }
  372. bool esp_efuse_get_keypurpose_dis_write(esp_efuse_block_t block)
  373. {
  374. assert(block >= EFUSE_BLK_KEY0 && block < EFUSE_BLK_KEY_MAX);
  375. unsigned idx = block - EFUSE_BLK_KEY0;
  376. return esp_efuse_read_field_bit(s_table[idx].keypurpose_wr_dis);
  377. }
  378. esp_err_t esp_efuse_set_keypurpose_dis_write(esp_efuse_block_t block)
  379. {
  380. if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX) {
  381. return ESP_ERR_INVALID_ARG;
  382. }
  383. unsigned idx = block - EFUSE_BLK_KEY0;
  384. const uint8_t one = 1;
  385. return esp_efuse_write_field_blob(s_table[idx].keypurpose_wr_dis, &one, 1);
  386. }
  387. bool esp_efuse_find_purpose(esp_efuse_purpose_t purpose, esp_efuse_block_t *block)
  388. {
  389. esp_efuse_block_t dummy;
  390. if (block == NULL) {
  391. block = &dummy;
  392. }
  393. for (esp_efuse_block_t b = EFUSE_BLK_KEY0; b < EFUSE_BLK_KEY_MAX; b++) {
  394. if (esp_efuse_get_key_purpose(b) == purpose) {
  395. *block = b;
  396. return true;
  397. }
  398. }
  399. return false;
  400. }
  401. esp_efuse_block_t esp_efuse_find_unused_key_block(void)
  402. {
  403. for (esp_efuse_block_t b = EFUSE_BLK_KEY0; b < EFUSE_BLK_KEY_MAX; b++) {
  404. if (esp_efuse_key_block_unused(b)) {
  405. return b;
  406. }
  407. }
  408. return EFUSE_BLK_KEY_MAX; // nothing
  409. }
  410. unsigned esp_efuse_count_unused_key_blocks(void)
  411. {
  412. unsigned r = 0;
  413. for (esp_efuse_block_t b = EFUSE_BLK_KEY0; b < EFUSE_BLK_KEY_MAX; b++) {
  414. if (esp_efuse_key_block_unused(b)) {
  415. r++;
  416. }
  417. }
  418. return r;
  419. }
  420. bool esp_efuse_key_block_unused(esp_efuse_block_t block)
  421. {
  422. if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX) {
  423. return false; // Not a key block
  424. }
  425. if (esp_efuse_get_key_purpose(block) != ESP_EFUSE_KEY_PURPOSE_USER ||
  426. esp_efuse_get_keypurpose_dis_write(block) ||
  427. esp_efuse_get_key_dis_read(block) ||
  428. esp_efuse_get_key_dis_write(block)) {
  429. return false; // Block in use!
  430. }
  431. for (int i = 0; i < 8; ++i) {
  432. if (esp_efuse_read_reg(block, i) != 0) {
  433. return false; // Block in use!
  434. }
  435. }
  436. return true; // Unused
  437. }
  438. bool esp_efuse_get_digest_revoke(unsigned num_digest)
  439. {
  440. assert(num_digest < sizeof(s_revoke_table) / sizeof(esp_efuse_revokes_t));
  441. return esp_efuse_read_field_bit(s_revoke_table[num_digest].revoke);
  442. }
  443. esp_err_t esp_efuse_set_digest_revoke(unsigned num_digest)
  444. {
  445. if (num_digest >= sizeof(s_revoke_table) / sizeof(esp_efuse_revokes_t)) {
  446. return ESP_ERR_INVALID_ARG;
  447. }
  448. return esp_efuse_write_field_bit(s_revoke_table[num_digest].revoke);
  449. }
  450. bool esp_efuse_get_write_protect_of_digest_revoke(unsigned num_digest)
  451. {
  452. assert(num_digest < sizeof(s_revoke_table) / sizeof(esp_efuse_revokes_t));
  453. return esp_efuse_read_field_bit(s_revoke_table[num_digest].revoke_wr_dis);
  454. }
  455. esp_err_t esp_efuse_set_write_protect_of_digest_revoke(unsigned num_digest)
  456. {
  457. if (num_digest >= sizeof(s_revoke_table) / sizeof(esp_efuse_revokes_t)) {
  458. return ESP_ERR_INVALID_ARG;
  459. }
  460. return esp_efuse_write_field_bit(s_revoke_table[num_digest].revoke_wr_dis);
  461. }
  462. esp_err_t esp_efuse_write_key(esp_efuse_block_t block, esp_efuse_purpose_t purpose, const void *key, size_t key_size_bytes)
  463. {
  464. esp_err_t err = ESP_OK;
  465. if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX || key_size_bytes > 32 || purpose >= ESP_EFUSE_KEY_PURPOSE_MAX) {
  466. return ESP_ERR_INVALID_ARG;
  467. }
  468. esp_efuse_batch_write_begin();
  469. if (!esp_efuse_key_block_unused(block)) {
  470. err = ESP_ERR_INVALID_STATE;
  471. } else {
  472. unsigned idx = block - EFUSE_BLK_KEY0;
  473. ESP_EFUSE_CHK(esp_efuse_write_field_blob(s_table[idx].key, key, key_size_bytes * 8));
  474. ESP_EFUSE_CHK(esp_efuse_set_key_dis_write(block));
  475. if (purpose == ESP_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_1 ||
  476. purpose == ESP_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_2 ||
  477. purpose == ESP_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY ||
  478. purpose == ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_ALL ||
  479. purpose == ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG ||
  480. purpose == ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_DIGITAL_SIGNATURE ||
  481. purpose == ESP_EFUSE_KEY_PURPOSE_HMAC_UP) {
  482. ESP_EFUSE_CHK(esp_efuse_set_key_dis_read(block));
  483. }
  484. ESP_EFUSE_CHK(esp_efuse_set_key_purpose(block, purpose));
  485. ESP_EFUSE_CHK(esp_efuse_set_keypurpose_dis_write(block));
  486. return esp_efuse_batch_write_commit();
  487. }
  488. err_exit:
  489. esp_efuse_batch_write_cancel();
  490. return err;
  491. }
  492. esp_err_t esp_efuse_write_keys(esp_efuse_purpose_t purposes[], uint8_t keys[][32], unsigned number_of_keys)
  493. {
  494. esp_err_t err = ESP_OK;
  495. if (number_of_keys == 0 || number_of_keys > (EFUSE_BLK_KEY_MAX - EFUSE_BLK_KEY0) || keys == NULL || purposes == NULL) {
  496. return ESP_ERR_INVALID_ARG;
  497. }
  498. esp_efuse_purpose_t purpose = 0;
  499. esp_efuse_block_t block = EFUSE_BLK_KEY0;
  500. esp_efuse_batch_write_begin();
  501. unsigned unused_keys = esp_efuse_count_unused_key_blocks();
  502. if (number_of_keys > unused_keys) {
  503. ESP_LOGE(TAG, "Not enough unused key blocks available. Required %d, was %d", number_of_keys, unused_keys);
  504. err = ESP_ERR_NOT_ENOUGH_UNUSED_KEY_BLOCKS;
  505. } else {
  506. for (int i_key = 0; (block < EFUSE_BLK_KEY_MAX) && (i_key < number_of_keys); block++) {
  507. if (esp_efuse_key_block_unused(block)) {
  508. purpose = purposes[i_key];
  509. ESP_LOGI(TAG, "Writing EFUSE_BLK_KEY%d with purpose %d", block - EFUSE_BLK_KEY0, purpose);
  510. ESP_EFUSE_CHK(esp_efuse_write_key(block, purpose, keys[i_key], 32));
  511. i_key++;
  512. }
  513. }
  514. return esp_efuse_batch_write_commit();
  515. err_exit:
  516. ESP_LOGE(TAG, "Failed to write EFUSE_BLK_KEY%d with purpose %d. Can't continue.", block - EFUSE_BLK_KEY0, purpose);
  517. }
  518. esp_efuse_batch_write_cancel();
  519. return err;
  520. }
  521. #endif // not CONFIG_IDF_TARGET_ESP32