diff --git a/main/Zbluefi.cpp b/main/Zbluefi.cpp new file mode 100644 index 0000000000..102c5d78a5 --- /dev/null +++ b/main/Zbluefi.cpp @@ -0,0 +1,447 @@ +#include +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" +#include "esp_system.h" +#include "esp_mac.h" +#include "esp_wifi.h" +#include "esp_event.h" +#include "esp_log.h" +#include "nvs_flash.h" +#include "esp_bt.h" + +#include "esp_blufi_api.h" +#include "Zbluefi.h" + +extern "C" { +#include "esp_blufi.h" +} +#include "NimBLEDevice.h" + +#define EXAMPLE_WIFI_CONNECTION_MAXIMUM_RETRY 2 //CONFIG_EXAMPLE_WIFI_CONNECTION_MAXIMUM_RETRY +#define EXAMPLE_INVALID_REASON 255 +#define EXAMPLE_INVALID_RSSI -128 + +#define WIFI_LIST_NUM 10 + +/* FreeRTOS event group to signal when we are connected & ready to make a request */ +static EventGroupHandle_t wifi_event_group; + +/* The event group allows multiple bits for each event, + but we only care about one event - are we connected + to the AP with an IP? */ +const int CONNECTED_BIT = BIT0; + +static uint8_t example_wifi_retry = 0; + +/* store the station info for send back to phone */ +static bool gl_sta_connected = false; +static bool gl_sta_got_ip = false; +static bool ble_is_connected = false; +static uint8_t gl_sta_bssid[6]; +static uint8_t gl_sta_ssid[32]; +static int gl_sta_ssid_len; +static wifi_sta_list_t gl_sta_list; +static bool gl_sta_is_connecting = false; +static esp_blufi_extra_info_t gl_sta_conn_info; +static wifi_config_t sta_config; +static wifi_config_t ap_config; + +static void example_event_callback(esp_blufi_cb_event_t event, esp_blufi_cb_param_t *param); + +static void example_record_wifi_conn_info(int rssi, uint8_t reason) +{ + memset(&gl_sta_conn_info, 0, sizeof(esp_blufi_extra_info_t)); + if (gl_sta_is_connecting) { + gl_sta_conn_info.sta_max_conn_retry_set = true; + gl_sta_conn_info.sta_max_conn_retry = EXAMPLE_WIFI_CONNECTION_MAXIMUM_RETRY; + } else { + gl_sta_conn_info.sta_conn_rssi_set = true; + gl_sta_conn_info.sta_conn_rssi = rssi; + gl_sta_conn_info.sta_conn_end_reason_set = true; + gl_sta_conn_info.sta_conn_end_reason = reason; + } +} + +static bool example_wifi_reconnect(void) +{ + bool ret; + if (gl_sta_is_connecting && example_wifi_retry++ < EXAMPLE_WIFI_CONNECTION_MAXIMUM_RETRY) { + BLUFI_INFO("BLUFI WiFi starts reconnection\n"); + gl_sta_is_connecting = (esp_wifi_connect() == ESP_OK); + example_record_wifi_conn_info(EXAMPLE_INVALID_RSSI, EXAMPLE_INVALID_REASON); + ret = true; + } else { + ret = false; + } + return ret; +} + +static void example_wifi_connect(void) +{ + example_wifi_retry = 0; + gl_sta_is_connecting = (esp_wifi_connect() == ESP_OK); + example_record_wifi_conn_info(EXAMPLE_INVALID_RSSI, EXAMPLE_INVALID_REASON); +} + +static int softap_get_current_connection_number(void) +{ + esp_err_t ret; + ret = esp_wifi_ap_get_sta_list(&gl_sta_list); + if (ret == ESP_OK) + { + return gl_sta_list.num; + } + + return 0; +} + +static void example_event_callback(esp_blufi_cb_event_t event, esp_blufi_cb_param_t *param) +{ + /* actually, should post to blufi_task handle the procedure, + * now, as a example, we do it more simply */ + switch (event) { + case ESP_BLUFI_EVENT_INIT_FINISH: + BLUFI_INFO("BLUFI init finish\n"); + esp_blufi_adv_start(); + break; + case ESP_BLUFI_EVENT_DEINIT_FINISH: + BLUFI_INFO("BLUFI deinit finish\n"); + break; + case ESP_BLUFI_EVENT_BLE_CONNECT: + BLUFI_INFO("BLUFI ble connect\n"); + ble_is_connected = true; + esp_blufi_adv_stop(); + blufi_security_init(); + break; + case ESP_BLUFI_EVENT_BLE_DISCONNECT: + BLUFI_INFO("BLUFI ble disconnect\n"); + ble_is_connected = false; + blufi_security_deinit(); + esp_blufi_adv_start(); + break; + case ESP_BLUFI_EVENT_SET_WIFI_OPMODE: + BLUFI_INFO("BLUFI Set WIFI opmode %d\n", param->wifi_mode.op_mode); + ESP_ERROR_CHECK( esp_wifi_set_mode(param->wifi_mode.op_mode) ); + break; + case ESP_BLUFI_EVENT_REQ_CONNECT_TO_AP: + BLUFI_INFO("BLUFI requset wifi connect to AP\n"); + + esp_wifi_disconnect(); + example_wifi_connect(); + break; + case ESP_BLUFI_EVENT_REQ_DISCONNECT_FROM_AP: + BLUFI_INFO("BLUFI requset wifi disconnect from AP\n"); + esp_wifi_disconnect(); + break; + case ESP_BLUFI_EVENT_REPORT_ERROR: + BLUFI_ERROR("BLUFI report error, error code %d\n", param->report_error.state); + esp_blufi_send_error_info(param->report_error.state); + break; + case ESP_BLUFI_EVENT_GET_WIFI_STATUS: { + wifi_mode_t mode; + esp_blufi_extra_info_t info; + + esp_wifi_get_mode(&mode); + + if (gl_sta_connected) { + memset(&info, 0, sizeof(esp_blufi_extra_info_t)); + memcpy(info.sta_bssid, gl_sta_bssid, 6); + info.sta_bssid_set = true; + info.sta_ssid = gl_sta_ssid; + info.sta_ssid_len = gl_sta_ssid_len; + esp_blufi_send_wifi_conn_report(mode, gl_sta_got_ip ? ESP_BLUFI_STA_CONN_SUCCESS : ESP_BLUFI_STA_NO_IP, softap_get_current_connection_number(), &info); + } else if (gl_sta_is_connecting) { + esp_blufi_send_wifi_conn_report(mode, ESP_BLUFI_STA_CONNECTING, softap_get_current_connection_number(), &gl_sta_conn_info); + } else { + esp_blufi_send_wifi_conn_report(mode, ESP_BLUFI_STA_CONN_FAIL, softap_get_current_connection_number(), &gl_sta_conn_info); + } + BLUFI_INFO("BLUFI get wifi status from AP\n"); + + break; + } + case ESP_BLUFI_EVENT_RECV_SLAVE_DISCONNECT_BLE: + BLUFI_INFO("blufi close a gatt connection"); + esp_blufi_disconnect(); + break; + case ESP_BLUFI_EVENT_DEAUTHENTICATE_STA: + break; + case ESP_BLUFI_EVENT_RECV_STA_BSSID: + memcpy(sta_config.sta.bssid, param->sta_bssid.bssid, 6); + sta_config.sta.bssid_set = 1; + esp_wifi_set_config(WIFI_IF_STA, &sta_config); + BLUFI_INFO("Recv STA BSSID %s\n", sta_config.sta.ssid); + break; + case ESP_BLUFI_EVENT_RECV_STA_SSID: + strncpy((char *)sta_config.sta.ssid, (char *)param->sta_ssid.ssid, param->sta_ssid.ssid_len); + sta_config.sta.ssid[param->sta_ssid.ssid_len] = '\0'; + esp_wifi_set_config(WIFI_IF_STA, &sta_config); + BLUFI_INFO("Recv STA SSID %s\n", sta_config.sta.ssid); + break; + case ESP_BLUFI_EVENT_RECV_STA_PASSWD: + strncpy((char *)sta_config.sta.password, (char *)param->sta_passwd.passwd, param->sta_passwd.passwd_len); + sta_config.sta.password[param->sta_passwd.passwd_len] = '\0'; + esp_wifi_set_config(WIFI_IF_STA, &sta_config); + BLUFI_INFO("Recv STA PASSWORD %s\n", sta_config.sta.password); + break; + case ESP_BLUFI_EVENT_RECV_SOFTAP_SSID: + strncpy((char *)ap_config.ap.ssid, (char *)param->softap_ssid.ssid, param->softap_ssid.ssid_len); + ap_config.ap.ssid[param->softap_ssid.ssid_len] = '\0'; + ap_config.ap.ssid_len = param->softap_ssid.ssid_len; + esp_wifi_set_config(WIFI_IF_AP, &ap_config); + BLUFI_INFO("Recv SOFTAP SSID %s, ssid len %d\n", ap_config.ap.ssid, ap_config.ap.ssid_len); + break; + case ESP_BLUFI_EVENT_RECV_SOFTAP_PASSWD: + strncpy((char *)ap_config.ap.password, (char *)param->softap_passwd.passwd, param->softap_passwd.passwd_len); + ap_config.ap.password[param->softap_passwd.passwd_len] = '\0'; + esp_wifi_set_config(WIFI_IF_AP, &ap_config); + BLUFI_INFO("Recv SOFTAP PASSWORD %s len = %d\n", ap_config.ap.password, param->softap_passwd.passwd_len); + break; + case ESP_BLUFI_EVENT_RECV_SOFTAP_MAX_CONN_NUM: + if (param->softap_max_conn_num.max_conn_num > 4) { + return; + } + ap_config.ap.max_connection = param->softap_max_conn_num.max_conn_num; + esp_wifi_set_config(WIFI_IF_AP, &ap_config); + BLUFI_INFO("Recv SOFTAP MAX CONN NUM %d\n", ap_config.ap.max_connection); + break; + case ESP_BLUFI_EVENT_RECV_SOFTAP_AUTH_MODE: + if (param->softap_auth_mode.auth_mode >= WIFI_AUTH_MAX) { + return; + } + ap_config.ap.authmode = param->softap_auth_mode.auth_mode; + esp_wifi_set_config(WIFI_IF_AP, &ap_config); + BLUFI_INFO("Recv SOFTAP AUTH MODE %d\n", ap_config.ap.authmode); + break; + case ESP_BLUFI_EVENT_RECV_SOFTAP_CHANNEL: + if (param->softap_channel.channel > 13) { + return; + } + ap_config.ap.channel = param->softap_channel.channel; + esp_wifi_set_config(WIFI_IF_AP, &ap_config); + BLUFI_INFO("Recv SOFTAP CHANNEL %d\n", ap_config.ap.channel); + break; + case ESP_BLUFI_EVENT_GET_WIFI_LIST:{ + wifi_scan_config_t scanConf = { + .ssid = NULL, + .bssid = NULL, + .channel = 0, + .show_hidden = false + }; + esp_err_t ret = esp_wifi_scan_start(&scanConf, true); + if (ret != ESP_OK) { + esp_blufi_send_error_info(ESP_BLUFI_WIFI_SCAN_FAIL); + } + break; + } + case ESP_BLUFI_EVENT_RECV_CUSTOM_DATA: + BLUFI_INFO("Recv Custom Data %" PRIu32 "\n", param->custom_data.data_len); + esp_log_buffer_hex("Custom Data", param->custom_data.data, param->custom_data.data_len); + break; + case ESP_BLUFI_EVENT_RECV_USERNAME: + break; + case ESP_BLUFI_EVENT_RECV_CA_CERT: + break; + case ESP_BLUFI_EVENT_RECV_CLIENT_CERT: + break; + case ESP_BLUFI_EVENT_RECV_SERVER_CERT: + break; + case ESP_BLUFI_EVENT_RECV_CLIENT_PRIV_KEY: + break;; + case ESP_BLUFI_EVENT_RECV_SERVER_PRIV_KEY: + break; + default: + break; + } +} + +static void ip_event_handler(void* arg, esp_event_base_t event_base, + int32_t event_id, void* event_data) +{ + wifi_mode_t mode; + + switch (event_id) { + case IP_EVENT_STA_GOT_IP: { + esp_blufi_extra_info_t info; + + xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); + esp_wifi_get_mode(&mode); + + memset(&info, 0, sizeof(esp_blufi_extra_info_t)); + memcpy(info.sta_bssid, gl_sta_bssid, 6); + info.sta_bssid_set = true; + info.sta_ssid = gl_sta_ssid; + info.sta_ssid_len = gl_sta_ssid_len; + gl_sta_got_ip = true; + if (ble_is_connected == true) { + esp_blufi_send_wifi_conn_report(mode, ESP_BLUFI_STA_CONN_SUCCESS, softap_get_current_connection_number(), &info); + } else { + BLUFI_INFO("BLUFI BLE is not connected yet\n"); + } + break; + } + default: + break; + } + return; +} + +static void wifi_event_handler(void* arg, esp_event_base_t event_base, + int32_t event_id, void* event_data) +{ + wifi_event_sta_connected_t *event; + wifi_event_sta_disconnected_t *disconnected_event; + wifi_mode_t mode; + + switch (event_id) { + case WIFI_EVENT_STA_START: + example_wifi_connect(); + break; + case WIFI_EVENT_STA_CONNECTED: + gl_sta_connected = true; + gl_sta_is_connecting = false; + event = (wifi_event_sta_connected_t*) event_data; + memcpy(gl_sta_bssid, event->bssid, 6); + memcpy(gl_sta_ssid, event->ssid, event->ssid_len); + gl_sta_ssid_len = event->ssid_len; + break; + case WIFI_EVENT_STA_DISCONNECTED: + /* Only handle reconnection during connecting */ + if (gl_sta_connected == false && example_wifi_reconnect() == false) { + gl_sta_is_connecting = false; + disconnected_event = (wifi_event_sta_disconnected_t*) event_data; + example_record_wifi_conn_info(disconnected_event->rssi, disconnected_event->reason); + } + /* This is a workaround as ESP32 WiFi libs don't currently + auto-reassociate. */ + gl_sta_connected = false; + gl_sta_got_ip = false; + memset(gl_sta_ssid, 0, 32); + memset(gl_sta_bssid, 0, 6); + gl_sta_ssid_len = 0; + xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); + break; + case WIFI_EVENT_AP_START: + esp_wifi_get_mode(&mode); + + /* TODO: get config or information of softap, then set to report extra_info */ + if (ble_is_connected == true) { + if (gl_sta_connected) { + esp_blufi_extra_info_t info; + memset(&info, 0, sizeof(esp_blufi_extra_info_t)); + memcpy(info.sta_bssid, gl_sta_bssid, 6); + info.sta_bssid_set = true; + info.sta_ssid = gl_sta_ssid; + info.sta_ssid_len = gl_sta_ssid_len; + esp_blufi_send_wifi_conn_report(mode, gl_sta_got_ip ? ESP_BLUFI_STA_CONN_SUCCESS : ESP_BLUFI_STA_NO_IP, softap_get_current_connection_number(), &info); + } else if (gl_sta_is_connecting) { + esp_blufi_send_wifi_conn_report(mode, ESP_BLUFI_STA_CONNECTING, softap_get_current_connection_number(), &gl_sta_conn_info); + } else { + esp_blufi_send_wifi_conn_report(mode, ESP_BLUFI_STA_CONN_FAIL, softap_get_current_connection_number(), &gl_sta_conn_info); + } + } else { + BLUFI_INFO("BLUFI BLE is not connected yet\n"); + } + break; + case WIFI_EVENT_SCAN_DONE: { + uint16_t apCount = 0; + esp_wifi_scan_get_ap_num(&apCount); + if (apCount == 0) { + BLUFI_INFO("Nothing AP found"); + break; + } + wifi_ap_record_t *ap_list = (wifi_ap_record_t *)malloc(sizeof(wifi_ap_record_t) * apCount); + if (!ap_list) { + BLUFI_ERROR("malloc error, ap_list is NULL"); + break; + } + ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&apCount, ap_list)); + esp_blufi_ap_record_t * blufi_ap_list = (esp_blufi_ap_record_t *)malloc(apCount * sizeof(esp_blufi_ap_record_t)); + if (!blufi_ap_list) { + if (ap_list) { + free(ap_list); + } + BLUFI_ERROR("malloc error, blufi_ap_list is NULL"); + break; + } + for (int i = 0; i < apCount; ++i) + { + blufi_ap_list[i].rssi = ap_list[i].rssi; + memcpy(blufi_ap_list[i].ssid, ap_list[i].ssid, sizeof(ap_list[i].ssid)); + } + + if (ble_is_connected == true) { + esp_blufi_send_wifi_list(apCount, blufi_ap_list); + } else { + BLUFI_INFO("BLUFI BLE is not connected yet\n"); + } + + esp_wifi_scan_stop(); + free(ap_list); + free(blufi_ap_list); + break; + } + case WIFI_EVENT_AP_STACONNECTED: { + wifi_event_ap_staconnected_t* event = (wifi_event_ap_staconnected_t*) event_data; + BLUFI_INFO("station "MACSTR" join, AID=%d", MAC2STR(event->mac), event->aid); + break; + } + case WIFI_EVENT_AP_STADISCONNECTED: { + wifi_event_ap_stadisconnected_t* event = (wifi_event_ap_stadisconnected_t*) event_data; + BLUFI_INFO("station "MACSTR" leave, AID=%d", MAC2STR(event->mac), event->aid); + break; + } + + default: + break; + } + return; +} + +static void initialise_wifi(void) +{ + ESP_ERROR_CHECK(esp_netif_init()); + wifi_event_group = xEventGroupCreate(); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta(); + assert(sta_netif); + esp_netif_t *ap_netif = esp_netif_create_default_wifi_ap(); + assert(ap_netif); + ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL)); + ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &ip_event_handler, NULL)); + + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); + ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); + example_record_wifi_conn_info(EXAMPLE_INVALID_RSSI, EXAMPLE_INVALID_REASON); + ESP_ERROR_CHECK( esp_wifi_start() ); +} + +static esp_blufi_callbacks_t example_callbacks = { + .event_cb = example_event_callback, + .negotiate_data_handler = blufi_dh_negotiate_data_handler, + .encrypt_func = blufi_aes_encrypt, + .decrypt_func = blufi_aes_decrypt, + .checksum_func = blufi_crc_checksum, +}; + +bool startBluefi() +{ + esp_err_t ret = ESP_OK; + initialise_wifi(); + + ret = esp_blufi_register_callbacks(&example_callbacks); + if(ret){ + BLUFI_ERROR("%s blufi register failed, error code = %x\n", __func__, ret); + return false; + } + + esp_blufi_gatt_svr_init(); + esp_blufi_btc_init(); + + NimBLEDevice::init("OMG_BLUEFI"); + + return true; +} diff --git a/main/Zbluefi.h b/main/Zbluefi.h new file mode 100644 index 0000000000..ace19aef1f --- /dev/null +++ b/main/Zbluefi.h @@ -0,0 +1,25 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#define BLUFI_EXAMPLE_TAG "BLUFI_EXAMPLE" +#define BLUFI_INFO(fmt, ...) ESP_LOGI(BLUFI_EXAMPLE_TAG, fmt, ##__VA_ARGS__) +#define BLUFI_ERROR(fmt, ...) ESP_LOGE(BLUFI_EXAMPLE_TAG, fmt, ##__VA_ARGS__) + +void blufi_dh_negotiate_data_handler(uint8_t *data, int len, uint8_t **output_data, int *output_len, bool *need_free); +int blufi_aes_encrypt(uint8_t iv8, uint8_t *crypt_data, int crypt_len); +int blufi_aes_decrypt(uint8_t iv8, uint8_t *crypt_data, int crypt_len); +uint16_t blufi_crc_checksum(uint8_t iv8, uint8_t *data, int len); + +esp_err_t blufi_security_init(void); +void blufi_security_deinit(void); +int esp_blufi_gap_register_callback(void); +esp_err_t esp_blufi_host_init(void); +esp_err_t esp_blufi_host_and_cb_init(esp_blufi_callbacks_t *callbacks); +esp_err_t esp_blufi_host_deinit(void); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/main/Zbluefi_sec.cpp b/main/Zbluefi_sec.cpp new file mode 100644 index 0000000000..11a5f66a19 --- /dev/null +++ b/main/Zbluefi_sec.cpp @@ -0,0 +1,217 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" +#include "esp_system.h" +#include "esp_wifi.h" +#include "esp_event.h" +#include "esp_log.h" +#include "nvs_flash.h" +#include "esp_random.h" +#include "esp_bt.h" + +#include "esp_blufi_api.h" +#include "Zbluefi.h" + +#include "mbedtls/aes.h" +#include "mbedtls/dhm.h" +#include "mbedtls/md5.h" +#include "esp_crc.h" + +/* + The SEC_TYPE_xxx is for self-defined packet data type in the procedure of "BLUFI negotiate key" + If user use other negotiation procedure to exchange(or generate) key, should redefine the type by yourself. + */ +#define SEC_TYPE_DH_PARAM_LEN 0x00 +#define SEC_TYPE_DH_PARAM_DATA 0x01 +#define SEC_TYPE_DH_P 0x02 +#define SEC_TYPE_DH_G 0x03 +#define SEC_TYPE_DH_PUBLIC 0x04 + + +struct blufi_security { +#define DH_SELF_PUB_KEY_LEN 128 +#define DH_SELF_PUB_KEY_BIT_LEN (DH_SELF_PUB_KEY_LEN * 8) + uint8_t self_public_key[DH_SELF_PUB_KEY_LEN]; +#define SHARE_KEY_LEN 128 +#define SHARE_KEY_BIT_LEN (SHARE_KEY_LEN * 8) + uint8_t share_key[SHARE_KEY_LEN]; + size_t share_len; +#define PSK_LEN 16 + uint8_t psk[PSK_LEN]; + uint8_t *dh_param; + int dh_param_len; + uint8_t iv[16]; + mbedtls_dhm_context dhm; + mbedtls_aes_context aes; +}; +static struct blufi_security *blufi_sec; + +static int myrand( void *rng_state, unsigned char *output, size_t len ) +{ + esp_fill_random(output, len); + return( 0 ); +} + +extern "C" void btc_blufi_report_error(esp_blufi_error_state_t state); + +void blufi_dh_negotiate_data_handler(uint8_t *data, int len, uint8_t **output_data, int *output_len, bool *need_free) +{ + int ret; + uint8_t type = data[0]; + + if (blufi_sec == NULL) { + BLUFI_ERROR("BLUFI Security is not initialized"); + btc_blufi_report_error(ESP_BLUFI_INIT_SECURITY_ERROR); + return; + } + + switch (type) { + case SEC_TYPE_DH_PARAM_LEN: + blufi_sec->dh_param_len = ((data[1]<<8)|data[2]); + if (blufi_sec->dh_param) { + free(blufi_sec->dh_param); + blufi_sec->dh_param = NULL; + } + blufi_sec->dh_param = (uint8_t *)malloc(blufi_sec->dh_param_len); + if (blufi_sec->dh_param == NULL) { + btc_blufi_report_error(ESP_BLUFI_DH_MALLOC_ERROR); + BLUFI_ERROR("%s, malloc failed\n", __func__); + return; + } + break; + case SEC_TYPE_DH_PARAM_DATA:{ + if (blufi_sec->dh_param == NULL) { + BLUFI_ERROR("%s, blufi_sec->dh_param == NULL\n", __func__); + btc_blufi_report_error(ESP_BLUFI_DH_PARAM_ERROR); + return; + } + uint8_t *param = blufi_sec->dh_param; + memcpy(blufi_sec->dh_param, &data[1], blufi_sec->dh_param_len); + ret = mbedtls_dhm_read_params(&blufi_sec->dhm, ¶m, ¶m[blufi_sec->dh_param_len]); + if (ret) { + BLUFI_ERROR("%s read param failed %d\n", __func__, ret); + btc_blufi_report_error(ESP_BLUFI_READ_PARAM_ERROR); + return; + } + free(blufi_sec->dh_param); + blufi_sec->dh_param = NULL; + + ret = mbedtls_dhm_make_public(&blufi_sec->dhm, (int) mbedtls_mpi_size( &blufi_sec->dhm.P ), blufi_sec->self_public_key, blufi_sec->dhm.len, myrand, NULL); if (ret) { + BLUFI_ERROR("%s make public failed %d\n", __func__, ret); + btc_blufi_report_error(ESP_BLUFI_MAKE_PUBLIC_ERROR); + return; + } + + ret = mbedtls_dhm_calc_secret( &blufi_sec->dhm, + blufi_sec->share_key, + SHARE_KEY_BIT_LEN, + &blufi_sec->share_len, + myrand, NULL); + if (ret) { + BLUFI_ERROR("%s mbedtls_dhm_calc_secret failed %d\n", __func__, ret); + btc_blufi_report_error(ESP_BLUFI_DH_PARAM_ERROR); + return; + } + + mbedtls_md5(blufi_sec->share_key, blufi_sec->share_len, blufi_sec->psk); + + mbedtls_aes_setkey_enc(&blufi_sec->aes, blufi_sec->psk, 128); + + /* alloc output data */ + *output_data = &blufi_sec->self_public_key[0]; + *output_len = blufi_sec->dhm.len; + *need_free = false; + + } + break; + case SEC_TYPE_DH_P: + break; + case SEC_TYPE_DH_G: + break; + case SEC_TYPE_DH_PUBLIC: + break; + } +} + +int blufi_aes_encrypt(uint8_t iv8, uint8_t *crypt_data, int crypt_len) +{ + int ret; + size_t iv_offset = 0; + uint8_t iv0[16]; + + memcpy(iv0, blufi_sec->iv, sizeof(blufi_sec->iv)); + iv0[0] = iv8; /* set iv8 as the iv0[0] */ + + ret = mbedtls_aes_crypt_cfb128(&blufi_sec->aes, MBEDTLS_AES_ENCRYPT, crypt_len, &iv_offset, iv0, crypt_data, crypt_data); + if (ret) { + return -1; + } + + return crypt_len; +} + +int blufi_aes_decrypt(uint8_t iv8, uint8_t *crypt_data, int crypt_len) +{ + int ret; + size_t iv_offset = 0; + uint8_t iv0[16]; + + memcpy(iv0, blufi_sec->iv, sizeof(blufi_sec->iv)); + iv0[0] = iv8; /* set iv8 as the iv0[0] */ + + ret = mbedtls_aes_crypt_cfb128(&blufi_sec->aes, MBEDTLS_AES_DECRYPT, crypt_len, &iv_offset, iv0, crypt_data, crypt_data); + if (ret) { + return -1; + } + + return crypt_len; +} + +uint16_t blufi_crc_checksum(uint8_t iv8, uint8_t *data, int len) +{ + /* This iv8 ignore, not used */ + return esp_crc16_be(0, data, len); +} + +esp_err_t blufi_security_init(void) +{ + blufi_sec = (struct blufi_security *)malloc(sizeof(struct blufi_security)); + if (blufi_sec == NULL) { + return ESP_FAIL; + } + + memset(blufi_sec, 0x0, sizeof(struct blufi_security)); + + mbedtls_dhm_init(&blufi_sec->dhm); + mbedtls_aes_init(&blufi_sec->aes); + + memset(blufi_sec->iv, 0x0, 16); + return 0; +} + +void blufi_security_deinit(void) +{ + if (blufi_sec == NULL) { + return; + } + if (blufi_sec->dh_param){ + free(blufi_sec->dh_param); + blufi_sec->dh_param = NULL; + } + mbedtls_dhm_free(&blufi_sec->dhm); + mbedtls_aes_free(&blufi_sec->aes); + + memset(blufi_sec, 0x0, sizeof(struct blufi_security)); + + free(blufi_sec); + blufi_sec = NULL; +} diff --git a/main/main.ino b/main/main.ino index 58110089dc..fef72ee2f5 100644 --- a/main/main.ino +++ b/main/main.ino @@ -866,11 +866,14 @@ void setESPWifiProtocolTxPower() { } #endif +extern bool startBluefi(); + void setup() { //Launch serial for debugging purposes Serial.begin(SERIAL_BAUD); Log.begin(LOG_LEVEL, &Serial); Log.notice(F(CR "************* WELCOME TO OpenMQTTGateway **************" CR)); + startBluefi(); #if defined(TRIGGER_GPIO) && !defined(ESPWifiManualSetup) pinMode(TRIGGER_GPIO, INPUT_PULLUP); checkButton(); diff --git a/sdkconfig.defaults b/sdkconfig.defaults index b8f0ec39e7..aca7b9ee8b 100644 --- a/sdkconfig.defaults +++ b/sdkconfig.defaults @@ -52,10 +52,62 @@ CONFIG_BTDM_CTRL_HLI=y # end of Bluetooth controller # CONFIG_BT_BLUEDROID_ENABLED is not set -# CONFIG_BT_NIMBLE_ENABLED is not set -CONFIG_BT_CONTROLLER_ONLY=y +CONFIG_BT_NIMBLE_ENABLED=y +# CONFIG_BT_CONTROLLER_ONLY is not set + +# +# NimBLE Options +# +CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL=y +# CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_DEFAULT is not set +# CONFIG_BT_NIMBLE_LOG_LEVEL_NONE is not set +# CONFIG_BT_NIMBLE_LOG_LEVEL_ERROR is not set +# CONFIG_BT_NIMBLE_LOG_LEVEL_WARNING is not set +CONFIG_BT_NIMBLE_LOG_LEVEL_INFO=y +# CONFIG_BT_NIMBLE_LOG_LEVEL_DEBUG is not set +CONFIG_BT_NIMBLE_LOG_LEVEL=1 +CONFIG_BT_NIMBLE_MAX_CONNECTIONS=3 +CONFIG_BT_NIMBLE_MAX_BONDS=3 +CONFIG_BT_NIMBLE_MAX_CCCDS=8 +CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM=0 +CONFIG_BT_NIMBLE_PINNED_TO_CORE_0=y +# CONFIG_BT_NIMBLE_PINNED_TO_CORE_1 is not set +CONFIG_BT_NIMBLE_PINNED_TO_CORE=0 +CONFIG_BT_NIMBLE_TASK_STACK_SIZE=4096 +CONFIG_BT_NIMBLE_ROLE_CENTRAL=y +CONFIG_BT_NIMBLE_ROLE_PERIPHERAL=y +CONFIG_BT_NIMBLE_ROLE_BROADCASTER=y +CONFIG_BT_NIMBLE_ROLE_OBSERVER=y +CONFIG_BT_NIMBLE_NVS_PERSIST=y +CONFIG_BT_NIMBLE_SM_LEGACY=y +CONFIG_BT_NIMBLE_SM_SC=y +# CONFIG_BT_NIMBLE_DEBUG is not set +# CONFIG_BT_NIMBLE_SM_SC_DEBUG_KEYS is not set +CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME="nimble" +CONFIG_BT_NIMBLE_GAP_DEVICE_NAME_MAX_LEN=31 +CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU=256 +CONFIG_BT_NIMBLE_SVC_GAP_APPEARANCE=0 +CONFIG_BT_NIMBLE_ACL_BUF_COUNT=20 +CONFIG_BT_NIMBLE_ACL_BUF_SIZE=255 +CONFIG_BT_NIMBLE_HCI_EVT_BUF_SIZE=70 +CONFIG_BT_NIMBLE_HCI_EVT_HI_BUF_COUNT=30 +CONFIG_BT_NIMBLE_HCI_EVT_LO_BUF_COUNT=8 +CONFIG_BT_NIMBLE_MSYS1_BLOCK_COUNT=12 +CONFIG_BT_NIMBLE_HS_FLOW_CTRL=y +CONFIG_BT_NIMBLE_HS_FLOW_CTRL_ITVL=1000 +CONFIG_BT_NIMBLE_HS_FLOW_CTRL_THRESH=2 +CONFIG_BT_NIMBLE_HS_FLOW_CTRL_TX_ON_DISCONNECT=y +CONFIG_BT_NIMBLE_RPA_TIMEOUT=900 +# CONFIG_BT_NIMBLE_MESH is not set +CONFIG_BT_NIMBLE_CRYPTO_STACK_MBEDTLS=y +CONFIG_BT_NIMBLE_HS_STOP_TIMEOUT_MS=2000 +# CONFIG_BT_NIMBLE_ENABLE_CONN_REATTEMPT is not set +CONFIG_BT_NIMBLE_BLUFI_ENABLE=y +CONFIG_BT_NIMBLE_USE_ESP_TIMER=y +# end of NimBLE Options # end of Bluetooth + # # TLS Key Exchange Methods #