odyshewroman / AndroidTVRemoteControl

MIT License
30 stars 9 forks source link

RemoteState always returns "connected" even with incorrect pairing code #7

Closed thachonline closed 10 months ago

thachonline commented 11 months ago

I've encountered an issue with the AndroidTVRemoteControl library. When I input an incorrect pairing code, the RemoteState always returns "connected," and I'm unable to initiate a new pairing process. This behavior is causing difficulties in re-establishing a valid pairing.

Additionally, the following error is displayed in the console of the demo app:

Error: 4823468592:error:10000416:SSL routines:OPENSSL_internal:SSLV3_ALERT_CERTIFICATE_UNKNOWN:/Library/Caches/com.apple.xbs/Sources/boringssl_Sim/ssl/tls_record.cc:592:SSL alert number 46

I believe there might be an issue with the handling of incorrect pairing codes and the SSL routines.

odyshewroman commented 11 months ago

This is very strange because if you enter an incorrect code, the hash generated using the last two digits is highly likely not to start with the first digit of the code. The probability of this happening is equal to the probability of collision in the SHA256 algorithm. I verify the hash match before sending it to the Android TV OS device by running a test and entering an incorrect code, and I received the corresponding error.

You can set a breakpoint at line 75 in the CryptoManager in the getEncodedCert function to check how the first byte of the hash is equal to the first hex digit of the incorrect code.

thachonline commented 11 months ago

When I debug, I notice that line 75 of the CryptoManager file is not being executed. The debugging process is as follows: in the handleConnectionState method, remoteState becomes .connected, and then an error occurs with the message "Receive failed with error 'misc. bad certificate'." Finally, it jumps into the case receiveDataError: -9825: misc. bad certificate in the RemoteTVManager file at line 194.

In this case:

The issue might be related to the certificate. When connecting to the TV, whether you enter a pairing code or not, if an incorrect pairing code is entered, the TV still stores the certificate from the client for later use. Therefore, in this situation, the certificate from the client might be corrupted and cannot be used further. It seems like I suspect that the problem is related to the certificate, especially when an incorrect pairing code is entered. The TV retains the client's certificate, and this certificate might be causing the issue.

odyshewroman commented 11 months ago

Oh, I should have made this Demo more simpler...

Ok, I try to explain one more time: Upon the initial connection attempt to the device, since pairing hasn't occurred, you receive a corresponding error along with logs in the console. The code branch with pairing is then executed, triggering an event where you need to enter the code. Upon entering the code, line 75 in CryptoManager must be executed, or you will encounter an error. You can trace the button "Send Code" functionality as follows: RemoteTVManager->sendCode => PairingManager->sendSecret => CryptoManager->getEncodedCert, where the only successful response occurs after passing through line 75.

Let me try to explain again:

If you catch an error related to the certificate from RemoteTVManager, you should initiate a new pairing process.

You can modify the connect function in RemoteTVManager as follows:

queue.async {
            self.remoteManager.stateChanged = { [weak self] remoteState in
                self?.remoteStateChanged?(remoteState.toString())
            }

            self.pairingManager.stateChanged = { [weak self] pairingState in
                self?.pairingStateChanged?(pairingState.toString())

                if case .successPaired = pairingState {
                    self?.remoteManager.connect(host)
                }
            }

            self.pairingManager.connect(host, "client", "iPhone")
        }

In this case, you will follow the canonical and sequential process of pairing first and then connecting.