Added session functionality#169
Conversation
The salt key is located in the null hierarchy and will later on be used for session management. By provideing a tpmKey, the ESAPI layer: 1. Generates a random salt. 2. Encrypts it with the tpmKey's public key (asymmetric encryption — only the TPM can decrypt it) 3. Sends the encrypted salt to the TPM during StartAuthSession 4. Both sides derive the session key from this shared salt This salt contributes entropy to the session key, which is then used as the symmetric key for AES-CFB parameter encryption/decryption. Without it, there's nothing to encrypt parameters with. Signed-off-by: Thomas Kopp <thomas.kopp@securiton.ch>
An auth session is being used to secure the communication between the provider and the TPM-chip itself. Signed-off-by: Thomas Kopp <thomas.kopp@securiton.ch>
In order to make sure passwords are being encrypted when communicating between the openssl provider and the TPM itself. Signed-off-by: Thomas Kopp <thomas.kopp@securiton.ch>
|
Based on the description, you have to trust that the communication channel is not compromised when you generate the null key. So an attacker just has to feed back a key they control. You need a way to verify that it's a known good key, during a step when the tpm is in a trusted state or verify it to an EK. This doesn't thwart the attack you're attempting to prevent. |
|
Thanks for your feedback William. Thanks for pointing that out. I (unfortunately) haven't been thinking about this aspect. It would be nice if we could find a solution which can be fully implemented in the provider itself. Without any requirements to the environment. But I don't really have an idea on how this can be achieved. You mentioned two ideas:
I also had a look at the tpm2-pkcs11 where you implemented the session handling (if I'm not mistaken). From my understanding you're using the primary key as tpm-key as well as bind parameter when calling Esys_StartAuthSession. That's a solution I've seen in multiple implementations. Also in this example here: https://gitlab.com/opensecuritytraining/TC1102_TPM_Intermediate_code_for_class/-/blob/main/solutions/lab4/lab4.c?ref_type=heads The problem I'm seeing is that the password for the owner hierarchy (when creating a primary key) or the password for the primary key (when creating a key below the primary) is being sent unencrypted. Therefore this approach isn't water-proof as well..... Do you have any other ideas? |
In the PKCS11 code, we make the following assumption:
I would use this model again here. We can store the parent key information in the PEM file, and use that to verify the key . I would just serialize the key name into the pem file, and then verify the names in the code. This model would work for both transient and persistent parent keys.
See above, in the threat model, we say when the primary key is being generated, the system must be in a known good state. One thing I wanted to add was a name option to the enrollment commands, so you can verify that the key you created is what you expected.
|
|
Thanks for your inputs. I see your point. What you assume in your threat model makes totally sense. You're talking about adding parent information to the pem file. I assume you're referring to the TSS2 PRIVATE KEY according to: https://github.com/tpm2-software/tpm2-openssl/blob/master/docs/keys.md#loading-a-private-key? You'd need to handle compatibility as earlier versions of the provider (or keys created by the tpm-tss-engine) wouldn't have that key name information. Additionally silently dropping session support in such cases doesn't feel like a good approach. Furthermore I don't see how the proposed approach would work for keys specified as handles or serialized objects. Serialized objects are created using tpm2-evictcontrol (which is not part of the provider-ecosystem and therefore would not be able to add any specific information used by the provider solely). Having session support exclusively for keys specified in PEM format unfortunately isn't a full solution, as keys stored as handles or serialized objects can be password protected too - therefore sessions are needed in these cases as well. |
I would just warn, this will preserve backwards compatibility behavior.
I think this is only for parent objects, which could be persistent objects. In this case, the parent information would be serialized to the child keys pem format IIUC. |
I see your point. Our primary is persistent as well as our derived keys. The problem is, that we're not using PEM files for the keys. Serialized objects are being created using the tpm2-tools. So it wouldn't be possible to add any additional parent information that the provider could use to start an auth session. Meaning: Adding information to a PEM file, isn't a solution for our use - case. Can't we find a solution that works for PEM-files, serialized objects as well as key-handles? |
The parent key should be the SRK (Storage Root Key) which has no password and is at a known fixed address. If this is not the case, then it would have made sense to make a passwordless parent key below the current parent key that has a password, this key could then serve as the parent to the actual keys.
The problem here is, the TPM has very limited amounts of persistent storage, so in shared systems, this can lead to an issue.
There could be a lookup a table in a config file somewhere, but this seems more like a hack job to make it work rather than a clean design on key management. Maybe support persistent keys in the PEM file. Something like, if key is marked persistent, and found |
Auth sessions are used to protect sensitive data (e.g. key passwords / parameters) transferred between the TPM and the provider.
Salt key
The approach was to generate a salt key in the null hierarchy. The key is being loaded when the provider is being initialized and destroyed when the provider is being tear down.
The flow is as follows
This salt contributes entropy to the session key, which is then used as the symmetric key for AES-CFB parameter encryption/decryption. Without it, there's nothing to encrypt parameters with.
Session lifetime
Sessions are being created per operation. If an operation leads to multiple ESYS-API commands, the same session is being reused. This should lead to a good balance between performance and ease of use. In order to start and end the session I added helper functions to tpm2-provider-core.c
Affected commands
I modified all commands which used TR_PASSWORD as session handle in order to use an auth session.
Testing
Regarding the current testing infrastructure, writing unit tests is difficult. This isn't anything which can be tested explicitly when using openssl cli. We'd need to mock the ESYS-API to verify if the corresponding methods are called.
Hint
I developed the idea as well as the implementation with the help of GitHub CoPilot and the Claude Opus 4.6 model. I did a manual review of the code (as well as I can do it) and did some manual adjustments. It compiles and it seems to work. I'm open to inputs regarding improvements.
Resolves: #65