OpenSC / libp11

PKCS#11 wrapper library
GNU Lesser General Public License v2.1
298 stars 183 forks source link

pkcs#11 unicode pin #515

Closed snoopyIV closed 9 months ago

snoopyIV commented 9 months ago

I would like to know which character sets are supported for PIN codes on libp11 implementation

I found pkcs11_login API will return value 0xa0 (which means PIN not correct) while the PIN include some special character defined by Unicode, like emoji. I tried Utf-8 and Percentage encoding, but the result are same. I can call pjcs11_login sucessfully, if the PIN not include emoji.

And the result is same when I use pkcs11-tool.exe

So, I want to know if there are any limitions on libp11, or pkcs#11 not support Unicode?

mtrojnar commented 9 months ago

I thought PIN stands for Personal Identification Number.

dwmw2 commented 9 months ago

The PKCS#11 spec says it's a CK_UTF8CHAR_PTR. https://docs.oasis-open.org/pkcs11/pkcs11-base/v3.0/os/pkcs11-base-v3.0-os.html#_Toc29976630

Unless your token rejects certain strings, libp11 ought to accept any valid UTF-8.

dwmw2 commented 9 months ago

Obviously, you were talking about login. If your PIN doesn't actually contain the emoji in question, then the login is expected to fail, right? :)

You should be able to set the PIN to any valid UTF-8. And then use that same valid UTF-8 to log in.

dengert commented 9 months ago

It will also depend on the token in the slot. Most tokens/smartcards expect only digits for example the command actually sent to a card may look like: 00 20 00 80 08 31 32 33 34 35 36 FF FF i.e. VERIFY command with 8 bytes of data, where pin is 123456 and the FF are padding to make it 8 bytes.

snoopyIV commented 9 months ago

Obviously, you were talking about login. If your PIN doesn't actually contain the emoji in question, then the login is expected to fail, right? :)

You should be able to set the PIN to any valid UTF-8. And then use that same valid UTF-8 to log in.

First, thanks for all your answers!

I found the C_Login function too, and because it declared CK_UTF8CHAR_PTR , I want to test emoji in Unicode. I tried use Unicode with UTF-8.

I have two usb key. One has emoji in PIN,like 😊😊123!@#, another has no emoji, like 123!@#. I tested these key same times, but the one has emoji in PIN always failed. In comparison, the usb key tool offered by usb key Manufacturer work well.

dengert commented 9 months ago

You have not said what is : "the usb key tool offered by usb key Manufacturer" and what PKCS11 module you are using or what system you are running on.

The "😊" in utf-8 is defined in https://apps.timwhitlock.info/emoji/tables/unicode#block-1-emoticons as 4 bytes: "\xF0\x9F\x98\x8A | smiling face with smiling eyes". So your: "😊😊123!@#" is 14 bytes long. This may exceed a length restriction of the usb token.

From looking at source of your e-mail: " In comparison, the usb key tool offered by usb key Manufacturer work well." is not a well know emoji, but shows as "=EF=BC=8C" aka "\xEF\xBC\x8C" or 3 bytes.

https://github.com/OpenSC/libp11/blob/master/src/eng_back.c#L39 limits to pin to 32 bytes +1.

So the problem does not appear to be in libp11.

This https://stackoverflow.com/questions/58210104/is-there-such-a-thing-as-non-utf8-character

dwmw2 commented 9 months ago

https://stackoverflow.com/questions/58210104/is-there-such-a-thing-as-non-utf8-character

There are invalid UTF-8 byte sequences though. For two-, three-, or four-byte UTF-8 sequences, the first byte should have an appropriate number of the top bits set, and every subsequent byte in the sequence must have 10 in the top bits.

Screenshot from 2023-09-23 04-06-20

That said, anything dealing with PINs/passwords purely in the hashing or strcmp sense should be able to deal with the byte sequence as a series of bytes, so even invalid UTF-8 will generally work.

An application running in a legacy 8-bit non-UTF-8 locale, however, should be converting from that character set to UTF-8 before presenting the byte sequence to the token. (cf. https://datatracker.ietf.org/doc/html/draft-woodhouse-cert-best-practice-01#name-pkcs11-pin )

For example, if I'm on a legacy ISO8859-1 system and my password is "naïve" that will be five bytes in my local system: 6e 61 ef 76 65. But an application shouldn't present those bytes to the PKCS#11 C_Login() call, because that's not UTF-8. The application should convert from the legacy crap to UTF-8, and call C_Login() with the 6 bytes 6e 61 c3 af 76 65.

nmav commented 9 months ago

UTF-8 is tricky with passwords. You can type certain letters in UTF-8 using different characters that are equivalent (e.g., multiple spaces), different unicode normalization etc. There is a certain profile applications can use to convert passwords in a certain "canonical" form as in https://datatracker.ietf.org/doc/html/rfc8265 . We had introduced gnutls_utf8_password_normalize() on gnutls for that reason.

mtrojnar commented 9 months ago

libp11 does not modify the UTF-8 sequence passed as PIN. I'm pretty sure it's the application that uses a different encoding for PIN.

Please reopen the issue that if you can reproduce it with OpenSSL CLI on a Unix configured with UTF-8 locale.

nmav commented 9 months ago

libp11 does not modify the UTF-8 sequence passed as PIN. I'm pretty sure it's the application that uses a different encoding for PIN.

Please reopen the issue that if you can reproduce it with OpenSSL CLI on a Unix configured with UTF-8 locale.

libp11 can be used by any application so if there are expectations from applications regarding utf-8 then they must be documented.

mtrojnar commented 9 months ago

@nmav I agree. Will you submit a PR?

snoopyIV commented 9 months ago

libp11 does not modify the UTF-8 sequence passed as PIN. I'm pretty sure it's the application that uses a different encoding for PIN. Please reopen the issue that if you can reproduce it with OpenSSL CLI on a Unix configured with UTF-8 locale.

libp11 can be used by any application so if there are expectations from applications regarding utf-8 then they must be documented.

Thanks for all your guys, I did find this question in windows. I suspect it's an application layer problem now. I agree this issue could be closed until I find the real reason.