main.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. /**
  2. * Copyright (c) 2018 - 2019, Nordic Semiconductor ASA
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without modification,
  7. * are permitted provided that the following conditions are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright notice, this
  10. * list of conditions and the following disclaimer.
  11. *
  12. * 2. Redistributions in binary form, except as embedded into a Nordic
  13. * Semiconductor ASA integrated circuit in a product or a software update for
  14. * such product, must reproduce the above copyright notice, this list of
  15. * conditions and the following disclaimer in the documentation and/or other
  16. * materials provided with the distribution.
  17. *
  18. * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
  19. * contributors may be used to endorse or promote products derived from this
  20. * software without specific prior written permission.
  21. *
  22. * 4. This software, with or without modification, must only be used with a
  23. * Nordic Semiconductor ASA integrated circuit.
  24. *
  25. * 5. Any software provided in binary form under this license must not be reverse
  26. * engineered, decompiled, modified and/or disassembled.
  27. *
  28. * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
  29. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  30. * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
  31. * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
  32. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  33. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  34. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  36. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  37. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  38. *
  39. */
  40. /**
  41. * @defgroup nrf_crypto_ecdh_example
  42. * @{
  43. * @ingroup nrf_crypto_ecdh
  44. * @brief ECDH Example Application main file.
  45. *
  46. * This file contains the source code for a sample application that demonstrates using the
  47. * nrf_crypto library to do ECHD computation. Different backends can be used by adjusting
  48. * @ref sdk_config.h accordingly.
  49. *
  50. */
  51. #include <stdbool.h>
  52. #include <stdint.h>
  53. #include "sdk_common.h"
  54. #include "nrf_assert.h"
  55. #include "app_error.h"
  56. #include "nrf_log.h"
  57. #include "nrf_log_ctrl.h"
  58. #include "nrf_log_default_backends.h"
  59. #include "nrf_crypto.h"
  60. #include "nrf_crypto_ecc.h"
  61. #include "nrf_crypto_ecdh.h"
  62. #include "nrf_crypto_error.h"
  63. #include "mem_manager.h"
  64. //======================================== Print functions ========================================
  65. //
  66. // This part of an example contains helper functions to print results generated in this examples.
  67. //
  68. static void print_array(uint8_t const * p_string, size_t size)
  69. {
  70. #if NRF_LOG_ENABLED
  71. size_t i;
  72. NRF_LOG_RAW_INFO(" ");
  73. for(i = 0; i < size; i++)
  74. {
  75. NRF_LOG_RAW_INFO("%02x", p_string[i]);
  76. }
  77. #endif // NRF_LOG_ENABLED
  78. }
  79. static void print_hex(char const * p_msg, uint8_t const * p_data, size_t size)
  80. {
  81. NRF_LOG_INFO(p_msg);
  82. print_array(p_data, size);
  83. NRF_LOG_RAW_INFO("\r\n");
  84. }
  85. #define DEMO_ERROR_CHECK(error) \
  86. do \
  87. { \
  88. if (error != NRF_SUCCESS) \
  89. { \
  90. NRF_LOG_ERROR("Error 0x%04X: %s", error, nrf_crypto_error_string_get(error));\
  91. APP_ERROR_CHECK(error); \
  92. } \
  93. } while(0)
  94. //==================================== Communication functions ====================================
  95. //
  96. // This part of an example contains helper functions to demonstrate communication between
  97. // Alice and Bob.
  98. //
  99. static uint8_t m_message_for_alice[256]; ///< @brief Message buffer from Bob to Alice
  100. static size_t m_message_for_alice_size; ///< @brief Message buffer size from Bob to Alice
  101. static uint8_t m_message_for_bob[256]; ///< @brief Message buffer from Alice to Bob
  102. static size_t m_message_for_bob_size; ///< @brief Message buffer size from Alice to Bob
  103. /** @brief Function to demonstrate message send to Alice.
  104. */
  105. static void send_to_alice(const uint8_t * p_data, size_t size)
  106. {
  107. print_hex("Message with public key from Bob to Alice: ", p_data, size);
  108. memcpy(m_message_for_alice, p_data, size);
  109. m_message_for_alice_size = size;
  110. }
  111. /** @brief Function to demonstrate message send to Bob.
  112. */
  113. static void send_to_bob(const uint8_t * p_data, size_t size)
  114. {
  115. print_hex("Message with public key from Alice to Bob: ", p_data, size);
  116. memcpy(m_message_for_bob, p_data, size);
  117. m_message_for_bob_size = size;
  118. }
  119. /** @brief Function to demonstrate message receive from Alice.
  120. */
  121. static size_t recv_from_alice(uint8_t * p_data)
  122. {
  123. memcpy(p_data, m_message_for_bob, m_message_for_bob_size);
  124. return m_message_for_bob_size;
  125. }
  126. /** @brief Function to demonstrate message receive from Bob.
  127. */
  128. static size_t recv_from_bob(uint8_t * p_data)
  129. {
  130. memcpy(p_data, m_message_for_alice, m_message_for_alice_size);
  131. return m_message_for_alice_size;
  132. }
  133. //========================================= Alice's site =========================================
  134. //
  135. // This part of an example contains implementation of Alice's site. Alice have public and private
  136. // key predefined. She is using always the same key pair for every secure connection. Code is
  137. // divided into two steps - before and after public key exchange with Bob.
  138. //
  139. /** @brief Predefined example private key
  140. *
  141. * This private key contains some dummy data just to show the functionality. Is should never be
  142. * placed in any practical usage. Is is not secure, because it is filled with ones (in HEX).
  143. */
  144. static const uint8_t m_alice_raw_private_key[] =
  145. {
  146. 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, // This is an example. DO NOT USE THIS KEY!
  147. 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, // This is an example. DO NOT USE THIS KEY!
  148. 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, // This is an example. DO NOT USE THIS KEY!
  149. 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, // This is an example. DO NOT USE THIS KEY!
  150. };
  151. /** @brief Predefined example public key that is associated with example private key
  152. * @ref alice_raw_private_key.
  153. */
  154. static const uint8_t m_alice_raw_public_key[] =
  155. {
  156. 0x02, 0x17, 0xE6, 0x17, 0xF0, 0xB6, 0x44, 0x39,
  157. 0x28, 0x27, 0x8F, 0x96, 0x99, 0x9E, 0x69, 0xA2,
  158. 0x3A, 0x4F, 0x2C, 0x15, 0x2B, 0xDF, 0x6D, 0x6C,
  159. 0xDF, 0x66, 0xE5, 0xB8, 0x02, 0x82, 0xD4, 0xED,
  160. 0x19, 0x4A, 0x7D, 0xEB, 0xCB, 0x97, 0x71, 0x2D,
  161. 0x2D, 0xDA, 0x3C, 0xA8, 0x5A, 0xA8, 0x76, 0x5A,
  162. 0x56, 0xF4, 0x5F, 0xC7, 0x58, 0x59, 0x96, 0x52,
  163. 0xF2, 0x89, 0x7C, 0x65, 0x30, 0x6E, 0x57, 0x94,
  164. };
  165. static nrf_crypto_ecdh_secp256r1_shared_secret_t m_shared_secret_bob;
  166. static nrf_crypto_ecdh_secp256r1_shared_secret_t m_shared_secret_alice;
  167. /** @brief First step of Alice's work. Ended with send public key to Bob.
  168. */
  169. static void alice_step_1()
  170. {
  171. NRF_LOG_INFO("Alice's prepare step");
  172. // Alice have predefined public key, so she just sends it to Bob
  173. send_to_bob(m_alice_raw_public_key, sizeof(m_alice_raw_public_key));
  174. }
  175. /** @brief Second step of Alice's work. At the end Alice will have shared secret the same as
  176. * Bob has.
  177. */
  178. static void alice_step_2()
  179. {
  180. static nrf_crypto_ecc_private_key_t alice_private_key;
  181. static nrf_crypto_ecc_public_key_t bob_public_key;
  182. static nrf_crypto_ecc_secp256r1_raw_public_key_t raw_key_buffer;
  183. ret_code_t err_code = NRF_SUCCESS;
  184. size_t size;
  185. NRF_LOG_INFO("Alice's compute step");
  186. // Alice receives Bob's raw public key
  187. size = recv_from_bob(raw_key_buffer);
  188. // Alice converts Bob's raw public key to internal representation
  189. err_code = nrf_crypto_ecc_public_key_from_raw(&g_nrf_crypto_ecc_secp256r1_curve_info,
  190. &bob_public_key,
  191. raw_key_buffer, size);
  192. DEMO_ERROR_CHECK(err_code);
  193. // Alice converts her raw private key to internal representation
  194. err_code = nrf_crypto_ecc_private_key_from_raw(&g_nrf_crypto_ecc_secp256r1_curve_info,
  195. &alice_private_key,
  196. m_alice_raw_private_key,
  197. sizeof(m_alice_raw_private_key));
  198. DEMO_ERROR_CHECK(err_code);
  199. // Alice computes shared secret using ECDH
  200. size = sizeof(m_shared_secret_alice);
  201. err_code = nrf_crypto_ecdh_compute(NULL,
  202. &alice_private_key,
  203. &bob_public_key,
  204. m_shared_secret_alice,
  205. &size);
  206. DEMO_ERROR_CHECK(err_code);
  207. // Alice can now use shared secret
  208. print_hex("Alice's shared secret: ", m_shared_secret_alice, size);
  209. // Key deallocation
  210. err_code = nrf_crypto_ecc_private_key_free(&alice_private_key);
  211. DEMO_ERROR_CHECK(err_code);
  212. err_code = nrf_crypto_ecc_public_key_free(&bob_public_key);
  213. DEMO_ERROR_CHECK(err_code);
  214. }
  215. //========================================== Bob's site ==========================================
  216. //
  217. // This part of an example contains implementation of Bobs's site. Bob do not have public and
  218. // private key predefined. He always generates a new key pair for each connection. Code is divided
  219. // into two steps - before and after public key exchange with Alice.
  220. //
  221. /** @brief Bob must keep his private key between step 1 and step 2.
  222. */
  223. static nrf_crypto_ecc_private_key_t m_bob_private_key;
  224. /** @brief First step of Bob's work. Ended with send public key to Alice.
  225. */
  226. void bob_step_1()
  227. {
  228. static nrf_crypto_ecc_public_key_t bob_public_key;
  229. static nrf_crypto_ecc_secp256r1_raw_public_key_t raw_key_buffer;
  230. ret_code_t err_code = NRF_SUCCESS;
  231. size_t size;
  232. NRF_LOG_INFO("Bob's prepare step");
  233. // Bob creates new key pair each time
  234. err_code = nrf_crypto_ecc_key_pair_generate(NULL,
  235. &g_nrf_crypto_ecc_secp256r1_curve_info,
  236. &m_bob_private_key,
  237. &bob_public_key);
  238. DEMO_ERROR_CHECK(err_code);
  239. // Bob converts public key to raw representation
  240. size = sizeof(raw_key_buffer);
  241. err_code = nrf_crypto_ecc_public_key_to_raw(&bob_public_key,
  242. raw_key_buffer,
  243. &size);
  244. DEMO_ERROR_CHECK(err_code);
  245. // Bob sends raw public key to Alice
  246. send_to_alice(raw_key_buffer, size);
  247. // Key deallocation
  248. err_code = nrf_crypto_ecc_public_key_free(&bob_public_key);
  249. DEMO_ERROR_CHECK(err_code);
  250. }
  251. /** @brief Second step of Bob's work. At the end Bob will have shared secret the same as Alice has.
  252. */
  253. void bob_step_2()
  254. {
  255. static nrf_crypto_ecc_public_key_t alice_public_key;
  256. static nrf_crypto_ecc_secp256r1_raw_public_key_t raw_key_buffer;
  257. ret_code_t err_code = NRF_SUCCESS;
  258. size_t size;
  259. NRF_LOG_INFO("Bob's compute step");
  260. // Bob receives Alice's raw public key
  261. size = recv_from_alice(raw_key_buffer);
  262. // Bob converts Alice's raw public key to internal representation
  263. err_code = nrf_crypto_ecc_public_key_from_raw(&g_nrf_crypto_ecc_secp256r1_curve_info,
  264. &alice_public_key,
  265. raw_key_buffer,
  266. size);
  267. DEMO_ERROR_CHECK(err_code);
  268. // Bob computes shared secret using ECDH
  269. size = sizeof(m_shared_secret_bob);
  270. err_code = nrf_crypto_ecdh_compute(NULL,
  271. &m_bob_private_key,
  272. &alice_public_key,
  273. m_shared_secret_bob,
  274. &size);
  275. DEMO_ERROR_CHECK(err_code);
  276. // Bob can now use shared secret
  277. print_hex("Bob's shared secret: ", m_shared_secret_bob, size);
  278. // Key deallocation
  279. err_code = nrf_crypto_ecc_private_key_free(&m_bob_private_key);
  280. DEMO_ERROR_CHECK(err_code);
  281. err_code = nrf_crypto_ecc_public_key_free(&alice_public_key);
  282. DEMO_ERROR_CHECK(err_code);
  283. }
  284. //========================================= Example entry =========================================
  285. //
  286. /** @brief Function for initializing the nrf log module.
  287. */
  288. static void log_init(void)
  289. {
  290. ret_code_t err_code = NRF_LOG_INIT(NULL);
  291. APP_ERROR_CHECK(err_code);
  292. NRF_LOG_DEFAULT_BACKENDS_INIT();
  293. }
  294. /** @brief Function for application main entry.
  295. */
  296. int main(void)
  297. {
  298. ret_code_t err_code = NRF_SUCCESS;
  299. log_init();
  300. NRF_LOG_INFO("ECDH example started.\r\n");
  301. err_code = nrf_mem_init();
  302. DEMO_ERROR_CHECK(err_code);
  303. err_code = nrf_crypto_init();
  304. DEMO_ERROR_CHECK(err_code);
  305. alice_step_1(); // Alice sends her public key to Bob
  306. bob_step_1(); // Bob generates new key pair and sends his public key to Alice
  307. alice_step_2(); // Alice receives Bob's public key and computes shared secret
  308. bob_step_2(); // Bob receives Alice's public key and computes shared secret
  309. if (memcmp(m_shared_secret_alice,
  310. m_shared_secret_bob,
  311. sizeof(nrf_crypto_ecdh_secp256r1_shared_secret_t)) == 0)
  312. {
  313. NRF_LOG_INFO("ECDH example executed successfully.");
  314. }
  315. else
  316. {
  317. NRF_LOG_ERROR("ECDH example failed!!!");
  318. }
  319. for (;;)
  320. {
  321. }
  322. }
  323. /** @}
  324. */