sm: ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS enables micro-ecc software implementation

This commit is contained in:
Matthias Ringwald 2017-08-28 21:10:17 +02:00
parent 43836aa6b3
commit fcae305fb2
19 changed files with 38 additions and 126 deletions

View File

@ -78,7 +78,8 @@ ENABLE_SCO_OVER_HCI | Enable SCO over HCI for chipsets (only TI CC25
ENABLE_HFP_WIDE_BAND_SPEECH | Enable support for mSBC codec used in HFP profile for Wide-Band Speech
ENBALE_LE_PERIPHERAL | Enable support for LE Peripheral Role in HCI and Security Manager
ENBALE_LE_CENTRAL | Enable support for LE Central Role in HCI and Security Manager
ENABLE_LE_SECURE_CONNECTIONS | Enable LE Secure Connections using [mbed TLS library](https://tls.mbed.org)
ENABLE_LE_SECURE_CONNECTIONS | Enable LE Secure Connections
ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS | Use [micro-ecc library](https://github.com/kmackay/micro-ecc) for ECC operations
ENABLE_LE_DATA_CHANNELS | Enable LE Data Channels in credit-based flow control mode
ENABLE_LE_DATA_LENGTH_EXTENSION | Enable LE Data Length Extension support
ENABLE_LE_SIGNED_WRITE | Enable LE Signed Writes in ATT/GATT
@ -86,6 +87,9 @@ ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE | Enable L2CAP Enhanced Retransmission
ENABLE_HCI_CONTROLLER_TO_HOST_FLOW_CONTROL | Enable HCI Controller to Host Flow Control, see below
ENABLE_CC256X_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND | Enable workaround for bug in CC256x Flow Control during baud rate change, see chipset docs.
Notes:
- ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS: Only some Bluetooth 4.2+ controllers (e.g., EM9304, ESP32) support the necessary HCI commands. Others reasons to enable the ECC software implementations are if the Host is much faster or if the micro-ecc library is already provided (e.g., ESP32, WICED)
### HCI Controller to Host Flow Control
In general, BTstack relies on flow control of the HCI transport, either via Hardware CTS/RTS flow control for UART or regular USB flow control. If this is not possible, e.g on an SoC, BTstack can use HCI Controller to Host Flow Control by defining ENABLE_HCI_CONTROLLER_TO_HOST_FLOW_CONTROL. If enabled, the HCI Transport implementation must be able to buffer the specified packets. In addition, it also need to be able to buffer a few HCI Events. Using a low number of host buffers might result in less throughput.

View File

@ -17,6 +17,8 @@
#define ENABLE_LE_CENTRAL
#define ENABLE_LE_DATA_LENGTH_EXTENSION
#define ENABLE_LE_SECURE_CONNECTIONS
// ESP32 supports ECDH HCI Commands, but micro-ecc lib is already provided anyway
#define ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS
#define ENABLE_LOG_ERROR
#define ENABLE_LOG_INFO
// #define ENABLE_LOG_DEBUG

View File

@ -18,6 +18,7 @@
#define ENABLE_LE_CENTRAL
#define ENABLE_LE_PERIPHERAL
#define ENABLE_LE_SECURE_CONNECTIONS
#define ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS
#define ENABLE_LE_DATA_LENGTH_EXTENSION
#define ENABLE_LOG_ERROR
#define ENABLE_LOG_INFO

View File

@ -16,8 +16,9 @@
#define ENABLE_LE_CENTRAL
#define ENABLE_LOG_ERROR
#define ENABLE_LOG_INFO
#define ENABLE_LE_SECURE_CONNECTIONS
//#define ENABLE_LOG_DEBUG
#define ENABLE_LE_SECURE_CONNECTIONS
#define ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS
// BTstack configuration. buffers, sizes, ...
#define HCI_ACL_PAYLOAD_SIZE 1021

View File

@ -12,6 +12,8 @@
#define ENABLE_BLE
#define ENABLE_CLASSIC
#define ENABLE_LE_SECURE_CONNECTIONS
#define ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS
//#define ENABLE_LOG_DEBUG
#define ENABLE_LE_PERIPHERAL
#define ENABLE_LE_CENTRAL
#define ENABLE_LOG_INFO

View File

@ -18,6 +18,7 @@
#define ENABLE_LE_CENTRAL
#define ENABLE_LE_PERIPHERAL
#define ENABLE_LE_SECURE_CONNECTIONS
#define ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS
#define ENABLE_LE_DATA_LENGTH_EXTENSION
#define ENABLE_LOG_ERROR
#define ENABLE_LOG_INFO

View File

@ -18,6 +18,7 @@
#define ENABLE_LE_CENTRAL
#define ENABLE_LE_PERIPHERAL
#define ENABLE_LE_SECURE_CONNECTIONS
#define ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS
#define ENABLE_LE_DATA_LENGTH_EXTENSION
#define ENABLE_LOG_ERROR
#define ENABLE_LOG_INFO

View File

@ -18,6 +18,7 @@
#define ENABLE_LE_CENTRAL
#define ENABLE_LE_PERIPHERAL
#define ENABLE_LE_SECURE_CONNECTIONS
#define ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS
#define ENABLE_LE_DATA_LENGTH_EXTENSION
#define ENABLE_LOG_ERROR
#define ENABLE_LOG_INFO

View File

@ -18,6 +18,7 @@
#define ENABLE_LE_CENTRAL
#define ENABLE_LE_PERIPHERAL
#define ENABLE_LE_SECURE_CONNECTIONS
#define ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS
#define ENABLE_LE_DATA_LENGTH_EXTENSION
#define ENABLE_LOG_ERROR
#define ENABLE_LOG_INFO

View File

@ -18,6 +18,7 @@
#define ENABLE_LE_CENTRAL
#define ENABLE_LE_PERIPHERAL
#define ENABLE_LE_SECURE_CONNECTIONS
#define ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS
#define ENABLE_LE_DATA_LENGTH_EXTENSION
#define ENABLE_LOG_ERROR
#define ENABLE_LOG_INFO

View File

@ -9,9 +9,9 @@
#define HAVE_EMBEDDED_TICK
#define HAVE_UART_DMA_SET_FLOWCONTROL
#define HAVE_BTSTACK_STDIN
#define ENABLE_BLE
#define ENABLE_CLASSIC
#define ENABLE_LOG_INFO
#define ENABLE_LOG_ERROR
#define ENABLE_LE_PERIPHERAL

View File

@ -15,6 +15,7 @@
#define ENABLE_LE_PERIPHERAL
#define ENABLE_LE_CENTRAL
#define ENABLE_LE_SECURE_CONNECTIONS
#define ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS
#define ENABLE_LE_DATA_LENGTH_EXTENSION
#define ENABLE_LOG_ERROR
#define ENABLE_LOG_INFO

View File

@ -16,6 +16,7 @@
#define ENABLE_LE_PERIPHERAL
#define ENABLE_LE_CENTRAL
#define ENABLE_LE_SECURE_CONNECTIONS
#define ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS
#define ENABLE_LE_DATA_LENGTH_EXTENSION
#define ENABLE_LOG_ERROR
#define ENABLE_LOG_INFO

View File

@ -18,6 +18,7 @@
#define ENABLE_LE_CENTRAL
#define ENABLE_LE_PERIPHERAL
#define ENABLE_LE_SECURE_CONNECTIONS
#define ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS
#define ENABLE_LE_DATA_LENGTH_EXTENSION
#define ENABLE_LOG_ERROR
#define ENABLE_LOG_INFO

View File

@ -18,6 +18,7 @@
#define ENABLE_LE_CENTRAL
#define ENABLE_LE_PERIPHERAL
#define ENABLE_LE_SECURE_CONNECTIONS
#define ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS
#define ENABLE_LE_DATA_LENGTH_EXTENSION
#define ENABLE_LOG_ERROR
#define ENABLE_LOG_INFO

View File

@ -76,16 +76,8 @@
#error "HCI_ACL_PAYLOAD_SIZE must be at least 69 bytes when using LE Secure Conection. Please increase HCI_ACL_PAYLOAD_SIZE or disable ENABLE_LE_SECURE_CONNECTIONS"
#endif
#ifdef HAVE_HCI_CONTROLLER_DHKEY_SUPPORT
// currently used to validate local and remote public key
#include "uECC.h"
#else
#define USE_MICROECC_FOR_ECDH
#endif
#endif
// Software ECDH implementation provided by micro-ecc
#ifdef USE_MICROECC_FOR_ECDH
#ifdef ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS
#include "uECC.h"
#endif
@ -1574,20 +1566,20 @@ static const sm_key_t f5_salt = { 0x6C ,0x88, 0x83, 0x91, 0xAA, 0xF5, 0xA5, 0x38
static const uint8_t f5_key_id[] = { 0x62, 0x74, 0x6c, 0x65 };
static const uint8_t f5_length[] = { 0x01, 0x00};
#ifdef ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS
static void sm_sc_calculate_dhkey(sm_key256_t dhkey){
memset(dhkey, 0, 32);
#ifdef USE_MICROECC_FOR_ECDH
#if uECC_SUPPORTS_secp256r1
// standard version
uECC_shared_secret(setup->sm_peer_q, ec_d, dhkey, uECC_secp256r1());
#else
// static version
uECC_shared_secret(setup->sm_peer_q, ec_d, dhkey);
#endif
#endif
log_info("dhkey");
log_info_hexdump(dhkey, 32);
}
#endif
static void f5_calculate_salt(sm_connection_t * sm_conn){
// calculate salt for f5
@ -1717,7 +1709,7 @@ static void sm_sc_calculate_remote_confirm(sm_connection_t * sm_conn){
static void sm_sc_prepare_dhkey_check(sm_connection_t * sm_conn){
#ifdef USE_MICROECC_FOR_ECDH
#ifdef ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS
// calculate DHKEY
sm_sc_calculate_dhkey(setup->sm_dhkey);
setup->sm_state_vars |= SM_STATE_VAR_DHKEY_CALCULATED;
@ -1897,7 +1889,7 @@ static void sm_run(void){
#ifdef ENABLE_LE_SECURE_CONNECTIONS
if (ec_key_generation_state == EC_KEY_GENERATION_ACTIVE){
#ifndef HAVE_HCI_CONTROLLER_DHKEY_SUPPORT
#ifdef ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS
sm_random_start(NULL);
#else
ec_key_generation_state = EC_KEY_GENERATION_W4_KEY;
@ -2157,17 +2149,12 @@ static void sm_run(void){
return;
}
#ifdef ENABLE_LE_SECURE_CONNECTIONS
#ifdef HAVE_HCI_CONTROLLER_DHKEY_SUPPORT
#if defined(ENABLE_LE_SECURE_CONNECTIONS) || !defined(ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS)
if (setup->sm_state_vars & SM_STATE_VAR_DHKEY_NEEDED){
setup->sm_state_vars &= ~SM_STATE_VAR_DHKEY_NEEDED;
hci_send_cmd(&hci_le_generate_dhkey, &setup->sm_peer_q[0], &setup->sm_peer_q[32]);
// for comparison
sm_key256_t dhkey;
sm_sc_calculate_dhkey(dhkey);
return;
}
#endif
#endif
// assert that we could send a SM PDU - not needed for all of the following
@ -2833,7 +2820,7 @@ static void sm_handle_encryption_result(uint8_t * data){
}
#ifdef ENABLE_LE_SECURE_CONNECTIONS
#ifndef HAVE_HCI_CONTROLLER_DHKEY_SUPPORT
#ifdef ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS
#if !defined(WICED_VERSION)
// @return OK
static int sm_generate_f_rng(unsigned char * buffer, unsigned size){
@ -2854,8 +2841,7 @@ static int sm_generate_f_rng(unsigned char * buffer, unsigned size){
// note: random generator is ready. this doesn NOT imply that aes engine is unused!
static void sm_handle_random_result(uint8_t * data){
#ifdef ENABLE_LE_SECURE_CONNECTIONS
#ifndef HAVE_HCI_CONTROLLER_DHKEY_SUPPORT
#if defined(ENABLE_LE_SECURE_CONNECTIONS) && defined(ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS)
if (ec_key_generation_state == EC_KEY_GENERATION_ACTIVE){
int num_bytes = setup->sm_passkey_bit;
@ -2869,7 +2855,6 @@ static void sm_handle_random_result(uint8_t * data){
setup->sm_passkey_bit = 0;
// generate EC key
#ifdef USE_MICROECC_FOR_ECDH
#ifndef WICED_VERSION
log_info("set uECC RNG for initial key generation with 64 random bytes");
// micro-ecc from WICED SDK uses its wiced_crypto_get_random by default - no need to set it
@ -2886,9 +2871,8 @@ static void sm_handle_random_result(uint8_t * data){
#else
// static version
uECC_make_key(ec_q, ec_d);
#endif /* USE_MICROECC_FOR_ECDH */
#endif /* ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS */
#endif /* USE_MICROECC_FOR_ECDH */
ec_key_generation_state = EC_KEY_GENERATION_DONE;
log_info("Elliptic curve: d");
log_info_hexdump(ec_d,32);
@ -3121,42 +3105,16 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint
#endif
break;
#ifdef ENABLE_LE_SECURE_CONNECTIONS
#ifdef HAVE_HCI_CONTROLLER_DHKEY_SUPPORT
#if defined(ENABLE_LE_SECURE_CONNECTIONS) && !defined(ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS)
case HCI_SUBEVENT_LE_READ_LOCAL_P256_PUBLIC_KEY_COMPLETE:
if (hci_subevent_le_read_local_p256_public_key_complete_get_status(packet)){
log_error("Read Local P256 Public Key failed");
break;
}
// 4 variants to read public key
// key is 64 byte value little endian
// reverse_bytes(&packet[4], ec_q, 64);
// key is 64 byte value big endian
// memcpy(ec_q, &packet[4], 64);
// key is x/y as little endian, like in public key command
hci_subevent_le_read_local_p256_public_key_complete_get_dhkey_x(packet, &ec_q[0]);
hci_subevent_le_read_local_p256_public_key_complete_get_dhkey_y(packet, &ec_q[32]);
// key is y/z as little endian
// hci_subevent_le_read_local_p256_public_key_complete_get_dhkey_x(packet, &ec_q[32]);
// hci_subevent_le_read_local_p256_public_key_complete_get_dhkey_y(packet, &ec_q[0]);
{
// validate public key using uECC for now
#if uECC_SUPPORTS_secp256r1
// standard version
int valid = uECC_valid_public_key(ec_q, uECC_secp256r1());
log_info("public key validA %u", valid);
#else
// static version
int valid = uECC_valid_public_key(ec_q);
log_info("public key validB %u", valid);
#endif
}
ec_key_generation_state = EC_KEY_GENERATION_DONE;
sm_log_ec_keypair();
break;
@ -3179,7 +3137,6 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint
sm_conn->sm_engine_state = SM_SC_W2_CALCULATE_F5_SALT;
}
break;
#endif
#endif
default:
break;
@ -3516,7 +3473,7 @@ static void sm_pdu_handler(uint8_t packet_type, hci_con_handle_t con_handle, uin
reverse_256(&packet[01], &setup->sm_peer_q[0]);
reverse_256(&packet[33], &setup->sm_peer_q[32]);
#ifdef USE_MICROECC_FOR_ECDH
#ifdef ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS
// validate public key
err = 0;
#if uECC_SUPPORTS_secp256r1
@ -3534,7 +3491,7 @@ static void sm_pdu_handler(uint8_t packet_type, hci_con_handle_t con_handle, uin
}
#endif
#ifndef USE_MICROECC_FOR_ECDH
#ifndef ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS
// start calculating dhkey
setup->sm_state_vars |= SM_STATE_VAR_DHKEY_NEEDED;
#endif

View File

@ -1,63 +0,0 @@
/*
* Copyright (C) 2014 BlueKitchen GmbH
*
* 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 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 the copyright holders nor the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* 4. Any redistribution, use, or modification is done solely for
* personal benefit and not for any commercial purpose or for
* monetary gain.
*
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
* RINGWALD 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.
*
* Please inquire about commercial licensing options at
* contact@bluekitchen-gmbh.com
*
*/
#ifndef __SM_MBEDTLS_ALLOCATOR_H
#define __SM_MBEDTLS_ALLOCATOR_H
#if defined __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stddef.h>
typedef struct sm_allocator_node {
uint32_t next; // offset from sm_allocator_buffer, 0 == last item
uint32_t size; // size of free chunk incl. header
} sm_allocator_node_t;
void sm_mbedtls_allocator_init(uint8_t * buffer, uint32_t size);
void sm_mbedtls_allocator_status(void);
void * sm_mbedtls_allocator_calloc(size_t count, size_t size);
void sm_mbedtls_allocator_free(void * data);
#if defined __cplusplus
}
#endif
#endif

View File

@ -70,10 +70,10 @@ extern "C" {
// packet buffer sizes
// Max HCI Commadn LE payload size:
// Max HCI Command LE payload size:
// 64 from LE Generate DHKey command
// 32 from LE Encrypt command
#if defined(ENABLE_LE_SECURE_CONNECTIONS) && !defined(HAVE_HCI_CONTROLLER_DHKEY_SUPPORT)
#if defined(ENABLE_LE_SECURE_CONNECTIONS) && !defined(ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS)
#define HCI_CMD_PAYLOAD_SIZE_LE 64
#else
#define HCI_CMD_PAYLOAD_SIZE_LE 32

View File

@ -1110,15 +1110,14 @@ OPCODE(OGF_LE_CONTROLLER, 0x25), ""
// LE Read Local P-256 Public Key Complete is generated on completion
};
#ifdef HAVE_HCI_CONTROLLER_DHKEY_SUPPORT
/**
* @param end_test_cmd
* @param public key
* @param private key
*/
const hci_cmd_t hci_le_generate_dhkey = {
OPCODE(OGF_LE_CONTROLLER, 0x26), "QQ"
// LE Generate DHKey Complete is generated on completion
};
#endif
/**
*/