LedgerHQ / ledger-u2f-javacard

Java Card FIDO U2F authenticator for Ledger Unplugged
Apache License 2.0
70 stars 40 forks source link

Installation #11

Open Aiosa opened 4 years ago

Aiosa commented 4 years ago

Hello,

Is this project dead? I would like to try it out; some things don't go well though

1) outdated readme: the API for sdk has changed in v3.0.5, in the Readme you advise using 3.0.2 but the newest source code uses RandomData.nextBytes() and other 3.0.5+ API.

2) could you please be more specific on the installation process? I was unable to find out which certificate should I get (and where) to proceed.

Thank you!

jaredvacanti commented 4 years ago

Hi @Aiosa - any progress on this front?

Aiosa commented 4 years ago

Well, yes and no. I was able to change the code to compile with sdk 3.0.2-4, because to be honest, not many cards (neither mine) support v.5.

On the certificate, fortunately, there are other projects based on this one https://github.com/fightyz/U2FToken https://github.com/tsenger/CCU2F

which are more friendly with providing an examples on the certificate. One thing is to say "upload a certificate", another is to know in which format(x509?), whether it has to/can be self-signed, raw (yeah at least here it is more or less obvious it will be raw) or pem...?

And lastly, I got stuck again, because after successful installation, I am unable to finish the personalisation proces, because

error: card returned 6881 (logical channel not supported)

I tried (with the test key/certificate from the other projects) to upload the certificate both part-by-part and at once:

F0010000803082013c3081e4a003020102020a47901280001155957352300a06082a8648ce3d0403023017311530130603550403130c476e756262792050696c6f74301e170d3132303831343138323933325a170d3133303831343138323933325a3031312f302d0603550403132650696c6f74476e756262792d302e342e312d34373930

F00100000001403082013c3081e4a003020102020a47901280001155957352300a06082a8648ce3d0403023017311530130603550403130c476e756262792050696c6f74301e170d3132303831343138323933325a170d3133303831343138323933325a3031312f302d0603550403132650696c6f74476e756262792d302e342e312d34373930313238303030313135353935373335323059301306072a8648ce3d020106082a8648ce3d030107034200048d617e65c9508e64bcc5673ac82a6799da3c1446682c258c463fffdf58dfd2fa3e6c378b53d795c4a4dffb4199edd7862f23abaf0203b4b8911ba0569994e101300a06082a8648ce3d0403020347003044022060cdb6061e9c22262d1aac1d96d8c70829b2366531dda268832cb836bcd30dfa0220631b1459f09e6330055722c8d89b7f48883b9089b88d60d1d9795902b30410df

Since the applet supports extended length, but the result was the same in both cases. Somewhere I found that the low 2 CLA bits specify the logical channel to use (e.g. 0/1/2/3) so I tried sending the install and apdu commands with CLA of _3 (F30100..) and got an error too (I think the same, but I am not sure, maybe it could also throw unsupported CLA, at least this is something I would expect).

I would've tried another card, but unfortunately, I have only one with 3.0.2+ SDK support availab.e (NXP JCOP 3 J3H145 P60).

Thanks

darconeous commented 4 years ago

Do we know specifically what API calls are being done that require JC >= 3.0.2? Those API calls might have replacements that will work with older cards.

jaredvacanti commented 4 years ago

When I try to build the current project I get these errors:

[ant:compile] /home/jared/dev/smartcards/ledger-u2f-javacard/src/main/java/com/ledger/u2f/FIDOStandalone.java:49: error: cannot find symbol
[ant:compile]         random = RandomData.getInstance(RandomData.ALG_KEYGENERATION);
[ant:compile]                                                   ^
[ant:compile]   symbol:   variable ALG_KEYGENERATION
[ant:compile]   location: class RandomData
[ant:compile] /home/jared/dev/smartcards/ledger-u2f-javacard/src/main/java/com/ledger/u2f/FIDOStandalone.java:52: error: cannot find symbol
[ant:compile]         random.nextBytes(scratch, (short) 0, (short) 32);
[ant:compile]               ^
[ant:compile]   symbol:   method nextBytes(byte[],short,short)
[ant:compile]   location: variable random of type RandomData
[ant:compile] 2 errors

> Task :buildJavaCard
[ant:cap] INFO: using JavaCard v3.x SDK in /home/jared/dev/smartcards/ledger-u2f-javacard/libs-sdks/jc304_kit
[ant:cap] Building CAP with 1 applet from package com.ledger.u2f
[ant:cap] com.ledger.u2f.U2FApplet A000000617004F97A2E94901
[ant:compile] Compiling 5 source files to /tmp/jccpro3059367291626440409

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':buildJavaCard'.
> Compile failed; see the compiler error output for details.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

BUILD FAILED in 4s
1 actionable task: 1 executed

My current environment:

$ java -version
openjdk version "1.8.0_242"
OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_242-b08)
OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.242-b08, mixed mode)

$ uname -a
Linux jared-ubuntu 5.3.0-40-generic #32-Ubuntu SMP Fri Jan 31 20:24:34 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

I'm at least able to get the previous FIDO2 certified branch (https://github.com/LedgerHQ/ledger-u2f-javacard/tree/u2f-certif-171215) to build successfully. I have a spare card with Java Card 2.2.2 and Global Platform 2.1.1. Installing on the card fails however.

Aiosa commented 4 years ago

I am not sure if @jaredvacanti answered to your question about those calls but yup, the errors he's getting are from wrong sdk version. For both (ALG_KEYGENERATION and nextBytes()) you need sdk of 3.0.5.

generateData(byte[] buffer, short offset, short length) Deprecated. As of release 3.0.5, replaced by nextBytes(byte[], short, short).

public static final byte ALG_KEYGENERATION This algorithm creates random numbers suitable to be used for key and nonce generation. The security level and the standards conformance of this algorithm is implementation dependant.

Since: 3.0.5

https://docs.oracle.com/javacard/3.0.5/api/javacard/security/RandomData.html

Now I remembered that I am not sure whether I modified the code or grabbed some previous version release in other to compile with 3.0.2... I am positive about the latter as I am not sure how I would replace ALG_KEYGENERATION... pretty crucial feature.. probably ALG_SECURE_RANDOM is the way to go

Aiosa commented 4 years ago

Any ideas on why the card returns 0x6881 when uploading the certificate? I checked that it's not something thrown by code (e.g. command should be valid), I modified the two lines of latest version in order to compile with SDK below 3.0.5 and still the same.

darconeous commented 4 years ago

FYI: I've got my own fork now that works pretty well. It seems to work fine on a 3.0.1 JC, and has some additional features like multiple counters, etc... Commits are well documented: https://github.com/darconeous/u2f-javacard/commits/master

darconeous commented 4 years ago

By the way, I would change PROPRIETARY_CLA to something like 0x80, recompile/load that, and then change the first byte of all of your provisioning commands to 80 instead of F0. I'd also cherry-pick #13, too.

Or just use my fork (Pre-compiled cap can be found here), which has both of those changes as well as and iOS compatibility and multiple counters.

Here is a gist with an installer script that you can use with GlobalPlatformPro:

https://gist.github.com/darconeous/adb1b2c4b15d3d8fbc72a5097270cdaf

Aiosa commented 4 years ago

Will definitelly check out :) I also forgot to mention the problem I was having with the 'bad logical channel' was not just with this project, but also with the other projects derived from this one (links above). Hope your's will work :)

jaredvacanti commented 4 years ago

I was able to successfully install the pre-compiled cap file using the gist of the installer script onto a NXP J3H145 Dual Interface Java card - 144k (3B DC 18 FF 81 91 FE 1F C3 80 73 C8 21 13 66 05 03 63 51 00 02 50).

There were a few warnings (e.g. [WARN] PlaintextKeys - Don't know how to calculate KCV, defaulting to SCP02) but otherwise installed successfully. I have the complete installation logs here: https://gist.github.com/jaredvacanti/f8e3591815b45a28d26beecc523a561e

Should this card then be testable with services like https://demo.yubico.com/webauthn-technical/registration or http://u2fdemo.appspot.com/ with this applet installed? I am using a ISO 7816/14443 form factor, but both sites ask me to press the button on the device. It was mentioned on the FIDO-DEV list a while ago that the insertion of the card could replace the touch action. Is that possible?

darconeous commented 4 years ago

I assume you are asking about my fork:

I was able to successfully install the pre-compiled cap file using the gist of the installer script onto a NXP J3H145 Dual Interface Java card

Yep, that's the chip/card I used to build my authentication ring.

There were a few warnings (e.g. [WARN] PlaintextKeys - Don't know how to calculate KCV, defaulting to SCP02) but otherwise installed successfully.

Warnings like that have to do with your card and the way you are using GP. You will get that warning loading any app.

I have the complete installation logs here: https://gist.github.com/jaredvacanti/f8e3591815b45a28d26beecc523a561e

I had a look, and it looks good!

Should this card then be testable with services like https://demo.yubico.com/webauthn-technical/registration or http://u2fdemo.appspot.com/ with this applet installed?

Yes. The easiest way to use it with those services is to use either an Android phone or a iPhone 7 (or later) running iOS 13. In those cases once you go to the site you should be able to tap the card to the back of the phone and it should work. On iOS, it may take a few taps to register due to a bug in iOS that will cause 25% of registration taps to fail. After a few taps it will catch and register. Authentications should always work.

If you use a Mac, you can use this hack I wrote to allow you to use the card as a U2F token with any browser (Safari, Chrome, Firefox, etc). It works very well for me.

There is a chance that the U2F applet may "just work" with recent versions of Windows and a smart card reader (either contact or contactless), but I haven't tried.

I haven't looked into how to use it on Linux.

darconeous commented 4 years ago

It was mentioned on the FIDO-DEV list a while ago that the insertion of the card could replace the touch action. Is that possible?

Yes, that is how this this applet (the original and the derivatives) is set up to work—although technically it is one "touch action" (called a "user presence test") per card reset rather than insertion. That's the best that can be done for a contact device without using proprietary APIs.

jaredvacanti commented 4 years ago

Thanks for the really great, comprehensive work and feedback. I am testing on an iPhone 7 on 13.3.1, but the card won't register after tens of attempts when using the https://demo.yubico.com/webauthn-technical/registration endpoint, although the Yubikey 5 NFC works straight away on each attempt.

I'm going to attempt your solution on the Mac with the Xcode project to see if there is any issue with the card itself or the installation - hopefully I can get some interaction (nothing yet on iOS or LInux).

darconeous commented 4 years ago

Thanks for the really great, comprehensive work and feedback.

No problem!

I am testing on an iPhone 7 on 13.3.1, but the card won't register after tens of attempts when using the https://demo.yubico.com/webauthn-technical/registration endpoint, although the Yubikey 5 NFC works straight away on each attempt.

Interesting. Do you know if your card was pre-personalized to be 14443-A ("NFC Type A") or 14443-B ("NFC Type B")? If it is pre-personalized for Type-B, then you are going to be out of luck on iOS and Android. Both iOS and Android require Type-A FIDO tokens, and refuse to work with Type-B FIDO tokens for some reason.

But even if it is Type-B, you should still be able to use it with my hack on macOS. If not, at least you will get some useful logs that might help identify what is going wrong.

I'm going to attempt your solution on the Mac with the Xcode project to see if there is any issue with the card itself or the installation - hopefully I can get some interaction (nothing yet on iOS or LInux).

Yeah, let me know. The hack is very chatty and logs a lot. And feel free to file an issue over there (or even on my U2F fork) if you run into problems.

Aiosa commented 4 years ago

Good, installed and personalised successfully :) did not try to use yet but it seems the F0 APDU was the problem. You could reflect this change in README too :) Added this repo to enigma (awaits pull request).

jaredvacanti commented 4 years ago

I'm still trying to debug further on a Mac, but I have checked that the card's manufacturer part is the NXP SmartMX2 SECID P60D144. The specsheet (available here) states that it uses:

• ISO/IEC 14443 Type A contactless interface unit optimized also for small antenna dimensions

Could the card be manufactured for Type A but personalized for Type B, or is this only a hardware/manufacturer level issue?

darconeous commented 4 years ago

Derp, looks like that chip only does 14443A. Some chips can do both, but it looks like this one doesn’t. There goes that theory. Hmm.

Can you get the ATS value? I’ll see if I can scrape up a iPhone 7 and see if it behaves differently.

jaredvacanti commented 4 years ago

Aha! It does seem like this identifies itself with Type (B) somehow when using contactless, due to the possible detection value listed here (ISO 14443 Type B without historical bytes), when used over RFID/NFC:

Sat Apr 11 19:00:24 2020
 Reader 2: Identiv uTrust 3700 F CL Reader [uTrust 3700 F CL Reader] (55021921203314) 00 00
  Event number: 53
  Card state: Card inserted, 
  ATR: 3B 80 80 01 01

ATR: 3B 80 80 01 01
+ TS = 3B --> Direct Convention
+ T0 = 80, Y(1): 1000, K: 0 (historical bytes)
  TD(1) = 80 --> Y(i+1) = 1000, Protocol T = 0 
-----
  TD(2) = 01 --> Y(i+1) = 0000, Protocol T = 1 
-----
+ Historical bytes: 
+ TCK = 01 (correct checksum)

Possibly identified card (using /home/jared/.cache/smartcard_list.txt):
3B 80 80 01 01
    ISO 14443 Type B without historical bytes
    Electronic Passport
    Spanish passport (2012)
    Canadian Passport
    Venez_Prox

Sat Apr 11 19:00:36 2020
 Reader 2: Identiv uTrust 3700 F CL Reader [uTrust 3700 F CL Reader] (55021921203314) 00 00
  Event number: 54
  Card state: Card removed, 

When I read the same card over contact:

Sat Apr 11 19:02:55 2020
 Reader 3: FEITIAN iR301 01 00
  Event number: 12
  Card state: Card inserted, 
  ATR: 3B DC 18 FF 81 91 FE 1F C3 80 73 C8 21 13 66 05 03 63 51 00 02 50

ATR: 3B DC 18 FF 81 91 FE 1F C3 80 73 C8 21 13 66 05 03 63 51 00 02 50
+ TS = 3B --> Direct Convention
+ T0 = DC, Y(1): 1101, K: 12 (historical bytes)
  TA(1) = 18 --> Fi=372, Di=12, 31 cycles/ETU
    129032 bits/s at 4 MHz, fMax for Fi = 5 MHz => 161290 bits/s
  TC(1) = FF --> Extra guard time: 255 (special value)
  TD(1) = 81 --> Y(i+1) = 1000, Protocol T = 1 
-----
  TD(2) = 91 --> Y(i+1) = 1001, Protocol T = 1 
-----
  TA(3) = FE --> IFSC: 254
  TD(3) = 1F --> Y(i+1) = 0001, Protocol T = 15 - Global interface bytes following 
-----
  TA(4) = C3 --> Clock stop: no preference - Class accepted by the card: (3G) A 5V B 3V 
+ Historical bytes: 80 73 C8 21 13 66 05 03 63 51 00 02
  Category indicator byte: 80 (compact TLV data object)
    Tag: 7, len: 3 (card capabilities)
      Selection methods: C8
        - DF selection by full DF name
        - DF selection by partial DF name
        - Implicit DF selection
      Data coding byte: 21
        - Behaviour of write functions: proprietary
        - Value 'FF' for the first byte of BER-TLV tag fields: invalid
        - Data unit in quartets: 2
      Command chaining, length fields and logical channels: 13
        - Logical channel number assignment: by the card
        - Maximum number of logical channels: 4
    Tag: 6, len: 6 (pre-issuing data)
      Data: 05 03 63 51 00 02
+ TCK = 50 (correct checksum)

Possibly identified card (using /home/jared/.cache/smartcard_list.txt):
3B DC 18 FF 81 91 FE 1F C3 80 73 C8 21 13 66 05 03 63 51 00 02 50
    JCOP3 SecID P60 CS (JavaCard)
darconeous commented 4 years ago

You can't trust the "ATR" that you see from a contactless card reader that emulates CCID. At best, it is massaging the bits from the ATS to somewhat fit into an ATR. At worst it may just be making it up. So I wouldn't read too much into that.

Getting ahold of the real ATS (the NFC Type-A equivalent to the ATR) can be a little tricky without an android phone handy. If you have an android phone handy, use NXP's TagInfo app. It is wonderful.

Does your reader work with libnfc? If it does, then you can use the nfs-list command to get the actual ATS, along with other info.

jaredvacanti commented 4 years ago

And feel free to file an issue over there (or even on my U2F fork) if you run into problems.

Issues aren't currently enabled on this fork. Would you consider enabling them? I've installed the branch successfully from Linux and have used it on a Mac, but so far have not been able to use it from Linux or iOS.