iOS Bluetooth LE : unable to connect using stored pairing data

16,367

You don't have to do anything in your app for pairing management.

If your app runs in LE Central mode, and the peripheral sends an Insufficient Authentication error code in response to a read / write request, iOS will automatically pair with your device and will retry the request.

If you disconnect from the device, and later reconnect again, the peripheral needs to send the Insufficient Authentication error code again for the iPhone to restart encryption. Again, you don't have to do anything special in your app here.

If your app runs in LE Peripheral mode, things are a bit different. When you set up your GATT database, make sure to set correct flags for both the CBAttributePermissions and CBCharacteristicProperties. This will tell iOS that it should send the Insufficient Authentication error code itself, if it is not paired. It is then the responsibility of the central device to start the encryption process.

In the Bluetooth Accessory Design Guidelines for Apple Products, further restrictions are described.

  • Your accessory needs the capability to resolve private Bluetooth addresses. The iPhone will change its public Bluetooth address every now and then, and only paired devices will have the correct key to resolve that public address and recognize the iPhone.

  • "Section 3.9 Pairing" is also interesting.

  • Note that if you pair without man-in-the-middle (MITM) protection, your peripheral can use the resulting key to resolve the private Bluetooth address of the iPhone. However, you won't be able to encrypt the channel.

    Pairing with MITM protection on iOS involves entering a PIN code that is displayed by the remote device. Out-of-band (OOB) pairing where you send pairing data over an external channel is not supported by iOS as far as I know (at least there's no public APIs to set OOB data).

    Long story short: if you have only a "Pair" / "Cancel" pairing, you cannot encrypt the LE channel but only recognize the iPhone in future connections. The nice thing is that you can still recognize the iPhone even if you unpair it on the iPhone side, and even after restoring the iPhone firmware ;-).

Regarding LE encryption in general: it's not secure anyways (see http://eprint.iacr.org/2013/309).

Share:
16,367

Related videos on Youtube

sdespont
Author by

sdespont

SOreadytohelp

Updated on September 20, 2022

Comments

  • sdespont
    sdespont over 1 year

    What I am trying to do

    I am trying to connect my app to a Bluetooth LE device which needs to be paired.

    Current behaviour

    There is no problem without pairing the device and my iPhone application. I am able to connect, reconnect and read/write characteristics without any problem.

    But, if the device need to be paired, I am only able to read/write characteristics the first time, right after the pairing popup confirmation. The next time, I discover and connect the app to my device, but I don't have the rights to read/write characteristics data because (I guess) I am not using the pairing information.

    Finally...

    After spending few hours searching around the web with no luck here are my questions :

    • How can I connect my app to a Bluetooth LE device from my iPhone app using the pairing data stored in my phone? Am I missing something?

    • Is it possible that it is not an IOS problem because if pairing data are present in the phone for the connecting device, it is automatically used?

    Is there someone with experience with Bluetooth LE and IOS to help me?

    Update 2013-10-27

    I have discovered that you can't read a protected characteristic by pairing authentication right after that the characteristic has been discovered if a pairing exists (no confirmation popup). No problem with non-protected characteristic! I don't know exactly why is happening, but the behavior is that the IOS app never receive answers from the device.

    So if the first reading is done after, it doesn't cause problem. Here is the code I am using to discover characteristics with the data reading in comment.

    - (void) peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error;
    {
        NSArray     *characteristics    = [service characteristics];
        CBCharacteristic *characteristic;
    
        if (peripheral != servicePeripheral) {
            NSLog(@"Wrong Peripheral.\n");
            return ;
        }
    
        if (service != batteryService) {
            NSLog(@"Wrong Service.\n");
            return ;
        }
    
        if (error != nil) {
            NSLog(@"Error %@\n", error);
            return ;
        }
    
        for (characteristic in characteristics) {
            NSLog(@"discovered characteristic %@", [characteristic UUID]);
    
            if ([[characteristic UUID] isEqual:[CBUUID UUIDWithString:kBatteryCharacteristicUUIDString]]) { // Bat
                NSLog(@"Discovered Bat Characteristic");
                batteryCharacteristic = [characteristic retain];
                //--> generate problem when pairing exists between IOS app and device
                //[peripheral readValueForCharacteristic:batteryCharacteristic];
            }
        }
    }
    
  • sdespont
    sdespont over 10 years
    Thanks for your complete and interesting answer. Because of my device has no display or keyboard, the authentication method is "Just Works". You are right about the fact that I don't need to do smth to work with current pairing information. With your answer in mind, I was able to point the real problem. Check my question update.
  • sdespont
    sdespont over 10 years
    the problem was in the BLE chip side. Thanks for helping me to trust the iPhone behaviour, I was blaming the wrong device :o)
  • Jorgen
    Jorgen about 10 years
    @Etan. I'm trying to "pair" an iOS device with a printer over Bluetooth. I would know the MAC address and the Bluetooth Pin for the printer. How can I do this in code without having to display a dialogue? Is it possible?
  • Etan
    Etan about 10 years
    This is not possible with public APIs. Maybe you can use the private BluetoothManager framework (undocumented) to achieve this. Interface here: github.com/nst/iOS-Runtime-Headers/blob/master/…
  • Jorgen
    Jorgen about 10 years
    @Etan, thanks. I've looked it up and sent a query to the GitHub owner to see if he can shed some light on it. However it looks very promising.
  • mfaani
    mfaani about 2 years
    I understand everything you said. Just don't get why would your device/app itself ever be "in LE Peripheral mode"?? Should all apps be just the receiving end of things?