From 8897e442f58ae507c289b6be35d96a5e27ee9e4a Mon Sep 17 00:00:00 2001
From: Chencheng Zhang <chencheng.zhang@rte.se>
Date: Tue, 26 Mar 2019 13:36:40 +0100
Subject: [PATCH] Secure HRSC v6

---
 .gitmodules                                   |    3 +
 examples/CMakeLists.txt                       |    3 +-
 examples/heart_rate_collector/main.c          |  357 ++++-
 examples/heart_rate_collector/micro-ecc       |    1 +
 .../micro_ecc_backend_ecc.c                   |  343 +++++
 .../micro_ecc_backend_ecc.h                   |  303 ++++
 .../micro_ecc_backend_ecdh.c                  |  103 ++
 .../micro_ecc_backend_ecdh.h                  |   88 ++
 .../micro_ecc_backend_shared.h                |   69 +
 examples/heart_rate_collector/nrf_ble_lesc.c  |  403 +++++
 examples/heart_rate_collector/nrf_ble_lesc.h  |  130 ++
 examples/heart_rate_collector/nrf_crypto.h    |   78 +
 .../heart_rate_collector/nrf_crypto_ecc.c     | 1315 +++++++++++++++++
 .../heart_rate_collector/nrf_crypto_ecc.h     | 1002 +++++++++++++
 .../nrf_crypto_ecc_backend.h                  |  339 +++++
 .../nrf_crypto_ecc_shared.h                   |  229 +++
 .../heart_rate_collector/nrf_crypto_ecdh.c    |  278 ++++
 .../heart_rate_collector/nrf_crypto_ecdh.h    |  201 +++
 .../nrf_crypto_ecdh_backend.h                 |  184 +++
 .../nrf_crypto_ecdh_shared.h                  |   79 +
 .../heart_rate_collector/nrf_crypto_error.h   |  113 ++
 .../heart_rate_collector/nrf_crypto_mem.h     |  186 +++
 .../heart_rate_collector/nrf_crypto_shared.c  |  114 ++
 .../heart_rate_collector/nrf_crypto_shared.h  |  190 +++
 .../heart_rate_collector/nrf_crypto_types.h   |  113 ++
 include/common/sdk_compat/sdk_alloca.h        |   85 ++
 include/common/sdk_compat/sdk_assert.h        |  116 ++
 include/common/sdk_compat/sdk_errors.h        |  167 +++
 include/common/sdk_compat/sdk_macros.h        |  175 +++
 29 files changed, 6741 insertions(+), 26 deletions(-)
 create mode 100644 .gitmodules
 create mode 160000 examples/heart_rate_collector/micro-ecc
 create mode 100644 examples/heart_rate_collector/micro_ecc_backend_ecc.c
 create mode 100644 examples/heart_rate_collector/micro_ecc_backend_ecc.h
 create mode 100644 examples/heart_rate_collector/micro_ecc_backend_ecdh.c
 create mode 100644 examples/heart_rate_collector/micro_ecc_backend_ecdh.h
 create mode 100644 examples/heart_rate_collector/micro_ecc_backend_shared.h
 create mode 100644 examples/heart_rate_collector/nrf_ble_lesc.c
 create mode 100644 examples/heart_rate_collector/nrf_ble_lesc.h
 create mode 100644 examples/heart_rate_collector/nrf_crypto.h
 create mode 100644 examples/heart_rate_collector/nrf_crypto_ecc.c
 create mode 100644 examples/heart_rate_collector/nrf_crypto_ecc.h
 create mode 100644 examples/heart_rate_collector/nrf_crypto_ecc_backend.h
 create mode 100644 examples/heart_rate_collector/nrf_crypto_ecc_shared.h
 create mode 100644 examples/heart_rate_collector/nrf_crypto_ecdh.c
 create mode 100644 examples/heart_rate_collector/nrf_crypto_ecdh.h
 create mode 100644 examples/heart_rate_collector/nrf_crypto_ecdh_backend.h
 create mode 100644 examples/heart_rate_collector/nrf_crypto_ecdh_shared.h
 create mode 100644 examples/heart_rate_collector/nrf_crypto_error.h
 create mode 100644 examples/heart_rate_collector/nrf_crypto_mem.h
 create mode 100644 examples/heart_rate_collector/nrf_crypto_shared.c
 create mode 100644 examples/heart_rate_collector/nrf_crypto_shared.h
 create mode 100644 examples/heart_rate_collector/nrf_crypto_types.h
 create mode 100644 include/common/sdk_compat/sdk_alloca.h
 create mode 100644 include/common/sdk_compat/sdk_assert.h
 create mode 100644 include/common/sdk_compat/sdk_errors.h
 create mode 100644 include/common/sdk_compat/sdk_macros.h

diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..b693ca5
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "examples/heart_rate_collector/micro-ecc"]
+	path = examples/heart_rate_collector/micro-ecc
+	url = https://github.com/kmackay/micro-ecc.git
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index 532410e..e4941ef 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -2,7 +2,7 @@ include(GNUInstallDirs)
 
 function(setup_example example_directory)
     set(EXAMPLE_NAME_BASE "${example_directory}")
-    file(GLOB EXAMPLE_SOURCE_FILES "${example_directory}/*.c")
+    file(GLOB EXAMPLE_SOURCE_FILES "${example_directory}/*.c" "${example_directory}/*/*.c")
 
     # Build executable
     foreach(SD_API_VER ${SD_API_VER_NUMS})
@@ -10,6 +10,7 @@ function(setup_example example_directory)
         add_executable(${EXAMPLE_NAME} ${EXAMPLE_SOURCE_FILES})
 
         target_compile_definitions(${EXAMPLE_NAME} PRIVATE -DNRF_SD_BLE_API=${SD_API_VER})
+        target_include_directories(${EXAMPLE_NAME} PRIVATE ../src/sd_api_common/sdk/components/libraries/util)
         target_include_directories(${EXAMPLE_NAME} PRIVATE ../include/sd_api_v${SD_API_VER})
 
         if(WIN32)
diff --git a/examples/heart_rate_collector/main.c b/examples/heart_rate_collector/main.c
index 907b104..49f33a3 100644
--- a/examples/heart_rate_collector/main.c
+++ b/examples/heart_rate_collector/main.c
@@ -57,11 +57,13 @@
 /** Includes */
 #include "ble.h"
 #include "sd_rpc.h"
+#include "nrf_ble_lesc.h"
 
 #include <stdbool.h>
 #include <stdio.h>
 #include <string.h>
-
+#include <unistd.h>
+#include <fcntl.h>
 
 /** Definitions */
 #define DEFAULT_BAUD_RATE 1000000 /**< The baud rate to be used for serial communication with nRF5 device. */
@@ -104,6 +106,15 @@ enum
 
 #define STRING_BUFFER_SIZE 50
 
+#define SEC_PARAM_BOND                      1                                 /**< Perform bonding. */
+#define SEC_PARAM_MITM                      1                                 /**< Man In The Middle protection not required. */
+#define SEC_PARAM_LESC                      1                                 /**< LE Secure Connections enabled. */
+#define SEC_PARAM_KEYPRESS                  0                                 /**< Keypress notifications not enabled. */
+#define SEC_PARAM_IO_CAPABILITIES           BLE_GAP_IO_CAPS_KEYBOARD_DISPLAY  /**< No I/O capabilities. */
+#define SEC_PARAM_OOB                       0                                 /**< Out Of Band data not available. */
+#define SEC_PARAM_MIN_KEY_SIZE              7                                 /**< Minimum encryption key size. */
+#define SEC_PARAM_MAX_KEY_SIZE              16                                /**< Maximum encryption key size. */
+
 typedef struct
 {
     uint8_t *     p_data;   /**< Pointer to data. */
@@ -177,7 +188,7 @@ static const ble_gap_conn_params_t m_connection_param =
  */
 static void status_handler(adapter_t * adapter, sd_rpc_app_status_t code, const char * message)
 {
-    printf("Status: %d, message: %s\n", (uint32_t)code, message);
+    printf("SDH: Status: %d, message: %s\n", (uint32_t)code, message);
     fflush(stdout);
 }
 
@@ -430,7 +441,7 @@ static uint32_t ble_cfg_set(uint8_t conn_cfg_tag)
 #endif
     ble_cfg.gap_cfg.role_count_cfg.periph_role_count    = 0;
     ble_cfg.gap_cfg.role_count_cfg.central_role_count   = 1;
-    ble_cfg.gap_cfg.role_count_cfg.central_sec_count    = 0;
+    ble_cfg.gap_cfg.role_count_cfg.central_sec_count    = 1;
 
     error_code = sd_ble_cfg_set(m_adapter, BLE_GAP_CFG_ROLE_COUNT, &ble_cfg, ram_start);
     if (error_code != NRF_SUCCESS)
@@ -440,9 +451,26 @@ static uint32_t ble_cfg_set(uint8_t conn_cfg_tag)
         return error_code;
     }
 
+    // Configure the connection GAP config.
+    memset(&ble_cfg, 0x00, sizeof(ble_cfg));
+    ble_cfg.conn_cfg.conn_cfg_tag                     = conn_cfg_tag;
+    ble_cfg.conn_cfg.params.gap_conn_cfg.conn_count   = BLE_GAP_CONN_COUNT_DEFAULT;
+    ble_cfg.conn_cfg.params.gap_conn_cfg.event_length = BLE_GAP_EVENT_LENGTH_DEFAULT;
+
+    error_code = sd_ble_cfg_set(m_adapter, BLE_CONN_CFG_GAP, &ble_cfg, ram_start);
+    if (error_code != NRF_SUCCESS)
+    {
+        printf("sd_ble_cfg_set() failed when attempting to set BLE_CONN_CFG_GAP. Error code: 0x%02X\n", error_code);
+        fflush(stdout);
+        return error_code;
+    }
+
+    // Configure the connection GATT config.
     memset(&ble_cfg, 0x00, sizeof(ble_cfg));
     ble_cfg.conn_cfg.conn_cfg_tag                 = conn_cfg_tag;
-    ble_cfg.conn_cfg.params.gatt_conn_cfg.att_mtu = 150;
+    // ble_cfg.conn_cfg.params.gatt_conn_cfg.att_mtu = 150;
+    // ble_cfg.conn_cfg.params.gatt_conn_cfg.att_mtu = BLE_GATT_ATT_MTU_DEFAULT;
+    ble_cfg.conn_cfg.params.gatt_conn_cfg.att_mtu = 247;
 
     error_code = sd_ble_cfg_set(m_adapter, BLE_CONN_CFG_GATT, &ble_cfg, ram_start);
     if (error_code != NRF_SUCCESS)
@@ -486,6 +514,34 @@ static uint32_t scan_start()
     return error_code;
 }
 
+/**@brief Start scanning (GAP Discovery procedure, Observer Procedure).
+ * *
+ * @return NRF_SUCCESS on successfully initiating scanning procedure, otherwise an error code.
+ */
+static void authentication_start()
+{
+    ble_gap_sec_params_t m_sec_params;   /**< Security requirements for this application. */
+    memset(&m_sec_params, 0, sizeof(m_sec_params));
+    m_sec_params.bond         = SEC_PARAM_BOND;
+    m_sec_params.mitm         = SEC_PARAM_MITM;
+    m_sec_params.lesc         = SEC_PARAM_LESC;
+    m_sec_params.keypress     = SEC_PARAM_KEYPRESS;
+    m_sec_params.io_caps      = SEC_PARAM_IO_CAPABILITIES;
+    m_sec_params.oob          = SEC_PARAM_OOB;
+    m_sec_params.min_key_size = SEC_PARAM_MIN_KEY_SIZE;
+    m_sec_params.max_key_size = SEC_PARAM_MAX_KEY_SIZE;
+
+    uint32_t error_code = sd_ble_gap_authenticate(m_adapter, m_connection_handle, &m_sec_params);
+    if (error_code != NRF_SUCCESS)
+    {
+        printf("sd_ble_gap_authenticate failed with error code: 0x%04X\n", error_code);
+    } else
+    {
+        printf("sd_ble_gap_authenticate succeeded\n");
+    }
+    fflush(stdout);
+}
+
 /**@brief Function called upon connecting to BLE peripheral.
  *
  * @details Initiates primary service discovery.
@@ -608,7 +664,10 @@ static void on_connected(const ble_gap_evt_t * const p_ble_gap_evt)
     m_connection_handle         = p_ble_gap_evt->conn_handle;
     m_connection_is_in_progress = false;
 
-    service_discovery_start();
+    // service_discovery_start();
+#if NRF_SD_BLE_API < 3
+    authentication_start();
+#endif
 }
 
 /**@brief Function called on BLE_GAP_EVT_ADV_REPORT event.
@@ -624,7 +683,7 @@ static void on_adv_report(const ble_gap_evt_t * const p_ble_gap_evt)
 
     // Log the Bluetooth device address of advertisement packet received.
     ble_address_to_string_convert(p_ble_gap_evt->params.adv_report.peer_addr, str);
-    printf("Received advertisement report with device address: 0x%s\n", str);
+    printf("Received BLE_GAP_EVT_ADV_REPORT with device address: 0x%s\n", str);
     fflush(stdout);
 
     if (find_adv_name(&p_ble_gap_evt->params.adv_report, TARGET_DEV_NAME))
@@ -686,6 +745,47 @@ static void on_timeout(const ble_gap_evt_t * const p_ble_gap_evt)
     }
 }
 
+/**@brief Function called on BLE_GAP_EVT_SEC_PARAMS_REQUEST event.
+ *
+ * @param[in] ble_gap_evt_t Security parameters request.
+ */
+static void on_sec_params_request(const ble_gap_evt_t * const p_ble_gap_evt)
+{
+    printf("Received BLE_GAP_EVT_SEC_PARAMS_REQUEST\n");
+    ble_gap_sec_keyset_t s_sec_keyset;   /**< Security key set for both local and peer keys. */
+    memset(&s_sec_keyset, 0, sizeof(s_sec_keyset));
+
+    ble_gap_sec_keys_t keys_own;
+    ble_gap_sec_keys_t keys_peer;
+    memset(&keys_own, 0, sizeof(keys_own));
+    memset(&keys_peer, 0, sizeof(keys_peer));
+    keys_own.p_pk = nrf_ble_lesc_public_key_get();
+
+    s_sec_keyset.keys_own  = keys_own;
+    s_sec_keyset.keys_peer = keys_peer;
+    if (s_sec_keyset.keys_own.p_pk == NULL)
+    {
+        printf("Got NULL p_pk!\n");
+    }
+    else
+    {
+        printf("Got p_pk\n");
+    }
+    fflush(stdout);
+
+    uint32_t err_code = sd_ble_gap_sec_params_reply(m_adapter, m_connection_handle,
+                                                    BLE_GAP_SEC_STATUS_SUCCESS, NULL, &s_sec_keyset);
+    if (err_code != NRF_SUCCESS)
+    {
+        printf("Security parameters reply failed, err_code 0x%04X\n", err_code);
+    }
+    else
+    {
+        printf("Security parameters replied.\n");
+    }
+    fflush(stdout);
+}
+
 /**@brief Function called on BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP event.
  *
  * @details Update service state and proceed to discovering the service's GATT characteristics.
@@ -698,7 +798,7 @@ static void on_service_discovery_response(const ble_gattc_evt_t * const p_ble_ga
     int service_index;
     const ble_gattc_service_t * service;
 
-    printf("Received service discovery response\n");
+    printf("Received BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP\n");
     fflush(stdout);
 
     if (p_ble_gattc_evt->gatt_status != NRF_SUCCESS)
@@ -760,7 +860,7 @@ static void on_characteristic_discovery_response(const ble_gattc_evt_t * const p
         return;
     }
 
-    printf("Received characteristic discovery response, characteristics count: %d\n", count);
+    printf("Received BLE_GATTC_EVT_CHAR_DISC_RSP, characteristics count: %d\n", count);
     fflush(stdout);
 
     for (int i = 0; i < count; i++)
@@ -797,7 +897,7 @@ static void on_descriptor_discovery_response(const ble_gattc_evt_t * const p_ble
         return;
     }
 
-    printf("Received descriptor discovery response, descriptor count: %d\n", count);
+    printf("Received BLE_GATTC_EVT_DESC_DISC_RSP, descriptor count: %d\n", count);
     fflush(stdout);
 
     for (int i = 0; i < count; i++)
@@ -822,7 +922,7 @@ static void on_descriptor_discovery_response(const ble_gattc_evt_t * const p_ble
  */
 static void on_write_response(const ble_gattc_evt_t * const p_ble_gattc_evt)
 {
-    printf("Received write response.\n");
+    printf("Received BLE_GATTC_EVT_WRITE_RSP.\n");
     fflush(stdout);
 
     if (p_ble_gattc_evt->gatt_status != NRF_SUCCESS)
@@ -844,7 +944,7 @@ static void on_hvx(const ble_gattc_evt_t * const p_ble_gattc_evt)
             p_ble_gattc_evt->params.hvx.handle <= m_hrm_cccd_handle) // Heart rate measurement.
     {
         // We know the heart rate reading is encoded as 2 bytes [flag, value].
-        printf("Received heart rate measurement: %d\n", p_ble_gattc_evt->params.hvx.data[1]);
+        printf("Received BLE_GATTC_EVT_HVX heart rate measurement: %d\n", p_ble_gattc_evt->params.hvx.data[1]);
     }
     else // Unknown data.
     {
@@ -854,6 +954,63 @@ static void on_hvx(const ble_gattc_evt_t * const p_ble_gattc_evt)
     fflush(stdout);
 }
 
+#if NRF_SD_BLE_API >= 5
+/**@brief Function called on BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST event.
+ *
+ * @details Data length update request
+ *
+ * @param[in] p_ble_gap_evt Data length update request Event.
+ */
+static void on_conn_data_length_update_request(const ble_gap_evt_t * const p_ble_gap_evt)
+{
+    ble_gap_data_length_params_t data_length = p_ble_gap_evt->params.data_length_update_request.peer_params;
+
+    printf("Received BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST. Peer data length is:\n");
+    printf("\tmax_rx_octets = %d\n", data_length.max_rx_octets);
+    printf("\tmax_tx_octets = %d\n", data_length.max_tx_octets);
+    printf("\tmax_rx_time = %d\n", data_length.max_rx_time_us);
+    printf("\tmax_tx_time = %d\n", data_length.max_tx_time_us);
+    fflush(stdout);
+
+    ble_gap_data_length_params_t const dlp =
+    {
+        // .max_rx_octets = 27, /* ref: NRF_SDH_BLE_GAP_DATA_LENGTH in sdk_config.h */
+        // .max_tx_octets = 27, /* ref: NRF_SDH_BLE_GAP_DATA_LENGTH in sdk_config.h */
+        // .max_rx_time_us = BLE_GAP_DATA_LENGTH_AUTO,
+        // .max_tx_time_us = BLE_GAP_DATA_LENGTH_AUTO
+        .max_rx_octets = 157, /* 157 is the maximum value that works */
+        .max_tx_octets = 157, /* 157 is the maximum value that works */
+        .max_rx_time_us = BLE_GAP_DATA_LENGTH_AUTO,
+        .max_tx_time_us = BLE_GAP_DATA_LENGTH_AUTO
+    };
+
+    ble_gap_data_length_limitation_t dll = { 0 };
+
+    uint32_t err_code = sd_ble_gap_data_length_update(m_adapter, m_connection_handle, &dlp, &dll);
+    // uint32_t err_code = sd_ble_gap_data_length_update(m_adapter, m_connection_handle, NULL, NULL);
+    if (err_code != NRF_SUCCESS)
+    {
+        printf("sd_ble_gap_data_length_update failed, err_code %d\n", err_code);
+        fflush(stdout);
+    }
+}
+
+/**@brief Function called on BLE_GAP_EVT_DATA_LENGTH_UPDATE event.
+ *
+ * @details Data length update request
+ *
+ * @param[in] p_ble_gap_evt Data length updated Event.
+ */
+static void on_conn_data_length_updated(const ble_gap_evt_t * const p_ble_gap_evt)
+{
+    printf("Received BLE_GAP_EVT_DATA_LENGTH_UPDATE (%u, max_rx_time %u).\n",
+            p_ble_gap_evt->params.data_length_update.effective_params.max_rx_octets,
+            p_ble_gap_evt->params.data_length_update.effective_params.max_rx_time_us);
+    fflush(stdout);
+    authentication_start();
+}
+#endif
+
 /**@brief Function called on BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST event.
  *
  * @details Update GAP connection parameters.
@@ -881,13 +1038,17 @@ static void on_conn_params_update_request(const ble_gap_evt_t * const p_ble_gap_
  */
 static void on_exchange_mtu_request(const ble_gatts_evt_t * const p_ble_gatts_evt)
 {
+    printf("Received BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST. Reply with 247\n");
+    fflush(stdout);
+
     uint32_t err_code = sd_ble_gatts_exchange_mtu_reply(
         m_adapter,
         m_connection_handle,
 #if NRF_SD_BLE_API < 5
         GATT_MTU_SIZE_DEFAULT);
 #else
-        BLE_GATT_ATT_MTU_DEFAULT);
+        // BLE_GATT_ATT_MTU_DEFAULT);
+        247);
 #endif
 
     if (err_code != NRF_SUCCESS)
@@ -907,11 +1068,33 @@ static void on_exchange_mtu_response(const ble_gattc_evt_t * const p_ble_gattc_e
 {
     uint16_t server_rx_mtu = p_ble_gattc_evt->params.exchange_mtu_rsp.server_rx_mtu;
 
-    printf("MTU response received. New ATT_MTU is %d\n", server_rx_mtu);
+    printf("Received BLE_GATTC_EVT_EXCHANGE_MTU_RSP. New ATT_MTU is %d\n", server_rx_mtu);
     fflush(stdout);
 }
 #endif
 
+#if NRF_SD_BLE_API == 3
+/**@brief Function called on BLE_EVT_DATA_LENGTH_CHANGED event.
+ *
+ * @details Logs the new BLE changed data length.
+ *
+ * @param[in] p_ble_common_evt BLE Common Event.
+ */
+static void on_data_length_changed(const ble_common_evt_t * const p_ble_common_evt)
+{
+    ble_evt_data_length_changed_t data_length = p_ble_common_evt->params.data_length_changed;
+
+    printf("Received BLE_EVT_DATA_LENGTH_CHANGED. New data length is:\n");
+    printf("\tmax_rx_octets = %d\n", data_length.max_rx_octets);
+    printf("\tmax_tx_octets = %d\n", data_length.max_tx_octets);
+    printf("\tmax_rx_time = %d\n", data_length.max_rx_time);
+    printf("\tmax_tx_time = %d\n", data_length.max_tx_time);
+    fflush(stdout);
+
+    authentication_start();
+}
+#endif
+
 
 /** Event dispatcher */
 
@@ -936,6 +1119,7 @@ static void ble_evt_dispatch(adapter_t * adapter, ble_evt_t * p_ble_evt)
             break;
 
         case BLE_GAP_EVT_DISCONNECTED:
+            nrf_ble_lesc_on_ble_evt(p_ble_evt);
             printf("Disconnected, reason: 0x%02X\n",
                    p_ble_evt->evt.gap_evt.params.disconnected.reason);
             fflush(stdout);
@@ -951,6 +1135,34 @@ static void ble_evt_dispatch(adapter_t * adapter, ble_evt_t * p_ble_evt)
             on_timeout(&(p_ble_evt->evt.gap_evt));
             break;
 
+        case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
+            on_sec_params_request(&(p_ble_evt->evt.gap_evt));
+            break;
+
+        case BLE_GAP_EVT_LESC_DHKEY_REQUEST:
+            nrf_ble_lesc_on_ble_evt(p_ble_evt);
+            break;
+
+        case BLE_GAP_EVT_CONN_SEC_UPDATE:
+            printf("BLE_GAP_EVT_AUTH_STATUS: status=0x%x bond=0x%x lv4: %d kdist_own:0x%x kdist_peer:0x%x\n",
+                   p_ble_evt->evt.gap_evt.params.auth_status.auth_status,
+                   p_ble_evt->evt.gap_evt.params.auth_status.bonded,
+                   p_ble_evt->evt.gap_evt.params.auth_status.sm1_levels.lv4,
+                   *((uint8_t *)&p_ble_evt->evt.gap_evt.params.auth_status.kdist_own),
+                   *((uint8_t *)&p_ble_evt->evt.gap_evt.params.auth_status.kdist_peer));
+            fflush(stdout);
+            if (p_ble_evt->evt.gap_evt.params.auth_status.auth_status == BLE_GAP_SEC_STATUS_SUCCESS)
+            {
+                service_discovery_start();
+            }
+            else
+            {
+                printf("Authorization failed with code: %u!\n",
+                       p_ble_evt->evt.gap_evt.params.auth_status.auth_status);
+                fflush(stdout);
+            }
+            break;
+
         case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP:
             on_service_discovery_response(&(p_ble_evt->evt.gattc_evt));
             break;
@@ -971,6 +1183,24 @@ static void ble_evt_dispatch(adapter_t * adapter, ble_evt_t * p_ble_evt)
             on_hvx(&(p_ble_evt->evt.gattc_evt));
             break;
 
+        case BLE_GAP_EVT_CONN_PARAM_UPDATE:
+        {
+            printf("Connection interval updated: 0x%x, 0x%x.\n",
+                p_ble_evt->evt.gap_evt.params.conn_param_update.conn_params.min_conn_interval,
+                p_ble_evt->evt.gap_evt.params.conn_param_update.conn_params.max_conn_interval);
+            fflush(stdout);
+        } break;
+
+    #if NRF_SD_BLE_API >= 5
+        case BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST:
+            on_conn_data_length_update_request(&(p_ble_evt->evt.gap_evt));
+            break;
+
+        case BLE_GAP_EVT_DATA_LENGTH_UPDATE:
+            on_conn_data_length_updated(&(p_ble_evt->evt.gap_evt));
+            break;
+    #endif
+
         case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST:
             on_conn_params_update_request(&(p_ble_evt->evt.gap_evt));
             break;
@@ -985,6 +1215,12 @@ static void ble_evt_dispatch(adapter_t * adapter, ble_evt_t * p_ble_evt)
             break;
     #endif
 
+    #if NRF_SD_BLE_API == 3
+        case BLE_EVT_DATA_LENGTH_CHANGED:
+            on_data_length_changed(&(p_ble_evt->evt.common_evt));
+            break;
+    #endif
+
         default:
             printf("Received an un-handled event with ID: %d\n", p_ble_evt->header.evt_id);
             fflush(stdout);
@@ -993,6 +1229,62 @@ static void ble_evt_dispatch(adapter_t * adapter, ble_evt_t * p_ble_evt)
 }
 
 
+static void shut_down()
+{
+    // error_code = sd_ble_gap_scan_stop(m_adapter);
+
+    // if (error_code != NRF_SUCCESS)
+    // {
+    //     printf("Failed to stop scanning. Error code: 0x%02X\n", error_code);
+    //     fflush(stdout);
+    // }
+
+    // Temporary fix the problem of failure to rerun the problem without reset the chip
+    uint32_t error_code = sd_ble_gap_disconnect(m_adapter, m_connection_handle, 0x13/*BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION*/);
+    if (error_code != NRF_SUCCESS)
+    {
+        printf("Failed to close connection. Error code: 0x%02X\n", error_code);
+        fflush(stdout);
+        return;
+    }
+    else
+    {
+        printf("Connection closed\n");
+        fflush(stdout);
+    }
+
+    // Wait for the disconnection callback
+    sleep(1);
+
+    error_code = sd_rpc_conn_reset(m_adapter, SYS_RESET);
+    if (error_code != NRF_SUCCESS)
+    {
+        printf("Failed to reset connectivity chip. Error code: 0x%02X\n", error_code);
+        fflush(stdout);
+        return;
+    }
+    else
+    {
+        printf("Connection chip reseted\n");
+        fflush(stdout);
+    }
+
+    error_code = sd_rpc_close(m_adapter);
+    if (error_code != NRF_SUCCESS)
+    {
+        printf("Failed to close nRF BLE Driver. Error code: 0x%02X\n", error_code);
+        fflush(stdout);
+        return;
+    }
+    else
+    {
+        printf("nRF BLE Driver closed\n");
+        fflush(stdout);
+    }
+
+    return;
+}
+
 /** Main */
 
 /**@brief Function for application main entry.
@@ -1047,6 +1339,15 @@ int main(int argc, char * argv[])
     }
 #endif
 
+    error_code = nrf_ble_lesc_init();
+
+    if (error_code != NRF_SUCCESS)
+    {
+        printf("Failed to nrf_ble_lesc_init. Error code: 0x%02X\n", error_code);
+        fflush(stdout);
+        return error_code;
+    }
+
     error_code = scan_start();
 
     if (error_code != NRF_SUCCESS)
@@ -1054,29 +1355,35 @@ int main(int argc, char * argv[])
         return error_code;
     }
 
+    int flags = fcntl(0, F_GETFL, 0); /* get current file status flags */
+    flags |= O_NONBLOCK; /* turn off blocking flag */ //flags & ~O_NONBLOCK
+    fcntl(0, F_SETFL, flags); /* set up non-blocking read */
     // Endlessly loop.
     for (;;)
     {
         char c = (char)getchar();
         if (c == 'q' || c == 'Q')
         {
-            error_code = sd_rpc_close(m_adapter);
-
-            if (error_code != NRF_SUCCESS)
-            {
-                printf("Failed to close nRF BLE Driver. Error code: 0x%02X\n", error_code);
-                fflush(stdout);
-                return error_code;
-            }
-
+            shut_down();
             printf("Closed\n");
             fflush(stdout);
 
             return NRF_SUCCESS;
         }
 
-        // Toggle notifications on the HRM characteristic every time user input is received.
-        cccd_value ^= BLE_CCCD_NOTIFY;
-        hrm_cccd_set(cccd_value);
+        error_code = nrf_ble_lesc_request_handler(m_adapter);
+        if (error_code != NRF_SUCCESS)
+        {
+            printf("Failed to handle LESC. Error code: 0x%02X\n", error_code);
+            fflush(stdout);
+            shut_down();
+            return error_code;
+        }
+        else if (c == 't')
+        {
+            // Toggle notifications on the HRM characteristic every time user input is received.
+            cccd_value ^= BLE_CCCD_NOTIFY;
+            hrm_cccd_set(cccd_value);
+        }
     }
 }
diff --git a/examples/heart_rate_collector/micro-ecc b/examples/heart_rate_collector/micro-ecc
new file mode 160000
index 0000000..601bd11
--- /dev/null
+++ b/examples/heart_rate_collector/micro-ecc
@@ -0,0 +1 @@
+Subproject commit 601bd11062c551b108adbb43ba99f199b840777c
diff --git a/examples/heart_rate_collector/micro_ecc_backend_ecc.c b/examples/heart_rate_collector/micro_ecc_backend_ecc.c
new file mode 100644
index 0000000..fcee94d
--- /dev/null
+++ b/examples/heart_rate_collector/micro_ecc_backend_ecc.c
@@ -0,0 +1,343 @@
+/**
+ * Copyright (c) 2018, 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.
+ *
+ */
+
+// #include "sdk_config.h"
+#include "nordic_common.h"
+
+// #if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC)
+
+#include <stdbool.h>
+#include <string.h>
+#include <stddef.h>
+
+// #include "app_util.h"
+#include "sdk_assert.h"
+#include "nrf_crypto_ecc.h"
+// #include "nrf_crypto_rng.h"
+#include "nrf_crypto_shared.h"
+#include "micro_ecc_backend_ecc.h"
+#include "micro_ecc_backend_shared.h"
+#include "micro-ecc/uECC.h"
+
+
+typedef uECC_Curve (*micro_ecc_curve_fn_t)(void);
+
+
+// int nrf_crypto_backend_micro_ecc_rng_callback(uint8_t * dest, unsigned size)
+// {
+// #if NRF_MODULE_ENABLED(NRF_CRYPTO_RNG)
+
+//     ret_code_t result;
+
+//     result = nrf_crypto_rng_vector_generate(dest, size);
+
+//     // Return values compatible with mbed TLS
+//     if (result != NRF_SUCCESS)
+//     {
+//         return 0;
+//     }
+//     return 1;
+
+// #else
+//     UNUSED_PARAMETER(dest);
+//     UNUSED_PARAMETER(size);
+//     return 0;
+// #endif
+// }
+
+
+uECC_Curve nrf_crypto_backend_micro_ecc_curve_get(
+    nrf_crypto_backend_micro_ecc_common_key_t const * p_key)
+{
+    nrf_crypto_internal_ecc_key_header_t const * p_key_header =
+        (nrf_crypto_internal_ecc_key_header_t const *)p_key;
+
+    //lint -save -e611 (Suspicious cast)
+    micro_ecc_curve_fn_t micro_ecc_curve_fn =
+        (micro_ecc_curve_fn_t)p_key_header->p_info->p_backend_data;
+    //lint -restore
+
+    uECC_Curve p_micro_ecc_curve = micro_ecc_curve_fn();
+
+    return p_micro_ecc_curve;
+}
+
+
+ret_code_t nrf_crypto_backend_micro_ecc_key_pair_generate(
+    void * p_context,
+    void * p_private_key,
+    void * p_public_key)
+{
+    int result;
+
+    nrf_crypto_backend_micro_ecc_common_key_t * p_prv =
+        (nrf_crypto_backend_micro_ecc_common_key_t *)p_private_key;
+    nrf_crypto_backend_micro_ecc_common_key_t * p_pub =
+        (nrf_crypto_backend_micro_ecc_common_key_t *)p_public_key;
+
+    uECC_Curve p_micro_ecc_curve = nrf_crypto_backend_micro_ecc_curve_get(p_prv);
+
+    // uECC_set_rng(nrf_crypto_backend_micro_ecc_rng_callback);
+    // TODO: RNG needed?
+
+    result = uECC_make_key((uint8_t *)(&p_pub->key[0]),
+                           (uint8_t *)(&p_prv->key[0]),
+                           p_micro_ecc_curve);
+
+    if (result == 0)
+    {
+        return NRF_ERROR_CRYPTO_INTERNAL;
+    }
+    return NRF_SUCCESS;
+}
+
+
+ret_code_t nrf_crypto_backend_micro_ecc_public_key_calculate(
+    void       * p_context,
+    void const * p_private_key,
+    void       * p_public_key)
+{
+    int result;
+
+    nrf_crypto_backend_micro_ecc_common_key_t const * p_prv =
+        (nrf_crypto_backend_micro_ecc_common_key_t const *)p_private_key;
+    nrf_crypto_backend_micro_ecc_common_key_t       * p_pub =
+        (nrf_crypto_backend_micro_ecc_common_key_t *)p_public_key;
+
+    uECC_Curve p_micro_ecc_curve = nrf_crypto_backend_micro_ecc_curve_get(p_prv);
+
+    result = uECC_compute_public_key((uint8_t *)(&p_prv->key[0]),
+                                     (uint8_t *)(&p_pub->key[0]),
+                                     p_micro_ecc_curve);
+
+    if (result == 0)
+    {
+        return NRF_ERROR_CRYPTO_INTERNAL;
+    }
+    return NRF_SUCCESS;
+}
+
+
+ret_code_t nrf_crypto_backend_micro_ecc_private_key_from_raw(
+    void          * p_private_key,
+    uint8_t const * p_raw_data)
+{
+    nrf_crypto_backend_micro_ecc_common_key_t * p_prv =
+        (nrf_crypto_backend_micro_ecc_common_key_t *)p_private_key;
+
+    nrf_crypto_ecc_curve_info_t const * p_info = p_prv->header.p_info;
+
+#if ECC_BACKEND_SWAP_BYTES
+    nrf_crypto_internal_swap_endian((uint8_t *)(&p_prv->key[0]),
+                                    p_raw_data,
+                                    p_info->raw_private_key_size);
+#else
+    memcpy(&p_prv->key[0], p_raw_data, p_info->raw_private_key_size);
+#endif
+
+    return NRF_SUCCESS;
+}
+
+
+ret_code_t nrf_crypto_backend_micro_ecc_private_key_to_raw(
+    void    const * p_private_key,
+    uint8_t       * p_raw_data)
+{
+    nrf_crypto_backend_micro_ecc_common_key_t const * p_prv =
+        (nrf_crypto_backend_micro_ecc_common_key_t const *)p_private_key;
+
+    nrf_crypto_ecc_curve_info_t const * p_info = p_prv->header.p_info;
+
+#if ECC_BACKEND_SWAP_BYTES
+    nrf_crypto_internal_swap_endian(p_raw_data,
+                                    (uint8_t *)(&p_prv->key[0]),
+                                    p_info->raw_private_key_size);
+#else
+    memcpy(p_raw_data, &p_prv->key[0], p_info->raw_private_key_size);
+#endif
+
+    return NRF_SUCCESS;
+}
+
+
+ret_code_t nrf_crypto_backend_micro_ecc_public_key_from_raw(
+    void          * p_public_key,
+    uint8_t const * p_raw_data)
+{
+    nrf_crypto_backend_micro_ecc_common_key_t * p_pub =
+        (nrf_crypto_backend_micro_ecc_common_key_t *)p_public_key;
+
+    nrf_crypto_ecc_curve_info_t const * p_info = p_pub->header.p_info;
+
+#if ECC_BACKEND_SWAP_BYTES
+    nrf_crypto_internal_double_swap_endian((uint8_t *)(&p_pub->key[0]),
+                                           p_raw_data,
+                                           p_info->raw_private_key_size);
+#else
+    memcpy(&p_pub->key[0], p_raw_data, p_info->raw_public_key_size);
+#endif
+
+    return NRF_SUCCESS;
+}
+
+
+ret_code_t nrf_crypto_backend_micro_ecc_public_key_to_raw(
+    void const * p_public_key,
+    uint8_t    * p_raw_data)
+{
+    nrf_crypto_backend_micro_ecc_common_key_t const * p_pub =
+        (nrf_crypto_backend_micro_ecc_common_key_t const *)p_public_key;
+
+    nrf_crypto_ecc_curve_info_t const * p_info = p_pub->header.p_info;
+
+#if ECC_BACKEND_SWAP_BYTES
+    nrf_crypto_internal_double_swap_endian(p_raw_data,
+                                           (uint8_t *)(&p_pub->key[0]),
+                                           p_info->raw_private_key_size);
+#else
+    memcpy(p_raw_data, &p_pub->key[0], p_info->raw_public_key_size);
+#endif
+
+    return NRF_SUCCESS;
+}
+
+
+// #if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP192R1)
+
+// // Make sure that common key structure match secp192r1 (NIST 192-bit) key structure to safely cast types.
+// STATIC_ASSERT(offsetof(nrf_crypto_backend_micro_ecc_common_key_t, key) ==
+//               offsetof(nrf_crypto_backend_secp192r1_private_key_t, key),
+//               "Common uECC private key structure does not match secp192r1 (NIST 192-bit) one.");
+// STATIC_ASSERT(offsetof(nrf_crypto_backend_micro_ecc_common_key_t, key) ==
+//               offsetof(nrf_crypto_backend_secp192r1_public_key_t, key),
+//               "Common ECC public key structure does not match secp192r1 (NIST 192-bit) one.");
+
+// const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp192r1_curve_info =
+// {
+//     .public_key_size      = sizeof(nrf_crypto_backend_secp192r1_public_key_t),
+//     .private_key_size     = sizeof(nrf_crypto_backend_secp192r1_private_key_t),
+//     .curve_type           = NRF_CRYPTO_ECC_SECP192R1_CURVE_TYPE,
+//     .raw_private_key_size = NRF_CRYPTO_ECC_SECP192R1_RAW_PRIVATE_KEY_SIZE,
+//     .raw_public_key_size  = NRF_CRYPTO_ECC_SECP192R1_RAW_PUBLIC_KEY_SIZE,
+//     //lint -save -e611 -e546 (Suspicious cast, Suspicious use of &)
+//     .p_backend_data       = (void *)&uECC_secp192r1,
+//     //lint -restore
+// };
+
+// #endif
+
+
+// #if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP224R1)
+
+// // Make sure that common key structure match secp224r1 (NIST 224-bit) key structure to safely cast types.
+// STATIC_ASSERT(offsetof(nrf_crypto_backend_micro_ecc_common_key_t, key) ==
+//               offsetof(nrf_crypto_backend_secp224r1_private_key_t, key),
+//               "Common uECC private key structure does not match secp224r1 (NIST 224-bit) one.");
+// STATIC_ASSERT(offsetof(nrf_crypto_backend_micro_ecc_common_key_t, key) ==
+//               offsetof(nrf_crypto_backend_secp224r1_public_key_t, key),
+//               "Common ECC public key structure does not match secp224r1 (NIST 224-bit) one.");
+
+// const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp224r1_curve_info =
+// {
+//     .public_key_size      = sizeof(nrf_crypto_backend_secp224r1_public_key_t),
+//     .private_key_size     = sizeof(nrf_crypto_backend_secp224r1_private_key_t),
+//     .curve_type           = NRF_CRYPTO_ECC_SECP224R1_CURVE_TYPE,
+//     .raw_private_key_size = NRF_CRYPTO_ECC_SECP224R1_RAW_PRIVATE_KEY_SIZE,
+//     .raw_public_key_size  = NRF_CRYPTO_ECC_SECP224R1_RAW_PUBLIC_KEY_SIZE,
+//     //lint -save -e611 -e546 (Suspicious cast, Suspicious use of &)
+//     .p_backend_data       = (void *)&uECC_secp224r1,
+//     //lint -restore
+// };
+
+// #endif
+
+
+// #if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP256R1)
+
+// Make sure that common key structure match secp256r1 (NIST 256-bit) key structure to safely cast types.
+STATIC_ASSERT(offsetof(nrf_crypto_backend_micro_ecc_common_key_t, key) ==
+              offsetof(nrf_crypto_backend_secp256r1_private_key_t, key),
+              "Common uECC private key structure does not match secp256r1 (NIST 256-bit) one.");
+STATIC_ASSERT(offsetof(nrf_crypto_backend_micro_ecc_common_key_t, key) ==
+              offsetof(nrf_crypto_backend_secp256r1_public_key_t, key),
+              "Common ECC public key structure does not match secp256r1 (NIST 256-bit) one.");
+
+const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp256r1_curve_info =
+{
+    .public_key_size      = sizeof(nrf_crypto_backend_secp256r1_public_key_t),
+    .private_key_size     = sizeof(nrf_crypto_backend_secp256r1_private_key_t),
+    .curve_type           = NRF_CRYPTO_ECC_SECP256R1_CURVE_TYPE,
+    .raw_private_key_size = NRF_CRYPTO_ECC_SECP256R1_RAW_PRIVATE_KEY_SIZE,
+    .raw_public_key_size  = NRF_CRYPTO_ECC_SECP256R1_RAW_PUBLIC_KEY_SIZE,
+    //lint -save -e611 -e546 (Suspicious cast, Suspicious use of &)
+    .p_backend_data       = (void *)&uECC_secp256r1,
+    //lint -restore
+};
+
+// #endif
+
+
+// #if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP256K1)
+
+// Make sure that common key structure match secp256k1 (Koblitz 256-bit) key structure to safely cast types.
+// STATIC_ASSERT(offsetof(nrf_crypto_backend_micro_ecc_common_key_t, key) ==
+//               offsetof(nrf_crypto_backend_secp256k1_private_key_t, key),
+//               "Common uECC private key structure does not match secp256k1 (Koblitz 256-bit) one.");
+// STATIC_ASSERT(offsetof(nrf_crypto_backend_micro_ecc_common_key_t, key) ==
+//               offsetof(nrf_crypto_backend_secp256k1_public_key_t, key),
+//               "Common ECC public key structure does not match secp256k1 (Koblitz 256-bit) one.");
+
+
+// const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp256k1_curve_info =
+// {
+//     .public_key_size      = sizeof(nrf_crypto_backend_secp256k1_public_key_t),
+//     .private_key_size     = sizeof(nrf_crypto_backend_secp256k1_private_key_t),
+//     .curve_type           = NRF_CRYPTO_ECC_SECP256K1_CURVE_TYPE,
+//     .raw_private_key_size = NRF_CRYPTO_ECC_SECP256K1_RAW_PRIVATE_KEY_SIZE,
+//     .raw_public_key_size  = NRF_CRYPTO_ECC_SECP256K1_RAW_PUBLIC_KEY_SIZE,
+//     //lint -save -e611 -e546 (Suspicious cast, Suspicious use of &)
+//     .p_backend_data       = (void *)&uECC_secp256k1,
+//     //lint -restore
+// };
+
+// #endif
+
+
+// #endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC)
diff --git a/examples/heart_rate_collector/micro_ecc_backend_ecc.h b/examples/heart_rate_collector/micro_ecc_backend_ecc.h
new file mode 100644
index 0000000..8434e8a
--- /dev/null
+++ b/examples/heart_rate_collector/micro_ecc_backend_ecc.h
@@ -0,0 +1,303 @@
+/**
+ * Copyright (c) 2018, 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.
+ *
+ */
+
+#ifndef MICRO_ECC_BACKEND_ECC_H__
+#define MICRO_ECC_BACKEND_ECC_H__
+
+// #include "sdk_config.h"
+#include "nordic_common.h"
+
+// #if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC)
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "nrf_crypto_ecc_shared.h"
+#include "micro-ecc/uECC.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/** @internal See @ref nrf_crypto_backend_ecc_key_pair_generate_fn_t.
+ */
+ret_code_t nrf_crypto_backend_micro_ecc_key_pair_generate(
+    void * p_context,
+    void * p_private_key,
+    void * p_public_key);
+
+
+/** @internal See @ref nrf_crypto_backend_ecc_public_key_calculate_fn_t.
+*/
+ret_code_t nrf_crypto_backend_micro_ecc_public_key_calculate(
+    void       * p_context,
+    void const * p_private_key,
+    void       * p_public_key);
+
+
+/** @internal See @ref nrf_crypto_backend_ecc_private_key_from_raw_fn_t.
+*/
+ret_code_t nrf_crypto_backend_micro_ecc_private_key_from_raw(
+    void          * p_private_key,
+    uint8_t const * p_raw_data);
+
+
+/** @internal See @ref nrf_crypto_backend_ecc_private_key_to_raw_fn_t.
+*/
+ret_code_t nrf_crypto_backend_micro_ecc_private_key_to_raw(
+    void    const * p_private_key,
+    uint8_t       * p_raw_data);
+
+
+/** @internal See @ref nrf_crypto_backend_ecc_public_key_from_raw_fn_t.
+*/
+ret_code_t nrf_crypto_backend_micro_ecc_public_key_from_raw(
+    void          * p_public_key,
+    uint8_t const * p_raw_data);
+
+
+/** @internal See @ref nrf_crypto_backend_ecc_public_key_to_raw_fn_t.
+*/
+ret_code_t nrf_crypto_backend_micro_ecc_public_key_to_raw(
+    void const * p_public_key,
+    uint8_t    * p_raw_data);
+
+
+/** @internal @brief Represents common uECC backend key structure.
+ */
+typedef struct
+{
+    nrf_crypto_internal_ecc_key_header_t header; /**< @internal @brief Common ECC key header */
+    uint32_t key[1];                             /**< @internal @brief micro-ecc specific key representation */
+} nrf_crypto_backend_micro_ecc_common_key_t;
+
+
+// /** @internal @brief Callback RNG function that can be provided to uECC API.
+//  *  @param dest     Destination buffer.
+//  *  @param size     Size of the buffer.
+//  *  @return         1 on success, 0 on error.
+//  */
+// int nrf_crypto_backend_micro_ecc_rng_callback(uint8_t * dest, unsigned size);
+
+
+/** @internal @brief Gets uECC type based on provided key.
+ *  @param p_key    uECC backend key (public or private).
+ *  @return         uECC specific value representing a curve.
+ */
+uECC_Curve nrf_crypto_backend_micro_ecc_curve_get(
+    nrf_crypto_backend_micro_ecc_common_key_t const * p_key);
+
+
+// #if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP192R1)
+
+// #if NRF_MODULE_ENABLED(NRF_CRYPTO_ECC_SECP192R1)
+// #error "More than one backend enabled for secp192r1 (NIST 192-bit).");
+// #endif
+// #define NRF_CRYPTO_ECC_SECP192R1_ENABLED 1
+
+// /** @internal @brief Structure holding private key for secp192r1 (NIST 192-bit) in micro-ecc.
+//  */
+// typedef struct
+// {
+//     nrf_crypto_internal_ecc_key_header_t header; /**< @internal @brief Common ECC key header */
+//     uint32_t key[192 / 32];                      /**< @internal @brief micro-ecc specific key representation */
+// } nrf_crypto_backend_secp192r1_private_key_t;
+
+// /** @internal @brief Structure holding public key for secp192r1 (NIST 192-bit) in micro-ecc.
+//  */
+// typedef struct
+// {
+//     nrf_crypto_internal_ecc_key_header_t header; /**< @internal @brief Common ECC key header */
+//     uint32_t key[2 * 192 / 32];                  /**< @internal @brief micro-ecc specific key representation */
+// } nrf_crypto_backend_secp192r1_public_key_t;
+
+// // Aliases for one common micro-ecc implementation
+// #define nrf_crypto_backend_secp192r1_key_pair_generate nrf_crypto_backend_micro_ecc_key_pair_generate
+// #define nrf_crypto_backend_secp192r1_public_key_calculate nrf_crypto_backend_micro_ecc_public_key_calculate
+// #define nrf_crypto_backend_secp192r1_private_key_from_raw nrf_crypto_backend_micro_ecc_private_key_from_raw
+// #define nrf_crypto_backend_secp192r1_private_key_to_raw nrf_crypto_backend_micro_ecc_private_key_to_raw
+// #define nrf_crypto_backend_secp192r1_public_key_from_raw nrf_crypto_backend_micro_ecc_public_key_from_raw
+// #define nrf_crypto_backend_secp192r1_public_key_to_raw nrf_crypto_backend_micro_ecc_public_key_to_raw
+// #define nrf_crypto_backend_secp192r1_private_key_free NULL
+// #define nrf_crypto_backend_secp192r1_public_key_free NULL
+// #define NRF_CRYPTO_BACKEND_SECP192R1_KEY_PAIR_GENERATE_CONTEXT_SIZE 0
+// #define NRF_CRYPTO_BACKEND_SECP192R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE 0
+
+// // Dummy typedef for unused context
+// typedef uint32_t nrf_crypto_backend_secp192r1_key_pair_generate_context_t;
+// typedef uint32_t nrf_crypto_backend_secp192r1_public_key_calculate_context_t;
+
+// #endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP192R1)
+
+
+// #if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP224R1)
+
+// #if NRF_MODULE_ENABLED(NRF_CRYPTO_ECC_SECP224R1)
+// #error "More than one backend enabled for secp224r1 (NIST 224-bit).");
+// #endif
+// #define NRF_CRYPTO_ECC_SECP224R1_ENABLED 1
+
+// /** @internal @brief Structure holding private key for secp224r1 (NIST 224-bit) in micro-ecc.
+//  */
+// typedef struct
+// {
+//     nrf_crypto_internal_ecc_key_header_t header; /**< @internal @brief Common ECC key header */
+//     uint32_t key[224 / 32];                      /**< @internal @brief micro-ecc specific key representation */
+// } nrf_crypto_backend_secp224r1_private_key_t;
+
+// /** @internal @brief Structure holding public key for secp224r1 (NIST 224-bit) in micro-ecc.
+//  */
+// typedef struct
+// {
+//     nrf_crypto_internal_ecc_key_header_t header; /**< @internal @brief Common ECC key header */
+//     uint32_t key[2 * 224 / 32];                  /**< @internal @brief micro-ecc specific key representation */
+// } nrf_crypto_backend_secp224r1_public_key_t;
+
+// // Aliases for one common micro-ecc implementation
+// #define nrf_crypto_backend_secp224r1_key_pair_generate nrf_crypto_backend_micro_ecc_key_pair_generate
+// #define nrf_crypto_backend_secp224r1_public_key_calculate nrf_crypto_backend_micro_ecc_public_key_calculate
+// #define nrf_crypto_backend_secp224r1_private_key_from_raw nrf_crypto_backend_micro_ecc_private_key_from_raw
+// #define nrf_crypto_backend_secp224r1_private_key_to_raw nrf_crypto_backend_micro_ecc_private_key_to_raw
+// #define nrf_crypto_backend_secp224r1_public_key_from_raw nrf_crypto_backend_micro_ecc_public_key_from_raw
+// #define nrf_crypto_backend_secp224r1_public_key_to_raw nrf_crypto_backend_micro_ecc_public_key_to_raw
+// #define nrf_crypto_backend_secp224r1_private_key_free NULL
+// #define nrf_crypto_backend_secp224r1_public_key_free NULL
+// #define NRF_CRYPTO_BACKEND_SECP224R1_KEY_PAIR_GENERATE_CONTEXT_SIZE 0
+// #define NRF_CRYPTO_BACKEND_SECP224R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE 0
+
+// // Dummy typedef for unused context
+// typedef uint32_t nrf_crypto_backend_secp224r1_key_pair_generate_context_t;
+// typedef uint32_t nrf_crypto_backend_secp224r1_public_key_calculate_context_t;
+
+// #endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP224R1)
+
+
+// #if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP256R1)
+
+// #if NRF_MODULE_ENABLED(NRF_CRYPTO_ECC_SECP256R1)
+// #error "More than one backend enabled for secp256r1 (NIST 256-bit).");
+// #endif
+#define NRF_CRYPTO_ECC_SECP256R1_ENABLED 1
+
+/** @internal @brief Structure holding private key for secp256r1 (NIST 256-bit) in micro-ecc.
+ */
+typedef struct
+{
+    nrf_crypto_internal_ecc_key_header_t header; /**< @internal @brief Common ECC key header */
+    uint32_t key[256 / 32];                      /**< @internal @brief micro-ecc specific key representation */
+} nrf_crypto_backend_secp256r1_private_key_t;
+
+/** @internal @brief Structure holding public key for secp256r1 (NIST 256-bit) in micro-ecc.
+ */
+typedef struct
+{
+    nrf_crypto_internal_ecc_key_header_t header; /**< @internal @brief Common ECC key header */
+    uint32_t key[2 * 256 / 32];                  /**< @internal @brief micro-ecc specific key representation */
+} nrf_crypto_backend_secp256r1_public_key_t;
+
+// Aliases for one common micro-ecc implementation
+#define nrf_crypto_backend_secp256r1_key_pair_generate nrf_crypto_backend_micro_ecc_key_pair_generate
+#define nrf_crypto_backend_secp256r1_public_key_calculate nrf_crypto_backend_micro_ecc_public_key_calculate
+#define nrf_crypto_backend_secp256r1_private_key_from_raw nrf_crypto_backend_micro_ecc_private_key_from_raw
+#define nrf_crypto_backend_secp256r1_private_key_to_raw nrf_crypto_backend_micro_ecc_private_key_to_raw
+#define nrf_crypto_backend_secp256r1_public_key_from_raw nrf_crypto_backend_micro_ecc_public_key_from_raw
+#define nrf_crypto_backend_secp256r1_public_key_to_raw nrf_crypto_backend_micro_ecc_public_key_to_raw
+#define nrf_crypto_backend_secp256r1_private_key_free NULL
+#define nrf_crypto_backend_secp256r1_public_key_free NULL
+#define NRF_CRYPTO_BACKEND_SECP256R1_KEY_PAIR_GENERATE_CONTEXT_SIZE 0
+#define NRF_CRYPTO_BACKEND_SECP256R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE 0
+
+// Dummy typedef for unused context
+typedef uint32_t nrf_crypto_backend_secp256r1_key_pair_generate_context_t;
+typedef uint32_t nrf_crypto_backend_secp256r1_public_key_calculate_context_t;
+
+// #endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP256R1)
+
+
+// #if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP256K1)
+
+// #if NRF_MODULE_ENABLED(NRF_CRYPTO_ECC_SECP256K1)
+// #error "More than one backend enabled for secp256k1 (Koblitz 256-bit).");
+// #endif
+// #define NRF_CRYPTO_ECC_SECP256K1_ENABLED 1
+
+// /** @internal @brief Structure holding private key for secp256k1 (Koblitz 256-bit) in micro-ecc.
+//  */
+// typedef struct
+// {
+//     nrf_crypto_internal_ecc_key_header_t header; /**< @internal @brief Common ECC key header */
+//     uint32_t key[256 / 32];                      /**< @internal @brief micro-ecc specific key representation */
+// } nrf_crypto_backend_secp256k1_private_key_t;
+
+// /** @internal @brief Structure holding public key for secp256k1 (Koblitz 256-bit) in micro-ecc.
+//  */
+// typedef struct
+// {
+//     nrf_crypto_internal_ecc_key_header_t header; /**< @internal @brief Common ECC key header */
+//     uint32_t key[2 * 256 / 32];                  /**< @internal @brief micro-ecc specific key representation */
+// } nrf_crypto_backend_secp256k1_public_key_t;
+
+// // Aliases for one common micro-ecc implementation
+// #define nrf_crypto_backend_secp256k1_key_pair_generate nrf_crypto_backend_micro_ecc_key_pair_generate
+// #define nrf_crypto_backend_secp256k1_public_key_calculate nrf_crypto_backend_micro_ecc_public_key_calculate
+// #define nrf_crypto_backend_secp256k1_private_key_from_raw nrf_crypto_backend_micro_ecc_private_key_from_raw
+// #define nrf_crypto_backend_secp256k1_private_key_to_raw nrf_crypto_backend_micro_ecc_private_key_to_raw
+// #define nrf_crypto_backend_secp256k1_public_key_from_raw nrf_crypto_backend_micro_ecc_public_key_from_raw
+// #define nrf_crypto_backend_secp256k1_public_key_to_raw nrf_crypto_backend_micro_ecc_public_key_to_raw
+// #define nrf_crypto_backend_secp256k1_private_key_free NULL
+// #define nrf_crypto_backend_secp256k1_public_key_free NULL
+// #define NRF_CRYPTO_BACKEND_SECP256K1_KEY_PAIR_GENERATE_CONTEXT_SIZE 0
+// #define NRF_CRYPTO_BACKEND_SECP256K1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE 0
+
+// // Dummy typedef for unused context
+// typedef uint32_t nrf_crypto_backend_secp256k1_key_pair_generate_context_t;
+// typedef uint32_t nrf_crypto_backend_secp256k1_public_key_calculate_context_t;
+
+// #endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP256K1)
+
+
+#ifdef __cplusplus
+}
+#endif
+
+// #endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC)
+
+#endif // MICRO_ECC_BACKEND_ECC_H__
diff --git a/examples/heart_rate_collector/micro_ecc_backend_ecdh.c b/examples/heart_rate_collector/micro_ecc_backend_ecdh.c
new file mode 100644
index 0000000..175f658
--- /dev/null
+++ b/examples/heart_rate_collector/micro_ecc_backend_ecdh.c
@@ -0,0 +1,103 @@
+/**
+ * Copyright (c) 2018, 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.
+ *
+ */
+
+// #include "sdk_config.h"
+#include "nordic_common.h"
+
+// #if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC)
+
+#include <string.h>
+
+#include "nrf_crypto_ecc_shared.h"
+#include "nrf_crypto_ecdh_shared.h"
+#include "nrf_crypto_ecdh.h"
+#include "nrf_crypto_shared.h"
+#include "micro_ecc_backend_ecc.h"
+#include "micro_ecc_backend_shared.h"
+#include "micro-ecc/uECC.h"
+
+
+ret_code_t nrf_crypto_backend_micro_ecc_ecdh_compute(
+    void       * p_context,
+    void const * p_private_key,
+    void const * p_public_key,
+    uint8_t    * p_shared_secret)
+{
+    int result;
+
+    nrf_crypto_backend_micro_ecc_common_key_t const * p_prv =
+        (nrf_crypto_backend_micro_ecc_common_key_t const *)p_private_key;
+    nrf_crypto_backend_micro_ecc_common_key_t const * p_pub =
+        (nrf_crypto_backend_micro_ecc_common_key_t const *)p_public_key;
+
+    nrf_crypto_ecc_curve_info_t const * p_info = p_prv->header.p_info;
+
+    uECC_Curve p_micro_ecc_curve = nrf_crypto_backend_micro_ecc_curve_get(p_prv);
+
+    // Check that the public key is valid 
+    if (!uECC_valid_public_key((uint8_t *)(&p_pub->key[0]), p_micro_ecc_curve))
+    {
+        return NRF_ERROR_CRYPTO_INTERNAL;
+    }
+    
+    result = uECC_shared_secret((uint8_t const *)(&p_pub->key[0]),
+                                (uint8_t const *)(&p_prv->key[0]),
+                                p_shared_secret,
+                                p_micro_ecc_curve);
+
+#if ECC_BACKEND_SWAP_BYTES
+    nrf_crypto_internal_swap_endian_in_place(p_shared_secret, p_info->raw_private_key_size);
+#else
+    UNUSED_PARAMETER(p_info);
+#endif
+
+    if (result == 0)
+    {
+        return NRF_ERROR_CRYPTO_INTERNAL;
+    }
+    
+    
+
+    
+    return NRF_SUCCESS;
+}
+
+
+// #endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC)
diff --git a/examples/heart_rate_collector/micro_ecc_backend_ecdh.h b/examples/heart_rate_collector/micro_ecc_backend_ecdh.h
new file mode 100644
index 0000000..e7bad3f
--- /dev/null
+++ b/examples/heart_rate_collector/micro_ecc_backend_ecdh.h
@@ -0,0 +1,88 @@
+/**
+ * Copyright (c) 2018, 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.
+ *
+ */
+
+#ifndef MICRO_ECC_BACKEND_ECDH_H__
+#define MICRO_ECC_BACKEND_ECDH_H__
+
+// #include "sdk_config.h"
+#include "nordic_common.h"
+
+// #if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC)
+
+#include "nrf_crypto_ecc.h"
+#include "nrf_crypto_ecdh_shared.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/** @internal See @ref nrf_crypto_backend_ecdh_compute_fn_t.
+ */
+ret_code_t nrf_crypto_backend_micro_ecc_ecdh_compute(
+    void       * p_context,
+    void const * p_private_key,
+    void const * p_public_key,
+    uint8_t    * p_shared_secret);
+
+// #if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP256R1)
+// Aliases for one common MICRO_ECC implementation
+#define nrf_crypto_backend_secp256r1_ecdh_compute nrf_crypto_backend_micro_ecc_ecdh_compute
+typedef uint32_t nrf_crypto_backend_secp256r1_ecdh_context_t;
+#define NRF_CRYPTO_BACKEND_SECP256R1_ECDH_CONTEXT_SIZE 0
+// #endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP256R1)
+
+
+// #if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP256K1)
+// // Aliases for one common MICRO_ECC implementation
+// #define nrf_crypto_backend_secp256k1_ecdh_compute nrf_crypto_backend_micro_ecc_ecdh_compute
+// typedef uint32_t nrf_crypto_backend_secp256k1_ecdh_context_t;
+// #define NRF_CRYPTO_BACKEND_SECP256K1_ECDH_CONTEXT_SIZE 0
+// #endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP256K1)
+
+
+#ifdef __cplusplus
+}
+#endif
+
+// #endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC)
+
+#endif // MICRO_ECC_BACKEND_ECDH_H__
diff --git a/examples/heart_rate_collector/micro_ecc_backend_shared.h b/examples/heart_rate_collector/micro_ecc_backend_shared.h
new file mode 100644
index 0000000..fc0a3f7
--- /dev/null
+++ b/examples/heart_rate_collector/micro_ecc_backend_shared.h
@@ -0,0 +1,69 @@
+/**
+ * Copyright (c) 2018, 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.
+ *
+ */
+#ifndef MICRO_ECC_BACKEND_SHARED_H__
+#define MICRO_ECC_BACKEND_SHARED_H__
+
+// #include "sdk_config.h"
+#include "nordic_common.h"
+
+// #if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC)
+
+#include "micro-ecc/uECC.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#if defined(NRF_CRYPTO_BACKEND_MICRO_ECC_LITTLE_ENDIAN_ENABLED)
+
+#error The configuration NRF_CRYPTO_BACKEND_MICRO_ECC_LITTLE_ENDIAN_ENABLED was removed in SDK 15.1.0. Please see release notes for details on removing this error message.
+    
+#endif
+
+#define ECC_BACKEND_SWAP_BYTES uECC_VLI_NATIVE_LITTLE_ENDIAN
+
+#ifdef __cplusplus
+}
+#endif
+
+// #endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC)
+
+#endif // MICRO_ECC_BACKEND_SHARED_H__
diff --git a/examples/heart_rate_collector/nrf_ble_lesc.c b/examples/heart_rate_collector/nrf_ble_lesc.c
new file mode 100644
index 0000000..159d39d
--- /dev/null
+++ b/examples/heart_rate_collector/nrf_ble_lesc.c
@@ -0,0 +1,403 @@
+/**
+ * Copyright (c) 2018, 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.
+ *
+ */
+
+// #include "sdk_common.h"
+#include "nordic_common.h"
+// #if NRF_MODULE_ENABLED(NRF_BLE_LESC)
+
+#include "nrf_ble_lesc.h"
+#include "nrf_crypto.h"
+#include "sdk_macros.h"
+
+// #define NRF_LOG_MODULE_NAME nrf_ble_lesc
+// #include "nrf_log.h"
+// NRF_LOG_MODULE_REGISTER();
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+#endif
+
+/**@brief Descriptor of the peer public key. */
+typedef struct
+{
+    nrf_crypto_ecc_public_key_t value;    /**< Peer public key. */
+    volatile bool               is_valid; /**< Flag indicating that the public key is valid. */
+} nrf_ble_lesc_peer_pub_key_t;
+
+/**@brief   The maximum number of peripheral and central connections combined.
+ *          This value is based on what is configured in the SoftDevice handler sdk_config.
+ */
+#define NRF_BLE_LESC_LINK_COUNT 16//(NRF_SDH_BLE_PERIPHERAL_LINK_COUNT + NRF_SDH_BLE_CENTRAL_LINK_COUNT)
+
+#ifdef __GNUC__
+#define __ALIGN(x) __attribute__((aligned(x)))
+#endif
+
+__ALIGN(4) static ble_gap_lesc_p256_pk_t m_lesc_public_key;                             /**< LESC ECC Public Key. */
+__ALIGN(4) static ble_gap_lesc_dhkey_t   m_lesc_dh_key;                                 /**< LESC ECC DH Key. */
+
+static nrf_crypto_ecdh_context_t                  m_ecdh_context;                       /**< Context to do the LESC ECDH calculation */
+
+static bool                                       m_ble_lesc_internal_error;            /**< Flag indicating that the module encountered an internal error. */
+static bool                                       m_keypair_generated;                  /**< Flag indicating that the local ECDH key pair was generated. */
+static nrf_crypto_ecc_key_pair_generate_context_t m_keygen_context;                     /**< Context to generate private/public key pair. */
+static nrf_crypto_ecc_private_key_t               m_private_key;                        /**< Allocated private key type to use for LESC DH generation. */
+static nrf_crypto_ecc_public_key_t                m_public_key;                         /**< Allocated public key type to use for LESC DH generation. */
+static nrf_ble_lesc_peer_pub_key_t                m_peer_keys[NRF_BLE_LESC_LINK_COUNT]; /**< Array of pointers to peer public keys, used for LESC DH generation. */
+
+
+ret_code_t nrf_ble_lesc_init(void)
+{
+    ret_code_t err_code;
+
+    memset((void *) m_peer_keys, 0, sizeof(m_peer_keys));
+
+#if NRF_CRYPTO_ALLOCATOR == NRF_CRYPTO_ALLOCATOR_NRF_MALLOC
+    // Initialize mem_manager if used by nrf_crypto.
+    err_code = nrf_mem_init();
+    if (err_code != NRF_SUCCESS)
+    {
+        // NRF_LOG_ERROR("nrf_mem_init() returned error 0x%x.", err_code);
+        printf("nrf_ble_lesc: nrf_mem_init() returned error 0x%x.\n", err_code);
+        fflush(stdout);
+        return err_code;
+    }
+#endif
+
+    // // Ensure that nrf_crypto has been initialized.
+    // err_code = nrf_crypto_init();
+    // if (err_code != NRF_SUCCESS)
+    // {
+    //     // NRF_LOG_ERROR("nrf_crypto_init() returned error 0x%x.", err_code);
+    //     printf("nrf_ble_lesc: nrf_crypto_init() returned error 0x%x.", err_code);
+    //     fflush(stdout);
+    //     return err_code;
+    // }
+    // // NRF_LOG_DEBUG("Initialized nrf_crypto.");
+    // printf("nrf_ble_lesc: Initialized nrf_crypto.");
+    // fflush(stdout);
+
+// #if defined(NRF_CRYPTO_RNG_AUTO_INIT_ENABLED) && (NRF_CRYPTO_RNG_AUTO_INIT_ENABLED == 1)
+//     // Do nothing. RNG is initialized with nrf_crypto_init call.
+// #elif defined((NRF_CRYPTO_RNG_AUTO_INIT_ENABLED) && (NRF_CRYPTO_RNG_AUTO_INIT_ENABLED == 0)
+//     // Initialize the RNG.
+//     err_code = nrf_crypto_rng_init(NULL, NULL);
+//     if (err_code != NRF_SUCCESS)
+//     {
+//         NRF_LOG_ERROR("nrf_crypto_rng_init() returned error 0x%x.", err_code);
+//         return err_code;
+//     }
+// #else
+//     #error Invalid sdk_config.h (does not contain NRF_CRYPTO_RNG_AUTO_INIT_ENABLED)
+// #endif // defined(NRF_CRYPTO_RNG_AUTO_INIT_ENABLED) && (NRF_CRYPTO_RNG_AUTO_INIT_ENABLED == 1)
+    // NRF_LOG_DEBUG("Initialized nrf_ble_lesc.");
+    printf("nrf_ble_lesc: Initialized nrf_ble_lesc.\n");
+    fflush(stdout);
+
+    // Reset module state.
+    m_ble_lesc_internal_error = false;
+    m_keypair_generated       = false;
+
+    // Generate ECC key pair. Only one key pair is automatically generated by this module.
+    err_code = nrf_ble_lesc_keypair_generate();
+    return err_code;
+}
+
+
+ret_code_t nrf_ble_lesc_keypair_generate(void)
+{
+    ret_code_t err_code;
+    size_t     public_len = NRF_CRYPTO_ECC_SECP256R1_RAW_PUBLIC_KEY_SIZE;
+
+    // Check if any DH computation is pending
+    for (uint32_t i = 0; i < ARRAY_SIZE(m_peer_keys); i++)
+    {
+        if (m_peer_keys[i].is_valid)
+        {
+            return NRF_ERROR_BUSY;
+        }
+    }
+
+    // Update flag to indicate that there is no valid private key.
+    m_keypair_generated = false;
+
+    // NRF_LOG_DEBUG("Generating ECC key pair");
+    printf("nrf_ble_lesc: Generating ECC key pair\n");
+    fflush(stdout);
+    err_code = nrf_crypto_ecc_key_pair_generate(&m_keygen_context,
+                                                &g_nrf_crypto_ecc_secp256r1_curve_info,
+                                                &m_private_key,
+                                                &m_public_key);
+    if (err_code != NRF_SUCCESS)
+    {
+        // NRF_LOG_ERROR("nrf_crypto_ecc_key_pair_generate() returned error 0x%x.", err_code);
+        printf("nrf_ble_lesc: nrf_crypto_ecc_key_pair_generate() returned error 0x%x.\n", err_code);
+        fflush(stdout);
+        return err_code;
+    }
+
+    // Convert to a raw type.
+    err_code = nrf_crypto_ecc_public_key_to_raw(&m_public_key,
+                                                m_lesc_public_key.pk,
+                                                &public_len);
+    if (err_code != NRF_SUCCESS)
+    {
+        // NRF_LOG_ERROR("nrf_crypto_ecc_public_key_to_raw() returned error 0x%x.", err_code);
+        printf("nrf_ble_lesc: nrf_crypto_ecc_public_key_to_raw() returned error 0x%x.\n", err_code);
+        fflush(stdout);
+        return err_code;
+    }
+
+    // Invert the raw type to little-endian (required for BLE).
+    err_code = nrf_crypto_ecc_byte_order_invert(&g_nrf_crypto_ecc_secp256r1_curve_info,
+                                                m_lesc_public_key.pk,
+                                                m_lesc_public_key.pk,
+                                                NRF_CRYPTO_ECC_SECP256R1_RAW_PUBLIC_KEY_SIZE);
+    if (err_code != NRF_SUCCESS)
+    {
+        // NRF_LOG_ERROR("nrf_crypto_ecc_byte_order_invert() returned error 0x%x.", err_code);
+        printf("nrf_ble_lesc: nrf_crypto_ecc_byte_order_invert() returned error 0x%x.\n", err_code);
+        fflush(stdout);
+    }
+    else
+    {
+        // Set the flag to indicate that there is a valid ECDH key pair generated.
+        m_keypair_generated = true;
+    }
+
+    return err_code;
+}
+
+
+ble_gap_lesc_p256_pk_t * nrf_ble_lesc_public_key_get(void)
+{
+    ble_gap_lesc_p256_pk_t * p_lesc_pk = NULL;
+
+    if (m_keypair_generated)
+    {
+        p_lesc_pk = &m_lesc_public_key;
+    }
+    else
+    {
+        // NRF_LOG_ERROR("Trying to access LESC public key that has not been generated yet.");
+        printf("nrf_ble_lesc: Trying to access LESC public key that has not been generated yet.\n");
+        fflush(stdout);
+    }
+
+    return p_lesc_pk;
+}
+
+
+/**@brief Function for calculating a DH key and responding to the DH key request on a given
+ *        connection handle.
+ *
+ * @param[in]  p_peer_public_key  ECC peer public key, used to compute shared secret.
+ * @param[in]  conn_handle        Connection handle.
+ *
+ * @retval NRF_SUCCESS If the operation was successful.
+ * @retval Other       Other error codes might be returned by the @ref nrf_crypto_ecdh_compute, @ref
+ *                     nrf_crypto_ecc_byte_order_invert, and @ref sd_ble_gap_lesc_dhkey_reply functions.
+ */
+static ret_code_t compute_and_give_dhkey(adapter_t                   * adapter,
+                                         nrf_ble_lesc_peer_pub_key_t * p_peer_public_key,
+                                         uint16_t                      conn_handle)
+{
+    ret_code_t err_code           = NRF_ERROR_INTERNAL;
+    size_t     shared_secret_size = BLE_GAP_LESC_DHKEY_LEN;
+    uint8_t  * p_shared_secret    = m_lesc_dh_key.key;
+
+    // Check if there is a valid generated and set a local ECDH public key.
+    if (!m_keypair_generated)
+    {
+        return NRF_ERROR_INTERNAL;
+    }
+
+    // Check if the public_key is valid
+    if (p_peer_public_key->is_valid)
+    {
+        err_code = nrf_crypto_ecdh_compute(&m_ecdh_context,
+                                           &m_private_key,
+                                           &p_peer_public_key->value,
+                                           p_shared_secret,
+                                           &shared_secret_size);
+    }
+
+    if (err_code == NRF_SUCCESS)
+    {
+        // Invert the shared secret for little endian format.
+        err_code = nrf_crypto_ecc_byte_order_invert(&g_nrf_crypto_ecc_secp256r1_curve_info,
+                                                    p_shared_secret,
+                                                    p_shared_secret,
+                                                    BLE_GAP_LESC_DHKEY_LEN);
+        VERIFY_SUCCESS(err_code);
+    }
+    else
+    {
+        // NRF_LOG_WARNING("Creating invalid shared secret to make LESC fail.");
+        printf("nrf_ble_lesc: Creating invalid shared secret to make LESC fail.\n");
+        fflush(stdout);
+        // err_code = nrf_crypto_rng_vector_generate(p_shared_secret, BLE_GAP_LESC_DHKEY_LEN);
+        // TODO: Implement own RNG.
+        VERIFY_SUCCESS(err_code);
+    }
+
+    // NRF_LOG_INFO("Calling sd_ble_gap_lesc_dhkey_reply on conn_handle: %d", conn_handle);
+    printf("nrf_ble_lesc: Calling sd_ble_gap_lesc_dhkey_reply on conn_handle: %d\n", conn_handle);
+    fflush(stdout);
+    err_code = sd_ble_gap_lesc_dhkey_reply(adapter, conn_handle, &m_lesc_dh_key);
+
+    return err_code;
+}
+
+
+ret_code_t nrf_ble_lesc_request_handler(adapter_t * adapter)
+{
+    ret_code_t err_code = NRF_SUCCESS;
+
+    // If the LESC module is in an invalid state, a restart is required.
+    if (m_ble_lesc_internal_error)
+    {
+        return NRF_ERROR_INTERNAL;
+    }
+
+    for (uint16_t i = 0; i < NRF_BLE_LESC_LINK_COUNT; i++)
+    {
+        if (m_peer_keys[i].is_valid)
+        {
+            err_code                = compute_and_give_dhkey(adapter, &m_peer_keys[i], i);
+            m_peer_keys[i].is_valid = false;
+            VERIFY_SUCCESS(err_code);
+        }
+    }
+
+    return err_code;
+}
+
+
+/**@brief Function for handling a DH key request event.
+ *
+ * @param[in]  conn_handle      Connection handle.
+ * @param[in]  p_dhkey_request  DH key request descriptor.
+ *
+ * @retval NRF_SUCCESS      If the operation was successful.
+ * @retval Other            Other error codes might be returned by the @ref nrf_crypto_ecc_byte_order_invert
+ *                          and @ref nrf_crypto_ecc_public_key_from_raw functions.
+ */
+static ret_code_t on_dhkey_request(uint16_t                                 conn_handle,
+                                   ble_gap_evt_lesc_dhkey_request_t const * p_dhkey_request)
+{
+    ret_code_t err_code = NRF_SUCCESS;
+    uint8_t    public_raw[BLE_GAP_LESC_P256_PK_LEN];
+    uint8_t  * p_public_raw;
+    size_t     public_raw_len;
+
+    // Convert the received public key from big-endian to little endian.
+    p_public_raw   = p_dhkey_request->p_pk_peer->pk;
+    public_raw_len = BLE_GAP_LESC_P256_PK_LEN;
+    err_code       = nrf_crypto_ecc_byte_order_invert(&g_nrf_crypto_ecc_secp256r1_curve_info,
+                                                      p_public_raw,
+                                                      public_raw,
+                                                      public_raw_len);
+    if (err_code != NRF_SUCCESS)
+    {
+        // NRF_LOG_ERROR("nrf_crypto_ecc_byte_order_invert() returned error 0x%x.", err_code);
+        printf("nrf_ble_lesc: nrf_crypto_ecc_byte_order_invert() returned error 0x%x.\n", err_code);
+        fflush(stdout);
+        return err_code;
+    }
+
+    // Copy peer public key to the allocated context. The dhkey calculation will be performed in
+    // @ref nrf_ble_lesc_request_handler, so it does not block normal operation.
+    err_code = nrf_crypto_ecc_public_key_from_raw(&g_nrf_crypto_ecc_secp256r1_curve_info,
+                                                  &m_peer_keys[conn_handle].value,
+                                                  public_raw,
+                                                  public_raw_len);
+    if (err_code != NRF_SUCCESS)
+    {
+        // NRF_LOG_ERROR("nrf_crypto_ecc_public_key_from_raw() returned error 0x%x.", err_code);
+        printf("nrf_ble_lesc: nrf_crypto_ecc_public_key_from_raw() returned error 0x%x.\n", err_code);
+        fflush(stdout);
+        m_peer_keys[conn_handle].is_valid = false;
+    }
+    else
+    {
+        m_peer_keys[conn_handle].is_valid = true;
+    }
+
+    return NRF_SUCCESS;
+}
+
+
+void nrf_ble_lesc_on_ble_evt(ble_evt_t const * p_ble_evt)
+{
+    ret_code_t err_code    = NRF_SUCCESS;
+    uint16_t   conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
+
+    switch (p_ble_evt->header.evt_id)
+    {
+        case BLE_GAP_EVT_DISCONNECTED:
+        {
+            // NRF_LOG_DEBUG("BLE_GAP_EVT_DISCONNECTED");
+            printf("nrf_ble_lesc: BLE_GAP_EVT_DISCONNECTED\n");
+            fflush(stdout);
+            m_peer_keys[conn_handle].is_valid = false;
+        } break;
+
+        case BLE_GAP_EVT_LESC_DHKEY_REQUEST:
+        {
+            // NRF_LOG_DEBUG("BLE_GAP_EVT_LESC_DHKEY_REQUEST");
+            printf("nrf_ble_lesc: BLE_GAP_EVT_LESC_DHKEY_REQUEST\n");
+            fflush(stdout);
+
+            err_code = on_dhkey_request(conn_handle,
+                                        &p_ble_evt->evt.gap_evt.params.lesc_dhkey_request);
+            if (err_code != NRF_SUCCESS)
+            {
+                m_ble_lesc_internal_error = true;
+            }
+        } break;
+
+        default:
+            break;
+    }
+}
+
+
+// #endif // NRF_BLE_LESC_ENABLED
diff --git a/examples/heart_rate_collector/nrf_ble_lesc.h b/examples/heart_rate_collector/nrf_ble_lesc.h
new file mode 100644
index 0000000..90bd119
--- /dev/null
+++ b/examples/heart_rate_collector/nrf_ble_lesc.h
@@ -0,0 +1,130 @@
+/**
+ * Copyright (c) 2018, 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.
+ *
+ */
+/** @file
+ *
+ * @defgroup nrf_ble_lesc LESC module
+ * @{
+ * @ingroup peer_manager
+ * @brief Module for handling LESC related events.
+ */
+
+#ifndef NRF_BLE_LESC_H__
+#define NRF_BLE_LESC_H__
+
+#include <stdint.h>
+#include <string.h>
+#include "ble.h"
+#include "sdk_errors.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**@brief   Function for initializing the LESC module.
+ *
+ * @details This function initializes the nrf_crypto for ECC and ECDH calculations, which are
+ *          required to handle LESC authentication procedures.
+ *
+ * @retval NRF_SUCCESS   If the operation was successful.
+ * @retval Other         Other error codes might be returned by the @ref nrf_crypto_init or
+ *                       @ref nrf_ble_lesc_keypair_generate functions.
+ */
+ret_code_t nrf_ble_lesc_init(void);
+
+
+/**@brief   Function for generating ECC keypair used for the LESC procedure.
+ *
+ * @details This function generates an ECC key pair, which consists of a private and public key. Keys are
+ *          generated using ECC and are used to create LESC DH key during authentication procedures.
+ *
+ * @retval NRF_SUCCESS    If the operation was successful.
+ * @retval NRF_ERROR_BUSY If any pending request needs to be processed by @ref nrf_ble_lesc_request_handler.
+ * @retval Other          Other error codes might be returned by the @ref nrf_crypto_ecc_key_pair_generate,
+ *                        @ref nrf_crypto_ecc_public_key_to_raw and @ref nrf_crypto_ecc_byte_order_invert
+ *                        functions.
+ */
+ret_code_t nrf_ble_lesc_keypair_generate(void);
+
+
+/**@brief   Function for accessing the ECC public key used for LESC DH key generation.
+ *
+ * @details This function can be used to access the ECC public key, which is required to generate a LESC DH key
+ *          at the peer side.
+ *
+ * @return Pointer to the generated public key or NULL if the key has not been generated yet.
+ */
+ble_gap_lesc_p256_pk_t * nrf_ble_lesc_public_key_get(void);
+
+
+/**@brief   Function for responding to a DH key requests.
+ *
+ * @details This function calculates DH keys and supplies them to the SoftDevice if there are any
+ *          pending requests for keys.
+ *
+ * @note This function should be called systematically (e.g. in the main application loop) to handle
+ *       any pending DH key requests.
+ *
+ * @retval NRF_SUCCESS        If the operation was successful.
+ * @retval NRF_ERROR_INTERNAL If the LESC module encountered an internal error. The only way to recover from
+ *                            this type of error is to reset the application.
+ * @retval Other              Other error codes might be returned by the @ref nrf_crypto_ecdh_compute,
+ *                            @ref nrf_crypto_ecc_byte_order_invert, and @ref sd_ble_gap_lesc_dhkey_reply
+ *                            functions.
+ */
+ret_code_t nrf_ble_lesc_request_handler(adapter_t * adapter);
+
+
+/**@brief   Function for handling BLE stack events.
+ *
+ * @details This function handles events from the BLE stack that are of interest to the module.
+ *
+ * @param[in]   p_ble_evt   Event received from the BLE stack.
+ */
+void nrf_ble_lesc_on_ble_evt(ble_evt_t const * p_ble_evt);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NRF_BLE_LESC_H__
+
+/** @} */
diff --git a/examples/heart_rate_collector/nrf_crypto.h b/examples/heart_rate_collector/nrf_crypto.h
new file mode 100644
index 0000000..5321e0b
--- /dev/null
+++ b/examples/heart_rate_collector/nrf_crypto.h
@@ -0,0 +1,78 @@
+/**
+ * Copyright (c) 2016 - 2018, 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.
+ *
+ */
+
+#ifndef NRF_CRYPTO_H__
+#define NRF_CRYPTO_H__
+
+/**
+ * @defgroup nrf_crypto Cryptography library
+ * @ingroup app_common
+ * @{
+ *
+ * @brief   Cryptography library (nrf_crypto).
+ *
+ * @details The cryptography library provides cryptographic functionality in a portable way.
+ *
+ * @note The functions in this API can run in software or hardware, depending on the supported features of your SoC and the configuration of nrf_crypto backend in the application.
+ * See @ref lib_crypto_config for details on changing the nrf_crypto backend.
+ *
+ * @}
+ *
+ */
+ 
+
+
+#include <stdint.h>
+// #include "nrf_crypto_init.h"
+#include "nrf_crypto_types.h"
+#include "nrf_crypto_mem.h"
+#include "nrf_crypto_ecc.h"
+// #include "nrf_crypto_hash.h"
+// #include "nrf_crypto_ecdsa.h"
+#include "nrf_crypto_ecdh.h"
+// #include "nrf_crypto_rng.h"
+// #include "nrf_crypto_aes.h"
+// #include "nrf_crypto_aead.h"
+// #include "nrf_crypto_hmac.h"
+// #include "nrf_crypto_hkdf.h"
+// #include "nrf_crypto_eddsa.h"
+
+
+#endif // NRF_CRYPTO_H__
diff --git a/examples/heart_rate_collector/nrf_crypto_ecc.c b/examples/heart_rate_collector/nrf_crypto_ecc.c
new file mode 100644
index 0000000..f9889c9
--- /dev/null
+++ b/examples/heart_rate_collector/nrf_crypto_ecc.c
@@ -0,0 +1,1315 @@
+/**
+ * Copyright (c) 2018, 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.
+ *
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "nordic_common.h"
+#include "nrf_crypto_error.h"
+#include "nrf_crypto_mem.h"
+#include "nrf_crypto_ecc.h"
+// #include "app_util.h"
+// #include "sdk_assert.h"
+#include "sdk_macros.h"
+
+
+#if NRF_CRYPTO_ECC_ENABLED
+
+
+#if NRF_CRYPTO_ECC_IMPLEMENTED_CURVES_COUNT > 1
+
+
+static const nrf_crypto_backend_ecc_key_pair_generate_fn_t key_pair_generate_impl[] =
+{
+#if NRF_CRYPTO_ECC_SECP160R1_ENABLED
+    nrf_crypto_backend_secp160r1_key_pair_generate,
+#endif
+#if NRF_CRYPTO_ECC_SECP160R2_ENABLED
+    nrf_crypto_backend_secp160r2_key_pair_generate,
+#endif
+#if NRF_CRYPTO_ECC_SECP192R1_ENABLED
+    nrf_crypto_backend_secp192r1_key_pair_generate,
+#endif
+#if NRF_CRYPTO_ECC_SECP224R1_ENABLED
+    nrf_crypto_backend_secp224r1_key_pair_generate,
+#endif
+#if NRF_CRYPTO_ECC_SECP256R1_ENABLED
+    nrf_crypto_backend_secp256r1_key_pair_generate,
+#endif
+#if NRF_CRYPTO_ECC_SECP384R1_ENABLED
+    nrf_crypto_backend_secp384r1_key_pair_generate,
+#endif
+#if NRF_CRYPTO_ECC_SECP521R1_ENABLED
+    nrf_crypto_backend_secp521r1_key_pair_generate,
+#endif
+#if NRF_CRYPTO_ECC_SECP160K1_ENABLED
+    nrf_crypto_backend_secp160k1_key_pair_generate,
+#endif
+#if NRF_CRYPTO_ECC_SECP192K1_ENABLED
+    nrf_crypto_backend_secp192k1_key_pair_generate,
+#endif
+#if NRF_CRYPTO_ECC_SECP224K1_ENABLED
+    nrf_crypto_backend_secp224k1_key_pair_generate,
+#endif
+#if NRF_CRYPTO_ECC_SECP256K1_ENABLED
+    nrf_crypto_backend_secp256k1_key_pair_generate,
+#endif
+#if NRF_CRYPTO_ECC_BP256R1_ENABLED
+    nrf_crypto_backend_bp256r1_key_pair_generate,
+#endif
+#if NRF_CRYPTO_ECC_BP384R1_ENABLED
+    nrf_crypto_backend_bp384r1_key_pair_generate,
+#endif
+#if NRF_CRYPTO_ECC_BP512R1_ENABLED
+    nrf_crypto_backend_bp512r1_key_pair_generate,
+#endif
+#if NRF_CRYPTO_ECC_CURVE25519_ENABLED
+    nrf_crypto_backend_curve25519_key_pair_generate,
+#endif
+#if NRF_CRYPTO_ECC_ED25519_ENABLED
+    nrf_crypto_backend_ed25519_key_pair_generate,
+#endif
+};
+
+
+static const uint16_t key_pair_generate_context_size[] =
+{
+#if NRF_CRYPTO_ECC_SECP160R1_ENABLED
+    NRF_CRYPTO_BACKEND_SECP160R1_KEY_PAIR_GENERATE_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_SECP160R2_ENABLED
+    NRF_CRYPTO_BACKEND_SECP160R2_KEY_PAIR_GENERATE_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_SECP192R1_ENABLED
+    NRF_CRYPTO_BACKEND_SECP192R1_KEY_PAIR_GENERATE_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_SECP224R1_ENABLED
+    NRF_CRYPTO_BACKEND_SECP224R1_KEY_PAIR_GENERATE_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_SECP256R1_ENABLED
+    NRF_CRYPTO_BACKEND_SECP256R1_KEY_PAIR_GENERATE_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_SECP384R1_ENABLED
+    NRF_CRYPTO_BACKEND_SECP384R1_KEY_PAIR_GENERATE_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_SECP521R1_ENABLED
+    NRF_CRYPTO_BACKEND_SECP521R1_KEY_PAIR_GENERATE_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_SECP160K1_ENABLED
+    NRF_CRYPTO_BACKEND_SECP160K1_KEY_PAIR_GENERATE_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_SECP192K1_ENABLED
+    NRF_CRYPTO_BACKEND_SECP192K1_KEY_PAIR_GENERATE_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_SECP224K1_ENABLED
+    NRF_CRYPTO_BACKEND_SECP224K1_KEY_PAIR_GENERATE_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_SECP256K1_ENABLED
+    NRF_CRYPTO_BACKEND_SECP256K1_KEY_PAIR_GENERATE_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_BP256R1_ENABLED
+    NRF_CRYPTO_BACKEND_BP256R1_KEY_PAIR_GENERATE_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_BP384R1_ENABLED
+    NRF_CRYPTO_BACKEND_BP384R1_KEY_PAIR_GENERATE_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_BP512R1_ENABLED
+    NRF_CRYPTO_BACKEND_BP512R1_KEY_PAIR_GENERATE_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_CURVE25519_ENABLED
+    NRF_CRYPTO_BACKEND_CURVE25519_KEY_PAIR_GENERATE_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_ED25519_ENABLED
+    NRF_CRYPTO_BACKEND_ED25519_KEY_PAIR_GENERATE_CONTEXT_SIZE,
+#endif
+};
+
+
+static const nrf_crypto_backend_ecc_public_key_calculate_fn_t public_key_calculate_impl[] =
+{
+#if NRF_CRYPTO_ECC_SECP160R1_ENABLED
+    nrf_crypto_backend_secp160r1_public_key_calculate,
+#endif
+#if NRF_CRYPTO_ECC_SECP160R2_ENABLED
+    nrf_crypto_backend_secp160r2_public_key_calculate,
+#endif
+#if NRF_CRYPTO_ECC_SECP192R1_ENABLED
+    nrf_crypto_backend_secp192r1_public_key_calculate,
+#endif
+#if NRF_CRYPTO_ECC_SECP224R1_ENABLED
+    nrf_crypto_backend_secp224r1_public_key_calculate,
+#endif
+#if NRF_CRYPTO_ECC_SECP256R1_ENABLED
+    nrf_crypto_backend_secp256r1_public_key_calculate,
+#endif
+#if NRF_CRYPTO_ECC_SECP384R1_ENABLED
+    nrf_crypto_backend_secp384r1_public_key_calculate,
+#endif
+#if NRF_CRYPTO_ECC_SECP521R1_ENABLED
+    nrf_crypto_backend_secp521r1_public_key_calculate,
+#endif
+#if NRF_CRYPTO_ECC_SECP160K1_ENABLED
+    nrf_crypto_backend_secp160k1_public_key_calculate,
+#endif
+#if NRF_CRYPTO_ECC_SECP192K1_ENABLED
+    nrf_crypto_backend_secp192k1_public_key_calculate,
+#endif
+#if NRF_CRYPTO_ECC_SECP224K1_ENABLED
+    nrf_crypto_backend_secp224k1_public_key_calculate,
+#endif
+#if NRF_CRYPTO_ECC_SECP256K1_ENABLED
+    nrf_crypto_backend_secp256k1_public_key_calculate,
+#endif
+#if NRF_CRYPTO_ECC_BP256R1_ENABLED
+    nrf_crypto_backend_bp256r1_public_key_calculate,
+#endif
+#if NRF_CRYPTO_ECC_BP384R1_ENABLED
+    nrf_crypto_backend_bp384r1_public_key_calculate,
+#endif
+#if NRF_CRYPTO_ECC_BP512R1_ENABLED
+    nrf_crypto_backend_bp512r1_public_key_calculate,
+#endif
+#if NRF_CRYPTO_ECC_CURVE25519_ENABLED
+    nrf_crypto_backend_curve25519_public_key_calculate,
+#endif
+#if NRF_CRYPTO_ECC_ED25519_ENABLED
+    nrf_crypto_backend_ed25519_public_key_calculate,
+#endif
+};
+
+
+static const uint16_t public_key_calculate_context_size[] =
+{
+#if NRF_CRYPTO_ECC_SECP160R1_ENABLED
+    NRF_CRYPTO_BACKEND_SECP160R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_SECP160R2_ENABLED
+    NRF_CRYPTO_BACKEND_SECP160R2_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_SECP192R1_ENABLED
+    NRF_CRYPTO_BACKEND_SECP192R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_SECP224R1_ENABLED
+    NRF_CRYPTO_BACKEND_SECP224R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_SECP256R1_ENABLED
+    NRF_CRYPTO_BACKEND_SECP256R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_SECP384R1_ENABLED
+    NRF_CRYPTO_BACKEND_SECP384R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_SECP521R1_ENABLED
+    NRF_CRYPTO_BACKEND_SECP521R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_SECP160K1_ENABLED
+    NRF_CRYPTO_BACKEND_SECP160K1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_SECP192K1_ENABLED
+    NRF_CRYPTO_BACKEND_SECP192K1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_SECP224K1_ENABLED
+    NRF_CRYPTO_BACKEND_SECP224K1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_SECP256K1_ENABLED
+    NRF_CRYPTO_BACKEND_SECP256K1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_BP256R1_ENABLED
+    NRF_CRYPTO_BACKEND_BP256R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_BP384R1_ENABLED
+    NRF_CRYPTO_BACKEND_BP384R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_BP512R1_ENABLED
+    NRF_CRYPTO_BACKEND_BP512R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_CURVE25519_ENABLED
+    NRF_CRYPTO_BACKEND_CURVE25519_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_ED25519_ENABLED
+    NRF_CRYPTO_BACKEND_ED25519_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE,
+#endif
+};
+
+
+static const nrf_crypto_backend_ecc_private_key_from_raw_fn_t private_key_from_raw_impl[] =
+{
+#if NRF_CRYPTO_ECC_SECP160R1_ENABLED
+    nrf_crypto_backend_secp160r1_private_key_from_raw,
+#endif
+#if NRF_CRYPTO_ECC_SECP160R2_ENABLED
+    nrf_crypto_backend_secp160r2_private_key_from_raw,
+#endif
+#if NRF_CRYPTO_ECC_SECP192R1_ENABLED
+    nrf_crypto_backend_secp192r1_private_key_from_raw,
+#endif
+#if NRF_CRYPTO_ECC_SECP224R1_ENABLED
+    nrf_crypto_backend_secp224r1_private_key_from_raw,
+#endif
+#if NRF_CRYPTO_ECC_SECP256R1_ENABLED
+    nrf_crypto_backend_secp256r1_private_key_from_raw,
+#endif
+#if NRF_CRYPTO_ECC_SECP384R1_ENABLED
+    nrf_crypto_backend_secp384r1_private_key_from_raw,
+#endif
+#if NRF_CRYPTO_ECC_SECP521R1_ENABLED
+    nrf_crypto_backend_secp521r1_private_key_from_raw,
+#endif
+#if NRF_CRYPTO_ECC_SECP160K1_ENABLED
+    nrf_crypto_backend_secp160k1_private_key_from_raw,
+#endif
+#if NRF_CRYPTO_ECC_SECP192K1_ENABLED
+    nrf_crypto_backend_secp192k1_private_key_from_raw,
+#endif
+#if NRF_CRYPTO_ECC_SECP224K1_ENABLED
+    nrf_crypto_backend_secp224k1_private_key_from_raw,
+#endif
+#if NRF_CRYPTO_ECC_SECP256K1_ENABLED
+    nrf_crypto_backend_secp256k1_private_key_from_raw,
+#endif
+#if NRF_CRYPTO_ECC_BP256R1_ENABLED
+    nrf_crypto_backend_bp256r1_private_key_from_raw,
+#endif
+#if NRF_CRYPTO_ECC_BP384R1_ENABLED
+    nrf_crypto_backend_bp384r1_private_key_from_raw,
+#endif
+#if NRF_CRYPTO_ECC_BP512R1_ENABLED
+    nrf_crypto_backend_bp512r1_private_key_from_raw,
+#endif
+#if NRF_CRYPTO_ECC_CURVE25519_ENABLED
+    nrf_crypto_backend_curve25519_private_key_from_raw,
+#endif
+#if NRF_CRYPTO_ECC_ED25519_ENABLED
+    nrf_crypto_backend_ed25519_private_key_from_raw,
+#endif
+};
+
+
+static const nrf_crypto_backend_ecc_private_key_to_raw_fn_t private_key_to_raw_impl[] =
+{
+#if NRF_CRYPTO_ECC_SECP160R1_ENABLED
+    nrf_crypto_backend_secp160r1_private_key_to_raw,
+#endif
+#if NRF_CRYPTO_ECC_SECP160R2_ENABLED
+    nrf_crypto_backend_secp160r2_private_key_to_raw,
+#endif
+#if NRF_CRYPTO_ECC_SECP192R1_ENABLED
+    nrf_crypto_backend_secp192r1_private_key_to_raw,
+#endif
+#if NRF_CRYPTO_ECC_SECP224R1_ENABLED
+    nrf_crypto_backend_secp224r1_private_key_to_raw,
+#endif
+#if NRF_CRYPTO_ECC_SECP256R1_ENABLED
+    nrf_crypto_backend_secp256r1_private_key_to_raw,
+#endif
+#if NRF_CRYPTO_ECC_SECP384R1_ENABLED
+    nrf_crypto_backend_secp384r1_private_key_to_raw,
+#endif
+#if NRF_CRYPTO_ECC_SECP521R1_ENABLED
+    nrf_crypto_backend_secp521r1_private_key_to_raw,
+#endif
+#if NRF_CRYPTO_ECC_SECP160K1_ENABLED
+    nrf_crypto_backend_secp160k1_private_key_to_raw,
+#endif
+#if NRF_CRYPTO_ECC_SECP192K1_ENABLED
+    nrf_crypto_backend_secp192k1_private_key_to_raw,
+#endif
+#if NRF_CRYPTO_ECC_SECP224K1_ENABLED
+    nrf_crypto_backend_secp224k1_private_key_to_raw,
+#endif
+#if NRF_CRYPTO_ECC_SECP256K1_ENABLED
+    nrf_crypto_backend_secp256k1_private_key_to_raw,
+#endif
+#if NRF_CRYPTO_ECC_BP256R1_ENABLED
+    nrf_crypto_backend_bp256r1_private_key_to_raw,
+#endif
+#if NRF_CRYPTO_ECC_BP384R1_ENABLED
+    nrf_crypto_backend_bp384r1_private_key_to_raw,
+#endif
+#if NRF_CRYPTO_ECC_BP512R1_ENABLED
+    nrf_crypto_backend_bp512r1_private_key_to_raw,
+#endif
+#if NRF_CRYPTO_ECC_CURVE25519_ENABLED
+    nrf_crypto_backend_curve25519_private_key_to_raw,
+#endif
+#if NRF_CRYPTO_ECC_ED25519_ENABLED
+    nrf_crypto_backend_ed25519_private_key_to_raw,
+#endif
+};
+
+
+static const nrf_crypto_backend_ecc_public_key_from_raw_fn_t public_key_from_raw_impl[] =
+{
+#if NRF_CRYPTO_ECC_SECP160R1_ENABLED
+    nrf_crypto_backend_secp160r1_public_key_from_raw,
+#endif
+#if NRF_CRYPTO_ECC_SECP160R2_ENABLED
+    nrf_crypto_backend_secp160r2_public_key_from_raw,
+#endif
+#if NRF_CRYPTO_ECC_SECP192R1_ENABLED
+    nrf_crypto_backend_secp192r1_public_key_from_raw,
+#endif
+#if NRF_CRYPTO_ECC_SECP224R1_ENABLED
+    nrf_crypto_backend_secp224r1_public_key_from_raw,
+#endif
+#if NRF_CRYPTO_ECC_SECP256R1_ENABLED
+    nrf_crypto_backend_secp256r1_public_key_from_raw,
+#endif
+#if NRF_CRYPTO_ECC_SECP384R1_ENABLED
+    nrf_crypto_backend_secp384r1_public_key_from_raw,
+#endif
+#if NRF_CRYPTO_ECC_SECP521R1_ENABLED
+    nrf_crypto_backend_secp521r1_public_key_from_raw,
+#endif
+#if NRF_CRYPTO_ECC_SECP160K1_ENABLED
+    nrf_crypto_backend_secp160k1_public_key_from_raw,
+#endif
+#if NRF_CRYPTO_ECC_SECP192K1_ENABLED
+    nrf_crypto_backend_secp192k1_public_key_from_raw,
+#endif
+#if NRF_CRYPTO_ECC_SECP224K1_ENABLED
+    nrf_crypto_backend_secp224k1_public_key_from_raw,
+#endif
+#if NRF_CRYPTO_ECC_SECP256K1_ENABLED
+    nrf_crypto_backend_secp256k1_public_key_from_raw,
+#endif
+#if NRF_CRYPTO_ECC_BP256R1_ENABLED
+    nrf_crypto_backend_bp256r1_public_key_from_raw,
+#endif
+#if NRF_CRYPTO_ECC_BP384R1_ENABLED
+    nrf_crypto_backend_bp384r1_public_key_from_raw,
+#endif
+#if NRF_CRYPTO_ECC_BP512R1_ENABLED
+    nrf_crypto_backend_bp512r1_public_key_from_raw,
+#endif
+#if NRF_CRYPTO_ECC_CURVE25519_ENABLED
+    nrf_crypto_backend_curve25519_public_key_from_raw,
+#endif
+#if NRF_CRYPTO_ECC_ED25519_ENABLED
+    nrf_crypto_backend_ed25519_public_key_from_raw,
+#endif
+};
+
+
+static const nrf_crypto_backend_ecc_public_key_to_raw_fn_t public_key_to_raw_impl[] =
+{
+#if NRF_CRYPTO_ECC_SECP160R1_ENABLED
+    nrf_crypto_backend_secp160r1_public_key_to_raw,
+#endif
+#if NRF_CRYPTO_ECC_SECP160R2_ENABLED
+    nrf_crypto_backend_secp160r2_public_key_to_raw,
+#endif
+#if NRF_CRYPTO_ECC_SECP192R1_ENABLED
+    nrf_crypto_backend_secp192r1_public_key_to_raw,
+#endif
+#if NRF_CRYPTO_ECC_SECP224R1_ENABLED
+    nrf_crypto_backend_secp224r1_public_key_to_raw,
+#endif
+#if NRF_CRYPTO_ECC_SECP256R1_ENABLED
+    nrf_crypto_backend_secp256r1_public_key_to_raw,
+#endif
+#if NRF_CRYPTO_ECC_SECP384R1_ENABLED
+    nrf_crypto_backend_secp384r1_public_key_to_raw,
+#endif
+#if NRF_CRYPTO_ECC_SECP521R1_ENABLED
+    nrf_crypto_backend_secp521r1_public_key_to_raw,
+#endif
+#if NRF_CRYPTO_ECC_SECP160K1_ENABLED
+    nrf_crypto_backend_secp160k1_public_key_to_raw,
+#endif
+#if NRF_CRYPTO_ECC_SECP192K1_ENABLED
+    nrf_crypto_backend_secp192k1_public_key_to_raw,
+#endif
+#if NRF_CRYPTO_ECC_SECP224K1_ENABLED
+    nrf_crypto_backend_secp224k1_public_key_to_raw,
+#endif
+#if NRF_CRYPTO_ECC_SECP256K1_ENABLED
+    nrf_crypto_backend_secp256k1_public_key_to_raw,
+#endif
+#if NRF_CRYPTO_ECC_BP256R1_ENABLED
+    nrf_crypto_backend_bp256r1_public_key_to_raw,
+#endif
+#if NRF_CRYPTO_ECC_BP384R1_ENABLED
+    nrf_crypto_backend_bp384r1_public_key_to_raw,
+#endif
+#if NRF_CRYPTO_ECC_BP512R1_ENABLED
+    nrf_crypto_backend_bp512r1_public_key_to_raw,
+#endif
+#if NRF_CRYPTO_ECC_CURVE25519_ENABLED
+    nrf_crypto_backend_curve25519_public_key_to_raw,
+#endif
+#if NRF_CRYPTO_ECC_ED25519_ENABLED
+    nrf_crypto_backend_ed25519_public_key_to_raw,
+#endif
+};
+
+
+static const nrf_crypto_backend_ecc_key_free_fn_t private_key_free_impl[] =
+{
+#if NRF_CRYPTO_ECC_SECP160R1_ENABLED
+    nrf_crypto_backend_secp160r1_private_key_free,
+#endif
+#if NRF_CRYPTO_ECC_SECP160R2_ENABLED
+    nrf_crypto_backend_secp160r2_private_key_free,
+#endif
+#if NRF_CRYPTO_ECC_SECP192R1_ENABLED
+    nrf_crypto_backend_secp192r1_private_key_free,
+#endif
+#if NRF_CRYPTO_ECC_SECP224R1_ENABLED
+    nrf_crypto_backend_secp224r1_private_key_free,
+#endif
+#if NRF_CRYPTO_ECC_SECP256R1_ENABLED
+    nrf_crypto_backend_secp256r1_private_key_free,
+#endif
+#if NRF_CRYPTO_ECC_SECP384R1_ENABLED
+    nrf_crypto_backend_secp384r1_private_key_free,
+#endif
+#if NRF_CRYPTO_ECC_SECP521R1_ENABLED
+    nrf_crypto_backend_secp521r1_private_key_free,
+#endif
+#if NRF_CRYPTO_ECC_SECP160K1_ENABLED
+    nrf_crypto_backend_secp160k1_private_key_free,
+#endif
+#if NRF_CRYPTO_ECC_SECP192K1_ENABLED
+    nrf_crypto_backend_secp192k1_private_key_free,
+#endif
+#if NRF_CRYPTO_ECC_SECP224K1_ENABLED
+    nrf_crypto_backend_secp224k1_private_key_free,
+#endif
+#if NRF_CRYPTO_ECC_SECP256K1_ENABLED
+    nrf_crypto_backend_secp256k1_private_key_free,
+#endif
+#if NRF_CRYPTO_ECC_BP256R1_ENABLED
+    nrf_crypto_backend_bp256r1_private_key_free,
+#endif
+#if NRF_CRYPTO_ECC_BP384R1_ENABLED
+    nrf_crypto_backend_bp384r1_private_key_free,
+#endif
+#if NRF_CRYPTO_ECC_BP512R1_ENABLED
+    nrf_crypto_backend_bp512r1_private_key_free,
+#endif
+#if NRF_CRYPTO_ECC_CURVE25519_ENABLED
+    nrf_crypto_backend_curve25519_private_key_free,
+#endif
+#if NRF_CRYPTO_ECC_ED25519_ENABLED
+    nrf_crypto_backend_ed25519_private_key_free,
+#endif
+};
+
+
+static const nrf_crypto_backend_ecc_key_free_fn_t public_key_free_impl[] =
+{
+#if NRF_CRYPTO_ECC_SECP160R1_ENABLED
+    nrf_crypto_backend_secp160r1_public_key_free,
+#endif
+#if NRF_CRYPTO_ECC_SECP160R2_ENABLED
+    nrf_crypto_backend_secp160r2_public_key_free,
+#endif
+#if NRF_CRYPTO_ECC_SECP192R1_ENABLED
+    nrf_crypto_backend_secp192r1_public_key_free,
+#endif
+#if NRF_CRYPTO_ECC_SECP224R1_ENABLED
+    nrf_crypto_backend_secp224r1_public_key_free,
+#endif
+#if NRF_CRYPTO_ECC_SECP256R1_ENABLED
+    nrf_crypto_backend_secp256r1_public_key_free,
+#endif
+#if NRF_CRYPTO_ECC_SECP384R1_ENABLED
+    nrf_crypto_backend_secp384r1_public_key_free,
+#endif
+#if NRF_CRYPTO_ECC_SECP521R1_ENABLED
+    nrf_crypto_backend_secp521r1_public_key_free,
+#endif
+#if NRF_CRYPTO_ECC_SECP160K1_ENABLED
+    nrf_crypto_backend_secp160k1_public_key_free,
+#endif
+#if NRF_CRYPTO_ECC_SECP192K1_ENABLED
+    nrf_crypto_backend_secp192k1_public_key_free,
+#endif
+#if NRF_CRYPTO_ECC_SECP224K1_ENABLED
+    nrf_crypto_backend_secp224k1_public_key_free,
+#endif
+#if NRF_CRYPTO_ECC_SECP256K1_ENABLED
+    nrf_crypto_backend_secp256k1_public_key_free,
+#endif
+#if NRF_CRYPTO_ECC_BP256R1_ENABLED
+    nrf_crypto_backend_bp256r1_public_key_free,
+#endif
+#if NRF_CRYPTO_ECC_BP384R1_ENABLED
+    nrf_crypto_backend_bp384r1_public_key_free,
+#endif
+#if NRF_CRYPTO_ECC_BP512R1_ENABLED
+    nrf_crypto_backend_bp512r1_public_key_free,
+#endif
+#if NRF_CRYPTO_ECC_CURVE25519_ENABLED
+    nrf_crypto_backend_curve25519_public_key_free,
+#endif
+#if NRF_CRYPTO_ECC_ED25519_ENABLED
+    nrf_crypto_backend_ed25519_public_key_free,
+#endif
+};
+
+
+#define BACKEND_IMPL_GET(table, curve_type) (table)[(uint32_t)(curve_type)]
+
+
+#else
+
+
+#if NRF_CRYPTO_ECC_SECP160R1_ENABLED
+#define key_pair_generate_impl    nrf_crypto_backend_secp160r1_key_pair_generate
+#define public_key_calculate_impl nrf_crypto_backend_secp160r1_public_key_calculate
+#define private_key_from_raw_impl nrf_crypto_backend_secp160r1_private_key_from_raw
+#define private_key_to_raw_impl   nrf_crypto_backend_secp160r1_private_key_to_raw
+#define public_key_from_raw_impl  nrf_crypto_backend_secp160r1_public_key_from_raw
+#define public_key_to_raw_impl    nrf_crypto_backend_secp160r1_public_key_to_raw
+#define private_key_free_impl     nrf_crypto_backend_secp160r1_private_key_free
+#define public_key_free_impl      nrf_crypto_backend_secp160r1_public_key_free
+#define key_pair_generate_context_size \
+    NRF_CRYPTO_BACKEND_SECP160R1_KEY_PAIR_GENERATE_CONTEXT_SIZE
+#define public_key_calculate_context_size \
+    NRF_CRYPTO_BACKEND_SECP160R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE
+#elif NRF_CRYPTO_ECC_SECP160R2_ENABLED
+#define key_pair_generate_impl    nrf_crypto_backend_secp160r2_key_pair_generate
+#define public_key_calculate_impl nrf_crypto_backend_secp160r2_public_key_calculate
+#define private_key_from_raw_impl nrf_crypto_backend_secp160r2_private_key_from_raw
+#define private_key_to_raw_impl   nrf_crypto_backend_secp160r2_private_key_to_raw
+#define public_key_from_raw_impl  nrf_crypto_backend_secp160r2_public_key_from_raw
+#define public_key_to_raw_impl    nrf_crypto_backend_secp160r2_public_key_to_raw
+#define private_key_free_impl     nrf_crypto_backend_secp160r2_private_key_free
+#define public_key_free_impl      nrf_crypto_backend_secp160r2_public_key_free
+#define key_pair_generate_context_size \
+    NRF_CRYPTO_BACKEND_SECP160R2_KEY_PAIR_GENERATE_CONTEXT_SIZE
+#define public_key_calculate_context_size \
+    NRF_CRYPTO_BACKEND_SECP160R2_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE
+#elif NRF_CRYPTO_ECC_SECP192R1_ENABLED
+#define key_pair_generate_impl    nrf_crypto_backend_secp192r1_key_pair_generate
+#define public_key_calculate_impl nrf_crypto_backend_secp192r1_public_key_calculate
+#define private_key_from_raw_impl nrf_crypto_backend_secp192r1_private_key_from_raw
+#define private_key_to_raw_impl   nrf_crypto_backend_secp192r1_private_key_to_raw
+#define public_key_from_raw_impl  nrf_crypto_backend_secp192r1_public_key_from_raw
+#define public_key_to_raw_impl    nrf_crypto_backend_secp192r1_public_key_to_raw
+#define private_key_free_impl     nrf_crypto_backend_secp192r1_private_key_free
+#define public_key_free_impl      nrf_crypto_backend_secp192r1_public_key_free
+#define key_pair_generate_context_size \
+    NRF_CRYPTO_BACKEND_SECP192R1_KEY_PAIR_GENERATE_CONTEXT_SIZE
+#define public_key_calculate_context_size \
+    NRF_CRYPTO_BACKEND_SECP192R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE
+#elif NRF_CRYPTO_ECC_SECP224R1_ENABLED
+#define key_pair_generate_impl    nrf_crypto_backend_secp224r1_key_pair_generate
+#define public_key_calculate_impl nrf_crypto_backend_secp224r1_public_key_calculate
+#define private_key_from_raw_impl nrf_crypto_backend_secp224r1_private_key_from_raw
+#define private_key_to_raw_impl   nrf_crypto_backend_secp224r1_private_key_to_raw
+#define public_key_from_raw_impl  nrf_crypto_backend_secp224r1_public_key_from_raw
+#define public_key_to_raw_impl    nrf_crypto_backend_secp224r1_public_key_to_raw
+#define private_key_free_impl     nrf_crypto_backend_secp224r1_private_key_free
+#define public_key_free_impl      nrf_crypto_backend_secp224r1_public_key_free
+#define key_pair_generate_context_size \
+    NRF_CRYPTO_BACKEND_SECP224R1_KEY_PAIR_GENERATE_CONTEXT_SIZE
+#define public_key_calculate_context_size \
+    NRF_CRYPTO_BACKEND_SECP224R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE
+#elif NRF_CRYPTO_ECC_SECP256R1_ENABLED
+#define key_pair_generate_impl    nrf_crypto_backend_secp256r1_key_pair_generate
+#define public_key_calculate_impl nrf_crypto_backend_secp256r1_public_key_calculate
+#define private_key_from_raw_impl nrf_crypto_backend_secp256r1_private_key_from_raw
+#define private_key_to_raw_impl   nrf_crypto_backend_secp256r1_private_key_to_raw
+#define public_key_from_raw_impl  nrf_crypto_backend_secp256r1_public_key_from_raw
+#define public_key_to_raw_impl    nrf_crypto_backend_secp256r1_public_key_to_raw
+#define private_key_free_impl     nrf_crypto_backend_secp256r1_private_key_free
+#define public_key_free_impl      nrf_crypto_backend_secp256r1_public_key_free
+#define key_pair_generate_context_size \
+    NRF_CRYPTO_BACKEND_SECP256R1_KEY_PAIR_GENERATE_CONTEXT_SIZE
+#define public_key_calculate_context_size \
+    NRF_CRYPTO_BACKEND_SECP256R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE
+#elif NRF_CRYPTO_ECC_SECP384R1_ENABLED
+#define key_pair_generate_impl    nrf_crypto_backend_secp384r1_key_pair_generate
+#define public_key_calculate_impl nrf_crypto_backend_secp384r1_public_key_calculate
+#define private_key_from_raw_impl nrf_crypto_backend_secp384r1_private_key_from_raw
+#define private_key_to_raw_impl   nrf_crypto_backend_secp384r1_private_key_to_raw
+#define public_key_from_raw_impl  nrf_crypto_backend_secp384r1_public_key_from_raw
+#define public_key_to_raw_impl    nrf_crypto_backend_secp384r1_public_key_to_raw
+#define private_key_free_impl     nrf_crypto_backend_secp384r1_private_key_free
+#define public_key_free_impl      nrf_crypto_backend_secp384r1_public_key_free
+#define key_pair_generate_context_size \
+    NRF_CRYPTO_BACKEND_SECP384R1_KEY_PAIR_GENERATE_CONTEXT_SIZE
+#define public_key_calculate_context_size \
+    NRF_CRYPTO_BACKEND_SECP384R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE
+#elif NRF_CRYPTO_ECC_SECP521R1_ENABLED
+#define key_pair_generate_impl    nrf_crypto_backend_secp521r1_key_pair_generate
+#define public_key_calculate_impl nrf_crypto_backend_secp521r1_public_key_calculate
+#define private_key_from_raw_impl nrf_crypto_backend_secp521r1_private_key_from_raw
+#define private_key_to_raw_impl   nrf_crypto_backend_secp521r1_private_key_to_raw
+#define public_key_from_raw_impl  nrf_crypto_backend_secp521r1_public_key_from_raw
+#define public_key_to_raw_impl    nrf_crypto_backend_secp521r1_public_key_to_raw
+#define private_key_free_impl     nrf_crypto_backend_secp521r1_private_key_free
+#define public_key_free_impl      nrf_crypto_backend_secp521r1_public_key_free
+#define key_pair_generate_context_size \
+    NRF_CRYPTO_BACKEND_SECP521R1_KEY_PAIR_GENERATE_CONTEXT_SIZE
+#define public_key_calculate_context_size \
+    NRF_CRYPTO_BACKEND_SECP521R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE
+#elif NRF_CRYPTO_ECC_SECP160K1_ENABLED
+#define key_pair_generate_impl    nrf_crypto_backend_secp160k1_key_pair_generate
+#define public_key_calculate_impl nrf_crypto_backend_secp160k1_public_key_calculate
+#define private_key_from_raw_impl nrf_crypto_backend_secp160k1_private_key_from_raw
+#define private_key_to_raw_impl   nrf_crypto_backend_secp160k1_private_key_to_raw
+#define public_key_from_raw_impl  nrf_crypto_backend_secp160k1_public_key_from_raw
+#define public_key_to_raw_impl    nrf_crypto_backend_secp160k1_public_key_to_raw
+#define private_key_free_impl     nrf_crypto_backend_secp160k1_private_key_free
+#define public_key_free_impl      nrf_crypto_backend_secp160k1_public_key_free
+#define key_pair_generate_context_size \
+    NRF_CRYPTO_BACKEND_SECP160K1_KEY_PAIR_GENERATE_CONTEXT_SIZE
+#define public_key_calculate_context_size \
+    NRF_CRYPTO_BACKEND_SECP160K1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE
+#elif NRF_CRYPTO_ECC_SECP192K1_ENABLED
+#define key_pair_generate_impl    nrf_crypto_backend_secp192k1_key_pair_generate
+#define public_key_calculate_impl nrf_crypto_backend_secp192k1_public_key_calculate
+#define private_key_from_raw_impl nrf_crypto_backend_secp192k1_private_key_from_raw
+#define private_key_to_raw_impl   nrf_crypto_backend_secp192k1_private_key_to_raw
+#define public_key_from_raw_impl  nrf_crypto_backend_secp192k1_public_key_from_raw
+#define public_key_to_raw_impl    nrf_crypto_backend_secp192k1_public_key_to_raw
+#define private_key_free_impl     nrf_crypto_backend_secp192k1_private_key_free
+#define public_key_free_impl      nrf_crypto_backend_secp192k1_public_key_free
+#define key_pair_generate_context_size \
+    NRF_CRYPTO_BACKEND_SECP192K1_KEY_PAIR_GENERATE_CONTEXT_SIZE
+#define public_key_calculate_context_size \
+    NRF_CRYPTO_BACKEND_SECP192K1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE
+#elif NRF_CRYPTO_ECC_SECP224K1_ENABLED
+#define key_pair_generate_impl    nrf_crypto_backend_secp224k1_key_pair_generate
+#define public_key_calculate_impl nrf_crypto_backend_secp224k1_public_key_calculate
+#define private_key_from_raw_impl nrf_crypto_backend_secp224k1_private_key_from_raw
+#define private_key_to_raw_impl   nrf_crypto_backend_secp224k1_private_key_to_raw
+#define public_key_from_raw_impl  nrf_crypto_backend_secp224k1_public_key_from_raw
+#define public_key_to_raw_impl    nrf_crypto_backend_secp224k1_public_key_to_raw
+#define private_key_free_impl     nrf_crypto_backend_secp224k1_private_key_free
+#define public_key_free_impl      nrf_crypto_backend_secp224k1_public_key_free
+#define key_pair_generate_context_size \
+    NRF_CRYPTO_BACKEND_SECP224K1_KEY_PAIR_GENERATE_CONTEXT_SIZE
+#define public_key_calculate_context_size \
+    NRF_CRYPTO_BACKEND_SECP224K1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE
+#elif NRF_CRYPTO_ECC_SECP256K1_ENABLED
+#define key_pair_generate_impl    nrf_crypto_backend_secp256k1_key_pair_generate
+#define public_key_calculate_impl nrf_crypto_backend_secp256k1_public_key_calculate
+#define private_key_from_raw_impl nrf_crypto_backend_secp256k1_private_key_from_raw
+#define private_key_to_raw_impl   nrf_crypto_backend_secp256k1_private_key_to_raw
+#define public_key_from_raw_impl  nrf_crypto_backend_secp256k1_public_key_from_raw
+#define public_key_to_raw_impl    nrf_crypto_backend_secp256k1_public_key_to_raw
+#define private_key_free_impl     nrf_crypto_backend_secp256k1_private_key_free
+#define public_key_free_impl      nrf_crypto_backend_secp256k1_public_key_free
+#define key_pair_generate_context_size \
+    NRF_CRYPTO_BACKEND_SECP256K1_KEY_PAIR_GENERATE_CONTEXT_SIZE
+#define public_key_calculate_context_size \
+    NRF_CRYPTO_BACKEND_SECP256K1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE
+#elif NRF_CRYPTO_ECC_BP256R1_ENABLED
+#define key_pair_generate_impl    nrf_crypto_backend_bp256r1_key_pair_generate
+#define public_key_calculate_impl nrf_crypto_backend_bp256r1_public_key_calculate
+#define private_key_from_raw_impl nrf_crypto_backend_bp256r1_private_key_from_raw
+#define private_key_to_raw_impl   nrf_crypto_backend_bp256r1_private_key_to_raw
+#define public_key_from_raw_impl  nrf_crypto_backend_bp256r1_public_key_from_raw
+#define public_key_to_raw_impl    nrf_crypto_backend_bp256r1_public_key_to_raw
+#define private_key_free_impl     nrf_crypto_backend_bp256r1_private_key_free
+#define public_key_free_impl      nrf_crypto_backend_bp256r1_public_key_free
+#define key_pair_generate_context_size \
+    NRF_CRYPTO_BACKEND_BP256R1_KEY_PAIR_GENERATE_CONTEXT_SIZE
+#define public_key_calculate_context_size \
+    NRF_CRYPTO_BACKEND_BP256R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE
+#elif NRF_CRYPTO_ECC_BP384R1_ENABLED
+#define key_pair_generate_impl    nrf_crypto_backend_bp384r1_key_pair_generate
+#define public_key_calculate_impl nrf_crypto_backend_bp384r1_public_key_calculate
+#define private_key_from_raw_impl nrf_crypto_backend_bp384r1_private_key_from_raw
+#define private_key_to_raw_impl   nrf_crypto_backend_bp384r1_private_key_to_raw
+#define public_key_from_raw_impl  nrf_crypto_backend_bp384r1_public_key_from_raw
+#define public_key_to_raw_impl    nrf_crypto_backend_bp384r1_public_key_to_raw
+#define private_key_free_impl     nrf_crypto_backend_bp384r1_private_key_free
+#define public_key_free_impl      nrf_crypto_backend_bp384r1_public_key_free
+#define key_pair_generate_context_size \
+    NRF_CRYPTO_BACKEND_BP384R1_KEY_PAIR_GENERATE_CONTEXT_SIZE
+#define public_key_calculate_context_size \
+    NRF_CRYPTO_BACKEND_BP384R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE
+#elif NRF_CRYPTO_ECC_BP512R1_ENABLED
+#define key_pair_generate_impl    nrf_crypto_backend_bp512r1_key_pair_generate
+#define public_key_calculate_impl nrf_crypto_backend_bp512r1_public_key_calculate
+#define private_key_from_raw_impl nrf_crypto_backend_bp512r1_private_key_from_raw
+#define private_key_to_raw_impl   nrf_crypto_backend_bp512r1_private_key_to_raw
+#define public_key_from_raw_impl  nrf_crypto_backend_bp512r1_public_key_from_raw
+#define public_key_to_raw_impl    nrf_crypto_backend_bp512r1_public_key_to_raw
+#define private_key_free_impl     nrf_crypto_backend_bp512r1_private_key_free
+#define public_key_free_impl      nrf_crypto_backend_bp512r1_public_key_free
+#define key_pair_generate_context_size \
+    NRF_CRYPTO_BACKEND_BP512R1_KEY_PAIR_GENERATE_CONTEXT_SIZE
+#define public_key_calculate_context_size \
+    NRF_CRYPTO_BACKEND_BP512R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE
+#elif NRF_CRYPTO_ECC_CURVE25519_ENABLED
+#define key_pair_generate_impl    nrf_crypto_backend_curve25519_key_pair_generate
+#define public_key_calculate_impl nrf_crypto_backend_curve25519_public_key_calculate
+#define private_key_from_raw_impl nrf_crypto_backend_curve25519_private_key_from_raw
+#define private_key_to_raw_impl   nrf_crypto_backend_curve25519_private_key_to_raw
+#define public_key_from_raw_impl  nrf_crypto_backend_curve25519_public_key_from_raw
+#define public_key_to_raw_impl    nrf_crypto_backend_curve25519_public_key_to_raw
+#define private_key_free_impl     nrf_crypto_backend_curve25519_private_key_free
+#define public_key_free_impl      nrf_crypto_backend_curve25519_public_key_free
+#define key_pair_generate_context_size \
+    NRF_CRYPTO_BACKEND_CURVE25519_KEY_PAIR_GENERATE_CONTEXT_SIZE
+#define public_key_calculate_context_size \
+    NRF_CRYPTO_BACKEND_CURVE25519_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE
+#elif NRF_CRYPTO_ECC_ED25519_ENABLED
+#define key_pair_generate_impl    nrf_crypto_backend_ed25519_key_pair_generate
+#define public_key_calculate_impl nrf_crypto_backend_ed25519_public_key_calculate
+#define private_key_from_raw_impl nrf_crypto_backend_ed25519_private_key_from_raw
+#define private_key_to_raw_impl   nrf_crypto_backend_ed25519_private_key_to_raw
+#define public_key_from_raw_impl  nrf_crypto_backend_ed25519_public_key_from_raw
+#define public_key_to_raw_impl    nrf_crypto_backend_ed25519_public_key_to_raw
+#define private_key_free_impl     nrf_crypto_backend_ed25519_private_key_free
+#define public_key_free_impl      nrf_crypto_backend_ed25519_public_key_free
+#define key_pair_generate_context_size \
+    NRF_CRYPTO_BACKEND_ED25519_KEY_PAIR_GENERATE_CONTEXT_SIZE
+#define public_key_calculate_context_size \
+    NRF_CRYPTO_BACKEND_ED25519_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE
+#else
+#define key_pair_generate_impl            NULL
+#define public_key_calculate_impl         NULL
+#define private_key_from_raw_impl         NULL
+#define private_key_to_raw_impl           NULL
+#define public_key_from_raw_impl          NULL
+#define public_key_to_raw_impl            NULL
+#define private_key_free_impl             NULL
+#define public_key_free_impl              NULL
+#define key_pair_generate_context_size    0
+#define public_key_calculate_context_size 0
+#endif
+
+
+#define BACKEND_IMPL_GET(function, curve_type) (function)
+
+
+#endif
+
+
+ret_code_t nrf_crypto_internal_ecc_key_output_prepare(
+    nrf_crypto_ecc_curve_info_t          const * p_curve_info,
+    nrf_crypto_internal_ecc_key_header_t       * p_key_header)
+{
+    // Check NULL pointers
+    VERIFY_TRUE(p_curve_info != NULL, NRF_ERROR_CRYPTO_INPUT_NULL);
+    VERIFY_TRUE(p_key_header != NULL, NRF_ERROR_CRYPTO_OUTPUT_NULL);
+
+    // Clear init value to indicate that this key is not valid yet.
+    p_key_header->init_value = 0;
+    // Save curve info inside the header
+    p_key_header->p_info = p_curve_info;
+
+    return NRF_SUCCESS;
+}
+
+
+ret_code_t nrf_crypto_internal_ecc_key_input_check(
+    nrf_crypto_internal_ecc_key_header_t const * p_key_header,
+    uint32_t                                     init_value)
+{
+    // Check NULL pointer
+    VERIFY_TRUE(p_key_header != NULL, NRF_ERROR_CRYPTO_INPUT_NULL);
+    // Check init value
+    VERIFY_TRUE(p_key_header->init_value == init_value, NRF_ERROR_CRYPTO_ECC_KEY_NOT_INITIALIZED);
+
+    return NRF_SUCCESS;
+}
+
+
+ret_code_t nrf_crypto_internal_ecc_raw_output_prepare(
+    uint8_t    * p_raw_data,
+    size_t     * p_raw_data_size,
+    size_t       expected_size)
+{
+    // Check NULL pointer
+    VERIFY_TRUE(p_raw_data != NULL, NRF_ERROR_CRYPTO_OUTPUT_NULL);
+
+    if (p_raw_data_size != NULL) // User can provide NULL as p_raw_data_size to skip size checking
+    {
+        // Check if data fits into buffer
+        VERIFY_TRUE(*p_raw_data_size >= expected_size, NRF_ERROR_CRYPTO_OUTPUT_LENGTH);
+        // Provide actual data size
+        *p_raw_data_size = expected_size;
+    }
+
+    return NRF_SUCCESS;
+}
+
+
+ret_code_t nrf_crypto_internal_ecc_raw_input_check(
+    uint8_t const * p_raw_data,
+    size_t          raw_data_size,
+    size_t          expected_size)
+{
+    VERIFY_TRUE(p_raw_data != NULL, NRF_ERROR_CRYPTO_INPUT_NULL);
+    VERIFY_TRUE(raw_data_size == expected_size, NRF_ERROR_CRYPTO_INPUT_LENGTH);
+
+    return NRF_SUCCESS;
+}
+
+
+ret_code_t nrf_crypto_ecc_key_pair_generate(
+    nrf_crypto_ecc_key_pair_generate_context_t       * p_context,
+    nrf_crypto_ecc_curve_info_t                const * p_curve_info,
+    nrf_crypto_ecc_private_key_t                     * p_private_key,
+    nrf_crypto_ecc_public_key_t                      * p_public_key)
+{
+    ret_code_t                                     result;
+    void                                         * p_allocated_context = NULL;
+    nrf_crypto_backend_ecc_key_pair_generate_fn_t  backend_implementation;
+    size_t                                         context_size;
+
+    // Get pointer to header for each key
+    nrf_crypto_internal_ecc_key_header_t * p_private_key_header =
+        (nrf_crypto_internal_ecc_key_header_t *)p_private_key;
+    nrf_crypto_internal_ecc_key_header_t * p_public_key_header =
+        (nrf_crypto_internal_ecc_key_header_t *)p_public_key;
+
+    // Check and prepare parameters
+    result = nrf_crypto_internal_ecc_key_output_prepare(p_curve_info, p_private_key_header);
+    VERIFY_SUCCESS(result);
+    result = nrf_crypto_internal_ecc_key_output_prepare(p_curve_info, p_public_key_header);
+    VERIFY_SUCCESS(result);
+
+    // Get backend specific information
+    backend_implementation = BACKEND_IMPL_GET(key_pair_generate_impl, p_curve_info->curve_type);
+    context_size = BACKEND_IMPL_GET(key_pair_generate_context_size, p_curve_info->curve_type);
+    VERIFY_TRUE(backend_implementation != NULL, NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE);
+
+    // Allocate context if not provided
+    if (p_context == NULL && context_size > 0)
+    {
+        p_allocated_context = NRF_CRYPTO_ALLOC(context_size);
+        VERIFY_TRUE(p_allocated_context != NULL, NRF_ERROR_CRYPTO_ALLOC_FAILED);
+        p_context = p_allocated_context;
+    }
+
+    // Execute backend implementation
+    result = backend_implementation(p_context, p_private_key, p_public_key);
+
+    // Set init values to indicate valid key
+    if (result == NRF_SUCCESS)
+    {
+        p_private_key_header->init_value = NRF_CRYPTO_INTERNAL_ECC_PRIVATE_KEY_INIT_VALUE;
+        p_public_key_header->init_value = NRF_CRYPTO_INTERNAL_ECC_PUBLIC_KEY_INIT_VALUE;
+    }
+
+    // Deallocate context if allocated
+    if (p_allocated_context != NULL)
+    {
+        NRF_CRYPTO_FREE(p_allocated_context);
+    }
+
+    return result;
+}
+
+
+ret_code_t nrf_crypto_ecc_public_key_calculate(
+    nrf_crypto_ecc_public_key_calculate_context_t       * p_context,
+    nrf_crypto_ecc_private_key_t                  const * p_private_key,
+    nrf_crypto_ecc_public_key_t                         * p_public_key)
+{
+    ret_code_t                                        result;
+    void                                            * p_allocated_context = NULL;
+    nrf_crypto_backend_ecc_public_key_calculate_fn_t  backend_implementation;
+    size_t                                            context_size;
+    nrf_crypto_ecc_curve_info_t               const * p_info;
+
+    // Get pointer to header for each key
+    nrf_crypto_internal_ecc_key_header_t const * p_private_key_header =
+        (nrf_crypto_internal_ecc_key_header_t const *)p_private_key;
+    nrf_crypto_internal_ecc_key_header_t       * p_public_key_header =
+        (nrf_crypto_internal_ecc_key_header_t *)p_public_key;
+
+    // Check and prepare parameters
+    result = nrf_crypto_internal_ecc_key_input_check(
+        p_private_key_header,
+        NRF_CRYPTO_INTERNAL_ECC_PRIVATE_KEY_INIT_VALUE);
+    VERIFY_SUCCESS(result);
+    p_info = p_private_key_header->p_info;
+    result  = nrf_crypto_internal_ecc_key_output_prepare(p_info, p_public_key_header);
+    VERIFY_SUCCESS(result);
+
+    // Get backend specific information
+    backend_implementation = BACKEND_IMPL_GET(public_key_calculate_impl, p_info->curve_type);
+    context_size = BACKEND_IMPL_GET(public_key_calculate_context_size, p_info->curve_type);
+    VERIFY_TRUE(backend_implementation != NULL, NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE);
+
+    // Allocate context if not provided
+    if (p_context == NULL && context_size > 0)
+    {
+        p_allocated_context = NRF_CRYPTO_ALLOC(context_size);
+        VERIFY_TRUE(p_allocated_context != NULL, NRF_ERROR_CRYPTO_ALLOC_FAILED);
+        p_context = p_allocated_context;
+    }
+
+    // Execute backend implementation
+    result = backend_implementation(p_context, p_private_key, p_public_key);
+
+    // Set init values to indicate valid key
+    if (result == NRF_SUCCESS)
+    {
+        p_public_key_header->init_value = NRF_CRYPTO_INTERNAL_ECC_PUBLIC_KEY_INIT_VALUE;
+    }
+
+    // Deallocate context if allocated
+    if (p_allocated_context != NULL)
+    {
+        NRF_CRYPTO_FREE(p_allocated_context);
+    }
+
+    return result;
+}
+
+
+ret_code_t nrf_crypto_ecc_private_key_from_raw(
+    nrf_crypto_ecc_curve_info_t  const * p_curve_info,
+    nrf_crypto_ecc_private_key_t       * p_private_key,
+    uint8_t                      const * p_raw_data,
+    size_t                               raw_data_size)
+{
+    ret_code_t                                       result;
+    nrf_crypto_backend_ecc_private_key_from_raw_fn_t backend_implementation;
+
+    // Get pointer to header
+    nrf_crypto_internal_ecc_key_header_t * p_private_key_header =
+        (nrf_crypto_internal_ecc_key_header_t *)p_private_key;
+
+    // Check and prepare parameters
+    result = nrf_crypto_internal_ecc_key_output_prepare(p_curve_info,
+                                                        p_private_key_header);
+    VERIFY_SUCCESS(result);
+    result = nrf_crypto_internal_ecc_raw_input_check(p_raw_data,
+                                                     raw_data_size,
+                                                     p_curve_info->raw_private_key_size);
+    VERIFY_SUCCESS(result);
+
+    // Get backend specific information
+    backend_implementation = BACKEND_IMPL_GET(private_key_from_raw_impl, p_curve_info->curve_type);
+    VERIFY_TRUE(backend_implementation != NULL, NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE);
+
+    // Execute backend implementation
+    result = backend_implementation(p_private_key, p_raw_data);
+
+    // Set init value to indicate valid key
+    if (result == NRF_SUCCESS)
+    {
+        p_private_key_header->init_value = NRF_CRYPTO_INTERNAL_ECC_PRIVATE_KEY_INIT_VALUE;
+    }
+
+    return result;
+}
+
+
+ret_code_t nrf_crypto_ecc_private_key_to_raw(
+    nrf_crypto_ecc_private_key_t const * p_private_key,
+    uint8_t                            * p_raw_data,
+    size_t                             * p_raw_data_size)
+{
+    ret_code_t                                             result;
+    nrf_crypto_ecc_curve_info_t                    const * p_info;
+    nrf_crypto_backend_ecc_private_key_to_raw_fn_t         backend_implementation;
+
+    // Get pointer to header
+    nrf_crypto_internal_ecc_key_header_t const * p_private_key_header =
+        (nrf_crypto_internal_ecc_key_header_t const *)p_private_key;
+
+    // Check and prepare parameters
+    result = nrf_crypto_internal_ecc_key_input_check(
+        p_private_key_header,
+        NRF_CRYPTO_INTERNAL_ECC_PRIVATE_KEY_INIT_VALUE);
+    VERIFY_SUCCESS(result);
+    p_info = p_private_key_header->p_info;
+    result = nrf_crypto_internal_ecc_raw_output_prepare(p_raw_data,
+                                                        p_raw_data_size,
+                                                        p_info->raw_private_key_size);
+    VERIFY_SUCCESS(result);
+
+    // Get backend specific information
+    backend_implementation = BACKEND_IMPL_GET(private_key_to_raw_impl, p_info->curve_type);
+    VERIFY_TRUE(backend_implementation != NULL, NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE);
+
+    // Execute backend implementation
+    result = backend_implementation(p_private_key, p_raw_data);
+
+    return result;
+}
+
+
+ret_code_t nrf_crypto_ecc_public_key_from_raw(
+    nrf_crypto_ecc_curve_info_t const * p_curve_info,
+    nrf_crypto_ecc_public_key_t       * p_public_key,
+    uint8_t                     const * p_raw_data,
+    size_t                              raw_data_size)
+{
+    ret_code_t                                       result;
+    nrf_crypto_backend_ecc_private_key_from_raw_fn_t backend_implementation;
+
+    // Get pointer to header
+    nrf_crypto_internal_ecc_key_header_t * p_public_key_header =
+        (nrf_crypto_internal_ecc_key_header_t *)p_public_key;
+
+    // Check and prepare parameters
+    result = nrf_crypto_internal_ecc_key_output_prepare(p_curve_info,
+                                                        p_public_key_header);
+    VERIFY_SUCCESS(result);
+    result = nrf_crypto_internal_ecc_raw_input_check(p_raw_data,
+                                                     raw_data_size,
+                                                     p_curve_info->raw_public_key_size);
+    VERIFY_SUCCESS(result);
+
+    // Get backend specific information
+    backend_implementation = BACKEND_IMPL_GET(public_key_from_raw_impl, p_curve_info->curve_type);
+    VERIFY_TRUE(backend_implementation != NULL, NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE);
+
+    // Execute backend implementation
+    result = backend_implementation(p_public_key, p_raw_data);
+
+    // Set init value to indicate valid key
+    if (result == NRF_SUCCESS)
+    {
+        p_public_key_header->init_value = NRF_CRYPTO_INTERNAL_ECC_PUBLIC_KEY_INIT_VALUE;
+    }
+
+    return result;
+}
+
+
+ret_code_t nrf_crypto_ecc_public_key_to_raw(
+    nrf_crypto_ecc_public_key_t const * p_public_key,
+    uint8_t                           * p_raw_data,
+    size_t                            * p_raw_data_size)
+{
+    ret_code_t                                            result;
+    nrf_crypto_ecc_curve_info_t                   const * p_info;
+    nrf_crypto_backend_ecc_public_key_to_raw_fn_t         backend_implementation;
+
+    // Get pointer to header
+    nrf_crypto_internal_ecc_key_header_t const * p_public_key_header =
+        (nrf_crypto_internal_ecc_key_header_t const *)p_public_key;
+
+    // Check and prepare parameters
+    result = nrf_crypto_internal_ecc_key_input_check(
+        p_public_key_header,
+        NRF_CRYPTO_INTERNAL_ECC_PUBLIC_KEY_INIT_VALUE);
+    VERIFY_SUCCESS(result);
+    p_info = p_public_key_header->p_info;
+    result = nrf_crypto_internal_ecc_raw_output_prepare(p_raw_data,
+                                                        p_raw_data_size,
+                                                        p_info->raw_public_key_size);
+    VERIFY_SUCCESS(result);
+
+    // Get backend specific information
+    backend_implementation = BACKEND_IMPL_GET(public_key_to_raw_impl, p_info->curve_type);
+    VERIFY_TRUE(backend_implementation != NULL, NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE);
+
+    // Execute backend implementation
+    result = backend_implementation(p_public_key, p_raw_data);
+
+    return result;
+}
+
+
+ret_code_t nrf_crypto_ecc_private_key_free(
+    nrf_crypto_ecc_private_key_t * p_private_key)
+{
+    ret_code_t                                   result;
+    nrf_crypto_ecc_curve_info_t          const * p_info;
+    nrf_crypto_backend_ecc_key_free_fn_t         backend_implementation;
+
+    // Get pointer to header
+    nrf_crypto_internal_ecc_key_header_t * p_private_key_header =
+        (nrf_crypto_internal_ecc_key_header_t *)p_private_key;
+
+    // Check and prepare parameters
+    result = nrf_crypto_internal_ecc_key_input_check(
+        p_private_key_header,
+        NRF_CRYPTO_INTERNAL_ECC_PRIVATE_KEY_INIT_VALUE);
+    VERIFY_SUCCESS(result);
+    p_info = p_private_key_header->p_info;
+
+    UNUSED_PARAMETER(p_info); // Is some situations BACKEND_IMPL_GET() macro may not use second parameter
+
+    // Get backend specific information
+    backend_implementation = BACKEND_IMPL_GET(private_key_free_impl, p_info->curve_type);
+
+    if (backend_implementation != NULL)
+    {
+        // Execute backend implementation
+        result = backend_implementation(p_private_key);
+    }
+    else
+    {
+        // Free is not implemented by the backend, so nothing have to deallocated.
+        result = NRF_SUCCESS;
+    }
+
+    // Clear init value to indicate invalid key
+    p_private_key_header->init_value = 0;
+
+    return result;
+}
+
+
+ret_code_t nrf_crypto_ecc_public_key_free(
+    nrf_crypto_ecc_public_key_t * p_public_key)
+{
+    ret_code_t                                   result;
+    nrf_crypto_ecc_curve_info_t          const * p_info;
+    nrf_crypto_backend_ecc_key_free_fn_t         backend_implementation;
+
+    // Get pointer to header
+    nrf_crypto_internal_ecc_key_header_t * p_public_key_header =
+        (nrf_crypto_internal_ecc_key_header_t *)p_public_key;
+
+    // Check and prepare parameters
+    result = nrf_crypto_internal_ecc_key_input_check(
+        p_public_key_header,
+        NRF_CRYPTO_INTERNAL_ECC_PUBLIC_KEY_INIT_VALUE);
+    VERIFY_SUCCESS(result);
+    p_info = p_public_key_header->p_info;
+
+    UNUSED_PARAMETER(p_info); // Is some situations BACKEND_IMPL_GET() macro may not use second parameter
+
+    // Get backend specific information
+    backend_implementation = BACKEND_IMPL_GET(public_key_free_impl, p_info->curve_type);
+
+    if (backend_implementation != NULL)
+    {
+        // Execute backend implementation
+        result = backend_implementation(p_public_key);
+    }
+    else
+    {
+        // Free is not implemented by the backend, so nothing have to deallocated.
+        result = NRF_SUCCESS;
+    }
+
+    // Clear init value to indicate invalid key
+    p_public_key_header->init_value = 0;
+
+    return result;
+}
+
+
+ret_code_t nrf_crypto_ecc_curve_info_get(
+    void                         const * p_key,
+    nrf_crypto_ecc_curve_info_t const ** pp_curve_info)
+{
+    ret_code_t result;
+
+    // Get pointer to header
+    nrf_crypto_internal_ecc_key_header_t const * p_key_header =
+        (nrf_crypto_internal_ecc_key_header_t const *)p_key;
+
+    // Check and prepare parameters
+    VERIFY_TRUE(pp_curve_info != NULL, NRF_ERROR_CRYPTO_INPUT_NULL);
+    result = nrf_crypto_internal_ecc_key_input_check(
+        p_key_header,
+        NRF_CRYPTO_INTERNAL_ECC_PRIVATE_KEY_INIT_VALUE);
+    if (result != NRF_SUCCESS)
+    {
+        // p_key can be private or public key, so check second case here
+        result = nrf_crypto_internal_ecc_key_input_check(
+            p_key_header,
+            NRF_CRYPTO_INTERNAL_ECC_PUBLIC_KEY_INIT_VALUE);
+    }
+    VERIFY_SUCCESS(result);
+
+    // Write output parameter
+    *pp_curve_info = p_key_header->p_info;
+
+    return NRF_SUCCESS;
+}
+
+
+ret_code_t nrf_crypto_ecc_byte_order_invert(
+    nrf_crypto_ecc_curve_info_t const * p_curve_info,
+    uint8_t                     const * p_raw_input,
+    uint8_t                           * p_raw_output,
+    size_t                              raw_data_size)
+{
+    uint8_t temp;
+    size_t  from_index;
+    size_t  to_index;
+    size_t  integer_size;
+
+    if (p_curve_info == NULL)
+    {
+        integer_size = raw_data_size;
+    }
+    else
+    {
+        integer_size = p_curve_info->raw_private_key_size;
+    }
+
+    VERIFY_TRUE(p_raw_input != NULL, NRF_ERROR_CRYPTO_INPUT_NULL);
+    VERIFY_TRUE(p_raw_output != NULL, NRF_ERROR_CRYPTO_OUTPUT_NULL);
+
+    // Loop over each big integer of the input
+    while (raw_data_size >= integer_size)
+    {
+        // Swap byte by byte in current integer
+        from_index = 0;
+        to_index = integer_size - 1;
+        while (from_index <= to_index)
+        {
+            // Swap bytes from source to destination, this may be the same buffer, so use temporary variable
+            temp = p_raw_input[from_index];
+            p_raw_output[from_index] = p_raw_input[to_index];
+            p_raw_output[to_index] = temp;
+            // Go to next pair of bytes
+            from_index++;
+            to_index--;
+        }
+        // Go to next integer
+        raw_data_size -= integer_size;
+        p_raw_input += integer_size;
+        p_raw_output += integer_size;
+    }
+
+    if (raw_data_size != 0)
+    {
+        // Input size is not a multiple of big integer size, so it is invalid
+        return NRF_ERROR_CRYPTO_INPUT_LENGTH;
+    }
+
+    return NRF_SUCCESS;
+}
+
+
+#endif // NRF_CRYPTO_ECC_ENABLED
diff --git a/examples/heart_rate_collector/nrf_crypto_ecc.h b/examples/heart_rate_collector/nrf_crypto_ecc.h
new file mode 100644
index 0000000..e506124
--- /dev/null
+++ b/examples/heart_rate_collector/nrf_crypto_ecc.h
@@ -0,0 +1,1002 @@
+/**
+ * Copyright (c) 2018, 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.
+ *
+ */
+
+#ifndef NRF_CRYPTO_ECC_H__
+#define NRF_CRYPTO_ECC_H__
+
+/** @addtogroup nrf_crypto
+ *  @{
+ *  @addtogroup nrf_crypto_ecc Elliptic Curve Cryptography Key Management
+ *  @{
+ *  @brief Provides elliptic curve cryptography API for public and private key management.
+ *
+ *  @addtogroup nrf_crypto_ecc_secp160r1   Definitions specific to secp160r1 (NIST 160-bit)
+ *  @addtogroup nrf_crypto_ecc_secp160r2   Definitions specific to secp160r2 (NIST 160-bit)
+ *  @addtogroup nrf_crypto_ecc_secp192r1   Definitions specific to secp192r1 (NIST 192-bit)
+ *  @addtogroup nrf_crypto_ecc_secp224r1   Definitions specific to secp224r1 (NIST 224-bit)
+ *  @addtogroup nrf_crypto_ecc_secp256r1   Definitions specific to secp256r1 (NIST 256-bit)
+ *  @addtogroup nrf_crypto_ecc_secp384r1   Definitions specific to secp384r1 (NIST 384-bit)
+ *  @addtogroup nrf_crypto_ecc_secp521r1   Definitions specific to secp521r1 (NIST 521-bit)
+ *  @addtogroup nrf_crypto_ecc_secp160k1   Definitions specific to secp160k1 (Koblitz 160-bit)
+ *  @addtogroup nrf_crypto_ecc_secp192k1   Definitions specific to secp192k1 (Koblitz 192-bit)
+ *  @addtogroup nrf_crypto_ecc_secp224k1   Definitions specific to secp224k1 (Koblitz 224-bit)
+ *  @addtogroup nrf_crypto_ecc_secp256k1   Definitions specific to secp256k1 (Koblitz 256-bit)
+ *  @addtogroup nrf_crypto_ecc_bp256r1     Definitions specific to bp256r1 (Brainpool 256-bit)
+ *  @addtogroup nrf_crypto_ecc_bp384r1     Definitions specific to bp384r1 (Brainpool 384-bit)
+ *  @addtogroup nrf_crypto_ecc_bp512r1     Definitions specific to bp512r1 (Brainpool 512-bit)
+ *  @addtogroup nrf_crypto_ecc_curve25519  Definitions specific to Curve25519
+ *  @addtogroup nrf_crypto_ecc_ed25519     Definitions specific to Ed25519
+ */
+
+#include <stdint.h>
+#include <stddef.h>
+
+#include "nrf_crypto_error.h"
+#include "nrf_crypto_ecc_shared.h"
+#include "nrf_crypto_ecc_backend.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#if defined(__SDK_DOXYGEN__)
+#define NRF_CRYPTO_ECC_SECP160R1_ENABLED  1  /**< @brief Defined as 1 if secp160r1 (NIST 160-bit) is enabled in any of the backends and it is usable in the API, 0 otherwise.    @ingroup nrf_crypto_ecc_secp160r1 */
+#define NRF_CRYPTO_ECC_SECP160R2_ENABLED  1  /**< @brief Defined as 1 if secp160r2 (NIST 160-bit) is enabled in any of the backends and it is usable in the API, 0 otherwise.    @ingroup nrf_crypto_ecc_secp160r2 */
+#define NRF_CRYPTO_ECC_SECP192R1_ENABLED  1  /**< @brief Defined as 1 if secp192r1 (NIST 192-bit) is enabled in any of the backends and it is usable in the API, 0 otherwise.    @ingroup nrf_crypto_ecc_secp192r1 */
+#define NRF_CRYPTO_ECC_SECP224R1_ENABLED  1  /**< @brief Defined as 1 if secp224r1 (NIST 224-bit) is enabled in any of the backends and it is usable in the API, 0 otherwise.    @ingroup nrf_crypto_ecc_secp224r1 */
+#define NRF_CRYPTO_ECC_SECP256R1_ENABLED  1  /**< @brief Defined as 1 if secp256r1 (NIST 256-bit) is enabled in any of the backends and it is usable in the API, 0 otherwise.    @ingroup nrf_crypto_ecc_secp256r1 */
+#define NRF_CRYPTO_ECC_SECP384R1_ENABLED  1  /**< @brief Defined as 1 if secp384r1 (NIST 384-bit) is enabled in any of the backends and it is usable in the API, 0 otherwise.    @ingroup nrf_crypto_ecc_secp384r1 */
+#define NRF_CRYPTO_ECC_SECP521R1_ENABLED  1  /**< @brief Defined as 1 if secp521r1 (NIST 521-bit) is enabled in any of the backends and it is usable in the API, 0 otherwise.    @ingroup nrf_crypto_ecc_secp521r1 */
+#define NRF_CRYPTO_ECC_SECP160K1_ENABLED  1  /**< @brief Defined as 1 if secp160k1 (Koblitz 160-bit) is enabled in any of the backends and it is usable in the API, 0 otherwise. @ingroup nrf_crypto_ecc_secp160k1 */
+#define NRF_CRYPTO_ECC_SECP192K1_ENABLED  1  /**< @brief Defined as 1 if secp192k1 (Koblitz 192-bit) is enabled in any of the backends and it is usable in the API, 0 otherwise. @ingroup nrf_crypto_ecc_secp192k1 */
+#define NRF_CRYPTO_ECC_SECP224K1_ENABLED  1  /**< @brief Defined as 1 if secp224k1 (Koblitz 224-bit) is enabled in any of the backends and it is usable in the API, 0 otherwise. @ingroup nrf_crypto_ecc_secp224k1 */
+#define NRF_CRYPTO_ECC_SECP256K1_ENABLED  1  /**< @brief Defined as 1 if secp256k1 (Koblitz 256-bit) is enabled in any of the backends and it is usable in the API, 0 otherwise. @ingroup nrf_crypto_ecc_secp256k1 */
+#define NRF_CRYPTO_ECC_BP256R1_ENABLED    1  /**< @brief Defined as 1 if bp256r1 (Brainpool 256-bit) is enabled in any of the backends and it is usable in the API, 0 otherwise. @ingroup nrf_crypto_ecc_bp256r1 */
+#define NRF_CRYPTO_ECC_BP384R1_ENABLED    1  /**< @brief Defined as 1 if bp384r1 (Brainpool 384-bit) is enabled in any of the backends and it is usable in the API, 0 otherwise. @ingroup nrf_crypto_ecc_bp384r1 */
+#define NRF_CRYPTO_ECC_BP512R1_ENABLED    1  /**< @brief Defined as 1 if bp512r1 (Brainpool 512-bit) is enabled in any of the backends and it is usable in the API, 0 otherwise. @ingroup nrf_crypto_ecc_bp512r1 */
+#define NRF_CRYPTO_ECC_CURVE25519_ENABLED 1  /**< @brief Defined as 1 if Curve25519 is enabled in any of the backends and it is usable in the API, 0 otherwise.                  @ingroup nrf_crypto_ecc_curve25519 */
+#define NRF_CRYPTO_ECC_ED25519_ENABLED    1  /**< @brief Defined as 1 if Ed25519 is enabled in any of the backends and it is usable in the API, 0 otherwise.                     @ingroup nrf_crypto_ecc_ed25519 */
+#endif
+
+
+#define NRF_CRYPTO_ECC_SECP160R1_RAW_PRIVATE_KEY_SIZE  (160 / 8)      /**< @brief Raw private key size for secp160r1 (NIST 160-bit).         @ingroup nrf_crypto_ecc_secp160r1 */
+#define NRF_CRYPTO_ECC_SECP160R2_RAW_PRIVATE_KEY_SIZE  (160 / 8)      /**< @brief Raw private key size for secp160r2 (NIST 160-bit).         @ingroup nrf_crypto_ecc_secp160r2 */
+#define NRF_CRYPTO_ECC_SECP192R1_RAW_PRIVATE_KEY_SIZE  (192 / 8)      /**< @brief Raw private key size for secp192r1 (NIST 192-bit).         @ingroup nrf_crypto_ecc_secp192r1 */
+#define NRF_CRYPTO_ECC_SECP224R1_RAW_PRIVATE_KEY_SIZE  (224 / 8)      /**< @brief Raw private key size for secp224r1 (NIST 224-bit).         @ingroup nrf_crypto_ecc_secp224r1 */
+#define NRF_CRYPTO_ECC_SECP256R1_RAW_PRIVATE_KEY_SIZE  (256 / 8)      /**< @brief Raw private key size for secp256r1 (NIST 256-bit).         @ingroup nrf_crypto_ecc_secp256r1 */
+#define NRF_CRYPTO_ECC_SECP384R1_RAW_PRIVATE_KEY_SIZE  (384 / 8)      /**< @brief Raw private key size for secp384r1 (NIST 384-bit).         @ingroup nrf_crypto_ecc_secp384r1 */
+#define NRF_CRYPTO_ECC_SECP521R1_RAW_PRIVATE_KEY_SIZE  (528 / 8)      /**< @brief Raw private key size for secp521r1 (NIST 521-bit).         @ingroup nrf_crypto_ecc_secp521r1 */
+#define NRF_CRYPTO_ECC_SECP160K1_RAW_PRIVATE_KEY_SIZE  (160 / 8)      /**< @brief Raw private key size for secp160k1 (Koblitz 160-bit).      @ingroup nrf_crypto_ecc_secp160k1 */
+#define NRF_CRYPTO_ECC_SECP192K1_RAW_PRIVATE_KEY_SIZE  (192 / 8)      /**< @brief Raw private key size for secp192k1 (Koblitz 192-bit).      @ingroup nrf_crypto_ecc_secp192k1 */
+#define NRF_CRYPTO_ECC_SECP224K1_RAW_PRIVATE_KEY_SIZE  (224 / 8)      /**< @brief Raw private key size for secp224k1 (Koblitz 224-bit).      @ingroup nrf_crypto_ecc_secp224k1 */
+#define NRF_CRYPTO_ECC_SECP256K1_RAW_PRIVATE_KEY_SIZE  (256 / 8)      /**< @brief Raw private key size for secp256k1 (Koblitz 256-bit).      @ingroup nrf_crypto_ecc_secp256k1 */
+#define NRF_CRYPTO_ECC_BP256R1_RAW_PRIVATE_KEY_SIZE    (256 / 8)      /**< @brief Raw private key size for bp256r1 (Brainpool 256-bit).      @ingroup nrf_crypto_ecc_bp256r1 */
+#define NRF_CRYPTO_ECC_BP384R1_RAW_PRIVATE_KEY_SIZE    (384 / 8)      /**< @brief Raw private key size for bp384r1 (Brainpool 384-bit).      @ingroup nrf_crypto_ecc_bp384r1 */
+#define NRF_CRYPTO_ECC_BP512R1_RAW_PRIVATE_KEY_SIZE    (512 / 8)      /**< @brief Raw private key size for bp512r1 (Brainpool 512-bit).      @ingroup nrf_crypto_ecc_bp512r1 */
+#define NRF_CRYPTO_ECC_CURVE25519_RAW_PRIVATE_KEY_SIZE (256 / 8)      /**< @brief Raw private key size for Curve25519.                       @ingroup nrf_crypto_ecc_curve25519 */
+#define NRF_CRYPTO_ECC_ED25519_RAW_PRIVATE_KEY_SIZE    (256 / 8)      /**< @brief Raw private key size for Ed25519.                          @ingroup nrf_crypto_ecc_ed25519 */
+
+
+#define NRF_CRYPTO_ECC_SECP160R1_RAW_PUBLIC_KEY_SIZE   (2 * 160 / 8)  /**< @brief Raw public key size for curve secp160r1 (NIST 160-bit).    @ingroup nrf_crypto_ecc_secp160r1 */
+#define NRF_CRYPTO_ECC_SECP160R2_RAW_PUBLIC_KEY_SIZE   (2 * 160 / 8)  /**< @brief Raw public key size for curve secp160r2 (NIST 160-bit).    @ingroup nrf_crypto_ecc_secp160r2 */
+#define NRF_CRYPTO_ECC_SECP192R1_RAW_PUBLIC_KEY_SIZE   (2 * 192 / 8)  /**< @brief Raw public key size for curve secp192r1 (NIST 192-bit).    @ingroup nrf_crypto_ecc_secp192r1 */
+#define NRF_CRYPTO_ECC_SECP224R1_RAW_PUBLIC_KEY_SIZE   (2 * 224 / 8)  /**< @brief Raw public key size for curve secp224r1 (NIST 224-bit).    @ingroup nrf_crypto_ecc_secp224r1 */
+#define NRF_CRYPTO_ECC_SECP256R1_RAW_PUBLIC_KEY_SIZE   (2 * 256 / 8)  /**< @brief Raw public key size for curve secp256r1 (NIST 256-bit).    @ingroup nrf_crypto_ecc_secp256r1 */
+#define NRF_CRYPTO_ECC_SECP384R1_RAW_PUBLIC_KEY_SIZE   (2 * 384 / 8)  /**< @brief Raw public key size for curve secp384r1 (NIST 384-bit).    @ingroup nrf_crypto_ecc_secp384r1 */
+#define NRF_CRYPTO_ECC_SECP521R1_RAW_PUBLIC_KEY_SIZE   (2 * 528 / 8)  /**< @brief Raw public key size for curve secp521r1 (NIST 521-bit).    @ingroup nrf_crypto_ecc_secp521r1 */
+#define NRF_CRYPTO_ECC_SECP160K1_RAW_PUBLIC_KEY_SIZE   (2 * 160 / 8)  /**< @brief Raw public key size for curve secp160k1 (Koblitz 160-bit). @ingroup nrf_crypto_ecc_secp160k1 */
+#define NRF_CRYPTO_ECC_SECP192K1_RAW_PUBLIC_KEY_SIZE   (2 * 192 / 8)  /**< @brief Raw public key size for curve secp192k1 (Koblitz 192-bit). @ingroup nrf_crypto_ecc_secp192k1 */
+#define NRF_CRYPTO_ECC_SECP224K1_RAW_PUBLIC_KEY_SIZE   (2 * 224 / 8)  /**< @brief Raw public key size for curve secp224k1 (Koblitz 224-bit). @ingroup nrf_crypto_ecc_secp224k1 */
+#define NRF_CRYPTO_ECC_SECP256K1_RAW_PUBLIC_KEY_SIZE   (2 * 256 / 8)  /**< @brief Raw public key size for curve secp256k1 (Koblitz 256-bit). @ingroup nrf_crypto_ecc_secp256k1 */
+#define NRF_CRYPTO_ECC_BP256R1_RAW_PUBLIC_KEY_SIZE     (2 * 256 / 8)  /**< @brief Raw public key size for curve bp256r1 (Brainpool 256-bit). @ingroup nrf_crypto_ecc_bp256r1 */
+#define NRF_CRYPTO_ECC_BP384R1_RAW_PUBLIC_KEY_SIZE     (2 * 384 / 8)  /**< @brief Raw public key size for curve bp384r1 (Brainpool 384-bit). @ingroup nrf_crypto_ecc_bp384r1 */
+#define NRF_CRYPTO_ECC_BP512R1_RAW_PUBLIC_KEY_SIZE     (2 * 512 / 8)  /**< @brief Raw public key size for curve bp512r1 (Brainpool 512-bit). @ingroup nrf_crypto_ecc_bp512r1 */
+#define NRF_CRYPTO_ECC_CURVE25519_RAW_PUBLIC_KEY_SIZE  (256 / 8)      /**< @brief Raw public key size for curve Curve25519.                  @ingroup nrf_crypto_ecc_curve25519 */
+#define NRF_CRYPTO_ECC_ED25519_RAW_PUBLIC_KEY_SIZE     (256 / 8)      /**< @brief Raw public key size for curve Ed25519.                     @ingroup nrf_crypto_ecc_ed25519 */
+
+
+#define NRF_CRYPTO_ECC_RAW_PRIVATE_KEY_MAX_SIZE NRF_CRYPTO_BACKEND_ECC_RAW_PRIVATE_KEY_MAX_SIZE  /**< @brief Maximum size of a raw private key for all enabled curves. */
+#define NRF_CRYPTO_ECC_RAW_PUBLIC_KEY_MAX_SIZE  NRF_CRYPTO_BACKEND_ECC_RAW_PUBLIC_KEY_MAX_SIZE   /**< @brief Maximum size of a raw public key for all enabled curves. */
+
+
+/** @brief Defines type of ECC curve.
+ */
+typedef enum
+{
+#if NRF_CRYPTO_ECC_SECP160R1_ENABLED
+    NRF_CRYPTO_ECC_SECP160R1_CURVE_TYPE,   /**< secp160r1 (NIST 160-bit) */
+#endif
+#if NRF_CRYPTO_ECC_SECP160R2_ENABLED
+    NRF_CRYPTO_ECC_SECP160R2_CURVE_TYPE,   /**< secp160r2 (NIST 160-bit) */
+#endif
+#if NRF_CRYPTO_ECC_SECP192R1_ENABLED
+    NRF_CRYPTO_ECC_SECP192R1_CURVE_TYPE,   /**< secp192r1 (NIST 192-bit) */
+#endif
+#if NRF_CRYPTO_ECC_SECP224R1_ENABLED
+    NRF_CRYPTO_ECC_SECP224R1_CURVE_TYPE,   /**< secp224r1 (NIST 224-bit) */
+#endif
+#if NRF_CRYPTO_ECC_SECP256R1_ENABLED
+    NRF_CRYPTO_ECC_SECP256R1_CURVE_TYPE,   /**< secp256r1 (NIST 256-bit) */
+#endif
+#if NRF_CRYPTO_ECC_SECP384R1_ENABLED
+    NRF_CRYPTO_ECC_SECP384R1_CURVE_TYPE,   /**< secp384r1 (NIST 384-bit) */
+#endif
+#if NRF_CRYPTO_ECC_SECP521R1_ENABLED
+    NRF_CRYPTO_ECC_SECP521R1_CURVE_TYPE,   /**< secp521r1 (NIST 521-bit) */
+#endif
+#if NRF_CRYPTO_ECC_SECP160K1_ENABLED
+    NRF_CRYPTO_ECC_SECP160K1_CURVE_TYPE,   /**< secp160k1 (Koblitz 160-bit) */
+#endif
+#if NRF_CRYPTO_ECC_SECP192K1_ENABLED
+    NRF_CRYPTO_ECC_SECP192K1_CURVE_TYPE,   /**< secp192k1 (Koblitz 192-bit) */
+#endif
+#if NRF_CRYPTO_ECC_SECP224K1_ENABLED
+    NRF_CRYPTO_ECC_SECP224K1_CURVE_TYPE,   /**< secp224k1 (Koblitz 224-bit) */
+#endif
+#if NRF_CRYPTO_ECC_SECP256K1_ENABLED
+    NRF_CRYPTO_ECC_SECP256K1_CURVE_TYPE,   /**< secp256k1 (Koblitz 256-bit) */
+#endif
+#if NRF_CRYPTO_ECC_BP256R1_ENABLED
+    NRF_CRYPTO_ECC_BP256R1_CURVE_TYPE,     /**< bp256r1 (Brainpool 256-bit) */
+#endif
+#if NRF_CRYPTO_ECC_BP384R1_ENABLED
+    NRF_CRYPTO_ECC_BP384R1_CURVE_TYPE,     /**< bp384r1 (Brainpool 384-bit) */
+#endif
+#if NRF_CRYPTO_ECC_BP512R1_ENABLED
+    NRF_CRYPTO_ECC_BP512R1_CURVE_TYPE,     /**< bp512r1 (Brainpool 512-bit) */
+#endif
+#if NRF_CRYPTO_ECC_CURVE25519_ENABLED
+    NRF_CRYPTO_ECC_CURVE25519_CURVE_TYPE,  /**< Curve25519 */
+#endif
+#if NRF_CRYPTO_ECC_ED25519_ENABLED
+    NRF_CRYPTO_ECC_ED25519_CURVE_TYPE,     /**< Ed25519 */
+#endif
+#if !NRF_CRYPTO_ECC_SECP160R1_ENABLED
+    NRF_CRYPTO_ECC_SECP160R1_CURVE_TYPE,   /**< secp160r1 (NIST 160-bit) */
+#endif
+#if !NRF_CRYPTO_ECC_SECP160R2_ENABLED
+    NRF_CRYPTO_ECC_SECP160R2_CURVE_TYPE,   /**< secp160r2 (NIST 160-bit) */
+#endif
+#if !NRF_CRYPTO_ECC_SECP192R1_ENABLED
+    NRF_CRYPTO_ECC_SECP192R1_CURVE_TYPE,   /**< secp192r1 (NIST 192-bit) */
+#endif
+#if !NRF_CRYPTO_ECC_SECP224R1_ENABLED
+    NRF_CRYPTO_ECC_SECP224R1_CURVE_TYPE,   /**< secp224r1 (NIST 224-bit) */
+#endif
+#if !NRF_CRYPTO_ECC_SECP256R1_ENABLED
+    NRF_CRYPTO_ECC_SECP256R1_CURVE_TYPE,   /**< secp256r1 (NIST 256-bit) */
+#endif
+#if !NRF_CRYPTO_ECC_SECP384R1_ENABLED
+    NRF_CRYPTO_ECC_SECP384R1_CURVE_TYPE,   /**< secp384r1 (NIST 384-bit) */
+#endif
+#if !NRF_CRYPTO_ECC_SECP521R1_ENABLED
+    NRF_CRYPTO_ECC_SECP521R1_CURVE_TYPE,   /**< secp521r1 (NIST 521-bit) */
+#endif
+#if !NRF_CRYPTO_ECC_SECP160K1_ENABLED
+    NRF_CRYPTO_ECC_SECP160K1_CURVE_TYPE,   /**< secp160k1 (Koblitz 160-bit) */
+#endif
+#if !NRF_CRYPTO_ECC_SECP192K1_ENABLED
+    NRF_CRYPTO_ECC_SECP192K1_CURVE_TYPE,   /**< secp192k1 (Koblitz 192-bit) */
+#endif
+#if !NRF_CRYPTO_ECC_SECP224K1_ENABLED
+    NRF_CRYPTO_ECC_SECP224K1_CURVE_TYPE,   /**< secp224k1 (Koblitz 224-bit) */
+#endif
+#if !NRF_CRYPTO_ECC_SECP256K1_ENABLED
+    NRF_CRYPTO_ECC_SECP256K1_CURVE_TYPE,   /**< secp256k1 (Koblitz 256-bit) */
+#endif
+#if !NRF_CRYPTO_ECC_BP256R1_ENABLED
+    NRF_CRYPTO_ECC_BP256R1_CURVE_TYPE,     /**< bp256r1 (Brainpool 256-bit) */
+#endif
+#if !NRF_CRYPTO_ECC_BP384R1_ENABLED
+    NRF_CRYPTO_ECC_BP384R1_CURVE_TYPE,     /**< bp384r1 (Brainpool 384-bit) */
+#endif
+#if !NRF_CRYPTO_ECC_BP512R1_ENABLED
+    NRF_CRYPTO_ECC_BP512R1_CURVE_TYPE,     /**< bp512r1 (Brainpool 512-bit) */
+#endif
+#if !NRF_CRYPTO_ECC_CURVE25519_ENABLED
+    NRF_CRYPTO_ECC_CURVE25519_CURVE_TYPE,  /**< Curve25519 */
+#endif
+#if !NRF_CRYPTO_ECC_ED25519_ENABLED
+    NRF_CRYPTO_ECC_ED25519_CURVE_TYPE,     /**< Ed25519 */
+#endif
+} nrf_crypto_ecc_curve_type_t;
+
+
+/** @brief Structure holding information on a specific curve.
+ *
+ *  @note This structure cannot be used to create a new variable. Only the variables defined by this
+ *  library can be used, e.g. @ref g_nrf_crypto_ecc_secp256r1_curve_info.
+ */
+typedef struct nrf_crypto_ecc_curve_info_s
+{
+    uint16_t                    public_key_size;       /**< @brief Size of a structure holding internal public key. */
+    uint16_t                    private_key_size;      /**< @brief Size of a structure holding internal private key. */
+    nrf_crypto_ecc_curve_type_t curve_type;            /**< @brief Type of the curve. */
+    uint8_t                     raw_private_key_size;  /**< @brief Size of a buffer containing raw private key. */
+    uint8_t                     raw_public_key_size;   /**< @brief Size of a buffer containing raw public key. */
+    void *                      p_backend_data;        /**< @brief Field to hold backend specific internal data. */
+} nrf_crypto_ecc_curve_info_t;
+
+
+/** @addtogroup nrf_crypto_ecc_secp160r1
+ *  @{ */
+
+typedef nrf_crypto_backend_secp160r1_key_pair_generate_context_t
+    nrf_crypto_ecc_secp160r1_key_pair_generate_context_t;            /**< @brief Context structure for key generation using secp160r1 (NIST 160-bit). */
+typedef nrf_crypto_backend_secp160r1_public_key_calculate_context_t
+    nrf_crypto_ecc_secp160r1_public_key_calculate_context_t;         /**< @brief Context structure for public key calculation using secp160r1 (NIST 160-bit). */
+typedef nrf_crypto_backend_secp160r1_private_key_t
+    nrf_crypto_ecc_secp160r1_private_key_t;                          /**< @brief Structure holding internal representation of a private key for secp160r1 (NIST 160-bit) */
+typedef nrf_crypto_backend_secp160r1_public_key_t
+    nrf_crypto_ecc_secp160r1_public_key_t;                           /**< @brief Structure holding internal representation of a public key for secp160r1 (NIST 160-bit) */
+typedef uint8_t nrf_crypto_ecc_secp160r1_raw_private_key_t
+    [NRF_CRYPTO_ECC_SECP160R1_RAW_PRIVATE_KEY_SIZE];                 /**< @brief Array holding raw private key for secp160r1 (NIST 160-bit) */
+typedef uint8_t nrf_crypto_ecc_secp160r1_raw_public_key_t
+    [NRF_CRYPTO_ECC_SECP160R1_RAW_PUBLIC_KEY_SIZE];                  /**< @brief Array holding raw public key for secp160r1 (NIST 160-bit) */
+
+
+#if NRF_CRYPTO_ECC_SECP160R1_ENABLED
+
+/** @brief Variable containing information on secp160r1 (NIST 160-bit).
+ *
+ *  It can be used as a parameter for the functions creating secp160r1 (NIST 160-bit) keys.
+ */
+extern const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp160r1_curve_info;
+
+#endif
+
+/** @} */
+
+
+/** @addtogroup nrf_crypto_ecc_secp160r2
+ *  @{ */
+
+typedef nrf_crypto_backend_secp160r2_key_pair_generate_context_t
+    nrf_crypto_ecc_secp160r2_key_pair_generate_context_t;            /**< @brief Context structure for key generation using secp160r2 (NIST 160-bit). */
+typedef nrf_crypto_backend_secp160r2_public_key_calculate_context_t
+    nrf_crypto_ecc_secp160r2_public_key_calculate_context_t;         /**< @brief Context structure for public key calculation using secp160r2 (NIST 160-bit). */
+typedef nrf_crypto_backend_secp160r2_private_key_t
+    nrf_crypto_ecc_secp160r2_private_key_t;                          /**< @brief Structure holding internal representation of a private key for secp160r2 (NIST 160-bit) */
+typedef nrf_crypto_backend_secp160r2_public_key_t
+    nrf_crypto_ecc_secp160r2_public_key_t;                           /**< @brief Structure holding internal representation of a public key for secp160r2 (NIST 160-bit) */
+typedef uint8_t nrf_crypto_ecc_secp160r2_raw_private_key_t
+    [NRF_CRYPTO_ECC_SECP160R2_RAW_PRIVATE_KEY_SIZE];                 /**< @brief Array holding raw private key for secp160r2 (NIST 160-bit) */
+typedef uint8_t nrf_crypto_ecc_secp160r2_raw_public_key_t
+    [NRF_CRYPTO_ECC_SECP160R2_RAW_PUBLIC_KEY_SIZE];                  /**< @brief Array holding raw public key for secp160r2 (NIST 160-bit) */
+
+
+#if NRF_CRYPTO_ECC_SECP160R2_ENABLED
+
+/** @brief Variable containing information on secp160r2 (NIST 160-bit).
+ *
+ *  It can be used as a parameter for the functions creating secp160r2 (NIST 160-bit) keys.
+ */
+extern const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp160r2_curve_info;
+
+#endif
+
+/** @} */
+
+
+/** @addtogroup nrf_crypto_ecc_secp192r1
+ *  @{ */
+
+typedef nrf_crypto_backend_secp192r1_key_pair_generate_context_t
+    nrf_crypto_ecc_secp192r1_key_pair_generate_context_t;            /**< @brief Context structure for key generation using secp192r1 (NIST 192-bit). */
+typedef nrf_crypto_backend_secp192r1_public_key_calculate_context_t
+    nrf_crypto_ecc_secp192r1_public_key_calculate_context_t;         /**< @brief Context structure for public key calculation using secp192r1 (NIST 192-bit). */
+typedef nrf_crypto_backend_secp192r1_private_key_t
+    nrf_crypto_ecc_secp192r1_private_key_t;                          /**< @brief Structure holding internal representation of a private key for secp192r1 (NIST 192-bit) */
+typedef nrf_crypto_backend_secp192r1_public_key_t
+    nrf_crypto_ecc_secp192r1_public_key_t;                           /**< @brief Structure holding internal representation of a public key for secp192r1 (NIST 192-bit) */
+typedef uint8_t nrf_crypto_ecc_secp192r1_raw_private_key_t
+    [NRF_CRYPTO_ECC_SECP192R1_RAW_PRIVATE_KEY_SIZE];                 /**< @brief Array holding raw private key for secp192r1 (NIST 192-bit) */
+typedef uint8_t nrf_crypto_ecc_secp192r1_raw_public_key_t
+    [NRF_CRYPTO_ECC_SECP192R1_RAW_PUBLIC_KEY_SIZE];                  /**< @brief Array holding raw public key for secp192r1 (NIST 192-bit) */
+
+
+#if NRF_CRYPTO_ECC_SECP192R1_ENABLED
+
+/** @brief Variable containing information on secp192r1 (NIST 192-bit).
+ *
+ *  It can be used as a parameter for the functions creating secp192r1 (NIST 192-bit) keys.
+ */
+extern const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp192r1_curve_info;
+
+#endif
+
+/** @} */
+
+
+/** @addtogroup nrf_crypto_ecc_secp224r1
+ *  @{ */
+
+typedef nrf_crypto_backend_secp224r1_key_pair_generate_context_t
+    nrf_crypto_ecc_secp224r1_key_pair_generate_context_t;            /**< @brief Context structure for key generation using secp224r1 (NIST 224-bit). */
+typedef nrf_crypto_backend_secp224r1_public_key_calculate_context_t
+    nrf_crypto_ecc_secp224r1_public_key_calculate_context_t;         /**< @brief Context structure for public key calculation using secp224r1 (NIST 224-bit). */
+typedef nrf_crypto_backend_secp224r1_private_key_t
+    nrf_crypto_ecc_secp224r1_private_key_t;                          /**< @brief Structure holding internal representation of a private key for secp224r1 (NIST 224-bit) */
+typedef nrf_crypto_backend_secp224r1_public_key_t
+    nrf_crypto_ecc_secp224r1_public_key_t;                           /**< @brief Structure holding internal representation of a public key for secp224r1 (NIST 224-bit) */
+typedef uint8_t nrf_crypto_ecc_secp224r1_raw_private_key_t
+    [NRF_CRYPTO_ECC_SECP224R1_RAW_PRIVATE_KEY_SIZE];                 /**< @brief Array holding raw private key for secp224r1 (NIST 224-bit) */
+typedef uint8_t nrf_crypto_ecc_secp224r1_raw_public_key_t
+    [NRF_CRYPTO_ECC_SECP224R1_RAW_PUBLIC_KEY_SIZE];                  /**< @brief Array holding raw public key for secp224r1 (NIST 224-bit) */
+
+
+#if NRF_CRYPTO_ECC_SECP224R1_ENABLED
+
+/** @brief Variable containing information on secp224r1 (NIST 224-bit).
+ *
+ *  It can be used as a parameter for the functions creating secp224r1 (NIST 224-bit) keys.
+ */
+extern const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp224r1_curve_info;
+
+#endif
+
+/** @} */
+
+
+/** @addtogroup nrf_crypto_ecc_secp256r1
+ *  @{ */
+
+typedef nrf_crypto_backend_secp256r1_key_pair_generate_context_t
+    nrf_crypto_ecc_secp256r1_key_pair_generate_context_t;            /**< @brief Context structure for key generation using secp256r1 (NIST 256-bit). */
+typedef nrf_crypto_backend_secp256r1_public_key_calculate_context_t
+    nrf_crypto_ecc_secp256r1_public_key_calculate_context_t;         /**< @brief Context structure for public key calculation using secp256r1 (NIST 256-bit). */
+typedef nrf_crypto_backend_secp256r1_private_key_t
+    nrf_crypto_ecc_secp256r1_private_key_t;                          /**< @brief Structure holding internal representation of a private key for secp256r1 (NIST 256-bit) */
+typedef nrf_crypto_backend_secp256r1_public_key_t
+    nrf_crypto_ecc_secp256r1_public_key_t;                           /**< @brief Structure holding internal representation of a public key for secp256r1 (NIST 256-bit) */
+typedef uint8_t nrf_crypto_ecc_secp256r1_raw_private_key_t
+    [NRF_CRYPTO_ECC_SECP256R1_RAW_PRIVATE_KEY_SIZE];                 /**< @brief Array holding raw private key for secp256r1 (NIST 256-bit) */
+typedef uint8_t nrf_crypto_ecc_secp256r1_raw_public_key_t
+    [NRF_CRYPTO_ECC_SECP256R1_RAW_PUBLIC_KEY_SIZE];                  /**< @brief Array holding raw public key for secp256r1 (NIST 256-bit) */
+
+
+#if NRF_CRYPTO_ECC_SECP256R1_ENABLED
+
+/** @brief Variable containing information on secp256r1 (NIST 256-bit).
+ *
+ *  It can be used as a parameter for the functions creating secp256r1 (NIST 256-bit) keys.
+ */
+extern const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp256r1_curve_info;
+
+#endif
+
+/** @} */
+
+
+/** @addtogroup nrf_crypto_ecc_secp384r1
+ *  @{ */
+
+typedef nrf_crypto_backend_secp384r1_key_pair_generate_context_t
+    nrf_crypto_ecc_secp384r1_key_pair_generate_context_t;            /**< @brief Context structure for key generation using secp384r1 (NIST 384-bit). */
+typedef nrf_crypto_backend_secp384r1_public_key_calculate_context_t
+    nrf_crypto_ecc_secp384r1_public_key_calculate_context_t;         /**< @brief Context structure for public key calculation using secp384r1 (NIST 384-bit). */
+typedef nrf_crypto_backend_secp384r1_private_key_t
+    nrf_crypto_ecc_secp384r1_private_key_t;                          /**< @brief Structure holding internal representation of a private key for secp384r1 (NIST 384-bit) */
+typedef nrf_crypto_backend_secp384r1_public_key_t
+    nrf_crypto_ecc_secp384r1_public_key_t;                           /**< @brief Structure holding internal representation of a public key for secp384r1 (NIST 384-bit) */
+typedef uint8_t nrf_crypto_ecc_secp384r1_raw_private_key_t
+    [NRF_CRYPTO_ECC_SECP384R1_RAW_PRIVATE_KEY_SIZE];                 /**< @brief Array holding raw private key for secp384r1 (NIST 384-bit) */
+typedef uint8_t nrf_crypto_ecc_secp384r1_raw_public_key_t
+    [NRF_CRYPTO_ECC_SECP384R1_RAW_PUBLIC_KEY_SIZE];                  /**< @brief Array holding raw public key for secp384r1 (NIST 384-bit) */
+
+
+#if NRF_CRYPTO_ECC_SECP384R1_ENABLED
+
+/** @brief Variable containing information on secp384r1 (NIST 384-bit).
+ *
+ *  It can be used as a parameter for the functions creating secp384r1 (NIST 384-bit) keys.
+ */
+extern const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp384r1_curve_info;
+
+#endif
+
+/** @} */
+
+
+/** @addtogroup nrf_crypto_ecc_secp521r1
+ *  @{ */
+
+typedef nrf_crypto_backend_secp521r1_key_pair_generate_context_t
+    nrf_crypto_ecc_secp521r1_key_pair_generate_context_t;            /**< @brief Context structure for key generation using secp521r1 (NIST 521-bit). */
+typedef nrf_crypto_backend_secp521r1_public_key_calculate_context_t
+    nrf_crypto_ecc_secp521r1_public_key_calculate_context_t;         /**< @brief Context structure for public key calculation using secp521r1 (NIST 521-bit). */
+typedef nrf_crypto_backend_secp521r1_private_key_t
+    nrf_crypto_ecc_secp521r1_private_key_t;                          /**< @brief Structure holding internal representation of a private key for secp521r1 (NIST 521-bit) */
+typedef nrf_crypto_backend_secp521r1_public_key_t
+    nrf_crypto_ecc_secp521r1_public_key_t;                           /**< @brief Structure holding internal representation of a public key for secp521r1 (NIST 521-bit) */
+typedef uint8_t nrf_crypto_ecc_secp521r1_raw_private_key_t
+    [NRF_CRYPTO_ECC_SECP521R1_RAW_PRIVATE_KEY_SIZE];                 /**< @brief Array holding raw private key for secp521r1 (NIST 521-bit) */
+typedef uint8_t nrf_crypto_ecc_secp521r1_raw_public_key_t
+    [NRF_CRYPTO_ECC_SECP521R1_RAW_PUBLIC_KEY_SIZE];                  /**< @brief Array holding raw public key for secp521r1 (NIST 521-bit) */
+
+
+#if NRF_CRYPTO_ECC_SECP521R1_ENABLED
+
+/** @brief Variable containing information on secp521r1 (NIST 521-bit).
+ *
+ *  It can be used as a parameter for the functions creating secp521r1 (NIST 521-bit) keys.
+ */
+extern const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp521r1_curve_info;
+
+#endif
+
+/** @} */
+
+
+/** @addtogroup nrf_crypto_ecc_secp160k1
+ *  @{ */
+
+typedef nrf_crypto_backend_secp160k1_key_pair_generate_context_t
+    nrf_crypto_ecc_secp160k1_key_pair_generate_context_t;            /**< @brief Context structure for key generation using secp160k1 (Koblitz 160-bit). */
+typedef nrf_crypto_backend_secp160k1_public_key_calculate_context_t
+    nrf_crypto_ecc_secp160k1_public_key_calculate_context_t;         /**< @brief Context structure for public key calculation using secp160k1 (Koblitz 160-bit). */
+typedef nrf_crypto_backend_secp160k1_private_key_t
+    nrf_crypto_ecc_secp160k1_private_key_t;                          /**< @brief Structure holding internal representation of a private key for secp160k1 (Koblitz 160-bit) */
+typedef nrf_crypto_backend_secp160k1_public_key_t
+    nrf_crypto_ecc_secp160k1_public_key_t;                           /**< @brief Structure holding internal representation of a public key for secp160k1 (Koblitz 160-bit) */
+typedef uint8_t nrf_crypto_ecc_secp160k1_raw_private_key_t
+    [NRF_CRYPTO_ECC_SECP160K1_RAW_PRIVATE_KEY_SIZE];                 /**< @brief Array holding raw private key for secp160k1 (Koblitz 160-bit) */
+typedef uint8_t nrf_crypto_ecc_secp160k1_raw_public_key_t
+    [NRF_CRYPTO_ECC_SECP160K1_RAW_PUBLIC_KEY_SIZE];                  /**< @brief Array holding raw public key for secp160k1 (Koblitz 160-bit) */
+
+
+#if NRF_CRYPTO_ECC_SECP160K1_ENABLED
+
+/** @brief Variable containing information on secp160k1 (Koblitz 160-bit).
+ *
+ *  It can be used as a parameter for the functions creating secp160k1 (Koblitz 160-bit) keys.
+ */
+extern const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp160k1_curve_info;
+
+#endif
+
+/** @} */
+
+
+/** @addtogroup nrf_crypto_ecc_secp192k1
+ *  @{ */
+
+typedef nrf_crypto_backend_secp192k1_key_pair_generate_context_t
+    nrf_crypto_ecc_secp192k1_key_pair_generate_context_t;            /**< @brief Context structure for key generation using secp192k1 (Koblitz 192-bit). */
+typedef nrf_crypto_backend_secp192k1_public_key_calculate_context_t
+    nrf_crypto_ecc_secp192k1_public_key_calculate_context_t;         /**< @brief Context structure for public key calculation using secp192k1 (Koblitz 192-bit). */
+typedef nrf_crypto_backend_secp192k1_private_key_t
+    nrf_crypto_ecc_secp192k1_private_key_t;                          /**< @brief Structure holding internal representation of a private key for secp192k1 (Koblitz 192-bit) */
+typedef nrf_crypto_backend_secp192k1_public_key_t
+    nrf_crypto_ecc_secp192k1_public_key_t;                           /**< @brief Structure holding internal representation of a public key for secp192k1 (Koblitz 192-bit) */
+typedef uint8_t nrf_crypto_ecc_secp192k1_raw_private_key_t
+    [NRF_CRYPTO_ECC_SECP192K1_RAW_PRIVATE_KEY_SIZE];                 /**< @brief Array holding raw private key for secp192k1 (Koblitz 192-bit) */
+typedef uint8_t nrf_crypto_ecc_secp192k1_raw_public_key_t
+    [NRF_CRYPTO_ECC_SECP192K1_RAW_PUBLIC_KEY_SIZE];                  /**< @brief Array holding raw public key for secp192k1 (Koblitz 192-bit) */
+
+
+#if NRF_CRYPTO_ECC_SECP192K1_ENABLED
+
+/** @brief Variable containing information on secp192k1 (Koblitz 192-bit).
+ *
+ *  It can be used as a parameter for the functions creating secp192k1 (Koblitz 192-bit) keys.
+ */
+extern const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp192k1_curve_info;
+
+#endif
+
+/** @} */
+
+
+/** @addtogroup nrf_crypto_ecc_secp224k1
+ *  @{ */
+
+typedef nrf_crypto_backend_secp224k1_key_pair_generate_context_t
+    nrf_crypto_ecc_secp224k1_key_pair_generate_context_t;            /**< @brief Context structure for key generation using secp224k1 (Koblitz 224-bit). */
+typedef nrf_crypto_backend_secp224k1_public_key_calculate_context_t
+    nrf_crypto_ecc_secp224k1_public_key_calculate_context_t;         /**< @brief Context structure for public key calculation using secp224k1 (Koblitz 224-bit). */
+typedef nrf_crypto_backend_secp224k1_private_key_t
+    nrf_crypto_ecc_secp224k1_private_key_t;                          /**< @brief Structure holding internal representation of a private key for secp224k1 (Koblitz 224-bit) */
+typedef nrf_crypto_backend_secp224k1_public_key_t
+    nrf_crypto_ecc_secp224k1_public_key_t;                           /**< @brief Structure holding internal representation of a public key for secp224k1 (Koblitz 224-bit) */
+typedef uint8_t nrf_crypto_ecc_secp224k1_raw_private_key_t
+    [NRF_CRYPTO_ECC_SECP224K1_RAW_PRIVATE_KEY_SIZE];                 /**< @brief Array holding raw private key for secp224k1 (Koblitz 224-bit) */
+typedef uint8_t nrf_crypto_ecc_secp224k1_raw_public_key_t
+    [NRF_CRYPTO_ECC_SECP224K1_RAW_PUBLIC_KEY_SIZE];                  /**< @brief Array holding raw public key for secp224k1 (Koblitz 224-bit) */
+
+
+#if NRF_CRYPTO_ECC_SECP224K1_ENABLED
+
+/** @brief Variable containing information on secp224k1 (Koblitz 224-bit).
+ *
+ *  It can be used as a parameter for the functions creating secp224k1 (Koblitz 224-bit) keys.
+ */
+extern const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp224k1_curve_info;
+
+#endif
+
+/** @} */
+
+
+/** @addtogroup nrf_crypto_ecc_secp256k1
+ *  @{ */
+
+typedef nrf_crypto_backend_secp256k1_key_pair_generate_context_t
+    nrf_crypto_ecc_secp256k1_key_pair_generate_context_t;            /**< @brief Context structure for key generation using secp256k1 (Koblitz 256-bit). */
+typedef nrf_crypto_backend_secp256k1_public_key_calculate_context_t
+    nrf_crypto_ecc_secp256k1_public_key_calculate_context_t;         /**< @brief Context structure for public key calculation using secp256k1 (Koblitz 256-bit). */
+typedef nrf_crypto_backend_secp256k1_private_key_t
+    nrf_crypto_ecc_secp256k1_private_key_t;                          /**< @brief Structure holding internal representation of a private key for secp256k1 (Koblitz 256-bit) */
+typedef nrf_crypto_backend_secp256k1_public_key_t
+    nrf_crypto_ecc_secp256k1_public_key_t;                           /**< @brief Structure holding internal representation of a public key for secp256k1 (Koblitz 256-bit) */
+typedef uint8_t nrf_crypto_ecc_secp256k1_raw_private_key_t
+    [NRF_CRYPTO_ECC_SECP256K1_RAW_PRIVATE_KEY_SIZE];                 /**< @brief Array holding raw private key for secp256k1 (Koblitz 256-bit) */
+typedef uint8_t nrf_crypto_ecc_secp256k1_raw_public_key_t
+    [NRF_CRYPTO_ECC_SECP256K1_RAW_PUBLIC_KEY_SIZE];                  /**< @brief Array holding raw public key for secp256k1 (Koblitz 256-bit) */
+
+
+#if NRF_CRYPTO_ECC_SECP256K1_ENABLED
+
+/** @brief Variable containing information on secp256k1 (Koblitz 256-bit).
+ *
+ *  It can be used as a parameter for the functions creating secp256k1 (Koblitz 256-bit) keys.
+ */
+extern const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp256k1_curve_info;
+
+#endif
+
+/** @} */
+
+
+/** @addtogroup nrf_crypto_ecc_bp256r1
+ *  @{ */
+
+typedef nrf_crypto_backend_bp256r1_key_pair_generate_context_t
+    nrf_crypto_ecc_bp256r1_key_pair_generate_context_t;              /**< @brief Context structure for key generation using bp256r1 (Brainpool 256-bit). */
+typedef nrf_crypto_backend_bp256r1_public_key_calculate_context_t
+    nrf_crypto_ecc_bp256r1_public_key_calculate_context_t;           /**< @brief Context structure for public key calculation using bp256r1 (Brainpool 256-bit). */
+typedef nrf_crypto_backend_bp256r1_private_key_t
+    nrf_crypto_ecc_bp256r1_private_key_t;                            /**< @brief Structure holding internal representation of a private key for bp256r1 (Brainpool 256-bit) */
+typedef nrf_crypto_backend_bp256r1_public_key_t
+    nrf_crypto_ecc_bp256r1_public_key_t;                             /**< @brief Structure holding internal representation of a public key for bp256r1 (Brainpool 256-bit) */
+typedef uint8_t nrf_crypto_ecc_bp256r1_raw_private_key_t
+    [NRF_CRYPTO_ECC_BP256R1_RAW_PRIVATE_KEY_SIZE];                   /**< @brief Array holding raw private key for bp256r1 (Brainpool 256-bit) */
+typedef uint8_t nrf_crypto_ecc_bp256r1_raw_public_key_t
+    [NRF_CRYPTO_ECC_BP256R1_RAW_PUBLIC_KEY_SIZE];                    /**< @brief Array holding raw public key for bp256r1 (Brainpool 256-bit) */
+
+
+#if NRF_CRYPTO_ECC_BP256R1_ENABLED
+
+/** @brief Variable containing information on bp256r1 (Brainpool 256-bit).
+ *
+ *  It can be used as a parameter for the functions creating bp256r1 (Brainpool 256-bit) keys.
+ */
+extern const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_bp256r1_curve_info;
+
+#endif
+
+/** @} */
+
+
+/** @addtogroup nrf_crypto_ecc_bp384r1
+ *  @{ */
+
+typedef nrf_crypto_backend_bp384r1_key_pair_generate_context_t
+    nrf_crypto_ecc_bp384r1_key_pair_generate_context_t;              /**< @brief Context structure for key generation using bp384r1 (Brainpool 384-bit). */
+typedef nrf_crypto_backend_bp384r1_public_key_calculate_context_t
+    nrf_crypto_ecc_bp384r1_public_key_calculate_context_t;           /**< @brief Context structure for public key calculation using bp384r1 (Brainpool 384-bit). */
+typedef nrf_crypto_backend_bp384r1_private_key_t
+    nrf_crypto_ecc_bp384r1_private_key_t;                            /**< @brief Structure holding internal representation of a private key for bp384r1 (Brainpool 384-bit) */
+typedef nrf_crypto_backend_bp384r1_public_key_t
+    nrf_crypto_ecc_bp384r1_public_key_t;                             /**< @brief Structure holding internal representation of a public key for bp384r1 (Brainpool 384-bit) */
+typedef uint8_t nrf_crypto_ecc_bp384r1_raw_private_key_t
+    [NRF_CRYPTO_ECC_BP384R1_RAW_PRIVATE_KEY_SIZE];                   /**< @brief Array holding raw private key for bp384r1 (Brainpool 384-bit) */
+typedef uint8_t nrf_crypto_ecc_bp384r1_raw_public_key_t
+    [NRF_CRYPTO_ECC_BP384R1_RAW_PUBLIC_KEY_SIZE];                    /**< @brief Array holding raw public key for bp384r1 (Brainpool 384-bit) */
+
+
+#if NRF_CRYPTO_ECC_BP384R1_ENABLED
+
+/** @brief Variable containing information on bp384r1 (Brainpool 384-bit).
+ *
+ *  It can be used as a parameter for the functions creating bp384r1 (Brainpool 384-bit) keys.
+ */
+extern const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_bp384r1_curve_info;
+
+#endif
+
+/** @} */
+
+
+/** @addtogroup nrf_crypto_ecc_bp512r1
+ *  @{ */
+
+typedef nrf_crypto_backend_bp512r1_key_pair_generate_context_t
+    nrf_crypto_ecc_bp512r1_key_pair_generate_context_t;              /**< @brief Context structure for key generation using bp512r1 (Brainpool 512-bit). */
+typedef nrf_crypto_backend_bp512r1_public_key_calculate_context_t
+    nrf_crypto_ecc_bp512r1_public_key_calculate_context_t;           /**< @brief Context structure for public key calculation using bp512r1 (Brainpool 512-bit). */
+typedef nrf_crypto_backend_bp512r1_private_key_t
+    nrf_crypto_ecc_bp512r1_private_key_t;                            /**< @brief Structure holding internal representation of a private key for bp512r1 (Brainpool 512-bit) */
+typedef nrf_crypto_backend_bp512r1_public_key_t
+    nrf_crypto_ecc_bp512r1_public_key_t;                             /**< @brief Structure holding internal representation of a public key for bp512r1 (Brainpool 512-bit) */
+typedef uint8_t nrf_crypto_ecc_bp512r1_raw_private_key_t
+    [NRF_CRYPTO_ECC_BP512R1_RAW_PRIVATE_KEY_SIZE];                   /**< @brief Array holding raw private key for bp512r1 (Brainpool 512-bit) */
+typedef uint8_t nrf_crypto_ecc_bp512r1_raw_public_key_t
+    [NRF_CRYPTO_ECC_BP512R1_RAW_PUBLIC_KEY_SIZE];                    /**< @brief Array holding raw public key for bp512r1 (Brainpool 512-bit) */
+
+
+#if NRF_CRYPTO_ECC_BP512R1_ENABLED
+
+/** @brief Variable containing information on bp512r1 (Brainpool 512-bit).
+ *
+ *  It can be used as a parameter for the functions creating bp512r1 (Brainpool 512-bit) keys.
+ */
+extern const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_bp512r1_curve_info;
+
+#endif
+
+/** @} */
+
+
+/** @addtogroup nrf_crypto_ecc_curve25519
+ *  @{ */
+
+typedef nrf_crypto_backend_curve25519_key_pair_generate_context_t
+    nrf_crypto_ecc_curve25519_key_pair_generate_context_t;           /**< @brief Context structure for key generation using Curve25519. */
+typedef nrf_crypto_backend_curve25519_public_key_calculate_context_t
+    nrf_crypto_ecc_curve25519_public_key_calculate_context_t;        /**< @brief Context structure for public key calculation using Curve25519. */
+typedef nrf_crypto_backend_curve25519_private_key_t
+    nrf_crypto_ecc_curve25519_private_key_t;                         /**< @brief Structure holding internal representation of a private key for Curve25519 */
+typedef nrf_crypto_backend_curve25519_public_key_t
+    nrf_crypto_ecc_curve25519_public_key_t;                          /**< @brief Structure holding internal representation of a public key for Curve25519 */
+typedef uint8_t nrf_crypto_ecc_curve25519_raw_private_key_t
+    [NRF_CRYPTO_ECC_CURVE25519_RAW_PRIVATE_KEY_SIZE];                /**< @brief Array holding raw private key for Curve25519 */
+typedef uint8_t nrf_crypto_ecc_curve25519_raw_public_key_t
+    [NRF_CRYPTO_ECC_CURVE25519_RAW_PUBLIC_KEY_SIZE];                 /**< @brief Array holding raw public key for Curve25519 */
+
+
+#if NRF_CRYPTO_ECC_CURVE25519_ENABLED
+
+/** @brief Variable containing information on Curve25519.
+ *
+ *  It can be used as a parameter for the functions creating Curve25519 keys.
+ */
+extern const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_curve25519_curve_info;
+
+#endif
+
+/** @} */
+
+
+/** @addtogroup nrf_crypto_ecc_ed25519
+ *  @{ */
+
+typedef nrf_crypto_backend_ed25519_key_pair_generate_context_t
+    nrf_crypto_ecc_ed25519_key_pair_generate_context_t;              /**< @brief Context structure for key generation using Ed25519. */
+typedef nrf_crypto_backend_ed25519_public_key_calculate_context_t
+    nrf_crypto_ecc_ed25519_public_key_calculate_context_t;           /**< @brief Context structure for public key calculation using Ed25519. */
+typedef nrf_crypto_backend_ed25519_private_key_t
+    nrf_crypto_ecc_ed25519_private_key_t;                            /**< @brief Structure holding internal representation of a private key for Ed25519 */
+typedef nrf_crypto_backend_ed25519_public_key_t
+    nrf_crypto_ecc_ed25519_public_key_t;                             /**< @brief Structure holding internal representation of a public key for Ed25519 */
+typedef uint8_t nrf_crypto_ecc_ed25519_raw_private_key_t
+    [NRF_CRYPTO_ECC_ED25519_RAW_PRIVATE_KEY_SIZE];                   /**< @brief Array holding raw private key for Ed25519 */
+typedef uint8_t nrf_crypto_ecc_ed25519_raw_public_key_t
+    [NRF_CRYPTO_ECC_ED25519_RAW_PUBLIC_KEY_SIZE];                    /**< @brief Array holding raw public key for Ed25519 */
+
+
+#if NRF_CRYPTO_ECC_ED25519_ENABLED
+
+/** @brief Variable containing information on Ed25519.
+ *
+ *  It can be used as a parameter for the functions creating Ed25519 keys.
+ */
+extern const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_ed25519_curve_info;
+
+#endif
+
+/** @} */
+
+
+typedef uint8_t nrf_crypto_ecc_raw_private_key_t[NRF_CRYPTO_ECC_RAW_PRIVATE_KEY_MAX_SIZE];  /**< @brief Type big enough to hold a raw private key for any the enabled curves. */
+typedef uint8_t nrf_crypto_ecc_raw_public_key_t [NRF_CRYPTO_ECC_RAW_PUBLIC_KEY_MAX_SIZE];   /**< @brief Type big enough to hold a raw public key for any the enabled curves. */
+
+
+/** @brief Union holding a context for a key pair generation.
+ */
+typedef union
+{
+    nrf_crypto_ecc_secp160r1_key_pair_generate_context_t  context_secp160r1;    /**< @brief Holds context for secp160r1 (NIST 160-bit). */
+    nrf_crypto_ecc_secp160r2_key_pair_generate_context_t  context_secp160r2;    /**< @brief Holds context for secp160r2 (NIST 160-bit). */
+    nrf_crypto_ecc_secp192r1_key_pair_generate_context_t  context_secp192r1;    /**< @brief Holds context for secp192r1 (NIST 192-bit). */
+    nrf_crypto_ecc_secp224r1_key_pair_generate_context_t  context_secp224r1;    /**< @brief Holds context for secp224r1 (NIST 224-bit). */
+    nrf_crypto_ecc_secp256r1_key_pair_generate_context_t  context_secp256r1;    /**< @brief Holds context for secp256r1 (NIST 256-bit). */
+    nrf_crypto_ecc_secp384r1_key_pair_generate_context_t  context_secp384r1;    /**< @brief Holds context for secp384r1 (NIST 384-bit). */
+    nrf_crypto_ecc_secp521r1_key_pair_generate_context_t  context_secp521r1;    /**< @brief Holds context for secp521r1 (NIST 521-bit). */
+    nrf_crypto_ecc_secp160k1_key_pair_generate_context_t  context_secp160k1;    /**< @brief Holds context for secp160k1 (Koblitz 160-bit). */
+    nrf_crypto_ecc_secp192k1_key_pair_generate_context_t  context_secp192k1;    /**< @brief Holds context for secp192k1 (Koblitz 192-bit). */
+    nrf_crypto_ecc_secp224k1_key_pair_generate_context_t  context_secp224k1;    /**< @brief Holds context for secp224k1 (Koblitz 224-bit). */
+    nrf_crypto_ecc_secp256k1_key_pair_generate_context_t  context_secp256k1;    /**< @brief Holds context for secp256k1 (Koblitz 256-bit). */
+    nrf_crypto_ecc_bp256r1_key_pair_generate_context_t    context_bp256r1;      /**< @brief Holds context for bp256r1 (Brainpool 256-bit). */
+    nrf_crypto_ecc_bp384r1_key_pair_generate_context_t    context_bp384r1;      /**< @brief Holds context for bp384r1 (Brainpool 384-bit). */
+    nrf_crypto_ecc_bp512r1_key_pair_generate_context_t    context_bp512r1;      /**< @brief Holds context for bp512r1 (Brainpool 512-bit). */
+    nrf_crypto_ecc_curve25519_key_pair_generate_context_t context_curve25519;   /**< @brief Holds context for Curve25519. */
+    nrf_crypto_ecc_ed25519_key_pair_generate_context_t    context_ed25519;      /**< @brief Holds context for Ed25519. */
+} nrf_crypto_ecc_key_pair_generate_context_t;
+
+
+/** @brief Union holding a context for a public key calculation.
+ */
+typedef union
+{
+    nrf_crypto_ecc_secp160r1_public_key_calculate_context_t  context_secp160r1;    /**< @brief Holds context for secp160r1 (NIST 160-bit). */
+    nrf_crypto_ecc_secp160r2_public_key_calculate_context_t  context_secp160r2;    /**< @brief Holds context for secp160r2 (NIST 160-bit). */
+    nrf_crypto_ecc_secp192r1_public_key_calculate_context_t  context_secp192r1;    /**< @brief Holds context for secp192r1 (NIST 192-bit). */
+    nrf_crypto_ecc_secp224r1_public_key_calculate_context_t  context_secp224r1;    /**< @brief Holds context for secp224r1 (NIST 224-bit). */
+    nrf_crypto_ecc_secp256r1_public_key_calculate_context_t  context_secp256r1;    /**< @brief Holds context for secp256r1 (NIST 256-bit). */
+    nrf_crypto_ecc_secp384r1_public_key_calculate_context_t  context_secp384r1;    /**< @brief Holds context for secp384r1 (NIST 384-bit). */
+    nrf_crypto_ecc_secp521r1_public_key_calculate_context_t  context_secp521r1;    /**< @brief Holds context for secp521r1 (NIST 521-bit). */
+    nrf_crypto_ecc_secp160k1_public_key_calculate_context_t  context_secp160k1;    /**< @brief Holds context for secp160k1 (Koblitz 160-bit). */
+    nrf_crypto_ecc_secp192k1_public_key_calculate_context_t  context_secp192k1;    /**< @brief Holds context for secp192k1 (Koblitz 192-bit). */
+    nrf_crypto_ecc_secp224k1_public_key_calculate_context_t  context_secp224k1;    /**< @brief Holds context for secp224k1 (Koblitz 224-bit). */
+    nrf_crypto_ecc_secp256k1_public_key_calculate_context_t  context_secp256k1;    /**< @brief Holds context for secp256k1 (Koblitz 256-bit). */
+    nrf_crypto_ecc_bp256r1_public_key_calculate_context_t    context_bp256r1;      /**< @brief Holds context for bp256r1 (Brainpool 256-bit). */
+    nrf_crypto_ecc_bp384r1_public_key_calculate_context_t    context_bp384r1;      /**< @brief Holds context for bp384r1 (Brainpool 384-bit). */
+    nrf_crypto_ecc_bp512r1_public_key_calculate_context_t    context_bp512r1;      /**< @brief Holds context for bp512r1 (Brainpool 512-bit). */
+    nrf_crypto_ecc_curve25519_public_key_calculate_context_t context_curve25519;   /**< @brief Holds context for Curve25519. */
+    nrf_crypto_ecc_ed25519_public_key_calculate_context_t    context_ed25519;      /**< @brief Holds context for Ed25519. */
+} nrf_crypto_ecc_public_key_calculate_context_t;
+
+
+/** @brief Union holding representation of a private key for any curve type.
+ */
+typedef union
+{
+    nrf_crypto_ecc_secp160r1_private_key_t  key_secp160r1;    /**< @brief Holds internal representation of a private key for secp160r1 (NIST 160-bit). */
+    nrf_crypto_ecc_secp160r2_private_key_t  key_secp160r2;    /**< @brief Holds internal representation of a private key for secp160r2 (NIST 160-bit). */
+    nrf_crypto_ecc_secp192r1_private_key_t  key_secp192r1;    /**< @brief Holds internal representation of a private key for secp192r1 (NIST 192-bit). */
+    nrf_crypto_ecc_secp224r1_private_key_t  key_secp224r1;    /**< @brief Holds internal representation of a private key for secp224r1 (NIST 224-bit). */
+    nrf_crypto_ecc_secp256r1_private_key_t  key_secp256r1;    /**< @brief Holds internal representation of a private key for secp256r1 (NIST 256-bit). */
+    nrf_crypto_ecc_secp384r1_private_key_t  key_secp384r1;    /**< @brief Holds internal representation of a private key for secp384r1 (NIST 384-bit). */
+    nrf_crypto_ecc_secp521r1_private_key_t  key_secp521r1;    /**< @brief Holds internal representation of a private key for secp521r1 (NIST 521-bit). */
+    nrf_crypto_ecc_secp160k1_private_key_t  key_secp160k1;    /**< @brief Holds internal representation of a private key for secp160k1 (Koblitz 160-bit). */
+    nrf_crypto_ecc_secp192k1_private_key_t  key_secp192k1;    /**< @brief Holds internal representation of a private key for secp192k1 (Koblitz 192-bit). */
+    nrf_crypto_ecc_secp224k1_private_key_t  key_secp224k1;    /**< @brief Holds internal representation of a private key for secp224k1 (Koblitz 224-bit). */
+    nrf_crypto_ecc_secp256k1_private_key_t  key_secp256k1;    /**< @brief Holds internal representation of a private key for secp256k1 (Koblitz 256-bit). */
+    nrf_crypto_ecc_bp256r1_private_key_t    key_bp256r1;      /**< @brief Holds internal representation of a private key for bp256r1 (Brainpool 256-bit). */
+    nrf_crypto_ecc_bp384r1_private_key_t    key_bp384r1;      /**< @brief Holds internal representation of a private key for bp384r1 (Brainpool 384-bit). */
+    nrf_crypto_ecc_bp512r1_private_key_t    key_bp512r1;      /**< @brief Holds internal representation of a private key for bp512r1 (Brainpool 512-bit). */
+    nrf_crypto_ecc_curve25519_private_key_t key_curve25519;   /**< @brief Holds internal representation of a private key for Curve25519. */
+    nrf_crypto_ecc_ed25519_private_key_t    key_ed25519;      /**< @brief Holds internal representation of a private key for Ed25519. */
+} nrf_crypto_ecc_private_key_t;
+
+
+/** @brief Union holding representation of a public key for any curve type.
+ */
+typedef union
+{
+    nrf_crypto_ecc_secp160r1_public_key_t  key_secp160r1;    /**< @brief Holds internal representation of a public key for secp160r1 (NIST 160-bit). */
+    nrf_crypto_ecc_secp160r2_public_key_t  key_secp160r2;    /**< @brief Holds internal representation of a public key for secp160r2 (NIST 160-bit). */
+    nrf_crypto_ecc_secp192r1_public_key_t  key_secp192r1;    /**< @brief Holds internal representation of a public key for secp192r1 (NIST 192-bit). */
+    nrf_crypto_ecc_secp224r1_public_key_t  key_secp224r1;    /**< @brief Holds internal representation of a public key for secp224r1 (NIST 224-bit). */
+    nrf_crypto_ecc_secp256r1_public_key_t  key_secp256r1;    /**< @brief Holds internal representation of a public key for secp256r1 (NIST 256-bit). */
+    nrf_crypto_ecc_secp384r1_public_key_t  key_secp384r1;    /**< @brief Holds internal representation of a public key for secp384r1 (NIST 384-bit). */
+    nrf_crypto_ecc_secp521r1_public_key_t  key_secp521r1;    /**< @brief Holds internal representation of a public key for secp521r1 (NIST 521-bit). */
+    nrf_crypto_ecc_secp160k1_public_key_t  key_secp160k1;    /**< @brief Holds internal representation of a public key for secp160k1 (Koblitz 160-bit). */
+    nrf_crypto_ecc_secp192k1_public_key_t  key_secp192k1;    /**< @brief Holds internal representation of a public key for secp192k1 (Koblitz 192-bit). */
+    nrf_crypto_ecc_secp224k1_public_key_t  key_secp224k1;    /**< @brief Holds internal representation of a public key for secp224k1 (Koblitz 224-bit). */
+    nrf_crypto_ecc_secp256k1_public_key_t  key_secp256k1;    /**< @brief Holds internal representation of a public key for secp256k1 (Koblitz 256-bit). */
+    nrf_crypto_ecc_bp256r1_public_key_t    key_bp256r1;      /**< @brief Holds internal representation of a public key for bp256r1 (Brainpool 256-bit). */
+    nrf_crypto_ecc_bp384r1_public_key_t    key_bp384r1;      /**< @brief Holds internal representation of a public key for bp384r1 (Brainpool 384-bit). */
+    nrf_crypto_ecc_bp512r1_public_key_t    key_bp512r1;      /**< @brief Holds internal representation of a public key for bp512r1 (Brainpool 512-bit). */
+    nrf_crypto_ecc_curve25519_public_key_t key_curve25519;   /**< @brief Holds internal representation of a public key for Curve25519. */
+    nrf_crypto_ecc_ed25519_public_key_t    key_ed25519;      /**< @brief Holds internal representation of a public key for Ed25519. */
+} nrf_crypto_ecc_public_key_t;
+
+
+/** @brief Generate a new pair of a public key and a private key.
+ *
+ *  Generated keys have to deallocated using @ref nrf_crypto_ecc_private_key_free and
+ *  @ref nrf_crypto_ecc_public_key_free.
+ *  @param[in]  p_context      Pointer to temporary structure holding context information.
+ *                             If it is NULL, necessary data will be allocated with
+ *                             @ref NRF_CRYPTO_ALLOC and freed at the end of the function.
+ *  @param[in]  p_curve_info   Pointer to information on selected curve. Use only global variables
+ *                             defined by nrf_crypto, e.g. @ref g_nrf_crypto_ecc_secp256r1_curve_info.
+ *  @param[out] p_private_key  Pointer to structure where newly generated private key will be put.
+ *  @param[out] p_public_key   Pointer to structure where newly generated public key will be put.
+ */
+ret_code_t nrf_crypto_ecc_key_pair_generate(
+    nrf_crypto_ecc_key_pair_generate_context_t       * p_context,
+    nrf_crypto_ecc_curve_info_t                const * p_curve_info,
+    nrf_crypto_ecc_private_key_t                     * p_private_key,
+    nrf_crypto_ecc_public_key_t                      * p_public_key);
+
+
+/** @brief Calculate public key associated with provided private key.
+ *
+ *  Calculated public key has to be deallocated using @ref nrf_crypto_ecc_public_key_free.
+ *  @param[in]  p_context      Pointer to temporary structure holding context information.
+ *                             If it is NULL, necessary data will be allocated with
+ *                             @ref NRF_CRYPTO_ALLOC and freed at the end of the function.
+ *  @param[in]  p_private_key  Pointer to structure holding a private key that will be used for computation.
+ *  @param[out] p_public_key   Pointer to structure where newly generated public key will be put.
+ */
+ret_code_t nrf_crypto_ecc_public_key_calculate(
+    nrf_crypto_ecc_public_key_calculate_context_t       * p_context,
+    nrf_crypto_ecc_private_key_t                  const * p_private_key,
+    nrf_crypto_ecc_public_key_t                         * p_public_key);
+
+
+/** @brief Create a private key from a raw data.
+ *
+ *  Generated private key has to be deallocated using @ref nrf_crypto_ecc_private_key_free.
+ * 
+ *  @note Ed25519 only: Memory is allocated internally using @ref nrf_crypto_mem.
+ * 
+ *  @param[in]  p_curve_info   Pointer to information on selected curve. Use only global variables
+ *                             defined by nrf_crypto, e.g. @ref g_nrf_crypto_ecc_secp256r1_curve_info.
+ *  @param[out] p_private_key  Pointer to structure where newly converted private key will be put.
+ *  @param[in]  p_raw_data     Pointer to buffer containing a big endian raw data.
+ *  @param[in]  raw_data_size  Number of bytes of a raw data. Correct size for selected curve can be found in
+ *                             @p p_curve_info and it is also defined by the preprocessor definitions, e.g.
+ *                             @ref NRF_CRYPTO_ECC_SECP256R1_RAW_PRIVATE_KEY_SIZE.
+ */
+ret_code_t nrf_crypto_ecc_private_key_from_raw(
+    nrf_crypto_ecc_curve_info_t  const * p_curve_info,
+    nrf_crypto_ecc_private_key_t       * p_private_key,
+    uint8_t                      const * p_raw_data,
+    size_t                               raw_data_size);
+
+
+/** @brief Convert a private key to a raw data.
+ *
+ *  @param[in]     p_private_key    Pointer to structure holding private key that will be convert.
+ *  @param[out]    p_raw_data       Pointer to buffer containing a big endian raw data.
+ *  @param[in,out] p_raw_data_size  Maximum number of bytes that @p p_raw_data buffer can hold on input
+ *                                  and the actual number of bytes used by the raw data on output.
+ *                                  Actual size for selected curve can be found in
+ *                                  @ref nrf_crypto_ecc_curve_info_t and it is also defined by
+ *                                  the preprocessor definitions, e.g.
+ *                                  @ref NRF_CRYPTO_ECC_SECP256R1_RAW_PRIVATE_KEY_SIZE.
+ */
+ret_code_t nrf_crypto_ecc_private_key_to_raw(
+    nrf_crypto_ecc_private_key_t const * p_private_key,
+    uint8_t                            * p_raw_data,
+    size_t                             * p_raw_data_size);
+
+
+/** @brief Create a public key from a raw data.
+ *
+ *  Generated public key has to be deallocated using @ref nrf_crypto_ecc_public_key_free.
+ *  @param[in]  p_curve_info   Pointer to information on selected curve. Use only global variables
+ *                             defined by nrf_crypto, e.g. @ref g_nrf_crypto_ecc_secp256r1_curve_info.
+ *  @param[out] p_public_key   Pointer to structure where newly converted public key will be put.
+ *  @param[in]  p_raw_data     Pointer to buffer containing a big endian raw data.
+ *  @param[in]  raw_data_size  Number of bytes of a raw data. Correct size for selected curve can be found in
+ *                             @p p_curve_info and it is also defined by the preprocessor definitions, e.g.
+ *                             @ref NRF_CRYPTO_ECC_SECP256R1_RAW_PUBLIC_KEY_SIZE.
+ */
+ret_code_t nrf_crypto_ecc_public_key_from_raw(
+    nrf_crypto_ecc_curve_info_t const * p_curve_info,
+    nrf_crypto_ecc_public_key_t       * p_public_key,
+    uint8_t                     const * p_raw_data,
+    size_t                              raw_data_size);
+
+
+/** @brief Convert a public key to a raw data.
+ *
+ *  @param[in]     p_public_key     Pointer to structure holding public key that will be convert.
+ *  @param[out]    p_raw_data       Pointer to buffer containing a big endian raw data.
+ *  @param[in,out] p_raw_data_size  Maximum number of bytes that @p p_raw_data buffer can hold on input
+ *                                  and the actual number of bytes used by the raw data on output.
+ *                                  Actual size for selected curve can be found in
+ *                                  @ref nrf_crypto_ecc_curve_info_t and it is also defined by
+ *                                  the preprocessor definitions, e.g.
+ *                                  @ref NRF_CRYPTO_ECC_SECP256R1_RAW_PUBLIC_KEY_SIZE.
+ */
+ret_code_t nrf_crypto_ecc_public_key_to_raw(
+    nrf_crypto_ecc_public_key_t const * p_public_key,
+    uint8_t                           * p_raw_data,
+    size_t                            * p_raw_data_size);
+
+
+/** @brief Release resources taken by a private key.
+ *
+ *  @param[in] p_private_key   Pointer to structure holding private key to release.
+ */
+ret_code_t nrf_crypto_ecc_private_key_free(
+    nrf_crypto_ecc_private_key_t * p_private_key);
+
+
+/** @brief Release resources taken by a public key.
+ *
+ *  @param[in] p_public_key    Pointer to structure holding public key to release.
+ */
+ret_code_t nrf_crypto_ecc_public_key_free(
+    nrf_crypto_ecc_public_key_t * p_public_key);
+
+
+/** @brief Gets curve information structure from provided key (private or public).
+ *
+ *  @param[in]  p_key          Pointer to structure holding private or public key.
+ *  @param[out] pp_curve_info  Pointer to location where put retrieved pointer to curve information structure.
+ */
+ret_code_t nrf_crypto_ecc_curve_info_get(
+    void                         const * p_key,
+    nrf_crypto_ecc_curve_info_t const ** pp_curve_info);
+
+
+/** @brief Inverts byte order of a big integers contained in a raw data.
+ *
+ *  All the ECC API accepts only data with big endian integers, so this function have to be used
+ *  if little endian is required. If input is in little endian byte order it will be converted
+ *  to big endian. If input is in big endian byte order it will be converted to little endian.
+ *  It works for ECC raw private key, raw public key, signature and shared secret. If raw data
+ *  contains two big integers (e.g. R, S, or X, Y) each integer is inverted separately.
+ *  If @p p_curve_info is NULL then all bytes in buffer will be inverted regardless what is the
+ *  content of the buffer.
+ *
+ *  @param[in]  p_curve_info   Pointer to information on selected curve. Use only global variables
+ *                             defined by nrf_crypto, e.g. @ref g_nrf_crypto_ecc_secp256r1_curve_info.
+ *  @param[in]  p_raw_input    Pointer to buffer holding source data.
+ *  @param[out] p_raw_output   Pointer to buffer that will be filled with inverted byte order.
+ *                             This parameter can be the same as @p p_raw_input, otherwise the
+ *                             buffers cannot overlap.
+ *  @param[in]  raw_data_size  Size of input and output buffer.
+ */
+ret_code_t nrf_crypto_ecc_byte_order_invert(
+    nrf_crypto_ecc_curve_info_t const * p_curve_info,
+    uint8_t                     const * p_raw_input,
+    uint8_t                           * p_raw_output,
+    size_t                              raw_data_size);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @}
+ *  @}
+ */
+
+#endif // NRF_CRYPTO_ECC_H__
diff --git a/examples/heart_rate_collector/nrf_crypto_ecc_backend.h b/examples/heart_rate_collector/nrf_crypto_ecc_backend.h
new file mode 100644
index 0000000..186f17b
--- /dev/null
+++ b/examples/heart_rate_collector/nrf_crypto_ecc_backend.h
@@ -0,0 +1,339 @@
+/**
+ * Copyright (c) 2018, 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.
+ *
+ */
+
+#ifndef NRF_CRYPTO_ECC_BACKEND_H__
+#define NRF_CRYPTO_ECC_BACKEND_H__
+#if !defined(__SDK_DOXYGEN__)
+
+#include <stdint.h>
+#include <stddef.h>
+
+// #include "sdk_config.h"
+#include "nordic_common.h"
+#include "nrf_crypto_error.h"
+#include "nrf_crypto_ecc_shared.h"
+
+// Include all backends
+// #include "cc310_backend_ecc.h"
+// #include "cc310_bl_backend_ecc.h"
+// #include "mbedtls_backend_ecc.h"
+// #include "oberon_backend_ecc.h"
+#include "micro_ecc_backend_ecc.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+// Make sure that all required defines are defined
+#if !defined(NRF_CRYPTO_ECC_SECP160R1_ENABLED)
+#define NRF_CRYPTO_ECC_SECP160R1_ENABLED 0
+#endif
+#if !defined(NRF_CRYPTO_ECC_SECP160R2_ENABLED)
+#define NRF_CRYPTO_ECC_SECP160R2_ENABLED 0
+#endif
+#if !defined(NRF_CRYPTO_ECC_SECP192R1_ENABLED)
+#define NRF_CRYPTO_ECC_SECP192R1_ENABLED 0
+#endif
+#if !defined(NRF_CRYPTO_ECC_SECP224R1_ENABLED)
+#define NRF_CRYPTO_ECC_SECP224R1_ENABLED 0
+#endif
+#if !defined(NRF_CRYPTO_ECC_SECP256R1_ENABLED)
+// #define NRF_CRYPTO_ECC_SECP256R1_ENABLED 0
+#define NRF_CRYPTO_ECC_SECP256R1_ENABLED 1
+#endif
+#if !defined(NRF_CRYPTO_ECC_SECP384R1_ENABLED)
+#define NRF_CRYPTO_ECC_SECP384R1_ENABLED 0
+#endif
+#if !defined(NRF_CRYPTO_ECC_SECP521R1_ENABLED)
+#define NRF_CRYPTO_ECC_SECP521R1_ENABLED 0
+#endif
+#if !defined(NRF_CRYPTO_ECC_SECP160K1_ENABLED)
+#define NRF_CRYPTO_ECC_SECP160K1_ENABLED 0
+#endif
+#if !defined(NRF_CRYPTO_ECC_SECP192K1_ENABLED)
+#define NRF_CRYPTO_ECC_SECP192K1_ENABLED 0
+#endif
+#if !defined(NRF_CRYPTO_ECC_SECP224K1_ENABLED)
+#define NRF_CRYPTO_ECC_SECP224K1_ENABLED 0
+#endif
+#if !defined(NRF_CRYPTO_ECC_SECP256K1_ENABLED)
+#define NRF_CRYPTO_ECC_SECP256K1_ENABLED 0
+#endif
+#if !defined(NRF_CRYPTO_ECC_BP256R1_ENABLED)
+#define NRF_CRYPTO_ECC_BP256R1_ENABLED 0
+#endif
+#if !defined(NRF_CRYPTO_ECC_BP384R1_ENABLED)
+#define NRF_CRYPTO_ECC_BP384R1_ENABLED 0
+#endif
+#if !defined(NRF_CRYPTO_ECC_BP512R1_ENABLED)
+#define NRF_CRYPTO_ECC_BP512R1_ENABLED 0
+#endif
+#if !defined(NRF_CRYPTO_ECC_CURVE25519_ENABLED)
+#define NRF_CRYPTO_ECC_CURVE25519_ENABLED 0
+#endif
+#if !defined(NRF_CRYPTO_ECC_ED25519_ENABLED)
+#define NRF_CRYPTO_ECC_ED25519_ENABLED 0
+#endif
+
+
+/** @internal @brief Definition to detect if ECC submodule is enabled. It will be enabled if any
+ *  curve of any of the backends is enabled.
+ */
+#define NRF_CRYPTO_ECC_ENABLED NRF_CRYPTO_ECC_SECP256R1_ENABLED
+
+
+/** @internal @brief Definition containing number of enabled curves.
+ */
+#define NRF_CRYPTO_ECC_IMPLEMENTED_CURVES_COUNT ( \
+    NRF_CRYPTO_ECC_SECP160R1_ENABLED + \
+    NRF_CRYPTO_ECC_SECP160R2_ENABLED + \
+    NRF_CRYPTO_ECC_SECP192R1_ENABLED + \
+    NRF_CRYPTO_ECC_SECP224R1_ENABLED + \
+    NRF_CRYPTO_ECC_SECP256R1_ENABLED + \
+    NRF_CRYPTO_ECC_SECP384R1_ENABLED + \
+    NRF_CRYPTO_ECC_SECP521R1_ENABLED + \
+    NRF_CRYPTO_ECC_SECP160K1_ENABLED + \
+    NRF_CRYPTO_ECC_SECP192K1_ENABLED + \
+    NRF_CRYPTO_ECC_SECP224K1_ENABLED + \
+    NRF_CRYPTO_ECC_SECP256K1_ENABLED + \
+    NRF_CRYPTO_ECC_BP256R1_ENABLED + \
+    NRF_CRYPTO_ECC_BP384R1_ENABLED + \
+    NRF_CRYPTO_ECC_BP512R1_ENABLED + \
+    NRF_CRYPTO_ECC_CURVE25519_ENABLED + \
+    NRF_CRYPTO_ECC_ED25519_ENABLED)
+
+
+#if !NRF_CRYPTO_ECC_SECP160R1_ENABLED
+// Dummy typedefs for disabled contexts
+typedef uint32_t nrf_crypto_backend_secp160r1_key_pair_generate_context_t;
+typedef uint32_t nrf_crypto_backend_secp160r1_public_key_calculate_context_t;
+// Dummy typedefs for disabled keys
+typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp160r1_private_key_t;
+typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp160r1_public_key_t;
+#endif
+
+#if !NRF_CRYPTO_ECC_SECP160R2_ENABLED
+// Dummy typedefs for disabled contexts
+typedef uint32_t nrf_crypto_backend_secp160r2_key_pair_generate_context_t;
+typedef uint32_t nrf_crypto_backend_secp160r2_public_key_calculate_context_t;
+// Dummy typedefs for disabled keys
+typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp160r2_private_key_t;
+typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp160r2_public_key_t;
+#endif
+
+#if !NRF_CRYPTO_ECC_SECP192R1_ENABLED
+// Dummy typedefs for disabled contexts
+typedef uint32_t nrf_crypto_backend_secp192r1_key_pair_generate_context_t;
+typedef uint32_t nrf_crypto_backend_secp192r1_public_key_calculate_context_t;
+// Dummy typedefs for disabled keys
+typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp192r1_private_key_t;
+typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp192r1_public_key_t;
+#endif
+
+#if !NRF_CRYPTO_ECC_SECP224R1_ENABLED
+// Dummy typedefs for disabled contexts
+typedef uint32_t nrf_crypto_backend_secp224r1_key_pair_generate_context_t;
+typedef uint32_t nrf_crypto_backend_secp224r1_public_key_calculate_context_t;
+// Dummy typedefs for disabled keys
+typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp224r1_private_key_t;
+typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp224r1_public_key_t;
+#endif
+
+#if !NRF_CRYPTO_ECC_SECP256R1_ENABLED
+// Dummy typedefs for disabled contexts
+typedef uint32_t nrf_crypto_backend_secp256r1_key_pair_generate_context_t;
+typedef uint32_t nrf_crypto_backend_secp256r1_public_key_calculate_context_t;
+// Dummy typedefs for disabled keys
+typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp256r1_private_key_t;
+typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp256r1_public_key_t;
+#endif
+
+#if !NRF_CRYPTO_ECC_SECP384R1_ENABLED
+// Dummy typedefs for disabled contexts
+typedef uint32_t nrf_crypto_backend_secp384r1_key_pair_generate_context_t;
+typedef uint32_t nrf_crypto_backend_secp384r1_public_key_calculate_context_t;
+// Dummy typedefs for disabled keys
+typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp384r1_private_key_t;
+typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp384r1_public_key_t;
+#endif
+
+#if !NRF_CRYPTO_ECC_SECP521R1_ENABLED
+// Dummy typedefs for disabled contexts
+typedef uint32_t nrf_crypto_backend_secp521r1_key_pair_generate_context_t;
+typedef uint32_t nrf_crypto_backend_secp521r1_public_key_calculate_context_t;
+// Dummy typedefs for disabled keys
+typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp521r1_private_key_t;
+typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp521r1_public_key_t;
+#endif
+
+#if !NRF_CRYPTO_ECC_SECP160K1_ENABLED
+// Dummy typedefs for disabled contexts
+typedef uint32_t nrf_crypto_backend_secp160k1_key_pair_generate_context_t;
+typedef uint32_t nrf_crypto_backend_secp160k1_public_key_calculate_context_t;
+// Dummy typedefs for disabled keys
+typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp160k1_private_key_t;
+typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp160k1_public_key_t;
+#endif
+
+#if !NRF_CRYPTO_ECC_SECP192K1_ENABLED
+// Dummy typedefs for disabled contexts
+typedef uint32_t nrf_crypto_backend_secp192k1_key_pair_generate_context_t;
+typedef uint32_t nrf_crypto_backend_secp192k1_public_key_calculate_context_t;
+// Dummy typedefs for disabled keys
+typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp192k1_private_key_t;
+typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp192k1_public_key_t;
+#endif
+
+#if !NRF_CRYPTO_ECC_SECP224K1_ENABLED
+// Dummy typedefs for disabled contexts
+typedef uint32_t nrf_crypto_backend_secp224k1_key_pair_generate_context_t;
+typedef uint32_t nrf_crypto_backend_secp224k1_public_key_calculate_context_t;
+// Dummy typedefs for disabled keys
+typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp224k1_private_key_t;
+typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp224k1_public_key_t;
+#endif
+
+#if !NRF_CRYPTO_ECC_SECP256K1_ENABLED
+// Dummy typedefs for disabled contexts
+typedef uint32_t nrf_crypto_backend_secp256k1_key_pair_generate_context_t;
+typedef uint32_t nrf_crypto_backend_secp256k1_public_key_calculate_context_t;
+// Dummy typedefs for disabled keys
+typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp256k1_private_key_t;
+typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp256k1_public_key_t;
+#endif
+
+#if !NRF_CRYPTO_ECC_BP256R1_ENABLED
+// Dummy typedefs for disabled contexts
+typedef uint32_t nrf_crypto_backend_bp256r1_key_pair_generate_context_t;
+typedef uint32_t nrf_crypto_backend_bp256r1_public_key_calculate_context_t;
+// Dummy typedefs for disabled keys
+typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_bp256r1_private_key_t;
+typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_bp256r1_public_key_t;
+#endif
+
+#if !NRF_CRYPTO_ECC_BP384R1_ENABLED
+// Dummy typedefs for disabled contexts
+typedef uint32_t nrf_crypto_backend_bp384r1_key_pair_generate_context_t;
+typedef uint32_t nrf_crypto_backend_bp384r1_public_key_calculate_context_t;
+// Dummy typedefs for disabled keys
+typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_bp384r1_private_key_t;
+typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_bp384r1_public_key_t;
+#endif
+
+#if !NRF_CRYPTO_ECC_BP512R1_ENABLED
+// Dummy typedefs for disabled contexts
+typedef uint32_t nrf_crypto_backend_bp512r1_key_pair_generate_context_t;
+typedef uint32_t nrf_crypto_backend_bp512r1_public_key_calculate_context_t;
+// Dummy typedefs for disabled keys
+typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_bp512r1_private_key_t;
+typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_bp512r1_public_key_t;
+#endif
+
+#if !NRF_CRYPTO_ECC_CURVE25519_ENABLED
+// Dummy typedefs for disabled contexts
+typedef uint32_t nrf_crypto_backend_curve25519_key_pair_generate_context_t;
+typedef uint32_t nrf_crypto_backend_curve25519_public_key_calculate_context_t;
+// Dummy typedefs for disabled keys
+typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_curve25519_private_key_t;
+typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_curve25519_public_key_t;
+#endif
+
+#if !NRF_CRYPTO_ECC_ED25519_ENABLED
+// Dummy typedefs for disabled contexts
+typedef uint32_t nrf_crypto_backend_ed25519_key_pair_generate_context_t;
+typedef uint32_t nrf_crypto_backend_ed25519_public_key_calculate_context_t;
+// Dummy typedefs for disabled keys
+typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_ed25519_private_key_t;
+typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_ed25519_public_key_t;
+#endif
+
+
+// Find biggest raw private and public key size that is currently enabled
+#if NRF_CRYPTO_ECC_SECP521R1_ENABLED
+#   define NRF_CRYPTO_BACKEND_ECC_RAW_PRIVATE_KEY_MAX_SIZE (66)
+#elif NRF_CRYPTO_ECC_BP512R1_ENABLED
+#   define NRF_CRYPTO_BACKEND_ECC_RAW_PRIVATE_KEY_MAX_SIZE (64)
+#elif NRF_CRYPTO_ECC_BP384R1_ENABLED || NRF_CRYPTO_ECC_SECP384R1_ENABLED
+#   define NRF_CRYPTO_BACKEND_ECC_RAW_PRIVATE_KEY_MAX_SIZE (48)
+#elif NRF_CRYPTO_ECC_BP256R1_ENABLED || NRF_CRYPTO_ECC_SECP256K1_ENABLED || NRF_CRYPTO_ECC_CURVE25519_ENABLED || NRF_CRYPTO_ECC_ED25519_ENABLED || NRF_CRYPTO_ECC_SECP256R1_ENABLED
+#   define NRF_CRYPTO_BACKEND_ECC_RAW_PRIVATE_KEY_MAX_SIZE (32)
+#elif NRF_CRYPTO_ECC_SECP224K1_ENABLED || NRF_CRYPTO_ECC_SECP224R1_ENABLED
+#   define NRF_CRYPTO_BACKEND_ECC_RAW_PRIVATE_KEY_MAX_SIZE (28)
+#elif NRF_CRYPTO_ECC_SECP192K1_ENABLED || NRF_CRYPTO_ECC_SECP192R1_ENABLED
+#   define NRF_CRYPTO_BACKEND_ECC_RAW_PRIVATE_KEY_MAX_SIZE (24)
+#elif NRF_CRYPTO_ECC_SECP160K1_ENABLED || NRF_CRYPTO_ECC_SECP160R1_ENABLED || NRF_CRYPTO_ECC_SECP160R2_ENABLED
+#   define NRF_CRYPTO_BACKEND_ECC_RAW_PRIVATE_KEY_MAX_SIZE (20)
+#else
+#   define NRF_CRYPTO_BACKEND_ECC_RAW_PRIVATE_KEY_MAX_SIZE (1)
+#endif
+
+#if NRF_CRYPTO_ECC_SECP521R1_ENABLED
+#   define NRF_CRYPTO_BACKEND_ECC_RAW_PUBLIC_KEY_MAX_SIZE (2 * 66)
+#elif NRF_CRYPTO_ECC_BP512R1_ENABLED
+#   define NRF_CRYPTO_BACKEND_ECC_RAW_PUBLIC_KEY_MAX_SIZE (2 * 64)
+#elif NRF_CRYPTO_ECC_BP384R1_ENABLED || NRF_CRYPTO_ECC_SECP384R1_ENABLED
+#   define NRF_CRYPTO_BACKEND_ECC_RAW_PUBLIC_KEY_MAX_SIZE (2 * 48)
+#elif NRF_CRYPTO_ECC_BP256R1_ENABLED || NRF_CRYPTO_ECC_SECP256K1_ENABLED || NRF_CRYPTO_ECC_SECP256R1_ENABLED
+#   define NRF_CRYPTO_BACKEND_ECC_RAW_PUBLIC_KEY_MAX_SIZE (2 * 32)
+#elif NRF_CRYPTO_ECC_SECP224K1_ENABLED || NRF_CRYPTO_ECC_SECP224R1_ENABLED
+#   define NRF_CRYPTO_BACKEND_ECC_RAW_PUBLIC_KEY_MAX_SIZE (2 * 28)
+#elif NRF_CRYPTO_ECC_SECP192K1_ENABLED || NRF_CRYPTO_ECC_SECP192R1_ENABLED
+#   define NRF_CRYPTO_BACKEND_ECC_RAW_PUBLIC_KEY_MAX_SIZE (2 * 24)
+#elif NRF_CRYPTO_ECC_SECP160K1_ENABLED || NRF_CRYPTO_ECC_SECP160R1_ENABLED || NRF_CRYPTO_ECC_SECP160R2_ENABLED
+#   define NRF_CRYPTO_BACKEND_ECC_RAW_PUBLIC_KEY_MAX_SIZE (2 * 20)
+#elif NRF_CRYPTO_ECC_CURVE25519_ENABLED || NRF_CRYPTO_ECC_ED25519_ENABLED
+#   define NRF_CRYPTO_BACKEND_ECC_RAW_PUBLIC_KEY_MAX_SIZE (32)
+#else
+#   define NRF_CRYPTO_BACKEND_ECC_RAW_PUBLIC_KEY_MAX_SIZE (1)
+#endif
+
+#if NRF_CRYPTO_ECC_CURVE25519_ENABLED && !defined(NRF_CRYPTO_CURVE25519_BIG_ENDIAN_ENABLED)
+#warning "NRF_CRYPTO_CURVE25519_BIG_ENDIAN_ENABLED not defined. Please define it to choose the endianness of Curve25519 parameters."
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif // !defined(__SDK_DOXYGEN__)
+#endif // NRF_CRYPTO_ECC_BACKEND_H__
diff --git a/examples/heart_rate_collector/nrf_crypto_ecc_shared.h b/examples/heart_rate_collector/nrf_crypto_ecc_shared.h
new file mode 100644
index 0000000..0117cfd
--- /dev/null
+++ b/examples/heart_rate_collector/nrf_crypto_ecc_shared.h
@@ -0,0 +1,229 @@
+/**
+ * Copyright (c) 2018, 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.
+ *
+ */
+
+#ifndef NRF_CRYPTO_ECC_SHARED_H__
+#define NRF_CRYPTO_ECC_SHARED_H__
+#if !defined(__SDK_DOXYGEN__)
+
+#include <stdint.h>
+#include <stddef.h>
+#include <stdbool.h>
+
+#include "sdk_errors.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define NRF_CRYPTO_INTERNAL_ECC_PRIVATE_KEY_INIT_VALUE (0x4D465276) /**< @internal @brief Init value for all ECC private keys. ASCII "nRFv". */
+#define NRF_CRYPTO_INTERNAL_ECC_PUBLIC_KEY_INIT_VALUE  (0x4D465270) /**< @internal @brief Init value for all ECC public keys. ASCII "nRFp". */
+
+
+// Forward declaration only
+struct nrf_crypto_ecc_curve_info_s;
+
+
+/** @brief Header structure at the beginning of each key structure.
+ */
+typedef struct
+{
+    uint32_t                                   init_value;    /**< @internal @brief Init value to check if key was correctly initialized. */
+    struct nrf_crypto_ecc_curve_info_s const * p_info;        /**< @internal @brief Points to information structure of an associated curve type. */
+} nrf_crypto_internal_ecc_key_header_t;
+
+
+/** @internal @brief Function pointer for backend implementation of a key pair garatarion.
+ *
+ * @note All parameters provided to the backend are vefified in frontend. Verification includes
+ * checking of NULL pointers, buffer size, initialization values. Front end also take full care of
+ * common ECC key hearder @ref nrf_crypto_internal_ecc_key_header_t.
+ *
+ * @param[in]  p_context      Pointer to context.
+ * @param[out] p_private_key  Pointer where to put new private key.
+ * @param[out] p_public_key   Pointer where to put new public key.
+ */
+typedef ret_code_t (*nrf_crypto_backend_ecc_key_pair_generate_fn_t)(
+    void * p_context,
+    void * p_private_key,
+    void * p_public_key);
+
+
+/** @internal @brief Function pointer for backend implementation of a public key calculation.
+ *
+ * @note All parameters provided to the backend are vefified in frontend. Verification includes
+ * checking of NULL pointers, buffer size, initialization values. Front end also take full care of
+ * common ECC key hearder @ref nrf_crypto_internal_ecc_key_header_t.
+ *
+ * @param[in]  p_context      Pointer to context.
+ * @param[in]  p_private_key  Pointer to private key.
+ * @param[out] p_public_key   Pointer where to put new public key.
+ */
+typedef ret_code_t (*nrf_crypto_backend_ecc_public_key_calculate_fn_t)(
+    void       * p_context,
+    void const * p_private_key,
+    void       * p_public_key);
+
+
+/** @internal @brief Function pointer for backend implementation of raw to private key conversion.
+ *
+ * @note All parameters provided to the backend are vefified in frontend. Verification includes
+ * checking of NULL pointers, buffer size, initialization values. Front end also take full care of
+ * common ECC key hearder @ref nrf_crypto_internal_ecc_key_header_t.
+ *
+ * @param[out] p_private_key  Pointer where to put new private key.
+ * @param[in]  p_raw_data     Pointer to raw data.
+ */
+typedef ret_code_t (*nrf_crypto_backend_ecc_private_key_from_raw_fn_t)(
+    void          * p_private_key,
+    uint8_t const * p_raw_data);
+
+
+/** @internal @brief Function pointer for backend implementation of private key to raw conversion.
+ *
+ * @note All parameters provided to the backend are vefified in frontend. Verification includes
+ * checking of NULL pointers, buffer size, initialization values. Front end also take full care of
+ * common ECC key hearder @ref nrf_crypto_internal_ecc_key_header_t.
+ *
+ * @param[in]  p_private_key  Pointer to private key.
+ * @param[out] p_raw_data     Pointer where to put raw data.
+ */
+typedef ret_code_t (*nrf_crypto_backend_ecc_private_key_to_raw_fn_t)(
+    void    const * p_private_key,
+    uint8_t       * p_raw_data);
+
+
+/** @internal @brief Function pointer for backend implementation of raw to public key conversion.
+ *
+ * @note All parameters provided to the backend are vefified in frontend. Verification includes
+ * checking of NULL pointers, buffer size, initialization values. Front end also take full care of
+ * common ECC key hearder @ref nrf_crypto_internal_ecc_key_header_t.
+ *
+ * @param[out] p_public_key  Pointer where to put new public key.
+ * @param[in]  p_raw_data    Pointer to raw data.
+ */
+typedef ret_code_t (*nrf_crypto_backend_ecc_public_key_from_raw_fn_t)(
+    void          * p_public_key,
+    uint8_t const * p_raw_data);
+
+
+/** @internal @brief Function pointer for backend implementation of public key to raw conversion.
+ *
+ * @note All parameters provided to the backend are vefified in frontend. Verification includes
+ * checking of NULL pointers, buffer size, initialization values. Front end also take full care of
+ * common ECC key hearder @ref nrf_crypto_internal_ecc_key_header_t.
+ *
+ * @param[in]  p_public_key  Pointer to public key.
+ * @param[out] p_raw_data    Pointer where to put raw data.
+ */
+typedef ret_code_t (*nrf_crypto_backend_ecc_public_key_to_raw_fn_t)(
+    void    const * p_public_key,
+    uint8_t       * p_raw_data);
+
+
+/** @internal @brief Function pointer for backend implementation of key (public or private) deallocation.
+ *
+ * @note All parameters provided to the backend are vefified in frontend. Verification includes
+ * checking of NULL pointers, buffer size, initialization values. Front end also take full care of
+ * common ECC key hearder @ref nrf_crypto_internal_ecc_key_header_t.
+ *
+ * @param[in]  p_key  Pointer to public or private key.
+ */
+typedef ret_code_t (*nrf_crypto_backend_ecc_key_free_fn_t)(
+    void * p_key);
+
+
+/** @internal @brief Function for checking and preparing ECC key output parameter.
+ *
+ * @param[in]  p_curve_info  Curve info provided by user that will be used to create a new key.
+ * @param[out] p_key_header  Key header that have to be prepared.
+ * @return                   NRF_SUCCESS if parameters are valid, error otherwise.
+ */
+ret_code_t nrf_crypto_internal_ecc_key_output_prepare(
+    struct nrf_crypto_ecc_curve_info_s   const * p_curve_info,
+    nrf_crypto_internal_ecc_key_header_t       * p_key_header);
+
+
+/** @internal @brief Function for checking ECC key input parameter.
+ *
+ * @param[in] p_key_header Key header that have to be checked.
+ * @param[in] init_value   Expected init value in this key.
+ * @return                 NRF_SUCCESS if parameter is valid, error otherwise.
+ */
+ret_code_t nrf_crypto_internal_ecc_key_input_check(
+    nrf_crypto_internal_ecc_key_header_t const * p_key_header,
+    uint32_t                                     init_value);
+
+
+/** @internal @brief Function for checking and preparing raw data output parameter.
+ *
+ * @param[out]    p_raw_data      Buffer where output will be written.
+ * @param[in,out] p_raw_data_size Pointer to size of the data. On input this is size of provided by
+ *                                the user buffer. On output is equal @p expected_size. This pointer
+ *                                can be NULL if used does not want to do size checking.
+ * @param[in]     expected_size   Size of output data that will be written to the buffer.
+ * @return                        NRF_SUCCESS if parameters are valid, error otherwise.
+ */
+ret_code_t nrf_crypto_internal_ecc_raw_output_prepare(
+    uint8_t    * p_raw_data,
+    size_t     * p_raw_data_size,
+    size_t       expected_size);
+
+
+/** @internal @brief Function for checking raw data input parameter.
+ *
+ * @param[in] p_raw_data     Buffer where data is located.
+ * @param[in] raw_data_size  Size of the data.Function will fail if it is different than @p expected_size.
+ * @param[in] expected_size  Expected size of the data.
+ * @return                   NRF_SUCCESS if parameters are valid, error otherwise.
+ */
+ret_code_t nrf_crypto_internal_ecc_raw_input_check(
+    uint8_t const * p_raw_data,
+    size_t          raw_data_size,
+    size_t          expected_size);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // !defined(__SDK_DOXYGEN__)
+#endif // NRF_CRYPTO_ECC_SHARED_H__
diff --git a/examples/heart_rate_collector/nrf_crypto_ecdh.c b/examples/heart_rate_collector/nrf_crypto_ecdh.c
new file mode 100644
index 0000000..d0fe7b6
--- /dev/null
+++ b/examples/heart_rate_collector/nrf_crypto_ecdh.c
@@ -0,0 +1,278 @@
+/**
+ * Copyright (c) 2018, 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.
+ *
+ */
+
+#include "nrf_crypto_error.h"
+#include "nrf_crypto_mem.h"
+#include "nrf_crypto_ecc.h"
+#include "nrf_crypto_ecdh.h"
+// #include "app_util.h"
+// #include "sdk_assert.h"
+#include "sdk_macros.h"
+
+
+#if NRF_CRYPTO_ECC_ENABLED
+
+
+#if NRF_CRYPTO_ECC_IMPLEMENTED_CURVES_COUNT > 1
+
+
+static const nrf_crypto_backend_ecdh_compute_fn_t compute_impl[] =
+{
+#if NRF_CRYPTO_ECC_SECP160R1_ENABLED
+    nrf_crypto_backend_secp160r1_ecdh_compute,
+#endif
+#if NRF_CRYPTO_ECC_SECP160R2_ENABLED
+    nrf_crypto_backend_secp160r2_ecdh_compute,
+#endif
+#if NRF_CRYPTO_ECC_SECP192R1_ENABLED
+    nrf_crypto_backend_secp192r1_ecdh_compute,
+#endif
+#if NRF_CRYPTO_ECC_SECP224R1_ENABLED
+    nrf_crypto_backend_secp224r1_ecdh_compute,
+#endif
+#if NRF_CRYPTO_ECC_SECP256R1_ENABLED
+    nrf_crypto_backend_secp256r1_ecdh_compute,
+#endif
+#if NRF_CRYPTO_ECC_SECP384R1_ENABLED
+    nrf_crypto_backend_secp384r1_ecdh_compute,
+#endif
+#if NRF_CRYPTO_ECC_SECP521R1_ENABLED
+    nrf_crypto_backend_secp521r1_ecdh_compute,
+#endif
+#if NRF_CRYPTO_ECC_SECP160K1_ENABLED
+    nrf_crypto_backend_secp160k1_ecdh_compute,
+#endif
+#if NRF_CRYPTO_ECC_SECP192K1_ENABLED
+    nrf_crypto_backend_secp192k1_ecdh_compute,
+#endif
+#if NRF_CRYPTO_ECC_SECP224K1_ENABLED
+    nrf_crypto_backend_secp224k1_ecdh_compute,
+#endif
+#if NRF_CRYPTO_ECC_SECP256K1_ENABLED
+    nrf_crypto_backend_secp256k1_ecdh_compute,
+#endif
+#if NRF_CRYPTO_ECC_BP256R1_ENABLED
+    nrf_crypto_backend_bp256r1_ecdh_compute,
+#endif
+#if NRF_CRYPTO_ECC_BP384R1_ENABLED
+    nrf_crypto_backend_bp384r1_ecdh_compute,
+#endif
+#if NRF_CRYPTO_ECC_BP512R1_ENABLED
+    nrf_crypto_backend_bp512r1_ecdh_compute,
+#endif
+#if NRF_CRYPTO_ECC_CURVE25519_ENABLED
+    nrf_crypto_backend_curve25519_ecdh_compute,
+#endif
+};
+
+
+static const uint16_t compute_impl_context_size[] =
+{
+#if NRF_CRYPTO_ECC_SECP160R1_ENABLED
+    NRF_CRYPTO_BACKEND_SECP160R1_ECDH_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_SECP160R2_ENABLED
+    NRF_CRYPTO_BACKEND_SECP160R2_ECDH_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_SECP192R1_ENABLED
+    NRF_CRYPTO_BACKEND_SECP192R1_ECDH_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_SECP224R1_ENABLED
+    NRF_CRYPTO_BACKEND_SECP224R1_ECDH_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_SECP256R1_ENABLED
+    NRF_CRYPTO_BACKEND_SECP256R1_ECDH_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_SECP384R1_ENABLED
+    NRF_CRYPTO_BACKEND_SECP384R1_ECDH_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_SECP521R1_ENABLED
+    NRF_CRYPTO_BACKEND_SECP521R1_ECDH_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_SECP160K1_ENABLED
+    NRF_CRYPTO_BACKEND_SECP160K1_ECDH_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_SECP192K1_ENABLED
+    NRF_CRYPTO_BACKEND_SECP192K1_ECDH_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_SECP224K1_ENABLED
+    NRF_CRYPTO_BACKEND_SECP224K1_ECDH_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_SECP256K1_ENABLED
+    NRF_CRYPTO_BACKEND_SECP256K1_ECDH_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_BP256R1_ENABLED
+    NRF_CRYPTO_BACKEND_BP256R1_ECDH_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_BP384R1_ENABLED
+    NRF_CRYPTO_BACKEND_BP384R1_ECDH_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_BP512R1_ENABLED
+    NRF_CRYPTO_BACKEND_BP512R1_ECDH_CONTEXT_SIZE,
+#endif
+#if NRF_CRYPTO_ECC_CURVE25519_ENABLED
+    NRF_CRYPTO_BACKEND_CURVE25519_ECDH_CONTEXT_SIZE,
+#endif
+};
+
+#define BACKEND_IMPL_GET(table, curve_type) (table)[(uint32_t)(curve_type)]
+
+#else
+
+
+#if NRF_CRYPTO_ECC_SECP160R1_ENABLED
+#define compute_impl              nrf_crypto_backend_secp160r1_ecdh_compute
+#define compute_impl_context_size NRF_CRYPTO_BACKEND_SECP160R1_ECDH_CONTEXT_SIZE
+#elif NRF_CRYPTO_ECC_SECP160R2_ENABLED
+#define compute_impl              nrf_crypto_backend_secp160r2_ecdh_compute
+#define compute_impl_context_size NRF_CRYPTO_BACKEND_SECP160R2_ECDH_CONTEXT_SIZE
+#elif NRF_CRYPTO_ECC_SECP192R1_ENABLED
+#define compute_impl              nrf_crypto_backend_secp192r1_ecdh_compute
+#define compute_impl_context_size NRF_CRYPTO_BACKEND_SECP192R1_ECDH_CONTEXT_SIZE
+#elif NRF_CRYPTO_ECC_SECP224R1_ENABLED
+#define compute_impl              nrf_crypto_backend_secp224r1_ecdh_compute
+#define compute_impl_context_size NRF_CRYPTO_BACKEND_SECP224R1_ECDH_CONTEXT_SIZE
+#elif NRF_CRYPTO_ECC_SECP256R1_ENABLED
+#define compute_impl              nrf_crypto_backend_secp256r1_ecdh_compute
+#define compute_impl_context_size NRF_CRYPTO_BACKEND_SECP256R1_ECDH_CONTEXT_SIZE
+#elif NRF_CRYPTO_ECC_SECP384R1_ENABLED
+#define compute_impl              nrf_crypto_backend_secp384r1_ecdh_compute
+#define compute_impl_context_size NRF_CRYPTO_BACKEND_SECP384R1_ECDH_CONTEXT_SIZE
+#elif NRF_CRYPTO_ECC_SECP521R1_ENABLED
+#define compute_impl              nrf_crypto_backend_secp521r1_ecdh_compute
+#define compute_impl_context_size NRF_CRYPTO_BACKEND_SECP521R1_ECDH_CONTEXT_SIZE
+#elif NRF_CRYPTO_ECC_SECP160K1_ENABLED
+#define compute_impl              nrf_crypto_backend_secp160k1_ecdh_compute
+#define compute_impl_context_size NRF_CRYPTO_BACKEND_SECP160K1_ECDH_CONTEXT_SIZE
+#elif NRF_CRYPTO_ECC_SECP192K1_ENABLED
+#define compute_impl              nrf_crypto_backend_secp192k1_ecdh_compute
+#define compute_impl_context_size NRF_CRYPTO_BACKEND_SECP192K1_ECDH_CONTEXT_SIZE
+#elif NRF_CRYPTO_ECC_SECP224K1_ENABLED
+#define compute_impl              nrf_crypto_backend_secp224k1_ecdh_compute
+#define compute_impl_context_size NRF_CRYPTO_BACKEND_SECP224K1_ECDH_CONTEXT_SIZE
+#elif NRF_CRYPTO_ECC_SECP256K1_ENABLED
+#define compute_impl              nrf_crypto_backend_secp256k1_ecdh_compute
+#define compute_impl_context_size NRF_CRYPTO_BACKEND_SECP256K1_ECDH_CONTEXT_SIZE
+#elif NRF_CRYPTO_ECC_BP256R1_ENABLED
+#define compute_impl              nrf_crypto_backend_bp256r1_ecdh_compute
+#define compute_impl_context_size NRF_CRYPTO_BACKEND_BP256R1_ECDH_CONTEXT_SIZE
+#elif NRF_CRYPTO_ECC_BP384R1_ENABLED
+#define compute_impl              nrf_crypto_backend_bp384r1_ecdh_compute
+#define compute_impl_context_size NRF_CRYPTO_BACKEND_BP384R1_ECDH_CONTEXT_SIZE
+#elif NRF_CRYPTO_ECC_BP512R1_ENABLED
+#define compute_impl              nrf_crypto_backend_bp512r1_ecdh_compute
+#define compute_impl_context_size NRF_CRYPTO_BACKEND_BP512R1_ECDH_CONTEXT_SIZE
+#elif NRF_CRYPTO_ECC_CURVE25519_ENABLED
+#define compute_impl              nrf_crypto_backend_curve25519_ecdh_compute
+#define compute_impl_context_size NRF_CRYPTO_BACKEND_CURVE25519_ECDH_CONTEXT_SIZE
+#else
+#define compute_impl              NULL
+#define compute_impl_context_size 0
+#endif
+
+#define BACKEND_IMPL_GET(function, curve_type) (function)
+
+#endif
+
+
+ret_code_t nrf_crypto_ecdh_compute(
+    nrf_crypto_ecdh_context_t          * p_context,
+    nrf_crypto_ecc_private_key_t const * p_private_key,
+    nrf_crypto_ecc_public_key_t  const * p_public_key,
+    uint8_t                            * p_shared_secret,
+    size_t                             * p_shared_secret_size)
+{
+    ret_code_t                             result;
+    void                                 * p_allocated_context    = NULL;
+    nrf_crypto_backend_ecdh_compute_fn_t   backend_implementation;
+    size_t                                 context_size;
+    nrf_crypto_ecc_curve_info_t    const * p_info;
+
+    // Get pointer to header for each key
+    nrf_crypto_internal_ecc_key_header_t const * p_private_key_header =
+        (nrf_crypto_internal_ecc_key_header_t const *)p_private_key;
+    nrf_crypto_internal_ecc_key_header_t const * p_public_key_header =
+        (nrf_crypto_internal_ecc_key_header_t const *)p_public_key;
+
+    // Check and prepare parameters
+    result = nrf_crypto_internal_ecc_key_input_check(
+        p_private_key_header,
+        NRF_CRYPTO_INTERNAL_ECC_PRIVATE_KEY_INIT_VALUE);
+    VERIFY_SUCCESS(result);
+    result = nrf_crypto_internal_ecc_key_input_check(
+        p_public_key_header,
+        NRF_CRYPTO_INTERNAL_ECC_PUBLIC_KEY_INIT_VALUE);
+    VERIFY_SUCCESS(result);
+    VERIFY_TRUE(p_private_key_header->p_info == p_public_key_header->p_info,
+                NRF_ERROR_CRYPTO_ECDH_CURVE_MISMATCH);
+    p_info = p_private_key_header->p_info;
+    result = nrf_crypto_internal_ecc_raw_output_prepare(
+               p_shared_secret,
+               p_shared_secret_size,
+               p_info->raw_private_key_size);
+    VERIFY_SUCCESS(result);
+
+    // Get backend specific information
+    backend_implementation = BACKEND_IMPL_GET(compute_impl, p_info->curve_type);
+    context_size = BACKEND_IMPL_GET(compute_impl_context_size, p_info->curve_type);
+    VERIFY_TRUE(backend_implementation != NULL, NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE);
+
+    // Allocate context if not provided
+    if (p_context == NULL && context_size > 0)
+    {
+        p_allocated_context = NRF_CRYPTO_ALLOC(context_size);
+        VERIFY_TRUE(p_allocated_context != NULL, NRF_ERROR_CRYPTO_ALLOC_FAILED);
+        p_context = p_allocated_context;
+    }
+
+    // Execute backend implementation
+    result = backend_implementation(p_context, p_private_key, p_public_key, p_shared_secret);
+
+    // Deallocate context if allocated
+    if (p_allocated_context != NULL)
+    {
+        NRF_CRYPTO_FREE(p_allocated_context);
+    }
+
+    return result;
+}
+
+
+#endif // NRF_CRYPTO_ECC_ENABLED
diff --git a/examples/heart_rate_collector/nrf_crypto_ecdh.h b/examples/heart_rate_collector/nrf_crypto_ecdh.h
new file mode 100644
index 0000000..cfc318f
--- /dev/null
+++ b/examples/heart_rate_collector/nrf_crypto_ecdh.h
@@ -0,0 +1,201 @@
+/**
+ * Copyright (c) 2018, 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.
+ *
+ */
+
+#ifndef NRF_CRYPTO_ECDH_H__
+#define NRF_CRYPTO_ECDH_H__
+
+/** @addtogroup nrf_crypto
+ *  @{
+ *  @addtogroup nrf_crypto_ecdh Elliptic Curve Diffie-Hellman (ECDH)
+ *  @{
+ *  @brief Provides elliptic curve cryptography functions for Diffie-Hellman shared secret exchange.
+ *
+ *  @addtogroup nrf_crypto_ecdh_secp160r1   Definitions specific to secp160r1 (NIST 160-bit)
+ *  @addtogroup nrf_crypto_ecdh_secp160r2   Definitions specific to secp160r2 (NIST 160-bit)
+ *  @addtogroup nrf_crypto_ecdh_secp192r1   Definitions specific to secp192r1 (NIST 192-bit)
+ *  @addtogroup nrf_crypto_ecdh_secp224r1   Definitions specific to secp224r1 (NIST 224-bit)
+ *  @addtogroup nrf_crypto_ecdh_secp256r1   Definitions specific to secp256r1 (NIST 256-bit)
+ *  @addtogroup nrf_crypto_ecdh_secp384r1   Definitions specific to secp384r1 (NIST 384-bit)
+ *  @addtogroup nrf_crypto_ecdh_secp521r1   Definitions specific to secp521r1 (NIST 521-bit)
+ *  @addtogroup nrf_crypto_ecdh_secp160k1   Definitions specific to secp160k1 (Koblitz 160-bit)
+ *  @addtogroup nrf_crypto_ecdh_secp192k1   Definitions specific to secp192k1 (Koblitz 192-bit)
+ *  @addtogroup nrf_crypto_ecdh_secp224k1   Definitions specific to secp224k1 (Koblitz 224-bit)
+ *  @addtogroup nrf_crypto_ecdh_secp256k1   Definitions specific to secp256k1 (Koblitz 256-bit)
+ *  @addtogroup nrf_crypto_ecdh_bp256r1     Definitions specific to bp256r1 (Brainpool 256-bit)
+ *  @addtogroup nrf_crypto_ecdh_bp384r1     Definitions specific to bp384r1 (Brainpool 384-bit)
+ *  @addtogroup nrf_crypto_ecdh_bp512r1     Definitions specific to bp512r1 (Brainpool 512-bit)
+ *  @addtogroup nrf_crypto_ecdh_curve25519  Definitions specific to Curve25519
+ */
+
+#include <stdint.h>
+#include <stddef.h>
+
+#include "nrf_crypto_error.h"
+#include "nrf_crypto_ecc.h"
+#include "nrf_crypto_ecdh_shared.h"
+#include "nrf_crypto_ecdh_backend.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define NRF_CRYPTO_ECDH_SECP160R1_SHARED_SECRET_SIZE  (160 / 8)   /**< @brief Number of bytes in a shared secret using secp160r1 (NIST 160-bit).     @ingroup nrf_crypto_ecdh_secp160r1 */
+#define NRF_CRYPTO_ECDH_SECP160R2_SHARED_SECRET_SIZE  (160 / 8)   /**< @brief Number of bytes in a shared secret using secp160r2 (NIST 160-bit).     @ingroup nrf_crypto_ecdh_secp160r2 */
+#define NRF_CRYPTO_ECDH_SECP192R1_SHARED_SECRET_SIZE  (192 / 8)   /**< @brief Number of bytes in a shared secret using secp192r1 (NIST 192-bit).     @ingroup nrf_crypto_ecdh_secp192r1 */
+#define NRF_CRYPTO_ECDH_SECP224R1_SHARED_SECRET_SIZE  (224 / 8)   /**< @brief Number of bytes in a shared secret using secp224r1 (NIST 224-bit).     @ingroup nrf_crypto_ecdh_secp224r1 */
+#define NRF_CRYPTO_ECDH_SECP256R1_SHARED_SECRET_SIZE  (256 / 8)   /**< @brief Number of bytes in a shared secret using secp256r1 (NIST 256-bit).     @ingroup nrf_crypto_ecdh_secp256r1 */
+#define NRF_CRYPTO_ECDH_SECP384R1_SHARED_SECRET_SIZE  (384 / 8)   /**< @brief Number of bytes in a shared secret using secp384r1 (NIST 384-bit).     @ingroup nrf_crypto_ecdh_secp384r1 */
+#define NRF_CRYPTO_ECDH_SECP521R1_SHARED_SECRET_SIZE  (528 / 8)   /**< @brief Number of bytes in a shared secret using secp521r1 (NIST 521-bit).     @ingroup nrf_crypto_ecdh_secp521r1 */
+#define NRF_CRYPTO_ECDH_SECP160K1_SHARED_SECRET_SIZE  (160 / 8)   /**< @brief Number of bytes in a shared secret using secp160k1 (Koblitz 160-bit).  @ingroup nrf_crypto_ecdh_secp160k1 */
+#define NRF_CRYPTO_ECDH_SECP192K1_SHARED_SECRET_SIZE  (192 / 8)   /**< @brief Number of bytes in a shared secret using secp192k1 (Koblitz 192-bit).  @ingroup nrf_crypto_ecdh_secp192k1 */
+#define NRF_CRYPTO_ECDH_SECP224K1_SHARED_SECRET_SIZE  (224 / 8)   /**< @brief Number of bytes in a shared secret using secp224k1 (Koblitz 224-bit).  @ingroup nrf_crypto_ecdh_secp224k1 */
+#define NRF_CRYPTO_ECDH_SECP256K1_SHARED_SECRET_SIZE  (256 / 8)   /**< @brief Number of bytes in a shared secret using secp256k1 (Koblitz 256-bit).  @ingroup nrf_crypto_ecdh_secp256k1 */
+#define NRF_CRYPTO_ECDH_BP256R1_SHARED_SECRET_SIZE    (256 / 8)   /**< @brief Number of bytes in a shared secret using bp256r1 (Brainpool 256-bit).  @ingroup nrf_crypto_ecdh_bp256r1 */
+#define NRF_CRYPTO_ECDH_BP384R1_SHARED_SECRET_SIZE    (384 / 8)   /**< @brief Number of bytes in a shared secret using bp384r1 (Brainpool 384-bit).  @ingroup nrf_crypto_ecdh_bp384r1 */
+#define NRF_CRYPTO_ECDH_BP512R1_SHARED_SECRET_SIZE    (512 / 8)   /**< @brief Number of bytes in a shared secret using bp512r1 (Brainpool 512-bit).  @ingroup nrf_crypto_ecdh_bp512r1 */
+#define NRF_CRYPTO_ECDH_CURVE25519_SHARED_SECRET_SIZE (256 / 8)   /**< @brief Number of bytes in a shared secret using Curve25519.                   @ingroup nrf_crypto_ecdh_curve25519 */
+#define NRF_CRYPTO_ECDH_SHARED_SECRET_MAX_SIZE        NRF_CRYPTO_ECC_RAW_PRIVATE_KEY_MAX_SIZE  /**< @brief Maximum size of a shared secret in bytes for all enabled curves. */
+
+
+typedef nrf_crypto_backend_secp160r1_ecdh_context_t  nrf_crypto_ecdh_secp160r1_context_t;    /**< @brief Context used to store temporary data during computing ECDH for curve secp160r1 (NIST 160-bit).     @ingroup nrf_crypto_ecdh_secp160r1 */
+typedef nrf_crypto_backend_secp160r2_ecdh_context_t  nrf_crypto_ecdh_secp160r2_context_t;    /**< @brief Context used to store temporary data during computing ECDH for curve secp160r2 (NIST 160-bit).     @ingroup nrf_crypto_ecdh_secp160r2 */
+typedef nrf_crypto_backend_secp192r1_ecdh_context_t  nrf_crypto_ecdh_secp192r1_context_t;    /**< @brief Context used to store temporary data during computing ECDH for curve secp192r1 (NIST 192-bit).     @ingroup nrf_crypto_ecdh_secp192r1 */
+typedef nrf_crypto_backend_secp224r1_ecdh_context_t  nrf_crypto_ecdh_secp224r1_context_t;    /**< @brief Context used to store temporary data during computing ECDH for curve secp224r1 (NIST 224-bit).     @ingroup nrf_crypto_ecdh_secp224r1 */
+typedef nrf_crypto_backend_secp256r1_ecdh_context_t  nrf_crypto_ecdh_secp256r1_context_t;    /**< @brief Context used to store temporary data during computing ECDH for curve secp256r1 (NIST 256-bit).     @ingroup nrf_crypto_ecdh_secp256r1 */
+typedef nrf_crypto_backend_secp384r1_ecdh_context_t  nrf_crypto_ecdh_secp384r1_context_t;    /**< @brief Context used to store temporary data during computing ECDH for curve secp384r1 (NIST 384-bit).     @ingroup nrf_crypto_ecdh_secp384r1 */
+typedef nrf_crypto_backend_secp521r1_ecdh_context_t  nrf_crypto_ecdh_secp521r1_context_t;    /**< @brief Context used to store temporary data during computing ECDH for curve secp521r1 (NIST 521-bit).     @ingroup nrf_crypto_ecdh_secp521r1 */
+typedef nrf_crypto_backend_secp160k1_ecdh_context_t  nrf_crypto_ecdh_secp160k1_context_t;    /**< @brief Context used to store temporary data during computing ECDH for curve secp160k1 (Koblitz 160-bit).  @ingroup nrf_crypto_ecdh_secp160k1 */
+typedef nrf_crypto_backend_secp192k1_ecdh_context_t  nrf_crypto_ecdh_secp192k1_context_t;    /**< @brief Context used to store temporary data during computing ECDH for curve secp192k1 (Koblitz 192-bit).  @ingroup nrf_crypto_ecdh_secp192k1 */
+typedef nrf_crypto_backend_secp224k1_ecdh_context_t  nrf_crypto_ecdh_secp224k1_context_t;    /**< @brief Context used to store temporary data during computing ECDH for curve secp224k1 (Koblitz 224-bit).  @ingroup nrf_crypto_ecdh_secp224k1 */
+typedef nrf_crypto_backend_secp256k1_ecdh_context_t  nrf_crypto_ecdh_secp256k1_context_t;    /**< @brief Context used to store temporary data during computing ECDH for curve secp256k1 (Koblitz 256-bit).  @ingroup nrf_crypto_ecdh_secp256k1 */
+typedef nrf_crypto_backend_bp256r1_ecdh_context_t    nrf_crypto_ecdh_bp256r1_context_t;      /**< @brief Context used to store temporary data during computing ECDH for curve bp256r1 (Brainpool 256-bit).  @ingroup nrf_crypto_ecdh_bp256r1 */
+typedef nrf_crypto_backend_bp384r1_ecdh_context_t    nrf_crypto_ecdh_bp384r1_context_t;      /**< @brief Context used to store temporary data during computing ECDH for curve bp384r1 (Brainpool 384-bit).  @ingroup nrf_crypto_ecdh_bp384r1 */
+typedef nrf_crypto_backend_bp512r1_ecdh_context_t    nrf_crypto_ecdh_bp512r1_context_t;      /**< @brief Context used to store temporary data during computing ECDH for curve bp512r1 (Brainpool 512-bit).  @ingroup nrf_crypto_ecdh_bp512r1 */
+typedef nrf_crypto_backend_curve25519_ecdh_context_t nrf_crypto_ecdh_curve25519_context_t;   /**< @brief Context used to store temporary data during computing ECDH for curve Curve25519.                   @ingroup nrf_crypto_ecdh_curve25519 */
+
+
+typedef uint8_t nrf_crypto_ecdh_secp160r1_shared_secret_t
+    [NRF_CRYPTO_ECDH_SECP160R1_SHARED_SECRET_SIZE];        /**< @brief Array type of a shared secret for curve secp160r1 (NIST 160-bit).  @ingroup nrf_crypto_ecdh_secp160r1 */
+typedef uint8_t nrf_crypto_ecdh_secp160r2_shared_secret_t
+    [NRF_CRYPTO_ECDH_SECP160R2_SHARED_SECRET_SIZE];        /**< @brief Array type of a shared secret for curve secp160r2 (NIST 160-bit).  @ingroup nrf_crypto_ecdh_secp160r2 */
+typedef uint8_t nrf_crypto_ecdh_secp192r1_shared_secret_t
+    [NRF_CRYPTO_ECDH_SECP192R1_SHARED_SECRET_SIZE];        /**< @brief Array type of a shared secret for curve secp192r1 (NIST 192-bit).  @ingroup nrf_crypto_ecdh_secp192r1 */
+typedef uint8_t nrf_crypto_ecdh_secp224r1_shared_secret_t
+    [NRF_CRYPTO_ECDH_SECP224R1_SHARED_SECRET_SIZE];        /**< @brief Array type of a shared secret for curve secp224r1 (NIST 224-bit).  @ingroup nrf_crypto_ecdh_secp224r1 */
+typedef uint8_t nrf_crypto_ecdh_secp256r1_shared_secret_t
+    [NRF_CRYPTO_ECDH_SECP256R1_SHARED_SECRET_SIZE];        /**< @brief Array type of a shared secret for curve secp256r1 (NIST 256-bit).  @ingroup nrf_crypto_ecdh_secp256r1 */
+typedef uint8_t nrf_crypto_ecdh_secp384r1_shared_secret_t
+    [NRF_CRYPTO_ECDH_SECP384R1_SHARED_SECRET_SIZE];        /**< @brief Array type of a shared secret for curve secp384r1 (NIST 384-bit).  @ingroup nrf_crypto_ecdh_secp384r1 */
+typedef uint8_t nrf_crypto_ecdh_secp521r1_shared_secret_t
+    [NRF_CRYPTO_ECDH_SECP521R1_SHARED_SECRET_SIZE];        /**< @brief Array type of a shared secret for curve secp521r1 (NIST 521-bit).  @ingroup nrf_crypto_ecdh_secp521r1 */
+typedef uint8_t nrf_crypto_ecdh_secp160k1_shared_secret_t
+    [NRF_CRYPTO_ECDH_SECP160K1_SHARED_SECRET_SIZE];        /**< @brief Array type of a shared secret for curve secp160k1 (Koblitz 160-bit).  @ingroup nrf_crypto_ecdh_secp160k1 */
+typedef uint8_t nrf_crypto_ecdh_secp192k1_shared_secret_t
+    [NRF_CRYPTO_ECDH_SECP192K1_SHARED_SECRET_SIZE];        /**< @brief Array type of a shared secret for curve secp192k1 (Koblitz 192-bit).  @ingroup nrf_crypto_ecdh_secp192k1 */
+typedef uint8_t nrf_crypto_ecdh_secp224k1_shared_secret_t
+    [NRF_CRYPTO_ECDH_SECP224K1_SHARED_SECRET_SIZE];        /**< @brief Array type of a shared secret for curve secp224k1 (Koblitz 224-bit).  @ingroup nrf_crypto_ecdh_secp224k1 */
+typedef uint8_t nrf_crypto_ecdh_secp256k1_shared_secret_t
+    [NRF_CRYPTO_ECDH_SECP256K1_SHARED_SECRET_SIZE];        /**< @brief Array type of a shared secret for curve secp256k1 (Koblitz 256-bit).  @ingroup nrf_crypto_ecdh_secp256k1 */
+typedef uint8_t nrf_crypto_ecdh_bp256r1_shared_secret_t
+    [NRF_CRYPTO_ECDH_BP256R1_SHARED_SECRET_SIZE];          /**< @brief Array type of a shared secret for curve bp256r1 (Brainpool 256-bit).  @ingroup nrf_crypto_ecdh_bp256r1 */
+typedef uint8_t nrf_crypto_ecdh_bp384r1_shared_secret_t
+    [NRF_CRYPTO_ECDH_BP384R1_SHARED_SECRET_SIZE];          /**< @brief Array type of a shared secret for curve bp384r1 (Brainpool 384-bit).  @ingroup nrf_crypto_ecdh_bp384r1 */
+typedef uint8_t nrf_crypto_ecdh_bp512r1_shared_secret_t
+    [NRF_CRYPTO_ECDH_BP512R1_SHARED_SECRET_SIZE];          /**< @brief Array type of a shared secret for curve bp512r1 (Brainpool 512-bit).  @ingroup nrf_crypto_ecdh_bp512r1 */
+typedef uint8_t nrf_crypto_ecdh_curve25519_shared_secret_t
+    [NRF_CRYPTO_ECDH_CURVE25519_SHARED_SECRET_SIZE];       /**< @brief Array type of a shared secret for curve Curve25519.  @ingroup nrf_crypto_ecdh_curve25519 */
+typedef uint8_t nrf_crypto_ecdh_shared_secret_t
+    [NRF_CRYPTO_ECDH_SHARED_SECRET_MAX_SIZE];              /**< @brief Array type of a shared secret for any of the enabled curves. */
+
+
+/** @brief Union holding a context for ECDH computation.
+ */
+typedef union
+{
+    nrf_crypto_ecdh_secp160r1_context_t  context_secp160r1;   /**< @brief Occupies space for secp160r1 (NIST 160-bit). */
+    nrf_crypto_ecdh_secp160r2_context_t  context_secp160r2;   /**< @brief Occupies space for secp160r2 (NIST 160-bit). */
+    nrf_crypto_ecdh_secp192r1_context_t  context_secp192r1;   /**< @brief Occupies space for secp192r1 (NIST 192-bit). */
+    nrf_crypto_ecdh_secp224r1_context_t  context_secp224r1;   /**< @brief Occupies space for secp224r1 (NIST 224-bit). */
+    nrf_crypto_ecdh_secp256r1_context_t  context_secp256r1;   /**< @brief Occupies space for secp256r1 (NIST 256-bit). */
+    nrf_crypto_ecdh_secp384r1_context_t  context_secp384r1;   /**< @brief Occupies space for secp384r1 (NIST 384-bit). */
+    nrf_crypto_ecdh_secp521r1_context_t  context_secp521r1;   /**< @brief Occupies space for secp521r1 (NIST 521-bit). */
+    nrf_crypto_ecdh_secp160k1_context_t  context_secp160k1;   /**< @brief Occupies space for secp160k1 (Koblitz 160-bit). */
+    nrf_crypto_ecdh_secp192k1_context_t  context_secp192k1;   /**< @brief Occupies space for secp192k1 (Koblitz 192-bit). */
+    nrf_crypto_ecdh_secp224k1_context_t  context_secp224k1;   /**< @brief Occupies space for secp224k1 (Koblitz 224-bit). */
+    nrf_crypto_ecdh_secp256k1_context_t  context_secp256k1;   /**< @brief Occupies space for secp256k1 (Koblitz 256-bit). */
+    nrf_crypto_ecdh_bp256r1_context_t    context_bp256r1;     /**< @brief Occupies space for bp256r1 (Brainpool 256-bit). */
+    nrf_crypto_ecdh_bp384r1_context_t    context_bp384r1;     /**< @brief Occupies space for bp384r1 (Brainpool 384-bit). */
+    nrf_crypto_ecdh_bp512r1_context_t    context_bp512r1;     /**< @brief Occupies space for bp512r1 (Brainpool 512-bit). */
+    nrf_crypto_ecdh_curve25519_context_t context_curve25519;  /**< @brief Occupies space for Curve25519. */
+} nrf_crypto_ecdh_context_t;
+
+
+/** @brief Computes shared secret using ECC Diffie-Hellman.
+ *
+ *  @param[in]     p_context             Pointer to temporary structure holding context information.
+ *                                       If it is NULL, necessary data will be allocated with
+ *                                       @ref NRF_CRYPTO_ALLOC and freed at the end of the function.
+ *  @param[in]     p_private_key         Pointer to structure holding a private key.
+ *  @param[in]     p_public_key          Pointer to structure holding a public key received from the other party.
+ *  @param[out]    p_shared_secret       Pointer to buffer where shared secret will be put.
+ *  @param[in,out] p_shared_secret_size  Maximum number of bytes that @p p_shared_secret buffer can hold on input
+ *                                       and the actual number of bytes used by the data on output.
+ *                                       Actual size for selected curve is defined by
+ *                                       the preprocessor definitions, e.g.
+ *                                       @ref NRF_CRYPTO_ECDH_SECP256R1_SHARED_SECRET_SIZE.
+ */
+ret_code_t nrf_crypto_ecdh_compute(
+    nrf_crypto_ecdh_context_t          * p_context,
+    nrf_crypto_ecc_private_key_t const * p_private_key,
+    nrf_crypto_ecc_public_key_t  const * p_public_key,
+    uint8_t                            * p_shared_secret,
+    size_t                             * p_shared_secret_size);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @}
+ *  @}
+ */
+
+#endif // NRF_CRYPTO_ECDH_H__
diff --git a/examples/heart_rate_collector/nrf_crypto_ecdh_backend.h b/examples/heart_rate_collector/nrf_crypto_ecdh_backend.h
new file mode 100644
index 0000000..77d2ba3
--- /dev/null
+++ b/examples/heart_rate_collector/nrf_crypto_ecdh_backend.h
@@ -0,0 +1,184 @@
+/**
+ * Copyright (c) 2018, 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.
+ *
+ */
+
+#ifndef NRF_CRYPTO_ECDH_BACKEND_H__
+#define NRF_CRYPTO_ECDH_BACKEND_H__
+#if !defined(__SDK_DOXYGEN__)
+
+#include <stdint.h>
+#include <stddef.h>
+
+#include "sdk_errors.h"
+// #include "sdk_config.h"
+#include "nrf_crypto_ecc.h"
+#include "nrf_crypto_ecdh_shared.h"
+
+// Include all backends
+// #include "cc310_backend_ecdh.h"
+// #include "cc310_bl_backend_ecdh.h"
+// #include "mbedtls_backend_ecdh.h"
+// #include "oberon_backend_ecdh.h"
+#include "micro_ecc_backend_ecdh.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#if !NRF_CRYPTO_ECC_SECP160R1_ENABLED
+// Dummy typedef for disabled context
+typedef uint32_t nrf_crypto_backend_secp160r1_ecdh_context_t;
+// Backend implementation is NULL to indicate feature not supported
+#define nrf_crypto_backend_secp160r1_ecdh_compute NULL
+#endif
+
+#if !NRF_CRYPTO_ECC_SECP160R2_ENABLED
+// Dummy typedef for disabled context
+typedef uint32_t nrf_crypto_backend_secp160r2_ecdh_context_t;
+// Backend implementation is NULL to indicate feature not supported
+#define nrf_crypto_backend_secp160r2_ecdh_compute NULL
+#endif
+
+#if !NRF_CRYPTO_ECC_SECP192R1_ENABLED
+// Dummy typedef for disabled context
+typedef uint32_t nrf_crypto_backend_secp192r1_ecdh_context_t;
+// Backend implementation is NULL to indicate feature not supported
+#define nrf_crypto_backend_secp192r1_ecdh_compute NULL
+#endif
+
+#if !NRF_CRYPTO_ECC_SECP224R1_ENABLED
+// Dummy typedef for disabled context
+typedef uint32_t nrf_crypto_backend_secp224r1_ecdh_context_t;
+// Backend implementation is NULL to indicate feature not supported
+#define nrf_crypto_backend_secp224r1_ecdh_compute NULL
+#endif
+
+#if !NRF_CRYPTO_ECC_SECP256R1_ENABLED
+// Dummy typedef for disabled context
+typedef uint32_t nrf_crypto_backend_secp256r1_ecdh_context_t;
+// Backend implementation is NULL to indicate feature not supported
+#define nrf_crypto_backend_secp256r1_ecdh_compute NULL
+#endif
+
+#if !NRF_CRYPTO_ECC_SECP384R1_ENABLED
+// Dummy typedef for disabled context
+typedef uint32_t nrf_crypto_backend_secp384r1_ecdh_context_t;
+// Backend implementation is NULL to indicate feature not supported
+#define nrf_crypto_backend_secp384r1_ecdh_compute NULL
+#endif
+
+#if !NRF_CRYPTO_ECC_SECP521R1_ENABLED
+// Dummy typedef for disabled context
+typedef uint32_t nrf_crypto_backend_secp521r1_ecdh_context_t;
+// Backend implementation is NULL to indicate feature not supported
+#define nrf_crypto_backend_secp521r1_ecdh_compute NULL
+#endif
+
+#if !NRF_CRYPTO_ECC_SECP160K1_ENABLED
+// Dummy typedef for disabled context
+typedef uint32_t nrf_crypto_backend_secp160k1_ecdh_context_t;
+// Backend implementation is NULL to indicate feature not supported
+#define nrf_crypto_backend_secp160k1_ecdh_compute NULL
+#endif
+
+#if !NRF_CRYPTO_ECC_SECP192K1_ENABLED
+// Dummy typedef for disabled context
+typedef uint32_t nrf_crypto_backend_secp192k1_ecdh_context_t;
+// Backend implementation is NULL to indicate feature not supported
+#define nrf_crypto_backend_secp192k1_ecdh_compute NULL
+#endif
+
+#if !NRF_CRYPTO_ECC_SECP224K1_ENABLED
+// Dummy typedef for disabled context
+typedef uint32_t nrf_crypto_backend_secp224k1_ecdh_context_t;
+// Backend implementation is NULL to indicate feature not supported
+#define nrf_crypto_backend_secp224k1_ecdh_compute NULL
+#endif
+
+#if !NRF_CRYPTO_ECC_SECP256K1_ENABLED
+// Dummy typedef for disabled context
+typedef uint32_t nrf_crypto_backend_secp256k1_ecdh_context_t;
+// Backend implementation is NULL to indicate feature not supported
+#define nrf_crypto_backend_secp256k1_ecdh_compute NULL
+#endif
+
+#if !NRF_CRYPTO_ECC_BP256R1_ENABLED
+// Dummy typedef for disabled context
+typedef uint32_t nrf_crypto_backend_bp256r1_ecdh_context_t;
+// Backend implementation is NULL to indicate feature not supported
+#define nrf_crypto_backend_bp256r1_ecdh_compute NULL
+#endif
+
+#if !NRF_CRYPTO_ECC_BP384R1_ENABLED
+// Dummy typedef for disabled context
+typedef uint32_t nrf_crypto_backend_bp384r1_ecdh_context_t;
+// Backend implementation is NULL to indicate feature not supported
+#define nrf_crypto_backend_bp384r1_ecdh_compute NULL
+#endif
+
+#if !NRF_CRYPTO_ECC_BP512R1_ENABLED
+// Dummy typedef for disabled context
+typedef uint32_t nrf_crypto_backend_bp512r1_ecdh_context_t;
+// Backend implementation is NULL to indicate feature not supported
+#define nrf_crypto_backend_bp512r1_ecdh_compute NULL
+#endif
+
+#if !NRF_CRYPTO_ECC_CURVE25519_ENABLED
+// Dummy typedef for disabled context
+typedef uint32_t nrf_crypto_backend_curve25519_ecdh_context_t;
+// Backend implementation is NULL to indicate feature not supported
+#define nrf_crypto_backend_curve25519_ecdh_compute NULL
+#endif
+
+#if !NRF_CRYPTO_ECC_ED25519_ENABLED
+// Dummy typedef for disabled context
+typedef uint32_t nrf_crypto_backend_ed25519_ecdh_context_t;
+// Backend implementation is NULL to indicate feature not supported
+#define nrf_crypto_backend_ed25519_ecdh_compute NULL
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // !defined(__SDK_DOXYGEN__)
+#endif // NRF_CRYPTO_ECDH_BACKEND_H__
diff --git a/examples/heart_rate_collector/nrf_crypto_ecdh_shared.h b/examples/heart_rate_collector/nrf_crypto_ecdh_shared.h
new file mode 100644
index 0000000..df39494
--- /dev/null
+++ b/examples/heart_rate_collector/nrf_crypto_ecdh_shared.h
@@ -0,0 +1,79 @@
+/**
+ * Copyright (c) 2018, 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.
+ *
+ */
+
+#ifndef NRF_CRYPTO_ECDH_SHARED_H__
+#define NRF_CRYPTO_ECDH_SHARED_H__
+#if !defined(__SDK_DOXYGEN__)
+
+#include <stdint.h>
+#include <stddef.h>
+
+#include "sdk_errors.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/** @internal @brief Function pointer for backend implementation of ECDH.
+ *
+ * @note All parameters provided to the backend are vefified in frontend. Verification includes
+ * checking of NULL pointers, buffer size, initialization values. Front end also take full care of
+ * common ECC key hearder @ref nrf_crypto_internal_ecc_key_header_t.
+ *
+ * @param[in]  p_context       Pointer to context.
+ * @param[in]  p_private_key   Pointer to private key.
+ * @param[in]  p_public_key    Pointer to public key.
+ * @param[out] p_shared_secret Pointer where to put generated shared secret.
+ */
+typedef ret_code_t (*nrf_crypto_backend_ecdh_compute_fn_t)(
+    void       * p_context,
+    void const * p_private_key,
+    void const * p_public_key,
+    uint8_t    * p_shared_secret);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // !defined(__SDK_DOXYGEN__)
+#endif // NRF_CRYPTO_ECDH_SHARED_H__
diff --git a/examples/heart_rate_collector/nrf_crypto_error.h b/examples/heart_rate_collector/nrf_crypto_error.h
new file mode 100644
index 0000000..9f23463
--- /dev/null
+++ b/examples/heart_rate_collector/nrf_crypto_error.h
@@ -0,0 +1,113 @@
+/**
+ * Copyright (c) 2017 - 2018, 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.
+ *
+ */
+
+#ifndef NRF_CRYPTO_ERROR_H__
+#define NRF_CRYPTO_ERROR_H__
+
+/**@file
+ *
+ * @defgroup nrf_crypto_error nrf_crypto error codes
+ * @{
+ * @ingroup nrf_crypto
+ *
+ * @details This is the standardized error codes provided when calling nrf_crypto APIs.
+ *          The error codes provided here are enumerated based on @ref NRF_ERROR_CRYPTO_ERR_BASE.
+ *
+ * @note Success code, NRF_SUCCESS, is used if the nrf_crypto operation was successful.
+ *
+ */
+
+#include "sdk_errors.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define NRF_ERROR_CRYPTO_NOT_INITIALIZED            (NRF_ERROR_CRYPTO_ERR_BASE + 0x00)      /**< @ref nrf_crypto_init was not called prior to this crypto function. */
+#define NRF_ERROR_CRYPTO_CONTEXT_NULL               (NRF_ERROR_CRYPTO_ERR_BASE + 0x01)      /**< A null pointer was provided for the context structure. */
+#define NRF_ERROR_CRYPTO_CONTEXT_NOT_INITIALIZED    (NRF_ERROR_CRYPTO_ERR_BASE + 0x02)      /**< The context was not initialized prior to this call or it was corrupted. Call the corresponding init function for the algorithm to initialize it. */
+#define NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE        (NRF_ERROR_CRYPTO_ERR_BASE + 0x03)      /**< The function was called with a feature that is unavailable. */
+#define NRF_ERROR_CRYPTO_BUSY                       (NRF_ERROR_CRYPTO_ERR_BASE + 0x04)      /**< The function could not be called because the crypto backend was busy. Rerun the cryptographic routine at a later time. */
+
+#define NRF_ERROR_CRYPTO_INPUT_NULL                 (NRF_ERROR_CRYPTO_ERR_BASE + 0x10)      /**< One or more of the input arguments for this function were NULL. */
+#define NRF_ERROR_CRYPTO_INPUT_LENGTH               (NRF_ERROR_CRYPTO_ERR_BASE + 0x11)      /**< The length of one or more of the input arguments was invalid. */
+#define NRF_ERROR_CRYPTO_INPUT_LOCATION             (NRF_ERROR_CRYPTO_ERR_BASE + 0x12)      /**< Input data not in RAM. */
+#define NRF_ERROR_CRYPTO_OUTPUT_NULL                (NRF_ERROR_CRYPTO_ERR_BASE + 0x13)      /**< One or more of the output arguments for this function were NULL. */
+#define NRF_ERROR_CRYPTO_OUTPUT_LENGTH              (NRF_ERROR_CRYPTO_ERR_BASE + 0x14)      /**< The length of one or more output arguments was too small. */
+#define NRF_ERROR_CRYPTO_ALLOC_FAILED               (NRF_ERROR_CRYPTO_ERR_BASE + 0x15)      /**< A required memory allocation failed. */
+#define NRF_ERROR_CRYPTO_INTERNAL                   (NRF_ERROR_CRYPTO_ERR_BASE + 0x16)      /**< An internal error occurred when calling this function. */
+#define NRF_ERROR_CRYPTO_INVALID_PARAM              (NRF_ERROR_CRYPTO_ERR_BASE + 0x17)      /**< Invalid combination of input parameters. */
+#define NRF_ERROR_CRYPTO_KEY_SIZE                   (NRF_ERROR_CRYPTO_ERR_BASE + 0x18)      /**< Size of the key is not supported by choosen backend. */
+#define NRF_ERROR_CRYPTO_STACK_OVERFLOW             (NRF_ERROR_CRYPTO_ERR_BASE + 0x19)      /**< Stack overflow detected. */
+
+#define NRF_ERROR_CRYPTO_ECC_ERR_BASE               (NRF_ERROR_CRYPTO_ERR_BASE + 0x40)      /**< Base error code for ECC. */
+#define NRF_ERROR_CRYPTO_ECC_KEY_NOT_INITIALIZED    (NRF_ERROR_CRYPTO_ECC_ERR_BASE + 0x00)  /**< The key was not initialized. */
+#define NRF_ERROR_CRYPTO_ECDH_CURVE_MISMATCH        (NRF_ERROR_CRYPTO_ECC_ERR_BASE + 0x01)  /**< Public and private key provided to ECDH have different types of curves. */
+#define NRF_ERROR_CRYPTO_ECDSA_INVALID_SIGNATURE    (NRF_ERROR_CRYPTO_ECC_ERR_BASE + 0x02)  /**< Signature verification check reported invalid signature. */
+#define NRF_ERROR_CRYPTO_ECC_INVALID_KEY            (NRF_ERROR_CRYPTO_ECC_ERR_BASE + 0x03)  /**< Provided key is invalid. */
+
+#define NRF_ERROR_CRYPTO_AES_ERR_BASE               (NRF_ERROR_CRYPTO_ERR_BASE + 0x50)      /**< Base error code for all AES modes. */
+#define NRF_ERROR_CRYPTO_AES_INVALID_PADDING        (NRF_ERROR_CRYPTO_AES_ERR_BASE + 0x00)  /**< Message padding is corrupted. */
+
+#define NRF_ERROR_CRYPTO_AEAD_ERR_BASE              (NRF_ERROR_CRYPTO_ERR_BASE + 0x60)      /**< Base error code for all AEAD modes. */
+#define NRF_ERROR_CRYPTO_AEAD_INVALID_MAC           (NRF_ERROR_CRYPTO_AEAD_ERR_BASE + 0x00) /**< MAC not matching encrypted text. */
+#define NRF_ERROR_CRYPTO_AEAD_NONCE_SIZE            (NRF_ERROR_CRYPTO_AEAD_ERR_BASE + 0x01) /**< Size of the nonce is not supported in this AEAD mode. */
+#define NRF_ERROR_CRYPTO_AEAD_MAC_SIZE              (NRF_ERROR_CRYPTO_AEAD_ERR_BASE + 0x02) /**< Size of the MAC (tag) is not supported in this AEAD mode. */
+
+#define NRF_ERROR_CRYPTO_RNG_ERR_BASE               (NRF_ERROR_CRYPTO_ERR_BASE + 0x70)      /**< Base error code for all RNG modes. */
+#define NRF_ERROR_CRYPTO_RNG_INIT_FAILED            (NRF_ERROR_CRYPTO_RNG_ERR_BASE + 0x00)  /**< Initialization or startup of RNG failed. */
+#define NRF_ERROR_CRYPTO_RNG_RESEED_REQUIRED        (NRF_ERROR_CRYPTO_RNG_ERR_BASE + 0x01)  /**< Reseed required (reseed counter overflowed). */
+
+/**
+ * @brief Function for converting an nrf_crypto error to a printable string pointer.
+ *
+ * @param[in] error     Error code.
+ *
+ * @return              Pointer to string explaining nrf_crypto error.
+ * */
+char const * nrf_crypto_error_string_get(ret_code_t error);
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */
+
+#endif // NRF_CRYPTO_ERROR_H__
diff --git a/examples/heart_rate_collector/nrf_crypto_mem.h b/examples/heart_rate_collector/nrf_crypto_mem.h
new file mode 100644
index 0000000..7281746
--- /dev/null
+++ b/examples/heart_rate_collector/nrf_crypto_mem.h
@@ -0,0 +1,186 @@
+/**
+ * Copyright (c) 2018, 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.
+ *
+ */
+
+#ifndef NRF_CRYPTO_MEM_H__
+#define NRF_CRYPTO_MEM_H__
+
+/** @file
+ *
+ * @defgroup nrf_crypto_mem Dynamic memory management module
+ * @{
+ * @ingroup nrf_crypto
+ *
+ * @brief Module to manage dynamically allocated memory used by nrf_crypto APIs.
+ *
+ * @ref NRF_CRYPTO_ALLOCATOR definition is used to configure this module.
+ */
+
+#include <stdint.h>
+// #include "sdk_common.h"
+// #include "sdk_config.h"
+#include "nrf_crypto_types.h"
+#include "sdk_alloca.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#ifndef __SDK_DOXYGEN__
+
+
+#define NRF_CRYPTO_ALLOCATOR_DEFAULT    0  /**< @internal @brief Value for NRF_CRYPTO_ALLOCATOR to select default memory allocation. */
+#define NRF_CRYPTO_ALLOCATOR_USER       1  /**< @internal @brief Value for NRF_CRYPTO_ALLOCATOR to select user defined memory allocation. */
+#define NRF_CRYPTO_ALLOCATOR_ALLOCA     2  /**< @internal @brief Value for NRF_CRYPTO_ALLOCATOR to select stack based memory allocation. */
+#define NRF_CRYPTO_ALLOCATOR_MALLOC     3  /**< @internal @brief Value for NRF_CRYPTO_ALLOCATOR to select stdlib's dynamic memory allocation. */
+#define NRF_CRYPTO_ALLOCATOR_NRF_MALLOC 4  /**< @internal @brief Value for NRF_CRYPTO_ALLOCATOR to select mem_manager for memory allocation. */
+
+
+#ifndef NRF_CRYPTO_ALLOCATOR
+#define NRF_CRYPTO_ALLOCATOR NRF_CRYPTO_ALLOCATOR_DEFAULT
+#endif
+
+
+#if NRF_CRYPTO_ALLOCATOR == NRF_CRYPTO_ALLOCATOR_DEFAULT
+#undef NRF_CRYPTO_ALLOCATOR
+#if SDK_ALLOCA_DEFINED// && !NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS)
+#define NRF_CRYPTO_ALLOCATOR NRF_CRYPTO_ALLOCATOR_ALLOCA
+#else
+#define NRF_CRYPTO_ALLOCATOR NRF_CRYPTO_ALLOCATOR_NRF_MALLOC
+#endif
+#endif
+
+
+#if NRF_CRYPTO_ALLOCATOR == NRF_CRYPTO_ALLOCATOR_USER
+
+#include "nrf_crypto_allocator.h"
+#ifndef NRF_CRYPTO_ALLOC
+#error "User defined allocator for nrf_crypto does not define NRF_CRYPTO_ALLOC"
+#endif
+#ifndef NRF_CRYPTO_FREE
+#error "User defined allocator for nrf_crypto does not define NRF_CRYPTO_FREE"
+#endif
+#ifndef NRF_CRYPTO_ALLOC_ON_STACK
+#error "User defined allocator for nrf_crypto does not define NRF_CRYPTO_ALLOC_ON_STACK"
+#endif
+
+#elif NRF_CRYPTO_ALLOCATOR == NRF_CRYPTO_ALLOCATOR_ALLOCA
+
+#if !SDK_ALLOCA_DEFINED
+#warning "Stack based allocation is selected, but alloca() is not supported on this platform"
+#endif
+#define NRF_CRYPTO_ALLOC(size)    (alloca((size_t)(size)))
+#define NRF_CRYPTO_FREE(p_buffer) // Empty
+#define NRF_CRYPTO_ALLOC_ON_STACK 1
+
+#elif NRF_CRYPTO_ALLOCATOR == NRF_CRYPTO_ALLOCATOR_MALLOC
+
+#include "stdlib.h"
+#define NRF_CRYPTO_ALLOC(size)    (malloc((size_t)(size)))
+#define NRF_CRYPTO_FREE(p_buffer) (free((void *)(p_buffer)))
+#define NRF_CRYPTO_ALLOC_ON_STACK 0
+
+#elif NRF_CRYPTO_ALLOCATOR == NRF_CRYPTO_ALLOCATOR_NRF_MALLOC
+
+// #include "mem_manager.h"
+// #define NRF_CRYPTO_ALLOC(size)    (nrf_malloc((uint32_t)(size)))
+// #define NRF_CRYPTO_FREE(p_buffer) (nrf_free((void *)(p_buffer)))
+// #define NRF_CRYPTO_ALLOC_ON_STACK 0
+#error "No support for mem_manager for memory allocation"
+
+#else
+
+#error "Invalid NRF_CRYPTO_ALLOCATOR configuration value"
+
+#endif
+
+
+#else // __SDK_DOXYGEN__
+
+
+/** @brief Defines memory allocation function for nrf_crypto.
+ *
+ *  This macro is used internally by nrf_crypto library to allocate temporary memory. It is not
+ *  intended to be used outside nrf_crypto library. How memory is actually allocated is configured
+ *  by @ref NRF_CRYPTO_ALLOCATOR definition.
+ *
+ *  If user macros are selected by @ref NRF_CRYPTO_ALLOCATOR then this macro have to be defined by
+ *  the user in "nrf_crypto_allocator.h" file. The file will be included into "nrf_crypto_mem.h".
+ *
+ *  If @ref NRF_CRYPTO_ALLOC_ON_STACK is 1 then this function will allocate data on stack,
+ *  so make sure that returned pointer is not used outside the caller function.
+ *
+ *  @param size      Number of bytes to allocate.
+ *  @returns         Pointer to newly allocated memory or NULL on error.
+ */
+#define NRF_CRYPTO_ALLOC(size)
+
+/** @brief Defines memory deallocation function for nrf_crypto.
+ *
+ *  This macro is used internally by nrf_crypto library to deallocate temporary memory. It is not
+ *  intended to be used outside nrf_crypto library.
+ *
+ *  If user macros are selected by @ref NRF_CRYPTO_ALLOCATOR then this macro have to be defined by
+ *  the user in "nrf_crypto_allocator.h" file. The file will be included into "nrf_crypto_mem.h".
+ *
+ *  @param p_buffer  Pointer to memory buffer for deallocation.
+ */
+#define NRF_CRYPTO_FREE(p_buffer)
+
+/** @brief Contains 1 if memory allocated by @ref NRF_CRYPTO_ALLOC is on stack or 0 otherwise.
+ *
+ *  This definition is used internally by nrf_crypto library. It is not intended to be used outside
+ *  nrf_crypto library.
+ *
+ *  If user macros are selected by @ref NRF_CRYPTO_ALLOCATOR then this macro have to be defined by
+ *  the user in "nrf_crypto_allocator.h" file. The file will be included into "nrf_crypto_mem.h".
+ */
+#define NRF_CRYPTO_ALLOC_ON_STACK
+
+
+#endif // __SDK_DOXYGEN__
+
+#ifdef __cplusplus
+}
+#endif
+
+/**@} */
+
+ #endif // NRF_CRYPTO_MEM_H__
diff --git a/examples/heart_rate_collector/nrf_crypto_shared.c b/examples/heart_rate_collector/nrf_crypto_shared.c
new file mode 100644
index 0000000..70311c3
--- /dev/null
+++ b/examples/heart_rate_collector/nrf_crypto_shared.c
@@ -0,0 +1,114 @@
+/**
+ * Copyright (c) 2018, 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.
+ *
+ */
+
+// #include "sdk_config.h"
+#include "nordic_common.h"
+#include "nrf_crypto_shared.h"
+
+
+// #if NRF_MODULE_ENABLED(NRF_CRYPTO)
+
+
+void nrf_crypto_internal_swap_endian_in_place(uint8_t * p_buffer, size_t size)
+{
+    // ASSERT(p_buffer != NULL);
+    if (p_buffer == NULL)
+    {
+        printf("ERROR: nrf_crypto_internal_swap_endian_in_place get NULL buffer\n");
+        fflush(stdout);
+        return;
+    }
+
+    uint8_t temp;
+    uint8_t * p_first = p_buffer;
+    uint8_t * p_last = p_buffer + size - 1;
+    while (p_last >= p_first)
+    {
+        temp = *p_first;
+        *p_first = *p_last;
+        *p_last = temp;
+        p_first++;
+        p_last--;
+    }
+}
+
+
+void nrf_crypto_internal_swap_endian(uint8_t * p_out, uint8_t const * p_in, size_t size)
+{
+    // ASSERT(p_out != NULL);
+    // ASSERT(p_in != NULL);
+    if (p_out == NULL)
+    {
+        printf("ERROR: nrf_crypto_internal_swap_endian get NULL p_out\n");
+        fflush(stdout);
+    }
+    if (p_in == NULL)
+    {
+        printf("ERROR: nrf_crypto_internal_swap_endian get NULL p_in\n");
+        fflush(stdout);
+    }
+    if ((p_out == NULL)||(p_in == NULL)) return;
+
+    uint8_t const * p_first = p_in;
+    uint8_t * p_last = p_out + size - 1;
+    while (p_last >= p_out)
+    {
+        *p_last = *p_first;
+        p_first++;
+        p_last--;
+    }
+}
+
+
+void nrf_crypto_internal_double_swap_endian(uint8_t * p_out, uint8_t const * p_in, size_t part_size)
+{
+    nrf_crypto_internal_swap_endian(p_out, p_in, part_size);
+    nrf_crypto_internal_swap_endian(&p_out[part_size], &p_in[part_size], part_size);
+}
+
+
+void nrf_crypto_internal_double_swap_endian_in_place(uint8_t * p_buffer, size_t part_size)
+{
+    nrf_crypto_internal_swap_endian_in_place(p_buffer, part_size);
+    nrf_crypto_internal_swap_endian_in_place(&p_buffer[part_size], part_size);
+}
+
+
+// #endif
diff --git a/examples/heart_rate_collector/nrf_crypto_shared.h b/examples/heart_rate_collector/nrf_crypto_shared.h
new file mode 100644
index 0000000..4842c36
--- /dev/null
+++ b/examples/heart_rate_collector/nrf_crypto_shared.h
@@ -0,0 +1,190 @@
+/**
+ * Copyright (c) 2018, 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.
+ *
+ */
+
+#ifndef NRF_CRYPTO_SHARED_H__
+#define NRF_CRYPTO_SHARED_H__
+
+/** @internal @file
+ *
+ * @defgroup nrf_crypto_shared Shared macros for nrf_crypto
+ * @{
+ * @ingroup nrf_crypto
+ *
+ * @brief Module containing shared macros for nrf_crypto.
+ */
+
+#include "sdk_macros.h"
+#include "sdk_errors.h"
+#include "nrf_crypto_mem.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @internal @brief Macro for verifying statement to be true. It will cause the exterior function
+ *                   to return err_code if the statement is not true, but only after freeing the
+ *                   memory pointed to by p_memory if p_memory is not NULL.
+ *
+ * @param[in]   statement   Statement to test.
+ * @param[in]   err_code    Error value to return if test was invalid.
+ * @param[in]   p_memory    The memory block to be freed in case of error.
+ *
+ * @retval      nothing, but will cause the exterior function to return @p err_code if @p statement
+ *              is false.
+ */
+#define NRF_CRYPTO_VERIFY_TRUE_DEALLOCATE(statement, err_code, p_memory)    \
+do                                                                          \
+{                                                                           \
+    if (!(statement))                                                       \
+    {                                                                       \
+        if (p_memory != NULL)                                               \
+        {                                                                   \
+            NRF_CRYPTO_FREE(p_memory);                                      \
+        }                                                                   \
+        return err_code;                                                    \
+    }                                                                       \
+} while (0)
+
+
+/**
+ * @internal @brief Macro for verifying that a function returned NRF_SUCCESS. It will cause the
+ *                  exterior function to return err_code if the err_code is not @ref NRF_SUCCESS,
+ *                  but only after freeing the memory pointed to by p_memory if p_memory is not
+ *                  NULL.
+ *
+ * @param[in] err_code The error code to check.
+ * @param[in] p_memory The memory block to be freed in case of error.
+ */
+#ifdef DISABLE_PARAM_CHECK
+#define NRF_CRYPTO_VERIFY_SUCCESS_DEALLOCATE()
+#else
+#define NRF_CRYPTO_VERIFY_SUCCESS_DEALLOCATE(err_code, p_memory)                       \
+    NRF_CRYPTO_VERIFY_TRUE_DEALLOCATE((err_code) == NRF_SUCCESS, (err_code), p_memory)
+#endif /* DISABLE_PARAM_CHECK */
+
+
+/**
+ * @internal @brief Generate a vector with random data of given size.
+ *
+ * @details This function does not check or lock the CC310 mutex, and should only be used
+ *
+ * @note Only for internal use in nrf_crypto.
+ *
+ * @param[in,out]   p_target    Buffer to hold the random generated data.
+ *                              This buffer must be at least as large as the size parameter.
+ * @param[in]       size        Length (in bytes) to generate random data for.
+ *
+ * @retval      See return values for @ref nrf_crypto_rng_vector_generate.
+ */
+ret_code_t nrf_crypto_rng_vector_generate_no_mutex(uint8_t * const p_target, size_t size);
+
+
+/**
+ * @internal @brief Generate a vector of constrained random data of given size, between the
+ *                  specified min and max values.
+ *
+ * @details This function does not check or lock the CC310 mutex, and should only be used
+ *
+ * @note Only for internal use in nrf_crypto.
+ *
+ * @param[in,out]   p_target    Buffer to hold the random generated data.
+ *                              This buffer must be at least as large as the size parameter.
+ * @param[in]       p_min       Byte array defining the lower limit of the random vector.
+ * @param[in]       p_max       Byte array defining the upper limit of the random vector.
+ * @param[in]       size        Length (in bytes) to generate random data for. Note that all three
+ *                              buffers (p_target, p_min and p_max) must be of this size.
+ *
+ * @retval      See return values for @ref nrf_crypto_rng_vector_generate_in_range.
+ */
+ret_code_t nrf_crypto_rng_vector_generate_in_range_no_mutex(uint8_t         * const p_target,
+                                                            uint8_t   const * const p_min,
+                                                            uint8_t   const * const p_max,
+                                                            size_t                  size);
+
+
+/** @internal @brief Swap bytes order inside provided buffer (in place).
+ *
+ * @note Only for internal use in nrf_crypto.
+ *
+ * @param[in,out]   p_buffer    Buffer with data to swap.
+ * @param[in]       size        Number of bytes in @p p_buffer.
+ */
+void nrf_crypto_internal_swap_endian_in_place(uint8_t * p_buffer, size_t size);
+
+
+/** @internal @brief Copy from one buffer to another and swap byte order.
+ *
+ * @note Only for internal use in nrf_crypto.
+ *
+ * @param[out]   p_out   Buffer with source data.
+ * @param[in]    p_in    Destination buffer with swapped bytes.
+ * @param[in]    size    Number of bytes in @p p_out and @p p_in.
+ */
+void nrf_crypto_internal_swap_endian(uint8_t * p_out, uint8_t const * p_in, size_t size);
+
+
+/** @internal @brief Swap bytes order inside buffer containing two integers (in place).
+ *
+ * @note Only for internal use in nrf_crypto.
+ *
+ * @param[in,out]   p_buffer    Buffer with data to swap.
+ * @param[in]       part_size   Number of bytes in single integer which is half of size of @p p_buffer.
+ */
+void nrf_crypto_internal_double_swap_endian_in_place(uint8_t * p_buffer, size_t part_size);
+
+
+/** @internal @brief Copy from one buffer containing two integers to another and swap byte order of each integer.
+ *
+ * @note Only for internal use in nrf_crypto.
+ *
+ * @param[out]   p_out      Buffer with source data.
+ * @param[in]    p_in       Destination buffer with swapped bytes.
+ * @param[in]    part_size  Number of bytes in single integer which is half of size of @p p_out and @p p_in.
+ */
+void nrf_crypto_internal_double_swap_endian(uint8_t * p_out, uint8_t const * p_in, size_t part_size);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/**@} */
+
+#endif // NRF_CRYPTO_SHARED_H__
diff --git a/examples/heart_rate_collector/nrf_crypto_types.h b/examples/heart_rate_collector/nrf_crypto_types.h
new file mode 100644
index 0000000..598bd9b
--- /dev/null
+++ b/examples/heart_rate_collector/nrf_crypto_types.h
@@ -0,0 +1,113 @@
+/**
+ * Copyright (c) 2016 - 2018, 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.
+ *
+ */
+
+#ifndef NRF_CRYPTO_TYPES_H__
+#define NRF_CRYPTO_TYPES_H__
+
+/** @file
+ *
+ * @defgroup nrf_crypto_types Commonly shared types
+ * @{
+ * @ingroup nrf_crypto
+ *
+ * @brief Provides definitions of commonly shared cryptographic types like hashes and curves used in the nrf_crypto APIs.
+ */
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @brief Hashing algorithms that are available through nrf_crypto.
+ *
+ * @note    All cryptographic hash types may not be available through the nrf_crypto backend.
+ */
+typedef enum
+{
+    NRF_CRYPTO_HASH_TYPE_INVALID    = 0x00,        //!< Invalid hashing algorithm.
+    NRF_CRYPTO_HASH_TYPE_MD5        = 0x01,        //!< MD5.
+    NRF_CRYPTO_HASH_TYPE_SHA1       = 0x03,        //!< SHA-1.
+    NRF_CRYPTO_HASH_TYPE_SHA224     = 0x04,        //!< SHA-224 (SHA-2).
+    NRF_CRYPTO_HASH_TYPE_SHA256     = 0x05,        //!< SHA-256 (SHA-2).
+    NRF_CRYPTO_HASH_TYPE_SHA384     = 0x06,        //!< SHA-384 (SHA-2).
+    NRF_CRYPTO_HASH_TYPE_SHA512     = 0x07,        //!< SHA-512 (SHA-2).
+
+} nrf_hash_type_t;
+
+/**@defgroup NRF_CRYPTO_HASH_SIZES Cryptographic hash sizes
+ * @brief Sizes of different cryptographic hashes.
+ * @{ */
+#define NRF_CRYPTO_HASH_SIZE_MD5        (20)
+#define NRF_CRYPTO_HASH_SIZE_SHA1       (20)
+#define NRF_CRYPTO_HASH_SIZE_SHA224     (28)
+#define NRF_CRYPTO_HASH_SIZE_SHA256     (32)
+#define NRF_CRYPTO_HASH_SIZE_SHA384     (48)
+#define NRF_CRYPTO_HASH_SIZE_SHA512     (64)
+/** @}  */
+
+
+/**@brief Type definition for key size.
+ */
+typedef enum
+{
+    NRF_CRYPTO_KEY_SIZE_128 = 128,
+    NRF_CRYPTO_KEY_SIZE_192 = 192,
+    NRF_CRYPTO_KEY_SIZE_256 = 256
+} nrf_crypto_key_size_id_t;
+
+/**@brief Type specifying whether decrypt or encrypt operation shall be performed.
+ */
+typedef enum
+{
+    NRF_CRYPTO_DECRYPT       = 0,
+    NRF_CRYPTO_ENCRYPT       = 1,
+    NRF_CRYPTO_MAC_CALCULATE = 2
+} nrf_crypto_operation_t;
+
+#define NRF_CRYPTO_AES_BLOCK_SIZE   (16u) // 16 bytes
+
+#ifdef __cplusplus
+}
+#endif
+
+/**@} */
+
+#endif // #ifndef NRF_CRYPTO_TYPES_H__
diff --git a/include/common/sdk_compat/sdk_alloca.h b/include/common/sdk_compat/sdk_alloca.h
new file mode 100644
index 0000000..2957db6
--- /dev/null
+++ b/include/common/sdk_compat/sdk_alloca.h
@@ -0,0 +1,85 @@
+/**
+ * Copyright (c) 2017 - 2018, 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.
+ *
+ */
+/** @file sdk_alloca.h
+ *
+ * @brief Defines alloca() function.
+ *
+ * @details This file defines alloca() function. This can be done directly or by including system
+ * header files. Not all platforms support alloca(). In this case no error will be shown, but
+ * SDK_ALLOCA_DEFINED will be set to 0.
+ */
+
+#ifndef SDK_ALLOCA_H__
+#define SDK_ALLOCA_H__
+
+
+#if defined(__SDK_DOXYGEN__)
+    /** @brief Set to one it alloca() function is available on this platform and it is correctly defined
+     *  by this header file.
+     */
+    #define SDK_ALLOCA_DEFINED 1
+#elif defined(__GNUC__)
+    #if defined(__SES_ARM)
+        // SES does not have definition of alloca(), but it have working GCC's __builtin_alloca().
+        #if !defined(alloca)
+            #define alloca(size) __builtin_alloca((size))
+        #endif
+    #else
+        // alloca() can be defined in <malloc.h> on some platforms, but if not then try standard <alloca.h> header file.
+        #include <malloc.h>
+        #if !defined(alloca)
+            #include <alloca.h>
+        #endif
+    #endif
+    #define SDK_ALLOCA_DEFINED 1
+#elif defined(__IAR_SYSTEMS_ICC__)
+    // IAR does not support alloca() function.
+    #define SDK_ALLOCA_DEFINED 0
+#else
+    // All other supported compilers have alloca() definition in <alloca.h> header file.
+    #include <alloca.h>
+    #define SDK_ALLOCA_DEFINED 1
+#endif
+
+
+/*lint -"d__builtin_alloca=(void*)" */
+
+
+#endif // NRF_ALLOCA_H__
diff --git a/include/common/sdk_compat/sdk_assert.h b/include/common/sdk_compat/sdk_assert.h
new file mode 100644
index 0000000..4970397
--- /dev/null
+++ b/include/common/sdk_compat/sdk_assert.h
@@ -0,0 +1,116 @@
+/**
+ * Copyright (c) 2012 - 2017, 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.
+ * 
+ */
+/** @file
+ *
+ * @defgroup sdk_assert Utility Functions and Definitions
+ * @{
+ * @ingroup app_common
+ *
+ * @brief Various types and definitions available to all applications.
+ */
+
+#ifndef SDK_ASSERT_H__
+#define SDK_ASSERT_H__
+
+// #include <assert.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**@brief Macro for doing static (i.e. compile time) assertion.
+*
+* @note If the EXPR isn't resolvable, then the error message won't be shown.
+* @note The output of STATIC_ASSERT will be different across different compilers.
+*
+* @param[in] EXPR Constant expression to be verified.
+* @hideinitializer
+*/
+#ifndef __LINT__
+
+#ifdef __GNUC__
+#define STATIC_ASSERT_SIMPLE(EXPR)      _Static_assert(EXPR, "unspecified message")
+#define STATIC_ASSERT_MSG(EXPR, MSG)    _Static_assert(EXPR, MSG)
+#endif
+
+#ifdef __CC_ARM
+#define STATIC_ASSERT_SIMPLE(EXPR)      extern char (*_do_assert(void)) [sizeof(char[1 - 2*!(EXPR)])]
+#define STATIC_ASSERT_MSG(EXPR, MSG)    extern char (*_do_assert(void)) [sizeof(char[1 - 2*!(EXPR)])]
+#endif
+
+#ifdef __ICCARM__
+#define STATIC_ASSERT_SIMPLE(EXPR)      static_assert(EXPR, "unspecified message")
+#define STATIC_ASSERT_MSG(EXPR, MSG)    static_assert(EXPR, MSG)
+#endif
+
+#else // __LINT__
+
+#define STATIC_ASSERT_SIMPLE(EXPR)      extern char (*_ignore(void))
+#define STATIC_ASSERT_MSG(EXPR, MSG)    extern char (*_ignore(void))
+
+#endif // __LINT__
+
+#define _SELECT_ASSERT_FUNC(x, EXPR, MSG, ASSERT_MACRO, ...) ASSERT_MACRO
+
+/**
+ * @brief   Static (i.e. compile time) assert macro.
+ *
+ * @note The output of STATIC_ASSERT can be different across compilers.
+ *
+ * Usage:
+ * STATIC_ASSERT(expression);
+ * STATIC_ASSERT(expression, message);
+ *
+ * @hideinitializer
+ */
+//lint -save -esym(???, STATIC_ASSERT)
+#define STATIC_ASSERT(...)                                                                          \
+    _SELECT_ASSERT_FUNC(x, ##__VA_ARGS__,                                                           \
+                        STATIC_ASSERT_MSG(__VA_ARGS__),                                             \
+                        STATIC_ASSERT_SIMPLE(__VA_ARGS__))
+//lint -restore
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // SDK_ASSERT_H__
diff --git a/include/common/sdk_compat/sdk_errors.h b/include/common/sdk_compat/sdk_errors.h
new file mode 100644
index 0000000..b482522
--- /dev/null
+++ b/include/common/sdk_compat/sdk_errors.h
@@ -0,0 +1,167 @@
+/**
+ * Copyright (c) 2013 - 2018, 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.
+ *
+ */
+/**@file
+ *
+ * @defgroup sdk_error SDK Error codes
+ * @{
+ * @ingroup app_common
+ * @{
+ * @details Error codes are 32-bit unsigned integers with the most significant 16-bit reserved for
+ *          identifying the module where the error occurred while the least least significant LSB
+ *          are used to provide the cause or nature of error. Each module is assigned a 16-bit
+ *          unsigned integer. Which it will use to identify all errors that occurred in it. 16-bit
+ *          LSB range is with module id as the MSB in the 32-bit error code is reserved for the
+ *          module. As an example, if 0x8800 identifies a certain SDK module, all values from
+ *          0x88000000 - 0x8800FFFF are reserved for this module.
+ *          It should be noted that common error reasons have been assigned values to make it
+ *          possible to decode error reason easily. As an example, lets module uninitialized has
+ *          been assigned an error code 0x000A0. Then, if application encounters an error code
+ *          0xZZZZ00A0, it knows that it accessing a certain module without initializing it.
+ *          Apart from this, each module is allowed to define error codes that are not covered by
+ *          the common ones, however, these values are defined in a range that does not conflict
+ *          with common error values. For module, specific error however, it is possible that the
+ *          same error value is used by two different modules to indicated errors of very different
+ *          nature. If error is already defined by the NRF common error codes, these are reused.
+ *          A range is reserved for application as well, it can use this range for defining
+ *          application specific errors.
+ *
+ * @note Success code, NRF_SUCCESS, does not include any module identifier.
+
+ */
+
+#ifndef SDK_ERRORS_H__
+#define SDK_ERRORS_H__
+
+#include <stdint.h>
+#include "nrf_error.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup sdk_err_base Base defined for SDK Modules
+ * @{
+ */
+#define NRF_ERROR_SDK_ERROR_BASE         (NRF_ERROR_BASE_NUM + 0x8000)   /**< Base value defined for SDK module identifiers. */
+#define NRF_ERROR_SDK_COMMON_ERROR_BASE  (NRF_ERROR_BASE_NUM + 0x0080)   /**< Base error value to be used for SDK error values. */
+/** @} */
+
+/**
+ * @defgroup sdk_module_codes Codes reserved as identification for module where the error occurred.
+ * @{
+ */
+#define NRF_ERROR_MEMORY_MANAGER_ERR_BASE   (0x8100)    /**< Base address for Memory Manager related errors. */
+#define NRF_ERROR_PERIPH_DRIVERS_ERR_BASE   (0x8200)    /**< Base address for Peripheral drivers related errors. */
+#define NRF_ERROR_GAZELLE_ERR_BASE          (0x8300)    /**< Base address for Gazelle related errors. */
+#define NRF_ERROR_BLE_IPSP_ERR_BASE         (0x8400)    /**< Base address for BLE IPSP related errors. */
+#define NRF_ERROR_CRYPTO_ERR_BASE           (0x8500)    /**< Base address for crypto related errors. */
+/** @} */
+
+
+/**
+ * @defgroup sdk_iot_errors Codes reserved as identification for IoT errors.
+ * @{
+ */
+#define NRF_ERROR_IOT_ERR_BASE_START        (0xA000)
+#define NRF_ERROR_IOT_ERR_BASE_STOP         (0xAFFF)
+/** @} */
+
+
+/**
+ * @defgroup sdk_common_errors Codes reserved as identification for common errors.
+ * @{
+ */
+#define NRF_ERROR_MODULE_NOT_INITIALIZED     (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0000) ///< Module not initialized
+#define NRF_ERROR_MUTEX_INIT_FAILED          (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0001) ///< Mutex initialization failed
+#define NRF_ERROR_MUTEX_LOCK_FAILED          (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0002) ///< Mutex lock failed
+#define NRF_ERROR_MUTEX_UNLOCK_FAILED        (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0003) ///< Mutex unlock failed
+#define NRF_ERROR_MUTEX_COND_INIT_FAILED     (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0004) ///< Mutex conditional initialization failed
+#define NRF_ERROR_MODULE_ALREADY_INITIALIZED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0005) ///< Module already initialized
+#define NRF_ERROR_STORAGE_FULL               (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0006) ///< Storage full
+#define NRF_ERROR_API_NOT_IMPLEMENTED        (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0010) ///< API not implemented
+#define NRF_ERROR_FEATURE_NOT_ENABLED        (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0011) ///< Feature not enabled
+#define NRF_ERROR_IO_PENDING                 (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0012) ///< Input/Output pending
+/** @} */
+
+
+/**
+ * @defgroup drv_specific_errors Error / status codes specific to drivers.
+ * @{
+ */
+#define NRF_ERROR_DRV_TWI_ERR_OVERRUN        (NRF_ERROR_PERIPH_DRIVERS_ERR_BASE + 0x0000)
+#define NRF_ERROR_DRV_TWI_ERR_ANACK          (NRF_ERROR_PERIPH_DRIVERS_ERR_BASE + 0x0001)
+#define NRF_ERROR_DRV_TWI_ERR_DNACK          (NRF_ERROR_PERIPH_DRIVERS_ERR_BASE + 0x0002)
+/** @} */
+
+
+/**
+ * @defgroup ble_ipsp_errors IPSP codes
+ * @brief Error and status codes specific to IPSP.
+ * @{
+ */
+#define NRF_ERROR_BLE_IPSP_RX_PKT_TRUNCATED       (NRF_ERROR_BLE_IPSP_ERR_BASE + 0x0000)
+#define NRF_ERROR_BLE_IPSP_CHANNEL_ALREADY_EXISTS (NRF_ERROR_BLE_IPSP_ERR_BASE + 0x0001)
+#define NRF_ERROR_BLE_IPSP_LINK_DISCONNECTED      (NRF_ERROR_BLE_IPSP_ERR_BASE + 0x0002)
+#define NRF_ERROR_BLE_IPSP_PEER_REJECTED          (NRF_ERROR_BLE_IPSP_ERR_BASE + 0x0003)
+/* @} */
+
+
+/**
+ * @brief API Result.
+ *
+ * @details Indicates success or failure of an API procedure. In case of failure, a comprehensive
+ *          error code indicating cause or reason for failure is provided.
+ *
+ *          Though called an API result, it could used in Asynchronous notifications callback along
+ *          with asynchronous callback as event result. This mechanism is employed when an event
+ *          marks the end of procedure initiated using API. API result, in this case, will only be
+ *          an indicative of whether the procedure has been requested successfully.
+ */
+typedef uint32_t ret_code_t;
+
+/** @} */
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // SDK_ERRORS_H__
diff --git a/include/common/sdk_compat/sdk_macros.h b/include/common/sdk_compat/sdk_macros.h
new file mode 100644
index 0000000..c5d4439
--- /dev/null
+++ b/include/common/sdk_compat/sdk_macros.h
@@ -0,0 +1,175 @@
+/**
+ * Copyright (c) 2013 - 2018, 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.
+ *
+ */
+/**@file
+ *
+
+ * @defgroup sdk_common_macros SDK Common Header
+ * @ingroup app_common
+ * @brief Macros for parameter checking and similar tasks
+ * @{
+ */
+
+#ifndef SDK_MACROS_H__
+#define SDK_MACROS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**@brief Macro for verifying statement to be true. It will cause the exterior function to return
+ *        err_code if the statement is not true.
+ *
+ * @param[in]   statement   Statement to test.
+ * @param[in]   err_code    Error value to return if test was invalid.
+ *
+ * @retval      nothing, but will cause the exterior function to return @p err_code if @p statement
+ *              is false.
+ */
+#define VERIFY_TRUE(statement, err_code)    \
+do                                          \
+{                                           \
+    if (!(statement))                       \
+    {                                       \
+        return err_code;                    \
+    }                                       \
+} while (0)
+
+
+/**@brief Macro for verifying statement to be true. It will cause the exterior function to return
+ *        if the statement is not true.
+ *
+ * @param[in]   statement   Statement to test.
+ */
+#define VERIFY_TRUE_VOID(statement) VERIFY_TRUE((statement), )
+
+
+/**@brief Macro for verifying statement to be false. It will cause the exterior function to return
+ *        err_code if the statement is not false.
+ *
+ * @param[in]   statement   Statement to test.
+ * @param[in]   err_code    Error value to return if test was invalid.
+ *
+ * @retval      nothing, but will cause the exterior function to return @p err_code if @p statement
+ *              is true.
+ */
+#define VERIFY_FALSE(statement, err_code)   \
+do                                          \
+{                                           \
+    if ((statement))                        \
+    {                                       \
+        return err_code;                    \
+    }                                       \
+} while (0)
+
+
+/**@brief Macro for verifying statement to be false. It will cause the exterior function to return
+ *        if the statement is not false.
+ *
+ * @param[in]   statement    Statement to test.
+ */
+#define VERIFY_FALSE_VOID(statement) VERIFY_FALSE((statement), )
+
+
+/**@brief Macro for verifying that a function returned NRF_SUCCESS. It will cause the exterior
+ *        function to return error code of statement if it is not @ref NRF_SUCCESS.
+ *
+ * @param[in] statement     Statement to check against NRF_SUCCESS.
+ */
+#define VERIFY_SUCCESS(statement)                       \
+do                                                      \
+{                                                       \
+    uint32_t _err_code = (uint32_t) (statement);        \
+    if (_err_code != NRF_SUCCESS)                       \
+    {                                                   \
+        return _err_code;                               \
+    }                                                   \
+} while(0)
+
+
+/**@brief Macro for verifying that a function returned NRF_SUCCESS. It will cause the exterior
+ *        function to return if the err_code is not @ref NRF_SUCCESS.
+ *
+ * @param[in] err_code The error code to check.
+ */
+#define VERIFY_SUCCESS_VOID(err_code) VERIFY_TRUE_VOID((err_code) == NRF_SUCCESS)
+
+
+/**@brief Macro for verifying that the module is initialized. It will cause the exterior function to
+ *        return @ref NRF_ERROR_INVALID_STATE if not.
+ *
+ * @note MODULE_INITIALIZED must be defined in each module using this macro. MODULE_INITIALIZED
+ *       should be true if the module is initialized, false if not.
+ */
+#define VERIFY_MODULE_INITIALIZED() VERIFY_TRUE((MODULE_INITIALIZED), NRF_ERROR_INVALID_STATE)
+
+
+/**@brief Macro for verifying that the module is initialized. It will cause the exterior function to
+ *        return if not.
+ *
+ * @note MODULE_INITIALIZED must be defined in each module using this macro. MODULE_INITIALIZED
+ *       should be true if the module is initialized, false if not.
+ */
+#define VERIFY_MODULE_INITIALIZED_VOID() VERIFY_TRUE_VOID((MODULE_INITIALIZED))
+
+
+/**@brief Macro for verifying that the module is initialized. It will cause the exterior function to
+ *        return if not.
+ *
+ * @param[in] param  The variable to check if is NULL.
+ */
+#define VERIFY_PARAM_NOT_NULL(param) VERIFY_FALSE(((param) == NULL), NRF_ERROR_NULL)
+
+
+/**@brief Macro for verifying that the module is initialized. It will cause the exterior function to
+ *        return if not.
+ *
+ * @param[in] param  The variable to check if is NULL.
+ */
+#define VERIFY_PARAM_NOT_NULL_VOID(param) VERIFY_FALSE_VOID(((param) == NULL))
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // SDK_MACROS_H__
+
-- 
2.21.0

