diff --git a/extmod/btstack/modbluetooth_btstack.c b/extmod/btstack/modbluetooth_btstack.c index 825a9ab7b1..ae4bac0094 100644 --- a/extmod/btstack/modbluetooth_btstack.c +++ b/extmod/btstack/modbluetooth_btstack.c @@ -53,6 +53,11 @@ STATIC const uint16_t BTSTACK_GAP_DEVICE_NAME_HANDLE = 3; volatile int mp_bluetooth_btstack_state = MP_BLUETOOTH_BTSTACK_STATE_OFF; +// sm_set_authentication_requirements is set-only, so cache current value. +#if MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING +STATIC uint8_t mp_bluetooth_btstack_sm_auth_req = 0; +#endif + #define ERRNO_BLUETOOTH_NOT_ACTIVE MP_ENODEV STATIC int btstack_error_to_errno(int err) { @@ -795,6 +800,39 @@ void mp_bluetooth_set_address_mode(uint8_t addr_mode) { } } +#if MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING +void mp_bluetooth_set_bonding(bool enabled) { + if (enabled) { + mp_bluetooth_btstack_sm_auth_req |= SM_AUTHREQ_BONDING; + } else { + mp_bluetooth_btstack_sm_auth_req &= ~SM_AUTHREQ_BONDING; + } + sm_set_authentication_requirements(mp_bluetooth_btstack_sm_auth_req); +} + +void mp_bluetooth_set_mitm_protection(bool enabled) { + if (enabled) { + mp_bluetooth_btstack_sm_auth_req |= SM_AUTHREQ_MITM_PROTECTION; + } else { + mp_bluetooth_btstack_sm_auth_req &= ~SM_AUTHREQ_MITM_PROTECTION; + } + sm_set_authentication_requirements(mp_bluetooth_btstack_sm_auth_req); +} + +void mp_bluetooth_set_le_secure(bool enabled) { + if (enabled) { + mp_bluetooth_btstack_sm_auth_req |= SM_AUTHREQ_SECURE_CONNECTION; + } else { + mp_bluetooth_btstack_sm_auth_req &= ~SM_AUTHREQ_SECURE_CONNECTION; + } + sm_set_authentication_requirements(mp_bluetooth_btstack_sm_auth_req); +} + +void mp_bluetooth_set_io_capability(uint8_t capability) { + sm_set_io_capabilities(capability); +} +#endif // MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING + size_t mp_bluetooth_gap_get_device_name(const uint8_t **buf) { uint8_t *value = NULL; size_t value_len = 0; diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c index 5d7de7b97f..06e340c42d 100644 --- a/extmod/modbluetooth.c +++ b/extmod/modbluetooth.c @@ -387,6 +387,28 @@ STATIC mp_obj_t bluetooth_ble_config(size_t n_args, const mp_obj_t *args, mp_map mp_bluetooth_set_address_mode(addr_mode); break; } + #if MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING + case MP_QSTR_bond: { + bool bonding_enabled = mp_obj_is_true(e->value); + mp_bluetooth_set_bonding(bonding_enabled); + break; + } + case MP_QSTR_mitm: { + bool mitm_protection = mp_obj_is_true(e->value); + mp_bluetooth_set_mitm_protection(mitm_protection); + break; + } + case MP_QSTR_io: { + mp_int_t io_capability = mp_obj_get_int(e->value); + mp_bluetooth_set_io_capability(io_capability); + break; + } + case MP_QSTR_le_secure: { + bool le_secure_required = mp_obj_is_true(e->value); + mp_bluetooth_set_le_secure(le_secure_required); + break; + } + #endif // MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING default: mp_raise_ValueError(MP_ERROR_TEXT("unknown config param")); } diff --git a/extmod/modbluetooth.h b/extmod/modbluetooth.h index 62ff6f2f9e..977453becd 100644 --- a/extmod/modbluetooth.h +++ b/extmod/modbluetooth.h @@ -152,6 +152,13 @@ #define MP_BLUETOOTH_ADDRESS_MODE_RPA (2) #define MP_BLUETOOTH_ADDRESS_MODE_NRPA (3) +// These match the spec values, can be used directly by the stack. +#define MP_BLUETOOTH_IO_CAPABILITY_DISPLAY_ONLY (0) +#define MP_BLUETOOTH_IO_CAPABILITY_DISPLAY_YESNO (1) +#define MP_BLUETOOTH_IO_CAPABILITY_KEYBOARD_ONLY (2) +#define MP_BLUETOOTH_IO_CAPABILITY_NO_INPUT_OUTPUT (3) +#define MP_BLUETOOTH_IO_CAPABILITY_KEYBOARD_DISPLAY (4) + /* These aren't included in the module for space reasons, but can be used in your Python code if necessary. @@ -208,6 +215,12 @@ _GATTS_ERROR_WRITE_NOT_PERMITTED = const(0x03) _GATTS_ERROR_INSUFFICIENT_AUTHENTICATION = const(0x05) _GATTS_ERROR_INSUFFICIENT_AUTHORIZATION = const(0x08) _GATTS_ERROR_INSUFFICIENT_ENCRYPTION = const(0x0f) + +_IO_CAPABILITY_DISPLAY_ONLY = const(0) +_IO_CAPABILITY_DISPLAY_YESNO = const(1) +_IO_CAPABILITY_KEYBOARD_ONLY = const(2) +_IO_CAPABILITY_NO_INPUT_OUTPUT = const(3) +_IO_CAPABILITY_KEYBOARD_DISPLAY = const(4) */ // bluetooth.UUID type. @@ -254,6 +267,17 @@ void mp_bluetooth_get_current_address(uint8_t *addr_type, uint8_t *addr); // Sets the addressing mode to use. void mp_bluetooth_set_address_mode(uint8_t addr_mode); +#if MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING +// Set bonding flag in pairing requests (i.e. persist security keys). +void mp_bluetooth_set_bonding(bool enabled); +// Require MITM protection. +void mp_bluetooth_set_mitm_protection(bool enabled); +// Require LE Secure pairing (rather than Legacy Pairing) +void mp_bluetooth_set_le_secure(bool enabled); +// I/O capabilities for authentication (see MP_BLUETOOTH_IO_CAPABILITY_*). +void mp_bluetooth_set_io_capability(uint8_t capability); +#endif // MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING + // Get or set the GAP device name that will be used by service 0x1800, characteristic 0x2a00. size_t mp_bluetooth_gap_get_device_name(const uint8_t **buf); int mp_bluetooth_gap_set_device_name(const uint8_t *buf, size_t len); diff --git a/extmod/nimble/modbluetooth_nimble.c b/extmod/nimble/modbluetooth_nimble.c index 312a564263..852b9eac02 100644 --- a/extmod/nimble/modbluetooth_nimble.c +++ b/extmod/nimble/modbluetooth_nimble.c @@ -552,6 +552,24 @@ void mp_bluetooth_set_address_mode(uint8_t addr_mode) { } } +#if MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING +void mp_bluetooth_set_bonding(bool enabled) { + ble_hs_cfg.sm_bonding = enabled; +} + +void mp_bluetooth_set_mitm_protection(bool enabled) { + ble_hs_cfg.sm_mitm = enabled; +} + +void mp_bluetooth_set_le_secure(bool enabled) { + ble_hs_cfg.sm_sc = enabled; +} + +void mp_bluetooth_set_io_capability(uint8_t capability) { + ble_hs_cfg.sm_io_cap = capability; +} +#endif // MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING + size_t mp_bluetooth_gap_get_device_name(const uint8_t **buf) { const char *name = ble_svc_gap_device_name(); *buf = (const uint8_t *)name; diff --git a/extmod/nimble/syscfg/syscfg.h b/extmod/nimble/syscfg/syscfg.h index bef6b3b921..a051a8fefd 100644 --- a/extmod/nimble/syscfg/syscfg.h +++ b/extmod/nimble/syscfg/syscfg.h @@ -116,18 +116,19 @@ int nimble_sprintf(char *str, const char *fmt, ...); #define MYNEWT_VAL_BLE_MONITOR_UART_BUFFER_SIZE (64) #define MYNEWT_VAL_BLE_MONITOR_UART_DEV ("uart0") #define MYNEWT_VAL_BLE_RPA_TIMEOUT (300) -#define MYNEWT_VAL_BLE_SM_BONDING (0) -#define MYNEWT_VAL_BLE_SM_IO_CAP (BLE_HS_IO_NO_INPUT_OUTPUT) #define MYNEWT_VAL_BLE_SM_KEYPRESS (0) #define MYNEWT_VAL_BLE_SM_LEGACY (1) #define MYNEWT_VAL_BLE_SM_MAX_PROCS (1) -#define MYNEWT_VAL_BLE_SM_MITM (0) #define MYNEWT_VAL_BLE_SM_OOB_DATA_FLAG (0) -#define MYNEWT_VAL_BLE_SM_OUR_KEY_DIST (0) -#define MYNEWT_VAL_BLE_SM_SC (1) -#define MYNEWT_VAL_BLE_SM_THEIR_KEY_DIST (0) +#define MYNEWT_VAL_BLE_SM_OUR_KEY_DIST (7) +#define MYNEWT_VAL_BLE_SM_THEIR_KEY_DIST (7) #define MYNEWT_VAL_BLE_STORE_MAX_BONDS (3) #define MYNEWT_VAL_BLE_STORE_MAX_CCCDS (8) +// These can be overridden at runtime with ble.config(le_secure, mitm, bond, io). +#define MYNEWT_VAL_BLE_SM_SC (1) +#define MYNEWT_VAL_BLE_SM_MITM (0) +#define MYNEWT_VAL_BLE_SM_BONDING (0) +#define MYNEWT_VAL_BLE_SM_IO_CAP (BLE_HS_IO_NO_INPUT_OUTPUT) /*** nimble/host/services/gap */ #define MYNEWT_VAL_BLE_SVC_GAP_APPEARANCE (0)