Open paulhowardarm opened 3 years ago
Does it make sense to model the Parsec service in terms of its providers, and perhaps have a slot per provider? What about slot PINs?
My vote would be to have a slot per provider and an empty PIN for each one (i.e. we just reject the call in the frontend if any PIN is supplied), it seems like a reasonable mapping.
What if the back-end is also PKCS#11 and has multiple slots? Should we try to reflect the back-end slots into front-end slots?
Unless we want to implement some PKCS11-specific operations to support this, I don't think it's do-able. There are a lot of complications that I can think of, it'd be better to discuss this one separately if we think it might be useful, but overall we'd have to use the current operations in a hacky way to achieve this (hacky including in the provider, not just in the frontend...).
Concerning the bridge from the C PKCS11 API to the Rust Parsec Client one, I think we can do:
rust-pkcs11
crate (some of which are already in this PR). Also probably the other way around for some operations.TryFrom
implementations in psa-crypto
. The reverse was already done in the PR linked above.I think the main type to convert is PKCS11 CK_MECHANISM
to rust-pkcs11
Mechanism
to psa-crypto
Algorithm
. Maybe for the key types as well but that's easier. Note that this also depends of the linked PR to be merged somewhere.
My vote would be to have a slot per provider and an empty PIN for each one (i.e. we just reject the call in the frontend if any PIN is supplied), it seems like a reasonable mapping.
Agreed as well, the problem remaining is how we map a provider to a specific slot ID. I propose that they can be listed, starting from 0 in a prioritised list (same order than what ListProviders
returns) and that we can convert the ProviderInfo
structure into a CK_SLOT_INFO
one to give more information if needed when C_GetSlotInfo
is called.
Agreed as well, the problem remaining is how we map a provider to a specific slot ID. I propose that they can be listed, starting from 0 in a prioritised list (same order than what ListProviders returns) and that we can convert the ProviderInfo structure into a CK_SLOT_INFO one to give more information if needed when C_GetSlotInfo is called.
Alternatively, we can use the provider UUID - it's essentially an 128-bit, base64 encoded number, so we can just take the lowest X bits and hope they don't collide.
We started investigating this topic a bit and found a few other questions and ideas to throw around.
pkcs11
crate was on the 2.40 version of the spec, but there's a version 3 out.We can start from the C headers of PKCS11 and build out the interface or use something like this and call our library from the methods we implement.
I have also had a look at the specs and can think of the following:
ListProviders
?).CK_ATTRIBUTE
: ID, sensitivity, etc) and the key name in Parsec (which will have to be generated). I don't think all CK_ATTRIBUTE
map to our PSA KeyAttributes but maybe we can make simplifications.CK_OBJECT_HANDLE
) and attributes/key names in order to use the correct keysC_FindObjects
, C_Sign
, C_Verify
, etc... As they have an Init
equivalent function to be called before. Correct error codes need to be returned in case the order in which they should be called is not respected.NULL
pointer argument as a way to tell the PKCS11 function to return the number of element/size of something instead of the actual result.CK_MECHANISM
that are planning to be used.Finally, we will have to think about security, PIN handling and authentication. As stated by the spec:
It is also possible for a token to have concurrent sessions with more than one application.
I think that it should be possible to access the same keys from multiple application in PKCS11. That would imply that the PKCS11 front end has a fixed, direct authentication name. That might lead to several problems.
All of these comments are for a general, compliant PKCS11 library. We could make simplifications if we put constraints on the use-case.
Does this ticket represent the current state of the PKCS11 frontend discussion? (or did I miss something?)
Hi @areiter - this ticket accurately reflects the current status. There was some initial discussion and investigation, but recently the focus of the project has shifted more towards natively integrating Parsec rather than using a common shim. This issue is still open because I don't think we completely rule out the possibility of a shim. But at this point my personal view is that a shim would more likely get created if there is a use case that specifically requires it, rather than as a strategic compatibility exercise. The philosophy behind Parsec is to avoid shims wherever possible, and instead to create attractive and ergonomic API surfaces in a variety of programming languages. We would like developers to embrace Parsec as a new and updated developer experience, and we are very keen to engage with engineers and partners who are willing to join us in that quest. I would be very keen to hear more about your possible use case with Parsec and/or PKCS#11.
Hi @paulhowardarm, thanks for your quick response, and thanks for all your effort!
Let me just give you a short overview: My system at hand is a multi tenant environment (not necessarily human users, let's call them apps), running on a single device. The system is already existing and many apps are already out there - using mainly pkcs#11 interface to perform different cryptographic operations but e.g. directly talk to the hardware --> Currently no abstraction layer is available. Apps can be completely custom binaries, but typically are a composition of existing tools, libraries,... When it comes to cryptographic operations most of these tools already support PKCS#11.
I'm now looking into different possibilities of how a "security abstraction layer" could look like, but also need to provide an easy migration path for existing components, without the need to rewrite all the existing components. For my use case it would also be a viable option to provide multiple interfaces.
Thanks @areiter - this sounds extremely interesting.
The PKCS#11 front-end shim work hasn't progressed in any material way as mentioned above, but there is plenty of room in the project for community contribution, if this is something that you would consider. As you might gather from the discussion above, there would be quite a lot of detail to resolve to create a general-purpose PKCS#11 front end. But perhaps that's not what you need? A narrow and highly-specialised subset could be considered instead, and either contributed into the broader Parsec project, or just kept as a separate component maintained elsewhere for your own use. But I think you would need to look at contributing that as part of your brownfield scenarios, because as I mentioned we are highly focused at the moment on creating client library experiences that are compelling in their own right, so there isn't any plan right now to deliver this feature.
For your greenfield use cases, where the client language is C or C++, you certainly can use the PSA Crypto API as way to call Parsec. Parsec doesn't have a C client library as such, but you can use Mbed TLS and link in a component known as the Parsec Secure Element Driver, see: https://github.com/parallaxsecond/parsec-se-driver
This method allows you to make C calls to PSA Crypto, and have those calls routed through to the Parsec service/daemon. For some minimal example of that, take a look at the CI tests for the SE driver here: https://github.com/parallaxsecond/parsec-se-driver/tree/main/ci/c-tests
If you would like to engage with the project team in order to discuss your requirements in more detail, feel free to join our public Slack channel or come to one of our regular open project meetings. Details for all of these can be found in our community repo: https://github.com/parallaxsecond/community
I hope that you will be able to find Parsec useful in your systems.
Summary
There are a number of existing systems that use PKCS#11 as their interface of choice for calling out to hardware security functions - it is a well-established interface with a lot of industry adoption. If Parsec could be accessed and driven through this interface, it would allow those systems to gain the benefits of the Parsec platform abstraction without having to code to any Parsec-specific front-end API or client library. Existing PKCS#11 client code would automatically "just work" with Parsec. Hence it would be a useful ecosystem enabler.
This request is to investigate and define the required work.
Design Considerations
A non-exhaustive list of design considerations for this investigation:
C_FindObjects
API could prove a challenge. Parsec currently has aListKeys
opcode, but it's not clear whether that is comprehensive enough to allow objects to be found by PKCS#11-style key/value pair templates.Definition of Done
This is a ticket for investigation, so the expected end result would be a more detailed specification and scope for the work, perhaps with a breakdown into individual issues for concrete engineering items. Part of the DoD should also be a specification (perhaps as a PR against
parsec-book
) for the subset of PKCS#11 standard that would be implemented - this should aim to resolve some of the questions about slot modelling noted above. A good first target would be to enable PKCS#11-compatible access to the Parsec features that exist at time of writing (November 2020) for the provisioning of asymmetric keys, sign/verify and asymmetric crypto primitives.