github-af / SmartPGP

SmartPGP is a JavaCard implementation of the OpenPGP card specifications
GNU General Public License v2.0
232 stars 48 forks source link

Key import fail with "Invalid value" error #15

Closed breard-r closed 5 years ago

breard-r commented 5 years ago

Hello,

After a few tests with SmartPGP, I found out that RSA 2048 key works well, but not NIST P-384. This problem affects both on-card key generation and the upload of computer-generated ones. My card is an ACOS-J, which does support ECC up to 384 bits. I do not have any other card to test against.

$ gpg --card-edit
[…]
Key attributes ...: rsa2048 rsa2048 rsa2048
[…]
gpg/card> generate
[…]
public and secret key created and signed.
$ gpg --card-edit
[…]
Key attributes ...: nistp384 nistp384 nistp384
[…]
gpg/card> generate
[…]
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
Key generation failed: Invalid value
$ gpg --homedir .gnupg --expert --edit-key test@example.com
[…]
gpg> keytocard
Please select where to store the key:
   (1) Signature key
   (3) Authentication key
Your selection? 1
gpg: KEYTOCARD failed: Invalid value

Edit: As stated below the problem is with key import, not ECC.

af-anssi commented 5 years ago

Could you test if NIST P-256 is working ? In case it fails, could you dump the APDUs exchanged (pcscd -a -f -d) ? (Be careful, it will expose the PIN code and private keys, so do not use real values, just default/test ones !)

breard-r commented 5 years ago

Could you test if NIST P-256 is working ?

It doesn't work either. I also tested brainpoolP256r1, same thing.

Here is the output of pcscd -a -f -d: https://0bin.net/paste/4yU7tzLVMmQPfghw#tsWL77BBeBTVZ7pJXcui4j3NcaWwz+YsBeRrUgQW2aa And the command I ran during this session: https://0bin.net/paste/VpDT1pmBkmMZh2BF#ctQpubicuFIodtkaIMN3SSubm8GtuItCJOHu4AqIb8i

Fun fact: after failing (for every ECC), I see it generated keys for signature and authentication but not for encryption. The signature counter is also incremented by 2. Here is what I got after the above session:

$ gpg --homedir .gnupg --expert --card-edit

Reader ...........: Gemalto PC Twin Reader (362E4E86) 00 00
Application ID ...: D276000124010303FF420E9805CC0000
Version ..........: 3.3
Manufacturer .....: unmanaged S/N range
Serial number ....: 0E9805CC
Name of cardholder: [not set]
Language prefs ...: en
Sex ..............: unspecified
URL of public key : [not set]
Login data .......: [not set]
Signature PIN ....: forced
Key attributes ...: nistp384 nistp384 nistp384
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 2
Signature key ....: CB5F DC17 7FFD 05EF 6FE9  B289 3642 29A6 2C0B 25F6
      created ....: 2018-12-04 18:05:24
Encryption key....: [none]
Authentication key: 6C9A 821D 06CE 33EF 1C40  C406 6BE0 115A E992 99C4
      created ....: 2018-12-04 18:05:24
General key info..: [none]
af-anssi commented 5 years ago

From what I see in the APDU exchanges, the problem arrises during key import

00000021 APDU: 00 DB 3F FF 3C 4D 3A B8 00 7F 48 02 92 30 5F 48 30 CC 3C BD 33 42 A4 6B 2A EF 35 15 DA BD 59 36 CE 78 4B 05 58 97 F7 BD 0C A7 BB 2D 0F 73 AA 5A 14 9C 1A 54 44 9D DA D3 BF 54 90 A8 32 32 95 22 F8 
00000009 ifdhandler.c:1303:IFDHTransmitToICC() usb:08e6/3437:libudev:0:/dev/bus/usb/002/004 (lun: 0)
01168985 SW: 6A 80 

Indeed, when the user says Yes to the question "Make off-card backup of encryption key? (Y/n)", the encryption key is generated outside the card, and then imported, which actually fails for an unknown reason yet.

Could you please retry without answering Yes to this question to be sure the problem is really the key import process ?

breard-r commented 5 years ago

You are right, the problem isn't with ECC but with the key import. Generating keys on the card without the backup does works.

af-anssi commented 5 years ago

Ok thank you. Key import was working on my other cards, so maybe it is related to gnupg. Could you tell me which version of gnupg and scdaemon you are using ? I will investigate the problem on my side as much as possible.

breard-r commented 5 years ago

Sure, here is the versions:

$ gpg --version
gpg (GnuPG) 2.2.11
libgcrypt 1.8.4
[…]
$ /usr/lib/gnupg/scdaemon --version
scdaemon (GnuPG) 2.2.11
libgcrypt 1.8.4
libksba 1.3.5
[…]

Thank you very much for your time!

af-anssi commented 5 years ago

In the key import command, only the private part (tag 92 in the APDU command) is provided by gnupg, not the public part (tag 99 in the APDU command). The public part is actually optional in the OpenPGP card specification (page 34), and gnupg seems not to provide it and it seems this card does not support this. I have updated the TestApplet to include a static key test without providing the public part ("... without W").

af-anssi commented 5 years ago

Sorry, I forgot that there is a solution. Gnupg can provide public key during key import if the last byte for the key attribute is set to 0xFF (specification page 31). The smartpgp-cli tool forces the last byte to be set accordingly when it switches: https://github.com/ANSSI-FR/SmartPGP/blob/aeea3fed4216a3aba15bb005dcd58f38180acb31/bin/smartpgp/commands.py#L202

Which tool did you use to switch your card to NIST-P384 ? Is the last byte of the key attributes set to 0xFF ?

af-anssi commented 5 years ago

From what I see in the response to the command get APPLICATION_RELATED_DATA

00000004 APDU: 00 CA 00 6E DC 
00000005 ifdhandler.c:1303:IFDHTransmitToICC() usb:08e6/3437:libudev:0:/dev/bus/usb/002/004 (lun: 0)
00235517 SW: 6E 81 D9 4F 10 D2 76 00 01 24 01 03 03 FF 42 0E 98 05 CC 00 00 5F 52 0A 00 C1 C5 73 C0 01 80 05 90 00 73 81 B7 C0 0A FF 03 00 20 04 80 00 FF 00 00 C1 06 13 2B 81 04 00 22 C2 06 12 2B 81 04 00 22 C3 06 13 2B 81 04 00 22 C4 07 01 7F 7F 7F 03 00 03 C5 3C CB 5F DC 17 7F FD 05 EF 6F E9 B2 89 36 42 29 A6 2C 0B 25 F6 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 6C 9A 82 1D 06 CE 33 EF 1C 40 C4 06 6B E0 11 5A E9 92 99 C4 C6 3C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 CD 0C 5C 06 C1 E4 00 00 00 00 5C 06 C1 E4 90 00 

the key attributes are set to the OID of ansix9p384r1 but without the additional 0xFF byte at the end:

Without the additional 0xFF byte at the end of those OIDs, gnupg will not send the optional public part of the EC key, which can fail on some cards like this one. Could you retry after switching to NISTP384 with smartpgp-cli and tell me if everything is OK then ?

breard-r commented 5 years ago

and it seems this card does not support this

It makes a lot of things this card doen't support, too bad it is the only JavaCard 3.0.4 card I found :/

Which tool did you use to switch your card to NIST-P384 ?

GnuPG, with gpg --card-edit and then key-attr in admin mode.

Could you retry after switching to NISTP384 with smartpgp-cli and tell me if everything is OK then ?

I just tested and it works! Thank you a lot! :) I guess I should suggest to the GnuPG maintainer they change the default behavior in order to add this extra 0xFF byte so people won't have similar troubles.