Directed advertising to Android phone without bonding

Hello,

Here is my setup:

  • Hardware
    • nRF52840 development kit - Qty: 2
      • One in Central Role
      • One in Peripheral Role
    • Android Phone (Google Pixel 4a)
  • Software
    • SDK 15.2 (Using old SDK because I am making changes to an old project)
    • SoftDevice: s140_nrf52_6.1.0

I have a few questions that I think I know the answer to, but can't find a definitive answer online. The questions are listed at the bottom of this post. To preface, I have read many posts on the Nordic devzone regarding this very topic. At present, my existing project performs directed advertising using an address type of BLE_GAP_ADDR_TYPE_RANDOM_STATIC. This works without issue between two nRF52840 development kits. The Central can connect to the Peripheral with this configuration, and I can see the directed advertisements in Wireshark with a Nordic devkit as a BLE sniffer. The directed advertisement packets list the "Target Address" as the static address of the Central. This is expected.

Now, I am trying to use an Android phone as the Central while the Peripheral directly advertises to it without having to bond.  The reason I don't want to bond is because our project does not currently use the peer manager. Integrating the peer manager into an existing project that is already in the field is not a trivial task and poses significant risk of breaking the current design and introducing bugs. Our device uses directed advertising to the Central so "average" users can't see the advertising packets on their phones, tablets, etc. I realize directed advertising provides no security and an attacker can see the directed advertisements and spoof the Central's BLE address. It's more of a way to filter out the advertising traffic since multiples of these devices can be in close proximity. 

Here is what I understand about direct advertising to an Android (and iPhone):

  • Android uses a BLE MAC type of BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE
    • This is a security feature to prevent location tracking
    • This results in the phone changing is BLE MAC at a defined interval (Usually every 15 minutes but can vary)
  • The Identity Resolving Key (IRK) allows the Peripheral to resolve the identity of the Android phone, which is shared during the standard BLE bonding process.

To achieve directed advertising to an Android phone without bonding, my plan was to do the following:

  1. Obtain the IRK from the Android phone manually.
    1. I have already done this using a nRF52840 development kit.
    2. As far as I know, the IRK stays the same for the life of the phone. Please correct me if I am wrong.
  2. Inject the phone IRK into the Peripheral and use this to advertise to the Android phone.
    1. Using a similar process as seen in this post:  Directed advertising with pre-shared IRK  and "Variant #1" in this bounce diagram: https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.s132.api.v3.0.0%2Fgroup___b_l_e___g_a_p___p_r_i_v_a_c_y___a_d_v___d_i_r___p_r_i_v___m_s_c.html&cp=2_3_0_1_1_2_1_3_9_1 

Questions:

  1. Is it possible for a nRF52840 to directly advertise (and connect) to an Android phone with a pre-shared IRK without bonding to it as proposed above?
  2. How does the Peripheral know what BLE MAC to insert into the direct advertising packet if the Android phone changes its MAC every 15 minutes?

Thanks,

Derek

Parents
  • Is it possible for a nRF52840 to directly advertise (and connect) to an Android phone with a pre-shared IRK without bonding to it as proposed above?

    Yes, This is how many customers/products have done it aswell. but that was on the older SDK, I need to dig a bit to find how to do this in nRF connect SDK.

    How does the Peripheral know what BLE MAC to insert into the direct advertising packet if the Android phone changes its MAC every 15 minutes?

    Again using whitelisting on IRK seems to be the solution here, as IRK wont change over time.

    As far as I know, the IRK stays the same for the life of the phone. Please correct me if I am wrong.

    You are right.

  • Derek,

    Sorry for delays, I was stuck in something else and did not manage to unplug from it. Thanks for being nice and patient. Really appreciate it. 

    droberson said:
    You cannot perform whitelisting and directed advertising at the same time, so how does whitelisting apply to question #2?

    Yes, sorry, Whitelisting cannot be used with directed advertising as it is assumed that you already know which device you want to communicate with.

    If you know that you want to connect to some Android phone, then you need to first connect and pair with it atleast once so that the Android phone can share its IRK with your device. Once you get it and save it, you can use it to check that the new device address used by Android phone is generated by the same IRK or not. You only send directed advertising to devices that pass this translation.

Reply
  • Derek,

    Sorry for delays, I was stuck in something else and did not manage to unplug from it. Thanks for being nice and patient. Really appreciate it. 

    droberson said:
    You cannot perform whitelisting and directed advertising at the same time, so how does whitelisting apply to question #2?

    Yes, sorry, Whitelisting cannot be used with directed advertising as it is assumed that you already know which device you want to communicate with.

    If you know that you want to connect to some Android phone, then you need to first connect and pair with it atleast once so that the Android phone can share its IRK with your device. Once you get it and save it, you can use it to check that the new device address used by Android phone is generated by the same IRK or not. You only send directed advertising to devices that pass this translation.

Children
  • Susheel,

    No worries, thanks for the reply. I already have the IRK from the phone I am trying to directly advertise to.

    Once you get it and save it, you can use it to check that the new device address used by Android phone is generated by the same IRK or not. You only send directed advertising to devices that pass this translation.

    I am not sure what you mean by this. "You can use it to check that the new device address" sounds like the Peripheral needs to listen to scan requests from all Centrals. In order to do this, the Peripheral would need to advertise to all Centrals, which defeats the purpose of what I want to achieve (direct advertising).

    To summarize and clarify my original post, I want to directly advertise to an Android phone 100% of the time unless connected to the phone. Is this possible so long as the Peripheral device knows the Android phone's IRK?

    To me, this doesn't seem possible because the Android phone rotates it's MAC every 15 minutes or so, hence why I am looking for a definitive answer.

    Thanks,

    Derek

  • Hi Derek

    Susheel is out of office, so I have been assigned to this case while he's away. it took a while to get through his cases, so sorry about the delay.

    Yes, directed advertising should be possible to do like this, but you need to get the IRK shared somehow to the Android, and the "normal/sensible" way to do so would be by bonding, which is what I would suggest. How you get the IRK on the Android without bonding will need to be handled by you though. We have a couple of discussions on this in the DevZone already: 

    Best regards,

    Simon

  • Hey Simon,

    No worries, thanks for the reply.

    but you need to get the IRK shared somehow to the Android

    Why does the Android phone need the IRK of the Peripheral device if the Peripheral uses a BLE address type of BLE_GAP_ADDR_TYPE_RANDOM_STATIC? I thought only the Peripheral needed the IRK of the Android phone?

    We have a couple of discussions on this in the DevZone already: 

    I reviewed both of the posts you linked. The post Advertising to pre-shared IRK never resulted in a conclusion, and the original poster was new to C, thus making his effort much more difficult, which he never achieved the desired outcome.

    The post Direct advertising with unbonded Android phone resulted in the following comment from FAE Torbjørn:

    --------------------------------

    Hi 

    The problem in this case is that the directed advertising packet will not be reported to the application as a normal advertising packet, so the phone would have to know about the device in some other way. 

    This is outside our control since it is handled by the Bluetooth stack in the phone. 

    Best regards
    Torbjørn

    --------------------------------

    Based on Torbjørn's response, it doesn't seem advertising to an Android phone with a pre-shared IRK is possible. Yet, Susheel and you say it is possible? Which is the case?

    I have directed advertising working fine without an IRK. Without IRK, my code is as follows:

    // Start advertising
    ble_advertising_start(&m_advertising, BLE_ADV_MODE_DIRECTED);
    
    ...
    This results in event BLE_ADV_EVT_PEER_ADDR_REQUEST
    ...
    
    case BLE_ADV_EVT_PEER_ADDR_REQUEST:
    {
       // This event occurs when directed advertising is used
       Log(BLE, "BLE_ADV_EVT_PEER_ADDR_REQUEST");
       
       ret_code_t retCode;
       uint8_t mac[BLE_GAP_ADDR_LEN] = {0xEE, 0xA5, 0x86, 0x7E, 0xE2, 0x3A};
       ble_gap_addr_t peerAddr;
    
       // Set GAP structure
       peerAddr.addr_id_peer = 0;
       peerAddr.addr_type = BLE_GAP_ADDR_TYPE_RANDOM_STATIC;
       
       // Copy in MAC but reverse byte order to match GAP address type
       rev_memcpy(peerAddr.addr, mac, sizeof(peerAddr.addr));
       
       retCode = ble_advertising_peer_addr_reply(&m_advertising, &peerAddr);
       APP_ERROR_CHECK(retCode);
       
       break;
    }

    Edit: Here is a Wireshark capture of my working directed advertising with a random static address (No IRK).

    Using the above working code as a template and "Variant #1" in this bounce diagram: https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.s132.api.v3.0.0%2Fgroup___b_l_e___g_a_p___p_r_i_v_a_c_y___a_d_v___d_i_r___p_r_i_v___m_s_c.html&cp=2_3_0_1_1_2_1_3_9_1 

    My IRK define and BLE_ADV_EVT_PEER_ADDR_REQUEST handler now looks like this:

    // Global constants for testing
    const ble_gap_id_key_t m_peer1 = 
    {
        .id_info =
        {
            // Android phone IRK
            .irk = {0x57, 0x5E, 0xA8, 0xBB, 0x22, 0x20, 0xB4, 0x47, 0xF4, 0xFF, 0xF1, 0x55, 0xE6, 0xCE, 0x02, 0xF1},
        }
    };
    
    const ble_gap_id_key_t * m_identities[] = {&m_peer1};
    
    case BLE_ADV_EVT_PEER_ADDR_REQUEST:
    {
       uint8_t mac[BLE_GAP_ADDR_LEN] = {0xEE, 0xA5, 0x86, 0x7E, 0xE2, 0x3A}; // Android Phone MAC
       ble_gap_addr_t peerAddr;
       
       // Set IRK so we can use directed advertising with an Android phone that uses a
       // private random resolvable address.
       retCode = sd_ble_gap_device_identities_set(m_identities, NULL, 1);
       APP_ERROR_CHECK(retCode);
    
       // Set GAP structure
       peerAddr.addr_id_peer = 0;
       peerAddr.addr_type = BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE;
       
       // Copy in MAC but reverse byte order to match GAP address type
       rev_memcpy(peerAddr.addr, mac, sizeof(peerAddr.addr));
       
       retCode = ble_advertising_peer_addr_reply(&m_advertising, &peerAddr);
       APP_ERROR_CHECK(retCode);
       
       break;
    }

    When I attempt to advertise with ble_advertising_start(&m_advertising, BLE_ADV_MODE_DIRECTED), this function returns error code 0x3202 which I understand to be BLE_ERROR_GAP_INVALID_BLE_ADDR and the device does not advertise at all.

    What am I doing wrong?

    Thanks,

    Derek

Related