test_ecdsa.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. /*
  2. * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: CC0-1.0
  5. */
  6. #include <stdio.h>
  7. #include <stdbool.h>
  8. #include <string.h>
  9. #include "esp_private/esp_crypto_lock_internal.h"
  10. #include "esp_random.h"
  11. #include "hal/clk_gate_ll.h"
  12. #include "hal/ecdsa_hal.h"
  13. #include "hal/ecdsa_ll.h"
  14. #include "hal/ecdsa_types.h"
  15. #include "memory_checks.h"
  16. #include "unity_fixture.h"
  17. #include "ecdsa_params.h"
  18. static void ecdsa_enable_and_reset(void)
  19. {
  20. ECDSA_RCC_ATOMIC() {
  21. ecdsa_ll_enable_bus_clock(true);
  22. ecdsa_ll_reset_register();
  23. }
  24. }
  25. static void ecdsa_disable(void)
  26. {
  27. ECDSA_RCC_ATOMIC() {
  28. ecdsa_ll_enable_bus_clock(false);
  29. }
  30. }
  31. static void ecc_be_to_le(const uint8_t* be_point, uint8_t *le_point, uint8_t len)
  32. {
  33. memset(le_point, 0x0, 32);
  34. for (int i = 0; i < len; i++) {
  35. le_point[i] = be_point[len - i - 1];
  36. }
  37. }
  38. static int test_ecdsa_verify(bool is_p256, uint8_t* sha, uint8_t* r_le, uint8_t* s_le, uint8_t *pub_x, uint8_t *pub_y)
  39. {
  40. uint16_t len;
  41. uint8_t sha_le[32];
  42. ecdsa_hal_config_t conf = {
  43. .mode = ECDSA_MODE_SIGN_VERIFY,
  44. .k_mode = ECDSA_K_USE_TRNG,
  45. .sha_mode = ECDSA_Z_USER_PROVIDED,
  46. };
  47. if (is_p256) {
  48. conf.curve = ECDSA_CURVE_SECP256R1;
  49. len = 32;
  50. } else {
  51. conf.curve = ECDSA_CURVE_SECP192R1;
  52. len = 24;
  53. }
  54. /* Set HASH */
  55. ecc_be_to_le(sha, sha_le, len);
  56. ecdsa_enable_and_reset();
  57. int ret = ecdsa_hal_verify_signature(&conf, sha_le, r_le, s_le, pub_x, pub_y, len);
  58. ecdsa_disable();
  59. return ret;
  60. }
  61. static void test_ecdsa_corrupt_data(bool is_p256, uint8_t* sha, uint8_t* r_le, uint8_t* s_le, uint8_t *pub_x, uint8_t *pub_y)
  62. {
  63. int len;
  64. if (is_p256) {
  65. len = 32;
  66. } else {
  67. len = 24;
  68. }
  69. // Randomly select a bit and corrupt its correpsonding value
  70. uint16_t r_bit = esp_random() % len * 8;
  71. printf("Corrupting SHA bit %d...\n", r_bit);
  72. sha[r_bit / 8] ^= 1 << (r_bit % 8);
  73. TEST_ASSERT_EQUAL(-1, test_ecdsa_verify(1, sha, r_le, s_le, pub_x, pub_y));
  74. sha[r_bit / 8] ^= 1 << (r_bit % 8);
  75. printf("Corrupting R bit %d...\n", r_bit);
  76. r_le[r_bit / 8] ^= 1 << (r_bit % 8);
  77. TEST_ASSERT_EQUAL(-1, test_ecdsa_verify(1, sha, r_le, s_le, pub_x, pub_y));
  78. r_le[r_bit / 8] ^= 1 << (r_bit % 8);
  79. printf("Corrupting S bit %d...\n", r_bit);
  80. s_le[r_bit / 8] ^= 1 << (r_bit % 8);
  81. TEST_ASSERT_EQUAL(-1, test_ecdsa_verify(1, sha, r_le, s_le, pub_x, pub_y));
  82. s_le[r_bit / 8] ^= 1 << (r_bit % 8);
  83. printf("Corrupting pub_x bit %d...\n", r_bit);
  84. pub_x[r_bit / 8] ^= 1 << (r_bit % 8);
  85. TEST_ASSERT_EQUAL(-1, test_ecdsa_verify(1, sha, r_le, s_le, pub_x, pub_y));
  86. pub_x[r_bit / 8] ^= 1 << (r_bit % 8);
  87. printf("Corrupting pub_y bit %d...\n", r_bit);
  88. pub_y[r_bit / 8] ^= 1 << (r_bit % 8);
  89. TEST_ASSERT_EQUAL(-1, test_ecdsa_verify(1, sha, r_le, s_le, pub_x, pub_y));
  90. pub_y[r_bit / 8] ^= 1 << (r_bit % 8);
  91. }
  92. static void test_ecdsa_sign(bool is_p256, uint8_t* sha, uint8_t* r_le, uint8_t* s_le, bool use_km_key)
  93. {
  94. uint8_t sha_le[32] = {0};
  95. uint8_t zeroes[32] = {0};
  96. uint16_t len;
  97. ecdsa_hal_config_t conf = {
  98. .mode = ECDSA_MODE_SIGN_GEN,
  99. .k_mode = ECDSA_K_USE_TRNG,
  100. .sha_mode = ECDSA_Z_USER_PROVIDED,
  101. .use_km_key = use_km_key,
  102. };
  103. if (is_p256) {
  104. conf.curve = ECDSA_CURVE_SECP256R1;
  105. if (use_km_key == 0) {
  106. conf.efuse_key_blk = 6;
  107. }
  108. len = 32;
  109. } else {
  110. conf.curve = ECDSA_CURVE_SECP192R1;
  111. if (use_km_key == 0) {
  112. conf.efuse_key_blk = 5;
  113. }
  114. len = 24;
  115. }
  116. /* Set HASH */
  117. ecc_be_to_le(sha, sha_le, len);
  118. ecdsa_enable_and_reset();
  119. do {
  120. ecdsa_hal_gen_signature(&conf, NULL, sha_le, r_le, s_le, len);
  121. } while(!memcmp(r_le, zeroes, len) || !memcmp(s_le, zeroes, len));
  122. ecdsa_disable();
  123. }
  124. static void test_ecdsa_sign_and_verify(bool is_p256, uint8_t* sha, uint8_t* pub_x, uint8_t* pub_y, bool use_km_key)
  125. {
  126. uint8_t r_le[32] = {0};
  127. uint8_t s_le[32] = {0};
  128. test_ecdsa_sign(is_p256, sha, r_le, s_le, use_km_key);
  129. TEST_ASSERT_EQUAL(0, test_ecdsa_verify(is_p256, sha, r_le, s_le, pub_x, pub_y));
  130. }
  131. #ifdef SOC_ECDSA_SUPPORT_EXPORT_PUBKEY
  132. static void test_ecdsa_export_pubkey(bool is_p256, bool use_km_key)
  133. {
  134. uint8_t pub_x[32] = {0};
  135. uint8_t pub_y[32] = {0};
  136. uint16_t len;
  137. ecdsa_hal_config_t conf = {
  138. .mode = ECDSA_MODE_EXPORT_PUBKEY,
  139. .use_km_key = use_km_key,
  140. };
  141. if (is_p256) {
  142. conf.curve = ECDSA_CURVE_SECP256R1;
  143. if (use_km_key == 0) {
  144. conf.efuse_key_blk = 6;
  145. }
  146. len = 32;
  147. } else {
  148. conf.curve = ECDSA_CURVE_SECP192R1;
  149. if (use_km_key == 0) {
  150. conf.efuse_key_blk = 5;
  151. }
  152. len = 24;
  153. }
  154. ecdsa_enable_and_reset();
  155. ecdsa_hal_export_pubkey(&conf, pub_x, pub_y, len);
  156. if (is_p256) {
  157. TEST_ASSERT_EQUAL_HEX8_ARRAY(ecdsa256_pub_x, pub_x, len);
  158. TEST_ASSERT_EQUAL_HEX8_ARRAY(ecdsa256_pub_y, pub_y, len);
  159. } else {
  160. TEST_ASSERT_EQUAL_HEX8_ARRAY(ecdsa192_pub_x, pub_x, len);
  161. TEST_ASSERT_EQUAL_HEX8_ARRAY(ecdsa192_pub_y, pub_y, len);
  162. }
  163. ecdsa_disable();
  164. }
  165. #endif /* SOC_ECDSA_SUPPORT_EXPORT_PUBKEY */
  166. TEST_GROUP(ecdsa);
  167. TEST_SETUP(ecdsa)
  168. {
  169. test_utils_record_free_mem();
  170. TEST_ESP_OK(test_utils_set_leak_level(0, ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_GENERAL));
  171. }
  172. TEST_TEAR_DOWN(ecdsa)
  173. {
  174. test_utils_finish_and_evaluate_leaks(test_utils_get_leak_level(ESP_LEAK_TYPE_WARNING, ESP_COMP_LEAK_ALL),
  175. test_utils_get_leak_level(ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_ALL));
  176. }
  177. TEST(ecdsa, ecdsa_SECP192R1_signature_verification)
  178. {
  179. TEST_ASSERT_EQUAL(0, test_ecdsa_verify(0, sha, ecdsa192_r, ecdsa192_s, ecdsa192_pub_x, ecdsa192_pub_y));
  180. }
  181. TEST(ecdsa, ecdsa_SECP192R1_sign_and_verify)
  182. {
  183. test_ecdsa_sign_and_verify(0, sha, ecdsa192_pub_x, ecdsa192_pub_y, 0);
  184. }
  185. TEST(ecdsa, ecdsa_SECP192R1_corrupt_signature)
  186. {
  187. test_ecdsa_corrupt_data(0, sha, ecdsa192_r, ecdsa192_s, ecdsa192_pub_x, ecdsa192_pub_y);
  188. }
  189. TEST(ecdsa, ecdsa_SECP256R1_signature_verification)
  190. {
  191. TEST_ASSERT_EQUAL(0, test_ecdsa_verify(1, sha, ecdsa256_r, ecdsa256_s, ecdsa256_pub_x, ecdsa256_pub_y));
  192. }
  193. TEST(ecdsa, ecdsa_SECP256R1_sign_and_verify)
  194. {
  195. test_ecdsa_sign_and_verify(1, sha, ecdsa256_pub_x, ecdsa256_pub_y, 0);
  196. }
  197. TEST(ecdsa, ecdsa_SECP256R1_corrupt_signature)
  198. {
  199. test_ecdsa_corrupt_data(1, sha, ecdsa256_r, ecdsa256_s, ecdsa256_pub_x, ecdsa256_pub_y);
  200. }
  201. #ifdef SOC_ECDSA_SUPPORT_EXPORT_PUBKEY
  202. TEST(ecdsa, ecdsa_SECP192R1_export_pubkey)
  203. {
  204. test_ecdsa_export_pubkey(0, 0);
  205. }
  206. TEST(ecdsa, ecdsa_SECP256R1_export_pubkey)
  207. {
  208. test_ecdsa_export_pubkey(1, 0);
  209. }
  210. #endif /* SOC_ECDSA_SUPPORT_EXPORT_PUBKEY */
  211. TEST_GROUP_RUNNER(ecdsa)
  212. {
  213. RUN_TEST_CASE(ecdsa, ecdsa_SECP192R1_signature_verification)
  214. RUN_TEST_CASE(ecdsa, ecdsa_SECP192R1_sign_and_verify)
  215. RUN_TEST_CASE(ecdsa, ecdsa_SECP192R1_corrupt_signature)
  216. RUN_TEST_CASE(ecdsa, ecdsa_SECP256R1_signature_verification)
  217. RUN_TEST_CASE(ecdsa, ecdsa_SECP256R1_sign_and_verify)
  218. RUN_TEST_CASE(ecdsa, ecdsa_SECP256R1_corrupt_signature)
  219. #ifdef SOC_ECDSA_SUPPORT_EXPORT_PUBKEY
  220. RUN_TEST_CASE(ecdsa, ecdsa_SECP192R1_export_pubkey)
  221. RUN_TEST_CASE(ecdsa, ecdsa_SECP256R1_export_pubkey)
  222. #endif /* SOC_ECDSA_SUPPORT_EXPORT_PUBKEY */
  223. }