mirror of https://github.com/ARMmbed/mbed-os.git
commit
fc27369865
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
@ -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_
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue