Closed tobuh closed 3 years ago
Does tpm2.CreateKey
or tpm2.Load
error? It does not appear that you are handling/printing/checking errors, that would be a good starting point to seeing any issues.
fwiw, I've found that most TPM simulators emit a ton of console messages, and not all warnings are erroneous.
One possible explanation is that Load
is erroring, and then your deferred call to tpm2.FlushContext(rwc, tpmKeyHandle)
is using an invalid transient handle (hence causing that message).
Of course I forgot to mention the error code. It's stripped down debugging code, so I did not do proper error handling, in sense of printing, but at least in sense of debug watches ...
ContextSave gives a tpm2.HandleError, with Code: 4 and Handle: RC1 (1)
CreateKey and Load are totally fine ... The tpmKeyHandle is "0x800000ff"
I can clearly watch while debugging, that ContextSave is causing this error.
To emphasize, what makes me helpless is: The same procedure is working with tpm2-tools ...
Whats the intent behind doing ContextSave ?
If you are trying to match the behavior of tpm2-tools, it might be useful to somehow dump the bytes on the tpm command socket so you can see the difference between what tpm2-tools is doing, and what your code is doing. If I had to guess:
I do not want to match exactly tpm2-tools. It was just to show that the basic setup with tabrmd, socat, etc. generally works. But it does unfortunately not work with go-tpm.
It is not only a misbehavior of ContextSave. I observed this also with other functions, that need the handle of a loaded key, like ReadPublic.
As I described in my initial post, in the error output of tabrmd, the translation of a vhandle to a phandle does not work. I cannot imagine why? Do you have an idea?
go-tpm is extremely simple in this regard: we take the command and serialize it into a byte stream the TPM expects. These methods work fine for me (though ive never used ContextSave), so would be surprised if we were encoding the handles wrong. Are you sure there is no bug in tabrmd
?
The only thing I can think of is the length prefix for the handles: Theres some subtlety in which encoding you use on the wire. Maybe theres some wierd edge case in tabrmd
there, or possibly go-tpm? If you could get a dump of the command bytes, it would be a lot easier to tell.
Out of curiosity, is there a reason yous are using tabrmd instead of the resource manager built into the operating system?
Disclaimer: I'm not an expert on TPM resource managers in general, or abrmd in particular. If I were writing a TPM resource manager, I would not support the ContextSave/ContextLoad commands, as it would drastically increase the complexity of my resource manager for little-to-no benefit (those commands exist so resource managers can exist).
I wouldn't expect abrmd to support ContextSave/ContextLoad based on this comment: https://github.com/tpm2-software/tpm2-abrmd/blob/b170475e6006fe95461d0c58770931eb151f4772/src/resource-manager.c#L1100
@twitchy-jsonp Would be log output of swtpm sufficient? There is a lot of traffic of course ... Which part do you exactly need?
I use tabrmd because of a recommendation from one of the main developers of tpm2-tss. And another opinion from here: https://github.com/tpm2-software/tpm2-abrmd/issues/730#issuecomment-674950210 I do not use a very recent kernel. So I thought it might be better to use tabrmd. Anyway, I somehow need to simulate a RM as in my (virtual) test setup environment. And third, I have a LSM, that gives access to /dev/tpm0 and /dev/tpmrm0 simultaneously. I cannot separately restrict /dev/tpm0. So this is also a further encapsulation method for TPM access.
@chrisfenner Thanks for the hint, this makes me wonder, if I need to readjust my setup. Anyway, the exact same use-case works with tpm2-tools.
Sorry for my reading comprehension, I see more clearly how tpm-tools seems to be saving the context successfully with an identical setup.
I'm curious how tabrmd tracks different callers so that it can reload state and recognize their contexts (caller A's key 0x800000ff is a totally other thing than caller B's key 0x800000ff). I wonder if the TPM writing pattern into the socket differs between go-tpm and tpm2-tools.
I investigated a bit further on this topic. I noticed there are (perhaps similar?) errors with my in-kernel RM (kernel 4.19). If I run on /dev/tpm0 directly, everything is working fine. Let me ask you one question, just to be sure: Do you successfully use this library in an environment with a RM with regard to functions that needs TPM contexts/sessions, like ContextSave, ReadPublic and so on?
I looked at the debugging output of tabrmd, and noticed a significant difference. On using go-tpm, the only messages that are in context with sessions is "resource_manager_remove_connection: flushing session contexts". So, I think, on every TPM connection close (on every TPM command?), there is this connection close, thus flushing contexts, thus no possibility any more to readdress the relationship between pHandle and vHandle.
Whereas the tpm2-tools with tpm2-tss, are making use of sessions extensively. There are a lot of session related messages. To give you an impression, some extracts:
create_context_mapping_session: handle is a session, creating entry for SessionList and SessionList
session_entry_new
resource_manager_load_session_from_handle: mapped session handle 0x02000000 to SessionEntry
resource_manager_flush_context handle: 0x2000000
resource_manager_flush_context: handle 0x02000000is a session, removing from SessionList
So, are there any commands missing, that I need to use from go-tpm, to enable such session handling?
If necessary I can provide detailed output tomorrow. I still need to do some simplified testing ...
Finally, found the origin of the problem, as I also noticed a lot of "received CONNECTION_REMOVED message for connection" from the tabrmd when using go-tpm, after each command.
As I am connecting to unix-sockets (instantiated by socat), go-tpm is using "EmulatorReadWriteCloser" which is always closing and opening the connection to the TPM, thus automatically flushing every contexts. I don't think this behaviour is correct. It is a special implementation for TPM emulator. I rewrote the "EmulatorReadWriteCloser" implementation, without close/reopening, and it works in my use case.
I will think about a proper solution here. Suggestions welcome.
Finally, easy one! Implemented my own OpenTPM function ... everything working as expected
I have following setup:
Reasons for this setup:
Additionally, I already created a SRK:
I succesfully ran tpm2-tools in this setup:
key.ctx has content! So the setup should generally work ...
Now to my problem. I have following demo code:
Socket is opening, CreateKey gives reasonable return values, but on ContextSave abrmd (with G_MESSAGES_DEBUG=all) gives follwing warning:
key.ctx is empty in this case! This is observed with every "key-handle" function, e.g. ReadPublic ...
When I ommit abrmd, using swtpm directly with
swtpm socket --tpmstate dir=/some/dir --tpm2 --ctrl type=tcp,port=2322 --server type=unixio,path=/path/to/socket --flags startup-clear
it works without problems.
But as I ran tpm2-tools successfully on this setup, it should work.
Any ideas, suggestions? Am I missing something?
Thanks for your help.