Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Key mismatch with OpenSSL and 2 prime256v1 keys in token #784

Closed
benoiton opened this issue Jan 29, 2025 · 9 comments
Closed

Key mismatch with OpenSSL and 2 prime256v1 keys in token #784

benoiton opened this issue Jan 29, 2025 · 9 comments

Comments

@benoiton
Copy link

On Debian testing, with:

  • softhsm2 2.6.1-2.1
  • openssl 3.4.0-2
  • libengine-pkcs11-openssl 0.4.12-0.1
  • opensc and opensc-pkcs11 0.23.0-0.3+deb12u2
LIB=/usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so
OPENSSL_CONF=''

softhsm2-util --init-token --free --label test --pin 0000 --so-pin 1234

pkcs11-tool --module $LIB --token-label test --login --pin 0000 --keypairgen --key-type EC:prime256v1 --usage-sign --label key1
pkcs11-tool --module $LIB --token-label test --login --pin 0000 --keypairgen --key-type EC:prime256v1 --usage-sign --label key2

openssl req -engine pkcs11 -keyform engine -new -subj "/CN=1" -out 1.csr -key "pkcs11:token=test;pin-value=0000;object=key1"
openssl req -engine pkcs11 -keyform engine -new -subj "/CN=2" -out 2.csr -key "pkcs11:token=test;pin-value=0000;object=key2"

openssl req -noout -verify -in 1.csr 
openssl req -noout -verify -in 2.csr 

The first CSR is ok.

The second CSR is wrong, with OpenSSL error:

Warning: CSR self-signature does not match the contents
Certificate request self-signature verify failure
40273EC3967F0000:error:06880006:asn1 encoding routines:ASN1_item_verify_ctx:EVP lib:../crypto/asn1/a_verify.c:218:
40273EC3967F0000:error:06880006:asn1 encoding routines:ASN1_item_verify_ctx:EVP lib:../crypto/asn1/a_verify.c:218:

If key2 is created before key1, 2.csr is ok and 1.csr is wrong.

There is no issue with RSA:2048 keys.

@dengert
Copy link

dengert commented Jan 29, 2025

Sounds like a problem with the pkcs11 URI (RFC 7512) and the first entry is found. I recall a problem (that I can not find) where only the first character was used on one of the entries in the URI in one of the packages you may be using.

Some things to try:

  • Use a label where the first character is not the same in both.

  • When creating the keys with pkcs11-tool add --id x (will be converted to hex) for CKA_ID which is used to associate a key, pubkey and certificate.

  • Use ./pkcs11-tool --list-slots

  • You may may need to add --slot n to PKCS11 and the slot-id to the URI

  • Use pkcs11-tool -O --login to see the objects just created on the default slot Add --slot n to see other slots.

  • Try using OpenSC SPY https://github.com/OpenSC/OpenSC/wiki/Using-OpenSC to log PKCS11 requests and responses between any PKCS11 application and any PKCS11 module. In effect the SPY is the module loaded by the application and the SPY module then loads the original module to be used.

@benoiton
Copy link
Author

Tests:

Use a label where the first character is not the same in both

softhsm2-util --init-token --free --label test --pin 0000 --so-pin 1234
pkcs11-tool --module $LIB --token-label test --login --pin 0000 --keypairgen --key-type EC:prime256v1 --usage-sign --label akey
pkcs11-tool --module $LIB --token-label test --login --pin 0000 --keypairgen --key-type EC:prime256v1 --usage-sign --label bkey
openssl req -engine pkcs11 -keyform engine -new -subj "/CN=a" -out a.csr -key "pkcs11:token=test;pin-value=0000;object=akey"
openssl req -engine pkcs11 -keyform engine -new -subj "/CN=b" -out b.csr -key "pkcs11:token=test;pin-value=0000;object=bkey"
openssl req -noout -verify -in a.csr
openssl req -noout -verify -in b.csr

No change: a.csr is correct, b.csr is wrong

When creating the keys with pkcs11-tool add --id x (will be converted to hex) for CKA_ID which is used to associate a key, pubkey and certificate.

softhsm2-util --init-token --free --label test --pin 0000 --so-pin 1234
pkcs11-tool --module $LIB --token-label test --login --pin 0000 --keypairgen --key-type EC:prime256v1 --usage-sign --label akey --id 1
pkcs11-tool --module $LIB --token-label test --login --pin 0000 --keypairgen --key-type EC:prime256v1 --usage-sign --label bkey --id 2
openssl req -engine pkcs11 -keyform engine -new -subj "/CN=a" -out a.csr -key "pkcs11:token=test;pin-value=0000;id=%01"
openssl req -engine pkcs11 -keyform engine -new -subj "/CN=b" -out b.csr -key "pkcs11:token=test;pin-value=0000;id=%02"
openssl req -noout -verify -in a.csr
openssl req -noout -verify -in b.csr

It does works.

Use ./pkcs11-tool --list-slots
You may may need to add --slot n to PKCS11 and the slot-id to the URI
Use pkcs11-tool -O --login to see the objects just created on the default slot Add --slot n to see other slots.

I don't see the point.

$ pkcs11-tool --module $LIB --list-slots --login -O
Available slots:
Slot 0 (0x38c06b45): SoftHSM slot ID 0x38c06b45
  token label        : test
  token manufacturer : SoftHSM project
  token model        : SoftHSM v2
  token flags        : login required, rng, token initialized, PIN initialized, other flags=0x20
  hardware version   : 2.6
  firmware version   : 2.6
  serial num         : b961a9e438c06b45
  pin min/max        : 4/255
Slot 1 (0x1): SoftHSM slot ID 0x1
  token state:   uninitialized
Using slot 0 with a present token (0x38c06b45)
Logging in to "test".
Please enter User PIN: 
Public Key Object; EC  EC_POINT 256 bits
  EC_POINT:   0441042cb5fbc55cd36ba4a9f3bc8070c84f8de89d5e69c98e7453c03f219defff46f84267bb6cc0fef787851fa454745fe27e41cf46edaa911718d0f68c818ed60a3a
  EC_PARAMS:  06082a8648ce3d030107
  label:      akey
  ID:         01
  Usage:      encrypt, verify, wrap
  Access:     local
Private Key Object; EC
  label:      akey
  ID:         01
  Usage:      decrypt, sign, unwrap
  Access:     sensitive, always sensitive, never extractable, local
Public Key Object; EC  EC_POINT 256 bits
  EC_POINT:   0441042449e1041f694922846990b1279612af18fcbae02acbe897d4e8a462aa9dacaa1ba5de0270c5c8012b557a3344530bd5d443bfffcb35a391b26d66df63729596
  EC_PARAMS:  06082a8648ce3d030107
  label:      bkey
  ID:         02
  Usage:      encrypt, verify, wrap
  Access:     local
Private Key Object; EC
  label:      bkey
  ID:         02
  Usage:      decrypt, sign, unwrap
  Access:     sensitive, always sensitive, never extractable, local

Try using OpenSC SPY

I'll try that later.

I don't understand why there is an issue with ECDSA, and not with RSA...

@dengert
Copy link

dengert commented Jan 30, 2025

Also check if the CSRs have the matching ECpoints output from pkcs11-tool. If they are the same that could be a problem and use the first created pubkey would point at parsing the URI in the the engine.

openssl asn1parse -i -in a.csr -dump and --inform PEM|DER as needed.

@benoiton
Copy link
Author

I do not know how to read ASN1.

$ softhsm2-util --init-token --free --label test --pin 0000 --so-pin 1234
Slot 0 has a free/uninitialized token.
The token has been initialized and is reassigned to slot 96442818

$ pkcs11-tool --module $LIB --token-label test --login --pin 0000 --keypairgen --key-type EC:prime256v1 --usage-sign --label akey
Key pair generated:
Private Key Object; EC
  label:      akey
  Usage:      decrypt, sign, unwrap
  Access:     sensitive, always sensitive, never extractable, local
Public Key Object; EC  EC_POINT 256 bits
  EC_POINT:   04410481b053f6978a6cbaac74c6213f3d7799820c1ac096c6cd6cdd198802d03827f49cf08274b2ae8aee58f6a979ff8eff5513aa742c155613c21c5b353ace33540b
  EC_PARAMS:  06082a8648ce3d030107
  label:      akey
  Usage:      encrypt, verify, wrap
  Access:     local

$ pkcs11-tool --module $LIB --token-label test --login --pin 0000 --keypairgen --key-type EC:prime256v1 --usage-sign --label bkey
Key pair generated:
Private Key Object; EC
  label:      bkey
  Usage:      decrypt, sign, unwrap
  Access:     sensitive, always sensitive, never extractable, local
Public Key Object; EC  EC_POINT 256 bits
  EC_POINT:   0441049a93e29aa1ab8ae7c88f06cd24a5f5f3e7a90f842f73e40a04e8ae21695dc55fef59a0b5d841832e100659409c439089a089512b52bc874705833c6633c2bf8c
  EC_PARAMS:  06082a8648ce3d030107
  label:      bkey
  Usage:      encrypt, verify, wrap
  Access:     local

$ openssl req -engine pkcs11 -keyform engine -new -subj "/CN=a" -out a.csr -key "pkcs11:token=test;pin-value=0000;object=akey"
Engine "pkcs11" set.

$ openssl req -engine pkcs11 -keyform engine -new -subj "/CN=b" -out b.csr -key "pkcs11:token=test;pin-value=0000;object=bkey"
Engine "pkcs11" set.

$ openssl req -noout -verify -in a.csr
Certificate request self-signature verify OK

$ openssl req -noout -verify -in b.csr
Warning: CSR self-signature does not match the contents
Certificate request self-signature verify failure
4087A432577F0000:error:06880006:asn1 encoding routines:ASN1_item_verify_ctx:EVP lib:../crypto/asn1/a_verify.c:218:
4087A432577F0000:error:06880006:asn1 encoding routines:ASN1_item_verify_ctx:EVP lib:../crypto/asn1/a_verify.c:218:
  
benoit@ginaz:/tmp/a 1 $ openssl asn1parse -i -in a.csr -dump
    0:d=0  hl=3 l= 197 cons: SEQUENCE          
    3:d=1  hl=2 l= 110 cons:  SEQUENCE          
    5:d=2  hl=2 l=   1 prim:   INTEGER           :00
    8:d=2  hl=2 l=  12 cons:   SEQUENCE          
   10:d=3  hl=2 l=  10 cons:    SET               
   12:d=4  hl=2 l=   8 cons:     SEQUENCE          
   14:d=5  hl=2 l=   3 prim:      OBJECT            :commonName
   19:d=5  hl=2 l=   1 prim:      UTF8STRING        :a
   22:d=2  hl=2 l=  89 cons:   SEQUENCE          
   24:d=3  hl=2 l=  19 cons:    SEQUENCE          
   26:d=4  hl=2 l=   7 prim:     OBJECT            :id-ecPublicKey
   35:d=4  hl=2 l=   8 prim:     OBJECT            :prime256v1
   45:d=3  hl=2 l=  66 prim:    BIT STRING        
      0000 - 00 04 81 b0 53 f6 97 8a-6c ba ac 74 c6 21 3f 3d   ....S...l..t.!?=
      0010 - 77 99 82 0c 1a c0 96 c6-cd 6c dd 19 88 02 d0 38   w........l.....8
      0020 - 27 f4 9c f0 82 74 b2 ae-8a ee 58 f6 a9 79 ff 8e   '....t....X..y..
      0030 - ff 55 13 aa 74 2c 15 56-13 c2 1c 5b 35 3a ce 33   .U..t,.V...[5:.3
      0040 - 54 0b                                             T.
  113:d=2  hl=2 l=   0 cons:   cont [ 0 ]        
  115:d=1  hl=2 l=  10 cons:  SEQUENCE          
  117:d=2  hl=2 l=   8 prim:   OBJECT            :ecdsa-with-SHA256
  127:d=1  hl=2 l=  71 prim:  BIT STRING        
      0000 - 00 30 44 02 20 3d 5e e0-44 72 34 83 aa 66 90 6f   .0D. =^.Dr4..f.o
      0010 - 22 01 16 4f 55 c7 e8 f0-1b 7d 4e 71 2f 49 f7 0d   "..OU....}Nq/I..
      0020 - 10 eb a0 38 44 02 20 7b-2a 35 5a 21 a0 a9 f6 59   ...8D. {*5Z!...Y
      0030 - 21 34 9e 0d aa 6b d9 8f-85 6b 7d 54 39 9f c7 ff   !4...k...k}T9...
      0040 - 17 72 df 8b 27 a5 e4                              .r..'..

$ openssl asn1parse -i -in b.csr -dump
    0:d=0  hl=3 l= 197 cons: SEQUENCE          
    3:d=1  hl=2 l= 110 cons:  SEQUENCE          
    5:d=2  hl=2 l=   1 prim:   INTEGER           :00
    8:d=2  hl=2 l=  12 cons:   SEQUENCE          
   10:d=3  hl=2 l=  10 cons:    SET               
   12:d=4  hl=2 l=   8 cons:     SEQUENCE          
   14:d=5  hl=2 l=   3 prim:      OBJECT            :commonName
   19:d=5  hl=2 l=   1 prim:      UTF8STRING        :b
   22:d=2  hl=2 l=  89 cons:   SEQUENCE          
   24:d=3  hl=2 l=  19 cons:    SEQUENCE          
   26:d=4  hl=2 l=   7 prim:     OBJECT            :id-ecPublicKey
   35:d=4  hl=2 l=   8 prim:     OBJECT            :prime256v1
   45:d=3  hl=2 l=  66 prim:    BIT STRING        
      0000 - 00 04 81 b0 53 f6 97 8a-6c ba ac 74 c6 21 3f 3d   ....S...l..t.!?=
      0010 - 77 99 82 0c 1a c0 96 c6-cd 6c dd 19 88 02 d0 38   w........l.....8
      0020 - 27 f4 9c f0 82 74 b2 ae-8a ee 58 f6 a9 79 ff 8e   '....t....X..y..
      0030 - ff 55 13 aa 74 2c 15 56-13 c2 1c 5b 35 3a ce 33   .U..t,.V...[5:.3
      0040 - 54 0b                                             T.
  113:d=2  hl=2 l=   0 cons:   cont [ 0 ]        
  115:d=1  hl=2 l=  10 cons:  SEQUENCE          
  117:d=2  hl=2 l=   8 prim:   OBJECT            :ecdsa-with-SHA256
  127:d=1  hl=2 l=  71 prim:  BIT STRING        
      0000 - 00 30 44 02 20 5a a9 4b-6a 01 61 b4 cc 63 68 e1   .0D. Z.Kj.a..ch.
      0010 - f6 08 73 22 b5 2a d7 3d-5a 87 c6 29 25 b7 29 36   ..s".*.=Z..)%.)6
      0020 - 16 c9 30 56 2c 02 20 1e-fb 37 1d b7 8b 3e 14 20   ..0V,. ..7...>. 
      0030 - ba 28 3c e6 82 20 60 f2-90 8e 55 46 23 58 e0 a0   .(<.. `...UF#X..
      0040 - 88 4a b9 6f e8 e4 05                              .J.o...

@dengert
Copy link

dengert commented Jan 30, 2025

I do not know how to read ASN1.

In openssl asn1parse -i -in a.csr -dump

14:d=5  hl=2 l=   3 prim:      OBJECT            :commonName
  19:d=5  hl=2 l=   1 prim:      UTF8STRING        :a

is the label=/CN=a and

   24:d=3  hl=2 l=  19 cons:    SEQUENCE          
   26:d=4  hl=2 l=   7 prim:     OBJECT            :id-ecPublicKey
   35:d=4  hl=2 l=   8 prim:     OBJECT            :prime256v1
   45:d=3  hl=2 l=  66 prim:    BIT STRING        
      0000 - 00 04 81 b0 53 f6 97 8a-6c ba ac 74 c6 21 3f 3d   ....S...l..t.!?=
      0010 - 77 99 82 0c 1a c0 96 c6-cd 6c dd 19 88 02 d0 38   w........l.....8
      0020 - 27 f4 9c f0 82 74 b2 ae-8a ee 58 f6 a9 79 ff 8e   '....t....X..y..
      0030 - ff 55 13 aa 74 2c 15 56-13 c2 1c 5b 35 3a ce 33   .U..t,.V...[5:.3
      0040 - 54 0b  

is the X509 format of the public key. where the ECpoint listed as 04|x|y i.e. uncompressed with the X and Y of the point

      04  81 b0 53 f6 97 8a-6c ba ac 74 c6 21 3f 3d  
      77 99 82 0c 1a c0 96 c6-cd 6c dd 19 88 02 d0 38  
      27 f4 9c f0 82 74 b2 ae-8a ee 58 f6 a9 79 ff 8e  
      ff 55 13 aa 74 2c 15 56-13 c2 1c 5b 35 3a ce 33 
      54 0b

In openssl asn1parse -i -in b.csr -dump

14:d=5  hl=2 l=   3 prim:      OBJECT            :commonName
 19:d=5  hl=2 l=   1 prim:      UTF8STRING        :b

is label=/CN=b

   24:d=3  hl=2 l=  19 cons:    SEQUENCE          
   26:d=4  hl=2 l=   7 prim:     OBJECT            :id-ecPublicKey
   35:d=4  hl=2 l=   8 prim:     OBJECT            :prime256v1
   45:d=3  hl=2 l=  66 prim:    BIT STRING        
      0000 - 00 04 81 b0 53 f6 97 8a-6c ba ac 74 c6 21 3f 3d   ....S...l..t.!?=
      0010 - 77 99 82 0c 1a c0 96 c6-cd 6c dd 19 88 02 d0 38   w........l.....8
      0020 - 27 f4 9c f0 82 74 b2 ae-8a ee 58 f6 a9 79 ff 8e   '....t....X..y..
      0030 - ff 55 13 aa 74 2c 15 56-13 c2 1c 5b 35 3a ce 33   .U..t,.V...[5:.3
      0040 - 54 0b  

which is the SAME AS IN a.csr

So most likely the engine is always selecting the first key i.e. ignores the object=akey You should report this
to: https://github.com/OpenSC/libp11/issues

Or try the latest version libp11-0.4.13 See https://github.com/OpenSC/libp11/wiki

This site can be helpful if you have the DER version of someting

@dengert
Copy link

dengert commented Jan 30, 2025

This site can be helpful if you have the DER version of something

I did not finish the line. The site is https://lapo.it/asn1js/

And search for "Layman's guide to ASN.1" which covers the basics.

@dengert
Copy link

dengert commented Jan 30, 2025

Newer versions of OpenSC's pkcs11-tool --list-objects --login will also print a URI of an object.
for example:

./pkcs11-tool --list-objects --login
Using slot 0 with a present token (0x0)
Logging in to "OpenPGP card (User PIN)".
Please enter User PIN: 
Private Key Object; EC
  label:      Authentication key
  ID:         03
  Usage:      sign
  Access:     sensitive, always sensitive, never extractable, local
  uri:        pkcs11:model=PKCS%2315%20emulated;manufacturer=Yubico;serial=000613412286;token=OpenPGP%20card%20%28User%20PIN%29;id=%03;object=Authentication%20key;type=private
Public Key Object; EC  EC_POINT 256 bits
  EC_POINT:   0441045442dd9f06625318d5a014ae897897666666863007abe5af4cfa5d54666da24f620862914d316d4c154036a903462116d282447377a19429bf34f613dce4a149
  EC_PARAMS:  06082a8648ce3d030107 (OID 1.2.840.10045.3.1.7)
  label:      Authentication key
  ID:         03
  Usage:      verify, verifyRecover
  Access:     none
  uri:        pkcs11:model=PKCS%2315%20emulated;manufacturer=Yubico;serial=000613412286;token=OpenPGP%20card%20%28User%20PIN%29;id=%03;object=Authentication%20key;type=public

Note the type=public, type=private for the keys. serial= is also good to use as it is (usual) unique among any token inserted.

@benoiton
Copy link
Author

I've just upgraded opensc from 0.23 (in Debian stable) to 0.26 (in Debian testing), and the uri will be very useful!
Thanks 🙏

@benoiton
Copy link
Author

So most likely the engine is always selecting the first key i.e. ignores the object=akey You should report this
to: https://github.com/OpenSC/libp11/issues

Opened here: OpenSC/OpenSC#3331

@benoiton benoiton closed this as not planned Won't fix, can't repro, duplicate, stale Jan 31, 2025
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants