Hello!
I'm trying to read data off of a commercial blood pressure monitor (Qardio arm) using an nrf51822 with the nrf51 SDK v10.0.0 as the central role (s120). I am able to connect using sd_ble_gap_connect(), and when I tried to write to a characteristic using sd_ble_gattc_write(), I get back an "Authenticated Link Required" error. I assume that this implies I need security on my connection.
So next I attempted to use sd_ble_gap_authenticate(), which resulted in "Pairing Not Supported". It should be noted that I am able to write to the blood pressure monitor using nordic's "nRF Connect for Mobile" android app (I have a google pixel running Android 7.1.2).
Following these attempts, I turned to the device manager. Below shows the parameters I've set up for the DM, which are the same parameters I tried using with sd_ble_gap_authenticate().
static void device_manager_init(bool erase_bonds) {
uint32_t err_code;
dm_init_param_t init_param = {.clear_persistent_data = erase_bonds};
dm_application_param_t register_param;
err_code = pstorage_init(); //must be called before initializing any modules
APP_ERROR_CHECK(err_code);
err_code = dm_init(&init_param); //must be called before using any dm API
APP_ERROR_CHECK(err_code);
memset(®ister_param.sec_param, 0, sizeof (ble_gap_sec_params_t)); //ZERO out the register_param.secparam
// Event handler to be registered with the module.
register_param.evt_handler = device_manager_event_handler;
// Service or protocol context for device manager to load, store and apply on behalf of application.
// Here set to client as application is a GATT client.
register_param.service_type = DM_PROTOCOL_CNTXT_GATT_CLI_ID;
// Secuirty parameters to be used for security procedures.
register_param.sec_param.bond = SEC_PARAM_BOND; // bond = 1
register_param.sec_param.mitm = SEC_PARAM_MITM; // mitm = 1
register_param.sec_param.io_caps = SEC_PARAM_IO_CAPABILITIES; // io cap = 3 (none)
register_param.sec_param.oob = SEC_PARAM_OOB; // oob = 0
register_param.sec_param.min_key_size = SEC_PARAM_MIN_KEY_SIZE; // min key = 7
register_param.sec_param.max_key_size = SEC_PARAM_MAX_KEY_SIZE; // max key = 16
//register_param.sec_param.kdist_central.enc = 0;
//register_param.sec_param.kdist_central.id = 1;
//register_param.sec_param.kdist_central.sign = 0;
register_param.sec_param.kdist_periph.enc = 1;
register_param.sec_param.kdist_periph.id = 1;
//register_param.sec_param.kdist_periph.sign = 0;
dm_register(&m_dm_app_id, ®ister_param); //app_id is a global variable
}
Now upon DM_EVT_CONNECTION, I would attempt dm_security_setup_req(), which then triggered DM_EVT_SECURITY_SETUP_COMPLETE. I had to use setup_req() again right after this (not sure why...), which then triggered DM_EVT_LINK_SECURED. It was here that I check my security level using dm_security_status_req(), which showed me that I'm still sm:1 lv:1.
I've also tried using the sd_ble_gap_encrypt() function, which triggers BLE_GAP_EVT_CONN_SEC_UPDATE. In here, I've also found myself to still be at sm:1 lv:1.
If "pairing isn't supported", how do I create an "authenticated link" so that I may write to the bp monitor's characteristic? What is the relation of authenticate() and encrypt()? Can I use one without the other?
Also, I am still new when it comes to BLE encryption. When using the sd_ble_gap_encrypt() function, specifically regarding the "ble_gap_master_id_t" and "ble_gap_enc_info_t" structs that the function takes as inputs, how do we populate those input parameters? Where does the LTK come from?
Also for reference, after i run sd_ble_gap_authenticate(), the following data is extracted from the BLE_GAP_EVT_AUTH_STATUS:
auth_status = 0x85 //this is the Authenticated Link Required error
error_src = 1
bonded = 1
sm1_levels.... lv1 = 1, lv2 = 1, lv3 = 1
sm2_levels.... lv1 = 1, lv2 = 1, lv3 = 1
kdist_periph.... enc = 1, id = 1, sign = 1
kdist_central... enc = 0, id = 1, sign = 1
I thank you in advance for your time in helping me with this matter.
Best, Tien Tran