diff --git a/example/libusb/Makefile b/example/libusb/Makefile index b0c357453..7c1155ca2 100644 --- a/example/libusb/Makefile +++ b/example/libusb/Makefile @@ -64,8 +64,8 @@ spp_counter_ssp: ${CORE_OBJ} ${COMMON_OBJ} spp_counter_ssp.c profile.h: profile.gatt python ${BTSTACK_ROOT}/ble/compile-gatt.py $< $@ -ble_server: ${CORE_OBJ} ${COMMON_OBJ} ble_server.c profile.h - ${CC} ${CORE_OBJ} ${COMMON_OBJ} ble_server.c ${CFLAGS} ${LDFLAGS} -o $@ +ble_server: ${CORE_OBJ} ${COMMON_OBJ} ble_server.c central_device_db_memory.c profile.h + ${CC} ${CORE_OBJ} ${COMMON_OBJ} ble_server.c central_device_db_memory.c ${CFLAGS} ${LDFLAGS} -o $@ ble_client: ${CORE_OBJ} ${COMMON_OBJ} ble_client.c ad_parser.c ${CC} ${CORE_OBJ} ${COMMON_OBJ} ad_parser.c ble_client.c ${CFLAGS} ${LDFLAGS} -o $@ diff --git a/example/libusb/ble_server.c b/example/libusb/ble_server.c index 40e530eac..9090df900 100644 --- a/example/libusb/ble_server.c +++ b/example/libusb/ble_server.c @@ -57,60 +57,13 @@ #include "l2cap.h" +#include "sm.h" #include "att.h" +#include "central_device_db.h" -#include "rijndael.h" - -// Bluetooth Spec definitions -typedef enum { - SM_CODE_PAIRING_REQUEST = 0X01, - SM_CODE_PAIRING_RESPONSE, - SM_CODE_PAIRING_CONFIRM, - SM_CODE_PAIRING_RANDOM, - SM_CODE_PAIRING_FAILED, - SM_CODE_ENCRYPTION_INFORMATION, - SM_CODE_MASTER_IDENTIFICATION, - SM_CODE_IDENTITY_INFORMATION, - SM_CODE_IDENTITY_ADDRESS_INFORMATION, - SM_CODE_SIGNING_INFORMATION, - SM_CODE_SECURITY_REQUEST -} SECURITY_MANAGER_COMMANDS; - -// Authentication requirement flags -#define SM_AUTHREQ_NO_BONDING 0x00 -#define SM_AUTHREQ_BONDING 0x01 -#define SM_AUTHREQ_MITM_PROTECTION 0x04 - -// Key distribution flags used by spec -#define SM_KEYDIST_ENC_KEY 0X01 -#define SM_KEYDIST_ID_KEY 0x02 -#define SM_KEYDIST_SIGN 0x04 - -// Key distribution flags used internally -#define SM_KEYDIST_FLAG_ENCRYPTION_INFORMATION 0x01 -#define SM_KEYDIST_FLAG_MASTER_IDENTIFICATION 0x02 -#define SM_KEYDIST_FLAG_IDENTITY_INFORMATION 0x04 -#define SM_KEYDIST_FLAG_IDENTITY_ADDRESS_INFORMATION 0x08 -#define SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION 0x10 - -// STK Generation Methods -#define SM_STK_GENERATION_METHOD_JUST_WORKS 0x01 -#define SM_STK_GENERATION_METHOD_OOB 0x02 -#define SM_STK_GENERATION_METHOD_PASSKEY 0x04 - -// Pairing Failed Reasons -#define SM_REASON_RESERVED 0x00 -#define SM_REASON_PASSKEYT_ENTRY_FAILED 0x01 -#define SM_REASON_OOB_NOT_AVAILABLE 0x02 -#define SM_REASON_AUTHENTHICATION_REQUIREMENTS 0x03 -#define SM_REASON_CONFIRM_VALUE_FAILED 0x04 -#define SM_REASON_PAIRING_NOT_SUPPORTED 0x05 -#define SM_REASON_ENCRYPTION_KEY_SIZE 0x06 -#define SM_REASON_COMMAND_NOT_SUPPORTED 0x07 -#define SM_REASON_UNSPECIFIED_REASON 0x08 -#define SM_REASON_REPEATED_ATTEMPTS 0x09 -// also, invalid parameters -// and reserved +// +// GAP API +// // IO Capability Values typedef enum { @@ -122,16 +75,14 @@ typedef enum { IO_CAPABILITY_UNKNOWN = 0xff } io_capability_t; - +// address type typedef enum { GAP_RANDOM_ADDRESS_TYPE_OFF = 0, GAP_RANDOM_ADDRESS_NON_RESOLVABLE, GAP_RANDOM_ADDRESS_RESOLVABLE, } gap_random_address_type_t; -// -// types used by client -// +// pairing user interacation typedef struct sm_event { uint8_t type; // see SM_... uint8_t addr_type; @@ -140,11 +91,9 @@ typedef struct sm_event { } sm_event_t; // -// internal types and globals +// SM internal types and globals // -typedef uint8_t key_t[16]; - typedef enum { SM_STATE_IDLE, @@ -265,12 +214,12 @@ typedef enum { // // Security Manager Master Keys, please use sm_set_er(er) and sm_set_ir(ir) with your own 128 bit random values -static key_t sm_persistent_er; -static key_t sm_persistent_ir; +static sm_key_t sm_persistent_er; +static sm_key_t sm_persistent_ir; // derived from sm_persistent_ir -static key_t sm_persistent_dhk; -static key_t sm_persistent_irk; +static sm_key_t sm_persistent_dhk; +static sm_key_t sm_persistent_irk; // derived from sm_persistent_er // .. @@ -310,13 +259,13 @@ static uint8_t sm_pairing_failed_reason = 0; static timer_source_t sm_timeout; // data to send to aes128 crypto engine, see sm_aes128_set_key and sm_aes128_set_plaintext -static key_t sm_aes128_key; -static key_t sm_aes128_plaintext; +static sm_key_t sm_aes128_key; +static sm_key_t sm_aes128_plaintext; static uint8_t sm_aes128_active; // generation method and temporary key for STK - STK is stored in sm_s_ltk static stk_generation_method_t sm_stk_generation_method; -static key_t sm_tk; +static sm_key_t sm_tk; // user response static uint8_t sm_user_response; @@ -338,51 +287,41 @@ static uint8_t sm_m_auth_req; static uint8_t sm_m_max_encryption_key_size; static uint8_t sm_m_key_distribution; static uint8_t sm_m_preq[7]; -static key_t sm_m_random; -static key_t sm_m_confirm; +static sm_key_t sm_m_random; +static sm_key_t sm_m_confirm; -static key_t sm_s_random; -static key_t sm_s_confirm; +static sm_key_t sm_s_random; +static sm_key_t sm_s_confirm; static uint8_t sm_s_pres[7]; // key distribution, slave sends -static key_t sm_s_ltk; +static sm_key_t sm_s_ltk; static uint16_t sm_s_y; static uint16_t sm_s_div; static uint16_t sm_s_ediv; static uint8_t sm_s_rand[8]; -static key_t sm_s_csrk; +static sm_key_t sm_s_csrk; // key distribution, received from master -static key_t sm_m_ltk; +static sm_key_t sm_m_ltk; static uint16_t sm_m_ediv; static uint8_t sm_m_rand[8]; static uint8_t sm_m_addr_type; static bd_addr_t sm_m_address; -static key_t sm_m_csrk; -static key_t sm_m_irk; +static sm_key_t sm_m_csrk; +static sm_key_t sm_m_irk; // CMAC calculation static cmac_state_t sm_cmac_state; -static key_t sm_cmac_k; +static sm_key_t sm_cmac_k; static uint16_t sm_cmac_message_len; static uint8_t * sm_cmac_message; -static key_t sm_cmac_m_last; -static key_t sm_cmac_x; +static sm_key_t sm_cmac_m_last; +static sm_key_t sm_cmac_x; static uint8_t sm_cmac_block_current; static uint8_t sm_cmac_block_count; static void (*sm_cmac_done_handler)(uint8_t hash[8]); -// CMAC Test Data -uint8_t m16[] = { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a}; -uint8_t m64[] = { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, - 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, - 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, - 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10}; -uint8_t m40[] = { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, - 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, - 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11}; - // @returns 1 if oob data is available // stores oob data in provided 16 byte buffer if not null static int (*sm_get_oob_data)(uint8_t addres_type, bd_addr_t * addr, uint8_t * oob_data) = NULL; @@ -400,31 +339,15 @@ static const stk_generation_method_t stk_generation_method[5][5] = { { PK_RESP_INPUT, PK_RESP_INPUT, PK_INIT_INPUT, JUST_WORKS, PK_RESP_INPUT }, }; -// ATT Server - -static att_connection_t att_connection; -static uint16_t att_addr_type; -static bd_addr_t att_address; - -typedef enum { - ATT_SERVER_IDLE, - ATT_SERVER_REQUEST_RECEIVED, - ATT_SERVER_W4_SIGNED_WRITE_VALIDATION, -} att_server_state_t; - -static att_server_state_t att_server_state; -static uint16_t att_request_handle = 0; -static uint16_t att_request_size = 0; -static uint8_t att_request_buffer[28]; - -// SECURITY MANAGER (SM) MATERIALIZES HERE static void sm_run(); +/// CMAC Suppport int sm_cmac_ready(); -static void sm_cmac_handle_encryption_result(key_t data); +static void sm_cmac_handle_encryption_result(sm_key_t data); static void sm_cmac_handle_aes_engine_ready(); -static void sm_cmac_start(key_t k, uint16_t message_len, uint8_t * message, void (*done_handler)(uint8_t hash[8])); +static void sm_cmac_start(sm_key_t k, uint16_t message_len, uint8_t * message, void (*done_handler)(uint8_t hash[8])); +// Utils static inline void swapX(uint8_t *src, uint8_t *dst, int len){ int i; for (i = 0; i < len; i++) @@ -443,6 +366,10 @@ static inline void swap128(uint8_t src[16], uint8_t dst[16]){ swapX(src, dst, 16); } +static void print_hex16(const char * name, uint16_t value){ + printf("%-6s 0x%04x\n", name, value); +} + // @returns 1 if all bytes are 0 static int sm_is_null_random(uint8_t random[8]){ int i; @@ -452,6 +379,7 @@ static int sm_is_null_random(uint8_t random[8]){ return 1; } +// Key utils static void sm_reset_tk(){ int i; for (i=0;i<16;i++){ @@ -461,128 +389,13 @@ static void sm_reset_tk(){ // "For example, if a 128-bit encryption key is 0x123456789ABCDEF0123456789ABCDEF0 // and it is reduced to 7 octets (56 bits), then the resulting key is 0x0000000000000000003456789ABCDEF0."" -static void sm_truncate_key(key_t key, int max_encryption_size){ +static void sm_truncate_key(sm_key_t key, int max_encryption_size){ int i; for (i = max_encryption_size ; i < 16 ; i++){ key[15-i] = 0; } } -static void print_key(const char * name, key_t key){ - printf("%-6s ", name); - hexdump(key, 16); -} - -static void print_hex16(const char * name, uint16_t value){ - printf("%-6s 0x%04x\n", name, value); -} - -// Central Device db interface - -void central_device_db_init(); - -// @returns index if successful, -1 otherwise -int central_device_db_add(int addr_type, bd_addr_t addr, key_t irk, key_t csrk); - -// @returns number of device in db -int central_device_db_count(void); - -// get device information: addr type and address -void central_device_db_info(int index, int * addr_type, bd_addr_t addr, key_t csrk); - -// get signature key -void central_device_db_csrk(int index, key_t csrk); - -// query last used/seen signing counter -uint32_t central_device_db_counter_get(int index); - -// update signing counter -void central_device_db_counter_set(int index, uint32_t counter); - -// free device -void central_device_db_remove(int index); - -// Central Device db implemenation using static memory -typedef struct central_device_memory_db { - int addr_type; - bd_addr_t addr; - key_t csrk; - key_t irk; - uint32_t signing_counter; -} central_device_memory_db_t; - -#define CENTRAL_DEVICE_MEMORY_SIZE 4 -static central_device_memory_db_t central_devices[CENTRAL_DEVICE_MEMORY_SIZE]; -static int central_devices_count; - -void central_device_db_init(){ - central_devices_count = 0; -} - -// @returns number of device in db -int central_device_db_count(void){ - return central_devices_count; -} - -// free device - TODO not implemented -void central_device_db_remove(int index){ -} - -int central_device_db_add(int addr_type, bd_addr_t addr, key_t irk, key_t csrk){ - if (central_devices_count >= CENTRAL_DEVICE_MEMORY_SIZE) return -1; - - printf("Central Device DB adding type %u - ", addr_type); - print_bd_addr(addr); - print_key("irk", irk); - print_key("csrk", csrk); - - int index = central_devices_count; - central_devices_count++; - - central_devices[index].addr_type = addr_type; - memcpy(central_devices[index].addr, addr, 6); - memcpy(central_devices[index].csrk, csrk, 16); - memcpy(central_devices[index].irk, irk, 16); - central_devices[index].signing_counter = 0; - - return index; -} - - -// get device information: addr type and address -void central_device_db_info(int index, int * addr_type, bd_addr_t addr, key_t irk){ - if (addr_type) *addr_type = central_devices[index].addr_type; - if (addr) memcpy(addr, central_devices[index].addr, 6); - if (irk) memcpy(irk, central_devices[index].irk, 16); -} - -// get signature key -void central_device_db_csrk(int index, key_t csrk){ - if (csrk) memcpy(csrk, central_devices[index].csrk, 16); -} - - -// query last used/seen signing counter -uint32_t central_device_db_counter_get(int index){ - return central_devices[index].signing_counter; -} - -// update signing counter -void central_device_db_counter_set(int index, uint32_t counter){ - central_devices[index].signing_counter = counter; -} - -void central_device_db_dump(){ - printf("Central Device DB dump, devices: %u\n", central_devices_count); - int i; - for (i=0;i + +// Central Device db interface +void central_device_db_init(); + +// @returns index if successful, -1 otherwise +int central_device_db_add(int addr_type, bd_addr_t addr, sm_key_t irk, sm_key_t csrk); + +// @returns number of device in db +int central_device_db_count(void); + +// get device information: addr type and address +void central_device_db_info(int index, int * addr_type, bd_addr_t addr, sm_key_t csrk); + +// get signature key +void central_device_db_csrk(int index, sm_key_t csrk); + +// query last used/seen signing counter +uint32_t central_device_db_counter_get(int index); + +// update signing counter +void central_device_db_counter_set(int index, uint32_t counter); + +// free device +void central_device_db_remove(int index); \ No newline at end of file diff --git a/example/libusb/central_device_db_memory.c b/example/libusb/central_device_db_memory.c new file mode 100644 index 000000000..a53dbe0f0 --- /dev/null +++ b/example/libusb/central_device_db_memory.c @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2011-2012 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 MATTHIAS RINGWALD 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 + * + */ + +#include "central_device_db.h" + +#include +#include + +// Central Device db implemenation using static memory +typedef struct central_device_memory_db { + int addr_type; + bd_addr_t addr; + sm_key_t csrk; + sm_key_t irk; + uint32_t signing_counter; +} central_device_memory_db_t; + +#define CENTRAL_DEVICE_MEMORY_SIZE 4 +static central_device_memory_db_t central_devices[CENTRAL_DEVICE_MEMORY_SIZE]; +static int central_devices_count; + +void central_device_db_init(){ + central_devices_count = 0; +} + +// @returns number of device in db +int central_device_db_count(void){ + return central_devices_count; +} + +// free device - TODO not implemented +void central_device_db_remove(int index){ +} + +int central_device_db_add(int addr_type, bd_addr_t addr, sm_key_t irk, sm_key_t csrk){ + if (central_devices_count >= CENTRAL_DEVICE_MEMORY_SIZE) return -1; + + printf("Central Device DB adding type %u - ", addr_type); + print_bd_addr(addr); + print_key("irk", irk); + print_key("csrk", csrk); + + int index = central_devices_count; + central_devices_count++; + + central_devices[index].addr_type = addr_type; + memcpy(central_devices[index].addr, addr, 6); + memcpy(central_devices[index].csrk, csrk, 16); + memcpy(central_devices[index].irk, irk, 16); + central_devices[index].signing_counter = 0; + + return index; +} + + +// get device information: addr type and address +void central_device_db_info(int index, int * addr_type, bd_addr_t addr, sm_key_t irk){ + if (addr_type) *addr_type = central_devices[index].addr_type; + if (addr) memcpy(addr, central_devices[index].addr, 6); + if (irk) memcpy(irk, central_devices[index].irk, 16); +} + +// get signature key +void central_device_db_csrk(int index, sm_key_t csrk){ + if (csrk) memcpy(csrk, central_devices[index].csrk, 16); +} + + +// query last used/seen signing counter +uint32_t central_device_db_counter_get(int index){ + return central_devices[index].signing_counter; +} + +// update signing counter +void central_device_db_counter_set(int index, uint32_t counter){ + central_devices[index].signing_counter = counter; +} + +void central_device_db_dump(){ + printf("Central Device DB dump, devices: %u\n", central_devices_count); + int i; + for (i=0;i