tpm2-software/tpm2-tss

test: rework FAPI integration test harness

joholl opened this issue · 6 comments

joholl commented

The FAPI test harness has several issues and should be refactored.

What is done already

In #2640, we finally switched to tctildr and enabled libtpms for our integration tests. While I was at it, I cleaned up the sys and esys test harnesses. I did this for three reasons:

  1. I want cleaner code
  2. I want to get rid of test/helper/tpm_startup.c, test/helper/tpm_dumpstate.c, test/helper/tpm_transientempty.c, ...
  3. I want to greatly simplify (or get rid of?) our bash scripting (script/int-log-compiler.sh, script/fint-log-compiler.sh, ...)

As a consequence, sys and esys can already run as standalone binaries. The dumpstate/transientempty/... logic is now part of the same binary and libtpms is loaded by tctildr if configured accordingly (currently via the mandatory env variable TPM20TEST_TCTI).

What needs to be done still

The fapi test harness is very complex. I'd like to see the following things:

  1. cleaner code, i.e. same structure as with sys/esys:
    • setup
    • checks_pre
    • invoke test
    • checks_post
    • teardown
  2. no global state
  3. not dependent on external calls
    1. remove test/helper/*.c (fairly easy, the ground work is done)
    2. remove test/helper/*.sh and calls to openssl: this applies mainly to EK generation stuff which is currently called from script/fint-log-compiler.sh

@JuergenReppSIT I need your support with 3.ii. When working on #2640, I started with this but realized this is not trivial. I don't know what exactly we are doing here, but I wonder if we can move some of this code to the c code for test setup and/or to bootstrap.sh. I'm open for other suggestions.

Why

Firstly, this should simplify the code a lot. This alone should be reason enough. Secondly, this enables calling fapi tests standalone which makes e.g. debugging via gdb much easier. Lastly, switching to meson some day (#955) requires having standalone binaries, afaik (@AndreasFuchsTPM correct me if I'm wrong).

One remark: In the past I did debug FAPI with the following script:

#!/usr/bin/env bash
export TPM20TEST_TCTI=mssim
touch test/integration/main-fapi.c
make $1 'CFLAGS=-DFAPI_TEST_EK_CERT_LESS -g'
libtool --mode=execute cgdb --args $1

I just replaced mssim with libtpms and it worked for test/integration/fapi-get-random.fint. So standalone debugging is already possible with libtpms in cert less mode.

2. no global state

you marked the variables related to the used config and keystore paths. What exactly did you mean in this context with "no global state"?

joholl commented

In the past I did debug FAPI with the following script

Ah, that is helpful, thanks.

What exactly did you mean in this context with "no global state"?

I mainly meant the global_fapi_context (but it applies all of these global variables). I'm not a huge fan of global state because basically every function in scope can meddle with it. E.g. init_fapi() gets a FAPI_CONTEXT **fapi_context but then also writes to global_fapi_context. This is confusing.

What I'd prefer having is a test context, like we have with sapi and esapi right now. This way, you can pass exactly what is needed by the function (either the whole context or members) to the function and it is instantly clear what is read/modified by the function.

typedef struct {
TSS2_TCTI_CONTEXT *tcti_ctx;
TSS2_SYS_CONTEXT *sys_ctx;
tpm_state *tpm_state;
} TSS2_TEST_SYS_CONTEXT;

typedef struct {
TSS2_TCTI_CONTEXT *tcti_ctx;
TSS2_TCTI_CONTEXT *tcti_proxy_ctx;
ESYS_CONTEXT *esys_ctx;
tpm_state *tpm_state;
} TSS2_TEST_ESYS_CONTEXT;

Admittedly this is not a huge deal or difficult to refactor, I was mentioning it more for completeness sake.

yes it would be cleaner to use a TSS2_TEST_FAPI_CONTEXT. As you wrote the checks, the writing of the EK pub to a file and perhaps the computation of the EK fingerprint could be integrated into the FAPI main program. Could we call the former create-ca.sh via a call of the C system function from the fapi-main? I would say porting all this stuff to C for openssl 3 and 1.1 is to much effort an not necessary.

joholl commented

I would say porting all this stuff to C for openssl 3 and 1.1 is to much effort an not necessary.

Agreed.

Could we call the former create-ca.sh via a call of the C system function from the fapi-main.

Technically we could, but I'd rather not have the (now currently self-sufficient) binaries call a shell to interpret some scripts. Could we maybe generate the stuff once and then use the same certificates for all the tests? If so, we could move the call to create_ca.sh e.g. to ./bootstrap.sh.

? If so, we could move the call to create_ca.sh e.g. to ./bootstrap.sh.

But you need the ek to generate the certificate. If you execute the provisioning with libtpms you will get a different ek for every call.