-
Notifications
You must be signed in to change notification settings - Fork 183
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
Issue with CKU_CONTEXT_SPECIFIC on Safenet HSM module #160
Comments
As you have noted in https://github.com/OpenSC/libp11/files/1005875/Npc_publicobj_sign.txt In lines 364 to 370 a C_SignInit returns USER_NOT_LOGED_IN. Libp11 is assuming that in this case the the module is expecting a C_Login with CKU_CONTEXT_SPECIFIC which is what would be expected to work if the CKA_ALWAYS_AUTHENTICATE=True. So this again is a problem with the module, it does not even understand CKU_CONTEXT_SPECIFIC. But to be fair, the PKCS#11 standards say C_SignInit can return CKR_USER_NOT_LOGGED_IN but does not limit it to private keys with CKA_ALWAYS_AUTHENTICATE=True. So the caller can not be sure if it should do a CKU_CONTEXT_SPECIFIC or normal C_Login with CKU_USER. Not recognizing standard attributes and CKU__CONTEXT_SPECIFIC is a bug in the Sefenet HSM module. Libp11 could make the assumption CKA_ALWAYS_AUTHENTICATE missing means False, and only do CKU_CONTEXT_SPECIFIC C_Login if CKA_ALWAYS_AUTHENTICATE=True. The next question is what other attributes does Sefenet HSM module not support correctly? |
I support treating CKA_ALWAYS_AUTHENTICATE missing as False. |
I went over documentation again and find this
Isn't it that CKA_ALWAYS_AUTHENTICATE was added in later versions of pkcs11? What looks very artsy to me, that Safenet didn't update their pkcs11 imeplentation even on devices released in 2015. |
CKA_ALWAYS_AUTHENTICATE is in PKCS#11-2.20 from 2004. Section "10.9 Private key objects" in Table 15. The default is CK_FALSE. CK__CONTEXT_SPECIFIC is also in 2.20. In https://github.com/OpenSC/libp11/files/1005875/Npc_publicobj_sign.txt pid(14918) tid(139744935835712) time(16/05/2017,23:02:07.225) < C_GetInfo rv=0x00000000{success} pInfo=0x0x7ffd53d62920 The SafeNet module appears to return version 2.20 |
Thanks for clarification, I will raise issue to support, but to be honest, I don't believe they will change anything... |
I tried to run test on lastest version of ProtectServer toolkit (pkcs11 lib for hsm) which should be v2.20 compliant, it failed same as older version. I reported this to gemalto support. I am not sure what to do next. I tried to compile lastest master from github, where I saw commits for this issue, but it won't compile. I ran bootstrap then configure, but it keeps running check and fails on missing autoconf build-master.txt. Thanks. |
Try configuring the correct timezone on your machine. Alternatively, use "git clone" instead of downloading the auto-generated tarball. |
thanks, I had date few days back I ran test with NO PUBLIC CRYPTO and PUBLIC OBJECT again, now I end up user not logged
in no public crypto mode, hsm requires to log in on every crypto operation |
C_Login is never called. I am also surprised that the private key was found without logging in. See lines 214-222. (Note CKO_PRIVATE_KEY is a private key object. All objects have a CKA_PRIVATE attribute.) PKCS#1 2.20 says: "The object search operation will only find objects that the session can view. For The SafeNet module appears to violate the above. (It is possible to have a private key with CKA_PRIVATE=False. Which would then allow for it to be found and used (for example with C_SignInit) without a login. But it looks like that is not what was intended, So the libp11 assumed it was found without a login and could be used without a login. Looks like c71401f does not address the problems of the SafeNet implementation. With previous code, pkcs11_authenticate would have been called, but pkcs11_authenticate has: But there are times when the token could loose the login state because of interference from other processes or even a powered down USB reader. pkcs11_authenticate could be passed another parameter indication it should try a CKU_USER login and/or a CKU_CONTEXT_SPECIFIC login depending on why it was being called. |
One more thing. What version of openssl are you using? Since you are trying to create the CA certificate that is self signed, you may want to look at the CA.sh or CA.pl scripts to see how OpenSSL creates a CA self signed certificate. |
I am using 1.0.1e release 60.el7_3.1, same for openssl-devel. Private key actually is not private object, list from safenet's key generation utility
list.txt That is because while we are running our HSM in production environment (and I am simulating this setting) with NO_PUBLIC_CRYPTO disabled, openssl engine won't Login, and if key is private object, it cannot see it. I have to generate it as public, so it's visible for engine. Now I try to simulate future event, switching HSM to FIPS mode (NO_PUBLIC_CRYPTO enabled) then the problem with missing login in sign operation arises, because key is visible, but HSM requires Login to Sign with it. I was also trying different approach, generating CA key as private object. But then, while NO_PUBLIC_CRYPTO disabled (as current production enviroment state), engine is not doing Login, therefore won't find private object. Probably because of missing CKA_ALWAYS_AUTHENTICATE attribute?
line 690 - enable NO_PUBLIC_CRYPTO
At first step, I thought that this issue might be resolved, treating missing CKA_ALWAYS_AUTHENTICATE as CKA_ALWAYS_AUTHENTICATE = true. But this can have more behind it what I cannot understand, because of my little knowledge. I understand, problem lies in different mode when generating key, and switch mode with already generated keys. But that's something I have to live with. I cannot change mode now, when generating key, because production systems (which are using HSM for various crypto operations with symmetric keys) are relaying on not having to Login for public object key using. They will have to be modified in future, before switch to FIPS mode. Self signing is only first step. As I mentioned, I successfully used openssl engine for singing CA, intermediate CAs and client certificates, but I can't proceed forward knowing whole mechanism stops working in future when HSM will be switched. So I am trying to find a way. |
Documentantion defines NO PUBLIC CRYPTO as follows:
|
I have not used libp11 recently either. Trying to build it from master c71401f @mtrojnar ../src/configure: line 13750: src/libp11.map: No such file or directory This looks like the libp11.map is being created in the @mirozitnansky @mtrojnar I also said: |
If I may ask, how CKF_LOGIN_REQUIRED should be correctly treated? |
What most applications do is find all the certificates and private keys before doing any login. Then if a private key is needed because they are usually CKA_PRIVATE=True, the application does a C_Login. libp11 looks at the flag and sets loginRequired and uses it in a number of places. It could be that ctx_load_privkey is called and the SafeNet has it marked as CKA_PRIVATE=False But if @mtrojnar fixes pkcs11_autuenticate to do a C_Login(CKU_USER) that might work too. You could try gdb or other debugger to see what is going on. |
There is nothing we can do at this point. Those objects are gone. Logging in again won't restore them. It will create new objects.
No, re-login would destroy the previously acquired object handles. (this sentence has been edited for a more clear wording) |
You said: "would destroy all the previously acquired handles" I don't understand. Which handles? PKCS#11-2.20 says: "When the user type is either CKU_SO or CKU_USER, if the call succeeds, each of the Are you saying this is something to do with pkcs11_authenticate() destroying the handles? |
@dengert What I'm saying is that |
In @mirozitnansky 's case , the private key is already available and already has a handle so there is no messing with available object handles. It looks like SafeNet was implemented to PKCS#11-2.10 which does not have CKA_ALWAYS_AUTHENTICATE or CKU_CONTEXT_SPECIFIC and the SafeNet's "No Public Crypto" option is their attempt to force a C_Login(CKU_USER) login. |
@mtrojnar I tried latest commit and it works as expected. When ?pin-value=1111 is present in URL, Sing work well even with public object in FIPS mode. I successfully created CA pair. Now I want to have set all needed in openssl.cnf, including URL for key, so user who is signing client certificate request, doesn't have to understand details of pkcs11 URL format.
then users call only
without URL part. Problem with this setup is, everyone who can read openssl.cnf knows the pin for the token with key. Maybe last thing, couldn't it be somehow implemented, at start of pksc11 session when GetInfo is called, to remember (or Login right away) that CKF_LOGIN_REQUIRED=1, and request pin when crypto operation is called same as when object is private and NO PUBLIC CRYPTO IS is enabled? I can imagine it's easier said than done. :) |
Are you saying any user can get the CA to sign a certificate? You let users on your CA machine? with regard to: "Maybe last thing, couldn't it be somehow implemented, at start of pksc11 session when GetInfo is called, to remember (or Login right away) that CKF_LOGIN_REQUIRED=1, and request pin when crypto operation is called same as when object is private and NO PUBLIC CRYPTO IS is enabled?" As I said above if you made your private keys CKA_PRIVATE=True, it would do a C_Login early: "It could be that ctx_load_privkey is called and the SafeNet has it marked as CKA_PRIVATE=False |
Our HSM is external, network accessed (under IPtables rules), device locked in in own dedicated rack. I am not saying this is ideal scenario, I am just trying to use existing infrastructure and this would be secure "enough" for our use cases. Those lines of code you put in here, that is something that could be done in future? Because now, when device has NO_PUBLIC_CRYPTO disabled and key is private, it's not found by engine. |
PKCS#11 v2.20 says:
CKF_LOGIN_REQUIRED never meant that all cryptographic functions of the device require the user to be logged in. |
I understand, didn't mean to play smartass, just trying to find way. It seems to as game with words, when who is the one who decided which operations are some... Anyway, you've both done a lot to help me, thanks for your time. If there won't be any other solution from me as having pin-value in URL to force login, I am still thankful. |
As @dengert wrote, this is exactly what CKA_PRIVATE is used for... |
Yes, a new engine parameter is definitely feasible. Give me a few days. |
That's great, it should resolve all my issues. I will be checking new commits. |
To put my two cents in, the safenet hsms are too popular today to handle them as special cases. I kind of like the suggestion of Doug, though in the end introduces quite some complexity. |
…y operation These HSMs do not support CKA_ALWAYS_AUTHENTICATE, but rather return CKR_USER_NOT_LOGGED_IN on every operation. Try to discover that state by utilizing the fact that CKA_ALWAYS_AUTHENTICATE is not supported by the HSM. See discussion in OpenSC/libp11#160 Signed-off-by: Nikos Mavrogiannopoulos <nmav@gnutls.org>
BTW, received response from gemalto support, they explained that module supports algorithms of 2.20 but nothing else. v2.10 compliance is required to work with their module. @nmav we chose Protectserver model because of it's ability to run custom made C application (they call FM module) within HSM module security domain, so it can access clear keys. That is fairly unique as far as I know. To be fair here, safenet's second product range called LUNA SA support OpenSSL integration out of the box. But we needed FM module at first place, CA keys and OpenSSL integration comes second. That's why was exited when found libp11 project. |
According to the manual (https://www.openssl.org/docs/man1.0.2/apps/config.html) the proper invocation is: |
A few questions about SafeNet:
|
I swear I didn't understood that explanation this way... to use EMPTY as actual value... Anyway thanks. I tested it, now it correctly ask for pin when having public object and no public crypto enabled.
PC_PRVOBJ.txt Just to be sure, I am really THANKFULL even for current solution. Only downside is, until hsm mode is switched to FIPS, it won't be required to enter pin when signing the certification request. |
There are some, but nothing can be used for NPC mode identification. They are saying CKF_LOGIN_REQUIRED should be sufficient to detect login requirement. Everything documentation says I posted before #160 (comment)
I can't tell for sure. Currently I think manufacturer="SafeNet Inc." could be also used for LUNA SA hsms. But, as Safenet was 2 years ago acquired by Gemalto, it's quite possible they will change manufacturer name to Gemalto in future firmwares. So this is completely unreliable.
#160 (comment) says In second document I found this definition.
Utilities that come with HSM for certification management always require to enter pin before C_Sign, regardless mode so I have quick way to test it. |
So it sounds like they interpret CKF_LOGIN_REQUIRED to mean do a C_Login up front before looking for keys? It looks like the ctx_load_privkey has be modified to test for What I was also asking about: Does SafeNet require C_Login to be called for every C_xxxInit call or |
@dengert you call C_Login once, than repeat crypto operations how many times you wish in same session, untis it closes. |
@mirozitnansky So it the only issue that this HSM doesn't support the CKU_CONTEXT_SPECIFIC? If C_Login falls back to using CKU_USER in the case CKR_USER_TYPE_INVALID is returned, would it address the issue? btw. I'm trying to replicate that behavior in mock pkcs11 module |
Yes, I suppose. That would address compatibility with pkcs v2.10, which hasn't CKU_CONTEXT_SPECIFIC specified. But this is my option, I am no expert in this. But setting FORCE_LOGIN, already overcome issue by forces engine to login before C_Sign CKU_USER. In my last comment to latest patch, I was just asking, if FORCE_LOGIN could work for every session, regardless of activity. |
So would some pseudo code like this work: rv = C_XXXXInit(...) replace every crypto Init call with something like the above. (Could be a macro) |
It does. It just needs to be enabled, which you forgot to do. |
So I ran same test again list of slot 0
private key is private object. NO_PUBLIC_CRYPTO is disabled print of used openssl config - engine.cnf and sign attempt
pkcs11 log there is no C_Login |
It's actually pretty similar behavior to p11tool, even if is set parameter --login to force user login, key is still not found
|
That is because the However, could that been a key that was generated with "no public crypto" disabled and listed when "no public crypto" is enabled? |
NO_PUBLIC_CRYPTO is one of the security flags which can be turned on/off for entire HSM, is has nothing to do with specific token or key generation process.
If object in token is private or public, is a attribute of that object set in time of creation. So I generate public object in when NO_PUBLIC_CRYPTO is set off (CKF_LOGIN_REQUIRED=0), then I set hsm flag NO_PUBLIC_CRYPTO on (that leads to CKF_LOGIN_REQUIRED=1 on every token), but object itself stays public. Same with private object. That's why I was asking to FORCE_LOGIN regardless of activity/setting/flags. In other words, if FORCE_LOGIN than always call C_Login second to C_Initialize. But again, I am layman here who doesn't have in-depth knowledge of the topic. |
Okay. I'll fix it. |
@mirozitnansky Can we close this issue now? |
@mtrojnar, I am sorry I didn't have time to test it earlier. |
These HSMs do not support CKA_ALWAYS_AUTHENTICATE, nor understand CKU_CONTEXT_SPECIFIC, but rather return CKR_USER_NOT_LOGGED_IN on the first private key operation. Try to discover that state by calling C_Login when CKR_USER_NOT_LOGGED_IN is seen, and retrying with CKU_USER after CKU_CONTEXT_SPECIFIC login fails. See discussion in OpenSC/libp11#160 Signed-off-by: Nikos Mavrogiannopoulos <nmav@gnutls.org>
These HSMs do not support CKA_ALWAYS_AUTHENTICATE, nor understand CKU_CONTEXT_SPECIFIC, but rather return CKR_USER_NOT_LOGGED_IN on the first private key operation. Try to discover that state by calling C_Login when CKR_USER_NOT_LOGGED_IN is seen, and retrying with CKU_USER after CKU_CONTEXT_SPECIFIC login fails. See discussion in OpenSC/libp11#160 Signed-off-by: Nikos Mavrogiannopoulos <nmav@gnutls.org>
These HSMs return CKR_USER_NOT_LOGGED_IN on the first private key operation, instead of using CKA_ALWAYS_AUTHENTICATE or similar. Detect that state and retry login with CKU_USER. See discussion in OpenSC/libp11#160 Signed-off-by: Nikos Mavrogiannopoulos <nmav@gnutls.org>
These HSMs return CKR_USER_NOT_LOGGED_IN on the first private key operation, instead of using CKA_ALWAYS_AUTHENTICATE or similar. Detect that state and retry login with CKU_USER. See discussion in OpenSC/libp11#160 Signed-off-by: Nikos Mavrogiannopoulos <nmav@gnutls.org>
First of all, you are doing great job guys, many thanks for time and energy you are putting into this project.
I am pretty noob with pkcs11 stuff, so please have patience with me.
I spent quite some time trying to implement OpenSSL certification authority based on Sefenet HSM module which should store CA private keys. CA key is than used for singing client/server certificates.
Using libp11 as OpenSSL engine, configured with pkcs11 lib supplied with HSM, I was able to make OpenSSL work correctly... on some conditions.
Our HSM can work in few modes. Safenet's default (we are currently using this mode), FIPS-140 and others.
We are planning to switch our device from current, default mode, into FIPS-140 mode. This means, among other things, device will be switched to No Public Crypto mode – user have to be always logged into token, if he is going to use key for crypto operation.
In current mode, there no need to be logged in token to do the sign operation in OpenSSL.
On the other hand, object in token can be public or private (I am not reffering to RSA pulic/private key). Private objects are only accessible after loggin in.
First problem I encountered lied on having private object while disabled No Public Crypto flag. Then even if I try to set pin for token, engine won’t log in and simply says there is no such object (because it was set private).
I have pkcs11 communication logged so pc_private_list.txt is list using safenet utility.
and pc_private_sign.txt is OpenSSL sign attempt which end up failed:
In this case, I assume, if OpenSSL logged into token, sing operation would worked fine.
So I set No public crypto flag to true, OpenSSL logs in correctly, finds private key and do the sing operation. Npc_private_sign.txt
Second thing, it seems to me, is some lack of implementation on side of Safenet. It looks like, they have not implemented CKU_CONTEXT_SPECIFIC user type in pkcs11 at all. When I have set No public crypto true, but my object is Public, OpenSSL finds it, then request pin (ignoring pin in URL), but then sing fails on
This seems to be a problem in pkcs11 log Npc_publicobj_sign.txt:
As I mentioned before, we plan to switch mode of our device to FIPS (with No public crypto flag), and we have public objects in token, so after switch we won’t be able to use them, because sing will fail as in previous case. If I am able to force login into token as standard user, crypto operations shoud work correctly even after mode switch.
I noticed Missing CKA_ALWAYS_AUTHENTICATE attribute message in OpenSSL operations, but I am not sure if this has something to do with my situation.
All tests I am doing, are done on software HSM emulation, but hardware HSM works the same.
Do you think, if is there any way to overcome this user type invalid issue?
Thanks in advance.
If there is any test/log I can provide, I'll be happy to.
The text was updated successfully, but these errors were encountered: