OP-TEE / optee_os

Trusted side of the TEE
Other
1.55k stars 1.04k forks source link

PKCS11 TA: use of persistent objects vs transient objects #6402

Closed fifalars closed 8 months ago

fifalars commented 10 months ago

Hi all,

I have a use case in mind where the bootloader (responsible for starting OPTEE) passes on secrets (e.g. found in SOTP) to OPTEE (e.g. through (secure?) device tree) and OPTEE (or another (custom) TA) fetching the keys from the device tree and injecting them into the PKCS11 TA. Those keys would then be stored as "Transient Objects", ensuring that they're not stored anywhere persistently and unavailable when the device is off.

I've been going through the documentation and the code for the PKCS11 Trusted Application. The PKCS11 TA currently has a fixed (by CFG_PKCS11_TA_TOKEN_COUNT) amount of tokens stored as persistent objects in OPTEE. With the amount of tokens being statically defined and those tokens being Persistent Objects by default, I don't see any room for injecting "run-time keys" into the PKCS11 TA.

I was wondering if the use-case I have is one that (1) complies with the specifications, (2) is sound from a security perspective and (3) if you would be open to receiving code contributions that make this use case possible.

Kind regards, Lars Feyaerts

etienne-lms commented 9 months ago

Sorry I did not read your entry. Quick answers are (1) I think it complies with the spec; (2) sounds ok to me; (3) contributions are always welcome but that does not guaranty them to be merged. Thanks a lot for the pull request. We'll have a look at it. Be patient, as you can see, feedback can take more or less time. Feel free to ping (re-post a comment in the P-R) if no one is commenting after few weeks. I hope (for you) that you'll get feedback sooner :).

vesajaaskelainen commented 9 months ago

Could you please describe why would you want to do that?

etienne-lms commented 9 months ago

@fifalars, I though your purpose was to have a pkcs#11 token that has built-in read-only objects (not modifialbe, not destroyable) that are not stored in OP-TEE secure storage but instead either provided by OP-TEE core (read from OPTs, passed by the bootloader stage, etc...). Implementation of https://github.com/OP-TEE/optee_os/pull/6471 is quite different, it looks like you want a token that has no persistent object support. I don't think it's the right way. You don't need such "Transient token" concept to achieve your initial goal. I think you rather need a specific internal object attribute to identify this kind of objectx and a PTA service in OP-TEE code for the pkcs11 TA to get such objects data when needed.

fifalars commented 9 months ago

Hi all, thanks for commenting.

My understanding of the existing implementation of the pkcs11 TA is that it's using TEE Persistent Objects to store the pkcs11 objects (keys, data etc). As far as I understand, TEE Persistent Objects are stored persistently meaning that they're stored somewhere on a flash or RPMB while the device is turned off.

I have a situation where the bootloader prior to OPTEE can access an SOTP memory containing a key. Said key is then used as a basis for deriving one or more application-specific keys. The bootloader would pass those keys on to OPTEE (e.g. through device tree), where a custom Trusted Application will extract these keys from device tree and inject them into the PKCS11 TA. Once linux boots, userspace can access those keys through the normal pkcs11 interface.

Derivation and passing on of the keys from the bootloader to OPTEE happens on every single boot and therefore I don't require OPTEE to store these keys persistently. In fact, I consider storing these keys persistently being worse (security-wise) than passing them on through the bootloader and keeping them in volatile ("transient") memory. In researching it was my understanding that the TEE Transient Object did exactly that: keeping it in volatile memory causing the key to be removed the moment the device turns off.

Perhaps I am misunderstanding how the Persistent Object works or perhaps I am making some false assumptions here?

etienne-lms commented 9 months ago

My understanding of the existing implementation of the pkcs11 TA is that it's using TEE Persistent Objects to store the pkcs11 objects (keys, data etc). As far as I understand, TEE Persistent Objects are stored persistently meaning that they're stored somewhere on a flash or RPMB while the device is turned off.

Only PKCS#11 token objects (a token object is a persistent object in PKCS#11 literature) are stored using TEE Persistent Objects resources. PKCS#11 session objects (non-persistent objects in PKCS#11 literature) are only stored in the TA RAM (and release once the owning PKCS#11 sessions are closed).

Note however that a PKCS#11 token (persistent) objects are is stored as a raw TEE objects (see TEE_TYPE_DATA) which data raw content is made of all the PKCS#11 attributes of the objects, serialized as a binary blob. You can see that by the fact we pass TEE_HANDLE_NULL to TEE_CreatePersistentObject() argument TEE_ObjectHandle attributes (5th arguments), in the create_object() function on creation of a persistent object.

When a PKCS#11 cryptographic object is to be used for a TEE operation (being persistent/token object or transient/session object), a TEE transient object is created to hold the object materials while the TEE operation is proceeded.

In fact, I consider storing these keys persistently being worse (security-wise) than...

I understand your concern. ~I~ It makes sense to me.

(edited, in blod)

etienne-lms commented 9 months ago

I guess a bit of description of the pkcs11 TA implementation in OP-TEE documentation would help every one. I'm ready to help on that topic but I don't have enough time to address this in the short term.

fifalars commented 9 months ago

Thanks for giving a bit more context.

You mention that a PKCS#11 token object is always considered to be a persistent object in the literature, but I don't see such mention in the specification I'm looking at. In fact, there is a mention of a "soft token" in that specification: there isn't any other mention regarding that soft token and I also can't seem to find any official information online, but the presence of said term caused me to believe the specification was open to token objects not backed by hardware. I interpreted that as an open door for supporting token objects that would only reside in volatile memory, which is exactly what I was looking for to solve my problem.

fifalars commented 9 months ago

As for the possible use of session objects; my understanding is that if my custom TA creates session ojects, userspace applications will not be able to use those tokens if the custom TA closes the session. Perhaps I can change that by keeping the session open?

etienne-lms commented 9 months ago

You mention that a PKCS#11 token object is always considered to be a persistent object in the literature, but I don't see such mention in the specification I'm looking at.

See the CKA_TOKEN object attribute, section 4.4 Storage Objects (v2.40 or and v3.0).

In fact, there is a mention of a "soft token" in that specification

A soft slot relates to a slot interfacing a software implementation of an enclave that can be accessed by the PKCS#11 API. A HW token is a physical slot connected to an enclave. This property is specified by the slot info flag CKF_HW_SLOT. Do not confuse this CKF_HW_SLOT slot flag and the CKA_TOKEN object attribute.

As for the possible use of session objects; my understanding is that if my custom TA creates session ojects, userspace applications will not be able to use those tokens if the custom TA closes the session. Perhaps I can change that by keeping the session open?

Indeed closing a session destroys its remaining session's objects.

Different applications will not be able to see the other application session objects but an application can open several sessions, in this case the session objects are visible from both sessions. I recommend to read section 2.6.8 Example of use of sessions of the PKCS#11 Usage Guide (in pkcs11-ug/v2.40) to better understand client, sessions, and session objects/token objects.

How can you distinguish between which application can access your specific object if it is created (and retrieved from OP-TEE core) at session opening? PKCS#11 recommends to use the PKCS#11 login resources to restrict objects visibility.

fifalars commented 9 months ago

See the CKA_TOKEN object attribute, section 4.4 Storage Objects (v2.40 or and v3.0).

I'm sorry, but I don't see how this implies that the token object has to be persistently stored. I only see the option for "token object" vs "session object". It doesn't say that "token objects"s should be persistent.

A soft slot relates to a slot interfacing a software implementation of an enclave that can be accessed by the PKCS#11 API.

That's what I'm trying to implement here. I've tried implementing the "software enclave" you mentioned by using a TEE Transient Object to store PKCS#11 token objects. That "software enclave" has no hardware backing, it's just stored in RAM. It's counterpart, the "hardware enclave", I expect to store the information in either a hardware module (e.g. HSM) or in some other (not as secure) medium such as RPMB. Perhaps you mean something else when talking about "a software implementation of an enclave"?

Different applications will not be able to see the other application session objects

Ok so using session objects is not an option.

How can you distinguish between which application can access your specific object if it is created (and retrieved from OP-TEE core) at session opening? PKCS#11 recommends to use the PKCS#11 login resources to restrict objects visibility.

Maybe I'm missing something here, but my idea was to have a custom TA fetch the keys from device tree, inject the keys in the PKCS#11 TA as a token object (making them visible to all userspace applications), set a PIN and make sure the applications that want to use the keys have access to the PIN.

etienne-lms commented 9 months ago

I'm sorry, but I don't see how this implies that the token object has to be persistently stored. I only see the option for "token object" vs "session object". It doesn't say that "token objects"s should be persistent.

Right, it does not. However a session object is destroyed once sessions are closed whereas a token object is not destroyed once sessions are closed. In GP TEE terminology, i think this is what we call a persistent object.

That's what I'm trying to implement here. I've tried implementing the "software enclave" you mentioned by using a TEE Transient Object to store PKCS#11 token objects. (...) software enclave" has no hardware backing, it's just stored in RAM. (...)

My reading of the PKCS#11 spec is that GP TEEs fall into the software enclave category. But I may be wrong. I definitely don't thing a software token cannot have persistent storage means (otherwise it would mean that CKA_TOKEN attribute should not be supported when CKF_HW_SLOT false is disabled). I don't think neither a HW PKCS11 slot/token cannot use RAM, indeed most of them do use some kind of internal RAM.

Maybe I'm missing something here, but my idea was to have a custom TA fetch the keys from device tree, inject the keys in the PKCS#11 TA as a token object (making them visible to all userspace applications), set a PIN and make sure the applications that want to use the keys have access to the PIN.

Makes sense. Whether you need a TA or an OP-TEE core PTA is still to discuss, or up to you. Using PKCS#11 PIN authentication is a good thing. Note however that the PKCS#11 spec considers only 1 user to own a token (there is only 1 user PIN per pkcs#11 token).

etienne-lms commented 9 months ago

Note that the pkcs11 uses a the TEE TEE_STORAGE_PRIVATE for storing persistent objects. There could be a TEE_STORAGE_OTP for read-only object stored in the device OTP fuses. May be it would be a more elegant way to implement your feature.

fifalars commented 9 months ago

Right, it does not. However a session object is destroyed once sessions are closed whereas a token object is not destroyed once sessions are closed. In GP TEE terminology, i think this is what we call a persistent object.

The way I see it, the PKCS#11 "session object" and "token object" are somewhat orthogonal to the GP TEE's Persistent Object and Transient Objects. A "session object" does seem to imply it has to be stored in RAM (i.e. as a TEE Transient Object), though there doesn't seem to be an explicit statement for that. One would expect such implication for a "token object" as well with regards to it having to be saved persistently (i.e. as a TEE Persistent Object), but in my opinion that's not the case. A quote from the user guide:

“Token objects” are visible to all applications connected to the token that have sufficient permission, and remain on the token even after the “sessions” (connections between an application and the token) are closed and the token is removed from its slot.

This talks about a "token object" always being present even if all sessions are closed and the "token object" is still present on the token if it's removed from it's slot. In the case of the PKCS#11 TA, token and slot are basically the same thing: it's not like you can remove the token from the slot here. Because of that, token objects don't have to be stored persistently on the token per se; they can just as easily be stored as a volatile token object.

My reading of the PKCS#11 spec is that GP TEEs fall into the software enclave category.

I agree that's also a good way of looking at it. Perhaps the leveraging of CKF_HW_SLOT to distinguish between "transient" and "persistent" tokens isn't the best, but it was the only thing I could see that would allow for it to even exist. I'm not aware of a PKCS#11 parameter that might tell the PKCS#11 TA to create either a Transient Object or a Persistent Object, perhaps there are some vendor-specific bits we can use for that? That is, off course, under the assumption that this proposal is accepted :)

There could be a TEE_STORAGE_OTP for read-only object stored in the device OTP fuses

The point of the use-case I'm trying to support is that access to (S)OTP, which contains secrets, is limited to the first stage bootloader and closed right after the keys have been read from it. Keeping access to (S)OTP open to OPTEE seems to me like an increased security risk: if an attacker were to be able to "hack" OPTEE, he would be able to read from SOTP, giving him direct access to the keys in (S)OTP. The fact that we derive keys from the "base key" in SOTP in the first stage bootloader and discard the "base key" from (S)RAM right after derivation is to make sure said "base key" isn't accessible for long, diminishing the attack vector on it.

I have the impression that the use case I'm proposing is something that is deemed valid, but there does seem to be resistance in how that use case is currently implemented. Is there any proposal you have on how I can implement this in a way that is acceptable to the community?

etienne-lms commented 9 months ago

Here, Transient objects and persistent objects are referring to the GP TEE concepts. Session objects and token objects are referring to PKCS#11 concepts. I agree there is no 1-to-1 relationship between both (otherwise the pkcs11 TA implementation would be much simpler).

That said, I'm still convinced that a PKCS#11 token object is something that persist even when the PKCS#11 token is down (e.g. device is powered off). I think a token object can be stored in OP-TEE secure storage but could also be stored in other places (OPT OTP fuses, ROM code, internal RAM or even an external device as TPM, etc...). OP-TEE pkcs11 TA currently uses OP-TEE secure storage for persistent data but could use other means. However, I think abstracting those another means behind a TEE_STORAGE_* API would simplify how the pkcs11 TA can interacts with OP-TEE core. For example, your OPT OTP-derived data could be accessed by such a TEE_STORAGE_OTP storage only accessible from the very pkcs11 TA, not other TAs, and only for PKCS#11 logged in sessions.

There could be a TEE_STORAGE_OTP for read-only object stored in the device OTP fuses

The point of the use-case I'm trying to support is that access to (S)OTP, which contains secrets, is limited to the first stage bootloader and closed right after the keys have been read from it. Keeping access to (S)OTP open to OPTEE seems to me like an increased security risk: if an attacker were to be able to "hack" OPTEE, he would be able to read from SOTP, giving him direct access to the keys in (S)OTP. The fact that we derive keys from the "base key" in SOTP in the first stage bootloader and discard the "base key" from (S)RAM right after derivation is to make sure said "base key" isn't accessible for long, diminishing the attack vector on it.

What you describe looks a lot like what DICE proposes. It fully makes sense. I think a platform cann fully emulate a TEE_STORAGE_OTP using secure RAM to store faked OTP data that are actually data derived from real OPT OTPs and passed to OP-TEE core at boot time.

I have the impression that the use case I'm proposing is something that is deemed valid, but there does seem to be resistance in how that use case is currently implemented. Is there any proposal you have on how I can implement this in a way that is acceptable to the community?

There is no resistance (if there were, I would be far less verbose in my answers :), just a will to understand to real need and find the best way for a generic approach.

(edited: s/OPT/OTP/g)

fifalars commented 9 months ago

Hey Etienne,

I seem to interpret some contradiction in your last post. You mention that:

That said, I'm still convinced that a PKCS#11 token object is something that persist even when the PKCS#11 token is down (e.g. device is powered off). I think a token object can be stored in OP-TEE secure storage but could also be stored in other places (OPT OTP fuses, ROM code, internal RAM or even an external device as TPM, etc...).

If a token object would be stored in internal RAM, it doesn't persist when the device is powered off?

If I understand correctly you would move away from using a Transient Object and move towards using a Persistent Object using TEE_STORAGE_OTP (e.g. TEE_OpenPersistentObject(TEE_STORAGE_OTP, etc). The OPTEE core would map this to internal RAM instead of any other persistent means. Is that a correct interpretation?

etienne-lms commented 9 months ago

If a token object would be stored in internal RAM, it doesn't persist when the device is powered off?

Yes, if the internal RAM content is preserved by some backup battery, as sometimes embedded on devices.

If I understand correctly you would move away from using a Transient Object and move towards using a Persistent Object using TEE_STORAGE_OTP (e.g. TEE_OpenPersistentObject(TEE_STORAGE_OTP, etc). The OPTEE core would map this to internal RAM instead of any other persistent means. Is that a correct interpretation?

No, I do not say all persistent objects should move into some other form of storage. OP-TEE persistent objects are currently stored in the secure torage (REE_FS or RPMB_FS) and can be remain there. But there could be another storage medium, OTP based, that would complement the existing one(s), and also provide TEE Persistent objects facilities.

We discussed this morning at the LOC (public discussions on OP-TEE evolutions, fixes, ..., see the meetings planned in https://linaro.atlassian.net/wiki/spaces/LOC/overview) on how to handle secret object stored in OTPs. It would be nice you could participate to the next meeting, if possible, to live discuss your needs with the OP-TEE maintainers and contributors. The discussion suggested some possible ways, creating a TEE_STORAGE_OTP not being the preferred one, but before I detail them, I need to make shure we use the same vocabulary.

TEE Transient objects and Persistent objects are a objects that complies comply with the GP TEE Internal Core API spec description. As such, they can be used with the TEE API crypto functions. The main diff between both is the storage medium that is volatile or persistent. The pkcs11 TA uses TEE Persistent raw data objects to store token objects, and creates Transient objects from the raw data objects content just in order to use the TEE API functions for crypto operations. You see here thatthe pkcs11 TA non-volatile objects uses rely on both TEE Persistent object resources AND TEE Transient object resources.

In your case, you need to perform crypto operations using a secret stored in the OTP. In order to use the GP TEE API crypto functions, the secret must be created as either a TEE Transcient object or a TEE Persistent object. As Because TEE Persistent objects are stored in OP-TEE secure storage but you don't want your object to be so, we need an alternate way. An alternate way could be to ask OP-TEE core to create a Transcient object for the TA, based on your OTP secret data so that the TA can later use the GP TEE API crypto functions with that secret. Does that seem fine to you? (before looking at how to implement that).

(edited: fixed typos, few rephrasing)

fifalars commented 9 months ago

No, I do not say all persistent objects should move into some other form of storage. OP-TEE persistent objects are currently stored in the secure torage (REE_FS or RPMB_FS) and can be remain there. But there could be another storage medium, OTP based, that would complement the existing one(s), and also provide TEE Persistent objects facilities.

Right, that was my understanding as well.

It would be nice you could participate to the next meeting, if possible, to live discuss your needs with the OP-TEE maintainers and contributors.

That would be great, please feel free to forward the meeting invite to the email address associated with this account.

An alternate way could be to ask OP-TEE core to create a Transcient object for the TA, based on your OTP secret data so that the TA can later use the GP TEE API crypto functions with that secret. Does that seem fine to you? (before looking at how to implement that).

That's indeed how I envisioned it and it's in fact how I've tried implementing it now; allocate and populate a Transient Object for storing these OTP(-derived) keys (see the addition to create_object in the PR associated to this ticket).

vesajaaskelainen commented 9 months ago

Let me share what we do.

We do not derive anything else from eFuses than secure storage key (on some platforms this is better than in some others). Please note that deriving too much from same key material is often a bad idea.

What we do in device manufacturing phase is that we dedicate one PKCS#11 token for manufacturing time data. In there we do generate key pairs and then store in example IDevID certificate.

To support factory reset operation we do make read-only backup of secure storage.

This way we get best of both worlds. Eg. secure storage gets best encryption key per platform and then we get random based private keys.

Then we have some supporting services as PTA in OP-TEE that also need access for protected materials (eg. eFuses or other uniqueness sources). One of those things that we do get from there is unique hardware ID that we can then lock device identity and such things to the device.

Just wondering if similar approach would also work for you too.

fifalars commented 9 months ago

secure storage key

What do you use such a key for?

What we do in device manufacturing phase is that we dedicate one PKCS#11 token for manufacturing time data.

Where do you store these PKCS#11 tokens?

etienne-lms commented 9 months ago

It would be nice you could participate to the next meeting, if possible, to live discuss your needs with the OP-TEE maintainers and contributors.

That would be great, please feel free to forward the meeting invite to the email address associated with this account.

I don't think there are invites. Just get the meeting details from https://linaro.atlassian.net/wiki/spaces/LOC/overview, next meeting is planned Tuesday, 26-th December 2023, 9:00am UTC, and join that day.

etienne-lms commented 9 months ago

Actually there is a mailing list you can register to to be notified on LOC meetings (IIUC): https://op-lists.linaro.org/archives/list/linaro-open-discussions@op-lists.linaro.org/

vesajaaskelainen commented 9 months ago

secure storage key

What do you use such a key for?

OP-TEE uses secure storage key and TA specific keys to encrypt secure storage it is using.

What we do in device manufacturing phase is that we dedicate one PKCS#11 token for manufacturing time data.

Where do you store these PKCS#11 tokens?

We have partition in eMMC with folder for OP-TEE's secure storage (tee-supplicant is the one to write the objects in there). Whether secure storage item is for PKCS#11 token cannot be seen from those files as OP-TEE is only party that can open secure storage items.

For manufacturing time factory setting or other information we have one read-only partition where we make tar archive of OP-TEE's secure storage. On factory reset operation we format the other partition and restore secure storage to its initial state.

In theory one could utilize eMMC's RPMB but we have not taken that in use and this method works fine for us.

jforissier commented 9 months ago

In theory one could utilize eMMC's RPMB but we have not taken that in use and this method works fine for us.

Side note: RPMB offers rollback protection, but as a consequence factory reset is a bit more difficult to implement.

github-actions[bot] commented 8 months ago

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