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

OAEP (RFC8017) padding check/removal #2475

Merged
merged 2 commits into from
Jan 5, 2022
Merged

Conversation

popovec
Copy link
Member

@popovec popovec commented Dec 27, 2021

If the card does not support OAEP, but RSA RAW operation is available,
OAEP padding check/removal is now supported by the software.

  • PKCS#11 module is tested

OAEP decrypt is tested by github actions (OsEID simulation).

@frankmorgner
Copy link
Member

Than you! Could you make this OpenSSL 3.0.0 compatible as well?

@frankmorgner
Copy link
Member

... see #2438 for examples for the new APIs

@popovec
Copy link
Member Author

popovec commented Dec 28, 2021

Customization to API 3.0: EVP_MD_CTX_create() replaced by EVP_MD_CTX_new(), EVP_MD_CTX_destroy() replaced by EVP_MD_CTX_free(). The current code should meet the requirements of openssl-3.0.

@mouse07410
Copy link
Contributor

Pardon my ignorance - do we want to move to OpenSSL-3.0 (aka,?break compatibility with 1.1.1), or add 3.0 (keeping support for both APIs)?

@popovec
Copy link
Member Author

popovec commented Dec 28, 2021

Pardon my ignorance - do we want to move to OpenSSL-3.0 (aka,?break compatibility with 1.1.1), or add 3.0 (keeping support for both APIs)?

Code in this PR is correct for both versions. When compiling with both versions of openssl, I did not find any "deprecated" functions.

@frankmorgner
Copy link
Member

frankmorgner commented Dec 28, 2021

Pardon my ignorance - do we want to move to OpenSSL-3.0 (aka,?break compatibility with 1.1.1), or add 3.0 (keeping support for both APIs)?

please discuss this in #2438

@popovec popovec mentioned this pull request Dec 28, 2021
3 tasks
@xhanulik
Copy link
Contributor

Customization to API 3.0: EVP_MD_CTX_create() replaced by EVP_MD_CTX_new(), EVP_MD_CTX_destroy() replaced by EVP_MD_CTX_free(). The current code should meet the requirements of openssl-3.0.

I checked the changes, and the code above should not cause problems with OpenSSL 3.0 (no deprecated functions and it keeps compatibility with both OpenSSL 1.1.1 and 3.0).

@popovec
Copy link
Member Author

popovec commented Dec 30, 2021

Customization to API 3.0: EVP_MD_CTX_create() replaced by EVP_MD_CTX_new(), EVP_MD_CTX_destroy() replaced by EVP_MD_CTX_free(). The current code should meet the requirements of openssl-3.0.

I checked the changes, and the code above should not cause problems with OpenSSL 3.0 (no deprecated functions and it keeps compatibility with both OpenSSL 1.1.1 and 3.0).

Thanks!

@Jakuje
Copy link
Member

Jakuje commented Jan 3, 2022

Can you update the src/tests/p11test/virt_cacard_ref.json file to make the test-cac test pass cleanly? The p11test with the CAC emulation looks like working fine, just the reference file is missing this mechanism ? Otherwise it looks good to me.

src/libopensc/padding.c Outdated Show resolved Hide resolved
If the card does not support OAEP, but RSA RAW operation is available,
OAEP padding check/removal is now supported by the software.
	modified:   src/tests/p11test/virt_cacard_ref.json
@frankmorgner
Copy link
Member

thank you

@popovec popovec mentioned this pull request Jan 5, 2022
2 tasks
@Jakuje Jakuje merged commit 4653d70 into OpenSC:master Jan 5, 2022
@mouse07410
Copy link
Contributor

Here's what I get with the current master:

$ pkcs11-tool -l -t
.  .  .
Decryption (currently only for RSA)
  testing key 0 (PIV AUTH key)
    RSA-X-509: OK
    RSA-PKCS: OK
    RSA-PKCS-OAEP: mgf not set, defaulting to MGF1-SHA256
OAEP parameters: hashAlg=SHA256, mgf=MGF1-SHA256, source_type=0, source_ptr=0x0, source_len=0
OK
  testing key 1 (SIGN key)
    RSA-X-509: OK
    RSA-PKCS: OK
    RSA-PKCS-OAEP: mgf not set, defaulting to MGF1-SHA256
OAEP parameters: hashAlg=SHA256, mgf=MGF1-SHA256, source_type=0, source_ptr=0x0, source_len=0
OK
  testing key 2 (KEY MAN key)
    RSA-X-509: OK
    RSA-PKCS: OK
    RSA-PKCS-OAEP: mgf not set, defaulting to MGF1-SHA256
OAEP parameters: hashAlg=SHA256, mgf=MGF1-SHA256, source_type=0, source_ptr=0x0, source_len=0
OK
  testing key 3 (CARD AUTH key)
    RSA-X-509: OK
    RSA-PKCS: OK
    RSA-PKCS-OAEP: mgf not set, defaulting to MGF1-SHA256
OAEP parameters: hashAlg=SHA256, mgf=MGF1-SHA256, source_type=0, source_ptr=0x0, source_len=0
OK
No errors

It says OK everywhere (so far so good), but why are the source ptr and len all zeroes? @popovec is it OK???

@popovec
Copy link
Member Author

popovec commented Jan 7, 2022

OAEP padding uses optional "label", here part from https://www.rfc-editor.org/rfc/rfc8017.html :

3.  EME-OAEP decoding:

          a.  If the label L is not provided, let L be the empty string.
              Let lHash = Hash(L), an octet string of length hLen (see
              the note in Section 7.1.1).

PKCS#11 allow us to specify this label as parameter:

typedef struct CK_RSA_PKCS_OAEP_PARAMS {
   CK_MECHANISM_TYPE            hashAlg;
   CK_RSA_PKCS_MGF_TYPE         mgf;
   CK_RSA_PKCS_OAEP_SOURCE_TYPE source;
   CK_VOID_PTR                  pSourceData;
   CK_ULONG                     ulSourceDataLen;
}  CK_RSA_PKCS_OAEP_PARAMS;

There is no support for this optional label in OpenSC for now (https://github.com/OpenSC/OpenSC/blob/master/src/libopensc/padding.c#L253).

I planned to write it, but I need to test it - ideally using openssl - but I didn't find support for specifying "label" for openssl decrypt operations (rsautl, pkeyutl).

When I find a reasonable way to do this in OpenSC (a problem similar to PSS salt-length how to pass pkcs#11 parameter to libopensc), including an independent test via openssl (or another cryptographic library .. soft-hsm, etc.), I will write the code for entering the label both in pkcs11-tool and in pkcs#11 module.

@mouse07410
Copy link
Contributor

@popovec are you saying that the "source_len = 0" refers to the label? And that's why it's OK, at least for now?
In that case, may I suggest changing the confusing output to something like "label ptr" and "label length"?

@popovec
Copy link
Member Author

popovec commented Jan 7, 2022

From pkcs#11 view - this is OAEP parameter. Messages from pkcs11-tool are only informative.

I understand that this information may be confusing, but in fact it is not a error. There is no label in pkcs#11 terminology .. pkcs#11 uses only mechanism parameters....

@mouse07410
Copy link
Contributor

Who is that message for? If it's for the user - then let's make it less confusing for the user. If for developer - let's avoid printing it out unless developer explicitly asks for it.

Anyway, in my fork I changed the text from PKCS#11-pure but confusing, to "impure" but clear.

@popovec
Copy link
Member Author

popovec commented Jan 8, 2022

PKCS#11 .. how to perform a OAEP decrypt operation:

Initialize the decrypt operation ..

CK_RV C_DecryptInit(CK_SESSION_HANDLE hSession,
                    CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey);

pMechanism is used to setup OAEP .. one part ot this setup is filling the OAEP parameters.

For OAEP, we have these parameters .. this is how PKCS#11 defines them, and whether they are confusing or not, we won't do anything about it.

hashAlg        mechanism ID of the message digest algorithm used to calculate the digest of the encoding parameter
mgf        mask generation function to use on the encoded block
source        source of the encoding parameter
pSourceData        data used as the input for the encoding parameter source
ulSourceDataLen       length of the encoding parameter source input

Would be better to change source_ptr=0x0 to encoding parameter source=0x0 ? I don't know if it would help ..

After the decrypt operation is initialized, the real decrypt follows (and here are the real data for decrypt pEncryptedData and ulEncryptedDataLen):

CK_RV C_Decrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData,
                CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData,
                CK_ULONG_PTR pulDataLen);

@dengert
Copy link
Member

dengert commented Jan 8, 2022

RFC 8017 says:
"Both the encryption and the decryption operations of RSAES-OAEP take
the value of a label L as input. In this version of PKCS #1, L is
the empty string; other uses of the label are outside the scope of
this document. See Appendix A.2.1 for the relevant ASN.1 syntax."

Appendix A.2.1 then says currently there is only one type : ncodingParameters ::= OCTET STRING(SIZE(0..MAX)) but allows for future types.

and says "The default label is an empty string (so that lHash will contain the hash of the empty string):'
which for SHA256 would produce according to: https://crypto.stackexchange.com/questions/26133/sha-256-hash-of-null-input
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

So I assume this "Label" is the "source data"?

PKCS11 curr-v3.0 "Table 6, PKCS #1 RSA OAEP: Encoding parameter sources"
CKZ_DATA_SPECIFIED | 0x00000001UL | "Array of CK_BYTE containing the value of the encoding parameter . If the parameter is empty, pSourceData must be NULL and ulSourceDataLen must be zero."

So it looks like CKZ_DATA_SPECIFIED is just a fancy way to say if there is any data i.e. Label present or not. But it also allows for future types of sources.

Would be better to change source_ptr=0x0 to encoding parameter source=0x0 ? I don't know if it would help ..

I read both PKCS11 and RFC8017 to say if source is 0, then the pointer and the length must also be zero, which says to hash the NULL string. But we should also allow for future types of sources. But for now source is 0 or 1. and ASN.1 as defined in Appendix A.2.1.

@popovec
Copy link
Member Author

popovec commented Jan 8, 2022

https://docs.oasis-open.org/pkcs11/pkcs11-curr/v3.0/os/pkcs11-curr-v3.0-os.html#_Toc30061136

Setting the "CK_RSA_PKCS_OAEP_SOURCE_TYPE" to "CKZ_DATA_SPECIFIED = 0x00000001UL" allow us to provide "CK_VOID_PTR pSourceData;" and "CK_ULONG ulSourceDataLen;".

I already found how to pass "label" into openssl oaep encrypt operation (-pkeyopt rsa_oaep_label:314F - the "label" is set to string "\x31\x4f"). This switch is working for me (openssl 1.1.1k-1+deb11u1). The man page for pkeyutl have no mention of this switch.

I will prepare a PR (for pkcs#11 module and for pkcs11-tool) that will allow to perform decryption using OAEP inclusive the "label" - of course also with a test, openssl encrypt then opensc pkcs#11 decrypt.

@dengert
Copy link
Member

dengert commented Jan 8, 2022

So I assume:
source=0, pSourceData=NULL and ulSourceDataLen= 0
source=1, pSourceData=NULL and ulSourceDataLen= 0
source=1, pSourceData=non-NULL and ulSourceDataLen= 0
produce the same results?
Or is the last case an error?

@popovec
Copy link
Member Author

popovec commented Jan 8, 2022

So I assume:
source=0, pSourceData=NULL and ulSourceDataLen= 0
source=1, pSourceData=NULL and ulSourceDataLen= 0
source=1, pSourceData=non-NULL and ulSourceDataLen= 0
produce the same results? Or is the last case an error?

Technically this is same as openssl function EVP_DigestUpdate (). I haven't tried how this function behaves if the input is not null and length = 0.

If we are to be very benevolent, all the above cases will generate the same result and we will not report an error.

@mouse07410
Copy link
Contributor

mouse07410 commented Jan 9, 2022

So I assume this "Label" is the "source data"?

Yes it is - and for the benefit of users I think it should be named "label", as opposed to the obscure PKCS11-internal confusing term currently used in the code.

If we are to be very benevolent, all the above cases will generate the same result and we will not report an error.

Yes, I think we do want to be benevolent here.

@popovec
Copy link
Member Author

popovec commented Jan 12, 2022

Continuation of OAEP patch (pkcs#11 code and test code in pkcs11-tool) is available under #2484. Thanks for any comments and testing.

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

6 participants