diff --git a/Kconfig b/Kconfig index 7c03dfd..749036a 100644 --- a/Kconfig +++ b/Kconfig @@ -1,5 +1,12 @@ source "Kconfig.zephyr" +config PW_SIGN_KEY + string "Signing key" + +config PW_ROTATE_PERIOD_SEC + int "How ofen message will be rotated" + default 15 + config ADV_BTN_TIMES int "How many times button press must be notified" default 10 diff --git a/Makefile b/Makefile index 68f019c..974bc6c 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: all build push +.PHONY: all build debug push BOARD := "xiao_ble" @@ -7,5 +7,8 @@ all: push build: west build -p always -b ${BOARD} . +debug: + west debug -r blackmagicprobe + push: build west -v flash -r blackmagicprobe diff --git a/boards/xiao_ble.conf b/boards/xiao_ble.conf new file mode 100644 index 0000000..237aff1 --- /dev/null +++ b/boards/xiao_ble.conf @@ -0,0 +1,3 @@ +CONFIG_LOG=y +CONFIG_SERIAL=y +CONFIG_CONSOLE=y diff --git a/prj.conf b/prj.conf index 91ccd1b..b176475 100644 --- a/prj.conf +++ b/prj.conf @@ -1,3 +1,6 @@ +CONFIG_BT_DEVICE_NAME="PinkyWinky" +CONFIG_PW_SIGN_KEY="lol-kek-cheburek" + CONFIG_MAIN_STACK_SIZE=2048 CONFIG_LOG=n @@ -7,10 +10,14 @@ CONFIG_CONSOLE=n CONFIG_BT=y CONFIG_BT_EXT_ADV=y CONFIG_BT_PER_ADV=n -CONFIG_BT_DEVICE_NAME="PinkyWinky" CONFIG_BT_PERIPHERAL=y CONFIG_BT_CTLR_ADV_DATA_LEN_MAX=64 +CONFIG_MBEDTLS=y +CONFIG_MBEDTLS_BUILTIN=y +CONFIG_MBEDTLS_HEAP_SIZE=512 +CONFIG_MBEDTLS_SHA1=y + CONFIG_PM_DEVICE=y CONFIG_PINCTRL=y diff --git a/pw-linux.code-workspace b/pw-linux.code-workspace index 2cf3148..998dfea 100644 --- a/pw-linux.code-workspace +++ b/pw-linux.code-workspace @@ -27,7 +27,8 @@ "variant": "c", "charconv": "c", "format": "c", - "cstdint": "c" + "cstdint": "c", + "stdbool.h": "c" }, "zephyr-ide.projects": {}, "python.defaultInterpreterPath": "~/zephyr/.venv/bin/python", diff --git a/src/ble.c b/src/ble.c index 5456450..0dd5bfb 100644 --- a/src/ble.c +++ b/src/ble.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "btn.h" @@ -19,7 +20,8 @@ LOG_MODULE_REGISTER(pw_ble); #define IDX_MFG_BATT_LVL 3 #define IDX_MFG_BTN_STATE (IDX_MFG_BATT_LVL + 1) #define IDX_MFG_TS (IDX_MFG_BTN_STATE + 1) -#define IDX_MFG_SIGN (IDX_MFG_TS + 8) +#define IDX_MFG_SIGN (IDX_MFG_TS + 4) +#define MFG_SIGN_LEN (10) static uint8_t mfg_data[] = { /* company ID must be 0xffff by spec */ @@ -31,9 +33,9 @@ static uint8_t mfg_data[] = { /* button state */ 0x00, /* ts */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* md5 sign */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, + /* truncated to 10 bytes sha1 sign */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const struct bt_data advertising[] = { @@ -43,14 +45,57 @@ static const struct bt_data advertising[] = { }; static struct bt_le_ext_adv *adv = NULL; -static uint64_t initial_ts = 0; +static uint32_t pw_initial_ts = 0; +static uint32_t pw_last_ts = 0; + +static uint8_t mfg_hash_buf[20] = {}; +static mbedtls_sha1_context mfg_hash_ctx; + +int pw_ble_update_mfg_sign() +{ + int err; + + err = mbedtls_sha1_starts(&mfg_hash_ctx); + if (err) { + LOG_ERR("failed to start sha1 hash (err %d)", err); + return -1; + } + + err = mbedtls_sha1_update(&mfg_hash_ctx, &mfg_data[0], IDX_MFG_SIGN); + if (err) { + LOG_ERR("failed to update hash (err %d)", err); + return -1; + } + + err = mbedtls_sha1_update(&mfg_hash_ctx, CONFIG_PW_SIGN_KEY, sizeof(CONFIG_PW_SIGN_KEY) - 1); + if (err) { + LOG_ERR("failed to update hash (err %d)", err); + return -1; + } + + err = mbedtls_sha1_finish(&mfg_hash_ctx, mfg_hash_buf); + if (err) { + LOG_ERR("failed to calculate hash (err %d)", err); + return -1; + } + + memcpy(&mfg_data[IDX_MFG_SIGN], mfg_hash_buf, MFG_SIGN_LEN); + return 0; +} void pw_ble_update_adv_data() { int err; - mfg_data[IDX_MFG_BTN_STATE] = pw_btn_is_pressed() ? 1 : 0; - sys_put_be64(initial_ts, &mfg_data[IDX_MFG_TS]); + pw_last_ts = pw_initial_ts + k_uptime_seconds(); + LOG_INF("upd: %u", pw_last_ts); + mfg_data[IDX_MFG_BTN_STATE] = is_pw_btn_pressed() ? 1 : 0; + sys_put_be32(pw_last_ts, &mfg_data[IDX_MFG_TS]); + + err = pw_ble_update_mfg_sign(); + if (err) { + LOG_ERR("failed to sign mfg data (err %d)", err); + } err = bt_le_ext_adv_set_data(adv, advertising, ARRAY_SIZE(advertising), NULL, 0); if (err) { @@ -65,12 +110,11 @@ void pw_ble_refresh_adv_data(struct k_work *work) K_WORK_DEFINE(refresh_adv_data_work, pw_ble_refresh_adv_data); - int pw_ble_init_adv_data() { int err; - err = bt_rand(&initial_ts, sizeof(uint32_t)); + err = bt_rand(&pw_initial_ts, sizeof(uint16_t)); if (err) { LOG_ERR("couldn't generate initial ts (err %d)", err); return -1; @@ -80,12 +124,20 @@ int pw_ble_init_adv_data() return 0; } +void pw_ble_adv_timer_cb(struct k_timer *dummy) +{ + LOG_INF("rotate data"); + pw_ble_refresh_data(); +} + +K_TIMER_DEFINE(pw_ble_adv_timer, pw_ble_adv_timer_cb, NULL); int pw_ble_enable() { int err; - /* Initialize the Bluetooth Subsystem */ + mbedtls_sha1_init(&mfg_hash_ctx); + err = bt_enable(NULL); if (err) { LOG_ERR("bluetooth init failed (err %d)", err); @@ -107,7 +159,6 @@ int pw_ble_enable() return -1; } - /* Set advertising data */ err = pw_ble_init_adv_data(); if (err) { LOG_ERR("advertising init failed (err %d)", err); @@ -120,6 +171,9 @@ int pw_ble_enable() LOG_ERR("failed to start extended advertising (err %d)", err); return -1; } + + LOG_INF("start adv msg rotation..."); + k_timer_start(&pw_ble_adv_timer, K_SECONDS(CONFIG_PW_ROTATE_PERIOD_SEC), K_SECONDS(CONFIG_PW_ROTATE_PERIOD_SEC)); LOG_INF("BLE initialized"); return 0; diff --git a/src/btn.c b/src/btn.c index ee2bcc4..476c69f 100644 --- a/src/btn.c +++ b/src/btn.c @@ -20,7 +20,7 @@ LOG_MODULE_REGISTER(pw_btn); static const struct gpio_dt_spec pw_btn = GPIO_DT_SPEC_GET(SW_NODE, gpios); static struct gpio_callback pw_btn_cb_data; -static uint8_t pw_btn_pressed = 0; +static bool pw_btn_pressed = 0; static uint32_t pw_btn_last_time = 0; void pw_btn_cb(const struct device *dev, struct gpio_callback *cb, uint32_t pins); @@ -53,13 +53,13 @@ int pw_btn_enable() return 0; } -int pw_btn_is_pressed() { - return pw_btn_pressed ? 1 : 0; +bool is_pw_btn_pressed() { + return pw_btn_pressed; } void pw_btn_release_cb(struct k_timer *dummy) { - pw_btn_pressed = 0; + pw_btn_pressed = false; pw_led_off(); pw_ble_refresh_data(); } @@ -76,7 +76,7 @@ void pw_btn_cb(const struct device *dev, struct gpio_callback *cb, uint32_t pins LOG_INF("button pressed at %" PRIu64, k_uptime_get()); pw_btn_last_time = time; - pw_btn_pressed = 1; + pw_btn_pressed = true; pw_led_on(); pw_ble_refresh_data(); k_timer_start(&pw_btn_release_timer, K_MSEC(CONFIG_ADV_BTN_TIMES * CONFIG_ADV_INTERVAL_MAX_MS), K_NO_WAIT); diff --git a/src/btn.h b/src/btn.h index 95a1e7f..08ff3fb 100644 --- a/src/btn.h +++ b/src/btn.h @@ -1,7 +1,9 @@ #ifndef H_PW_BTN_ #define H_PW_BTN_ +#include + int pw_btn_enable(); -int pw_btn_is_pressed(); +bool is_pw_btn_pressed(); #endif