summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Mussared <jim.mussared@gmail.com>2020-11-26 23:49:45 +1100
committerDamien George <damien@micropython.org>2020-12-02 14:43:32 +1100
commite4f27cbee767d24f8e05678a484a584ec6fbe974 (patch)
tree2c922904be6249b14323cbec9f8fe2228181ba2d
parent4bcbbfdb6cde6293085f4123090890c889cad50d (diff)
extmod/modbluetooth: Add support for passkey authentication.
Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
-rw-r--r--extmod/modbluetooth.c14
-rw-r--r--extmod/modbluetooth.h20
-rw-r--r--extmod/nimble/modbluetooth_nimble.c37
3 files changed, 71 insertions, 0 deletions
diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c
index ba5333e70..caaf872e7 100644
--- a/extmod/modbluetooth.c
+++ b/extmod/modbluetooth.c
@@ -689,6 +689,14 @@ STATIC mp_obj_t bluetooth_ble_gap_pair(mp_obj_t self_in, mp_obj_t conn_handle_in
return bluetooth_handle_errno(mp_bluetooth_gap_pair(conn_handle));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(bluetooth_ble_gap_pair_obj, bluetooth_ble_gap_pair);
+
+STATIC mp_obj_t bluetooth_ble_gap_passkey(size_t n_args, const mp_obj_t *args) {
+ uint16_t conn_handle = mp_obj_get_int(args[1]);
+ uint8_t action = mp_obj_get_int(args[2]);
+ mp_int_t passkey = mp_obj_get_int(args[3]);
+ return bluetooth_handle_errno(mp_bluetooth_gap_passkey(conn_handle, action, passkey));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gap_passkey_obj, 4, 4, bluetooth_ble_gap_passkey);
#endif // MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING
// ----------------------------------------------------------------------------
@@ -894,6 +902,7 @@ STATIC const mp_rom_map_elem_t bluetooth_ble_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_gap_disconnect), MP_ROM_PTR(&bluetooth_ble_gap_disconnect_obj) },
#if MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING
{ MP_ROM_QSTR(MP_QSTR_gap_pair), MP_ROM_PTR(&bluetooth_ble_gap_pair_obj) },
+ { MP_ROM_QSTR(MP_QSTR_gap_passkey), MP_ROM_PTR(&bluetooth_ble_gap_passkey_obj) },
#endif
// GATT Server (i.e. peripheral/advertiser role)
{ MP_ROM_QSTR(MP_QSTR_gatts_register_services), MP_ROM_PTR(&bluetooth_ble_gatts_register_services_obj) },
@@ -1167,6 +1176,11 @@ bool mp_bluetooth_gap_on_set_secret(uint8_t type, const uint8_t *key, size_t key
mp_obj_t result = invoke_irq_handler(MP_BLUETOOTH_IRQ_SET_SECRET, args, 1, 0, NULL_ADDR, NULL_UUID, data, data_len, 2);
return mp_obj_is_true(result);
}
+
+void mp_bluetooth_gap_on_passkey_action(uint16_t conn_handle, uint8_t action, mp_int_t passkey) {
+ mp_int_t args[] = { conn_handle, action, passkey };
+ invoke_irq_handler(MP_BLUETOOTH_IRQ_PASSKEY_ACTION, args, 2, 1, NULL_ADDR, NULL_UUID, NULL_DATA, NULL_DATA_LEN, 0);
+}
#endif // MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING
void mp_bluetooth_gatts_on_write(uint16_t conn_handle, uint16_t value_handle) {
diff --git a/extmod/modbluetooth.h b/extmod/modbluetooth.h
index d79b7f56b..f14033de3 100644
--- a/extmod/modbluetooth.h
+++ b/extmod/modbluetooth.h
@@ -148,6 +148,7 @@
#define MP_BLUETOOTH_IRQ_ENCRYPTION_UPDATE (28)
#define MP_BLUETOOTH_IRQ_GET_SECRET (29)
#define MP_BLUETOOTH_IRQ_SET_SECRET (30)
+#define MP_BLUETOOTH_IRQ_PASSKEY_ACTION (31)
#define MP_BLUETOOTH_ADDRESS_MODE_PUBLIC (0)
#define MP_BLUETOOTH_ADDRESS_MODE_RANDOM (1)
@@ -167,6 +168,12 @@
#define MP_BLUETOOTH_PASSKEY_ACTION_DISPLAY (3)
#define MP_BLUETOOTH_PASSKEY_ACTION_NUMERIC_COMPARISON (4)
+// These match NimBLE BLE_SM_IOACT_.
+#define MP_BLUETOOTH_PASSKEY_ACTION_NONE (0)
+#define MP_BLUETOOTH_PASSKEY_ACTION_INPUT (2)
+#define MP_BLUETOOTH_PASSKEY_ACTION_DISPLAY (3)
+#define MP_BLUETOOTH_PASSKEY_ACTION_NUMERIC_COMPARISON (4)
+
/*
These aren't included in the module for space reasons, but can be used
in your Python code if necessary.
@@ -202,6 +209,7 @@ _IRQ_CONNECTION_UPDATE = const(27)
_IRQ_ENCRYPTION_UPDATE = const(28)
_IRQ_GET_SECRET = const(29)
_IRQ_SET_SECRET = const(30)
+_IRQ_PASSKEY_ACTION = const(31)
_FLAG_BROADCAST = const(0x0001)
_FLAG_READ = const(0x0002)
@@ -231,6 +239,11 @@ _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)
+
+_PASSKEY_ACTION_NONE = const(0)
+_PASSKEY_ACTION_INPUT = const(2)
+_PASSKEY_ACTION_DISPLAY = const(3)
+_PASSKEY_ACTION_NUMERIC_COMPARISON = const(4)
*/
// bluetooth.UUID type.
@@ -332,6 +345,9 @@ int mp_bluetooth_set_preferred_mtu(uint16_t mtu);
#if MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING
// Initiate pairing on the specified connection.
int mp_bluetooth_gap_pair(uint16_t conn_handle);
+
+// Respond to a pairing request.
+int mp_bluetooth_gap_passkey(uint16_t conn_handle, uint8_t action, mp_int_t passkey);
#endif // MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING
#if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
@@ -387,8 +403,12 @@ void mp_bluetooth_gatts_on_encryption_update(uint16_t conn_handle, bool encrypte
// Call this when you need the application to manage persistent key data.
// For get, if key is NULL, then the implementation must return the index'th matching key. Otherwise it should return a specific key.
// For set, if value is NULL, then delete.
+// The "type" is stack-specific, but could also be used to implement versioning.
bool mp_bluetooth_gap_on_get_secret(uint8_t type, uint8_t index, const uint8_t *key, size_t key_len, const uint8_t **value, size_t *value_len);
bool mp_bluetooth_gap_on_set_secret(uint8_t type, const uint8_t *key, size_t key_len, const uint8_t *value, size_t value_len);
+
+// Call this when a passkey verification needs to be processed.
+void mp_bluetooth_gap_on_passkey_action(uint16_t conn_handle, uint8_t action, mp_int_t passkey);
#endif // MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING
// Call this when a characteristic is written to.
diff --git a/extmod/nimble/modbluetooth_nimble.c b/extmod/nimble/modbluetooth_nimble.c
index 2b273c6bc..ae727086e 100644
--- a/extmod/nimble/modbluetooth_nimble.c
+++ b/extmod/nimble/modbluetooth_nimble.c
@@ -347,6 +347,16 @@ STATIC int gap_event_cb(struct ble_gap_event *event, void *arg) {
return BLE_GAP_REPEAT_PAIRING_RETRY;
}
+ case BLE_GAP_EVENT_PASSKEY_ACTION: {
+ DEBUG_printf("gap_event_cb: passkey action: conn_handle=%d action=%d num=" UINT_FMT "\n", event->passkey.conn_handle, event->passkey.params.action, (mp_uint_t)event->passkey.params.numcmp);
+
+ #if MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING
+ mp_bluetooth_gap_on_passkey_action(event->passkey.conn_handle, event->passkey.params.action, event->passkey.params.numcmp);
+ #endif
+
+ return 0;
+ }
+
default:
DEBUG_printf("gap_event_cb: unknown type %d\n", event->type);
break;
@@ -886,6 +896,33 @@ int mp_bluetooth_gap_pair(uint16_t conn_handle) {
DEBUG_printf("mp_bluetooth_gap_pair: conn_handle=%d\n", conn_handle);
return ble_hs_err_to_errno(ble_gap_security_initiate(conn_handle));
}
+
+int mp_bluetooth_gap_passkey(uint16_t conn_handle, uint8_t action, mp_int_t passkey) {
+ struct ble_sm_io io = {0};
+
+ switch (action) {
+ case MP_BLUETOOTH_PASSKEY_ACTION_INPUT: {
+ io.passkey = passkey;
+ break;
+ }
+ case MP_BLUETOOTH_PASSKEY_ACTION_DISPLAY: {
+ io.passkey = passkey;
+ break;
+ }
+ case MP_BLUETOOTH_PASSKEY_ACTION_NUMERIC_COMPARISON: {
+ io.numcmp_accept = passkey != 0;
+ break;
+ }
+ default: {
+ return MP_EINVAL;
+ }
+ }
+
+ io.action = action;
+
+ DEBUG_printf("mp_bluetooth_gap_passkey: injecting IO: conn_handle=%d, action=%d, passkey=" UINT_FMT ", numcmp_accept=%d\n", conn_handle, io.action, (mp_uint_t)io.passkey, io.numcmp_accept);
+ return ble_hs_err_to_errno(ble_sm_inject_io(conn_handle, &io));
+}
#endif // MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING
#if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE