Yubico/yubico-piv-tool

C_Sign with CKM_RSA_PKCS doesn't perform EMSA_PKCS1-v1_5-ENCODE before signing

svmhdvn opened this issue · 2 comments

I'm not sure if this is issue is best filed here or directly against the cryptoki spec [0], but here is the issue:

I am trying to integrate pkcs11 functionality (using my yubikey) with BearSSL's client certificate support. The idea is to use the hardware token to perform private-key operations during the TLS handshake that attaches the client certificate to the request. To do that, bearssl requires a PKCS1 v1.5 RSA signature computed over a provided hash (with input given as {hash, hash_len, hash_algo_identifier}).

As I understand it from the PKCS1 RFC Section 9.2 [1], the hash must first be encoded using EMSA_PKCS1-v1_5-ENCODE, then signed using the RSA algorithm. BearSSL provides a signing function that does exactly this, so I've used it as a test vector to check against ykcs11's sign function with the CKM_RSA_PKCS mechanism. I noticed that CKM_RSA_PKCS doesn't take in a parameter, so there is no way to encode the hash algorithm identifier into the message, so EMSA_PKCS1-v1_5-ENCODE cannot be performed. The way to get around this is by using an internal private function that BearSSL provides to do EMSA_PKCS1-v1_5-ENCODE explicitly, then use the CKM_RSA_X_509 raw mechanism to sign that data. This works correctly.

Is this intentional? What is the correct way to do PKCS1 v1.5 RSA signatures over an already-provided hash value + hash algorithm identifier? The other CKM_*_RSA_PKCS mechanisms perform hashing + signature over an arbitrary value, which isn't desired either.

[0] https://docs.oasis-open.org/pkcs11/pkcs11-base/v2.40/os/pkcs11-base-v2.40-os.html
[1] https://www.rfc-editor.org/rfc/rfc8017#section-9.2

CKM_RSA_PKCS simply performs a RSA_padding_add_PKCS1_type_1, i.e. it performs only the padding, not the encoding of algorithm identifier or hash, and then signs the resulting data. This is by specification. So if you do that encoding yourself you can then call libykcs11 (or any pkcs11 module) with CKM_RSA_PKCS to pad that data and sign it. Or if you prefer you can also do the padding yourself and then use CKM_RSA_X_509 to have the pkcs11 module perform only the RSA modexp operation. So CKM_RSA_PKCS is really there as a utility. In contrast the hashing signature mechanisms do perform the encoding as well. See the function prepare_rsa_signature in yubico-piv-tool for an example of encoding the data using openssl.

Thanks for the info! Closing now since this is not a bug.