Failed to create PKCS #15 meta structure: Not supported

Dear EE,

Today the new Nitrokey Pro 2 got delivered and I’m really excited to get this little fellow up and running.
My primary goal is to use the Nitrokey in conjunction with OpenVPN, but I would also like to use GnuPG features.

So at first I set the admin PIN and the user PIN using gpg2 --card-edit > admin > passwd in the process I set as well user, lang, and sex with the intention this might hopefully be enough to consider it a GnuPG initialization. Everything worked like a charm, so I did a reset just to make sure I got a way out, which worked as well. I performed the same sequence again and went on to initialize the pkcs15 structure which didn’t worked as expected and what made me come to this place.

packages:
ccid-1.4.30
gnupg-2.2.12
opensc-0.19.0
pcsc-lite-1.8.23,2
pcsc-tools-1.5.3
pkcs11-helper-1.25.1_1

So just for clarification:
All commands are performed as root, to avoid any permission issues.

$ opensc-tool -l

Detected readers (pcsc)

Nr. Card Features Name
0 No Alcor Micro AU9560 00 00
1 Yes Nitrokey Nitrokey Pro (XXX) XX XX

$ pkcs15-tool --list-info
Using reader with a card: Nitrokey Nitrokey Pro (XXX) XX XX
PKCS#15 Card [OpenPGP card]:
Version : 0
Serial number : XXX
Manufacturer ID: ZeitControl
Language : en
Flags : PRN generation, EID compliant

$ pkcs15-init -E
Using reader with a card: Nitrokey Nitrokey Pro (XXX) XX XX
Failed to erase card: Not supported

$ pkcs15-init --create-pkcs15
Using reader with a card: Nitrokey Nitrokey Pro (XXX) XX XX
New Security Officer PIN (Optional - press return for no PIN).
Please enter Security Officer PIN:
Please type again to verify:
Unblock Code for New User PIN (Optional - press return for no PIN).
Please enter User unblocking PIN (PUK):
Please type again to verify:
Failed to create PKCS #15 meta structure: Not supported

What happened in the background:
read(0,“12345678\n”,4096) = 9 (0x9)
ioctl(1,TIOCSETAF,0x7fffffffe180) = 0 (0x0)
write(1,"\n",1) = 1 (0x1)
write(1,“Please type again to verify: “,29) = 29 (0x1d)
ioctl(1,TIOCGETA,0x7fffffffe180) = 0 (0x0)
ioctl(1,TIOCSETAF,0x7fffffffe150) = 0 (0x0)
read(0,“12345678\n”,4096) = 9 (0x9)
ioctl(1,TIOCSETAF,0x7fffffffe180) = 0 (0x0)
write(1,”\n”,1) = 1 (0x1)
write(1,“Unblock Code for New User PIN (O”…,68) = 68 (0x44)
write(1,“Please enter User unblocking PIN”…,40) = 40 (0x28)
ioctl(1,TIOCGETA,0x7fffffffe180) = 0 (0x0)
ioctl(1,TIOCSETAF,0x7fffffffe150) = 0 (0x0)
read(0,“87654321\n”,4096) = 9 (0x9)
ioctl(1,TIOCSETAF,0x7fffffffe180) = 0 (0x0)
write(1,"\n",1) = 1 (0x1)
write(1,“Please type again to verify: “,29) = 29 (0x1d)
ioctl(1,TIOCGETA,0x7fffffffe180) = 0 (0x0)
ioctl(1,TIOCSETAF,0x7fffffffe150) = 0 (0x0)
read(0,“87654321\n”,4096) = 9 (0x9)
ioctl(1,TIOCSETAF,0x7fffffffe180) = 0 (0x0)
write(1,”\n”,1) = 1 (0x1)
select(4,0x0,{ 3 },0x0,0x0) = 1 (0x1)
sendto(3,"\b\0\0\0\a\0\0\0",8,MSG_NOSIGNAL,NULL,0) = 8 (0x8)
select(4,0x0,{ 3 },0x0,0x0) = 1 (0x1)
sendto(3,“g\M-I\0002\0\0\0\0”,8,MSG_NOSIGNAL,NULL,0) = 8 (0x8)
select(4,{ 3 },0x0,0x0,0x0) = 1 (0x1)
read(3,“g\M-I\0002\0\0\0\0”,8) = 8 (0x8)
select(4,0x0,{ 3 },0x0,0x0) = 1 (0x1)
sendto(3,"\f\0\0\0\b\0\0\0",8,MSG_NOSIGNAL,NULL,0) = 8 (0x8)
select(4,0x0,{ 3 },0x0,0x0) = 1 (0x1)
sendto(3,“g\M-I\0002\0\0\0\0\0\0\0\0”,12,MSG_NOSIGNAL,NULL,0) = 12 (0xc)
select(4,{ 3 },0x0,0x0,0x0) = 1 (0x1)
read(3,“g\M-I\0002\0\0\0\0\0\0\0\0”,12) = 12 (0xc)
nanosleep({ 0.008487000 }) = 0 (0x0)
write(2,“Failed to create PKCS #15 meta s”…,56) = 56 (0x38)
select(4,0x0,{ 3 },0x0,0x0) = 1 (0x1)
sendto(3,"\f\0\0\0^F\0\0\0",8,MSG_NOSIGNAL,NULL,0) = 8 (0x8)
select(4,0x0,{ 3 },0x0,0x0) = 1 (0x1)
sendto(3,“g\M-I\0002\0\0\0\0\0\0\0\0”,12,MSG_NOSIGNAL,NULL,0) = 12 (0xc)
select(4,{ 3 },0x0,0x0,0x0) = 1 (0x1)
read(3,“g\M-I\0002\0\0\0\0\0\0\0\0”,12) = 12 (0xc)
select(4,0x0,{ 3 },0x0,0x0) = 1 (0x1)
sendto(3,"\b\0\0\0^B\0\0\0",8,MSG_NOSIGNAL,NULL,0) = 8 (0x8)
select(4,0x0,{ 3 },0x0,0x0) = 1 (0x1)
sendto(3,"\M^[\M-utV\0\0\0\0",8,MSG_NOSIGNAL,NULL,0) = 8 (0x8)
select(4,{ 3 },0x0,0x0,0x0) = 1 (0x1)
read(3,"\M^[\M-utV\0\0\0\0",8) = 8 (0x8)
close(3) = 0 (0x0)
munmap(0x803200000,2142208) = 0 (0x0)
munmap(0x80340b000,2121728) = 0 (0x0)
<thread 100227 exited>
exit(0x1)
process exit, rval = 1

Any suggestions?

Yepp: PKCS#15 is not supported. Try PKCS#11 (https://www.nitrokey.com/files/doc/Nitrokey_Pro_factsheet.pdf)

Peacekeeper:
https://www.nitrokey.com/documentation/smime-email-encryption
https://github.com/OpenSC/OpenSC/wiki/Frequently-Asked-Questions

Appreciate the talk. :slight_smile:

Right now I’m under the impression the following applies here:

… a smart card might come with a PKCS#11 provider for platform X but format data on the card differently than PKCS#15 defines.

Source: Frequently Asked Questions · OpenSC/OpenSC Wiki · GitHub

Anyone else ?

As said, the #15 structure is not supported. Try #12 structure :

pkcs15-init … --format pkcs12 …

Oh sorry my fault, in conjunction with my 2nd post, I thought it would be clear I already did this:

pkcs15-init --delete-objects privkey,pubkey --id 3 --generate-key rsa/4096 --auth-id 3 --verify-pin
pkcs15-init --delete-objects privkey,pubkey --id 3 --store-private-key file.p12 --format pkcs12 --auth-id 03 --verify-pin

Consulting the man page again regarding: pkcs15-init … --format pkcs12 … this option is to be used in conjunction with --store-private-key, or --store-public-key which in default expects PEM format. So --format pkcs12 is only being used as an input file format option and is not related to how the data are stored. Where as the PKCS15 seems to be the actual on-card structure which defines a filesystem layout for smart cards.
OpenSC - FAQ
man pkcs15-init

At least that’s my current understanding…

Anyway, pkcs15-tool -D showed me afterwards a x509 certificate had been imported, gpg2 --card-status showed me that an authentication key had been imported as well. So I adjusted my OpenVPN configuration to support pkcs11 and tried to establish a connection using the NitroKey Pro, which resulted in:

PKCS#11: Cannot get certificate object
PKCS#11: Cannot get certificate object
PKCS#11: Unable get evp object
Cannot load certificate “XXX” using PKCS#11 interface
Error: private key password verification failed

From there I went back resetting the NitroKey Pro several times and tried a few different sequences with the goal to somehow overcome these error messages, unfortunately without any success so far.

OpenVPN had been compiled from the source:

export LZO_CFLAGS=-I/usr/local/include
export LZO_LIBS=“-L/usr/local/lib -lz -llzo2”
./configure --prefix=/usr/local/openvpn --enable-pkcs11

Which brought me to my assumption PKCS15 is not supported, which had been backed up by:

pkcs15-init -E
Using reader with a card: Nitrokey Nitrokey Pro (XXX) XX XX
Failed to erase card: Not supported

and brought me here in the first place.

Long story short: PKCS15 as on-card structure is not supported and from my web research it seems like nobody is using the Nitrokey Pro 2 as a hardware authentication device in conjunction with OpenVPN. Sad.

Taking the hint that PKCS#11 is supported, I digged a little bit into pkcs11-tool command and tried to use it to get the Nitrokey Pro 2 running:

pkcs11-tool --id 03 --type cert -w certificate.crt.der -l --login-type so

Worked like a charm, using:

pkcs11-tool -l -O
Using slot 0 with a present token (0x0)
Logging in to “User PIN (OpenPGP card)”.
Please enter User PIN:
Certificate Object; type = X.509 cert
label: Cardholder certificate
subject: XXX
ID: 03
Public Key Object; RSA 4096 bits
label: Cardholder certificate
ID: 03
Usage: encrypt, verify

Excited about the success I tried to store the private key as well:

pkcs11-tool --id 03 --type privkey -w private.key.der -l --login-type so
Using slot 0 with a present token (0x0)
Logging in to “User PIN (OpenPGP card)”.
Please enter SO PIN:
error: PKCS11 function C_CreateObject failed: rv = CKR_GENERAL_ERROR (0x5)
Aborting.

:disappointed:

So I downloaded the OpenSC source and compiled it with debug options enabled to get an idea what actually is happening. To make it short the error message is originating in pkcs11-tool.c: 3063

3062 if (n_privkey_attr) {
3063 rv = p11->C_CreateObject(session, privkey_templ, n_privkey_attr, &privkey_obj);
3064 if (rv != CKR_OK)
3065 p11_fatal(“C_CreateObject”, rv);
3066
3067 printf(“Created private key:\n”);
3068 show_object(session, privkey_obj);
3069 }

And p11 seems to originate here pkcs11-tool.c:892

892 module = C_LoadModule(opt_module, &p11);
893 if (module == NULL)
894 util_fatal(“Failed to load pkcs11 module”);
895
896 rv = p11->C_Initialize(NULL);
897 if (rv == CKR_CRYPTOKI_ALREADY_INITIALIZED)
898 fprintf(stderr, “\n*** Cryptoki library has already been initialized ***\n”);
899 else if (rv != CKR_OK)
900 p11_fatal(“C_Initialize”, rv);
901

Seems like a deep rabbit hole … :thinking:

Anybody any experience with pkcs11-tool and storing a private.key? :slight_smile:

Hi,

this wiki page applies to the Pro and may helps. Furthermore, you get recent OpenSC build for Debian here.

Kind regards
Alex

Hi nitroalex,

Thanks for your reply.

I solved the issue already yesterday in so far, that I found a reliable way to store the OpenVPN client certificate and the private key on the Nitrokey Pro 2 using PKCS11.
OpenVPN asks for the User PIN, verification is successful, but then the OpenVPN client is freezing after or during the call of …

PKCS#11: __pkcs11h_forkFixup entry pid=15139, activate_slotevent=1

Right now I’m under the impression, that this is not related to the Nitrokey Pro 2 itself, and it’s more an issue of the pkcs11-helper library and OpenVPN, so I opened a thread here:
OpenVPN forum: PKCS#11: __pkcs11h_forkFixup freeze

Regards,
tanis

BTW: Thanks for sharing your experience ! I am not using OpenVPN, so you filled a gap :smiley:

Peacekeeper:

If this is of any interest I can share my experience, so someone else might have an easier time to get this done. From what I understood in the process of figuring this out, it might also be a reliable in addition to gpgsm to handle s/mime in conjunction with the Nitrokey Pro 2.

Regards,
tanis