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

ta: pkcs11: Build time option for controlling pin locking #7040

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

Conversation

TanelDettenborn
Copy link

Proposing a new build time option for pkcs11 TA. Proposed option would enable or disable pin locking after failed authentication attempts. Option would control both pins (User and SO). Default value is 'y'/enabled.

In other worlds option would allow unlimited authentication attempts, but in certain specific scenarios it is desirable. As an example scenario would be pkcs11 token proxy access. A malicious actor could execute DDOS attack and could lock pin after 2³32 attempts (pin count stored uint32_t). A mitigation could be unlimited login attempts and using a long pin (mitigate against brute force attack).

Adding a build time option for disabling or enabling pin
locking after failed authentication attempts. Option
controls both, User and SO, pins. Default is 'y'.

Option is called:
 CFG_PKCS11_TA_LOCK_PIN_AFTER_FAILED_LOGIN_ATTEMPTS

Signed-off-by: Tanel Dettenborn <[email protected]>
@etienne-lms
Copy link
Contributor

Thanks @TanelDettenborn for the proposal.
I'm not fully convinced this is the good way. Could limiting login attempts on time periods upon consecutive login failure help here? I'd rather have the feed back from other pkcs11 TA contributors. @vesajaaskelainen, do you have any advise on this?
By the way, i'd rather have another name for the config switch, so that we would not be confused with older implementation that do not enable such config switch, e.g. CFG_PKCS11_TA_UNLIMITED_PIN_ATTEMPTS ?= n.

@vesajaaskelainen
Copy link
Contributor

vesajaaskelainen commented Sep 24, 2024

PIN in embedded devices is a bit of problem as by PKCS#11 standard it can cause the locked out scenario that you describe.

We have one existing solution around this is to use "TEE Identity based authentication for tokens".
https://github.com/OP-TEE/optee_os/blob/master/ta/pkcs11/include/pkcs11_ta.h#L886-L939

This method disables the lockdown counter completely when method is activated for the token.

There is access protection feature in Linux kernel that makes sure that group membership is checked for calling process.

This authentication happens when connection is made from user space to PKCS#11 TA:
https://github.com/OP-TEE/optee_client/blob/master/libteec/src/tee_client_api.c#L541-L641

There is also support library in here in case you want to handle this:
https://github.com/OP-TEE/optee_client/blob/master/libteeacl/include/teeacl.h

When active for the token you just make sure that your calling process has needed credentials and just supply dummy PIN.

I have a bit old instructions on how to use this in here:
https://github.com/vesajaaskelainen/meta-optee-demo

And here is also Linaro conference recording with demonstration:
https://www.youtube.com/watch?v=7pBzFlrZdTI

And the asciinema script for that demonstration:
https://asciinema.org/a/432598

Would this work for you?

@vesajaaskelainen
Copy link
Contributor

Thanks @TanelDettenborn for the proposal. I'm not fully convinced this is the good way. Could limiting login attempts on time periods upon consecutive login failure help here?

I suppose the "TEE Identity based authentication for tokens" gives a bit prettier approach but may not be usable in all scenarios.

Today many systems seem to utilize cool down period on login failures -- this could be volatile implementation eg. does not go into token itself but stays in memory. I suppose the problem here is that it would require concept of monotonic time. Now we come to problem what does different users want from the feature.

Problem with the code proposed here allows one to quite easily bruteforce the PINs.

@vesajaaskelainen
Copy link
Contributor

In other worlds option would allow unlimited authentication attempts, but in certain specific scenarios it is desirable. As an example scenario would be pkcs11 token proxy access. A malicious actor could execute DDOS attack and could lock pin after 2³32 attempts (pin count stored uint32_t). A mitigation could be unlimited login attempts and using a long pin (mitigate against brute force attack).

Today if you get access to OP-TEE PKCS#11 API you can cause PIN lockout much faster:
https://github.com/OP-TEE/optee_os/blob/master/ta/pkcs11/src/pkcs11_token.h#L44-L45

There is room for extra entropy for the PIN:
https://github.com/OP-TEE/optee_os/blob/master/ta/pkcs11/src/pkcs11_token.h#L42-L43
https://github.com/OP-TEE/optee_os/blob/master/ta/pkcs11/src/pkcs11_token.h#L73
https://github.com/OP-TEE/optee_os/blob/master/ta/pkcs11/src/persistent_token.c#L74-L113

I would prefer a solution that can be active for all users and they can just select it during runtime -- this would make it practical for someone else to use. Eg. if OP-TEE is part of some standard distribution then end-user does not need to guess whether the feature is available. Compile time enablements are always very firmware specific options.

@TanelDettenborn
Copy link
Author

@vesajaaskelainen and @etienne-lms I appreciate your time and attention in reviewing my pull request. Hopefully I am able to address all of your feedback.

"TEE Identity based authentication for tokens" is a practical and a neat feature, but unfortunately in our scenario it does not truly work. It would work partially, because we have a proxy setup and therefore only proxy daemon would interact with TEE/PKCS11 token. In matter of fact we are taking an extra step for enforcing pin usage by compiling our PKCS11 TA with CFG_PKCS11_TA_AUTH_TEE_IDENTITY=n.

Perhaps it would be a good idea to put some meat into discussion? I have at my dissposal NVIDIA's Orin NX board with our configuration. I would not put too much focus on board's configuration due following test is anyway highly hardware and configuration specific: Banging 60 second incorrect pin.

Following script uses OpenSC's pkcs11-tool for banging incrroct login from host (no proxies involved)

alias p11="pkcs11-tool-optee --slot-index 0 --label test"
p11 --init-token --so-pin 1111
p11 --init-pin --login --so-pin 1111 --new-pin 2222
end=$((SECONDS+60))
counter=0
while [ $SECONDS -lt $end ]; do
p11 --login --pin 1234 --list-object 1> /dev/null 2> /dev/null
counter=$((counter + 1))
done
echo $counter

Results (average of three execution)
a. Unlimited logins attemps ~5.7k
b. Limited login ~1.2k (note: PKCS11_TOKEN_USER_PIN_COUNT_MAX was increased)

If above results are analyzed from DDOS and brute force attack perspective

  1. My patch significantly eases brute force attack by removing a slow "DB-update"-operation
  2. Reaching PKCS11_TOKEN_USER_PIN_COUNT_MAX ((2^32)-1) would require roughly of 7 year of execution (note: pin counter is zeroed in every succesfull login!)

In overall I would judge both attacks impact as severe, but exploitability low.


Problem with the code proposed here allows one to quite easily bruteforce the PINs.

True! Unlimited logins exposes PKCS11 token to brute force attacks, but it can be mitigated with long pin(s). OP-TEE's PKCS11 TA supports pins sizes up to 128 characters and it should be sufficient pin space for rendering brute force attacks impractical.

Today many systems seem to utilize cool down period on login failures -- this could be volatile implementation eg. does not go into token itself but stays in memory. I suppose the problem here is that it would require concept of monotonic time. Now we come to problem what does different users want from the feature.

I agree, but in our case timeout-solution would be another avenue for DDOS.

I would prefer a solution that can be active for all users and they can just select it during runtime -- this would make it practical for someone else to use. Eg. if OP-TEE is part of some standard distribution then end-user does not need to guess whether the feature is available. Compile time enablements are always very firmware specific options.

I have proposed it as build time option, because I have rationalized that this should be option, which should be used with extra care. Token/solution should design from the beginning in this feature in mind rather later toggle it on/off. For example designer could enforce minimum pin size at the compile time.

By the way, i'd rather have another name for the config switch, so that we would not be confused with older implementation that do not enable such config switch, e.g. CFG_PKCS11_TA_UNLIMITED_PIN_ATTEMPTS ?= n.

I was too attached to not to use exlamation mark. Your suggestion is a lot better than my!

In conclusion I would raise a question if this is a feature that you would like to add into PKCS11 TA? If you feel it is a feature for a specific niche and would not like to bloat PKCS11 TA code then we could close this pull request. But if it usable for others also then I can put some effort in and rework it. I think that I would propose e.g. "1ms sleep" into check pin functions (mitigate brute force). I can also separate SO and USER into different compile flags.

@vesajaaskelainen
Copy link
Contributor

In conclusion I would raise a question if this is a feature that you would like to add into PKCS11 TA? If you feel it is a feature for a specific niche and would not like to bloat PKCS11 TA code then we could close this pull request. But if it usable for others also then I can put some effort in and rework it. I think that I would propose e.g. "1ms sleep" into check pin functions (mitigate brute force). I can also separate SO and USER into different compile flags.

Could you describe your use case in more practical level?. Eg. what kind of setup you are trying to do?

Any added details would help with pondering what is the best course of action.

So far the main use cases (as far as I know) has been protecting private keys/secrets within embedded device and there are no pkcs11 proxies. In embedded device the PIN is problematic as it is a bit hard to protect so the user/group/application based authentication takes that problem away and works in closed embedded device quite OK.

With pkcs11 proxy you need to also think how persistent the connection to the token would be. Eg. how often the PIN would need to be asked as pkcs11 proxy may keep the connection to the token open for long periods of time. With some HSM solutions there are "security world / PIN preload" applications that let you enter the PIN in controlled manner and then allow other automation to utilize pkcs11 tokens thru the pkcs11 proxy without having the access for real PIN. This of course requires then additional protection for the pkcs11 proxy access.

Now I don't know what kind of use case/solution you are targeting.

@TanelDettenborn
Copy link
Author

Could you describe your use case in more practical level?. Eg. what kind of setup you are trying to do?

Any added details would help with pondering what is the best course of action.

Hmm.. In short it is about security. Increasing maximum login attempts to its maximum possible value would not be same as unlimited login attempts even if both would lead to almost identical result (obviously the end result is case depended). In more practical terms our setup involves Virtual Machines. The setup has VMs and they require access to hardware PKCS11 token. Actually our setup is open source and available at the Github.

So far the main use cases (as far as I know) has been protecting private keys/secrets within embedded device and there are no pkcs11 proxies. In embedded device the PIN is problematic as it is a bit hard to protect so the user/group/application based authentication takes that problem away and works in closed embedded device quite OK.

If I would wonder a bit off topic then a neat solution would be a direct access from VM to OPTEE. It would not change the fact about unlimited login issue, but it would remove pkcs11 proxy!

With pkcs11 proxy you need to also think how persistent the connection to the token would be. Eg. how often the PIN would need to be asked as pkcs11 proxy may keep the connection to the token open for long periods of time. With some HSM solutions there are "security world / PIN preload" applications that let you enter the PIN in controlled manner and then allow other automation to utilize pkcs11 tokens thru the pkcs11 proxy without having the access for real PIN. This of course requires then additional protection for the pkcs11 proxy access.

The threat is more about DDOS than protecting the PIN. It is about compartmentalizing the damage into VM rather spilling it over to other VMs. For example a rogue actor (inside VM) could start DDOS towards other user (if it has gained enough capabilities/privileges).

I am not familiar with "security world / PIN preload"-applications. Would there be any examples/documentation/applications online?

Copy link

github-actions bot commented Nov 2, 2024

This pull request has been marked as a stale pull request because it has been open (more than) 30 days with no activity. Remove the stale label or add a comment, otherwise this pull request will automatically be closed in 5 days. Note, that you can always re-open a closed issue at any time.

@github-actions github-actions bot added the Stale label Nov 2, 2024
@mamunergfno
Copy link

YouTube unlimited comment

@github-actions github-actions bot removed the Stale label Nov 5, 2024
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.

4 participants