NordicSemiconductor / Android-nRF-Mesh-Library

The Bluetooth Mesh Provisioner and Configurator library.
https://www.nordicsemi.com/
BSD 3-Clause "New" or "Revised" License
407 stars 176 forks source link

ExtendedInvalidCipherTextException message response after switching from iOS to Android #295

Closed antoniovillanova closed 4 years ago

antoniovillanova commented 4 years ago

Describe the bug We have the scenario in which same Mesh Network can be edited on both Android and iOS devices. We managed to successfully restore Mesh Network with import and export built-in procedures, by creating different provisioners for each device and platform. The issue we're facing is that after iOS can succesfully get the response after sending a Vendor Model Message, Android receives the Exception i reported below in Logs / Screenshots section. Only powering the BT peripheral off and back on seems to fix the issue on the Android side.

To Reproduce Steps to reproduce the behavior:

  1. Create Mesh Network from Android
  2. Provision a Node
  3. Import Mesh Network on iOS
  4. Get a parameter from one vendor model
  5. Switch back to Android
  6. Get a parameter from same vendor model

Expected behavior Successfully read response value

Platform details:

Logs / Screenshots

no.nordicsemi.android.meshprovisioner.utils.ExtendedInvalidCipherTextException: mac check in CCM failed
    at no.nordicsemi.android.meshprovisioner.transport.BaseMeshMessageHandler.parseMeshPduNotifications(BaseMeshMessageHandler.java:163)
    at no.nordicsemi.android.meshprovisioner.MeshMessageHandler.parseMeshPduNotifications(MeshMessageHandler.java:61)
    at no.nordicsemi.android.meshprovisioner.MeshManagerApi.parseNotifications(MeshManagerApi.java:263)
    at no.nordicsemi.android.meshprovisioner.MeshManagerApi.handleNotifications(MeshManagerApi.java:235)
    at com.vimar.p406.ble.viewmodel.NrfMeshRepository.onDataReceived(NrfMeshRepository.java:540)
    at com.vimar.p406.ble.BleMeshManager$1.lambda$initialize$0$BleMeshManager$1(BleMeshManager.java:145)
    at com.vimar.p406.ble.-$$Lambda$BleMeshManager$1$menHcS3BNZmUA4ruRSpuglMOKeA.onDataReceived(Unknown Source:2)
    at no.nordicsemi.android.ble.ValueChangedCallback.notifyValueChanged(ValueChangedCallback.java:123)
    at no.nordicsemi.android.ble.BleManager$BleManagerGattCallback.onCharacteristicChangedSafe(BleManager.java:2884)
    at no.nordicsemi.android.ble.MainThreadBluetoothGattCallback.lambda$onCharacteristicChanged$4$MainThreadBluetoothGattCallback(MainThreadBluetoothGattCallback.java:135)
    at no.nordicsemi.android.ble.-$$Lambda$MainThreadBluetoothGattCallback$7AU42XLOqZKSRIMVuifw3eecBbw.run(Unknown Source:8)
    at android.os.Handler.handleCallback(Handler.java:883)
    at android.os.Handler.dispatchMessage(Handler.java:100)
    at android.os.Looper.loop(Looper.java:237)
    at android.app.ActivityThread.main(ActivityThread.java:8016)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1076)
roshanrajaratnam commented 4 years ago

Hi @antoniovillanova , so I gave this a try and i was unable to reproduce the same issue as you are facing. I can detail the steps I took just like you had mentioned.

  1. Create Mesh Network from Android
  2. Provision a Node
  3. Import Mesh Network on iOS (I did not use the same provisioner as on Android as this is bound to fail because the sequence numbers are not exported for any given provisioner)
  4. Bind key to vendor model using iOS
  5. Control vendor model
  6. Switch back to Android
  7. Go to vendor model pull to refresh to get the newly bound key configuration that was added using iOS
  8. Control the vendor model.

I repeated the process 3 times and it worked 3 out of 3 times. Also I extended the test process by

  1. Unbinding the key on the vendor model from Android
  2. Pulled to refresh on iOS to update the the unbound key setting
  3. Bind again
  4. Control

All messages worked as it should. Have you checked if you are encrypting your message properly on the fw side? If you want me to test against your fw you can create a private ticket on devzone

antoniovillanova commented 4 years ago

HI @roshanrajaratnam,

a couple of things about the steps you mentioned.

  1. Bind key to vendor model. In my scenario i bind the app key on the vendor model first time on Android side. May this affect your tests?
  2. Control vendor model. What do you mean with "Control"? it's a simple Request/Response message?
  3. Switch back to Android When you switch back to Android, are you sure the provisioner is the same as it was the first time? Or a new provisioner will be created? If the provisioner remains the same, how do you handle restoring its sequence number?

Thank you!

antoniovillanova commented 4 years ago

Furthermore, reading Bluetooth spec about Mesh Message encryption, both sequence number and IV Index are involved.

I know there will be a patch next week involving a bug fix you have on IV index handling. So both this and restoring Android previous provisioner (and its sequence number) could possibly cause the exception. Am i right?

Thank you again.

philips77 commented 4 years ago

// FYI: IV Index Update has now been fix in the iOS library. It's on develop branch, not pushed to master yet. We are working on implementing the same on Android.

roshanrajaratnam commented 4 years ago

@antoniovillanova the current iv index patch will not affect this as long as you don't have run out of sequence numbers. I don't think this is the case for you since your issue occurs right after provisioning and for an IV Index update to take place the network have to function at least around 192 hours if i'm not completely wrong so I will exclude this case. Coming back to your original issue I will try to give this a spin this evening and if not first thing in the morning tomorrow. Also it will be really helpful if you can give me a detailed description of the exact steps to reproduce this. For now I will try with the steps you suggested previously by binding keys using Android.

  1. Controlling vendor model was done with an unacked message but I don't remember to be honest so I can re-run it for you.

  2. When switching back to the Android device it is the same original provisioner used for provisioning process.

However I should note that you cannot use the same provisioner in two different devices. It has to be two different provisioners as the sequence number is not exported in Json file, i.e. provision on Android with one provisioner and after importing on iOS it has to be a different provisioner that has to send your message. The sample iOS app handles this automatically when importing a network which means that a new provisioner will be created.

antoniovillanova commented 4 years ago

We're using two different provisioners. The thing is:

philips77 commented 4 years ago

When exporting sequence number from iOS, do you get the value from UserDefaults at key "S\(address.hex)" (mind the S inside)?

philips77 commented 4 years ago

I'll add methods to obtain and update sequence numbers on iOS.

fiveagle commented 4 years ago

When exporting sequence number from iOS, do you get the value from UserDefaults at key "S\(address.hex)" (mind the S inside)?

Hi, on iOS we recreate a new provisioner with a different address each time, hence I don't read or write any sequence. I just keep the android sequence on the cloud backup without modifying it.

I'll add methods to obtain and update sequence numbers on iOS.

This would certainly help. Do you think this issue is caused by this cross platform sequence management?

Thanks

philips77 commented 4 years ago

I don't know but you requested it anyway. I will discourage using it on doc, but want people to use it correctly.

roshanrajaratnam commented 4 years ago

@fiveagle @antoniovillanova sorry for the delay but have been a bit busy with handling the IV Index update. I believe it's something to do with cross platform sequence management don't know for sure though. In-order to clarify do you know if the same happens with SigModels? or does this happen only on VendorModels?

antoniovillanova commented 4 years ago

I couldn't test with SigModels. Could you please provide me more details on how i can execute this test?

Furthermore i've some other question:

  1. Have you identified the root cause of the problem?
  2. When will you release the 2.2.2 version?
  3. Do you plan to patch the current version?

Thank you.

roshanrajaratnam commented 4 years ago

@antoniovillanova I was referring to the same test you did on vendor models.

  1. I will start testing now to find out your issue.
  2. 2.2.2 will be released later during the day.
  3. Not sure what you mean exactly here.
antoniovillanova commented 4 years ago
  1. Not sure what you mean exactly here.

Yep, sorry i edited.

If you'll manage to find the issue, will be released a patch for the actual version too?

Thank you

roshanrajaratnam commented 4 years ago

@antoniovillanova I have retried to reproduce this issue but it does not happen in our side. After configuring and controlling from Android and importing to iOS, the iOS app uses the default provisioner created in the app. We do not export sequence numbers and is not recommended so there is no chance of using the same provisioner that was used on the Android side. After switching to the Android phone the app it will continue using the same provisioner and the same sequence number as it last used so there will be no new provisioner created.

I have updated the api in this case where you can set the sequence number of a provisioner node. So you do not have to re-create the same provisioner as @fiveagle has mentioned. You can use the provisionerUuid to locate the node of the provisioner from the node list in the network and call node.setSequenceNumber to update the sequence number of that node.

I also suggest to try out 2.2.2 version of the library once it's released as it will contain some important fixes related to Secure Network Beacon handling.

roshanrajaratnam commented 4 years ago

@antoniovillanova have you managed to solve your issue?

roshanrajaratnam commented 4 years ago

@antoniovillanova closing due to inactivity!