Key generation with Nitrokey Start on Debian buster fails / RSA4096

Dear all,

Many thanks for your product and support.

I’m trying to use Nitrokey Start on Debian Buster.
I would like to use on different tokens different keys (RSA4096 and ECC NIST256).

I found that I had to add OpenSC0.20. Obviously i’m also facing the pb with the scdaemon but i’m ok to run a script if i want to use gpg2 or to removeand insert the token if i want to use openpgp-tool or any pkcs1x solution.

I was able to create ECC NIST256 keys through gpg2. But I was not able to create ECC NIST256 keys through pkcs11-tool. I got an GNPUK error saying that RSA keys longer than 2048 is forbidden.
OPENSC_DEBUG=9 pkcs11-tool --module /usr/lib/opensc-pkcs11.so -l --keypairgen --key-type EC:secp256r1 --id 1 --label "RootCA" --usage-sign

I can’t remember where I saw a clue saying that I have to set RSA4096 first in gpg2.
So I tried to did it. But I’m not able to create the keys with gpg2.

When I tried to use
pkcs15-init --delete-objects privkey,pubkey --id 1 --generate-key rsa/4096 --auth-id 3 --verify
I got the following error : failed to generate Key : Invalid arguments.
and in addition Unknown algorithm.

If I try
pkcs11-tool --module /usr/lib/x86_64-linux-gnu/opensc-pkcs11.so -l --keypairgen --key-type rsa:4096 --id 1

I get rv=CKR_ARGUMENTS_BAD.

After all this attempts i’m a little bit lost.
Any help will be welcomed.

Many thanks in advance and I wish you a pleasant day.

Best regards.

Hi @PhilC!

Thank you for using Nitrokey Start.
As far as I remember it is not possible to generate the RSA4096 key on the NK Start due to hardware limitations (both calculation time and memory), so one needs to generate it first, ideally (for production use) on the air-gapped diskless hardware, and then upload it to the device. It is possible to do so by e.g.:

  1. Booting PC up with Tails;
  2. Running GnuPG2, and generating the key locally;
  3. Running gpg2 --card-edit, then executing keytocard command;

Details for point 3 could be found here: https://www.nitrokey.com/documentation/openpgp-create-backup.

NK Start’s strength are rather ECC keys, with efficient implementation of popular curves.

Have a nice weekend!
Regards.

Hi @szszszsz,

Many thanks for your prompt answer.
I will test this evening.

And regarding pkcs11-tool and ECC NISTP256 key generation do you have any pointer ?

Because when I created the ECC through gpg2, pkcs11-tool complians afterward that some parameters where missing. So I coonclude that I have to create it first with pkcs-11-tool or pkcs15-init.

Have a nice week-end too.

Regards.

It’s possible this is not handled properly through OpenSC. Could you show the commands invocation and their debug log from the execution?

@nitroalex: Any ideas?

Hi @szszszsz,

Sorry for the delay.
I planned to use RSA4096 with a Nitrokey Start token for a Certification Authority. Since i had to generate the key outside of the token, I changed my mind and created a full offline CA without token. Then this token will be devoted for another IPSEC user. Many thanks for your help and support for this point and sorry if I changed my mind. I hope your answer will help someone else.

Regarding ECC keys, I was able, and it’s easy like ABC, to generate a ECC signing key, a RSA 2048 cipher key and ECC authentication key with the Nitrokey Start token.
My trouble came just after.

The keys exits.
Pkcs15-tool -D

gives

Private EC Key [Signature key]
	Object Flags   : [0x03], private, modifiable
	Usage          : [0x20C], sign, signRecover, nonRepudiation
	Access Flags   : [0x1D], sensitive, alwaysSensitive, neverExtract, local
	FieldLength    : 0
	Key ref        : 0 (0x00)
	Native         : yes
	Auth ID        : 01
	ID             : 01
	MD:guid        : bf1d1c6e-5a08-6cae-5379-fb04034dfe41

Private RSA Key [Encryption key]
	Object Flags   : [0x03], private, modifiable
	Usage          : [0x22], decrypt, unwrap
	Access Flags   : [0x1D], sensitive, alwaysSensitive, neverExtract, local
	ModLength      : 2048
	Key ref        : 1 (0x01)
	Native         : yes
	Auth ID        : 02
	ID             : 02
	MD:guid        : 835bcf57-4391-e359-50c6-75b32ac6cb67

Private EC Key [Authentication key]
	Object Flags   : [0x03], private, modifiable
	Usage          : [0x222], decrypt, unwrap, nonRepudiation
	Access Flags   : [0x1D], sensitive, alwaysSensitive, neverExtract, local
	FieldLength    : 0
	Key ref        : 2 (0x02)
	Native         : yes
	Auth ID        : 02
	ID             : 03
	MD:guid        : fdb57137-ef9c-3eb3-9194-76776622d509

Then I follow the guideline for IPSEC and ran the following commands.

OpenSSL> engine dynamic -pre SO_PATH:/usr/lib/x86_64-linux-gnu/engines-1.1/pkcs11.so -pre ID:pkcs11 -pre LIST_ADD:1 -pre LOAD -pre MODULE_PATH:/usr/lib/x86_64-linux-gnu/pkcs11/opensc-pkcs11.so
(dynamic) Dynamic engine loading support
[Success]: SO_PATH:/usr/lib/x86_64-linux-gnu/engines-1.1/pkcs11.so
[Success]: ID:pkcs11
[Success]: LIST_ADD:1
[Success]: LOAD
[Success]: MODULE_PATH:/usr/lib/x86_64-linux-gnu/pkcs11/opensc-pkcs11.so
Loaded: (pkcs11) pkcs11 engine

OpenSSL> req -engine pkcs11 -sha256 -new -key 01 -keyform engine -out SigningKeyCsr.pem -outform PEM -subj '...Blabla...'
engine "pkcs11" set.
Enter PKCS#11 token PIN for OpenPGP card (User PIN):
Key not found.
PKCS11_get_private_key returned NULL
cannot load Private Key from engine
140501148918912:error:80067065:pkcs11 engine:ctx_load_privkey:object not found:eng_back.c:862:
140501148918912:error:26096080:engine routines:ENGINE_load_private_key:failed loading private key:../crypto/engine/eng_pkey.c:78:
unable to load Private Key
error in req

I saw that gpgsm could generate CSR, so I will try this way and provide the answer afterwards.

Kind regards.

Unfortunately, I am not able to create the CSR with gpgsm.
Version used :
gpgsm (GnuPG) 2.2.12
libgcrypt 1.8.4
libksba 1.3.5-unknown

I launched the command
gpgsm --generate-key --output SigningKeyCsr.pem

These are my selections

> Selection of Key : : 3 - Key existing in the token.
Available keys : 
   (1) 0326DA57889968681EA29446CE9E324427A8B5B2 OPENPGP.1
   (2) F51F54DDCBDE64F4D1E32B19B11D8149D073AD3E OPENPGP.2
   (3) DB70D221E1B6307542DD0A05E62F5537C39FEEC4 OPENPGP.3

Select 1 

Action for your RSA keys : 
  1. Sign and Cipher
  2. Sign
  3. Cipher

well, it look strange to have RSA key, since I have an ECC key. But I continued and select 2) Sign.

And I received after some few exchanges :

gpgsm: error setting the siginfo: Wrong public key algorithm
gpgsm: error creating certificate request: Wrong public key algorithm <GpgSM>  

I’m still digging …

Kind regards.

So here are some results or comments.

I tried to decode the log of the command :

OPENSC_DEBUG=9 openssl req -engine pkcs11 -sha256 -new -key 01 -keyform engine -out SigningKeyCsr.pem -outform PEM -subj '...blabla...'

The ATR analysis seems very long and should be optimised, but it’s not the problem.

Once the OpenPGP card module found , there are some exchanges with the card. OK.
But it sounds strange to have a GET DATA HistoricalBytes and after a GET DATA ApplicationRelatedData. As far as I have seen, HistoricalBytes must be in ApplicationRelatedData for an openPGP card. Since i’m not familiar with topics, there should be an explanation.

In the trace, we could find :

P:4245; T:0x139913859376256 11:55:16.167 [opensc-pkcs11] pkcs15-pubkey.c:1159:sc_pkcs15_dup_pubkey: named_curve parameter missing
P:4245; T:0x139913859376256 11:55:16.167 [opensc-pkcs11] pkcs15-pubkey.c:1174:sc_pkcs15_dup_pubkey: returning with: -1408 (Not supported)

This trace is also strange, since during the ApplicationRelatedData, we got:

  4F 10 D2 76 00 01 24 01 02 00 FF FE 67 09 33 52 O..v..$.....g.3R
00 00 5F 52 0A 00 31 84 73 80 01 80 05 90 00 73 .._R..1.s......s
81 BD C0 0A 74 00 00 20 08 00 00 FF 01 00 C1 09 ....t.. ........
13 2A 86 48 CE 3D 03 01 07 C2 06 01 08 00 00 20 .*.H.=......... 
00 C3 09 13 2A 86 48 CE 3D 03 01 07 C4 07 00 7F ....*.H.=.......
7F 7F 03 03 03 C5 3C 9F 9E A6 64 67 F0 D4 C5 E9 ......<...dg....
EE FE F1 F8 4E B3 B7 D1 F0 B7 30 D0 DF CB 05 C1 ....N.....0.....
3A F7 31 6C 1B CF B7 C9 6B 91 2B 5D A0 6D 73 A4 :.1l....k.+].ms.
3E 4F F6 AD DE 6C 9F 96 06 41 59 C9 B3 7B B6 02 >O...l...AY..{..
31 1D 8A C6 3C 00 00 00 00 00 00 00 00 00 00 00 1...<...........
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 5E 9A DA 5F 5E 9A DA 5F 5E 9A DA 5F 90 ...^.._^.._^.._.
00                             

And if we decode :

4F : Full AID
	10 : Length
		D276000124010200FFFE670933520000

5F52 : Historical Bytes
	0A : Length 
		00318473800180059000

73 : Discretionary data objects
	81 : Length on 1 byte : BD

	C0 : Extended Capabilities
		0A : Length 
			 74 00 00 20 08 00 00 FF 01 00 
	C1 : Algorithm Attributes signature
		09 : length
			 13 2A 86 48 CE 3D 03 01 07 => 0x13 = 19 : ECDSA. OID for NIST curve 
	C2 : Algorithm decryption
		06 : Length
			 01 08 00 00 20 00

	C3 : Algorithm attributes authentication
		09 : length 
			 13 2A 86 48 CE 3D 03 01 07  => 0x13 = 19 : ECDSA. OID for NIST curve 

	C4 PW Status Bytes
		07:length
			00 7F	7F 7F 03 03 03


	C5 : fingerprints
		3C : Length
		 9F9EA66467F0D4C5E9EEFEF1F84EB3B7D1F0B730
		 D0DFCB05C13AF7316C1BCFB7C96B912B5DA06D73
		 A43E4FF6ADDE6C9F96064159C9B37BB602311D8A


	C6 : List of CA-Fingerprints
		 3C : Length
			000   

CD : List of generation dates/times

Afterward, I’m a little bit disappointed, to see that the VERIFY command is not protected.
Moreover, we can found in the trace the user pin in clear !

I guess and hope that it will be corrected at the very next release,

And then no more exchanges with the card, and finally got :

 Key not found.
PKCS11_get_private_key returned NULL
cannot load Private Key from engine
139862395589760:error:80067065:pkcs11 engine:ctx_load_privkey:object not found:eng_back.c:862:
139862395589760:error:26096080:engine routines:ENGINE_load_private_key:failed loading private key:../crypto/engine/eng_pkey.c:78:
unable to load Private Key

I found this a little bit strange, since I believed that we will try to sign a buffer with the token in order to get the CSR.

1°) Could you confirm my assumption ?
Because, if the problem comes from pkcs15 or pkcs11 and the if the card content is OK, then I should be able to make a workaround with some scripts to create the CSR, and wait for the official update afterward.

2°) If I have correctly overviewed the openPGP card specification, it seems that only ECDSA is supported. do you know why ECDH is not supported ?

Many thanks in advance for your help and support.

Best regards.

1 Like

Hi @PhilC!

Sorry for the delay.
Thank you for the elaborate description! We will take a look into this. I am a bit worried Nitrokey Start is not up for this task, as its implementation for OpenPGP 2.x might be incomplete, but I hope there would be some workaround. It would be good to test this with OpenPGP 3.x based Nitrokey Pro 2 first as well.

I apologize about not mentioning the PIN being logged in the debug log. You are of course right about showing at least a warning to the user about this, if not masking it completely - will mention this to the OpenSC development team.

Created ticket OpenSC#2014.

Hi @szszszsz,

No worries for delay or whatever.
Would you mind clarifying what you are meaning with the following sentence ?

Is it linked to the fact that Nitrokey Start is not tamper responsive ? Or limited to AES128 ?
Or something else ?

Many thanks for your answers.

Have a great and pleasant day.

PS : I don’t know how to change the title of this ticket, it migh be interesting for other readers to add a reference to ECC too.

Best regards.

I thought mostly about the implementation details here - that some OpenSC tools might not work correctly.
Another point is being not tamper-resistant indeed - with physical access, and if the PIN is short enough, the user data could be copied to PC with debug adapter hardware (despite hardware read protection being enabled) and by using brute-forcing the PIN combination private key data could be extracted from the image. This hardware attack was shown just recently. I believe this is not a real risk for regular users, but definitely is for a CA.
To avoid this attack the PIN needs to be set to more than 11 printable characters (small and big letters, digits, special characters) or at least 14 small ASCII letters (the more the better - device allows for PIN length up to 128 bytes, but lower count should be sufficient). If possible, using local diacritics with UTF-8 increases the required work to break the protection further.
Nitrokey Pro, HSM and Storage do not suffer from this issue, as the keys are stored off the MCU, on a tamper-resistant smart card, hence the PIN length could be smaller.

Calculations for the required safe PIN length for Nitrokey Start against the mentioned below hardware:

Constants:

  • 26 ASCII small letters to create the PIN;
  • 14 - PIN length, letters chosen randomly;
  • 192 - minimal count of SHA256 rounds run on the device to create the storage encryption key for the data;
  • 7747e7 - average SHA256 hashes count computed per second on 10x NVIDIA GTX 2080 GPU with hashcat (taken from this benchmark);
  • /2 - average result.

Edit: Benchmark sources update:

Edit: Announcement about the attack:

Edit: Instead of unmanageable random 14-letters PIN it is advised to use KDF-DO where possible. In other cases the PIN can be multiple (5-6) word based, exceeding the minimal PIN ASCII length, ideally containing national characters (aka accents / diacritics).

1 Like

To close this topic, I was able to generate my CSR for 2 ECC keys (sign and authenticate) and 1 RSA 4096bit keys.
ECC keys were created inside the token. I have checked that the RSA decryption is OK.

So I believe we can close this topic.

Hi @szszszsz,

OK. I agree. I was not thinking at CA issues.