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

Queries related to PKCS11 based tests #721

Open
anvisriv opened this issue Jan 11, 2024 · 59 comments
Open

Queries related to PKCS11 based tests #721

anvisriv opened this issue Jan 11, 2024 · 59 comments

Comments

@anvisriv
Copy link

Hi Team

If repos (optee_test,optee_client,optee_os)with tag 4.0.0 is used then,

  1. Can you please confirm whether all the PKCS11 related test cases are passing in OPTEE? If not, can you please highlight those testcases and the plan to fix them?
  2. Some of the test cases(like 1008,1009.1020) require NULL input to be handled by returning the output size, although the GP specification(for TEE_CipherUpdate, TEE_MACComputeFinal) does not mention this requirement. These test cases are bound to fail where GP APIs are not implemented as the test case expects. Any reason why these test cases were designed in such a way?
@etienne-lms
Copy link
Contributor

Hi @anvisriv,

  1. Can you please confirm whether all the PKCS11 related test cases are passing in OPTEE?

All pkcs11 test from xtest are expected to pass.
OP-TEE CI tests check that using qemu_armv8a platform setup.

  1. Some of the test cases(like 1008,1009.1020) require NULL input to be handled by returning the output size

Pkcs11 API functions differ from GP TEE API functions in how to get an output buffer size. With Pkcs11, to query an output buffer size, you can either pass a NULL pointer (in which case you get an CKR_OK status with the size output argument set) or you can pass a too small buffer (in which case you get a CKR_BUFFER_TOO_SMALL status and the size output argument set). pkcs11 xtest test are implemented using Pkcs11 cryptoki API functions.

@anvisriv
Copy link
Author

anvisriv commented Jan 12, 2024

Hi @etienne-lms

Pkcs11 API functions differ from GP TEE API functions in how to get an output buffer size. With Pkcs11, to query an output buffer size, you can either pass a NULL pointer (in which case you get an CKR_OK status with the size output argument set) or you can pass a too small buffer (in which case you get a CKR_BUFFER_TOO_SMALL status and the size output argument set). pkcs11 xtest test are implemented using Pkcs11 cryptoki API functions.

Can you please tell me where the output size is calculated for the ‘NULL buffer case with size as 0’ subtest of PKCS11 Test 1008?
Is it calculated inside the PKC11 cryptoki Client library or inside the PKCS11 TA?
Based on the code, it appears that the output size is calculated by the PKCS11 TA using GP TEE API TEE_MACComputeFinal (processing_symm.c#L854) and then returned to the PKCS11 Client library.

@etienne-lms
Copy link
Contributor

The trick is done in the cryptoki API library. When a NULL ref is passed by caller, the API passes a 0 size non-null memref to the TA and expects CKR_BUFFER_TOO_SMALL return code which is converted back into a CKR_OK code. On TA side we always expect a buffer reference.

Regarding C_EncyptFinal() API function, the implementation (ck_signverify_final()) calls ckteec_alloc_shm() with a 0 size when sign_ref is NULL. When TA returns, we handle case CKR_BUFFER_TOO_SMALL && !sign_ref:

	if (sign_ref && sign_len && *sign_len)
		io = ckteec_register_shm(sign_ref, *sign_len,
					 sign ? CKTEEC_SHM_OUT : CKTEEC_SHM_IN);
	else
		io = ckteec_alloc_shm(0, sign ? CKTEEC_SHM_OUT : CKTEEC_SHM_IN);

	if (!io) {
		rv = CKR_HOST_MEMORY;
		goto bail;
	}

	rv = ckteec_invoke_ta(sign ? PKCS11_CMD_SIGN_FINAL :
			      PKCS11_CMD_VERIFY_FINAL, ctrl, NULL, io,
			      &io_size, NULL, NULL);

	if (sign && sign_len && (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL))
		*sign_len = io_size;

	if (rv == CKR_BUFFER_TOO_SMALL && io_size && !sign_ref)
		rv = CKR_OK;

The same sequence is implemented in other cryptoki API functions, for example ck_wrap_key() for C_WrapKey().

@anvisriv
Copy link
Author

Thanks for the explanation regarding the error codes. Could you also explain how the output_size would be handeled in these cases?

@anvisriv
Copy link
Author

Hi @etienne-lms
Gentle Reminder on the pending query.

@etienne-lms
Copy link
Contributor

etienne-lms commented Jan 19, 2024

Could you also explain how the output_size would be handeled in these cases?

The sequence is:

  1. Client calls C_SignFinal(session, NULL, &out_size);.
  2. Libckteec does not use the NULL reference but instead passes a 0 sized non-null pointer to pkcs11 TA.
  3. Pkcs11 TA calls related TEE API function for signing, passing 0 as output buffer size.
  4. OP-TEE OS returns TEE_ERROR_SHORT_BUFFER to the TA, passing back the requested output size.
  5. Pkcs11 TA returns with error code CK_BUFFER_TO_SMALL, passing the requested output size.
  6. Libckteec returns with code CKR_OK with out_size content set to the passed requested output size.
  7. Client gets CKR_OK and the output size, as expected and can allocate its buffer and call C_SignFinal() again.

Does that answer your question?

@anvisriv
Copy link
Author

Could you also explain how the output_size would be handeled in these cases?

The sequence is:

  1. Client calls C_SignFinal(session, NULL, &out_size);.
  2. Libckteec does not use the NULL reference but instead passes a 0 sized non-null pointer to pkcs11 TA.
  3. Pkcs11 TA calls related TEE API function for signing, passing 0 as output buffer size.
  4. OP-TEE OS returns TEE_ERROR_SHORT_BUFFER to the TA, passing back the requested output size.
  5. Pkcs11 TA returns with error code CK_BUFFER_TO_SMALL, passing the requested output size.
  6. Libckteec returns with code CKR_OK with out_size content set to the passed requested output size.
  7. Client gets CKR_OK and the output size, as expected and can allocate its buffer and call C_SignFinal() again.

Does that answer your question?

Hi @etienne-lms
Thanks for the explanation.
What is the expected behavior for step 4? Should OPTEE return the size and error code, or is it the responsibility of the GP TEE API?
If OPTEE OS is responsible for this behavior, then is this behavior specific to OS?

Also, can you please tell which PKCS11 specification(v2.4 or v3.1) does current implementation follow?

@etienne-lms
Copy link
Contributor

What is the expected behavior for step 4? Should OPTEE return the size and error code, or is it the responsibility of the GP TEE API?

It is part of the GP TEE Internal core API that there are functions that are expected to return TEE_ERROR_SHORT_BUFFER when an output buffer is either too small or is referred by a NULL pointer: these 2 methods allow a caller to get the required size of an output buffer.

Also, can you please tell which PKCS11 specification(v2.4 or v3.1) does current implementation follow?

We mainly follow the spec PKCS11 spec v2.4 with some extra support from the spec v3.0, if i'm right.

@anvisriv
Copy link
Author

Hi @etienne-lms

Can you please point me in the GP specification where it says it is supposed to return size in these cases?

@etienne-lms
Copy link
Contributor

This is described in section 3.4.4 [outbuf] in TEE Internal Core API specification v1.3.1:

  • If the output does not fit in the output buffer, then the implementation SHALL update *size with
    the required number of bytes and SHALL return TEE_ERROR_SHORT_BUFFER. It is
    implementation-dependent whether the output buffer is left untouched or contains part of the
    output. In any case, the TA SHOULD consider that its content is undefined after the function
    returns.

When the function returns TEE_ERROR_SHORT_BUFFER , it SHALL return the size of the output data.

@anvisriv
Copy link
Author

This is described in section 3.4.4 [outbuf] in TEE Internal Core API specification v1.3.1:

  • If the output does not fit in the output buffer, then the implementation SHALL update *size with
    the required number of bytes and SHALL return TEE_ERROR_SHORT_BUFFER. It is
    implementation-dependent whether the output buffer is left untouched or contains part of the
    output. In any case, the TA SHOULD consider that its content is undefined after the function
    returns.

When the function returns TEE_ERROR_SHORT_BUFFER , it SHALL return the size of the output data.

Hi @etienne-lms

Could you also explain why the size is expected in subtest https://github.com/OP-TEE/optee_test/blob/4.0.0/host/xtest/pkcs11_1000.c#L6001?

As per section 3.4.4,

On entry, *size contains the number of bytes actually allocated in buffer. The buffer with this
number of bytes SHALL be entirely writable by the Trusted Application; otherwise the implementation
SHALL panic the calling Trusted Application instance. In any case, the implementation SHALL NOT
write beyond this limit.

Also,

Note that if the caller sets *size to 0, the function will always return TEE_ERROR_SHORT_BUFFER unless
the actual output data is empty. In this case, the parameter buffer can take any value, e.g. NULL, as it
will not be accessed by the implementation. If *size is set to a non-zero value on entry, then buffer cannot
be NULL because the buffer starting from the NULL address is never writable.

@etienne-lms
Copy link
Contributor

Becareful. https://github.com/OP-TEE/optee_test/blob/4.0.0/host/xtest/pkcs11_1000.c#L6001 relies on the PKCS#11 API, not the GP TEE API.

PKCS#11 API behave differently:
When output buffer reference is NULL, the related PKCS#11 API function is expected to return CKR_OK and provide the output buffer size.
When output buffer reference is not NULL and the size is too smal, the related PKCS#11 API function is expected to return CKR_BUFFER_TOO_SMALL and to provide the output buffer size.

@anvisriv
Copy link
Author

Hi @etienne-lms
In this case, is the output size returned from the GP TEE Internal API or does the PKCS11 API handle the case internally? If it is the PKCS11 API, could you please point me to the code?

Also, could you please help with the flow for the below test case?

xtest_pkcs11_test_1018
subtest: https://github.com/OP-TEE/optee_test/blob/4.0.0/host/xtest/pkcs11_1000.c#L5100
The expected Result is CKR_OK
However, the PKCS11 TA will return PKCS11_CKR_ARGUMENTS_BAD from https://github.com/OP-TEE/optee_os/blob/4.0.0/ta/pkcs11/src/processing_digest.c#L199.
Is this analysis correct?

@etienne-lms
Copy link
Contributor

The test instruction you point to calls C_DigestFinal(session, NULL, &disgest_size) hence providing a NULL output buffer reference.

C_DigestFinal() is implemented by libckteec library: it calls ck_digest_final() that allocates an output buffer and invokes the pkcs11 with an output size set to 0 (here).
The function expects return code CKR_BUFFER_TOO_SMALL in which case it converts the return code into CKR_OK (here) and sets the output size to the size provided by the TA (here).
If everything goes as expected, xtest pkcs11_1018 get return code CKR_OK (here) and the requested output buffer size (here).

It the pkcs11 returns PKCS11_CKR_ARGUMENTS_BAD, then something went wrong and this return code to provided to the caller xtest application.

@anvisriv
Copy link
Author

anvisriv commented Feb 2, 2024

Hi @etienne-lms
Thanks for the explanation above.
Can you please help with the below queries as well?

  • Is TEE_ALG_RSAES_PKCS1_V1_5 specific to OPTEE OS? If not, where can I find information about it in the GlobalPlatform (GP) specification? I could only find the symbol with Hash algorithm appended to it and not without it.

  • Which specification does OPTEE OS libmbedtls follow?

@etienne-lms
Copy link
Contributor

TEE_ALG_RSAES_PKCS1_V1_5 is indeed a GlobalPlatform defined identifier. See "Table C-1: Normative References for Algorithms", page 365 of the GP TEE Internal Core API spec v1.3.1.

Libmbedtls integrated in OP-TEE is based on mainline mbedtls (https://github.com/Mbed-TLS/mbedtls.git). Its revision tag depends on the OP-TEE release tag. Latest OP-TEE, since tag 4.0.0 is based on mbedtls-3.4.0; OP-TEE tags 3.19.0 to 3.22.0 were based on mbedtls-2.28.1; etc... See the Git history of OP-TEE OS directory lib/libmbedtls for more information.

@anvisriv
Copy link
Author

anvisriv commented Feb 19, 2024

Hi @etienne-lms

  1. Can you please help with TEE_ALG_RSASSA_PKCS1_V1_5 also? Is it OPTEE specific? If not, where can I find information about it in the GlobalPlatform (GP) specification?

  2. According to the GP specification for TEE_AsymetricSignDigest, if digestLen is not equal to the hash size of the algorithm in non-XOF (extendable output function) functions, panic will happen. Regarding the Test1019, where the digest_test_pattern_sha256 is used, shouldn't it be changed to digest_test_pattern_sha512 in the subtest?

@anvisriv
Copy link
Author

Hi @etienne-lms
Did you get a chance to check on this?

@etienne-lms
Copy link
Contributor

TEE_ALG_RSASSA_PKCS1_V1_5 is also defined in "Table C-1: Normative References for Algorithms" of the GP TEE Internal Core API spec v1.3.1, see page 364.

  1. According to the GP specification ...

You mean the pkcs11 TA should have panicked for that test? We need to cross check this.

@anvisriv
Copy link
Author

Hi @etienne-lms

TEE_ALG_RSASSA_PKCS1_V1_5 is also defined in "Table C-1: Normative References for Algorithms" of the GP TEE Internal Core API spec v1.3.1, see page 364.

The TEE_ALG_RSASSA_PKCS1_V1_5 is used in combination with SHA, but unlike TEE_ALG_RSAES_PKCS1_V1_5, there is no standalone symbol defined for it. Could you please verify once more if this symbol is specific to OPTEE?

@etienne-lms
Copy link
Contributor

My bad, I was to quick grepping into the spec document.
Indeed TEE_ALG_RSASSA_PKCS1_V1_5 is an OP-TEE extension to the GP spec. It is defined in lib/libutee/include/tee_api_defines_extensions.h. Explanation can be found in commit 6a2e0a9.

@anvisriv
Copy link
Author

anvisriv commented Feb 29, 2024

Hi @etienne-lms

For ECDSA usecase, TA is determining TEE algorithm based on the key size of ECDSA(here) while the GP specification v1.3 in section B.3 Deprecated Algorithm Identifiers Page 352 says:

ECDSA algorithm identifiers should be tied to the size of the digest, not the key. The key size information is provided with the key material.

Can you please confirm what is the right expectation?

Adding one more query.
What is the ideal configuration for libutils and libmbedtls library to support PKCS11 TA's RSA AES wrap key use case ?

@anvisriv
Copy link
Author

anvisriv commented Mar 6, 2024

Hi @etienne-lms did you get a chance to check?

@anvisriv
Copy link
Author

anvisriv commented Mar 8, 2024

Hi @etienne-lms
In wrap_rsa_aes call flow,
wrap_rsa_aes_key --> mbedtls_nist_kw_setkey --> mbedtls_cipher_setup -> ctx_alloc_func --> (becuase it is AES, call flow should be coming to aes_ctx_alloc --> mbedtls_calloc --> calloc -> raw_calloc --> bgetz --> bget

In bget there is while (b != &poolset->freelist) but i see that this condition will never be true, as in bget_malloc.c , poolset->freelist.ql.flink = &poolset->freelist, consequently always NULL is returned.

Assuming all the BGET configurations are disabled. In the above call flow i didn't find where the poolset's freelist is getting modified to return otherwise from bget.

Can you please guide and clarify the understanding?

@anvisriv
Copy link
Author

Hi @etienne-lms

Adding one more question to the list :)
GP specification for TEE_PopulateTransientObject (Section 5.6.4 Table 5-10), in case of TEE_TYPE_RSA_KEYPAIR says,

The following attributes SHALL be provided:
TEE_ATTR_RSA_MODULUS
TEE_ATTR_RSA_PUBLIC_EXPONENT
TEE_ATTR_RSA_PRIVATE_EXPONENT
The CRT parameters are optional. If any of these attributes is
provided, then all of them SHALL be provided:
TEE_ATTR_RSA_PRIME1
TEE_ATTR_RSA_PRIME2
TEE_ATTR_RSA_EXPONENT1
TEE_ATTR_RSA_EXPONENT2
TEE_ATTR_RSA_COEFFICIENT

But, in case of test 1026, the test client is only setting first 5 attributes for unwrapping key. Will it not cause any issue in TEE_PopulateTransientObject in case of Unwrap usecase?

@etienne-lms
Copy link
Contributor

Sorry, I've not looked at your request. I'll try to find a bit of time....

@anvisriv
Copy link
Author

Hi @etienne-lms
Can you also share what are the appropriate inputs that needs to be passed when EncryptUpdate and EncryptFinal are used? Also, for DecryptUpdate/DecryptFinal?

@anvisriv
Copy link
Author

Hi @etienne-lms

Did you got a chance to check?

@etienne-lms
Copy link
Contributor

Hi @anvisriv, sorry for my late feedback.

/Regarding comment #721 (comment):

Can you also share what are the appropriate inputs that needs to be passed when EncryptUpdate and EncryptFinal are used? Also, for DecryptUpdate/DecryptFinal?

These API functions are described in the PKCS#11 spec (e.g. https://docs.oasis-open.org/pkcs11/pkcs11-base/v3.0/os/pkcs11-base-v3.0-os.html#_Toc29976646 for C_EncryptUpdate()). I strongly recommend to read the spec to properly use the PKCS#11 interface. OP-TEE's implementation of this interface is expected to follow the spec. Do you have questions on our implementation or on the spec itself?

/Regarding comment #721 (comment):

GP specification for TEE_PopulateTransientObject (Section 5.6.4 Table 5-10), in case of TEE_TYPE_RSA_KEYPAIR says,
...
But, in case of test 1026, the test client is only setting first 5 attributes for unwrapping key. Will it not cause any issue in TEE_PopulateTransientObject in case of Unwrap usecase?

Unless I missed something, the pkcs11 TA does consider this constriaint: see https://github.com/OP-TEE/optee_os/blob/4.2.0/ta/pkcs11/src/processing_rsa.c#L562-L593.

/Regarding comment #721 (comment) on bget:

I'm not shure to understand your question. Do you face issues with bget allocator integration? It's been used since a while in OP-TEE core and TAs.
I found this article on Bget (how its OP-TEE integration and miss-use could lead to exploits) maybe it can help you:
https://phi1010.github.io/2020-09-14-bget-exploitation/ and https://phi1010.github.io/2020-11-02-bget-exploitation-2/.

/Regarding comment #721 (comment) on ECDSA and PKCS#11 key wrapping with RSA:

For ECDSA usecase, TA is determining TEE algorithm based on the key size of ECDSA ...

This is still an open point. A pull request was created last summer but stalled before reaching a clean conclusion, see OP-TEE/optee_os#6230. I think the issue is still pending and deserves investigation.

What is the ideal configuration for libutils and libmbedtls library to support PKCS11 TA's ... ?

Pkcs11 TA implementation embeds MbedTLS library and supports key wrapping. There is nothing to configure, but ensure the TA heap is sized enough (CFG_PKCS11_TA_HEAP_SIZE), your platform produces good quality random bytes, and the RSA key used to wrap the AES key is well sized (I think an RSA key of at least 3072bit is recommended for protection of a 128byte AES key, but you should better crosscheck this information).

@anvisriv
Copy link
Author

anvisriv commented Apr 21, 2024

Hi @etienne-lms

Unless I missed something, the pkcs11 TA does consider this constriaint: see https://github.com/OP-TEE/optee_os/blob/4.2.0/ta/pkcs11/src/processing_rsa.c#L562-L593.

Even in the absence of exponent1, exponent2, and coefficient, the count will continue to increment, potentially leading to complications when invoking TEE_PopulateTransientObject. Can you please reverify on your end?

Also, thanks for other references.

@etienne-lms
Copy link
Contributor

Hi @anvisriv, I took the liberty of creating a P-R for the RSA attributes in the pkcs11 TA. Please see OP-TEE/optee_os#6815.

@anvisriv
Copy link
Author

Hi @etienne-lms
Could you please provide more details on how this change will address the previously discussed issue?
Is it feasible to include a memory leak test case that detects memory leaks in both the PKCS11 library and the Trusted Application (TA)?

@etienne-lms
Copy link
Contributor

Could you please provide more details on how this change will address the previously discussed issue?

This change ensures that rc = PKCS11_CKR_OK only if count == 8 before the break instruction (line 597).

Is it feasible to include a memory leak test case that detects memory leaks in both the PKCS11 library and the Trusted Application (TA)?

I guess it is feasible. Proposals are welcome.
One way to test the TA against heap allocation leakage (is that what you mean by "memory leaks"?) is to run a usecase (some operation) many times. TA heap is quite small (few kBytes, see CFG_PKCS11_TA_HEAP_SIZE) so heap leakage should soon trigger a CKR_DEVICE_MEMORY error.
As for the pkcs11 lib (libckteec) heap leakage, it will be a bit harder I think as Linux applications heap is far bigger.

@jforissier
Copy link
Contributor

Is it feasible to include a memory leak test case that detects memory leaks in both the PKCS11 library and the Trusted Application (TA)?

I guess it is feasible. Proposals are welcome. One way to test the TA against heap allocation leakage (is that what you mean by "memory leaks"?) is to run a usecase (some operation) many times. TA heap is quite small (few kBytes, see CFG_PKCS11_TA_HEAP_SIZE) so heap leakage should soon trigger a CKR_DEVICE_MEMORY error.

Maybe the statistics PTA could be used to query the TA heap size before and after the test ?

@anvisriv
Copy link
Author

This change ensures that rc = PKCS11_CKR_OK only if count == 8 before the break instruction (line 597).

Hi @etienne-lms, the count will increase regardless of whether the value is NULL or not NULL, as there is no condition to stop the execution or treat it as an error. Furthermore, the code should handle these three scenarios:

  1. The client provides 3 attributes.
  2. The client provides 8 attributes.
  3. The client supplies a number of attributes that is either less than 3 or more than 3 but less than 8.
    Please let me know if i have missed anything.

I guess it is feasible. Proposals are welcome. One way to test the TA against heap allocation leakage (is that what you mean by "memory leaks"?) is to run a usecase (some operation) many times. TA heap is quite small (few kBytes, see CFG_PKCS11_TA_HEAP_SIZE) so heap leakage should soon trigger a CKR_DEVICE_MEMORY error. As for the pkcs11 lib (libckteec) heap leakage, it will be a bit harder I think as Linux applications heap is far bigger.

How about we consider redefining malloc, calloc, free, and realloc using macro to track memory allocation in libckteec? This approach may require changes in most of the source code of the library.
Or, is it possible to hook up Valgrind?

Maybe the statistics PTA could be used to query the TA heap size before and after the test ?

Sure, will have a look at it for detecting memory leak in TA.

@etienne-lms
Copy link
Contributor

Hi @etienne-lms, the count will increase regardless of whether the value is NULL or not NULL, as there is no condition to stop the execution or treat it as an error. Furthermore, the code should handle these three scenarios:

The client provides 3 attributes.
The client provides 8 attributes.
The client supplies a number of attributes that is either less than 3 or more than 3 but less than 8.
Please let me know if i have missed anything.

Would you be ok to post comments in OP-TEE/optee_os#6815 and discuss the fix on that P-R?

I think the P-R is okay: load_tee_rsa_key_attrs() will succeed only if either the 3 mandatory attributes are found, or if the 8 attributes are found. If the attribute are wrong (e.g. empty) then I expect the TEE operation using the key to fail. But I may have missed something, please fell free to contradict me.

As for the pkcs11 lib (libckteec) heap leakage, it will be a bit harder I think as Linux applications heap is far bigger.

How about we consider redefining malloc, calloc, free, and realloc using macro to track memory allocation in libckteec? This approach may require changes in most of the source code of the library.
Or, is it possible to hook up Valgrind?

I guess using Valgrind could help. Instrumenting allocation from libckteec looks also a good solution. Feel free to propose change if you have some ideas.

@anvisriv
Copy link
Author

anvisriv commented May 17, 2024

Hi @etienne-lms

think the P-R is okay: load_tee_rsa_key_attrs() will succeed only if either the 3 mandatory attributes are found, or if the 8 attributes are found. If the attribute are wrong (e.g. empty) then I expect the TEE operation using the key to fail. But I may have missed something, please fell free to contradict me.

Sure.

I guess using Valgrind could help. Instrumenting allocation from libckteec looks also a good solution. Feel free to propose change if you have some ideas.

Are there any steps available for using Valgrind on PKCS11 TA/lib or any other OPTEE TA/lib?

Is ECDHE key derivation supported in PKCS11 lib? I didn't find any test case but see that it is present in TA. Can you please confirm?

@etienne-lms
Copy link
Contributor

Are there any steps available for using Valgrind on PKCS11 TA/lib or any other OPTEE TA/lib?

libckteec is a Linux userland library. It should be quite easy I guess to use Valgrind on this library.
Regarding TAs library (libraries used by OP-TEE Trusted Applications), there is no support for Valgrind.

Is ECDHE key derivation supported in PKCS11 lib? I didn't find any test case but see that it is present in TA. Can you please confirm?

True, ECDH is supported but there are no test available in xtest.

@anvisriv
Copy link
Author

anvisriv commented Jun 10, 2024

Hi @etienne-lms
Can you please confirm whether following features are supported in PKCS11?

  1. Multiclient and Multithreading support (By multiclient it means multiple application tries to request TA service simultaneously.)
  2. CKM_ECDH1_DERIVE and CKM_ECDH1_COFACTOR_DERIVE mechanism support
  3. CKM_HKDF_DERIVE mechanism support
  4. Test cases related to above features

If not, is there any plan to support above features in upcoming releases?

@anvisriv
Copy link
Author

Hi @etienne-lms any update?

@etienne-lms
Copy link
Contributor

Hi @anvisriv

Multiclient and Multithreading support (By multiclient it means multiple application tries to request TA service simultaneously.)

If Multiclient & Multithreading means concurrently executing PKCS#11 services, then no, it is not supported: the pkcs11 TA processes requests 1 by 1, sequentially. See discussion thread OP-TEE/optee_os#6900.

CKM_ECDH1_DERIVE and CKM_ECDH1_COFACTOR_DERIVE mechanism support
CKM_HKDF_DERIVE mechanism support

CKM_ECDH1_DERIVE is implemented (currently only supports KDF type CKD_NULL), but sorry, I see it lacks test cases in optee_test.
CKM_ECDH1_COFACTOR_DERIVE and CKM_HKDF_DERIVE are not supported.
There are currently no plan for them, AFAICT. Contributions and proposal are welcome, of course.

@anvisriv
Copy link
Author

Hi @etienne-lms
Any reason why TOKEN_COUNT is set to 3 in the TA?
Also, there were few more queries related to guidelines mentioned in PKCS11 specification. Can you please suggest if this will be the right forum to discuss those questions?

@etienne-lms
Copy link
Contributor

Any reason why TOKEN_COUNT is set to 3 in the TA?

The value was initially set to 3 to default have at least a token for platforms needs and a token for test purpose that would not mess up with the token used for some real use case in the default configuration. OP-TEE test uses the last token ID for pkcs11 non-regression tests. 3 is quite empiric. It could have been 2.

Also, there were few more queries related to guidelines mentioned in PKCS11 specification. Can you please suggest if this will be the right forum to discuss those questions?

I guess this is the right forum for question on the PKCS#11 TA. My apologies if I missed some of your questions. Please resend them as a comment post in this Issue or using a dedicate Issue entry.

@dlansky1
Copy link

Hi,

Regarding Multithreading support, can you address this from reentrancy point of view?
I understand GP/TA would serialize the calls. What about libckteec?
Let's say we have two HLOS threads running in parallel, which perform the same crypto operation, on same slot and session, would that work as expected (both succeed) ?

@etienne-lms
Copy link
Contributor

etienne-lms commented Jun 27, 2024

TAs are not reentrant, applies to the pkcs11 TA.
libckteec API functions are reentrant.
If 2 (or more) threads are running in parallel and invoke the pkcs11 TA, the first reaching the TA will get its request processed first and the second will get is its request processed once the TA is done with the 1st request. Threads that need to wait are queued in a wait queued queue in the Linux kernel. Whenever a TA instance completes a command execution, if there are pending requests, OP-TEE notifies waiters in the Linux kernel that the TA instance is now available. This scheme applies whatever the requests to the pkcs11 TA are, being the same or completely different.

@anvisriv
Copy link
Author

Hi @etienne-lms

  1. Can you please clarify in what scenario *_VENDOR_DEFINED can be used? Also, it would be helpful if you can share some examples.
  2. Why is PKCS11 TA using libmbedtls library for some of its usecases?
  3. What is the use of CFG_PKCS11_TA_AUTH_TEE_IDENTITY flag?

@etienne-lms
Copy link
Contributor

Hi @anvisriv,

Can you please clarify in what scenario *_VENDOR_DEFINED can be used? Also, it would be helpful if you can share some examples.

There are several areas where the PKCS#11 spec allows vendor to define IDs that are not interoperable: object classes, HW capabilities, key types and object attributes. They allow client applications to use vendor specific token features assuming the client application knows it interacts with a compliant vendor token.

In OP-TEE pkcs11 TA, we currently use only 1 vendor attribute ID, for EC private keys to store the curve point. This is driven by a requirement in the GP TEE API spec. However, OP-TEE pkcs11 TA does not expose this attribute to the client so it remains inside the pkcs11 TA and is not expected have interoperability impacts with standard PKCS#11 clients.

Why is PKCS11 TA using libmbedtls library for some of its usecases?

OP-TEE pkcs11 TA relies on GP TEE Internal Core API spec for persistent storage and crypto operations (and a bit more). However, the GP TEE spec we're based on does not provide some operations needed for few PKCS#11 features while mbedTLS lib does and is available to OP-TEE TAs since a while. Therefore, we use mbedtls for some operations, see
OP-TEE/optee_os@45d40bd "ta: pkcs11: Add RSA AES key wrap" and
OP-TEE/optee_os@7c24332 "ta: pkcs11: fix EC private key import".

What is the use of CFG_PKCS11_TA_AUTH_TEE_IDENTITY flag?

This feature allows to replace the PKCS#11 client login/authentication (supervisor and user) based on PIN with an client authentication based on Linux OS user ID or group ID (managed by Linux ACL). When CFG_PKCS11_TA_AUTH_TEE_IDENTITY is enabled, a token can be initialized to define the Linux user ID or group ID that be able to login/authenticate into the related token. The feature uses CKFT_PROTECTED_AUTHENTICATION_PATH to state that login is not more based on a PIN but on an alternate path (that is Linux ACL identities).
See https://github.com/OP-TEE/optee_os/blob/4.3.0/ta/pkcs11/include/pkcs11_ta.h#L886-L939 for more details.

@anvisriv
Copy link
Author

anvisriv commented Aug 14, 2024

Hi @etienne-lms

Q1. Will token object persist in scenario described below?

  1. Client creates a token object (obj_hdl_a)
  2. Performs operation with that object
  3. Closes the session with the token
  4. Again opens a session with the same token
  5. And tries to use the same token object (obj_hdl_a)

Q2. When a TEE_PANIC occurs due to a specific scenario in TZ, is there a method for the client to identify the root cause? (say if TEE_PANIC happens if heap memory runs out)

Q3. Are there any restrictions on mechanisms or interfaces for key objects created through hardware tokens? Additionally, which attribute distinguishes objects created from hardware versus software solutions? Is it possible to have CKA_HW_FEATURE_TYPE used for key objects making it CKH_VENDOR_DEFINED?

@anvisriv
Copy link
Author

Why is PKCS11 TA using libmbedtls library for some of its usecases?

OP-TEE pkcs11 TA relies on GP TEE Internal Core API spec for persistent storage and crypto operations (and a bit more). However, the GP TEE spec we're based on does not provide some operations needed for few PKCS#11 features while mbedTLS lib does and is available to OP-TEE TAs since a while. Therefore, we use mbedtls for some operations, see OP-TEE/optee_os@45d40bd "ta: pkcs11: Add RSA AES key wrap" and OP-TEE/optee_os@7c24332 "ta: pkcs11: fix EC private key import".

Can you please elaborate on what was the delta because of which there was a requirement to use libmbedtls?

etienne-lms added a commit to etienne-lms/optee_os that referenced this issue Aug 21, 2024
Fix RSA key attributes function load_tee_rsa_key_attrs() that badly
checks that the 5 extended RSA attributes are found in the key object.

Link: OP-TEE/optee_test#721 (comment)
Link: OP-TEE/optee_test#721 (comment)
Fixes: 0442c95 ("ta: pkcs11: Add support for RSA signing & verification")
Signed-off-by: Etienne Carriere <[email protected]>
Reviewed-by: Vesa Jääskeläinen <[email protected]>
jforissier pushed a commit to OP-TEE/optee_os that referenced this issue Aug 21, 2024
Fix RSA key attributes function load_tee_rsa_key_attrs() that badly
checks that the 5 extended RSA attributes are found in the key object.

Link: OP-TEE/optee_test#721 (comment)
Link: OP-TEE/optee_test#721 (comment)
Fixes: 0442c95 ("ta: pkcs11: Add support for RSA signing & verification")
Signed-off-by: Etienne Carriere <[email protected]>
Reviewed-by: Vesa Jääskeläinen <[email protected]>
@anvisriv
Copy link
Author

Hi @etienne-lms
Gentle Reminder!

@etienne-lms
Copy link
Contributor

Hi @anvisrv, sorry for that late answer.

Q1. Will token object persist in scenario described below?

  1. Client creates a token object (obj_hdl_a)
  2. Performs operation with that object
  3. Closes the session with the token
  4. Again opens a session with the same token
  5. And tries to use the same token object (obj_hdl_a)

The current pkcs11 TA implementation is made so that object handle at step 5. indeed refers to the initial persistent object. But that is an implementation side effect and implementation can change (for example if the client closes all its sessions towards the pkcs11 TA token). I strongly suggest your client rather relies on the PKCS#11 specification: at step 5, it is safer to find the object (C_FindObjects*()) to ensure you get a reliable object handle.

Q2. When a TEE_PANIC occurs due to a specific scenario in TZ, is there a method for the client to identify the root cause? (say if TEE_PANIC happens if heap memory runs out)

In case of a TA panic, the client only gets a "TEE_ERROR_TARGET_DEAD" code. In case of a core panic, system will likely hang AFAICT. In both case, only OP-TEE core trace messages can give you some hints of what could have happened.

Q3. Are there any restrictions on mechanisms or interfaces for key objects created through hardware tokens?

The PKCS#11 spec puts no restrictions on that but allows tokens (hardware or software ones) to have specific restrictions.

Additionally, which attribute distinguishes objects created from hardware versus software solutions? Is it possible to have CKA_HW_FEATURE_TYPE used for key objects making it CKH_VENDOR_DEFINED?

We could introduce a vendor specific attribute to object in the pkcs11 TA but I would not recommend that in the generic pkcs11 TA since such attribute you be meaningful only for specif vendor client applications.

>> Why is PKCS11 TA using libmbedtls library for some of its usecases?
> (...)
Can you please elaborate on what was the delta because of which there was a requirement to use libmbedtls?

Regarding CKM_RSA_AES_KEY_WRAP, the issue is NIST key wrapping (NIST SP 800-38F) not being supported by the GP TEE API but being supported by MbedTLS API, as detailed in the commit message:
"The mechanism requires AES KWP mechanism CKM_AES_KEY_WRAP_KWP which is not currently implemented in OP-TEE nor mentioned in Global Platform specification.
Use the MBedTLS to wrap/unwrap the target key."

Regarding EC private key import, the issue is GP TEE API require a private key object to also relate to a public key but that API does while the PKCS#11 API allows a client to import only a private key. Because the GP TEE API does not allow to generate a public key from a private key, we use MbedTLS API to generate an EC point as an object attribute of the PKCS11 object that is not exposed to client and only remains in the TA for internal use.

@anvisriv
Copy link
Author

Hi @etienne-lms
Is there an attribute that can prevent the deletion of key objects even if the client reinitializes the token? The CKA_DESTROYABLE attribute can restrict object deletion, but it doesn’t apply in the case of reinitialization, correct?

@etienne-lms
Copy link
Contributor

The CKA_DESTROYABLE attribute can restrict object deletion, but it doesn’t apply in the case of reinitialization, correct?

That is right.

The PKCS#11 specification allows token to have objects not destroyed when the token is initialized. Such are vendor specific. I think we can introduce a vendor specific object boolean attribute ID for objects that are to be always persistent. It should be clear however who is responsible for loading such objects: I think at least only SO or maybe USER should be allowed to create such object.

@dlansky1
Copy link

Hi @etienne-lms,
Can we open a feature request for such "indestructible" boolean attribute?

@etienne-lms
Copy link
Contributor

Sure, you are free to create a pull request for any contribution you would like to be discussed.
Do you really expect such object to be "indestructible"? Even an SO logged-in application should not be able to destroy it?

@dmukhopa
Copy link

dmukhopa commented Oct 3, 2024

Hi @etienne-lms,

I have noticed that for many PKCS11 mechanisms, test cases have been added to the "optee_test" repository. For instance, test cases for CKM_AES_GCM can be found here:

static void xtest_pkcs11_test_1030(ADBG_Case_t *c)
.

However, I observed that test cases for CKM_ECDH1_DERIVE have not been included in the "optee_test" repository. Instead, PKCS11-tool was used for testing this mechanism.

Could you please clarify why CKM_ECDH1_DERIVE related test cases were not added to "optee_test" and is there any plan to include these test cases in the future?

Additionally, is there any future plan to integrate pkcs11-tool to "optee test" repository?

Thanks in advance.

@etienne-lms
Copy link
Contributor

etienne-lms commented Oct 4, 2024

Could you please clarify why CKM_ECDH1_DERIVE related test cases were not added to "optee_test" and is there any plan to include these test cases in the future?

Indeed, it would be better we have a xtest test case for CKM_ECDH1_DERIVE. I'll try to if I find time. Contributions are welcome.

Additionally, is there any future plan to integrate pkcs11-tool to "optee test" repository?

No and I don't think it would add much value. One can pick the pkcs11-tool source tree and build it if needed.

If your are using Buildroot, you only have to enable BR2_PACKAGE_OPENSC=y to embed pkcs11-tool in your system. That is what we do in the OP-TEE release distribution.

Using Yocto, using the opensc layer and adding opensc in the package list should also do the work.

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

No branches or pull requests

5 participants