Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

pkcs11-tool: add pure EdDSA support to sign/verify #2979

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

dlegaultbbry
Copy link
Contributor

Adding Pure EdDSA using ed25519 and ed448 keys to pkcs11-tool.

I used @dengert changes here to wire ed448 keys to be able to generate them using my custom soft hsm: dengert@1b0d7c9#diff-fcf954433b996121efbb3028d15e969537c35c7fd4bcd8b2a31bba29c4af18f7R160

Related #2952

# pkcs11-tool --module=/system/lib/dll/pkcs11-qkeystore.so --keypairgen --key-type EC:edwards25519 --usage-sign --label ed25519key --id 1
Using slot 0 with a present token (0x0)
Key pair generated:
Private Key Object; EC_EDWARDS
  label:      ed25519key
  ID:         01
  Usage:      sign
  Access:     sensitive, always sensitive, never extractable, local
Public Key Object; EC_EDWARDS  EC_POINT 255 bits
  EC_POINT:   fed9e24a03a7d163bc3e6b0275aba8bff92f13ad125c676faa4dfd7e131a5294
  EC_PARAMS:  130c656477617264733235353139 (OID 2.21.100.119.97.114.100.115.50.53.53.49.57)
  label:      ed25519key
  ID:         01
  Usage:      verify
  Access:     local

# echo -n "000102030405060708090a0b0c0d0e0f" > /data/sign.bin

# pkcs11-tool --module=/system/lib/dll/pkcs11-qkeystore.so --sign --mechanism EDDSA --label ed25519key --input-file /data/sign.bin --output-file /data/sig.bin
Using slot 0 with a present token (0x0)
Using signature algorithm EDDSA

# pkcs11-tool --module=/system/lib/dll/pkcs11-qkeystore.so --verify --mechanism EDDSA --label ed25519key --input-file /data/sign.bin --signature-file /data/sig.bin
Using slot 0 with a present token (0x0)
Using signature algorithm EDDSA
Signature is valid
# pkcs11-tool --module=/system/lib/dll/pkcs11-qkeystore.so --keypairgen --key-type EC:Ed448 --usage-sign --label ed448key --id 2
Using slot 0 with a present token (0x0)
Key pair generated:
Private Key Object; EC_EDWARDS
  label:      ed448key
  ID:         02
  Usage:      sign
  Access:     sensitive, always sensitive, never extractable, local
Public Key Object; EC_EDWARDS  EC_POINT 255 bits
  EC_POINT:   38dd2151d0a622417779b533524108442b537b6525cd11f6950a962b78267c4cdb17aab3df8561855c39bc4d33ecf20c2ba448482c50389100
  EC_PARAMS:  06032b6571 (OID 1.3.101.113)
  label:      ed448key
  ID:         02
  Usage:      verify
  Access:     local

# echo -n "000102030405060708090a0b0c0d0e0f" > /data/sign.bin

# pkcs11-tool --module=/system/lib/dll/pkcs11-qkeystore.so --sign --mechanism EDDSA --label ed448key --input-file /data/sign.bin --output-file /data/sig.bin
Using slot 0 with a present token (0x0)
Using signature algorithm EDDSA

# pkcs11-tool --module=/system/lib/dll/pkcs11-qkeystore.so --verify --mechanism EDDSA --label ed448key --input-file /data/sign.bin --signature-file /data/sig.bin
Using slot 0 with a present token (0x0)
Using signature algorithm EDDSA
Signature is valid
Checklist
  • [X ] PKCS#11 module is tested (custom softhsm)

src/tools/pkcs11-tool.c Outdated Show resolved Hide resolved
src/tools/pkcs11-tool.c Outdated Show resolved Hide resolved
@dengert
Copy link
Member

dengert commented Jan 12, 2024

In first example you use EC:edwards25519 which is using the non-standard OID, and it is a printable name. Then this shows up as
130c656477617264733235353139 (OID 2.21.100.119.97.114.100.115.50.53.53.49.57) which is all wrong.

Are you good with matching the EC_PARAMS using the ec_curve_info and then checking the size field which would be either 255 or 448 depending on key type?

Actually the Ed25519 and ED448 have different OIDs which implies the bits. Look at the sc_pkcs15_fix_ec_parameters and it table, that will convert the printable string into the OID.

The code I am working on now is the pkcs15init/pkcs15-openpgp.c and card-openpgp.c so they pass the provided OID, and only in card-openpgp.c does the choid of old or new OID is written to the card.

src/tools/pkcs11-tool.c Outdated Show resolved Hide resolved
@Jakuje
Copy link
Member

Jakuje commented Jan 12, 2024

In first example you use EC:edwards25519 which is using the non-standard OID, and it is a printable name. Then this shows up as 130c656477617264733235353139 (OID 2.21.100.119.97.114.100.115.50.53.53.49.57) which is all wrong.

As already mentioned, I think this is already fixed in master with 5493770 I think @dlegaultbbry just runs the older opensc version.

@dlegaultbbry
Copy link
Contributor Author

Yes, for the OID string printing, I don't have the latest and greatest version running which has the fix for that (running on a base 0.24.0 build right now).

@Jakuje
Copy link
Member

Jakuje commented Jan 15, 2024

I think detection by the length is good enough, but the best would be to compare probably by the name.

In any case, you will need also to pull the ed448 definitions into the ec_curve_infos. As for now, there are not ed448 definitions in the ec_curve_infos that would have the size 448 so the code as it is is a dead code.

@dlegaultbbry
Copy link
Contributor Author

This can wait for @dengert to merge his upcoming curve changes.

@dengert
Copy link
Member

dengert commented Jan 22, 2024

@dlegaultbbry I have for pushed changes to https://github.com/dengert/OpenSC/tree/X25519-improvements-2 last night.

All the pkcs11-tool changes are in first 7 commits: master...dengert:OpenSC:X25519-improvements-2

Please have a look, and if looks OK I will submit as PR.

Notable changes in all commits are:

  • RFC 8410 says for ASN.1 for Edwards and Montgomery public keys are in Bit Strings.

  • The RFC 8410 curve names are uses were possible.

  • OpenSC openpgp code will accept either RFC 8410 names or names used used in older RFC or in GnuPG and card-openpgp.c will map these to the older non standard OIDs that are written to Yubico and GNUK cards. This opens the way for other cards (which we do not have) to use just the RFC 8410 names.

  • pkcs15-tool can accept any of the known names when creating one of these keys. See the doc/tools/pkcs15-init.1.xml file.

  • I have not looked at importing keys, only creating keys using pkcs15.

  • pkcs1-tool -O now shows the bit string, size and OIDs in RFC 8410 see below.

  • I don't have any card that supports 448 bit keys, but the code is ready for them.

Things still to be done include:

  • Are these pubic key exported for use with OpenSSH correctly.
  • Will there be any problems with using older OpenSC code with the newer code. As OpenSSL uses only the RFC 8410 names, that should not be a problem. as ECDH between OpenSC and OpenSSL created keys derive the same values and OpenSSL can verify a EDDSA signature created bi OpenPGP card.
$ ./pkcs11-tool -O
Using slot 0 with a present token (0x0)
Public Key Object; RSA 2048 bits
  label:      Authentication key
  ID:         03
  Usage:      encrypt, verify, wrap
  Access:     none
Public Key Object; EC_MONTGOMERY  EC_POINT 256 bits
  EC_POINT:   032100d315256abfd74ccbef4f0322d41c5216224b2b6a97c6690ccc4bbcd8cc8cea13
  EC_PARAMS:  06032b656e (OID 1.3.101.110)
  label:      Encryption key
  ID:         02
  Usage:      derive
  Access:     none
Profile object 1028322784
  profile_id:          CKP_PUBLIC_CERTIFICATES_TOKEN (4)


$ ./pkcs11-tool --slot 1 -O
Public Key Object; EC_EDWARDS  EC_POINT 256 bits
  EC_POINT:   032100c077beadbae5871b77f952e342772a1126539f88a4af9c43e70c6720ce043d99
  EC_PARAMS:  06032b6570 (OID 1.3.101.112)
  label:      Signature key
  ID:         01
  Usage:      verify, verifyRecover
  Access:     none
Profile object 733237664
  profile_id:          CKP_PUBLIC_CERTIFICATES_TOKEN (4)

The 0x03 is BIT STRING, length is 0x21 the 0x00 says no padding needed as string is multiple of 8 bits. The rest is the actually public key. (EC use -x04 OCTET STRING and uncompressed 04||x||y)

Interesting note: OpenSSL x509 has option: -force_pubkey infile Place the given key in new certificate which can be used to create a certificate for a Montgomery key and signed by a CA.

@dlegaultbbry
Copy link
Contributor Author

dlegaultbbry commented Jan 22, 2024

@dlegaultbbry I have for pushed changes to https://github.com/dengert/OpenSC/tree/X25519-improvements-2 last night.

All the pkcs11-tool changes are in first 7 commits: master...dengert:OpenSC:X25519-improvements-2

Please have a look, and if looks OK I will submit as PR.

Notable changes in all commits are:

* RFC 8410 says for ASN.1 for  Edwards and Montgomery public keys are in Bit Strings.

* The RFC 8410 curve names are uses were possible.

* OpenSC openpgp  code will accept either RFC 8410 names or names used used in older RFC or in GnuPG and `card-openpgp.c` will map these to the older non standard OIDs that are written to Yubico and GNUK cards. This opens the way for other cards (which we do not have) to use just the RFC 8410 names.

* pkcs15-tool can accept any of the known names when creating one of these keys. See the   doc/tools/pkcs15-init.1.xml file.

* I have not looked at importing keys, only creating keys using pkcs15.

* pkcs1-tool -O now shows the bit string, size and OIDs in RFC 8410 see below.

* I don't have any card that supports 448 bit keys, but the code is ready for them.

Things still to be done include:

* Are these pubic key exported for use with OpenSSH correctly.

* Will there be any problems with using older OpenSC code with the newer code. As OpenSSL uses only the RFC 8410 names, that should not be a problem. as ECDH between OpenSC and OpenSSL created keys derive the same values and OpenSSL can verify a EDDSA signature created bi OpenPGP card.
$ ./pkcs11-tool -O
Using slot 0 with a present token (0x0)
Public Key Object; RSA 2048 bits
  label:      Authentication key
  ID:         03
  Usage:      encrypt, verify, wrap
  Access:     none
Public Key Object; EC_MONTGOMERY  EC_POINT 256 bits
  EC_POINT:   032100d315256abfd74ccbef4f0322d41c5216224b2b6a97c6690ccc4bbcd8cc8cea13
  EC_PARAMS:  06032b656e (OID 1.3.101.110)
  label:      Encryption key
  ID:         02
  Usage:      derive
  Access:     none
Profile object 1028322784
  profile_id:          CKP_PUBLIC_CERTIFICATES_TOKEN (4)


$ ./pkcs11-tool --slot 1 -O
Public Key Object; EC_EDWARDS  EC_POINT 256 bits
  EC_POINT:   032100c077beadbae5871b77f952e342772a1126539f88a4af9c43e70c6720ce043d99
  EC_PARAMS:  06032b6570 (OID 1.3.101.112)
  label:      Signature key
  ID:         01
  Usage:      verify, verifyRecover
  Access:     none
Profile object 733237664
  profile_id:          CKP_PUBLIC_CERTIFICATES_TOKEN (4)

The 0x03 is BIT STRING, length is 0x21 the 0x00 says no padding needed as string is multiple of 8 bits. The rest is the actually public key. (EC use -x04 OCTET STRING and uncompressed 04||x||y)

Interesting note: OpenSSL x509 has option: -force_pubkey infile Place the given key in new certificate which can be used to create a certificate for a Montgomery key and signed by a CA.

Changes look good to me for pkcs11-tool except this: dengert@ae43814

From what I understand getEC_POINT returns the size in bytes since the value uses CK_BYTE (would be 32 for both 25519 or 56/57 for X448/Ed448). It seems to mix bits and bytes in the calculation. The previous calculation looked more accurate in regards to this. I'm not even sure I understand this one 100%: dengert@5493770

Supporting information for EC and 25519/448

The public key EC point {x, y} can be compressed to just one of the coordinates + 1 bit (parity). For the secp256k1 curve, the private key is 256-bit integer (32 bytes) and the compressed public key is 257-bit integer (~ 33 bytes).

https://www.cryptosys.net/pki/manpki/pki_eccsafecurves.html

@dengert
Copy link
Member

dengert commented Jan 22, 2024

Changes look good to me for pkcs11-tool except this: dengert@ae43814

The code is in the show key section which is only used to list out objects from pkcs11-tool -O like
"Public Key Object; EC_MONTGOMERY EC_POINT 256 bits" or "Public Key Object; EC_EDWARDS EC_POINT 256 bits" . It was copied from 5493770 already in master used for EC keys.

Both the pieces of code are decoding the ASN1 of the EC_POINT, in EC case it is OCTET STRING, and in
EC_EDWARDS/EC_MONTGOMERY it is BIT STRING. The "Do simple size calculation based on DER encoding" is is looking at total length to figure size of the actual key bytes.

The messages are a little misleading, listing bits. They do list the RFC 8410 OIDs and the EC_POINT in hex format. Note: https://www.cryptosys.net/pki/manpki/pki_eccsafecurves.html does not mention PKCS11 accept for referencing RFC 8410 which gives an example of encoding a pubkey as a pem file.

- add matching of ec_curve_info using ec_params value
- distinguish between ed25519 and edd448 using curve size

Related OpenSC#2952
@dlegaultbbry
Copy link
Contributor Author

@Jakuje Any hope to get this included in 0.25.0 too?

@Jakuje
Copy link
Member

Jakuje commented Feb 20, 2024

as I mentioned in #2979 (comment) for now it does not provide much new functionality, as this PR is missing the ed448 definitions in https://github.com/OpenSC/OpenSC/blob/master/src/tools/pkcs11-tool.c#L115

I think if they are included, we can get it in. Without them, I do not see much point as it mostly adds unreachable code.

Looking at it again, isn't something similar needed also for the verification operation?

@dengert
Copy link
Member

dengert commented Feb 20, 2024 via email

@Jakuje
Copy link
Member

Jakuje commented Feb 20, 2024

The X25519-improvments-2 includes X448

I know, but it will likely not make it to 0.25.0 as it is quite many changes and we have rc0 out now.

@dengert
Copy link
Member

dengert commented Feb 20, 2024

I know, but it will likely not make it to 0.25.0 as it is quite many changes and we have rc0 out now.

I was not expecting it to be in 0.25.0, as it has "quite many changes" and I have some questions too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants