diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XCrypto.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XCrypto.cpp index ca875d805f..090b29db62 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XCrypto.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XCrypto.cpp @@ -37,6 +37,8 @@ #include "cmsis.h" #include "nRF5xCrypto.h" #include "platform/mbed_assert.h" +#include "nrf_soc.h" + namespace ble { namespace pal { @@ -128,6 +130,36 @@ bool CryptoToolbox::generate_shared_secret( return err ? false : true; } +bool CryptoToolbox::ah( + const ArrayView& irk, + const ArrayView& prand, + ArrayView hash +) { + // Note copy then swap operation can be optimized. + + // Note: the encryption block works in big endian; go figure. + nrf_ecb_hal_data_t ecb_hal_data; + + memcpy(ecb_hal_data.key, irk.data(), irk.size()); + swap_endian(ecb_hal_data.key, sizeof(ecb_hal_data.key)); + + memcpy(ecb_hal_data.cleartext, prand.data(), prand.size()); + memset(ecb_hal_data.cleartext + prand.size(), 0, sizeof(ecb_hal_data.cleartext) - prand.size()); + swap_endian(ecb_hal_data.cleartext, sizeof(ecb_hal_data.cleartext)); + + uint32_t err = sd_ecb_block_encrypt(&ecb_hal_data); + + if (err) { + return false; + } + + swap_endian(ecb_hal_data.ciphertext, sizeof(ecb_hal_data.ciphertext)); + + memcpy(hash.data(), ecb_hal_data.ciphertext, hash.size()); + + return true; +} + void CryptoToolbox::load_mpi(mbedtls_mpi& dest, const ArrayView& src) { ble::public_key_coord_t src_be = src.data(); diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xCrypto.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xCrypto.h index 0189e44ddc..470002c7e1 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xCrypto.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xCrypto.h @@ -48,6 +48,21 @@ public: */ static const ptrdiff_t lesc_key_size_ = public_key_coord_t::size_; + /** + * Size of an IRK. + */ + static const ptrdiff_t irk_size_ = irk_t::size_; + + /** + * Size of the hash generated by ah. + */ + static const ptrdiff_t hash_size_ = 3; + + /** + * Size of prand. + */ + static const ptrdiff_t prand_size_ = 3; + /** * Create a new CryptoToolbox. */ @@ -88,6 +103,25 @@ public: ArrayView shared_secret ); + /** + * Execute the function ah. This function can be used to generate private + * resolvable addresses and resolve them. + * + * @note all parameters passed and return by this fucntion are in little + * endian. + * + * @param[in] irk The key used to create hash. + * @param[in] prand The random part from which the hash will be generated. + * @param[out] hash The hash generated. + * + * @return true in case of success and false otherwise. + */ + bool ah( + const ArrayView& irk, + const ArrayView& prand, + ArrayView hash + ); + private: void load_mpi(mbedtls_mpi& dest, const ArrayView& src);