This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

resolve BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE address without using whitelist advertising

Hi there,

Is there any way to resolve a BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE address without using whitelist advertising? If not, I guess I should implement the ah function by myself.

I know that Nordic softdevice certainly has this function implemented. My question is, could I have the access to it?

Thank you for any information

  • @chd: I afraid that there is no API for doing the address IRK resolve exposed from the stack. You would need to implement the ah function on your own.

    I did a quick search and found this from the BLUEZ stack (Linux's BLE stack). I guess it would be useful for you:

    https://kernel.googlesource.com/pub/scm/bluetooth/bluez/+/5.15/src/shared/crypto.c

    (look for bt_crypto_ah)

  • You can do this with the sd_ecb_block_encrypt() function. Here is a quick and dirty example function that checks if a given address matches a given IRK. This assumes the address has the BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE type, and does not handle any errors with the encryption call.

    static bool resolve_addr(ble_gap_addr_t * addr, const uint8_t * irk_array)
    {
        ble_gap_addr_t tmp_addr = {0};
        nrf_ecb_hal_data_t encryption_data;
        uint32_t errcode;
        uint8_t i;
       
        memcpy(&tmp_addr.addr[3], &addr->addr[3], 3);
        memset(&encryption_data, 0, sizeof(encryption_data));
    
        /* Reverse the array as ECB expects it in big-endian format */
        for (i=0; i<sizeof(encryption_data.key); i++)
        {
            encryption_data.key[i] = irk_array[sizeof(encryption_data.key)-1-i];
            if (i < 3)
            {
                encryption_data.cleartext[15-i] = tmp_addr.addr[3+i];
            }
        }
    
        errcode = sd_ecb_block_encrypt(&encryption_data);
        for (i=0; i<3; i++)
        {
            tmp_addr.addr[i] = encryption_data.ciphertext[15-i];
        }
    
        return (memcmp(addr->addr, tmp_addr.addr, sizeof(addr->addr)) == 0);
    }
    

    Edit: Indentation is different from the edit mode :(

  • @Hung, Ulrich: Thank you so much for your swift responses. I haven't tested your solutions yet but after a quick look I think both of the implementations can resolve the problem I mentioned in the first time. Another question: currently I use the irk directly to identify my peer devices since I believe that the irk is unchanged during device's lifetime. Am I right?

  • This is correct. An IRK should be static as long as the bond is valid. For our devices it is based on some randomly generated factory settings, but can be manually overridden with the options API.

  • What do you mean by "as long as the bond is valid"? As my observation the irk is unchanged even when I do a manually "forget device" in bluetooth settings (iOS) then do the bonding again. Did you mean that as long as the 2 devices are successfully bonded to each other?

Related