tpm2-software / tpm2-tss-engine

OpenSSL Engine for TPM2 devices
https://tpm2-software.github.io
BSD 3-Clause "New" or "Revised" License
149 stars 99 forks source link

Concurrent access to hardware not possible #149

Closed jhealyt closed 4 years ago

jhealyt commented 4 years ago

I get the following intermittently:

`Failed to open device file /dev/tpm0: Device or resource busy`

when I load the engine into OpenSSL, or when I try to get a random number from the TPM2 chip.

To get around this, I have patched the OpenSSL library so that it locks a globally named mutex every time it loads the engine or tries to retrieve a random number. But is there a better way of doing this?

I notice that there is also "/dev/tpmrm0". . . Does this have something to do with concurrent access?

AndreasFuchsTPM commented 4 years ago

Yes.

If you need concurrent access, either go via tpmrm0 or use tpm2-abrmd

healytpk commented 4 years ago

Yes.

If you need concurrent access, either go via tpmrm0 or use tpm2-abrmd

I have patched the OpenSSL library so that it always loads the TPM2 engine and always uses it. I have removed the built-in random number generator from OpenSSL, and I have removed the Intel RDRAND engine too. Also I have removed the 'mssim' simulator from tpm2-tss.

So if the TPM2 engine for OpenSSL fails to load, or if there's a problem with the TPM2 chip, then there isn't anywhere else that a random number can come from. In fact the OpenSSL library will fail to load altogether if the TPM2 isn't working. (I'm also looking at removing the PRNG from the Linux kernel too but that's another day's work).

As the OpenSSL library is loaded by half a dozen processes, and as some of these processes are multithreaded, I was at first getting intermittent errors when trying to do "openssl rand -hex 128", like so: "Device or resource busy /dev/tpm0".

My solution to this problem was to go into the source code for libOpenSSL in the "rand_bytes" function and to use a globally named mutex, like this:

int rand_bytes(char *const p, int const i) {     Lock_Global_Mutex("openssl_tpm2");

    int const retval = rand_bytes_real(p,i);

    Unlock_Global_Mutex("openssl_tpm2");

    return retval; }

This solved the problem of concurrent accesses failing with "Device or resource busy /dev/tpm0", but then I later found that I must now do the same thing with the function 'Tss2_Tcti_Device_Init' as it is occasionally failing with the same error (e.g. if two processes try to load the OpenSSL library within a few hundred milliseconds of each other).

I can of course amend the OpenSSL source code to use the globally named mutex for the 'Init' function also, but before I go any further. . . I'd like to ask if there's an easier or better way of enabling concurrency.

Can I do away with my globally named mutex if I reconfigure tcti-device to use "/dev/tpmrm0" instead of "/dev/tpm0"? I also had a look at tpm2-abrmd but I don't understand what it does or what it's used for.

At the moment, the only program/library using the TPM2 chip on my embedded device is the libOpenSSL library, however later I might also use some of the tpm2-tools at the command line, which means I might occassionally get the error "Device or resource busy /dev/tpm0".

Is the solution here simply to use "/dev/tpmrm0" ? Do I simply recompile the entire tpm2-software suite to use /dev/tpmrm0 ?

AndreasFuchsTPM commented 4 years ago

Duplicate of https://github.com/tpm2-software/tpm2-tss/issues/1550