123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399 |
- /**
- * Copyright (c) 2018 - 2019, Nordic Semiconductor ASA
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form, except as embedded into a Nordic
- * Semiconductor ASA integrated circuit in a product or a software update for
- * such product, must reproduce the above copyright notice, this list of
- * conditions and the following disclaimer in the documentation and/or other
- * materials provided with the distribution.
- *
- * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * 4. This software, with or without modification, must only be used with a
- * Nordic Semiconductor ASA integrated circuit.
- *
- * 5. Any software provided in binary form under this license must not be reverse
- * engineered, decompiled, modified and/or disassembled.
- *
- * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
- /**
- * @defgroup nrf_crypto_ecdh_example
- * @{
- * @ingroup nrf_crypto_ecdh
- * @brief ECDH Example Application main file.
- *
- * This file contains the source code for a sample application that demonstrates using the
- * nrf_crypto library to do ECHD computation. Different backends can be used by adjusting
- * @ref sdk_config.h accordingly.
- *
- */
- #include <stdbool.h>
- #include <stdint.h>
- #include "sdk_common.h"
- #include "nrf_assert.h"
- #include "app_error.h"
- #include "nrf_log.h"
- #include "nrf_log_ctrl.h"
- #include "nrf_log_default_backends.h"
- #include "nrf_crypto.h"
- #include "nrf_crypto_ecc.h"
- #include "nrf_crypto_ecdh.h"
- #include "nrf_crypto_error.h"
- #include "mem_manager.h"
- //======================================== Print functions ========================================
- //
- // This part of an example contains helper functions to print results generated in this examples.
- //
- static void print_array(uint8_t const * p_string, size_t size)
- {
- #if NRF_LOG_ENABLED
- size_t i;
- NRF_LOG_RAW_INFO(" ");
- for(i = 0; i < size; i++)
- {
- NRF_LOG_RAW_INFO("%02x", p_string[i]);
- }
- #endif // NRF_LOG_ENABLED
- }
- static void print_hex(char const * p_msg, uint8_t const * p_data, size_t size)
- {
- NRF_LOG_INFO(p_msg);
- print_array(p_data, size);
- NRF_LOG_RAW_INFO("\r\n");
- }
- #define DEMO_ERROR_CHECK(error) \
- do \
- { \
- if (error != NRF_SUCCESS) \
- { \
- NRF_LOG_ERROR("Error 0x%04X: %s", error, nrf_crypto_error_string_get(error));\
- APP_ERROR_CHECK(error); \
- } \
- } while(0)
- //==================================== Communication functions ====================================
- //
- // This part of an example contains helper functions to demonstrate communication between
- // Alice and Bob.
- //
- static uint8_t m_message_for_alice[256]; ///< @brief Message buffer from Bob to Alice
- static size_t m_message_for_alice_size; ///< @brief Message buffer size from Bob to Alice
- static uint8_t m_message_for_bob[256]; ///< @brief Message buffer from Alice to Bob
- static size_t m_message_for_bob_size; ///< @brief Message buffer size from Alice to Bob
- /** @brief Function to demonstrate message send to Alice.
- */
- static void send_to_alice(const uint8_t * p_data, size_t size)
- {
- print_hex("Message with public key from Bob to Alice: ", p_data, size);
- memcpy(m_message_for_alice, p_data, size);
- m_message_for_alice_size = size;
- }
- /** @brief Function to demonstrate message send to Bob.
- */
- static void send_to_bob(const uint8_t * p_data, size_t size)
- {
- print_hex("Message with public key from Alice to Bob: ", p_data, size);
- memcpy(m_message_for_bob, p_data, size);
- m_message_for_bob_size = size;
- }
- /** @brief Function to demonstrate message receive from Alice.
- */
- static size_t recv_from_alice(uint8_t * p_data)
- {
- memcpy(p_data, m_message_for_bob, m_message_for_bob_size);
- return m_message_for_bob_size;
- }
- /** @brief Function to demonstrate message receive from Bob.
- */
- static size_t recv_from_bob(uint8_t * p_data)
- {
- memcpy(p_data, m_message_for_alice, m_message_for_alice_size);
- return m_message_for_alice_size;
- }
- //========================================= Alice's site =========================================
- //
- // This part of an example contains implementation of Alice's site. Alice have public and private
- // key predefined. She is using always the same key pair for every secure connection. Code is
- // divided into two steps - before and after public key exchange with Bob.
- //
- /** @brief Predefined example private key
- *
- * This private key contains some dummy data just to show the functionality. Is should never be
- * placed in any practical usage. Is is not secure, because it is filled with ones (in HEX).
- */
- static const uint8_t m_alice_raw_private_key[] =
- {
- 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, // This is an example. DO NOT USE THIS KEY!
- 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, // This is an example. DO NOT USE THIS KEY!
- 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, // This is an example. DO NOT USE THIS KEY!
- 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, // This is an example. DO NOT USE THIS KEY!
- };
- /** @brief Predefined example public key that is associated with example private key
- * @ref alice_raw_private_key.
- */
- static const uint8_t m_alice_raw_public_key[] =
- {
- 0x02, 0x17, 0xE6, 0x17, 0xF0, 0xB6, 0x44, 0x39,
- 0x28, 0x27, 0x8F, 0x96, 0x99, 0x9E, 0x69, 0xA2,
- 0x3A, 0x4F, 0x2C, 0x15, 0x2B, 0xDF, 0x6D, 0x6C,
- 0xDF, 0x66, 0xE5, 0xB8, 0x02, 0x82, 0xD4, 0xED,
- 0x19, 0x4A, 0x7D, 0xEB, 0xCB, 0x97, 0x71, 0x2D,
- 0x2D, 0xDA, 0x3C, 0xA8, 0x5A, 0xA8, 0x76, 0x5A,
- 0x56, 0xF4, 0x5F, 0xC7, 0x58, 0x59, 0x96, 0x52,
- 0xF2, 0x89, 0x7C, 0x65, 0x30, 0x6E, 0x57, 0x94,
- };
- static nrf_crypto_ecdh_secp256r1_shared_secret_t m_shared_secret_bob;
- static nrf_crypto_ecdh_secp256r1_shared_secret_t m_shared_secret_alice;
- /** @brief First step of Alice's work. Ended with send public key to Bob.
- */
- static void alice_step_1()
- {
- NRF_LOG_INFO("Alice's prepare step");
- // Alice have predefined public key, so she just sends it to Bob
- send_to_bob(m_alice_raw_public_key, sizeof(m_alice_raw_public_key));
- }
- /** @brief Second step of Alice's work. At the end Alice will have shared secret the same as
- * Bob has.
- */
- static void alice_step_2()
- {
- static nrf_crypto_ecc_private_key_t alice_private_key;
- static nrf_crypto_ecc_public_key_t bob_public_key;
- static nrf_crypto_ecc_secp256r1_raw_public_key_t raw_key_buffer;
- ret_code_t err_code = NRF_SUCCESS;
- size_t size;
- NRF_LOG_INFO("Alice's compute step");
- // Alice receives Bob's raw public key
- size = recv_from_bob(raw_key_buffer);
- // Alice converts Bob's raw public key to internal representation
- err_code = nrf_crypto_ecc_public_key_from_raw(&g_nrf_crypto_ecc_secp256r1_curve_info,
- &bob_public_key,
- raw_key_buffer, size);
- DEMO_ERROR_CHECK(err_code);
- // Alice converts her raw private key to internal representation
- err_code = nrf_crypto_ecc_private_key_from_raw(&g_nrf_crypto_ecc_secp256r1_curve_info,
- &alice_private_key,
- m_alice_raw_private_key,
- sizeof(m_alice_raw_private_key));
- DEMO_ERROR_CHECK(err_code);
- // Alice computes shared secret using ECDH
- size = sizeof(m_shared_secret_alice);
- err_code = nrf_crypto_ecdh_compute(NULL,
- &alice_private_key,
- &bob_public_key,
- m_shared_secret_alice,
- &size);
- DEMO_ERROR_CHECK(err_code);
- // Alice can now use shared secret
- print_hex("Alice's shared secret: ", m_shared_secret_alice, size);
- // Key deallocation
- err_code = nrf_crypto_ecc_private_key_free(&alice_private_key);
- DEMO_ERROR_CHECK(err_code);
- err_code = nrf_crypto_ecc_public_key_free(&bob_public_key);
- DEMO_ERROR_CHECK(err_code);
- }
- //========================================== Bob's site ==========================================
- //
- // This part of an example contains implementation of Bobs's site. Bob do not have public and
- // private key predefined. He always generates a new key pair for each connection. Code is divided
- // into two steps - before and after public key exchange with Alice.
- //
- /** @brief Bob must keep his private key between step 1 and step 2.
- */
- static nrf_crypto_ecc_private_key_t m_bob_private_key;
- /** @brief First step of Bob's work. Ended with send public key to Alice.
- */
- void bob_step_1()
- {
- static nrf_crypto_ecc_public_key_t bob_public_key;
- static nrf_crypto_ecc_secp256r1_raw_public_key_t raw_key_buffer;
- ret_code_t err_code = NRF_SUCCESS;
- size_t size;
- NRF_LOG_INFO("Bob's prepare step");
- // Bob creates new key pair each time
- err_code = nrf_crypto_ecc_key_pair_generate(NULL,
- &g_nrf_crypto_ecc_secp256r1_curve_info,
- &m_bob_private_key,
- &bob_public_key);
- DEMO_ERROR_CHECK(err_code);
- // Bob converts public key to raw representation
- size = sizeof(raw_key_buffer);
- err_code = nrf_crypto_ecc_public_key_to_raw(&bob_public_key,
- raw_key_buffer,
- &size);
- DEMO_ERROR_CHECK(err_code);
- // Bob sends raw public key to Alice
- send_to_alice(raw_key_buffer, size);
- // Key deallocation
- err_code = nrf_crypto_ecc_public_key_free(&bob_public_key);
- DEMO_ERROR_CHECK(err_code);
- }
- /** @brief Second step of Bob's work. At the end Bob will have shared secret the same as Alice has.
- */
- void bob_step_2()
- {
- static nrf_crypto_ecc_public_key_t alice_public_key;
- static nrf_crypto_ecc_secp256r1_raw_public_key_t raw_key_buffer;
- ret_code_t err_code = NRF_SUCCESS;
- size_t size;
- NRF_LOG_INFO("Bob's compute step");
- // Bob receives Alice's raw public key
- size = recv_from_alice(raw_key_buffer);
- // Bob converts Alice's raw public key to internal representation
- err_code = nrf_crypto_ecc_public_key_from_raw(&g_nrf_crypto_ecc_secp256r1_curve_info,
- &alice_public_key,
- raw_key_buffer,
- size);
- DEMO_ERROR_CHECK(err_code);
- // Bob computes shared secret using ECDH
- size = sizeof(m_shared_secret_bob);
- err_code = nrf_crypto_ecdh_compute(NULL,
- &m_bob_private_key,
- &alice_public_key,
- m_shared_secret_bob,
- &size);
- DEMO_ERROR_CHECK(err_code);
- // Bob can now use shared secret
- print_hex("Bob's shared secret: ", m_shared_secret_bob, size);
- // Key deallocation
- err_code = nrf_crypto_ecc_private_key_free(&m_bob_private_key);
- DEMO_ERROR_CHECK(err_code);
- err_code = nrf_crypto_ecc_public_key_free(&alice_public_key);
- DEMO_ERROR_CHECK(err_code);
- }
- //========================================= Example entry =========================================
- //
- /** @brief Function for initializing the nrf log module.
- */
- static void log_init(void)
- {
- ret_code_t err_code = NRF_LOG_INIT(NULL);
- APP_ERROR_CHECK(err_code);
- NRF_LOG_DEFAULT_BACKENDS_INIT();
- }
- /** @brief Function for application main entry.
- */
- int main(void)
- {
- ret_code_t err_code = NRF_SUCCESS;
- log_init();
- NRF_LOG_INFO("ECDH example started.\r\n");
- err_code = nrf_mem_init();
- DEMO_ERROR_CHECK(err_code);
- err_code = nrf_crypto_init();
- DEMO_ERROR_CHECK(err_code);
- alice_step_1(); // Alice sends her public key to Bob
- bob_step_1(); // Bob generates new key pair and sends his public key to Alice
- alice_step_2(); // Alice receives Bob's public key and computes shared secret
- bob_step_2(); // Bob receives Alice's public key and computes shared secret
- if (memcmp(m_shared_secret_alice,
- m_shared_secret_bob,
- sizeof(nrf_crypto_ecdh_secp256r1_shared_secret_t)) == 0)
- {
- NRF_LOG_INFO("ECDH example executed successfully.");
- }
- else
- {
- NRF_LOG_ERROR("ECDH example failed!!!");
- }
- for (;;)
- {
- }
- }
- /** @}
- */
|