#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>

#include <tc/tc_api.h>
#include <tc/tc_type.h>
#include <tc/tc_errcode.h>

void _tc_print_format_binary(const unsigned char* in, const unsigned int len) 
{
    int i=0;
    printf("Size=%d\n", len);
    for(; i<len; i++) {
        printf("%02x", in[i]);
        if(0 == (i+1)%4) printf(" ");
        if(0 == (i+1)%32) printf("\n");
    }
    if(0 != (i+1)%32) printf("\n");
}

int main()
{
    TC_RC rc;

    TC_HANDLE tc_handle = 0;
    uint32_t  primary_index;
    uint32_t  key_index;
    uint32_t  persist_index = 0x81000000;

    TC_BUFFER bfPlainText, bfEncryptText, bfDecryptText;

    bfPlainText.buffer = (unsigned char *)malloc(3);
    memcpy(bfPlainText.buffer, "abc", 3);
    bfPlainText.size = 3;

    rc = TC_Start("tabrmd",
                  &tc_handle);
    if (rc != TC_SUCCESS) {
        printf("Failed to start TC device\n");
        goto end;
    }

    rc = TC_CreatePrimary(tc_handle,
                          TC_SHA256,
                          TC_TPM2_RH_ENDORSEMENT,
                          NULL,
                          TC_RSA,
                          NULL,
                          &primary_index);
    if (rc != TC_SUCCESS) {
        printf("Failed to createPrimary\n");
        goto end;
    }

    rc = TC_Create(tc_handle,
                   TC_SHA256,
                   primary_index,
                   NULL,
                   TC_SYMMETRIC,
                   NULL,
                   &key_index);
    if (rc != TC_SUCCESS) {
        printf("Failed to create key\n");
        goto end;
    }

    rc = TC_Load(tc_handle,
                 key_index,
                 NULL);
    if (rc != TC_SUCCESS) {
        printf("Failed to load key\n");
        goto end;
    }

    rc = TC_EvictControl(tc_handle,
                         true,
                         persist_index,
                         key_index,
                         TC_TPM2_RH_OWNER,
                         NULL);
    if (rc != TC_SUCCESS) {
        printf("Failed to enable evict control key\n");
        goto end;
    }

    rc = TC_Encrypt(tc_handle,
                    persist_index,
                    NULL,
                    TC_SYMMETRIC,
                    &bfPlainText,
                    &bfEncryptText);
    if (rc != TC_SUCCESS) {
        printf("Failed to encrypt msg\n");
        goto end;
    }
    _tc_print_format_binary(bfEncryptText.buffer, bfEncryptText.size);

    rc = TC_Decrypt(tc_handle,
                    persist_index,
                    NULL,
                    TC_SYMMETRIC,
                    &bfEncryptText,
                    &bfDecryptText);
    if (rc != TC_SUCCESS) {
        printf("Failed to Decrypt encrypt data\n");
        goto end;
    }
    _tc_print_format_binary(bfDecryptText.buffer, bfDecryptText.size);

    rc = TC_EvictControl(tc_handle,
                         false,
                         persist_index,
                         key_index,
                         TC_TPM2_RH_OWNER,
                         NULL);
    if (rc != TC_SUCCESS) {
        printf("Failed to disable evict control key\n");
        goto end;
    }

end:
    free(bfPlainText.buffer);
    free(bfEncryptText.buffer);
    rc = TC_End(&tc_handle);
    if (rc != TC_SUCCESS) {
        printf("Failed to stop TC device\n");
    } 
}