pp3345 / ykDroid

YubiKey challenge-response USB and NFC driver for Android
GNU General Public License v3.0
97 stars 14 forks source link

Yubikey NEO fails #5

Closed innovate-invent closed 6 years ago

innovate-invent commented 6 years ago

When trying to scan a Yubikey NEO using NFC to authenticate Keepass2Android it fails with an error. The error flashes so fast back to the scan prompt that I can not read it.

This may be due to the default timeout of the OS being too short for NFC transactions. See here for details: https://github.com/brush701/yubichallenge/issues/3

pp3345 commented 6 years ago

This should have been fixed by https://github.com/pp3345/ykDroid/commit/cfe8281f41395382072c93d7f09a3bd23100f475. Could you please attach the logcat output of what happens when swiping the YubiKey?

innovate-invent commented 6 years ago

I can't seem to find a settings menu or anything that would allow me to save a log for your app.

pp3345 commented 6 years ago

logcat is an Android tool that dumps the system log output. If you have ADB (Android Debug Bridge, part of the Android SDK) installed and USB debugging is enabled on your device, you may grab the logcat output by typing adb logcat into a terminal. See https://developer.android.com/studio/command-line/logcat for more information.

Alternatively, you may first try the following version that uses a further increased NFC timeout: https://dev.pp3345.net/ykdroid-cd90092+-release-signed.apk Let me know if it works.

innovate-invent commented 6 years ago

Expecting an end user to set up a Android dev environment or figure out how to enable and manage 3rd party apk's is a little much.

If I have to do any of that I am just going to install an older version of Keepass.

pp3345 commented 6 years ago

You click onto the download link on your Android device and it will ask you whether you want to install the APK. On some devices you might also need to enable "Install apps from unknown sources" under Settings -> Security first.

matya commented 6 years ago

Hi, I have the same issue on a freshly updated LineageOS 15.1 (Android 8.1) on a Nexus 5x (bullhead).

Here are my logfiles with the error (I cut out quite some logfiles as they contain private data, hope this is enough, if not, give me a ping for the required content).

I/ActivityManager( 3778): Displayed net.pp3345.ykdroid/.ChallengeResponseActivity: +332ms
D/KP2A    (17999): GlobalLayout
D/KP2A    (17999): ActualHeight=1038
D/KP2A    (17999): ProposedHeight=1731
D/NativeNfcTag( 6442): Connect to a tech with a different handle
D/NativeNfcTag( 6442): Starting background presence check
I/ActivityManager( 3778): START u0 {act=android.nfc.action.TECH_DISCOVERED cmp=net.pp3345.ykdroid/.ChallengeResponseActivity (has extras)} from uid 10235
W/ActivityManager( 3778): startActivity called from non-Activity context; forcing Intent.FLAG_ACTIVITY_NEW_TASK for: Intent { act=android.nfc.action.TECH_DISCOVERED cmp=net.pp3345.ykdroid/.ChallengeResponseActivity (has extras) }
E/BrcmNfcJni( 6442): nativeNfcTag_doTransceive: wait response timeout
E/ykDroid (20946): Error during challenge-response request
E/ykDroid (20946): net.pp3345.ykdroid.yubikey.ConnectionLostException: android.nfc.TagLostException: Tag was lost.
E/ykDroid (20946):  at net.pp3345.ykdroid.yubikey.NfcYubiKey.challengeResponse(NfcYubiKey.java:68)
E/ykDroid (20946):  at net.pp3345.ykdroid.ChallengeResponseActivity$1.doInBackground(ChallengeResponseActivity.java:94)
E/ykDroid (20946):  at net.pp3345.ykdroid.ChallengeResponseActivity$1.doInBackground(ChallengeResponseActivity.java:88)
E/ykDroid (20946):  at android.os.AsyncTask$2.call(AsyncTask.java:333)
E/ykDroid (20946):  at java.util.concurrent.FutureTask.run(FutureTask.java:266)
E/ykDroid (20946):  at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)
E/ykDroid (20946):  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
E/ykDroid (20946):  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
E/ykDroid (20946):  at java.lang.Thread.run(Thread.java:764)
E/ykDroid (20946): Caused by: android.nfc.TagLostException: Tag was lost.
E/ykDroid (20946):  at android.nfc.TransceiveResult.getResponseOrThrow(TransceiveResult.java:48)
E/ykDroid (20946):  at android.nfc.tech.BasicTagTechnology.transceive(BasicTagTechnology.java:151)
E/ykDroid (20946):  at android.nfc.tech.IsoDep.transceive(IsoDep.java:172)
E/ykDroid (20946):  at net.pp3345.ykdroid.yubikey.NfcYubiKey.challengeResponse(NfcYubiKey.java:55)
E/ykDroid (20946):  ... 8 more
D/NativeNfcTag( 6442): Tag lost, restarting polling loop
D/NfcService( 6442): Discovery configuration equal, not updating.
D/NativeNfcTag( 6442): Stopping background presence check

[==8<==]

E/BrcmNfcJni( 6442): nativeNfcTag_doTransceive: wait response timeout
E/ykDroid (20946): Error during challenge-response request
E/ykDroid (20946): net.pp3345.ykdroid.yubikey.ConnectionLostException: android.nfc.TagLostException: Tag was lost.
E/ykDroid (20946):  at net.pp3345.ykdroid.yubikey.NfcYubiKey.challengeResponse(NfcYubiKey.java:68)
E/ykDroid (20946):  at net.pp3345.ykdroid.ChallengeResponseActivity$1.doInBackground(ChallengeResponseActivity.java:94)
E/ykDroid (20946):  at net.pp3345.ykdroid.ChallengeResponseActivity$1.doInBackground(ChallengeResponseActivity.java:88)
E/ykDroid (20946):  at android.os.AsyncTask$2.call(AsyncTask.java:333)
E/ykDroid (20946):  at java.util.concurrent.FutureTask.run(FutureTask.java:266)
E/ykDroid (20946):  at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)
E/ykDroid (20946):  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
E/ykDroid (20946):  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
E/ykDroid (20946):  at java.lang.Thread.run(Thread.java:764)
E/ykDroid (20946): Caused by: android.nfc.TagLostException: Tag was lost.
E/ykDroid (20946):  at android.nfc.TransceiveResult.getResponseOrThrow(TransceiveResult.java:48)
E/ykDroid (20946):  at android.nfc.tech.BasicTagTechnology.transceive(BasicTagTechnology.java:151)
E/ykDroid (20946):  at android.nfc.tech.IsoDep.transceive(IsoDep.java:172)
E/ykDroid (20946):  at net.pp3345.ykdroid.yubikey.NfcYubiKey.challengeResponse(NfcYubiKey.java:55)
E/ykDroid (20946):  ... 8 more
D/NativeNfcTag( 6442): Tag lost, restarting polling loop
D/NfcService( 6442): Discovery configuration equal, not updating.
D/NativeNfcTag( 6442): Stopping background presence check
E/BrcmNfcNfa( 6442): nfa_dm_act_deactivate (): invalid protocol, mode or state
pp3345 commented 6 years ago

@matya Thank you very much for your logs, they're indeed helpful. A YubiKey should, per specification, never take this long, but well, it seems that some NEOs are buggy. Could you please try the APK I've linked above (https://dev.pp3345.net/ykdroid-cd90092+-release-signed.apk) and report whether it works for you?

matya commented 6 years ago

Installed it, now I get a null pointer exception:

I/ActivityManager( 3778): START u0 {act=net.pp3345.ykdroid.intent.action.CHALLENGE_RESPONSE cmp=net.pp3345.ykdroid/.ChallengeResponseActivity (has extras)} from uid 10087
I/ActivityManager( 3778): Start proc 9185:net.pp3345.ykdroid/u0a235 for activity net.pp3345.ykdroid/.ChallengeResponseActivity
I/ActivityManager( 3778): START u0 {act=android.nfc.action.TECH_DISCOVERED cmp=net.pp3345.ykdroid/.ChallengeResponseActivity (has extras)} from uid 10235
W/ActivityManager( 3778): startActivity called from non-Activity context; forcing Intent.FLAG_ACTIVITY_NEW_TASK for: Intent { act=android.nfc.action.TECH_DISCOVERED cmp=net.pp3345.ykdroid/.ChallengeResponseActivity (has extras) }
E/ykDroid ( 9185): Error during challenge-response request
E/ykDroid ( 9185): java.lang.NullPointerException: Attempt to get length of null array
E/ykDroid ( 9185):  at net.pp3345.ykdroid.apdu.CommandApdu.build(CommandApdu.java:12)
E/ykDroid ( 9185):  at net.pp3345.ykdroid.yubikey.NfcYubiKey.challengeResponse(NfcYubiKey.java:60)
E/ykDroid ( 9185):  at net.pp3345.ykdroid.ChallengeResponseActivity$1.doInBackground(ChallengeResponseActivity.java:94)
E/ykDroid ( 9185):  at net.pp3345.ykdroid.ChallengeResponseActivity$1.doInBackground(ChallengeResponseActivity.java:88)
E/ykDroid ( 9185):  at android.os.AsyncTask$2.call(AsyncTask.java:333)
E/ykDroid ( 9185):  at java.util.concurrent.FutureTask.run(FutureTask.java:266)
E/ykDroid ( 9185):  at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)
E/ykDroid ( 9185):  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
E/ykDroid ( 9185):  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
E/ykDroid ( 9185):  at java.lang.Thread.run(Thread.java:764)
I/ActivityManager( 3778): START u0 {act=android.nfc.action.TECH_DISCOVERED cmp=net.pp3345.ykdroid/.ChallengeResponseActivity (has extras)} from uid 10235
W/ActivityManager( 3778): startActivity called from non-Activity context; forcing Intent.FLAG_ACTIVITY_NEW_TASK for: Intent { act=android.nfc.action.TECH_DISCOVERED cmp=net.pp3345.ykdroid/.ChallengeResponseActivity (has extras) }
E/ykDroid ( 9185): Error during challenge-response request
E/ykDroid ( 9185): java.lang.NullPointerException: Attempt to get length of null array
E/ykDroid ( 9185):  at net.pp3345.ykdroid.apdu.CommandApdu.build(CommandApdu.java:12)
E/ykDroid ( 9185):  at net.pp3345.ykdroid.yubikey.NfcYubiKey.challengeResponse(NfcYubiKey.java:60)
E/ykDroid ( 9185):  at net.pp3345.ykdroid.ChallengeResponseActivity$1.doInBackground(ChallengeResponseActivity.java:94)
E/ykDroid ( 9185):  at net.pp3345.ykdroid.ChallengeResponseActivity$1.doInBackground(ChallengeResponseActivity.java:88)
E/ykDroid ( 9185):  at android.os.AsyncTask$2.call(AsyncTask.java:333)
E/ykDroid ( 9185):  at java.util.concurrent.FutureTask.run(FutureTask.java:266)
E/ykDroid ( 9185):  at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)
E/ykDroid ( 9185):  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
E/ykDroid ( 9185):  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
E/ykDroid ( 9185):  at java.lang.Thread.run(Thread.java:764)
I/ActivityManager( 3778): Process net.pp3345.ykdroid (pid 9185) has died: cch+2CEM 
pp3345 commented 6 years ago

Did you invoke ykDroid through Keepass2Android or did you somehow (e.g. am start-activity) try to run ykDroid directly? This NPE shouldn't be caused by the changes in the new APK, but rather indicates that the challenge was missing. Maybe try to reselect the database in KP2A.

matya commented 6 years ago

It was called by KeePass, trying to open a DB and loading the OTP Auxiliary File. However, I now found that it did open it from cache. I closed it and reopened the .kdbx and browsed the .xml file also from google drive. Now it loads the yubikey's C-R and I managed to open the DB. It is strange. Nevertheless, I find it a little bit disturbing that is throws a nullpointer exception instead of an error message.

pp3345 commented 6 years ago

Nevertheless, I find it a little bit disturbing that is throws a nullpointer exception instead of an error message.

Yeah, me too. Will push a fix for that, too.

Apart from that, everything is working with the APK from above? Any further issues?

matya commented 6 years ago

Only when I use an USB-C OTG adapter and try to use that with touch-confirmed loading:

I/ActivityManager( 3778): START u0 {act=net.pp3345.ykdroid.intent.action.CHALLENGE_RESPONSE cmp=net.pp3345.ykdroid/.ChallengeResponseActivity (has extras)} from uid 10087
I/ActivityManager( 3778): Start proc 16997:net.pp3345.ykdroid/u0a235 for activity net.pp3345.ykdroid/.ChallengeResponseActivity
E/ykDroid (16997): Error during challenge-response request
E/ykDroid (16997): net.pp3345.ykdroid.yubikey.TimeoutException
E/ykDroid (16997):  at net.pp3345.ykdroid.yubikey.UsbYubiKey.waitForStatus(UsbYubiKey.java:249)
E/ykDroid (16997):  at net.pp3345.ykdroid.yubikey.UsbYubiKey.readResponse(UsbYubiKey.java:261)
E/ykDroid (16997):  at net.pp3345.ykdroid.yubikey.UsbYubiKey.challengeResponse(UsbYubiKey.java:160)
E/ykDroid (16997):  at net.pp3345.ykdroid.ChallengeResponseActivity$1.doInBackground(ChallengeResponseActivity.java:94)
E/ykDroid (16997):  at net.pp3345.ykdroid.ChallengeResponseActivity$1.doInBackground(ChallengeResponseActivity.java:88)
E/ykDroid (16997):  at android.os.AsyncTask$2.call(AsyncTask.java:333)
E/ykDroid (16997):  at java.util.concurrent.FutureTask.run(FutureTask.java:266)
E/ykDroid (16997):  at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)
E/ykDroid (16997):  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
E/ykDroid (16997):  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
E/ykDroid (16997):  at java.lang.Thread.run(Thread.java:764)

but this also makes me headaches, since it takes 3-4 iterations because android thinks it's a keyboard, and also ykDroid always keeps asking for permission to access the USB (Somehow Android does not remember that I check the "Use bt default for this USB device" choice), nor does it react when I repeadetly hit the button on it...

pp3345 commented 6 years ago

Somehow Android does not remember that I check the "Use bt default for this USB device" choice

Yes, this is somewhat buggy in Android, but sadly there is nothing ykDroid can do here.

nor does it react when I repeadetly hit the button on it...

If the LED of the YubiKey keeps blinking, that means the YubiKey didn't detect you pressed it. If the LED goes from blinking to steady green after you pressed it and it still timeouts, please open a new issue for that.

pp3345 commented 6 years ago

Thank you very much for your tests. I've pushed an update with a fix to Google Play that should appear in the Play Store shortly. Please feel free to open another issue if any further problems occur.