Closed 16L-YT closed 3 years ago
@16L-YT thank you for raising this issue.Please take a look at the following comments:
How can we reproduce your issue?
NOTE: If there are fields which are not applicable then please just add 'n/a' or 'None'. This indicates to us that at least all the fields have been considered. Please update the issue header with the missing information, the issue will not be mirrored to our internal defect tracking system or investigated until this has been fully resolved.
Thank you for raising this detailed GitHub issue. I am now notifying our internal issue triagers. Internal Jira reference: https://jira.arm.com/browse/IOTOSM-3831
@ARMmbed/mbed-os-connectivity Please review
@0xc0170 I know that there is no any obligation to check the bug (if exists) during a constrained time. But is there any time frame for mbed-os-connectivity team to check the issue as It is blocking further development from our side.
UPDATE:
I can ask a more precise question: According to #7300
Unfortunately writing in the flash while BLE is on was out of the scope for the release; it is a complex process as when the flash is written.
According to my understanding, mbed-os can't handle storing the Bonding information to Flash without a filesystem already initialized. So a call to securityManager
like this will always produce a fail in Bonding.
error = _ble.securityManager().init(
/* enableBonding */ true,
/* requireMITM */ false,
/* iocaps */ SecurityManager::IO_CAPS_NONE,
/* passkey */ nullptr,
/* signing */ false,
/* dbFilepath */ nullptr
);
And according to this there is no way to ask Android to do pairing without bonding.
As a result and as Ambiq has no LOCALFILESYSTEM
feature, then actually bonding can't be done.
Is my understanding correct ? Any workaround if it is correct ?
Sorry, I looked at this on Friday but it appears something went wrong posting it :( Let me try again: I need the rest of your code to figure out what is happening. Maybe you can make a repo that contains your code and I can check it out. The current code could be disconnecting after 2 seconds (look at the _bonded variable). Example code is just for educational purposes it's not necessarily a good base for real code (we are working on something like that). As for bonding without a FS, it does work. The bonding information is kept in RAM. Works the same but obviously will be lost on reset.
I've used the the https://github.com/ARMmbed/mbed-os-example-ble/tree/development/BLE_SecurityAndPrivacy example without modification on an Ambiq target and am also unable to pair the device with an android phone. The pairing request always fails with error code " SEC_STATUS_CONFIRM_VALUE = 0x84, /*< Confirm value failed. /".
Again this is a progression blocking issue on a commercial development project.
I don't have an Ambiq board. What LL firwmare is on the BLE chip?
The reason I ask is because I remember I had to make a workaround for the wb55 firmware for a bug in the LL that was causing the same kind of issue you're describing.
The same one the latest mbed has:
/*! \brief Version number. */
#define LL_VER_NUM 1366
How to compare with cordio used with Ambiq sdk ? Because bonding seems working using the official sdk without mbed os .
The following is from wsf/include/ll_defs.h from AmbiqSuite-R2.5.1
* \brief Link layer constant definitions.
*
* $Date: 2017-03-10 20:10:06 -0600 (Fri, 10 Mar 2017) $
* $Revision: 11511 $
Also mbed is using Ambiq ble related source files from 2.4.2 version. An update to 2.5.1 version did not solved the issue (please check the following 2 commits).
https://github.com/16Lab-Inc/mbed-os/commit/02c92998e8fc46b7ea2ed3443ab6efc1fc79f14a https://github.com/16Lab-Inc/mbed-os/commit/aad39c01e7a38320b2579b07e51d27aacbe2731b
Here under "Known limitations" it says that security does not work due to pairing failure. Has pairing been confirmed to work on any targets yet? It seems like this issue is not Ambiq target specific.
It works on nrf52840 and DISCO_L475VG_IOT01A and the bluenrg 1 shield. The bluenrg 2 indeed had some pairing issues - hence the note.
@16L-YT Can you run your application with traces and share the traces with us. This document: https://os.mbed.com/docs/mbed-os/v6.9/apis/ble.html explain how to enable traces.
If the CONFIRM_VALUE is wrong that means that the local calculation of the value doesn't match the one done on the remote. This is most likely caused by disagreement on addresses - one of the values used in the calculation of the confirm value is the address of the device. This is the most likely point where a bug could exist so try to verify the values used for the confirm value calculation are correct.
With mbed_app.json like this:
{
"target_overrides": {
"*": {
"mbed-trace.enable": true,
"mbed-trace.max-level": "TRACE_LEVEL_DEBUG",
"cordio.trace-hci-packets": false,
"cordio.trace-cordio-wsf-traces": true,
"ble.trace-human-readable-enums": true,
"target.macros_add": ["MBED_MINIMAL_PRINTF"],
"target.console-uart-flow-control": null,
"ble.ble-gap-host-based-private-address-resolution": false,
"cordio.rpa-swap-workaround": true,
"cordio.trace-pal-echoes": 1,
"platform.stdio-baud-rate": 115200
}
}
}
I get the following trace: trace_pair.txt
NB! setting "cordio.trace-hci-packets": true, hard crashes the device.
Intresting things I see:
[INFO][BLGP]: Connection 1 successfully completed - role=PERIPHERAL, peer_address_type=RANDOM peer_address=d1:5f:31:53:7b:5a, connection_interval=40, connection_latency=0, supervision_timeout=500, local_resolvable_private_address=00:00:00:00:00:00, peer_resolvable_private_address=00:00:00:00:00:00
local address is 0
[INFO][BLSM]: SM init: bondable=false, mitm=false, iocaps=IO_CAPS_NONE, passkey=0x45DD8, signing=false, db_path=0x386B8
passkey is not 0 even though init is called like this:
error = _ble.securityManager().init(
/* enableBonding */ false,
/* requireMITM */ false,
/* iocaps */ SecurityManager::IO_CAPS_NONE,
/* passkey */ nullptr,
/* signing */ false,
/* dbFilepath */ db_path
);
[INFO][BLSM]: Set stack display passkey: 30:30:30:30:30:30
passkey is set even though a null pointer is passed to securityManager().init()
[ERR ][BLSM]: Host based private address resolution enabled but not supported by the controller
even though "ble.ble-gap-host-based-private-address-resolution": false,
is defined in mbed_app.json
[ERR ][BLSM]: Host based private address resolution enabled but not supported by the controller
that error message appears to be misleading, I think it should say: disabled
not enabled
. Since your controller doesn't support privacy you need to enable "ble.ble-gap-host-based-private-address-resolution" if you want to use privacy.
As for the SM init: bondable=false, mitm=false, iocaps=IO_CAPS_NONE, passkey=0x45DD8, signing=false, db_path=0x386B8
showing the passykey as not null, the line with the trace print has an error:
tr_info("SM init: bondable=%s, mitm=%s, iocaps=%s, passkey=%p, signing=%s, db_path=%p",
should be
tr_info("SM init: bondable=%s, mitm=%s, iocaps=%s, passkey=%s, signing=%s, db_path=%p",
so it prints the pointer instead of the string.
Thanks, I'll fix that along with the error message.
Even with this mistake the printed value should still be 0x00. Because a null pointer should be passed to it or is the nullptr passed to _ble.securityManager().init() transformed into a string before printing?
As far as I can tell the printing happens directly after the init call or am I missing something? :
ble_error_t SecurityManager::init(
bool bondable,
bool mitm,
SecurityIOCapabilities_t iocaps,
const uint8_t* passkey,
bool signing,
const char* db_path
)
{
tr_info("SM init: bondable=%s, mitm=%s, iocaps=%s, passkey=%p, signing=%s, db_path=%p",
to_string(bondable),
to_string(mitm),
to_string(iocaps),
passkey_str(passkey),
to_string(signing),
db_path
);
Also later the passkey is printed as 30:30:30:30:30:30
. Is this expected behaviour? Similarly as far as I can tell having the local_resolvable_private_address be 00:00:00:00:00:00 is not valid.
Finally a trace with "ble.ble-gap-host-based-private-address-resolution": true
[INFO][BLCO]: WSF Cordio tracing enabled
[INFO][BLE ]: Allocated 9000 bytes for Cordio
[INFO][BLE ]: BLE features enabled: EXTENDED_ADVERTISING GATT_CLIENT GATT_SERVER PERIODIC_ADVERTISING PHY_MANAGEMENT PRIVACY SECURE_CONNECTIONS SECURITY SIGNING WHITELIST
[INFO][BLE ]: BLE roles enabled: PERIPHERAL CENTRAL
[INFO][BLE ]: Initialising Cordio host stack
[DBG ][BLE ]: HCI handler id: 0
[DBG ][BLE ]: DM handler id: 1
[DBG ][BLE ]: L2C slave handler id: 2
[DBG ][BLE ]: ATT handler id: 3
[DBG ][BLE ]: SMP handler id: 4
[DBG ][BLE ]: stack handler id: 5
* Device is a peripheral *
[INFO][BLPR]: Initialize privacy PAL
[INFO][BLE ]: Initialising BLE instance
[INFO][BLHC]: CordioHCIDriver initializing
[DBG ][BLE ]: Cordio HCI reset started
[DBG ][BLE ]: Reset sequence command complete: HCI_OPCODE_RESET
[DBG ][BLE ]: Reset sequence command complete: HCI_OPCODE_SET_EVENT_MASK
[DBG ][BLE ]: Reset sequence command complete: HCI_OPCODE_LE_SET_EVENT_MASK
[DBG ][BLE ]: Reset sequence command complete: HCI_OPCODE_SET_EVENT_MASK_PAGE2
[DBG ][BLE ]: Reset sequence command complete: HCI_OPCODE_READ_BD_ADDR
[DBG ][BLE ]: Reset sequence command complete: HCI_OPCODE_LE_READ_BUF_SIZE
[DBG ][BLE ]: Reset sequence command complete: HCI_OPCODE_LE_READ_SUP_STATES
[DBG ][BLE ]: Reset sequence command complete: HCI_OPCODE_LE_READ_WHITE_LIST_SIZE
[DBG ][BLE ]: Reset sequence command complete: HCI_OPCODE_LE_READ_LOCAL_SUP_FEAT
[DBG ][BLE ]: Reset sequence command complete: HCI_OPCODE_LE_READ_MAX_DATA_LEN
[DBG ][BLE ]: Reset sequence command complete: HCI_OPCODE_LE_WRITE_DEF_DATA_LEN
[DBG ][BLE ]: Reset sequence command complete: HCI_OPCODE_LE_RAND
[DBG ][BLE ]: Reset sequence command complete: HCI_OPCODE_LE_RAND
[DBG ][BLE ]: Reset sequence command complete: HCI_OPCODE_LE_RAND
[DBG ][BLE ]: Reset sequence command complete: HCI_OPCODE_LE_RAND
[DBG ][BLHC]: Signal cordio HCI reset sequence done
[DBG ][BLE ]: stack_handler received DM_RESET_CMPL_IND
[INFO][BLE ]: Reset sequence complete. Controller supported features:
[INFO][BLE ]: ENCRYPTION
[INFO][BLE ]: DATA_LEN_EXT
[INFO][BLE ]: Initialising extended features
[INFO][BLGS]: Initialize GattServer
[INFO][BLGS]: Add Generic Access Service to the Gatt Server: handle=1
[INFO][BLGS]: Add Device Name characteristic: handle=3
[INFO][BLGS]: Add Appearance characteristic: handle=5
[INFO][BLGS]: Add Peripheral Preferred Connection characteristic: handle=7
[INFO][BLGS]: Add Generic Attribute Service to the Gatt Server: handle=8
[INFO][BLGS]: Add Service Changed characteristic: handle=10
[INFO][BLGP]: Get address - type=PUBLIC, address=00:00:00:00:00:00
Device address: 66:77:88:23:bb:ef
[INFO][BLSM]: SM init: bondable=false, mitm=false, iocaps=IO_CAPS_NONE, passkey=0x46BDC, signing=false, db_path=0x393E0
[INFO][BLSM]: Initialize PAL SM
[INFO][BLSM]: Initialize database. Path = /fs/bt_sec_db
[WARN][BLDB]: Security DB didn't exist, creating new one
[ERR ][BLDB]: Failed to create security DB
[INFO][BLDB]: Using memory security DB (capacity 5 entries) - no persistence across reset
[INFO][BLSM]: Set stack I/O capabilities: NO_INPUT_NO_OUTPUT
[INFO][BLSM]: Set stack display passkey: 30:30:30:30:30:30
[DBG ][BLSM]: Secure connection support: false
[INFO][BLSM]: Initialize resolving list
[INFO][BLSM]: Identity list retrieved: 0 entries to add to the resolving list
[INFO][BLSM]: Clear resolving list
[INFO][BLSM]: Init identity
[INFO][BLSM]: Stack generated random data: ab:00:59:51:eb:7a:5b:30
[INFO][BLSM]: Stack generated random data: 62:2f:0c:54:d6:20:6c:07
[INFO][BLSM]: Random data generated: ab:00:59:51:eb:7a:5b:30:62:2f:0c:54:d6:20:6c:07
[INFO][BLSM]: Set stack local IRK: ab:00:59:51:eb:7a:5b:30:62:2f:0c:54:d6:20:6c:07
[INFO][BLSM]: Set local irk: ab:00:59:51:eb:7a:5b:30:62:2f:0c:54:d6:20:6c:07
[INFO][BLPR]: PAL start generation of RPA from local irk: ab:00:59:51:eb:7a:5b:30:62:2f:0c:54:d6:20:6c:07
[INFO][BLSM]: Set stack local identity address: address = 00:00:00:00:00:00, public = false
[INFO][BLSM]: Set manual handling of pairing request: true
[INFO][BLSM]: Set role reversal hint: true
[INFO][BLGP]: Enable privacy -enable=true
[INFO][BLSM]: Start private address generation
[INFO][BLPR]: Non resolvable private address generated: 71:6e:72:77:39:0c
[INFO][BLGP]: Private address generated - connectable=false
[DBG ][BLE ]: stack_handler received DM_PRIV_GENERATE_ADDR_IND
[INFO][BLPR]: Privacy handling: DM_PRIV_GENERATE_ADDR_IND
[INFO][BLSM]: Resolvable private address generated: f8:9e:d9:98:51:4f
[INFO][BLGP]: Private address generated - connectable=true
[INFO][BLGP]: Set peripheral privacy configuration - use_non_resolvable_random_address=false, resolution_strategy=PERFORM_PAIRING_PROCEDURE
[INFO][BLGP]: Advertising set 0: set advertising data - payload=02:01:06:0d:09:53:65:63:75:72:69:74:79:44:65:6d:6f, minimiseFragmentation=true, scan_response=false
[INFO][BLGP]: Advertising set 0: set extended advertising parameters - _advType=CONNECTABLE_UNDIRECTED, _minInterval=640ms, _maxInterval=1280ms, _peerAddressType=PUBLIC, _ownAddressType=RANDOM, _policy=NO_FILTER, _primaryPhy=LE_1M, _secondaryPhy=LE_1M, _peerAddress=00:00:00:00:00:00, _txPower=127, _maxSkip=0, _channel37=true, _channel38=true, _channel39=true, _anonymous=false, _notifyOnScan=false, _legacyPDU=true, _includeHeaderTxPower=false
[INFO][BLDM]: Advertising set 0: set extended advertising parameters - event_properties:[ connectable scannable use_legacy_pdu ], primary_advertising_interval_min=1024, primary_advertising_interval_max=2048, primary_advertising_channel_map=[111], own_address_type=RANDOM, peer_address_type=PUBLIC, peer_address=00:00:00:00:00:00, advertising_filter_policy=NO_FILTER, advertising_power=127, primary_advertising_phy=LE_1M, secondary_advertising_max_skip=0, secondary_phy=LE_1M, advertising_sid=0, scan_request_notification=false
[INFO][BLDM]: Legacy PDU w/undirected advertising event
[INFO][BLDM]: Advertising set 0: update direct advertising parameters - advertising_type=0, peer_address=00:00:00:00:00:00, peer_address_type=PUBLIC
[INFO][BLDM]: Set advertising data - advertising_data_length=17, advertising_data=02:01:06:0d:09:53:65:63:75:72:69:74:79:44:65:6d:6f
[INFO][BLGP]: Advertising set 0: set advertising parameters - _advType=CONNECTABLE_UNDIRECTED, _minInterval=640ms, _maxInterval=1280ms, _peerAddressType=PUBLIC, _ownAddressType=RANDOM, _policy=NO_FILTER, _primaryPhy=LE_1M, _secondaryPhy=LE_1M, _peerAddress=00:00:00:00:00:00, _txPower=127, _maxSkip=0, _channel37=true, _channel38=true, _channel39=true, _anonymous=false, _notifyOnScan=false, _legacyPDU=true, _includeHeaderTxPower=false
[INFO][BLDM]: Set advertising parameters - advertising_interval_min=1024, advertising_interval_max=2048, advertising_type=CONNECTABLE_UNDIRECTED, own_address_type=RANDOM, peer_address_type=PUBLIC, peer_address=00:00:00:00:00:00, advertising_channel_map=[111], advertising_filter_policy_t=NO_FILTER
[INFO][BLDM]: Advertising set 0: update direct advertising parameters - advertising_type=0, peer_address=00:00:00:00:00:00, peer_address_type=PUBLIC
[INFO][BLGP]: Advertising set 0: start advertising - maxDuration=10000ms, maxEvents=0
[INFO][BLDM]: Set random address - address=f8:9e:d9:98:51:4f
[INFO][BLDM]: Advertising enable - enable=true
Advertising...
[DBG ][BLCO]: >>> Trace buffer overflowed; 1 message(s) lost <<<
[DBG ][BLCO]: dmAdvActConfig: state: 0
[DBG ][BLCO]: dmAdvActSetData: state: 0
[DBG ][BLCO]: dmAdvActConfig: state: 0
[DBG ][BLCO]: dmAdvActStart: state: 0
[DBG ][BLE ]: stack_handler received DM_UNHANDLED_CMD_CMPL_EVT_IND
[DBG ][BLE ]: stack_handler received DM_UNHANDLED_CMD_CMPL_EVT_IND
[DBG ][BLE ]: stack_handler received DM_UNHANDLED_CMD_CMPL_EVT_IND
[DBG ][BLCO]: HCI_LE_ADV_ENABLE_CMD_CMPL_CBACK_EVT: state: 3
[DBG ][BLCO]: dmDevPassEvtToDevPriv: event: 12, param: 33, advHandle: 0
[DBG ][BLE ]: stack_handler received DM_ADV_START_IND
[INFO][BLGP]: Legacy advertising started
[DBG ][BLCO]: dmConnIdByBdAddr not found
[DBG ][BLCO]: dmConnCcbAlloc 1
[DBG ][BLCO]: dmConnSmExecute event=28 state=0
[DBG ][BLCO]: dmAdvConnected: state: 1
[DBG ][BLCO]: dmDevPassEvtToDevPriv: event: 13, param: 34, advHandle: 0
[DBG ][BLE ]: Connection 1 - Initialise CCC table
[DBG ][BLCO]: AttsCccInitTable connId=1
[DBG ][BLCO]: smpDbGetRecord: connId: 1 type: 1
[DBG ][BLCO]: smpDbAddDevice
[DBG ][BLCO]: SmpDbGetFailureCount: connId: 1 count: 0
[DBG ][BLCO]: smpDbGetRecord: connId: 1 type: 1
[DBG ][BLCO]: smpDbAddDevice
[DBG ][BLCO]: SmpDbGetPairingDisabledTime: connId: 1 period: 0 attemptMult: 0
[DBG ][BLE ]: stack_handler received DM_CONN_OPEN_IND
[DBG ][BLGP]: GAP event of type CONNECTION_COMPLETE received
[INFO][BLGP]: Connection 1 successfully completed - role=PERIPHERAL, peer_address_type=RANDOM peer_address=51:a0:3a:a9:30:44, connection_interval=36, connection_latency=0, supervision_timeout=500, local_resolvable_private_address=00:00:00:00:00:00, peer_resolvable_private_address=00:00:00:00:00:00
[INFO][BLDM]: Advertising enable - enable=false
[DBG ][BLSM]: Address not found in cache: 51:a0:3a:a9:30:44
[INFO][BLSM]: Queue privacy request
[DBG ][BLSM]: Address resolution complete: rpa=51:a0:3a:a9:30:44, resolved=false
[INFO][BLGP]: Address resolution completed - peer_resolvable_address=51:a0:3a:a9:30:44, resolved=false, identity_address_type=PUBLIC, identity_address=00:00:00:00:00:00
[DBG ][BLDB]: Retrieve a disconnected entry to use as a new entry in DB.
[DBG ][BLDB]: Using a previously unused entry as a new entry in DB.
[INFO][BLSM]: Connection 1 - Open: ltk=false, csrk=false, irk=false
Connected to peer: 44:30:a9:3a:a0:51
[INFO][BLSM]: Connection 1 - Set link security: SECURITY_MODE_ENCRYPTION_NO_MITM
[INFO][BLSM]: Connection 1 - Set encryption: ENCRYPTED
[INFO][BLSM]: Connection 1 - Enable encryption
[INFO][BLSM]: Connection 1 - Ltk not available, send slave security request
[INFO][BLSM]: Connection 1 - Initiate security request
[INFO][BLSM]: Connection 1 - Pass slave security to the stack: authentication = 10
[INFO][BLSM]: Connection 1 - Request authentication
[INFO][BLSM]: Connection 1 - ltk not mitm protected, issue slave security request
[INFO][BLSM]: Connection 1 - Initiate security request
[INFO][BLSM]: Connection 1 - Pass slave security to the stack: authentication = 14
[DBG ][BLCO]: dmAdvActStop: state: 0
[DBG ][BLCO]: smpSmExecute event=5 state=0
[DBG ][BLCO]: hciCoreTxAclStart len=6
[DBG ][BLCO]: smpSmExecute event=5 state=1
[DBG ][BLE ]: stack_handler received DM_CONN_DATA_LEN_CHANGE_IND
[DBG ][BLCO]: smpSmExecute event=6 state=1
[DBG ][BLCO]: connId=1 idleMask=0x0001
[DBG ][BLE ]: stack_handler received DM_SEC_PAIR_IND
[INFO][BLSM]: Handling event DM_SEC_PAIR_IND
[INFO][BLSM]: Connection 1 - pairing request received: use_oob = false, authentication = 0D, initiator_dist = 0F, responder_dist = 0F
[INFO][BLSM]: Connection 1 - Forwarding pairing request to user handler
Pairing requested - authorising
[INFO][BLSM]: Connection 1 - Accept pairing request
[INFO][BLSM]: Connection 1 - Update OOB presence: false
[INFO][BLSM]: Connection 1 - Send pairing response: oob = false, auth = 14, initiator dist = 03, responder dist = 03
[DBG ][BLCO]: smpSmExecute event=2 state=2
[DBG ][BLCO]: smpSmExecute event=18 state=3
[DBG ][BLCO]: hciCoreTxAclStart len=11
[DBG ][BLCO]: smpSmExecute event=4 state=28
[DBG ][BLCO]: connId=1 idleMask=0x0005
[DBG ][BLCO]: hciCoreTxAclStart len=18
[DBG ][BLCO]: hciCoreTxAclStart len=9
[DBG ][BLCO]: hciCoreTxAclStart len=27
[DBG ][BLCO]: hciCoreTxAclStart len=9
[DBG ][BLCO]: dmConnSmExecute event=30 state=3
[DBG ][BLE ]: stack_handler received DM_CONN_UPDATE_IND
[DBG ][BLGP]: GAP event of type CONNECTION_UPDATE received
[INFO][BLGP]: Connection 1 update successfully completed - connection_interval=6, connection_latency=0,supervision_timeout=500,
[DBG ][BLCO]: hciCoreTxAclStart len=9
[DBG ][BLCO]: hciCoreTxAclStart len=13
[DBG ][BLCO]: hciCoreTxAclStart len=9
[DBG ][BLCO]: connId=1 idleMask=0x0005
[DBG ][BLCO]: hciCoreTxAclStart len=9
[DBG ][BLCO]: dmConnSmExecute event=30 state=3
[DBG ][BLE ]: stack_handler received DM_CONN_UPDATE_IND
[DBG ][BLGP]: GAP event of type CONNECTION_UPDATE received
[INFO][BLGP]: Connection 1 update successfully completed - connection_interval=36, connection_latency=0,supervision_timeout=500,
[DBG ][BLCO]: smpSmExecute event=6 state=29
[DBG ][BLCO]: smpSmExecute event=11 state=30
[DBG ][BLCO]: smpSmExecute event=11 state=31
[DBG ][BLCO]: hciCoreTxAclStart len=21
[DBG ][BLCO]: smpSmExecute event=6 state=32
[DBG ][BLCO]: smpSmExecute event=11 state=33
[DBG ][BLCO]: smpSmExecute event=11 state=34
[DBG ][BLCO]: smpDbGetRecord: connId: 1 type: 1
[DBG ][BLCO]: smpDbAddDevice
[DBG ][BLCO]: SmpDbPairingFailed: connId: 1
[DBG ][BLCO]: smpSmExecute event=13 state=35
[DBG ][BLCO]: hciCoreTxAclStart len=6
[DBG ][BLCO]: connId=1 idleMask=0x0004
[DBG ][BLE ]: stack_handler received DM_SEC_PAIR_FAIL_IND
[INFO][BLSM]: Handling event DM_SEC_PAIR_FAIL_IND
[INFO][BLSM]: Connection 1 - Pairing error true received
[INFO][BLSM]: Connection 1 - MITM performed: false
Pairing failed with error code: 84
[DBG ][BLCO]: smpDbGetRecord: connId: 1 type: 1
[DBG ][BLCO]: smpDbAddDevice
[DBG ][BLCO]: SmpDbMaxAttemptReached: connId: 1
[DBG ][BLCO]: smpSmExecute event=16 state=38
[INFO][BLGP]: Connection 1: disconnect - reason=USER_TERMINATION
[INFO][BLDM]: Connection 1: disconnect - disconnection_reason=USER_TERMINATION
[DBG ][BLCO]: dmConnSmExecute event=25 state=3
[DBG ][BLCO]: dmConnSmExecute event=29 state=4
[DBG ][BLCO]: dmConnCcbDealloc 1
[DBG ][BLE ]: Connection 1 - Clear CCC table
[DBG ][BLCO]: AttsCccClearTable connId=1
[DBG ][BLCO]: smpDbGetRecord: connId: 1 type: 1
[DBG ][BLCO]: SmpDbSetFailureCount: connId: 1 count: 0
[DBG ][BLCO]: smpSmExecute event=10 state=0
[DBG ][BLE ]: stack_handler received DM_CONN_CLOSE_IND
[DBG ][BLGP]: GAP event of type DISCONNECTION_COMPLETE received
[INFO][BLGP]: Disconnection 1 successfully completed - reason=19
[INFO][BLSM]: Connection 1 - Process disconnection
[INFO][BLSM]: Connection 1 - Remove stack peer CSRK
Failed to bond.
* Device is a central *
Yeah, it's converted to a string. Is this trace the trace of an unchanged example?
Basically unmodified.
mbed_trace_init();
mbed_trace_config_set(TRACE_ACTIVE_LEVEL_ALL);
has been added to main(); also
error = _ble.securityManager().init(
/* enableBonding */ false,
/* requireMITM */ false,
/* iocaps */ SecurityManager::IO_CAPS_NONE,
/* passkey */ nullptr,
/* signing */ false,
/* dbFilepath */ db_path
);
enableBonding has been set to false because we suspected the lack of file-system is to blame.
void pairingResult(
ble::connection_handle_t connectionHandle,
SecurityManager::SecurityCompletionStatus_t result
) override
{
if (result == SecurityManager::SEC_STATUS_SUCCESS) {
printf("Pairing successful\r\n");
_bonded = true;
} else {
printf("Pairing failed with error code: %x\r\n", result);
}
_event_queue.call_in(
delay,
[this, connectionHandle] {
_ble.gap().disconnect(connectionHandle, ble::local_disconnection_reason_t::USER_TERMINATION);
}
);
}
and pairing result callback has been modified to print error code.
Just to exclude problems with android could you please run the example on two of your ambiq boards?
Different colors are different Boards. Also no more specific traces since they all hard crash. Mostly with file accessed in ISR error.
OK, I need to get an artemis board. This board is not yet officially supported and obviously we never tested ble on it. I'll get back to you when I get the board but I cannot guarantee this will be fixed.
Doing some digging I found that in the HCITransportDriver setting a random address is supressed. Would this cause pairing not to work?
uint16_t AP3CordioHCITransportDriver::write(uint8_t packet_type, uint16_t len, uint8_t *data)
{
#if PRINT_DEBUG_HCI
printf("sent tx packet_type: %02X data: ", packet_type);
for (int i = 0; i < len; i++)
{
printf(" %02X", data[i]);
}
printf("\r\n");
#endif
//Temporary workaround, random address not working, suppress it.
if (data[0] == 0x06 && data[1] == 0x20)
{
#if PRINT_DEBUG_HCI
printf("LE Set Advertising Params\r\n");
#endif
data[8] = 0;
}
Yes, if addresses don't match between the devices the confirm value will be different and therefore pairing will fail.
I've removed the following part from AP3CordioHCITransportDriver::write
//Temporary workaround, random address not working, suppress it.
if (data[0] == 0x06 && data[1] == 0x20)
{
#if PRINT_DEBUG_HCI
printf("LE Set Advertising Params\r\n");
#endif
data[8] = 0;
}
and this breaks BLE.
Any ideas on why this happens? What does the command being suppressed specifically do? What would be the workaround if the controller doesn't support the command being suppressed? Could this command not working be a CORDIO stack issue?
Judging by the comment in the code setting random address breaks the controller so that line stops you from setting the address type to random when advertising. The code checks if the HCI command is "LE Set Advertising Parameters command" (page 2482 in the 5.2 ble spec), the 6th byte that it overwrites (data[8]) is the "Own_Address_Type" and 0 is the public address. In effect this means the board will always advertise with public address and you cannot use privacy as it will cause the confirm values to differ since each side thinks the address is different.
Is pairing/bonding possible without supporting a random address during advertising? I expect setting a random address manually could be possible workaround.
Also the example code provided by the vendor (cordio based) performs paring/bonding without issue. I was surprised to find that mbed-os's SecurityManager is not based on cordio's SMP. Are these incompatible or is there a way to use the entire cordio stack with mbed-os?
You can probably pair and bond but only with a public address - so you cannot enable privacy (which requires random addresses).
Is pairing/bonding possible without supporting a random address during advertising? I expect setting a random address manually could be possible workaround.
Yes it is possible to use public addresses to pair and bond however if you cannot set a random address in the controller then the privacy won't work. When privacy is enabled, your device advertise with a private resolvable address which is renewed every 15 minutes. Until Bluetooth 5, this private resolvable address was computed on the host and set in the controller using the set random address HCI command. With Bluetooth 5, link layer privacy has been introduced and the controller can generate an address when it advertise, scan or initiate connection. Not all BT5 controller supports this feature.
To solve your issue I suggest you remove privacy related bits and use a public address:
class DevAdvSecurity : private mbed::NonCopyable<DevAdvSecurity>,
public SecurityManager::EventHandler,
public ble::Gap::EventHandler
{
public:
DevAdvSecurity(BLE &ble, events::EventQueue &event_queue) :
_ble(ble), _event_queue(event_queue),_post_init_cb() { };
virtual ~DevAdvSecurity()
{
_ble.onEventsToProcess(nullptr);
};
/** Start BLE interface initialisation */
void run()
{
/* this will inform us off all events so we can schedule their handling
* using our event queue */
_ble.onEventsToProcess(makeFunctionPointer(this, &DevAdvSecurity::schedule_ble_events));
/* handle gap events */
_ble.gap().setEventHandler(this);
if (_ble.hasInitialized()) {
/* ble instance already initialised, skip init and start activity */
start();
} else {
ble_error_t error = _ble.init(this, &DevAdvSecurity::on_init_complete);
if (error) {
return;
}
}
if (_post_init_cb) {
_post_init_cb(_ble, _event_queue);
}
/* this will not return until shutdown */
_event_queue.dispatch_forever();
};
/** Override to start chosen activity when the system starts */
virtual void start() = 0;
/** This is called when BLE interface is initialised and starts the demonstration */
void on_init_complete(BLE::InitializationCompleteCallbackContext *event)
{
ble_error_t error;
if (event->error) {
return;
}
// SecurityManager::Passkey_t passkey = {0,0,0,0,0,0};
error = _ble.securityManager().init(
/* enableBonding */ true,
/* requireMITM */ false,
/* iocaps */ SecurityManager::IO_CAPS_NONE,
/* passkey */ nullptr,
/* signing */ false,
/* dbFilepath */ nullptr
);
if (error) {
return;
}
/* This tells the stack to generate a pairingRequest event which will require
* this application to respond before pairing can proceed. Setting it to false
* will automatically accept pairing. */
_ble.securityManager().setPairingRequestAuthorisation(true);
/* Tell the security manager to use methods in this class to inform us
* of any events. Class needs to implement SecurityManagerEventHandler. */
_ble.securityManager().setSecurityManagerEventHandler(this);
/* gap events also handled by this class */
_ble.gap().setEventHandler(this);
start();
};
/** Schedule processing of events from the BLE in the event queue. */
void schedule_ble_events(BLE::OnEventsToProcessCallbackContext *context)
{
_event_queue.call([&ble_instance = context->ble] { ble_instance.processEvents(); });
};
private:
/* SecurityManager Event handler */
/** Respond to a pairing request. This will be called by the stack
* when a pairing request arrives and expects the application to
* call acceptPairingRequest or cancelPairingRequest */
void pairingRequest(ble::connection_handle_t connectionHandle) override
{
_ble.securityManager().acceptPairingRequest(connectionHandle);
}
/** Inform the application of pairing */
void pairingResult(
ble::connection_handle_t connectionHandle,
SecurityManager::SecurityCompletionStatus_t result
) override
{
if (result == SecurityManager::SEC_STATUS_SUCCESS) {
_bonded = true;
}
// _event_queue.call_in(
// delay,
// [this, connectionHandle] {
// _ble.gap().disconnect(connectionHandle, ble::local_disconnection_reason_t::USER_TERMINATION);
// }
// );
}
void linkEncryptionResult(ble::connection_handle_t connectionHandle, ble::link_encryption_t result) override
{
// if (result == ble::link_encryption_t::ENCRYPTED) {
// printf("Link ENCRYPTED\r\n");
// } else if (result == ble::link_encryption_t::ENCRYPTED_WITH_MITM) {
// printf("Link ENCRYPTED_WITH_MITM\r\n");
// } else if (result == ble::link_encryption_t::NOT_ENCRYPTED) {
// printf("Link NOT_ENCRYPTED\r\n");
// }
}
/* Gap Event handler */
/** This is called by Gap to notify the application we connected */
void onConnectionComplete(const ble::ConnectionCompleteEvent &event) override
{
_handle = event.getConnectionHandle();
if (_bonded) {
/* disconnect in 2s */
_event_queue.call_in(
delay,
[this] {
_ble.gap().disconnect(_handle, ble::local_disconnection_reason_t::USER_TERMINATION);
}
);
} else {
/* start bonding */
ble_error_t error = _ble.securityManager().setLinkSecurity(
_handle,
SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM
);
if (error) {
_ble.gap().disconnect(_handle, ble::local_disconnection_reason_t::USER_TERMINATION);
}
}
};
/** This is called by Gap to notify the application we disconnected */
void onDisconnectionComplete(const ble::DisconnectionCompleteEvent &event) override
{
if (_bonded) {
/* we have connected to and bonded with the other device, from now
* on we will use the second start function and stay in the same role
* as peripheral or central */
_event_queue.call_in(delay, [this] { start(); });
}
else {
_event_queue.break_dispatch();
}
};
void onAdvertisingEnd(const ble::AdvertisingEndEvent &event) override
{
if (!event.isConnected()) {
_event_queue.break_dispatch();
}
}
/**
* Subscription to the ble interface initialization event.
*/
void on_init(mbed::Callback<void(BLE&, events::EventQueue&)> cb)
{
_post_init_cb = cb;
}
protected:
BLE &_ble;
events::EventQueue &_event_queue;
ble::connection_handle_t _handle = 0;
bool _bonded = false;
mbed::Callback<void(BLE&, events::EventQueue&)> _post_init_cb;
};
class DevPeripheral :public DevAdvSecurity
{
public:
DevPeripheral(BLE &ble, events::EventQueue &event_queue)
: DevAdvSecurity(ble, event_queue)
{ }
void start() override
{
start_advertising();
}
void register_oninit_cb(mbed::Callback<void(BLE&, events::EventQueue&)> cb)
{
_post_init_cb = cb;
}
void set_dev_name(std::string name)
{
strncpy(adv_name, name.c_str(), sizeof(adv_name));
}
private:
void start_advertising()
{
uint8_t adv_buffer[ble::LEGACY_ADVERTISING_MAX_SIZE];
/* use the helper to build the payload */
ble::AdvertisingDataBuilder adv_data_builder(adv_buffer);
adv_data_builder.setFlags();
adv_data_builder.setName((const char*)adv_name);
/* Set payload for the set */
ble_error_t error = _ble.gap().setAdvertisingPayload(
ble::LEGACY_ADVERTISING_HANDLE,
adv_data_builder.getAdvertisingData()
);
if (error) {
return;
}
ble::AdvertisingParameters adv_parameters(
ble::advertising_type_t::CONNECTABLE_UNDIRECTED,
ble::adv_interval_t(ble::millisecond_t(1000)),
ble::adv_interval_t(ble::millisecond_t(2000))
);
adv_parameters.setOwnAddressType(ble::own_address_type_t::PUBLIC);
// adv_params.setTxPower(-127);
error = _ble.gap().setAdvertisingParameters(ble::LEGACY_ADVERTISING_HANDLE, adv_parameters);
if (error) {
return;
}
error = _ble.gap().startAdvertising(ble::LEGACY_ADVERTISING_HANDLE);
if (error) {
return;
}
}
protected:
char adv_name[32];
};
Thank you this worked. I'm now able to pair with an Android device but for some reason pairing confirmation on Android side always has to be preformed twice. The vendor provided cordio based examples succeed on the first attempt. It seems like the paring is initiated twice for some reason.
Follow up in https://github.com/ARMmbed/mbed-os/issues/14654
Description of defect
When I try to add simple bonding feature to my BLE device by adapting most parts of SecurityAndPrivacy example , and after getting rid of
SecurityCentral
class, as my case includes only a peripheral (my ble device) and an Android phone trying to bond with it. When I try to connect to the device using NRF connect, I have a popup from Android to pair with device 2 times in sequence. After all, the bonding fail and Android shows me that bonding is failed due to incorrect PIN or passphrase although I don't use it in my application. I tried 2 different Android phones to make sure it is not an issue related to my phone. I also tried to add passphrase and I got the same result. I have a fealing that this is due to a miss-leading documentation of SecurityManager calss or to a bug in Mbed somewhere. Note: My device has no interface with user.This is the log from NRF Connect while doing a connection:
Here is the code I run:
from main.cpp:
Target(s) affected by this defect ?
AMA3B1KK-KBR-B0
Toolchain(s) (name and version) displaying this defect ?
gcc version 10.2.1 20201103 (release) (xPack GNU Arm Embedded GCC, 64-bit)
What version of Mbed-os are you using (tag or sha) ?
mbed-os-6.9.0
What version(s) of tools are you using. List all that apply (E.g. mbed-cli)
Tools that comes with Mbed Studio 1.4.0
How is this defect reproduced ?
By running the attached code.