Connection using old pairing information saved

I am running an experiment to use a static keys for pairing information without breaking the existing flow of pairing/bonding.
What I am doing is I am storing the pairing info of my central device and storing it into a structure and then erasing the flash to remove those information, and after reset I am retrieving those bonding information and connecting again using the same central devices but I am getting "Peer removed bonding info" response on my phone.

void store_ltk_in_zephyr(void)
{
    int id, err;
    struct bt_keys pairing_info = {
    .addr = {
        .type = BT_ADDR_LE_PUBLIC,
        .a.val = {0x43,0x82,0x5E,0xC7,0xE8,0xF4,0xFD}
    },
    .irk = {0x8A, 0x27, 0x1E, 0xA7, 0x92, 0x2A, 0xF0, 0x15, 0x41, 0x69, 0x48, 0xDD, 0xC0, 0x7E, 0xDD, 0xF7},
    .ltk = {
        .val = {0xc0, 0xe6, 0x9a, 0x0a, 0xf7, 0x4b, 0xdc, 0xb7, 0x7d, 0x23, 0xf4, 0xb4, 0x89, 0x8d, 0x96, 0x02},
        .ediv = {0x00,0x00},
        .rand = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
      }
    };

    // Store the keys using the settings API
    err = bt_keys_store(&pairing_info);
    if (err) {
        printk("Failed to store keys (err %d)\n", err);
    } else {
        printk("Keys stored successfully\n");
    }
}


In main, I am calling like this to load the info onto the flash- 

  settings_subsys_init();
  //smp_bt_register();
	bt_conn_auth_cb_register(&auth_cb_display);
  bt_conn_auth_info_cb_register(&conn_auth_info_callbacks);
	err = bt_enable(NULL);
	if (err) {
		printk("Bluetooth init failed (err %d)\n", err);
    k_sleep(K_MSEC(100));
		err = bt_enable(NULL);                                      //Trying one more time after this system reset
    if(err) NVIC_SystemReset();
	}
  store_ltk_in_zephyr();
  if (IS_ENABLED(CONFIG_SETTINGS)) {
    settings_load();
  }


And on connect I am using like this-
  bt_conn_set_security(conn, BT_SECURITY_L1|BT_SECURITY_FORCE_PAIR);


Do let me know, how can I connect with the same bonding info which I have made a copy of from the same bonding structure.

Parents Reply Children
  • Here is an updated version of the pre_shared_bond_set() function which should handle legacy pairing:

    static void pre_shared_bond_set(void)
    {
    	int err;
    	int bond_num = 0;
    	struct bt_keys *pairing_info;
    
    	// true if pm_peer_data_bonding.own_ltk.enc_info.ltk.lesc == 0
    	bool legacy_pairing = true;
    
    	bt_foreach_bond(BT_ID_DEFAULT, bond_cb, &bond_num);
    
    	if (bond_num) {
    		return;
    	}
    
    	//pm_peer_data_bonding.peer_ble_id.id_addr_info
    	bt_addr_le_t addr = {
    	    .type = BT_ADDR_LE_PUBLIC,
    	    .a.val = {0x23, ....}
    	};
    
    	//pm_peer_data_bonding.own_ltk.enc_info.ltk
    	struct bt_ltk ltk = {
    	    .val = {0x0e, 0x31, 0xed, 0xa8, 0x6a, 0xdd, 0x9f, 0xba, 0xd5, 0xcc, 0xb7,
    	            0x78, 0x4b, 0xb7, 0xaf, 0xee},
    	    .ediv = {0x02,0x56}, // remember to check the byte order
    	    .rand = {0xcc, 0x57, 0x52, 0xee, 0x4c, 0x5a, 0xa6, 0xc6}		
    	};
    	
    	//pm_peer_data_bonding.peer_ble_id.id_info
    	struct bt_irk irk = {
    		.val = {0xd6, ....},
    		.rpa.val = {0}		
    	}; 
    
    	pairing_info = bt_keys_get_addr(0, &addr);
    	if (pairing_info == NULL) {
    		LOG_ERR("Failed to get keyslot");
    		return;
    	}
    
    	if (legacy_pairing) {
    		memcpy(&pairing_info->periph_ltk, &ltk, sizeof(pairing_info->periph_ltk));
    	} 
    	else {
    		memcpy(&pairing_info->ltk, &ltk, sizeof(pairing_info->ltk));
    	}
    	
    	memcpy(&pairing_info->irk, &irk, sizeof(pairing_info->irk));
    
    	if (legacy_pairing) {
    		pairing_info->flags = 0;
    		pairing_info->enc_size = BT_SMP_MAX_ENC_KEY_SIZE;
    		pairing_info->keys = BT_KEYS_IRK | BT_KEYS_PERIPH_LTK;
    	}
    	else {
    		pairing_info->flags = BT_KEYS_SC;
    		pairing_info->enc_size = BT_SMP_MAX_ENC_KEY_SIZE;
    		pairing_info->keys = BT_KEYS_IRK | BT_KEYS_LTK_P256;
    	}
    
    
    	err = bt_keys_store(pairing_info);
        if (err) {
            LOG_ERR("Failed to store keys (err %d)\n", err);
        } else {
            LOG_INF("Keys stored successfully\n");
        }
    
    }

    I have also noted down which elements in the pm_peer_data_bonding_t struct you should use to populate keys struct with.

  •  These changes I already had in my code, been testing and sending you logs from that only-

    static void pre_shared_bond_set(void)
    {
    	int err;
    	int bond_num = 0;
    	struct bt_keys *pairing_info;
    
    	bt_foreach_bond(BT_ID_DEFAULT, bond_cb, &bond_num);
    
    	if (bond_num) {
    		return;
    	}
    
    	bt_addr_le_t addr = {
    	    .type = BT_ADDR_LE_PUBLIC,
    	    .a.val = {0x43,0x82,0x5E,0xC7,0xE8,0xF4}
    	};
    
    	struct bt_ltk ltk = {
    	    .val = {0x31, 0x30, 0xca, 0x16, 0x8d, 0x53, 0x73, 0x7c, 0x89, 0xee, 0x42, 0x58, 0x61, 0x47, 0x03, 0xb4},//{0xcb, 0xea, 0xd5, 0xea, 0xe1, 0xab, 0x7c, 0x36, 0x91, 0x1b, 0xe7, 0xd3, 0x31, 0xd1, 0xf8, 0xbc},
    	    .ediv = {0},
    	    .rand = {0}		
    	};
    
    	struct bt_irk irk = {
    		.val = {0xF7, 0xDD, 0x7E, 0xC0, 0xDD, 0x48, 0x69, 0x41, 0x15, 0xF0, 0x2A, 0x92, 0xA7, 0x1E, 0x27, 0x8A},
    		.rpa.val = {0}		
    	}; 
    
      /**Copying the retrieved values from the memory onto the relevant array to pass the pairing infos*/
      memcpy(&addr.a.val[0],keys_addr,6);
      memcpy(&irk.val[0],irk_val,16);
      memcpy(&ltk.val[0],ltk_val,16);
      memcpy(&ltk.ediv[0],ltk_ediv,2);
      memcpy(&ltk.rand[0],ltk_rand,8);
    
    	pairing_info = bt_keys_get_addr(0, &addr);
    	if (pairing_info == NULL) {
    		printk("Failed to get keyslot\n");
    	}
    
      memcpy(&pairing_info->periph_ltk, &ltk, sizeof(pairing_info->ltk));
    	//memcpy(&pairing_info->ltk, &ltk, sizeof(pairing_info->ltk));
    	memcpy(&pairing_info->irk, &irk, sizeof(pairing_info->irk));
    
    	pairing_info->flags = 0;
    	pairing_info->enc_size = 16;
    	pairing_info->keys = BT_KEYS_IRK | BT_KEYS_PERIPH_LTK;
    
    	err = bt_keys_store(pairing_info);
        if (err) {
            printk("Failed to store keys (err %d)\n", err);
        } else {
            printk("Keys stored successfully\n");
        }
    
    }
    
    void reverse_copy_bytes(uint8_t* src, uint8_t* dst, size_t size) {
        if (size != 2) {
            printf("Error: Function is intended for size 2.\n");
            return;
        }
    
        // Reverse the bytes during copy
        dst[0] = src[1];
        dst[1] = src[0];
    }
    
    void retrieve_pairing_keys(void)
    {
      const volatile uint32_t *ptr = (const volatile uint32_t *)(0xf5100); //Workaround to read back the pairing info from the old SDK
      uint8_t reversed_ltk_ediv[2]; // Array to store reversed bytes
      uint8_t reversed_ltk_val[16];
      uint8_t reversed_ltk_rand[8];
      memcpy(&irk_val[0],((uint8_t*)ptr),16);
      memcpy(&keys_addr[0],((uint8_t*)ptr+16+1),6);
      memcpy(&reversed_ltk_val[0],((uint8_t*)ptr+16+6+1),16);
      memcpy(&reversed_ltk_ediv[0],((uint8_t*)ptr+16+6+16+1+2),2);
      memcpy(&reversed_ltk_rand[0],((uint8_t*)ptr+16+6+16+2+1+2),8);
      // memcpy(&ltk_val[0],((uint8_t*)ptr+16+6+1),16);
      // memcpy(&ltk_ediv[0],((uint8_t*)ptr+16+6+16+1+2),2);
      // memcpy(&ltk_rand[0],((uint8_t*)ptr+16+6+16+2+1+2),8);  
      // Perform the reverse copy
      reverse_bytes(&ltk_ediv[0], &reversed_ltk_ediv[0], 2);
      reverse_bytes(&ltk_val[0], &reversed_ltk_val[0], 16);
      reverse_bytes(&ltk_rand[0], &reversed_ltk_rand[0], 8);
      for(uint8_t i =0;i<16;i++)
      {
        printk(" %02x",reversed_ltk_val[i]);
      }
      printk("Successfully copied pairing info from the memory\n");
    }


    Needed help from the nrf5SDK side, if anything in copying I missed. I will also share ble sniffer trace tomorrow(But I dont remember seeing EDIV and RAND related logs in sniffer trace ,btw I use wireshark for BLE sniffing).

  • Just read the comments in the code, I`ll test with these changes and let you know.
    Thanks

  • Here is an updated version of the pre_shared_bond_set() function which should handle legacy pairing

    Still disconnecting after the changes,but the EDIV and RAND are matching now-

    00> 8a 27 1e a7 92 2a f0 15 41 69 48 dd c0 7e dd f7 [00:00:08.474,365] <inf> bt_keys: Legacy LTK: 0x81ee0de3848ec6bf4d9d9d4cb98de928 (peripheral)
    00> Connected
    00> [00:00:08.672,668] <dbg> bt_keys: bt_keys_find: type 32 F4:E8:C7:5E:82:43 (public)
    00> [00:00:08.672,851] <dbg> bt_keys: bt_keys_find: type 1 F4:E8:C7:5E:82:43 (public)
    00> [00:00:08.672,851] <dbg> bt_smp: bt_smp_request_ltk: Its inside this loop now 3
    00> 
    00> RAND from key : 12030894171999848549
    00> RAND from HCI buf: 12030894171999848549
    00> EDIV from key : 64060
    00> EDIV from HCI buf : 64060
    00> [00:00:08.762,512] <dbg> bt_smp: bt_smp_disconnected: chan 0x20003ce8 cid 0x0006
    00> [00:00:08.762,847] <dbg> bt_keys: bt_keys_find_addr: F4:E8:C7:5E:82:43 (public)
    00> [00:00:08.763,031] <dbg> bt_keys: bt_keys_find_addr: F4:E8:C7:5E:82:43 (public)
    00> Disconnected (reason 0x13)

  • Still disconnecting after the changes,but the EDIV and RAND are matching now-

     Recheck it again by simply copying the values directly in the structure and still not able to connect.

    00> 8a 27 1e a7 92 2a f0 15 41 69 48 dd c0 7e dd f7 [00:00:08.060,668] <inf> bt_keys: Legacy LTK: 0x863be25911d3af286101dad5dab01db1 (peripheral)
    00> Connected
    00> [00:00:08.060,699] <dbg> bt_smp: smp_send_security_req: 
    00> [00:00:08.060,882] <dbg> bt_keys: bt_keys_get_addr: F4:E8:C7:5E:82:43 (public)
    00> [00:00:08.061,065] <dbg> bt_smp: smp_init: prnd 37a95cfba06b8f8ed4dbabde26d4bdc6
    00> [00:00:08.228,851] <dbg> bt_smp: bt_smp_request_ltk: Its inside this loop now 3
    00> 
    00> RAND from key : 14895755191182585488
    00> RAND from HCI buf: 14895755191182585488
    00> EDIV from key : 2479
    00> EDIV from HCI buf : 2479

    Logs from nrf5SDK version-

    00>  F7 DD 7E C0 DD 48 69 41 15 F0 2A 92 A7 1E 27 8A<info> app: Address:
    00>
    00>  43 82 5E C7 E8 F4 42<info> app: LTK:
    00>
    00>  B1 1D B0 DA D5 DA 01 61 28 AF D3 11 59 E2 3B 86<info> app: LTK others:
    00>
    00> <info> app:  9AF
    00>
    00> <info> app: RAND:
    00>
    00>  90 6E 9E DF 6C 5A B8 CE

Related