espressif / esp-idf-provisioning-android

Android Provisioning application for ESP-IDF Unified provisioning
Apache License 2.0
199 stars 131 forks source link

AES encryption for profile Security1 #89

Open miki-bgd opened 1 year ago

miki-bgd commented 1 year ago

Hello,

Application works on Android, i tried both in Java and ported to Xamarin C#. However, i am not experienced in cryptography, and would appreciate some explanations about AES algorithm.

  1. Why Encrypt and Decrypt both invoke encryptor, and not decryptor?
  2. Why DoFinal method is never invoked?
  3. I have tried BouncyCastle, which has almost identical initialization like Javax.Crypto, but there is a problem. Up until WiFi scanning, all messages are 32 bytes long, and everyting works. Starting with WiFi scan, generated message has only 6 bytes, and BoncyCastle's method ProcessBytes returns null. If BC's DoFinal is invoked, it gives correct result (checked with JavaxCrypto), but from that moment BoncyCastle's encryption is wrong.
    • i know this is outside of scope for espressif, but i am trying to understand algorithm you are using, in hope to find solution for my other problem.

Thanks in advance, Miki

miki-bgd commented 1 year ago

I have found solution, so here is explanation for future readers.

3 . Javax.Crypto AES/CTR/NoPadding algorithm returns results even if you provide array of bytes which is shorter than block size (for AES it is 128b/16B). You provide 4B, it will return E/D(encrypted/decrypted) 4B (this is because E/D is performed on complete block of 16B, but bytes do not have any correlation between them; you can provide bytes 3,4,5, and result will be at those indexes as well). BouncyCastle doesn't return result, until complete internal buffer is full (16B). If DoFinal is invoked, then result is good, but it also performs reset of the counter, which means invoking E/D won't work anymore, because counter is disrupted.

1 . I believe i have understanding about this. IV and counter combination, in AES/CTR must be used only once, in order to preserve security. One instance can do either encryption or decryption. Since counter is initialized from IV (copied, precisely), for both encryption and decryption, it would need 2 IV (remember IV and C combination can be used only once). I believe it was design decision. One thing is little bit unusual (at least to me), this approach means that data is first decrypted by idf, and client will need to encrypt it to get information.

2 . DoFinal will do padding and will return result no matter if buffer is full, but it will also reset counter which means encryptor/decryptor can't be used anymore.

PS. This is just my understanding. Would be nice if someone confirms it, and maybe gives some additional explanation.

Cheers

d-rahul commented 9 months ago

I found the same one but I am not using Xamarin. I have another connected Bluetooth Device and now I am trying to provision with ESP32 C3. Able to search and write POP but for scanning WiFi devices it returns null Encrypted Data for sending Config Data. I cross-confirmed it by disconnecting the other Bluetooth Device and trying to provision ESP and it worked well with no issues in scanning BLE, Wi-Fi, and configuring Data.

@ameyinamdar What could be the issue for provisioning a device if there is already a connection to another Bluetooth Device (Not ESP)? Could you please explore it, below are the logs for your reference..Security1 encryption doesn't work in this case...

Start Wi-Fi Scan 11:49:55.060 D Send Wi-Fi scan command to device 11:49:55.073 E Security sendConfigData Data: [82, 4, 8, 1, 32, 120] EncryptedData: null 11:49:55.074 W java.lang.RuntimeException: Security encryption failed 11:49:55.075 W at com.espressif.provisioning.Session.sendDataToDevice(Session.java:132) 11:49:55.076 W at com.espressif.provisioning.ESPDevice.startNetworkScan(ESPDevice.java:699) 11:49:55.077 W at com.espressif.provisioning.ESPDevice.scanNetworks(ESPDevice.java:525) 11:49:55.078 W at com.lion.smart.ui.fragments.gateway.GatewayScanWifiFragment.startWifiScan(GatewayScanWifiFragment.java:131) 11:49:55.079 W at com.lion.smart.ui.fragments.gateway.GatewayScanWifiFragment.setDefaults(GatewayScanWifiFragment.java:115) 11:49:55.080 W at com.lion.smart.ui.fragments.gateway.GatewayScanWifiFragment.init(GatewayScanWifiFragment.java:94) 11:49:55.081 W at com.lion.smart.ui.fragments.gateway.GatewayScanWifiFragment.onViewCreated(GatewayScanWifiFragment.java:83) 11:49:55.082 W at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:3128) 11:49:55.083 W at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:552) 11:49:55.084 W at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:261) 11:49:55.084 W at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1890) 11:49:55.085 W at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1808) 11:49:55.086 W at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1751) 11:49:55.087 W at androidx.fragment.app.FragmentManager$5.run(FragmentManager.java:538) 11:49:55.088 W at android.os.Handler.handleCallback(Handler.java:938) 11:49:55.088 W at android.os.Handler.dispatchMessage(Handler.java:99) 11:49:55.089 W at android.os.Looper.loopOnce(Looper.java:210) 11:49:55.090 W at android.os.Looper.loop(Looper.java:299) 11:49:55.091 W at android.app.ActivityThread.main(ActivityThread.java:8309) 11:49:55.091 W at java.lang.reflect.Method.invoke(Native Method) 11:49:55.092 W at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:556) 11:49:55.093 W at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1038)

11:49:55.094 E onWiFiScanFailed

11:49:55.095 W java.lang.RuntimeException: Failed to send Wi-Fi scan command. 11:49:55.096 W at com.espressif.provisioning.ESPDevice$8.onFailure(ESPDevice.java:728) 11:49:55.097 W at com.espressif.provisioning.Session.sendDataToDevice(Session.java:132) 11:49:55.097 W at com.espressif.provisioning.ESPDevice.startNetworkScan(ESPDevice.java:699) 11:49:55.098 W at com.espressif.provisioning.ESPDevice.scanNetworks(ESPDevice.java:525) 11:49:55.099 W at com.lion.smart.ui.fragments.gateway.GatewayScanWifiFragment.startWifiScan(GatewayScanWifiFragment.java:131) 11:49:55.099 W at com.lion.smart.ui.fragments.gateway.GatewayScanWifiFragment.setDefaults(GatewayScanWifiFragment.java:115) 11:49:55.100 W at com.lion.smart.ui.fragments.gateway.GatewayScanWifiFragment.init(GatewayScanWifiFragment.java:94) 11:49:55.101 W at com.lion.smart.ui.fragments.gateway.GatewayScanWifiFragment.onViewCreated(GatewayScanWifiFragment.java:83) 11:49:55.102 W at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:3128) 11:49:55.103 W at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:552) 11:49:55.104 W at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:261) 11:49:55.104 W at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1890) 11:49:55.105 W at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1808) 11:49:55.106 W at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1751) 11:49:55.107 W at androidx.fragment.app.FragmentManager$5.run(FragmentManager.java:538) 11:49:55.108 W at android.os.Handler.handleCallback(Handler.java:938) 11:49:55.108 W at android.os.Handler.dispatchMessage(Handler.java:99) 11:49:55.109 W at android.os.Looper.loopOnce(Looper.java:210) 11:49:55.110 W at android.os.Looper.loop(Looper.java:299) 11:49:55.111 W at android.app.ActivityThread.main(ActivityThread.java:8309) 11:49:55.112 W at java.lang.reflect.Method.invoke(Native Method) 11:49:55.113 W at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:556) 11:49:55.114 W at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1038)