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
  • To retrieve the EDIV,RAND and LTK I am using ble_gap_enc_key_t peer_ltk not own_ltk structure.

    What was the EDIV and RAND read by the pm_peer_data_bonding_load()?

    This is the log on the Zephyr version to get the keys values-
    00> RAND from key : 9352719265585580685
    00> RAND from HCI buf: 7538881654322155438
    00> EDIV from key : 47645
    00> EDIV from HCI buf : 45333

    And on the nrf5SDK, I am getting the same keys, which I am sending to Zephyr.
    EDIV:  47645
    RAND : 9352719265585580685

Children
  •  Anything pls or pls share your sample code on the nrf5SDK. These changes are very urgent to implement.
    Pls help.

  • I don't have a sample ready for the nRF5 SDK, and I don't see how it is relevant since you have already managed to get this working with LESC pairing. What would be helpful is if you could capture the sniffer traces as I suggested.

  • For LESC, I only did on Zephyr version not through saving the info on nrf5SDK and then getting that info onto Zephyr and reconnecting.

    On Zephyr application, I bonded the device and then saved those info and then cleared the flash and reconnected with the old bond info and it reconnected.
    Thats why wanted to verify from the nrf5SDK if I have missed anything.

  • 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).

Related