-
Notifications
You must be signed in to change notification settings - Fork 709
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
pkcs11-tool -t: Key unwrap testing fails #1796
Comments
similar result - MyEID driver, OsEID simulated card, opensc from git d4a97c6
With patch from above:
|
I have to correct myself:
|
Looks like for DES or AES (and may be others) you may need to add CKA_VALUE_LEN to the template. http://docs.oasis-open.org/pkcs11/pkcs11-curr/v2.40/pkcs11-curr-v2.40.html 2.8.4 AES-ECB "For unwrapping, the mechanism decrypts the wrapped key, and truncates the result according to the CKA_KEY_TYPE attribute of the template and, if it has one, and the key type supports it, the CKA_VALUE_LEN attribute of the template." It gets messy. |
@dengert The missing of parameters "u8 * out, size_t outlen" in function unwrap makes sense to me only, if it's supposed to write it's result to a somehow known or fixed location itself. So the "Logs"/pkcs11-tool errors "Key length mismatch (0 !=..." are to be expected as acos5_64_unwrap currently doesn't write anything anywhere (because unknown where to write to). |
There may be some issues. These may have resulted from what does a card can do with an unwrapped key. Does it return the results or does it unwrap the key and leave it on the card to be used on the card at a leter time. PKCS#11 support this as a derive or unwrap requires a template and a key object is created which may or may not be a key on the card or in memory. pkcs11-tool.c can do either. But
In response to the question in line 911, I would say YES as many can only return the key value. So the ability to return in software the key value is not supported. It is also not clear if the key is unwrapped and left on the card how is it identified by PKCS#11. |
just some comments to unwrap operation.. From card view, PSO operation:
P1 - 00 - the response data field is absent For Unwrap, both APDU seems to be identical, because security environment is used to set where the unwrapped key is to be stored... CT template Tag 0x83, Len 2, V - file reference. (alt, tag 0x84, more in table 33 in iso7816-4). example APDU for MSE: (generated by test software for MyEID card from https://github.com/hhonkanen/WrapTest operation UNWRAP AES key by RSA key)
|
For card ACOS5-64, storing a sym. key on card from an unwrap result (or any other source) is possible, e.g. for PSO to iEF Symmetric File (file->type==SC_FILE_TYPE_INTERNAL_EF, file->ef_structure==SC_FILE_EF_LINEAR_VARIABLE). From the above follows, that an unwrapped key length of {UpdateEdit: 16 or} 24 bytes would be ambiguous to deduce an Algorithm reference from (3DES or AES?), and that some key identifying information still would be needed from unwrap parameters (or must be immutably fixed by acos5_64_unwrap; something like record # or 1 byte Key identifier which will be used as key_reference). The options of Key type/Information (External Authentication Error Counter or Internal Authentication Usage Counter) are supposed to not be fed in by an unwrap parameter. Storing a sym. key on card with ACOS5-64 is done via SC_AC_OP_UPDATE's requirement satisfied for iEF Symmetric File and ordinary sc_update_record or sc_write_record, with special indexing, beginning from 1 and flag SC_RECORD_BY_REC_NR; no sc_set_security_env required. |
I'm not sure if we can resolve all the issues mentioned here soon... It seems that I suspect the mentioned issues don't affect the regular user's experience and the intended workflow, suggested in https://github.com/OpenSC/OpenSC/pull/1393/files. @hhonkanen could you look at the release candidate to check if at least your use cases are OK? If so, I'd like to postpone the fixing for the next release. |
PKCS#11 wrapping/unwrapping - I suspect - doesn't work for any type of card/OS in a general way, currently, because nobody can write a PKCS#11 application that refers to an unwrapped key on an arbitrary card. With the current design of unwrap, each card is supposed to do some arbitrary on-card-storage or nothing. PKCS#11 can never refer to an unwrapped key again in a general way and this also is by design untestable, except tailored to what a specific card does and e.g. pkcs11-tool.c knows that specific card's unwrap circumstances. @frankmorgner If You refer to my patches as proposed fixes: The first one could be part of fixing but NOT the second one: That was just the dirty hack to make the framework (core code of OpenSC) think there is an on-card-unwrap-target in order to continue processing; otherwise it would have stopped (as shown in popovec's output with ERR: C_UnwrapKey failed: CKR_GENERAL_ERROR) and never called card's unwrap function. |
I wrote the wrap/unwrap implementation, so let me explain how it is designed and how it works. There was discussion pn should we allow returning key material in sc_card_operations:unwrap, and I finally decided to not add an output buffer to the argument list. The reason is that if you want to decrypt wrapped key material and return the unwrapped key material to caller, you could as well just use C_Decrypt to do this. A reason to specifically use C_UnwrapKey in PKCS#11 would be to unwrap the key material inside a hardware token (a HSM or a smart card), and not reveal the key as plain text outside the token during the operation. In these use cases it is often essential to know and trust that the unwrapped key never leaves the protected hardware. So not even having an output buffer kind of guarantees that the operation is done inside the token and the key stays there securely. In PKCS#11 level it works so, that C_UnwrapKey first creates the target object. Calls lead to pkcs15_create_secret key in framework_pkcs15.c. This function calls pkcs15init to create the secret key object on card. pkcs15init also creates the pkcs#15 structures for the object. A handle to this object is returned to pkcs11 level, and it is passed to function sc_pkcs15_unwrap, which can pass it to the card driver using sc_set_security_env. The driver should command the card to do the unwrap operation and place the resulting data into the new key object. The handle to this key object is returned to the caller in the last argument of C_UnwrapKey. From that point it is just another PKCS#11 key object. The implementation is designed to be generic for any card that can unwrap keys directly into an object on card. If support for cards that cannot unwrap keys fully on harware shall be added (I mean, you'd need to decrypt the key, read the result from card, create a new key object and write the key material to the card), I suggest that the logic would be implemented into sc_pkcs15_unwrap so that driver's unwrap function wouldn't be called at all. You could use decrypt() function. But this would be kind of similar to extracting a private RSA key from card and doing the crypto operation on software - why would you want to do that? My idea of flags SC_CARD_CAP_WRAP_KEY and SC_CARD_CAP_UNWRAP_KEY is that they indicate, that a card can do key warpping/unwrapping fully on card. I have created a little test program to test the wrap and unwrap operations using PKCS#11. You can find it here: https://github.com/hhonkanen/WrapTest. I am familiar with the issue with pkcs11-tool -t. The current implementation assumes that the key material can be extracted from the card, then it tries to do crypto with this using openssl. I had plans to make it compliant with the new wrap/unwrap code, but unfortunately haven't had time to do it. @carblue your changes to pkcs11-tool to add more information to the target key template look ok, but testing the resulting key if it has CKA_EXTRACTABLE=FALSE is more complicated. Temporary solution would be to just check for CKA_EXTRACTABLE and skip that test in this case. I don't see need for changes in pkcs15-sec in setting target key path, because the path of the target object should come from framework-pkcs15. |
I'll try to summarize it if I understand it well .. For now,
|
@hhonkanen Hello Hannu, thank You for Your detailed explanation how unwrap is designed and how it works, the pointer to the test program and of course for Your implementation. It will take time to follow the flow of control, test etc. and possibly comment. Obviously I missed/overlooked any feedback from unwrap operation to PKCS#11. What I can say upfront: I agree with Your reasoning in Your first 2 sentences, i.a. "essential to know and trust that the unwrapped key never leaves the protected hardware". But for the same reason, the unwrapped key should then never be extractable, but that extractability is currently assumed in the pkcs11-tool unwrap testing. The "Temporary solution would be to just check for CKA_EXTRACTABLE" currently is impossible to practice for me with my card/card content? (see issue #1805 "pkcs11-tool -l -O -y secrkey: Secret sym. key listing fails"): None of my sym. keys get's recognized as such, nor it's correct extractability attribute. |
It's great to see this commitment and I am sure we can refine the status quo soon. So far, nobody linked this problem to a certain commit that introduces the problem, so I assume the main problem is that the new feature of key wrapping is not (yet) as universal as it could be. For the upcoming release, I think we should postpone this issue, however, and follow the suggestion to disable the tests temporarily. |
In response to: #1796 (comment) The PKCS#11 CKM_ECDH is very similar to an unwrap. A crypto operation accepts a blob of data I had also said: "It is also not clear - if the key is unwrapped and left on the card - how is it The mechanism/CKF_HW flag could be used to indicate the unwrap is done on the card with the key stored on the card and the unwrapped key must be on the card. This should be set It may be possible for a calling application that does not require CKF_HW to request where it would like the unwrapped/derive key to be stored. It can do this by trial and error by requesting So on some cards it may be possible to only unwrap a key and leave it on the card. On others |
I wonder how the unwrap test in pkcs11-tool could have ever worked in OpenSC, because C_UnwrapKey wasn't supported before 2017, but the test was already there. Maybe somebody originally wrote it to test some other pkcs#11 library? I don't understand either, how it could work with the incomplete target key template. The workflow proposed by @popovec would be good to begin with. I agree that it would be a good feature to also support unwrapping keys to memory, as long as users are able to distinguish whether the key leaves the token or not. @dengert your idea of using CKF_HW flag sounds good. The current three phase implementation of unwrap is fine with MyEID: The empty key object is first created on card and pkcs#15 structure is updated, the new key object is set as target key in MSE and unwrapping is finally executed using a PSO command. In other cards the workflow might be a bit different, the card might for example create the target key object in the unwrap command. I'm not familiar with ohter implementations but I believe this kind of workflow could also be supported without significant changes to OpenSC core. |
... until OpenSC#1796 is resolved
... until OpenSC#1796 is resolved
See #1808 for the suggested temporary workaround |
@dengert I am not sure what you mean " On others like the PIV, it is only possible to unwrap and leave the key in memory. " What is If PIV card is able to unwrap key into card (for now it is irrelevant, if it is session object or token object), this is real unwrap. If key is returned to middleware this is only decipher operation. If card does not have support for real unwrap, there is of course way to implement this in middleware .. we can run decipher and result can be stored back into card as token object .. but this is security issue. |
I meant memory in middleware. The card only supports RSA RAW (CKM_RSA_X_509), ECDSA and ECDH. So all RSA operations to card send k bytes to the card and receive k bytes in return. All padding is handled in software. "If key is returned to middleware this is only decipher operation." Is correct. Padding is checked and removed by the middleware. Having C_UnWrap support the operation and return a CKO_SECRET_KEY object as a session object makes it easier for the calling PKCS#11 application. For example C_Encrypt using an AES key could be used with the CKO_SECRET_KEY on a card or from the key in memory. An in memory key could also be extractable requesting CKA_VALUE. With the PIV and many cards, an unwrapped key can not be written to the card. (Actually the PIV standards leave it up to card vendors on how to write 3DES or AES key used for card management authentication. The vendor can chose to not support a 9B key and do card management authentication in other ways. PIVkey for example do not support a 9B key. |
Real world example: pay TV .. AES key wrapped by RSA is received by smartcard, card does unwrap, and then AES key is used to decipher pay TV content .. User is not allowed to extract AES key from card. User is not allowed to decipher the AES key (RSA key can do only unwrap to card - token object, there is no decipher operation allowed). Implementing "software" unwrap in opensc is wrong, some user may have feel, that unwrapped key is safe - but no, this in no safe key. BTW, security of RSA private operation is reduced, if card return whole deciphered data with padding - better is if card does padding removal and in case of wrong padding only error in SW is returned. Similar, RSA sign operation - card should check for proper padding of signed data and revoke sign if data are not properly padded - or card may add padding automatically. |
Not all cards should be used in some senerios. In your TV example, the cable/pay-per-view/content-owner is interested in not exposing the AES key to the consumer. They control your TV and the card/token within it. They are only interested is showing the TV content to the user. They control your TV. I would not expect to see a PIV type card used in this case. A PIV was designed as a badge for physical access, logical access: login, web authentication, signatures and data encryption with escrow keys. NIST could have come up with a card that did more on the card, but they did not. They kept it simple and only support RAW RSA and two elliptical curves. I don't have a specific example of doing unwrap with PIV at this time. But I bet there may be one. There is an argument to be made over what OpenSC should support. What I hear you saying is C_Unwrap should only be supported if it is done on the card and not extractable. We already support software padding and C_Verify if OpenSSL is enabled to make PKCS#11 easier to use with every card. The security resides on the card. So select a card that meets your security requirements. I think that means opensc should support access to some functions even if done in software. See the comment about using CKF_HW above. |
Exposing secret key (AES) to middleware is security risk, this is not comparable to software padding function. But OK, pkcs11-tool does not have support for unwrap operation, in future release this support can be added. If this tool detect that card does not have support for "hardware" unwrap, this tool then must reject unwrap operation. To allow unwrap in software, special switch (--soft-unwrap-force) may be used, with special phrase "--yes-i-know-what-i-am-doing" or "--please-expose-my-secret-to-world"... (similar switches are used in hdparm software, to prevent users from dangerous commands). |
Something like that is OK for now. The CKF_HW needs to be implemented. |
While continuing to try to test "Key Unwrap" in pkcs11-tool, I'm stuck now: I have an operational implementation for RSA_WRAPPED_AES_KEY with template entries for receiving sym. key: CKA_TOKEN=TRUE and CKA_EXTRACTABLE=FALSE.
Another finding: I suggest to comment-out these until they possibly get used later on. |
OpenSC doesn't support symmetric decrypt/encrypt operations, because nobody has implemented them yet. Keys can be loaded using pkcs15-init and symmetric keys can used to wrap/unwrap keys but not for just doing encryption. It could be implemented in quite similar way as the wrap/unwrap, but it needs to be done all the way from the pkcs11-layer via framework-pkcs15 to the card driver level. Handling of target file in security environment is actually done by adding a dynamic parmeter of type sc_sec_env_param with param_type SC_SEC_ENV_PARAM_TARGET_FILE to the security environment. Please take a look at lines 418-428 in pkcs15-sec.c on how the target file is set and card-myeid.c to see how it is finally used. The framework calls pkcs15init to create the target file in earlier phase, and the file gets a FID assigned there. The path is passed back to framework-pkcs15 which passes it to pkcs15-sec, to point to the (at this point empty) key file which shall receive the unwrapped key data. |
At least I think that symmetric on-card crypto would be a good feature. It would make OpenSC's implementation of PKCS#11 more comprehensive and I know there are some users who need this functionality. Much of the code needed is already there. You can already wrap or unwrap a symmetric key with another symmetric key, if your card/driver supports it. These features could be extended to encrypt or decrypt data and return the result. Basically you could take functions pkcs15_skey_wrap, pkcs15_sckey_unwrap, sc_pkcs15_wrap and sc_pkcs15_unwrap, extend and refactor them a bit to allow taking the input from caller in C_Encrypt and returning the plaintext data to caller in C_Decrypt. |
@hhonkanen |
@hhonkanen
It supports C_EncryptInit, C_Encrypt, C_DecryptInit, C_Decrypt for AES: ECB, CBC, CBC_PAD (what my card can do, hence I can test). My design rationale is at https://github.com/carblue/acos5/tree/master/info/design_rationale_sym.md with more details, comments. @frankmorgner and/or @Jakuje |
I don't have anything against this even though I do not have direct use case for this just now. In any case, I would like to see some test coverage of the new code, making sure it works. As you wrote that the MyEID should work with this, there are already test cases with the OsEID SW implementation so you can use it as a start. |
Beware, OsEID implementation is incomplete - there is no CBC chaining implemented. I didn't finish it because there was no code in OpenSC that I could test my implementation with. First I will try to write the necessary things to the MyEID driver and when it works with a real MyEID card, I will adjust the OsEID implementation accordingly. |
@carblue Currently with your patch:
Alternatively .. is there a another tool available in the regular Linux distribution that encrypts (with AES) the file via the pkcs11 interface (using opensc-pkcs11.so of course) and returns the output so that I can check it via openssl? |
@popovec |
I picked up your commits via cherry-pick. I wrote symmetric encryption support for MyEID. https://github.com/popovec/OpenSC/tree/sym_hw_encrypt Here experimental OsEID code that is used to test AES cipher: https://travis-ci.com/github/popovec/oseid-travis
You should probably modify your |
@popovec |
modified: src/tools/pkcs11-tool.c
modified: src/tools/pkcs11-tool.c
modified: src/tools/pkcs11-tool.c
modified: src/tools/pkcs11-tool.c
modified: src/tools/pkcs11-tool.c
modified: src/tools/pkcs11-tool.c
What's the status of this topic, well we get something working now that we are way ahead of a new relase? |
This test is rather problematic to write so that it works for all pkcs11 libraries. There are several reasons. The first problem is the template. Some implementations need CKA_VALUE_LEN, others do not. (http://docs.oasis-open.org/pkcs11/pkcs11-curr/v2.40/cos01/pkcs11-curr-v2.40-cos01.html 2.8.4 ) SoftHSM must not have CKA_VALUE_LEN set, but I need this value for the MyEID card (before the unwrap operation I have to create a file for the key, and it must have a defined length). Another problem is that this test modifies the content of the token ... which is sometimes/sometimes not a problem. If we store the unwrapped key in the session object, it will be deleted when the token is reset. But again, not all pkcs11 implementations support session objects. Of course, we can delete the created key after the test. However, here we are again faced with the problem of how many rewrites the token can handle (this may not be a major problem, eeprom in tokens can handle even 100,000 of these "writes", but does the user really want that during testing?) and do we even have the access right to create a new key on the token ( can be conditioned by entering SO-PIN, depends on PKCS#15 profile) And then we come to the unwrap operation itself.. This test uses the RSA operation to unwrap keys, and the result is a symmetric key.. AES or DES. And here we have the problem that some implementations support only DES and another only AES. The test will necessarily be written in such a way that if the template with CKA_VALUE_LEN set fails, we will test the template without CKA_VALUE_LEN in the next attempt .. and similarly for session object, key type etc.. |
Thanks for the comprehensive summary (sorry, for my missing effort reading through the whole thread 🙈 ) To move forward, I would propose to create a seperate commandline switch (e.g. If you think handling the flexibility with CKA_VALUE_LEN for the actual test is too difficult, please implement it in a way that is compatible with the OpenSC pkcs11 module, i.e. MyEID, first (for use in CI and release testing). Please write some documentation regarding the unwrap operation and its limitations when used with MyEID. I assume the best place to put this, would be the wiki https://github.com/OpenSC/OpenSC/wiki/Aventra-MyEID-PKI-card |
I think the test tool can quite simply distinguish the different pkcs11 modules or even drivers in opensc by the token/slot info so I would prefer to use that information rather than trying different combinations. I was stumbling around similar issues in the |
Currently in CI unwrap /wrap is tested using OsEID simulator .. pkcs11-tool --unwrap/--wrap is used. The operation of unwrapping an AES key using the AES-CBC-PAD and RSA-PKCS mechanisms and wrapping an AES key using AES-CBC-PAD is tested. But the separate test |
Problem Description
There are still errors with pkcs11-tool -t (see output below)
The "fix pkcs11-tool: broken encryption/decryption #1786" by commit 25bc8fc was incomplete, in that now (for me) there is a total match within the first 10 bytes of Original/Decrypted but the length differ and thus result in error(s) (see output below in the end)UpdateEdit: False alarm, it's no OpenSC issue, but my own bug issue"Key unwrap" testing seems to be not fully implemented in OpenSC. With the following (incomplete) patch I succeed to at least get a call to card's sc_card_operations:unwrap function, otherwise that would never be called:
Proposed Resolution
For encryption/decryption: nothing supplied.
For unwrap maybe something similar to:
Steps to reproduce
Mark keyusage (PKCS#15) of an RSA key as decrypt, unwrap and invoke
pkcs11-tool -t -l
Logs
The text was updated successfully, but these errors were encountered: