tpm2-software / tpm2-tss

OSS implementation of the TCG TPM2 Software Stack (TSS2)
https://tpm2-software.github.io
BSD 2-Clause "Simplified" License
730 stars 359 forks source link

Help writing simple C program to read PCR values. #394

Closed Scrappy20907 closed 7 years ago

Scrappy20907 commented 7 years ago

Hello,

I am slowly trying to gain an understanding of TPMs and how to write programs to interact with TPMs. The end goal is to do remote attestation to make sure no malicious changes were made to the computer. I want to start simple and work my way up to more complex.

Right now I just want to write a simple c program in Ubuntu to read the PCR values from the TPM without having to use the resource manager. something like:

include "headers"

int main() { int i; int pcrs[8]; for( i=0 ; i<8; i=i+1) { pcrs[i]=read_PCR_values(i); printf("PCR[%d]=%d\n", i, pcrs[i]); } return 0; }

I tried looking at examples in "TPM2.0-TSS/test/integration" and "tpm2.0-tools/tools/tpm2_listpcrs.c" but they have too many extra things that I don't understand yet.

I am not very fluent with C programming in linux environment, I studied Electrical Engineering and ended up getting a job in System Security Engineering, so a lot of this is new to me. Would anybody be able to help me?

-thank you

danglus commented 7 years ago

Hi @Scrappy20907, I'm also in the process of learning how to use the TPM, so I wrote the following code for you (as an exercise). Basically, it reads the context of PCR0 from the physical TPM at /dev/tpm0.

I only tried it with the Infinion TPM that is available in the NUC that I'm using (running Ubuntu 16.04). The code is based on the tpm2_tools.

To complie it, you have to use the following gcc flags in order to include the relevant TSS libraries: -ltcti-device -lsapi To run it, you'll probably need to use 'sudo' (as it connects directly to the driver).

Let me know if it works for you.

Cheers! Dan

//------------------------------------------------------

include

include

include

include <tcti/tcti_device.h>

include <sapi/tpm20.h>

define TCTI_DEVICE_DEFAULT_PATH "/dev/tpm0"

define BUFFER_SIZE(type, field) (sizeof((((type *)NULL)->t.field)))

define TPM2B_TYPE_INIT(type, field) { .t = { .size = BUFFER_SIZE(type, field), }, }

TSS2_TCTI_CONTEXT tcti_device_init (char const device_file) { TCTI_DEVICE_CONF conf = { .device_path = device_file, .logCallback = NULL, .logData = NULL, }; size_t size; TSS2_RC rc; TSS2_TCTI_CONTEXT *tcti_ctx;

// this function is located at: TPM2.0-TSS/tcti/tcti_device.c
rc = InitDeviceTcti (NULL, &size, 0);
if (rc != TSS2_RC_SUCCESS) {
    fprintf (stderr,
             "Failed to get allocation size for device tcti context: "
             "0x%x\n", rc);
    return NULL;
}
tcti_ctx = (TSS2_TCTI_CONTEXT*)calloc (1, size);
if (tcti_ctx == NULL) {
    fprintf (stderr,
             "Allocation for device TCTI context failed: %s\n",
             strerror (errno));
    return NULL;
}
rc = InitDeviceTcti (tcti_ctx, &size, &conf);
if (rc != TSS2_RC_SUCCESS) {
    fprintf (stderr,
             "Failed to initialize device TCTI context: 0x%x\n",
             rc);
    free (tcti_ctx);
    return NULL;
}
return tcti_ctx;

}

/*

int main(int argc, char argv[]) { TSS2_TCTI_CONTEXT tcti_ctx; TSS2_SYS_CONTEXT* sapi_ctx;

tcti_ctx= tcti_device_init (TCTI_DEVICE_DEFAULT_PATH);
if(tcti_ctx==NULL) exit(0);

sapi_ctx= sapi_ctx_init(tcti_ctx);
if(sapi_ctx==NULL) exit (0);

// ------------------------------------------------------------

TPML_PCR_SELECTION pcr_selection_tmp;
TPML_PCR_SELECTION pcr_selection_out;
UINT32 pcr_update_counter;
TPML_DIGEST pcr_values;

pcr_selection_tmp.count = 1;
pcr_selection_tmp.pcrSelections[0].hash = TPM_ALG_SHA1;
pcr_selection_tmp.pcrSelections[0].pcrSelect[0] = 1;
pcr_selection_tmp.pcrSelections[0].pcrSelect[1] = 0;
pcr_selection_tmp.pcrSelections[0].pcrSelect[2] = 0;
pcr_selection_tmp.pcrSelections[0].sizeofSelect = 3;

UINT32 rval = Tss2_Sys_PCR_Read(sapi_ctx, 0, &pcr_selection_tmp,
            &pcr_update_counter, &pcr_selection_out,
            &pcr_values, 0);

if (rval != TPM_RC_SUCCESS) {
     printf("read pcr failed. tpm error 0x%X\n", rval);
     return -1;
}
printf("pcr_update_counter=%d\n",pcr_update_counter);
for (int i=0; i<pcr_values.count ; i++) {
    printf("pcr_value[%d]=",i);
    for(int j=0; j < pcr_values.digests[i].t.size; j++) {
        printf("%X ", pcr_values.digests[i].t.buffer[j]);
    }
    printf("\n");
}
// --------------------------------------------------------
Tss2_Sys_Finalize (sapi_ctx);
free (sapi_ctx);
tss2_tcti_finalize (tcti_ctx);
free (tcti_ctx);

}

Scrappy20907 commented 7 years ago

When I try to compile the program I get the errors shown in the picture below: terminal I have all the relevant header files and libraries in my /usr/include system directory. the code I tried to compile is in the .txt file below if you would like to see it. (but its pretty much just copying and pasting what you wrote). pcr_test.txt Do I just need to tweak the code a little bit? Or does this seem like a deeper problem?

Edit: Also, thank you very much for helping me. I didn't expect anyone to take the time to write me some sample code and help me out.

Scrappy20907 commented 7 years ago

Here is the code pasted out if you don't want to download the .txt file:

include

include

include

include <tcti/tcti_device.h>

include <sapi/tpm20.h>

define TCTI_DEVICE_DEFAULT_PATH "/dev/tpm0"

define BUFFER_SIZE(type, field) (sizeof((((type *)NULL)->t.field)))

define TPM2B_TYPE_INIT(type, field) { .t = { .size = BUFFER_SIZE(type, field), }, }

TSS2_TCTI_CONTEXT tcti_device_init (char const device_file) { TCTI_DEVICE_CONF conf = { .device_path = device_file, .logCallback = NULL, .logData = NULL, }; size_t size; TSS2_RC rc; TSS2_TCTI_CONTEXT *tcti_ctx;

rc = InitDeviceTcti (NULL, &size, 0);
if (rc != TSS2_RC_SUCCESS) {
    fprintf (stderr,
         "Failed to get allocation size for device tcti context: "
         "0x%x\n", rc);
    return NULL;
}
tcti_ctx = (TSS2_TCTI_CONTEXT*)calloc (1, size);
if (tcti_ctx == NULL) {
    fprintf (stderr,
         "Allocation for device TCTI context failed: %s\n",
         strerror (errno));
    return NULL;
}
rc = InitDeviceTcti (tcti_ctx, &size, &conf);
if (rc != TSS2_RC_SUCCESS) {
    fprintf (stderr,
         "Failed to initialize device TCTI context: 0x%x\n",
         rc);
    free (tcti_ctx);
    return NULL;
}
return tcti_ctx;

}

TSS2_SYS_CONTEXT sapi_ctx_init (TSS2_TCTI_CONTEXT tcti_ctx) { TSS2_SYS_CONTEXT sapi_ctx; TSS2_RC rc; size_t size; TSS2_ABI_VERSION abi_version = { .tssCreator = TSSWG_INTEROP, .tssFamily = TSS_SAPI_FIRST_FAMILY, .tssLevel = TSS_SAPI_FIRST_LEVEL, .tssVersion = TSS_SAPI_FIRST_VERSION, };

size = Tss2_Sys_GetContextSize (0);
sapi_ctx = (TSS2_SYS_CONTEXT*)calloc (1, size);
if (sapi_ctx == NULL) {
    printf ("Failed to allocate 0x%zx bytes for the SAPI context\n",
    size);
    return NULL;
}
rc = Tss2_Sys_Initialize (sapi_ctx, size, tcti_ctx, &abi_version);
if (rc != TSS2_RC_SUCCESS) {
    printf ("Failed to initialize SAPI context: 0x%x\n", rc);
    free (sapi_ctx);
    return NULL;
}
return sapi_ctx;

}

int main(int argc, char argv[]) { TSS2_TCTI_CONTEXT tcti_ctx; TSS2_SYS_CONTEXT* sapi_ctx;

tcti_ctx= tcti_device_init (TCTI_DEVICE_DEFAULT_PATH);
if(tcti_ctx==NULL) exit(0);

sapi_ctx= sapi_ctx_init(tcti_ctx);
if(sapi_ctx==NULL) exit (0);

// ------------------------------------------------------------

TPML_PCR_SELECTION pcr_selection_tmp;
TPML_PCR_SELECTION pcr_selection_out;
UINT32 pcr_update_counter;
TPML_DIGEST pcr_values;

pcr_selection_tmp.count = 1;
pcr_selection_tmp.pcrSelections[0].hash = TPM_ALG_SHA1;
pcr_selection_tmp.pcrSelections[0].pcrSelect[0] = 1;
pcr_selection_tmp.pcrSelections[0].pcrSelect[1] = 0;
pcr_selection_tmp.pcrSelections[0].pcrSelect[2] = 0;
pcr_selection_tmp.pcrSelections[0].sizeofSelect = 3;

UINT32 rval = Tss2_Sys_PCR_Read(sapi_ctx, 0, &pcr_selection_tmp,
        &pcr_update_counter, &pcr_selection_out,
        &pcr_values, 0);

if (rval != TPM_RC_SUCCESS) {
     printf("read pcr failed. tpm error 0x%X\n", rval);
     return -1;
}
printf("pcr_update_counter=%d\n",pcr_update_counter);
for (int i=0; i<pcr_values.count ; i++) {
    printf("pcr_value[%d]=",i);
    for(int j=0; j < pcr_values.digests[i].t.size; j++) {
        printf("%X ", pcr_values.digests[i].t.buffer[j]);
    }
    printf("\n");
}

// --------------------------------------------------------

Tss2_Sys_Finalize (sapi_ctx);
free (sapi_ctx);
tss2_tcti_finalize (tcti_ctx);
free (tcti_ctx);

}

danglus commented 7 years ago

let's see, Here is the original file: pcr_read.c.txt

Two questions: 1) Have you run'make install' in the TPM2.0-TSS directory? 2) Have you used the gcc flags that I've mentioned?

Thanks, Dan

Scrappy20907 commented 7 years ago

I have run "make install" in the TPM2.0-TSS directory. If i had moved the TPM2.0-TSS directory after running "make install" would that mess things up? And I thought if I had those libraries in my /usr/include directory I didn't need to use those flags. Because they would be included by just using #include in the code. But there is a high chance I don't know what I'm talking about :P. I will try again with the flags.

-Andrew

Scrappy20907 commented 7 years ago

oh okay, the flags do something different than I thought. I was able to compile the code with no errors. But now I get "Failed to initialize device TCTI context: 0xa000a". selection_004

danglus commented 7 years ago

"sudo ./pcr_read" should do the trick...

Scrappy20907 commented 7 years ago

... face palm Okay, its all working now lol. Now that I have something working I can read through the code and try to understand how it all works more easily. Thank you very much, you have been very helpful. -Andrew