Merge pull request #27 from pan-/sc-nordic

LE Secure Connections Nordic
pull/6932/head
Paul Szczepanek 2018-04-09 09:12:55 +01:00 committed by GitHub
commit fc27369865
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 669 additions and 100 deletions

View File

@ -17,8 +17,11 @@
#ifndef BLE_ARRAY_VIEW_H_
#define BLE_ARRAY_VIEW_H_
#include <algorithm>
#include <stddef.h>
#include <stdint.h>
#include "platform/mbed_assert.h"
/**
* @addtogroup ble
@ -33,11 +36,18 @@
namespace ble {
/**
* Special value for the Size parameter of ArrayView.
* If the type use this value then the size of the array is stored in the object
* at runtime.
*/
#define ARRAY_VIEW_DYNAMIC_SIZE -1
/**
* Immutable view to an array.
*
* Array views encapsulate the pointer to an array and its size into a single
* object; however, it does not manage the lifetime of the array viewed.
* object or type; however, it does not manage the lifetime of the array viewed.
* You can use instances of ArrayView to replace the traditional pair of pointer
* and size arguments in function calls.
*
@ -48,20 +58,28 @@ namespace ble {
* @note You can create ArrayView instances with the help of the function
* template make_ArrayView() and make_const_ArrayView().
*
* @note ArrayView<T, Size> objects can be implicitly converted to ArrayView<T>
* objects where required.
*
* @tparam T type of objects held by the array.
* @tparam Size The size of the array viewed. The default value
* ARRAY_VIEW_DYNAMIC_SIZE is special as it allows construction of ArrayView
* objects of any size (set at runtime).
*/
template<typename T>
template<typename T, ptrdiff_t Size = ARRAY_VIEW_DYNAMIC_SIZE>
struct ArrayView {
MBED_STATIC_ASSERT(Size >= 0, "Invalid size for an ArrayView");
/**
* Construct a view to an empty array.
*
* @post a call to size() will return 0, and data() will return NULL.
*/
ArrayView() : _array(0), _size(0) { }
ArrayView() : _array(NULL) { }
/**
* Construct an array view from a pointer to a buffer and its size.
* Construct an array view from a pointer to a buffer.
*
* @param array_ptr Pointer to the array data
* @param array_size Number of elements of T present in the array.
@ -70,7 +88,9 @@ struct ArrayView {
* array_tpr.
*/
ArrayView(T* array_ptr, size_t array_size) :
_array(array_ptr), _size(array_size) { }
_array(array_ptr) {
MBED_ASSERT(array_size >= (size_t) Size);
}
/**
* Construct an array view from the reference to an array.
@ -82,9 +102,8 @@ struct ArrayView {
* @post a call to size() will return Size, and data() will return
* a pointer to elements.
*/
template<size_t Size>
ArrayView(T (&elements)[Size]):
_array(elements), _size(Size) { }
_array(elements) { }
/**
* Return the size of the array viewed.
@ -93,7 +112,7 @@ struct ArrayView {
*/
size_t size() const
{
return _size;
return _array ? Size : 0;
}
/**
@ -144,40 +163,115 @@ struct ArrayView {
return _array;
}
private:
T* const _array;
};
/**
* ArrayView specialisation that handle dynamic array size.
*/
template<typename T>
struct ArrayView<T, ARRAY_VIEW_DYNAMIC_SIZE> {
/**
* Equality operator.
* Construct a view to an empty array.
*
* @param lhs Left hand side of the binary operation.
* @param rhs Right hand side of the binary operation.
*
* @return True if arrays in input have the same size and the same content
* and false otherwise.
* @post a call to size() will return 0, and data() will return NULL.
*/
friend bool operator==(const ArrayView& lhs, const ArrayView& rhs)
ArrayView() : _array(0), _size(0) { }
/**
* Construct an array view from a pointer to a buffer and its size.
*
* @param array_ptr Pointer to the array data
* @param array_size Number of elements of T present in the array.
*
* @post a call to size() will return array_size and data() will return
* array_tpr.
*/
ArrayView(T* array_ptr, size_t array_size) :
_array(array_ptr), _size(array_size) { }
/**
* Construct an array view from the reference to an array.
*
* @param elements Reference to the array viewed.
*
* @tparam Size Number of elements of T presents in the array.
*
* @post a call to size() will return Size, and data() will return
* a pointer to elements.
*/
template<size_t Size>
ArrayView(T (&elements)[Size]):
_array(elements), _size(Size) { }
/**
* Construct a ArrayView object with a dynamic size from an ArrayView object
* with a static size.
* @param other The ArrayView object used to construct this.
*/
template<size_t Size>
ArrayView(ArrayView<T, Size> other):
_array(other.data()), _size(other.size()) { }
/**
* Return the size of the array viewed.
*
* @return The number of elements present in the array viewed.
*/
size_t size() const
{
if (lhs.size() != rhs.size()) {
return false;
}
if (lhs.data() == rhs.data()) {
return true;
}
return memcmp(lhs.data(), rhs.data(), lhs.size()) == 0;
return _size;
}
/**
* Not equal operator
* Access to a mutable element of the array.
*
* @param lhs Left hand side of the binary operation.
* @param rhs Right hand side of the binary operation.
* @param index Element index to access.
*
* @return True if arrays in input do not have the same size or the same
* content and false otherwise.
* @return A reference to the element at the index specified in input.
*
* @pre index shall be less than size().
*/
friend bool operator!=(const ArrayView& lhs, const ArrayView& rhs)
T& operator[](size_t index)
{
return !(lhs == rhs);
return _array[index];
}
/**
* Access to an immutable element of the array.
*
* @param index Element index to access.
*
* @return A const reference to the element at the index specified in input.
*
* @pre index shall be less than size().
*/
const T& operator[](size_t index) const
{
return _array[index];
}
/**
* Get the raw pointer to the array.
*
* @return The raw pointer to the array.
*/
T* data()
{
return _array;
}
/**
* Get the raw const pointer to the array.
*
* @return The raw pointer to the array.
*/
const T* data() const
{
return _array;
}
private:
@ -186,6 +280,45 @@ private:
};
/**
* Equality operator.
*
* @param lhs Left hand side of the binary operation.
* @param rhs Right hand side of the binary operation.
*
* @return True if arrays in input have the same size and the same content
* and false otherwise.
*/
template<typename T, ptrdiff_t LhsSize, ptrdiff_t RhsSize>
bool operator==(const ArrayView<T, LhsSize>& lhs, const ArrayView<T, LhsSize>& rhs)
{
if (lhs.size() != rhs.size()) {
return false;
}
if (lhs.data() == rhs.data()) {
return true;
}
return std::equal(lhs.data(), lhs.data() + lhs.size(), rhs.data());
}
/**
* Not equal operator
*
* @param lhs Left hand side of the binary operation.
* @param rhs Right hand side of the binary operation.
*
* @return True if arrays in input do not have the same size or the same
* content and false otherwise.
*/
template<typename T, ptrdiff_t LhsSize, ptrdiff_t RhsSize>
bool operator!=(const ArrayView<T, LhsSize>& lhs, const ArrayView<T, LhsSize>& rhs)
{
return !(lhs == rhs);
}
/**
* Generate an array view from a reference to a C/C++ array.
*
@ -200,9 +333,28 @@ private:
* created 'inline'.
*/
template<typename T, size_t Size>
ArrayView<T> make_ArrayView(T (&elements)[Size])
ArrayView<T, Size> make_ArrayView(T (&elements)[Size])
{
return ArrayView<T>(elements);
return ArrayView<T, Size>(elements);
}
/**
* Generate an array view from a pointer to a C/C++ array.
*
* @tparam Size Number of items held in elements.
* @tparam T Type of elements held in elements.
*
* @param elements The reference to the array viewed.
*
* @return The ArrayView to elements.
*
* @note This helper avoids the typing of template parameter when ArrayView is
* created 'inline'.
*/
template<size_t Size, typename T>
ArrayView<T, Size> make_ArrayView(T* elements)
{
return ArrayView<T, Size>(elements, Size);
}
/**
@ -237,9 +389,28 @@ ArrayView<T> make_ArrayView(T* array_ptr, size_t array_size)
* created 'inline'.
*/
template<typename T, size_t Size>
ArrayView<const T> make_const_ArrayView(T (&elements)[Size])
ArrayView<const T, Size> make_const_ArrayView(T (&elements)[Size])
{
return ArrayView<const T>(elements);
return ArrayView<const T, Size>(elements);
}
/**
* Generate a const array view from a pointer to a C/C++ array.
*
* @tparam Size Number of items held in elements.
* @tparam T Type of elements held in elements.
*
* @param elements The reference to the array viewed.
*
* @return The ArrayView to elements.
*
* @note This helper avoids the typing of template parameter when ArrayView is
* created 'inline'.
*/
template<size_t Size, typename T>
ArrayView<const T, Size> make_const_ArrayView(const T* elements)
{
return ArrayView<const T, Size>(elements, Size);
}
/**

View File

@ -21,6 +21,7 @@
#include <stdint.h>
#include <string.h>
#include "ble/SafeEnum.h"
#include "ble/ArrayView.h"
/**
* @addtogroup ble
@ -284,6 +285,11 @@ void set_all_zeros(byte_array_class &byte_array) {
template <size_t array_size>
struct byte_array_t {
/**
* Size of the array; accessible at compile time.
*/
static const size_t size_ = array_size;
/**
* Default to all zeroes
*/
@ -327,7 +333,14 @@ struct byte_array_t {
/**
* Subscript operator to access data content
*/
uint8_t& operator[](uint8_t i) {
uint8_t& operator[](size_t i) {
return _value[i];
}
/**
* Subscript operator to access data content
*/
uint8_t operator[](size_t i) const {
return _value[i];
}
@ -341,7 +354,7 @@ struct byte_array_t {
/**
* Return the pointer to the buffer holding data.
*/
uint8_t* buffer() {
uint8_t* data() {
return _value;
}
@ -356,6 +369,32 @@ protected:
uint8_t _value[array_size];
};
/**
* Construct a fixed size ArrayView from a byte_array_t.
*
* @param src byte_array_t to create a view from.
*
* @return An ArrayView to @p src.
*/
template<size_t Size>
ArrayView<uint8_t, Size> make_ArrayView(byte_array_t<Size>& src)
{
return ArrayView<uint8_t, Size>(src.data(), src.size());
}
/**
* Construct a fixed size ArrayView from a const byte_array_t.
*
* @param src byte_array_t to create a view from.
*
* @return An ArrayView to @p src.
*/
template<size_t Size>
ArrayView<const uint8_t, Size> make_const_ArrayView(const byte_array_t<Size>& src)
{
return ArrayView<const uint8_t, Size>(src.data(), src.size());
}
/** 128 bit keys used by paired devices */
typedef byte_array_t<16> irk_t;
typedef byte_array_t<16> csrk_t;

View File

@ -643,7 +643,7 @@ ble_error_t GenericSecurityManager::init_signing() {
if (!pcsrk) {
csrk_t csrk;
ble_error_t ret = get_random_data(csrk.buffer(), csrk.size());
ble_error_t ret = get_random_data(csrk.data(), csrk.size());
if (ret != BLE_ERROR_NONE) {
return ret;
}
@ -665,7 +665,7 @@ ble_error_t GenericSecurityManager::get_random_data(uint8_t *buffer, size_t size
if (ret != BLE_ERROR_NONE) {
return ret;
}
memcpy(buffer, random_data.buffer(), copy_size);
memcpy(buffer, random_data.data(), copy_size);
size -= copy_size;
buffer += copy_size;
}

View File

@ -366,7 +366,7 @@ ble_error_t CordioSecurityManager::cancel_pairing(
ble_error_t CordioSecurityManager::get_random_data(byte_array_t<8> &random_data)
{
SecRand(random_data.buffer(), random_data.size());
SecRand(random_data.data(), random_data.size());
return BLE_ERROR_NOT_IMPLEMENTED;
}

View File

@ -185,7 +185,7 @@ static void btle_handler(ble_evt_t *p_ble_evt)
nRF5xn &ble = nRF5xn::Instance(BLE::DEFAULT_INSTANCE);
nRF5xGap &gap = (nRF5xGap &) ble.getGap();
nRF5xGattServer &gattServer = (nRF5xGattServer &) ble.getGattServer();
nRF5xSecurityManager &securityManager = (nRF5xSecurityManager &) ble.getSecurityManager();
nRF5xSecurityManager &securityManager = nRF5xSecurityManager::get_security_manager();
/* Custom event handler */
switch (p_ble_evt->header.evt_id) {

View File

@ -0,0 +1,153 @@
/* mbed Microcontroller Library
* Copyright (c) 2018-2018 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <algorithm>
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include <stdio.h>
#include <string.h>
#include "mbedtls/platform.h"
#include "mbedtls/ecdh.h"
#include "mbedtls/memory_buffer_alloc.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ecp.h"
#include "platform/NonCopyable.h"
#include "platform/CriticalSectionLock.h"
#include "ble/BLETypes.h"
#include "cmsis.h"
#include "nRF5xCrypto.h"
#include "platform/mbed_assert.h"
namespace ble {
namespace pal {
namespace vendor {
namespace nordic {
CryptoToolbox::CryptoToolbox() : _initialized(false) {
mbedtls_entropy_init(&_entropy_context);
mbedtls_ecp_group_init(&_group);
int err = mbedtls_ecp_group_load(
&_group,
MBEDTLS_ECP_DP_SECP256R1
);
_initialized = err ? false : true;
}
CryptoToolbox::~CryptoToolbox() {
mbedtls_ecp_group_free(&_group);
mbedtls_entropy_free(&_entropy_context);
}
bool CryptoToolbox::generate_keys(
ArrayView<uint8_t, lesc_key_size_> X,
ArrayView<uint8_t, lesc_key_size_> Y,
ArrayView<uint8_t, lesc_key_size_> secret
) {
mbedtls_mpi secret_key;
mbedtls_ecp_point public_keys;
mbedtls_mpi_init(&secret_key);
mbedtls_ecp_point_init(&public_keys);
int err = mbedtls_ecp_gen_keypair(
&_group,
&secret_key,
&public_keys,
mbedtls_entropy_func,
&_entropy_context
);
if (!err) {
store_mpi(secret, secret_key);
store_mpi(X, public_keys.X);
store_mpi(Y, public_keys.Y);
}
mbedtls_ecp_point_free(&public_keys);
mbedtls_mpi_free(&secret_key);
return err ? false : true;
}
bool CryptoToolbox::generate_shared_secret(
const ArrayView<const uint8_t, lesc_key_size_>& peer_X,
const ArrayView<const uint8_t, lesc_key_size_>& peer_Y,
const ArrayView<const uint8_t, lesc_key_size_>& own_secret,
ArrayView<uint8_t, lesc_key_size_> shared_secret
) {
mbedtls_mpi result;
mbedtls_mpi secret_key;
mbedtls_ecp_point public_keys;
mbedtls_mpi_init(&result);
mbedtls_mpi_init(&secret_key);
mbedtls_ecp_point_init(&public_keys);
load_mpi(secret_key, own_secret);
load_mpi(public_keys.X, peer_X);
load_mpi(public_keys.Y, peer_Y);
mbedtls_mpi_lset( &public_keys.Z, 1 );
int err = mbedtls_ecdh_compute_shared(
&_group,
&result,
&public_keys,
&secret_key,
/* rng function; optional */ NULL,
/* rng param */ NULL
);
if (!err) {
store_mpi(shared_secret, result);
}
mbedtls_ecp_point_free(&public_keys);
mbedtls_mpi_free(&secret_key);
mbedtls_mpi_free(&result);
return err ? false : true;
}
void CryptoToolbox::load_mpi(mbedtls_mpi& dest, const ArrayView<const uint8_t, lesc_key_size_>& src) {
ble::public_key_coord_t src_be = src.data();
swap_endian(src_be.data(), src_be.size());
mbedtls_mpi_read_binary(&dest, src_be.data(), src_be.size());
}
void CryptoToolbox::store_mpi(ArrayView<uint8_t, lesc_key_size_>& dest, const mbedtls_mpi& src) {
mbedtls_mpi_write_binary(&src, dest.data(), dest.size());
swap_endian(dest.data(), dest.size());
}
void CryptoToolbox::swap_endian(uint8_t* buf, size_t len) {
for(size_t low = 0, high = (len - 1); high > low; --high, ++low) {
std::swap(buf[low], buf[high]);
}
}
} // nordic
} // vendor
} // pal
} // ble

View File

@ -0,0 +1,108 @@
/* mbed Microcontroller Library
* Copyright (c) 2018-2018 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef NRF5X_CRYPTO_
#define NRF5X_CRYPTO_
#include <stdint.h>
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include "mbedtls/platform.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ecp.h"
#include "platform/NonCopyable.h"
#include "ble/BLETypes.h"
namespace ble {
namespace pal {
namespace vendor {
namespace nordic {
/**
* Toolbox of cryptographic functions used in BLE.
*/
class CryptoToolbox : mbed::NonCopyable<CryptoToolbox> {
public:
/**
* Size of the Key used in lesc crypto operations.
*/
static const ptrdiff_t lesc_key_size_ = public_key_coord_t::size_;
/**
* Create a new CryptoToolbox.
*/
CryptoToolbox();
/**
* Destroy a CryptoTioolbox object.
*/
~CryptoToolbox();
/**
* Generate lesc public and private keys.
* @param[out] X The component X of the public key.
* @param[out] Y The component Y of the public key.
* @param[out] secret The secret key.
* @return true if the shared secret has been successfully generated and
* false otherwise.
*/
bool generate_keys(
ArrayView<uint8_t, lesc_key_size_> X,
ArrayView<uint8_t, lesc_key_size_> Y,
ArrayView<uint8_t, lesc_key_size_> secret
);
/**
* Generate a shared secret from a peer public key and a local secret key.
* @param[in] peer_X The component X of the peer public key.
* @param[in] peer_Y The component Y of the peer public key.
* @param[in] own_secret The local secret key.
* @param[out] shared_secret The shared secret generated.
* @return true if the shared secret has been successfully generated and
* false otherwise.
*/
bool generate_shared_secret(
const ArrayView<const uint8_t, lesc_key_size_>& peer_X,
const ArrayView<const uint8_t, lesc_key_size_>& peer_Y,
const ArrayView<const uint8_t, lesc_key_size_>& own_secret,
ArrayView<uint8_t, lesc_key_size_> shared_secret
);
private:
void load_mpi(mbedtls_mpi& dest, const ArrayView<const uint8_t, lesc_key_size_>& src);
void store_mpi(ArrayView<uint8_t, lesc_key_size_>& dest, const mbedtls_mpi& src);
void swap_endian(uint8_t* buf, size_t len);
bool _initialized;
mbedtls_entropy_context _entropy_context;
mbedtls_ecp_group _group;
};
} // nordic
} // vendor
} // pal
} // ble
#endif // NRF5X_CRYPTO_

View File

@ -76,6 +76,11 @@ struct nRF5xSecurityManager::pairing_control_block_t {
ble_gap_id_key_t peer_id_key;
ble_gap_sign_info_t peer_sign_key;
ble_gap_lesc_p256_pk_t peer_pk;
// flag required to help DHKey computation/process; should be removed with
// later versions of the softdevice
uint8_t own_oob:1;
uint8_t peer_oob:1;
};
nRF5xSecurityManager::nRF5xSecurityManager()
@ -90,7 +95,7 @@ nRF5xSecurityManager::nRF5xSecurityManager()
nRF5xSecurityManager::~nRF5xSecurityManager()
{
terminate();
}
////////////////////////////////////////////////////////////////////////////
@ -99,19 +104,31 @@ nRF5xSecurityManager::~nRF5xSecurityManager()
ble_error_t nRF5xSecurityManager::initialize()
{
// FIXME: generate and set public and private keys
return BLE_ERROR_NONE;
if (_crypto.generate_keys(
make_ArrayView(X),
make_ArrayView(Y),
make_ArrayView(secret)
)) {
return BLE_ERROR_NONE;
}
return BLE_ERROR_INTERNAL_STACK_FAILURE;
}
ble_error_t nRF5xSecurityManager::terminate()
{
release_all_pairing_cb();
return BLE_ERROR_NONE;
}
ble_error_t nRF5xSecurityManager::reset()
{
// FIXME: reset public and private keys
return BLE_ERROR_NONE;
ble_error_t err = terminate();
if (err) {
return err;
}
return initialize();
}
////////////////////////////////////////////////////////////////////////////
@ -173,6 +190,10 @@ ble_error_t nRF5xSecurityManager::send_pairing_request(
initiator_dist.set_signing(false);
responder_dist.set_signing(false);
// override link parameter
initiator_dist.set_link(false);
responder_dist.set_link(false);
ble_gap_sec_params_t security_params = make_security_params(
oob_data_flag,
authentication_requirements,
@ -209,6 +230,10 @@ ble_error_t nRF5xSecurityManager::send_pairing_response(
initiator_dist.set_signing(false);
responder_dist.set_signing(false);
// override link parameter
initiator_dist.set_link(false);
responder_dist.set_link(false);
ble_gap_sec_params_t security_params = make_security_params(
oob_data_flag,
authentication_requirements,
@ -239,7 +264,7 @@ ble_error_t nRF5xSecurityManager::send_pairing_response(
ble_error_t nRF5xSecurityManager::cancel_pairing(
connection_handle_t connection, pairing_failure_t reason
) {
// this is the default path except when a key is expected to be enterred by
// this is the default path except when a key is expected to be entered by
// the user.
uint32_t err = sd_ble_gap_sec_params_reply(
connection,
@ -272,9 +297,7 @@ ble_error_t nRF5xSecurityManager::cancel_pairing(
ble_error_t nRF5xSecurityManager::get_secure_connections_support(
bool &enabled
) {
// NRF5x platforms support secure connections
// FIXME: set to true once the ECC library is included
enabled = false;
enabled = true;
return BLE_ERROR_NONE;
}
@ -399,7 +422,7 @@ ble_error_t nRF5xSecurityManager::encrypt_data(
const byte_array_t<16> &key,
encryption_block_t &data
) {
// FIXME: With signing ?
// FIXME: Implement in LescCrypto ?
return BLE_ERROR_NOT_IMPLEMENTED;
}
@ -446,8 +469,8 @@ ble_error_t nRF5xSecurityManager::set_ltk(
uint32_t err = sd_ble_gap_sec_info_reply(
connection,
&enc_info,
NULL,
NULL // Not supported
/* id info */ NULL,
/* sign info */ NULL // Not supported
);
return convert_sd_error(err);
@ -498,7 +521,7 @@ ble_error_t nRF5xSecurityManager::set_csrk(const csrk_t& csrk)
ble_error_t nRF5xSecurityManager::get_random_data(byte_array_t<8> &random_data)
{
uint32_t err = sd_rand_application_vector_get(
random_data.buffer(), random_data.size()
random_data.data(), random_data.size()
);
return convert_sd_error(err);
}
@ -520,6 +543,11 @@ ble_error_t nRF5xSecurityManager::set_display_passkey(passkey_num_t passkey)
ble_error_t nRF5xSecurityManager::passkey_request_reply(
connection_handle_t connection, const passkey_num_t passkey
) {
pairing_control_block_t* pairing_cb = get_pairing_cb(connection);
if (!pairing_cb) {
return BLE_ERROR_INVALID_STATE;
}
PasskeyAscii pkasc(passkey);
uint32_t err = sd_ble_gap_auth_key_reply(
connection,
@ -530,6 +558,37 @@ ble_error_t nRF5xSecurityManager::passkey_request_reply(
return convert_sd_error(err);
}
ble_error_t nRF5xSecurityManager::secure_connections_oob_request_reply(
connection_handle_t connection,
const oob_lesc_value_t &local_random,
const oob_lesc_value_t &peer_random,
const oob_confirm_t &peer_confirm
) {
pairing_control_block_t* pairing_cb = get_pairing_cb(connection);
if (!pairing_cb) {
return BLE_ERROR_INVALID_STATE;
}
ble_gap_lesc_oob_data_t oob_own;
ble_gap_lesc_oob_data_t oob_peer;
// is own address important ?
memcpy(oob_own.r, local_random.data(), local_random.size());
// FIXME: What to do with local confirm ???
// is peer address important ?
memcpy(oob_peer.r, peer_random.data(), peer_random.size());
memcpy(oob_peer.c, peer_confirm.data(), peer_confirm.size());
uint32_t err = sd_ble_gap_lesc_oob_data_set(
connection,
pairing_cb->own_oob ? &oob_own : NULL,
pairing_cb->peer_oob ? &oob_peer : NULL
);
return convert_sd_error(err);
}
ble_error_t nRF5xSecurityManager::legacy_pairing_oob_request_reply(
connection_handle_t connection,
const oob_tk_t& oob_data
@ -546,11 +605,17 @@ ble_error_t nRF5xSecurityManager::legacy_pairing_oob_request_reply(
ble_error_t nRF5xSecurityManager::confirmation_entered(
connection_handle_t connection, bool confirmation
) {
pairing_control_block_t* pairing_cb = get_pairing_cb(connection);
if (!pairing_cb) {
return BLE_ERROR_INVALID_STATE;
}
uint32_t err = sd_ble_gap_auth_key_reply(
connection,
confirmation ? BLE_GAP_AUTH_KEY_TYPE_PASSKEY : BLE_GAP_AUTH_KEY_TYPE_NONE,
NULL
);
return convert_sd_error(err);
}
@ -568,25 +633,26 @@ ble_error_t nRF5xSecurityManager::send_keypress_notification(
ble_error_t nRF5xSecurityManager::generate_secure_connections_oob(
connection_handle_t connection
) {
// FIXME: made with external library; requires SDK v13
return BLE_ERROR_NOT_IMPLEMENTED;
}
ble_gap_lesc_p256_pk_t own_secret;
ble_gap_lesc_oob_data_t oob_data;
memcpy(own_secret.pk, secret.data(), secret.size());
ble_error_t nRF5xSecurityManager::secure_connections_oob_received(
const address_t &address,
const oob_lesc_value_t &random,
const oob_confirm_t &confirm
) {
// FIXME: store locally
return BLE_ERROR_NOT_IMPLEMENTED;
}
uint32_t err = sd_ble_gap_lesc_oob_data_get(
connection,
&own_secret,
&oob_data
);
bool nRF5xSecurityManager::is_secure_connections_oob_present(
const address_t &address
) {
// FIXME: lookup local store
return false;
if (!err) {
get_event_handler()->on_secure_connections_oob_generated(
connection,
oob_data.r,
oob_data.c
);
}
return convert_sd_error(err);
}
nRF5xSecurityManager& nRF5xSecurityManager::get_security_manager()
@ -653,18 +719,15 @@ bool nRF5xSecurityManager::sm_handler(const ble_evt_t *evt)
);
}
} else {
AuthenticationMask authentication_requirements(
params.bond,
params.mitm,
params.lesc,
params.keypress
);
handler->on_pairing_request(
connection,
params.oob,
authentication_requirements,
AuthenticationMask(
params.bond,
params.mitm,
params.lesc,
params.keypress
),
initiator_dist,
responder_dist
);
@ -695,7 +758,11 @@ bool nRF5xSecurityManager::sm_handler(const ble_evt_t *evt)
PasskeyAscii::to_num(req.passkey)
);
} else {
// FIXME handle this case for secure pairing
handler->on_passkey_display(
connection,
PasskeyAscii::to_num(req.passkey)
);
handler->on_confirmation_request(connection);
}
return true;
@ -708,6 +775,7 @@ bool nRF5xSecurityManager::sm_handler(const ble_evt_t *evt)
);
return true;
}
case BLE_GAP_EVT_AUTH_KEY_REQUEST: {
uint8_t key_type = gap_evt.params.auth_key_request.key_type;
@ -727,9 +795,28 @@ bool nRF5xSecurityManager::sm_handler(const ble_evt_t *evt)
return true;
}
case BLE_GAP_EVT_LESC_DHKEY_REQUEST:
// FIXME: Add with LESC support
case BLE_GAP_EVT_LESC_DHKEY_REQUEST: {
const ble_gap_evt_lesc_dhkey_request_t& dhkey_request =
gap_evt.params.lesc_dhkey_request;
static const size_t key_size = public_key_coord_t::size_;
ble_gap_lesc_dhkey_t shared_secret;
_crypto.generate_shared_secret(
make_const_ArrayView<key_size>(dhkey_request.p_pk_peer->pk),
make_const_ArrayView<key_size>(dhkey_request.p_pk_peer->pk + key_size),
make_const_ArrayView(secret),
shared_secret.key
);
sd_ble_gap_lesc_dhkey_reply(connection, &shared_secret);
if (dhkey_request.oobd_req) {
handler->on_secure_connections_oob_request(connection);
}
return true;
}
case BLE_GAP_EVT_AUTH_STATUS: {
const ble_gap_evt_auth_status_t& status = gap_evt.params.auth_status;
@ -954,13 +1041,13 @@ ble_gap_sec_keyset_t nRF5xSecurityManager::make_keyset(
own_dist->get_encryption() ? &pairing_cb.own_enc_key : NULL,
own_dist->get_identity() ? &pairing_cb.own_id_key : NULL,
own_dist->get_signing() ? &pairing_cb.own_sign_key : NULL,
own_dist->get_link() ? &pairing_cb.own_pk : NULL
&pairing_cb.own_pk
},
/* keys_peer */ {
peer_dist->get_encryption() ? &pairing_cb.peer_enc_key : NULL,
peer_dist->get_identity() ? &pairing_cb.peer_id_key : NULL,
peer_dist->get_signing() ? &pairing_cb.peer_sign_key : NULL,
peer_dist->get_link() ? &pairing_cb.peer_pk : NULL
&pairing_cb.peer_pk
}
};
@ -969,6 +1056,10 @@ ble_gap_sec_keyset_t nRF5xSecurityManager::make_keyset(
memcpy(keyset.keys_own.p_sign_key->csrk, _csrk.data(), _csrk.size());
}
// copy public keys used
memcpy(pairing_cb.own_pk.pk, X.data(), X.size());
memcpy(pairing_cb.own_pk.pk + X.size(), Y.data(), Y.size());
return keyset;
}
@ -1016,6 +1107,13 @@ nRF5xSecurityManager::get_pairing_cb(connection_handle_t connection)
return NULL;
}
void nRF5xSecurityManager::release_all_pairing_cb()
{
while(_control_blocks) {
release_pairing_cb(_control_blocks);
}
}
} // nordic
} // vendor
} // pal

View File

@ -20,6 +20,7 @@
#include "ble/BLETypes.h"
#include "ble/pal/PalSecurityManager.h"
#include "nrf_ble.h"
#include "nRF5xCrypto.h"
namespace ble {
namespace pal {
@ -264,6 +265,16 @@ public:
passkey_num_t passkey
);
/**
* @see ::ble::pal::SecurityManager::secure_connections_oob_request_reply
*/
virtual ble_error_t secure_connections_oob_request_reply(
connection_handle_t connection,
const oob_lesc_value_t &local_random,
const oob_lesc_value_t &peer_random,
const oob_confirm_t &peer_confirm
);
/**
* @see ::ble::pal::SecurityManager::legacy_pairing_oob_request_reply
*/
@ -293,22 +304,6 @@ public:
connection_handle_t connection
);
/**
* @see ::ble::pal::SecurityManager::secure_connections_oob_received
*/
virtual ble_error_t secure_connections_oob_received(
const address_t &address,
const oob_lesc_value_t &random,
const oob_confirm_t &confirm
);
/**
* @see ::ble::pal::SecurityManager::is_secure_connections_oob_present
*/
virtual bool is_secure_connections_oob_present(
const address_t &address
);
// singleton of nordic Security Manager
static nRF5xSecurityManager& get_security_manager();
@ -339,8 +334,13 @@ private:
pairing_control_block_t* allocate_pairing_cb(connection_handle_t connection);
void release_pairing_cb(pairing_control_block_t* pairing_cb);
pairing_control_block_t* get_pairing_cb(connection_handle_t connection);
void release_all_pairing_cb();
pairing_control_block_t* _control_blocks;
CryptoToolbox _crypto;
ble::public_key_coord_t X;
ble::public_key_coord_t Y;
ble::public_key_coord_t secret;
};
} // nordic