After bonding, I receive write events from the central, but after reconnecting, the write events no longer come through.

Nice to meet you.

I'm looking to embark on BLE development using nrf52840.
The requirements include one-to-one communication with one central and one peripheral, and pairing using LE Secure Connection is necessary (just works).
I will be developing the peripheral side of this. The BLE requirements are based on the specifications of the central side.

Now, initially, I tried implementing it myself based on various online information and samples.
I have successfully paired, and I can receive write events from the central side.
However, when I turn off the power on the central side, then turn it back on and perform a reconnection, I no longer receive write events from the central side.

Specifically, I am manipulating the central device to perform a write operation on the peripheral.
However, I only receive BLE_GAP_EVT_CONN_PARAM_UPDATE, and no other events.

First, let me share the logs!
If there's anything suspicious, please let me know. I can also provide the code.
Thank you.

SEGGER J-Link V7.88j - Real time terminal output
SEGGER J-Link (unknown) V1.0, SN=1050228242
Process: JLinkGDBServerCLExe
<info> app_timer: RTC: initialized.
<info> app: ble_stack__init
<info> app: Service UUID:0000, UUID Type: 2
<info> app: Erase bonds.
<info> peer_manager_handler: All peers deleted.
<info> app: PM_EVT_PEERS_DELETE_SUCCEEDED
<info> app_timer: RTC: initialized.
<info> app: ble_stack__init
<info> app: Service UUID:0000, UUID Type: 2
<info> app: Erase bonds.
<info> peer_manager_handler: All peers deleted.
<info> app: PM_EVT_PEERS_DELETE_SUCCEEDED
<info> app: PM_EVT_CONN_CONFIG_REQ
<info> app: BLE_GAP_EVT_CONNECTED
<info> app: PM_EVT_CONN_SEC_START
<info> app: PM_EVT_CONN_SEC_PARAMS_REQ
<info> app: BLE_GAP_EVT_SEC_PARAMS_REQUEST
<info> app: BLE_GAP_EVT_LESC_DHKEY_REQUEST
<info> nrf_ble_lesc: Calling sd_ble_gap_lesc_dhkey_reply on conn_handle: 0
<info> app: BLE_GAP_EVT_CONN_SEC_UPDATE
<info> app: Security mode: 1. Security level: 2
<info> peer_manager_handler: Connection secured: role: Peripheral, conn_handle: 0, procedure: Bonding
<warning> app: PM_EVT_CONN_SEC_SUCCEEDED
<info> app: BLE_GAP_EVT_AUTH_STATUS: status=0x0, bond=0x1, kdist_own:0x3 kdist_peer:0x2
<info> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Bonding data, action: Update
<info> app: PM_EVT_PEER_DATA_UPDATE_SUCCEEDED
<info> app: Writing or overwriting the data.
<info> app: Flash changed.
<info> app: New Bond, add the peer to the whitelist if possible
<info> app: whitelist_peer_cnt 1, MAX_PEERS_WLIST 8
<info> app: Bonded to a new peer, add it to the whitelist.
<info> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Peer rank, action: Update
<info> app: PM_EVT_PEER_DATA_UPDATE_SUCCEEDED
<info> app: Writing or overwriting the data.
<info> app: Flash changed.
<info> app: PM_PEER_DATA_ID_PEER_RANK
<info> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Local database, action: Update
<info> app: PM_EVT_PEER_DATA_UPDATE_SUCCEEDED
<info> app: Flash changed.
<info> app: PM_PEER_DATA_ID_GATT_LOCAL
<warning> app: ble_evt_handler:53
<info> app: BLE_GATTS_EVT_WRITE
<info> app: Notification enabled
<info> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Central address resolution, action: Update
<info> app: PM_EVT_PEER_DATA_UPDATE_SUCCEEDED
<info> app: Writing or overwriting the data.
<info> app: Flash changed.
<info> app: PM_PEER_DATA_ID_CENTRAL_ADDR_RES
<info> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Local database, action: Update
<info> app: PM_EVT_PEER_DATA_UPDATE_SUCCEEDED
<info> app: Writing or overwriting the data.
<info> app: Flash changed.
<info> app: PM_PEER_DATA_ID_GATT_LOCAL
<info> app: BLE_GATTS_EVT_WRITE
<info> app: command_char_handles
<info> app:  01 00 02 00 1E 00 1A 00|........
<info> app:  01 61 C6 00 54 53 11 00|.a..TS..
<info> app:  A5 16 FF 00            |....    
<info> app: BLE_GATTS_EVT_WRITE
<info> app: command_char_handles
<info> app:  01 01 FF FF 00 00 A7 0B|........
<info> app:  AF 16 00 01 00 00 00 52|.......R
<info> app:  7C 07                  ||.      
<info> app: BLE_GATTS_EVT_WRITE
<info> app: command_char_handles
<info> app:  01 00 02 00 1E 00 1A 00|........
<info> app:  01 61 C6 00 54 53 11 00|.a..TS..
<info> app:  A5 16 FF 00            |....    
<info> app: BLE_GATTS_EVT_WRITE
<info> app: command_char_handles
<info> app:  01 01 FF FF 00 00 A7 0B|........
<info> app:  AF 16 00 01 00 00 00 52|.......R
<info> app:  7C 07                  ||.      
<info> app: BLE_GATTS_EVT_WRITE
<info> app: command_char_handles
<info> app:  01 00 02 00 1E 00 1A 00|........
<info> app:  01 61 C6 00 54 53 11 00|.a..TS..
<info> app:  A5 16 FF 00            |....    
<info> app: BLE_GATTS_EVT_WRITE
<info> app: command_char_handles
<info> app:  01 01 FF FF 00 00 A7 0B|........
<info> app:  AF 16 00 01 00 00 00 52|.......R
<info> app:  7C 07                  ||.      
<info> app: BLE_GATTS_EVT_WRITE
<info> app: command_char_handles
<info> app:  01 00 02 00 1E 00 1A 00|........
<info> app:  01 61 C6 00 54 53 11 00|.a..TS..
<info> app:  A5 16 FF 00            |....    
<info> app: BLE_GATTS_EVT_WRITE
<info> app: command_char_handles
<info> app:  01 01 FF FF 00 00 A7 0B|........
<info> app:  AF 16 00 01 00 00 00 52|.......R
<info> app:  7C 07                  ||.     

======
Here, intentionally turning the power of the central device OFF/ON to trigger a reconnection.
======

<info> app: Disconnected, reason 8.
<info> app: PM_EVT_CONN_CONFIG_REQ
<info> app: PM_EVT_CONN_SEC_PARAMS_REQ
<info> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Peer rank, action: Update, no change
<info> app: PM_EVT_PEER_DATA_UPDATE_SUCCEEDED
<info> app: Writing or overwriting the data.
<info> app: Flash not changed.
<info> app: PM_PEER_DATA_ID_PEER_RANK
<warning> app: PM_EVT_BONDED_PEER_CONNECTED
<info> app: PM_EVT_LOCAL_DB_CACHE_APPLIED
<info> app: BLE_GAP_EVT_CONNECTED
<info> app: PM_EVT_CONN_SEC_START
<info> app: BLE_GAP_EVT_SEC_INFO_REQUEST
<info> peer_manager_handler: Connection secured: role: Peripheral, conn_handle: 0, procedure: Encryption
<info> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Peer rank, action: Update, no change
<info> app: PM_EVT_PEER_DATA_UPDATE_SUCCEEDED
<info> app: Writing or overwriting the data.
<info> app: Flash not changed.
<info> app: PM_PEER_DATA_ID_PEER_RANK
<warning> app: PM_EVT_CONN_SEC_SUCCEEDED
<info> app: BLE_GAP_EVT_CONN_SEC_UPDATE
<info> app: BLE_GAP_EVT_CONN_PARAM_UPDATE
<info> app: connection parameters updated. min_interval:160, max_interval:160, latency:0, timeout:810
<info> app: BLE_GAP_EVT_CONN_PARAM_UPDATE
<info> app: connection parameters updated. min_interval:80, max_interval:80, latency:0, timeout:810
<info> app: BLE_GAP_EVT_CONN_PARAM_UPDATE
<info> app: connection parameters updated. min_interval:160, max_interval:160, latency:0, timeout:810
<info> app: BLE_GAP_EVT_CONN_PARAM_UPDATE
<info> app: connection parameters updated. min_interval:80, max_interval:80, latency:0, timeout:810
<info> app: BLE_GAP_EVT_CONN_PARAM_UPDATE
<info> app: connection parameters updated. min_interval:160, max_interval:160, latency:0, timeout:810

  • Hello, Mr. Hung Bui.

    After setting the key, I clicked the arrow button to confirm the changes in the display. Following that, I captured a new connection, but it is currently in a state where the output reads "Encrypted packet decrypted incorrectly (bad MIC)." It seems that the sniffer is unable to decrypt the connection for some reason. I will also try using ble_app_hrs.

    Additionally, I am considering implementing the central side and trying to debug by checking the peripheral side as well. (Debugging from the central perspective is challenging as it involves a product from a different company.)

  • I'm not so sure why it doesn't work in your case. Have you tried again with a phone and a SDK example ? 
    You can also try to turn off Secure Connection so that it will do Legacy pairing, then it's much easier to sniff the communication without the need for LTK. If the central accept legacy pairing I think it's what you should do to debug. 

  • Good evening, Mr. Hung Bui,

    I tried using ble_app_hrs and checked with both the nrf52840 and a mobile phone. However, when I entered the Long Term Key (LTK) that appears during reconnection into the sniffer, I encountered the message "Encrypted packet decrypted incorrectly (bad MIC)."

    Furthermore, it seems that the central device I am trying to connect to does not support legacy pairing.

  • This is so strange. I tried again with another bonding and new LTK key and it worked just fine. 
    Could you check if you are having latest sniffer version. Which wireshark version do you have ? 

    If you have a screen recording that you record the whole test it would be nice. 
    Please send us the sniffer trace as well. 

  • Dear Mr. Hung Bui,

    It's been a while. Regarding the LTK in the Sniffer, when I converted the alphabet to lowercase, Wireshark started decrypting it!

    Furthermore, there was an issue during reconnection where the Central stopped sending Write requests. Upon sending the Sniffer data to the company developing the Central, it was pointed out that the problem lies in the fact that the Peripheral is issuing a Security Request during reconnection. Since the PM_HANDLER_SEC_DELAY_MS was set to 0, changing it to 4000 resolved the issue. However, after the delay, the delayed_conn_secure function is called, but after 4000ms, the encrypted communication is already established, leading to the following code snippet not initiating the security procedure:

    static void _conn_secure(uint16_t conn_handle, bool force)
    {
        ret_code_t err_code;
    
        if (!force)
        {
            pm_conn_sec_status_t status;
            err_code = pm_conn_sec_status_get(conn_handle, &status);
            if (err_code != BLE_ERROR_INVALID_CONN_HANDLE)
            {
                APP_ERROR_CHECK(err_code);
            }
    
            // If the link is already secured, don't initiate security procedure.
            if (status.encrypted)
            {
                NRF_LOG_DEBUG("Already encrypted, skipping security.");
                return;
            }
        }
    
        err_code = pm_conn_secure(conn_handle, false);
        // ...
    }
    
    static void delayed_conn_secure(void * context)
    {
        conn_secure_context_t sec_context = {.p_void = context};
        _conn_secure(sec_context.values.conn_handle, sec_context.values.force);
    }
    
    static void conn_secure(uint16_t conn_handle, bool force)
    {
        ret_code_t err_code;
        static bool created = false;
        if (!created)
        {
            err_code = app_timer_create(&secure_delay_timer,
                                        APP_TIMER_MODE_SINGLE_SHOT,
                                        delayed_conn_secure);
            APP_ERROR_CHECK(err_code);
            created = true;
        }
    
        conn_secure_context_t sec_context = {0};
        sec_context.values.conn_handle    = conn_handle;
        sec_context.values.force          = force;
    
        err_code = app_timer_start(secure_delay_timer,
                                   APP_TIMER_TICKS(PM_HANDLER_SEC_DELAY_MS),
                                   sec_context.p_void);
        APP_ERROR_CHECK(err_code);
    }

    As a result, pm_conn_secure is not called, and security requests are not issued, resolving the problem. What does this imply? Does it mean that the initiation of encrypted communication must be done by the Central?

Related