How to set up libmosquitto with TPM (tpm2tss)

Hi,

it is not quite clear to me how to use the hardware TPM module of my system in combination with libmosquitto, I also failed to find any examples, I hope I am not the first one who is trying this :slight_smile:

So, what I was able to figure out so far from the documentation and googling is:

  • use mosquitto_string_option(msq_client, MOSQ_OPT_TLS_ENGINE, "tpm2tss"); to set the engine
  • use mosquitto_string_option(msq_client, MOSQ_OPT_TLS_KEYFORM, "engine"); to tell the library that we want to use an engine in the first place

How do I pass it the key identifier, i.e. how do I tell it which key from TPM to use? I was not yet able to figure this out… Is this still done via mosquitto_tls_set()? If yes, what would be the “keyfile” then, the TPM storage path?

Kind regards,
Jin

Hi Jin,

The TPM related code was contributed and it’s not something I’ve personally used. Looking at the code, the intention is that you set at least one of capath, cafile, or set the option to use OS CA certs, in order to enable TLS mode.

Then the certfile and keyfile arguments need setting, with certfile being the server certificate, and the keyfile parameter telling the TPM engine which key to use. If this doesn’t work then please let me know - as I say it’s not something I’ve especially had chance to work with.

Regards,

Roger

Hi Roger,

Then the certfile and keyfile arguments need setting, with certfile being the server certificate, and the
keyfile parameter telling the TPM engine which key to use.

this is what I am struggling with somehow, if I look at int mosquitto_tls_set() in lib/options.c, what it does with the keyfile is the following:

    if(keyfile){
        fptr = mosquitto__fopen(keyfile, "rt", false);
        if(fptr){
            fclose(fptr);
        }else{
            mosquitto__free(mosq->tls_cafile);
            mosq->tls_cafile = NULL;

            mosquitto__free(mosq->tls_capath);
            mosq->tls_capath = NULL;

            mosquitto__free(mosq->tls_certfile);
            mosq->tls_certfile = NULL;
            return MOSQ_ERR_INVAL;
        }
        mosq->tls_keyfile = mosquitto__strdup(keyfile);
        if(!mosq->tls_keyfile){
            return MOSQ_ERR_NOMEM;
        }

So the function expects a key file to be an actual file, else it considers it to be an error… but this is the private key, right? So in the TPM case it can not be a file on the filesystem, it has to be the key identifier for tpm2tss. If I look at the tpm2tss docs, I see that Fapi works with key paths, which I guess makes sense - we tell Fapi functions the key path in the storage, usually HS/SRK/mykey (see the keyPath parameter in Fapi functions tpm2-tss: Fapi_Sign).

So I wonder if I am still missing something or if the guys who contributed that code used it differently. I am not a TPM expert, so its difficult for me to decide if its my “user error” or if something is still missing in the library implementation.

I understand that you did not use this API yet, so ultimately we both do not know if it works; I am not sure I am educated enough on the matter to say that it doesn’t, it’s my first time with TPM :) How should we proceed here?

Regards,
Jin

Hi Roger,

with some help from the tpm2-software mailing lists I think I now have an idea of how this is supposed to work, looks like the API provided by libmosquitto should be enough, I’ll write a short summary later once I had the time to actually test the setup.

Basically one needs to tell TPM to create that key file and then everything should work:
https://lists.01.org/hyperkitty/list/tpm2@lists.01.org/thread/PBFPE3EHIKAATVRL4TPULDS3FFJSCHFF/

Kind regards,
Jin

Finally got to test it and it seems to work like this (assuming you have already created a key in your TPM):

tss2_gettpmblobs --path=HS/SRK/mykey -u blob.pub -r blob.priv
tpm2_encodeobject -u blob.pub -r blob.priv -C 0x81000001 -o key.pem

Then in libmosquitto one should set:

mosquitto_string_option(msq_client, MOSQ_OPT_TLS_ENGINE, "tpm2tss");
mosquitto_string_option(msq_client, MOSQ_OPT_TLS_KEYFORM, "engine");
mosquitto_tls_set(msq_client, NULL, "/etc/ssl/certs", "mydomain.crt", "key.pem", NULL)

It seems to be important to call mosquitto_tls_set() after applying the above ENGINE and KEYOFORM options.

Regards,
Jin