From ef4b305eb1e7b025b58c85402b21f39975513a78 Mon Sep 17 00:00:00 2001 From: Michael Preisach Date: Thu, 19 Nov 2020 16:42:49 +0000 Subject: [PATCH] member_tpm updated to recent protocol version --- CMakeLists.txt | 23 ++- create_tpm_key | Bin 0 -> 22040 bytes create_tpm_key-util.c | 402 +++++++++++++++++++++++++++++++++++++++++ daa-test-tpm.c | 351 +++++++++++++++++++++++++++++++++++- daa-test-tpm.h | 2 + ecdaa_issuer | Bin 22984 -> 22992 bytes ecdaa_member | Bin 36104 -> 36112 bytes ecdaa_member_tpm | Bin 0 -> 36400 bytes ecdaa_test | Bin 31800 -> 31880 bytes ecdaa_test_tpm | Bin 0 -> 27168 bytes ecdaa_verifier | Bin 26976 -> 26984 bytes member-tpm.c | 410 +++++++++++++++++++++++++----------------- member-tpm.h | 12 +- 13 files changed, 1029 insertions(+), 171 deletions(-) create mode 100755 create_tpm_key create mode 100644 create_tpm_key-util.c create mode 100755 ecdaa_member_tpm create mode 100755 ecdaa_test_tpm diff --git a/CMakeLists.txt b/CMakeLists.txt index 604297d..c07d468 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,6 +23,8 @@ target_include_directories(ecdaa_member_tpm PUBLIC ) target_link_libraries(ecdaa_member_tpm /usr/lib/x86_64-linux-gnu/libecdaa.so) target_link_libraries(ecdaa_member_tpm /usr/lib/x86_64-linux-gnu/libecdaa-tpm.so) +target_link_libraries(ecdaa_member_tpm /usr/lib/x86_64-linux-gnu/libtss2-tcti-device.so) +target_link_libraries(ecdaa_member_tpm /usr/lib/x86_64-linux-gnu/libtss2-sys.so) add_executable(ecdaa_verifier verifier.c common.h common.c server.h server.c client.h client.c) target_include_directories(ecdaa_verifier PUBLIC @@ -30,9 +32,26 @@ target_include_directories(ecdaa_verifier PUBLIC ) target_link_libraries(ecdaa_verifier /usr/lib/x86_64-linux-gnu/libecdaa.so) -add_executable(ecdaa_test daa-test.c common.h common.c client.h client.c server.h server.c) +add_executable(ecdaa_test daa-test.c daa-test.h common.h common.c client.h client.c server.h server.c) target_include_directories(ecdaa_test PUBLIC ${ECDAA_AMCL} ) target_link_libraries(ecdaa_test /usr/lib/x86_64-linux-gnu/libecdaa.so) -target_link_libraries(ecdaa_test /usr/lib/x86_64-linux-gnu/libecdaa-tpm.so) + +add_executable(ecdaa_test_tpm daa-test-tpm.c daa-test-tpm.h common.h common.c client.h client.c server.h server.c) +target_include_directories(ecdaa_test_tpm PUBLIC + ${ECDAA_AMCL} + ) +target_link_libraries(ecdaa_test_tpm /usr/lib/x86_64-linux-gnu/libecdaa.so) +target_link_libraries(ecdaa_test_tpm /usr/lib/x86_64-linux-gnu/libecdaa-tpm.so) +target_link_libraries(ecdaa_test_tpm /usr/lib/x86_64-linux-gnu/libtss2-tcti-device.so) +target_link_libraries(ecdaa_test_tpm /usr/lib/x86_64-linux-gnu/libtss2-sys.so) + +add_executable(create_tpm_key create_tpm_key-util.c) +target_include_directories(create_tpm_key PUBLIC + ${ECDAA_AMCL} + ) +target_link_libraries(create_tpm_key /usr/lib/x86_64-linux-gnu/libecdaa.so) +target_link_libraries(create_tpm_key /usr/lib/x86_64-linux-gnu/libecdaa-tpm.so) +target_link_libraries(create_tpm_key /usr/lib/x86_64-linux-gnu/libtss2-tcti-device.so) +target_link_libraries(create_tpm_key /usr/lib/x86_64-linux-gnu/libtss2-sys.so) diff --git a/create_tpm_key b/create_tpm_key new file mode 100755 index 0000000000000000000000000000000000000000..bf6d1c82d3f10bea8af110e58de482497100defb GIT binary patch literal 22040 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 \n", argv[0]); + exit(1); + } + + pub_key_filename = argv[1]; + handle_filename = argv[2]; + printf("Saving public key to %s and handle to %s\n", pub_key_filename, handle_filename); +} + +struct test_context { + TSS2_SYS_CONTEXT *sapi_ctx; + TPM2_HANDLE primary_key_handle; + TPM2_HANDLE signing_key_handle; + TPM2_HANDLE persistent_key_handle; + TPM2B_PUBLIC out_public; + TPM2B_PRIVATE out_private; + unsigned char tcti_buffer[256]; + unsigned char sapi_buffer[4200]; + +}; + +static void initialize(struct test_context *ctx); +static void cleanup(struct test_context *ctx); + +static void create_key(const char* pub_key_filename, const char* handle_filename); +static int clear(struct test_context *ctx); +static int create_primary(struct test_context *ctx); +static int create(struct test_context *ctx); +static int load(struct test_context *ctx); +static int save_public_key_info(const struct test_context* ctx, const char* pub_key_filename, const char* handle_filename); +static int evict_control(struct test_context *ctx); + +int main(int argc, char *argv[]) +{ + // Included in the utils header, but we don't need them. +// (void)tpm_initialize; +// (void)tpm_cleanup; + +// parse_cmd_args(argc, argv); + + printf("Saving public key to %s and handle to %s\n", pub_key_filename, handle_filename); + create_key(pub_key_filename, handle_filename); +} + +void initialize(struct test_context *ctx) +{ + const char *device_conf = "/dev/tpm0"; + + int init_ret; + + memset(ctx->tcti_buffer, 0, sizeof(ctx->tcti_buffer)); + memset(ctx->sapi_buffer, 0, sizeof(ctx->sapi_buffer)); + + TSS2_TCTI_CONTEXT *tcti_ctx = (TSS2_TCTI_CONTEXT*)ctx->tcti_buffer; + + size_t size; + init_ret = Tss2_Tcti_Device_Init(NULL, &size, device_conf); + if (TSS2_RC_SUCCESS != init_ret) { + printf("Failed to get allocation size for tcti context\n"); + exit(1); + } + if (size > sizeof(ctx->tcti_buffer)) { + printf("Error: device TCTI context size larger than pre-allocated buffer\n"); + exit(1); + } + init_ret = Tss2_Tcti_Device_Init(tcti_ctx, &size, device_conf); + if (TSS2_RC_SUCCESS != init_ret) { + printf("Error: Unable to initialize device TCTI context\n"); + exit(1); + } + + ctx->sapi_ctx = (TSS2_SYS_CONTEXT*)ctx->sapi_buffer; + size_t sapi_ctx_size = Tss2_Sys_GetContextSize(0); + + TSS2_ABI_VERSION abi_version = TSS2_ABI_VERSION_CURRENT; + init_ret = Tss2_Sys_Initialize(ctx->sapi_ctx, + sapi_ctx_size, + tcti_ctx, + &abi_version); + + ctx->out_public.size = 0; + ctx->out_private.size = 0; +} + +void cleanup(struct test_context *ctx) +{ + TSS2_TCTI_CONTEXT *tcti_context = NULL; + TSS2_RC rc; + + if (ctx->sapi_ctx != NULL) { + rc = Tss2_Sys_GetTctiContext(ctx->sapi_ctx, &tcti_context); + + Tss2_Tcti_Finalize(tcti_context); + + Tss2_Sys_Finalize(ctx->sapi_ctx); + } +} + +void create_key(const char* pub_key_filename, const char* handle_filename) +{ + struct test_context ctx; + initialize(&ctx); + + int ret = 0; + +// ret = clear(&ctx); +// if(ret != TSS2_RC_SUCCESS) { +// printf("TPM Clear failed: %x\n",ret); +// } + + ret = create_primary(&ctx); + if(ret != TSS2_RC_SUCCESS) { + printf("TPM Create Primary failed: %x\n",ret); + } + + ret = create(&ctx); + if(ret != TSS2_RC_SUCCESS) { + printf("TPM Create failed: %x\n",ret); + } + + ret = load(&ctx); + if(ret != TSS2_RC_SUCCESS) { + printf("TPM Load failed: %x\n",ret); + } + + ret = evict_control(&ctx); + if(ret != TSS2_RC_SUCCESS) { + printf("TPM Evict Control failed: %x\n",ret); + } + + ret = save_public_key_info(&ctx, pub_key_filename, handle_filename); + if(ret != TSS2_RC_SUCCESS) { + printf("Save Public Key Info failed: %x\n",ret); + } + + cleanup(&ctx); +} + +int save_public_key_info(const struct test_context *ctx, const char* pub_key_filename, const char* handle_filename) +{ + int write_ret = 0; + + FILE *pub_key_file_ptr = fopen(pub_key_filename, "w"); + if (NULL == pub_key_file_ptr) + return -1; + do { + if (fprintf(pub_key_file_ptr, "%02X", 4) != 2) + break; + + for (unsigned i=0; i < ctx->out_public.publicArea.unique.ecc.x.size; i++) { + if (fprintf(pub_key_file_ptr, "%02X", ctx->out_public.publicArea.unique.ecc.x.buffer[i]) != 2) { + write_ret = -1; + break; + } + } + if (0 != write_ret) + break; + + for (unsigned i=0; i < ctx->out_public.publicArea.unique.ecc.y.size; i++) { + if (fprintf(pub_key_file_ptr, "%02X", ctx->out_public.publicArea.unique.ecc.y.buffer[i]) != 2) { + write_ret = -1; + break; + } + } + if (0 != write_ret) + break; + } while(0); + (void)fclose(pub_key_file_ptr); + + (void)handle_filename; + FILE *handle_file_ptr = fopen(handle_filename, "w"); + if (NULL == handle_file_ptr) + return -1; + write_ret = 0; + do { + for (int i=(sizeof(ctx->persistent_key_handle)-1); i >= 0; i--) { + if (fprintf(handle_file_ptr, "%02X", (ctx->persistent_key_handle >> i*8) & 0xFF) != 2) { + write_ret = -1; + break; + } + } + if (0 != write_ret) + break; + } while(0); + (void)fclose(handle_file_ptr); + + return write_ret; +} + +int clear(struct test_context *ctx) +{ + TPMI_RH_CLEAR auth_handle = TPM2_RH_LOCKOUT; + + TSS2L_SYS_AUTH_COMMAND sessionsData = {}; + sessionsData.auths[0].sessionHandle = TPM2_RS_PW; + sessionsData.auths[0].sessionAttributes = empty_session_attributes; + sessionsData.count = 1; + + TSS2L_SYS_AUTH_RESPONSE sessionsDataOut = {}; + sessionsDataOut.count = 1; + + TSS2_RC ret = Tss2_Sys_Clear(ctx->sapi_ctx, + auth_handle, + &sessionsData, + &sessionsDataOut); + + printf("Clear ret=%#X\n", ret); + + return ret; +} + +int create_primary(struct test_context *ctx) +{ + TPMI_RH_HIERARCHY hierarchy = TPM2_RH_ENDORSEMENT; + + TSS2L_SYS_AUTH_COMMAND sessionsData = {}; + sessionsData.auths[0].sessionHandle = TPM2_RS_PW; + sessionsData.auths[0].sessionAttributes = empty_session_attributes; + sessionsData.count = 1; + + TSS2L_SYS_AUTH_RESPONSE sessionsDataOut = {}; + sessionsDataOut.count = 1; + + TPM2B_SENSITIVE_CREATE inSensitive = {}; + + TPM2B_PUBLIC in_public = {}; + in_public.publicArea.type = TPM2_ALG_ECC; + in_public.publicArea.nameAlg = TPM2_ALG_SHA256; + in_public.publicArea.objectAttributes = TPMA_OBJECT_FIXEDTPM | + TPMA_OBJECT_FIXEDPARENT | + TPMA_OBJECT_SENSITIVEDATAORIGIN | + TPMA_OBJECT_USERWITHAUTH | + TPMA_OBJECT_DECRYPT | + TPMA_OBJECT_RESTRICTED; + in_public.publicArea.parameters.eccDetail.symmetric.algorithm = TPM2_ALG_AES; + in_public.publicArea.parameters.eccDetail.symmetric.keyBits.aes = 128; + in_public.publicArea.parameters.eccDetail.symmetric.mode.sym = TPM2_ALG_CFB; + in_public.publicArea.parameters.eccDetail.scheme.scheme = TPM2_ALG_NULL; + in_public.publicArea.parameters.eccDetail.curveID = TPM2_ECC_NIST_P256; + in_public.publicArea.parameters.eccDetail.kdf.scheme = TPM2_ALG_NULL; + + TPM2B_DATA outsideInfo = {}; + + TPML_PCR_SELECTION creationPCR = {}; + + TPM2B_CREATION_DATA creationData = {}; + TPM2B_DIGEST creationHash = {}; + TPMT_TK_CREATION creationTicket = {}; + + TPM2B_NAME name = {}; + + TPM2B_PUBLIC public_key = {}; + + TSS2_RC ret = Tss2_Sys_CreatePrimary(ctx->sapi_ctx, + hierarchy, + &sessionsData, + &inSensitive, + &in_public, + &outsideInfo, + &creationPCR, + &ctx->primary_key_handle, + &public_key, + &creationData, + &creationHash, + &creationTicket, + &name, + &sessionsDataOut); + + printf("CreatePrimary ret=%#X\n", ret); + + return ret; +} + +int create(struct test_context *ctx) +{ + TSS2L_SYS_AUTH_COMMAND sessionsData = {}; + sessionsData.auths[0].sessionHandle = TPM2_RS_PW; + sessionsData.auths[0].sessionAttributes = empty_session_attributes; + sessionsData.count = 1; + + TSS2L_SYS_AUTH_RESPONSE sessionsDataOut = {}; + sessionsDataOut.count = 1; + + TPM2B_SENSITIVE_CREATE inSensitive = {}; + + TPM2B_PUBLIC in_public = {}; + in_public.publicArea.type = TPM2_ALG_ECC; + in_public.publicArea.nameAlg = TPM2_ALG_SHA256; + in_public.publicArea.objectAttributes = TPMA_OBJECT_FIXEDTPM | + TPMA_OBJECT_FIXEDPARENT | + TPMA_OBJECT_SENSITIVEDATAORIGIN | + TPMA_OBJECT_USERWITHAUTH | + TPMA_OBJECT_SIGN_ENCRYPT; + in_public.publicArea.parameters.eccDetail.symmetric.algorithm = TPM2_ALG_NULL; + in_public.publicArea.parameters.eccDetail.scheme.scheme = TPM2_ALG_ECDAA; + in_public.publicArea.parameters.eccDetail.scheme.details.ecdaa.hashAlg = TPM2_ALG_SHA256; + in_public.publicArea.parameters.eccDetail.scheme.details.ecdaa.count = 1; + in_public.publicArea.parameters.eccDetail.curveID = TPM2_ECC_BN_P256; + in_public.publicArea.parameters.eccDetail.kdf.scheme = TPM2_ALG_NULL; + + TPM2B_DATA outsideInfo = {}; + + TPML_PCR_SELECTION creationPCR = {}; + + TPM2B_CREATION_DATA creationData = {}; + TPM2B_DIGEST creationHash = {}; + TPMT_TK_CREATION creationTicket = {}; + + TSS2_RC ret = Tss2_Sys_Create(ctx->sapi_ctx, + ctx->primary_key_handle, + &sessionsData, + &inSensitive, + &in_public, + &outsideInfo, + &creationPCR, + &ctx->out_private, + &ctx->out_public, + &creationData, + &creationHash, + &creationTicket, + &sessionsDataOut); + + printf("Create ret=%#X\n", ret); + + return ret; +} + +int load(struct test_context *ctx) +{ + TSS2L_SYS_AUTH_COMMAND sessionsData = {}; + sessionsData.auths[0].sessionHandle = TPM2_RS_PW; + sessionsData.auths[0].sessionAttributes = empty_session_attributes; + sessionsData.count = 1; + + TSS2L_SYS_AUTH_RESPONSE sessionsDataOut = {}; + sessionsDataOut.count = 1; + + TPM2B_NAME name = {}; + + int ret = Tss2_Sys_Load(ctx->sapi_ctx, + ctx->primary_key_handle, + &sessionsData, + &ctx->out_private, + &ctx->out_public, + &ctx->signing_key_handle, + &name, + &sessionsDataOut); + + printf("Load ret=%#X\n", ret); + + return ret; +} + +int evict_control(struct test_context *ctx) +{ + TSS2L_SYS_AUTH_COMMAND sessionsData = {}; + sessionsData.auths[0].sessionHandle = TPM2_RS_PW; + sessionsData.auths[0].sessionAttributes = empty_session_attributes; + sessionsData.count = 1; + + TSS2L_SYS_AUTH_RESPONSE sessionsDataOut = {}; + sessionsDataOut.count = 1; + + ctx->persistent_key_handle = 0x81010000; + + TSS2_RC ret = Tss2_Sys_EvictControl(ctx->sapi_ctx, + TPM2_RH_OWNER, + ctx->signing_key_handle, + &sessionsData, + ctx->persistent_key_handle, + &sessionsDataOut); + + printf("EvictControl ret=%#X\n", ret); + + return ret; +} diff --git a/daa-test-tpm.c b/daa-test-tpm.c index 2ed9e77..5dcfc9b 100644 --- a/daa-test-tpm.c +++ b/daa-test-tpm.c @@ -1,8 +1,30 @@ #include "daa-test-tpm.h" +struct test_context { + TSS2_SYS_CONTEXT *sapi_ctx; + TPM2_HANDLE primary_key_handle; + TPM2_HANDLE signing_key_handle; + TPM2_HANDLE persistent_key_handle; + TPM2B_PUBLIC out_public; + TPM2B_PRIVATE out_private; + unsigned char tcti_buffer[256]; + unsigned char sapi_buffer[4200]; +}test_context; + +static TPMA_SESSION empty_session_attributes = {0}; + int test1(); -int test2(); -int test3(); +//int test2(); +//int test3(); +void initialize(struct test_context *ctx); +void create_key(const char* pub_key_filename, const char* handle_filename); +int clear(struct test_context *ctx); +int create_primary(struct test_context *ctx); +int create(struct test_context *ctx); +int load(struct test_context *ctx); +int save_public_key_info(const struct test_context* ctx, const char* pub_key_filename, const char* handle_filename); +int evict_control(struct test_context *ctx); +void cleanup(struct test_context *ctx); int main(int argc, char **argv) { if(0 != test1()) { @@ -10,11 +32,336 @@ int main(int argc, char **argv) { return 0; } else { printf("test1 succeeded\n"); + } } int test1() { const char *pub_key_filename = "pub_key.txt"; const char *handle_filename = "handle.txt"; + struct test_context ctx; + initialize(&ctx); + + int ret = 0; + ret = clear(&ctx); + if(ret != TSS2_RC_SUCCESS) { + printf("TPM Clear failed: %x\n",ret); + return ret; + } + ret = create_primary(&ctx); + if(ret != TSS2_RC_SUCCESS) { + printf("TPM Create Primary failed: %x\n",ret); + return ret; + } + ret = create(&ctx); + if(ret != TSS2_RC_SUCCESS) { + printf("TPM Create failed: %x\n",ret); + return ret; + } + ret = evict_control(&ctx); + if(ret != TSS2_RC_SUCCESS) { + printf("TPM Evict Control failed: %x\n",ret); + return ret; + } + ret = save_public_key_info(&ctx, pub_key_filename, handle_filename); + if(ret != TSS2_RC_SUCCESS) { + printf("Save Public Key Info failed: %x\n",ret); + return ret; + } + cleanup(&ctx); return 0; } + +void initialize(struct test_context *ctx) +{ + const char *device_conf = "/dev/tpm0"; + + int init_ret; + + memset(ctx->tcti_buffer, 0, sizeof(ctx->tcti_buffer)); + memset(ctx->sapi_buffer, 0, sizeof(ctx->sapi_buffer)); + + TSS2_TCTI_CONTEXT *tcti_ctx = (TSS2_TCTI_CONTEXT*)ctx->tcti_buffer; + size_t size; + init_ret = Tss2_Tcti_Device_Init(NULL, &size, device_conf); + if (TSS2_RC_SUCCESS != init_ret) { + printf("Failed to get allocation size for tcti context\n"); + exit(1); + } + if (size > sizeof(ctx->tcti_buffer)) { + printf("Error: device TCTI context size larger than pre-allocated buffer\n"); + exit(1); + } + init_ret = Tss2_Tcti_Device_Init(tcti_ctx, &size, device_conf); + if (TSS2_RC_SUCCESS != init_ret) { + printf("Error: Unable to initialize device TCTI context\n"); + exit(1); + } + ctx->sapi_ctx = (TSS2_SYS_CONTEXT*)ctx->sapi_buffer; + size_t sapi_ctx_size = Tss2_Sys_GetContextSize(0); + + TSS2_ABI_VERSION abi_version = TSS2_ABI_VERSION_CURRENT; + init_ret = Tss2_Sys_Initialize(ctx->sapi_ctx, + sapi_ctx_size, + tcti_ctx, + &abi_version); + + ctx->out_public.size = 0; + ctx->out_private.size = 0; +} + +int clear(struct test_context *ctx) +{ + TPMI_RH_CLEAR auth_handle = TPM2_RH_LOCKOUT; + + TSS2L_SYS_AUTH_COMMAND sessionsData = {}; + sessionsData.auths[0].sessionHandle = TPM2_RS_PW; + sessionsData.auths[0].sessionAttributes = empty_session_attributes; + sessionsData.count = 1; + + TSS2L_SYS_AUTH_RESPONSE sessionsDataOut = {}; + sessionsDataOut.count = 1; + + TSS2_RC ret = Tss2_Sys_Clear(ctx->sapi_ctx, + auth_handle, + &sessionsData, + &sessionsDataOut); + + printf("Clear ret=%#X\n", ret); + + return ret; +} + +int create_primary(struct test_context *ctx) +{ + TPMI_RH_HIERARCHY hierarchy = TPM2_RH_ENDORSEMENT; + + TSS2L_SYS_AUTH_COMMAND sessionsData = {}; + sessionsData.auths[0].sessionHandle = TPM2_RS_PW; + sessionsData.auths[0].sessionAttributes = empty_session_attributes; + sessionsData.count = 1; + + TSS2L_SYS_AUTH_RESPONSE sessionsDataOut = {}; + sessionsDataOut.count = 1; + + TPM2B_SENSITIVE_CREATE inSensitive = {}; + + TPM2B_PUBLIC in_public = {}; + in_public.publicArea.type = TPM2_ALG_ECC; + in_public.publicArea.nameAlg = TPM2_ALG_SHA256; + + //default attributes in tpm2-tools https://github.com/tpm2-software/tpm2-tools/blob/master/tools/tpm2_createprimary.c + in_public.publicArea.objectAttributes = TPMA_OBJECT_FIXEDTPM | + TPMA_OBJECT_FIXEDPARENT | + TPMA_OBJECT_SENSITIVEDATAORIGIN | + TPMA_OBJECT_USERWITHAUTH | + TPMA_OBJECT_DECRYPT | + TPMA_OBJECT_RESTRICTED; + in_public.publicArea.parameters.eccDetail.symmetric.algorithm = TPM2_ALG_AES; + in_public.publicArea.parameters.eccDetail.symmetric.keyBits.aes = 128; + in_public.publicArea.parameters.eccDetail.symmetric.mode.sym = TPM2_ALG_CFB; + in_public.publicArea.parameters.eccDetail.scheme.scheme = TPM2_ALG_NULL; + in_public.publicArea.parameters.eccDetail.curveID = TPM2_ECC_NIST_P256; + in_public.publicArea.parameters.eccDetail.kdf.scheme = TPM2_ALG_NULL; + + TPM2B_DATA outsideInfo = {}; + + TPML_PCR_SELECTION creationPCR = {}; + + TPM2B_CREATION_DATA creationData = {}; + TPM2B_DIGEST creationHash = {}; + TPMT_TK_CREATION creationTicket = {}; + + TPM2B_NAME name = {}; + + TPM2B_PUBLIC public_key = {}; + + TSS2_RC ret = Tss2_Sys_CreatePrimary(ctx->sapi_ctx, + hierarchy, + &sessionsData, + &inSensitive, + &in_public, + &outsideInfo, + &creationPCR, + &ctx->primary_key_handle, + &public_key, + &creationData, + &creationHash, + &creationTicket, + &name, + &sessionsDataOut); + + printf("CreatePrimary ret=%#X\n", ret); + + return ret; +} + +int create(struct test_context *ctx) +{ + TSS2L_SYS_AUTH_COMMAND sessionsData = {}; + sessionsData.auths[0].sessionHandle = TPM2_RS_PW; + sessionsData.auths[0].sessionAttributes = empty_session_attributes; + sessionsData.count = 1; + + TSS2L_SYS_AUTH_RESPONSE sessionsDataOut = {}; + sessionsDataOut.count = 1; + + TPM2B_SENSITIVE_CREATE inSensitive = {}; + + TPM2B_PUBLIC in_public = {}; + in_public.publicArea.type = TPM2_ALG_ECC; + in_public.publicArea.nameAlg = TPM2_ALG_SHA256; + in_public.publicArea.objectAttributes = TPMA_OBJECT_FIXEDTPM | + TPMA_OBJECT_FIXEDPARENT | + TPMA_OBJECT_SENSITIVEDATAORIGIN | + TPMA_OBJECT_USERWITHAUTH | + TPMA_OBJECT_SIGN_ENCRYPT; + in_public.publicArea.parameters.eccDetail.symmetric.algorithm = TPM2_ALG_NULL; + in_public.publicArea.parameters.eccDetail.scheme.scheme = TPM2_ALG_ECDAA; + in_public.publicArea.parameters.eccDetail.scheme.details.ecdaa.hashAlg = TPM2_ALG_SHA256; + in_public.publicArea.parameters.eccDetail.scheme.details.ecdaa.count = 1; + in_public.publicArea.parameters.eccDetail.curveID = TPM2_ECC_BN_P256; + in_public.publicArea.parameters.eccDetail.kdf.scheme = TPM2_ALG_NULL; + + TPM2B_DATA outsideInfo = {}; + + TPML_PCR_SELECTION creationPCR = {}; + + TPM2B_CREATION_DATA creationData = {}; + TPM2B_DIGEST creationHash = {}; + TPMT_TK_CREATION creationTicket = {}; + + TSS2_RC ret = Tss2_Sys_Create(ctx->sapi_ctx, + ctx->primary_key_handle, + &sessionsData, + &inSensitive, + &in_public, + &outsideInfo, + &creationPCR, + &ctx->out_private, + &ctx->out_public, + &creationData, + &creationHash, + &creationTicket, + &sessionsDataOut); + + printf("Create ret=%#X\n", ret); + + return ret; +} + +int load(struct test_context *ctx) +{ + TSS2L_SYS_AUTH_COMMAND sessionsData = {}; + sessionsData.auths[0].sessionHandle = TPM2_RS_PW; + sessionsData.auths[0].sessionAttributes = empty_session_attributes; + sessionsData.count = 1; + + TSS2L_SYS_AUTH_RESPONSE sessionsDataOut = {}; + sessionsDataOut.count = 1; + + TPM2B_NAME name = {}; + + int ret = Tss2_Sys_Load(ctx->sapi_ctx, + ctx->primary_key_handle, + &sessionsData, + &ctx->out_private, + &ctx->out_public, + &ctx->signing_key_handle, + &name, + &sessionsDataOut); + + printf("Load ret=%#X\n", ret); + + return ret; +} + +int evict_control(struct test_context *ctx) +{ + TSS2L_SYS_AUTH_COMMAND sessionsData = {}; + sessionsData.auths[0].sessionHandle = TPM2_RS_PW; + sessionsData.auths[0].sessionAttributes = empty_session_attributes; + sessionsData.count = 1; + + TSS2L_SYS_AUTH_RESPONSE sessionsDataOut = {}; + sessionsDataOut.count = 1; + + ctx->persistent_key_handle = 0x81010000; + + TSS2_RC ret = Tss2_Sys_EvictControl(ctx->sapi_ctx, + TPM2_RH_OWNER, + ctx->signing_key_handle, + &sessionsData, + ctx->persistent_key_handle, + &sessionsDataOut); + + printf("EvictControl ret=%#X\n", ret); + + return ret; +} + +int save_public_key_info(const struct test_context *ctx, const char* pub_key_filename, const char* handle_filename) +{ + int write_ret = 0; + + FILE *pub_key_file_ptr = fopen(pub_key_filename, "w"); + if (NULL == pub_key_file_ptr) + return -1; + do { + if (fprintf(pub_key_file_ptr, "%02X", 4) != 2) + break; + + for (unsigned i=0; i < ctx->out_public.publicArea.unique.ecc.x.size; i++) { + if (fprintf(pub_key_file_ptr, "%02X", ctx->out_public.publicArea.unique.ecc.x.buffer[i]) != 2) { + write_ret = -1; + break; + } + } + if (0 != write_ret) + break; + + for (unsigned i=0; i < ctx->out_public.publicArea.unique.ecc.y.size; i++) { + if (fprintf(pub_key_file_ptr, "%02X", ctx->out_public.publicArea.unique.ecc.y.buffer[i]) != 2) { + write_ret = -1; + break; + } + } + if (0 != write_ret) + break; + } while(0); + (void)fclose(pub_key_file_ptr); + + (void)handle_filename; + FILE *handle_file_ptr = fopen(handle_filename, "w"); + if (NULL == handle_file_ptr) + return -1; + write_ret = 0; + do { + for (int i=(sizeof(ctx->persistent_key_handle)-1); i >= 0; i--) { + if (fprintf(handle_file_ptr, "%02X", (ctx->persistent_key_handle >> i*8) & 0xFF) != 2) { + write_ret = -1; + break; + } + } + if (0 != write_ret) + break; + } while(0); + (void)fclose(handle_file_ptr); + + return write_ret; +} + +void cleanup(struct test_context *ctx) +{ + TSS2_TCTI_CONTEXT *tcti_context = NULL; + TSS2_RC rc; + + if (ctx->sapi_ctx != NULL) { + rc = Tss2_Sys_GetTctiContext(ctx->sapi_ctx, &tcti_context); + + Tss2_Tcti_Finalize(tcti_context); + + Tss2_Sys_Finalize(ctx->sapi_ctx); + } +} + diff --git a/daa-test-tpm.h b/daa-test-tpm.h index 4e07370..d7477da 100644 --- a/daa-test-tpm.h +++ b/daa-test-tpm.h @@ -6,8 +6,10 @@ #include "client.h" #include "common.h" #include +#include #include #include #include #include +#endif diff --git a/ecdaa_issuer b/ecdaa_issuer index 7b8f186b4449584c159d5ddbf893b51bf09005b5..ac835e2a2c9935829d6450516d79b2d65fc52dd8 100755 GIT binary patch delta 103 zcmV-t0GR*CvjNbv0gxyG5V0vg0~C6Ji*^0Xl5C09B*J+BdkN-BRAsY#1Gqd6H+5ol zZgh1qeljpFFf@}qKq#|fK*0(EHZYP)7PC7`tqlPxlMzG{ll)jD0Z@}6Sw8{jlVMpu J0q~QdStk&eCL{m= delta 97 zcmV-n0G|KQvjNDn0gxyG2(c+Y0~AdXg88qr@fbd$oDj5|&D=i_F8H&21Gqd7Fm+;e zZgh1rDIhs6GcGWbu>v8pY(T#X0yR0aEla}<0VI?0ST_MklPOt00pOEqSw8{jlc`xJ DI_)Hs diff --git a/ecdaa_member b/ecdaa_member index 5e0d9039c3e7b309515d1288edd097d5d3772da6..5932b66caba99c284bfa6f8f3be1df8fad6c7654 100755 GIT binary patch delta 100 zcmeB}#WVqkG#CRmYT7f4@TR`3*lFXyQa_>n-qCYQH?CWdIel{t^NAcj^U|c!ypmGG zIwJ!;1Cz-<1sa=+3JQ6c%nT+Us1e)zyGECvQERehk2zz)v8pd~k0J0yR0a?R-NI0VI<#j5h&TlWB}Ulb~)0ldz090W6d0 Fj3+_LB?SNg diff --git a/ecdaa_member_tpm b/ecdaa_member_tpm new file mode 100755 index 0000000000000000000000000000000000000000..08cad58fd2320186eefec1a74adc128390b1e48b GIT binary patch literal 36400 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 delta 3926 zcmbtX4OA4@6`nWz?JCNG!h(p1g0KcfQ2rvQ2vY~66^;@Wv51P%NEDS#G|_Q4f8y~?bPdxat7;Vx(b(UnyWHXqyLY;9H@C*Lj(0gki zf4r$@hwx~`ryHgpeY|hy%FFw0o879yG+&2uoM;`i);1-ghp~E?9GMidOGman#g}AR zw0>HAmV|lQITC}`LwV#Z7Gb**>Bd+Xv_;)#2HPb=8Dj?^_qj76moW{BO;%#3g)6b; z5lZZ5kRIL5&clRpt^8fB&3F8(jJjcVIeeSAt+(@0Sj>UAVAV8)iqct8s&{I% zNMh!cH1;SM+zDkPT_E>8NS!!3a3j`0<@Z#`Qe#HoTDiAiK=g2UcVcv2HJZ)UB>|!} z_2h7Lakpf-lHn?y5$?2Iv$8?y6#AP&(62+kx!O34%0^2oo>Szx(8p9q^CLImkI|zh zZbhB)dA%>NSjjnlgUeHP^GOPOC~yg^o0RC+px~9nz6nNa;7yn{E+}OdAzVIhOlmgG zoj0gZX5Cm4@dg*~U6q$mBB5%*Cw?63fYkU!0S)LAO(%4&t?#52!f(K|@grXNkjk(Y z8C|};G{4o|Tb7}`QkJrKJPj-pmMH!eM9>x=^#yIGpeoQO%=0%=a(zpk9fqE4C`(9W ztDrJren9rq{_{cT|3eoXjTxbjqO=}#JxL{k<{P`9J0>{j-^fFYnlLlWbO`QJNA7gk zm6#pC(CS*0Jfn#8%5_*fb_5H7p-JP|IotH4$&4>Ahpox8*+w{*9L-*Up5&m?@^TD} zTC}+CpFSfV<%rT(qO_%1l#F&!%4rZSLW5|k=EbT{K2{&`e!D2y#YSh1gO`NvdZB}= zQZG13bk4x#)UZuT;DAwW4*l!y+`{s|z7_F$RCKLXhe`qN@Fp7HdLJ zCA>K`ggt`2Q!Cg>$exxJQqhjRZLTh*7u1fS2sWXi-rVsg86WV8)hAEGXnISc#bS2i zSjA=0Pb01LF8U;MHyTZUqmkPbh&(S6kD(m~rw#L3OuD8WV$vd_+mIUbq8Ek&X>21( zS_*I1gXQ8x?}#YeQHh6B-wtJIDW#{0UT86GX;BMfAhP8cRY}=(<*&et!gHU|U2%pW zxmu_*YN3uHPAQa9nwBc1SW4DB(z@y+55Z7B%0pD#^5 z5irjIm#0U2ts&jufWhg*BEP^`tAtPHsmodz12 zPH(BS`LnF4e~sk0v==j_3u!r-(!bK?rAa+GqIKNw(L8sS;TzG^t#O84w&e@^2Y}tT z?9W-1UZscdWUvFdq6S%}_g44kvh0m@=|LHevgiw0K7;lg{7_86`8AYzC|l3V@@ACx zn`L<~%51F1F_dK}TTq@x*@JQnR&+RiF#H8&3d(tSeoIgm;3X;Jx$)c0RY9D^xw8D7*eTsZzs!oM;&ydW~D z`Lrx6W^&J9n|Kb76`tJ zf;~%6vv)$=qUqXWs6N0_de~}wXEE56H-kmlYVwx3`Aje_HLfW!#u-K?kDoYx0vzVU zYpBa^XwN z1NIljuz}E6n9sIA>+X08Zjxv*-*ITj1aFZ~??-2H;y#II_KZBA3kE@GziSisj^ z&wizh$CS~jj6raCrJjv}HXKuF49fLT8KS1DkzZmq^sFMUy9K?lwP46h?w2l{e~Rj- zKBVU(wEOZwoTgZv_l^}V{42?-ML9%N>tNj~J^pJ$Yd>^h4rQpALRYXB-g#LM_Emwg zp)SP82-T&uDykt^OWOCOB-Nhjij08Rm-Sd5jAsj>0LPywdNGZe`(05mR)q)RoSu(d z_J6q8l!iq65tm)_yaMBtCPTGO;k>Afo)ETL9~6vDPgT%;s|t~jy;{%G2*ZkLbl-+Z zXv`nVenV4mtWM|SlXn*d*d`bCxWUf`c)~8Nmu*gQ78_i+Y44rQzY7eYdXGg%WIT6cPusQNS#})*R diff --git a/ecdaa_test_tpm b/ecdaa_test_tpm new file mode 100755 index 0000000000000000000000000000000000000000..7a566a72c3ff06f4cedd1a266376b501c53429ae GIT binary patch literal 27168 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 literal 0 HcmV?d00001 diff --git a/ecdaa_verifier b/ecdaa_verifier index 491cb2cbed9aee48bfef15f646b761e5e02cf987..672d031a0838c6e9dec42cd001234b71eabd04a1 100755 GIT binary patch delta 107 zcmV-x0F?jW(gEnw0gxyGsIe(O0~8#-dNAm9Q&v7x{V74KB#vTNh;p-h1F%dLH+5ol zZgh1qeljpFFf=J3IW99UFq5$YBePsk*9rnQFq05l7PCuRH4OnOlYwYA0Z5a%Xg>k? Nllf>r0gID4X(x3cCV>C| delta 100 zcmV-q0Gt2l(gEPo0gxyGps^`G0~A(_F%ehQWKNF0uQrfP}d3qH950ATT2ZAB$J6~HvvGC!Dv4L@RI>)KLLZ2 GL1`yWTq9io diff --git a/member-tpm.c b/member-tpm.c index d37cf87..0dd72e8 100644 --- a/member-tpm.c +++ b/member-tpm.c @@ -19,52 +19,147 @@ typedef struct member { uint8_t bsn[MAX_BSNSIZE]; size_t bsn_len; struct ecdaa_tpm_context ctx; + TPM2_HANDLE pk_handle; + unsigned char pk_in[ECP_FP256BN_LENGTH]; + unsigned char tcti_buffer[256]; } member_t; member_t member; +uint8_t msg[MAX_MSGSIZE]; +size_t msg_len; +const char *pub_key_filename = "pub_key.txt"; +const char *handle_filename = "handle.txt"; int init_tpm(); int free_tpm(); +static int read_public_key_from_files(uint8_t *public_key, TPM2_HANDLE *key_handle, const char *pub_key_filename, const char *handle_filename); int member_join(char *buffer); -int member_attest(char *buffer); +int member_verifymsg(char *buffer); int member_publish(char *buffer); -int member_getpublic(char *buffer); int member_joinappend(char *buffer); int member_joinfinish(char *buffer); -int main() { - - init_tpm(); - if (2 != server_start(&process_member, MEMBERPORT)) { - printf("server failed\n"); +int main(int argc, char *argv[]) { + char buffer[MAX_BUFSIZE]; + char *remote_ip = argv[2]; + int ret = 0; + TPM2_HANDLE sk_handle = 0; + + //strncpy(member.bsn, "mybasename", 10); + //member.bsn_len = strlen(member.bsn); + switch(argc) { + case 3: + if( 0 == strncasecmp("--join", argv[1], 6) || 0 == strncasecmp("-j", argv[1], 2)) { + if (0 != read_public_key_from_files(member.pk_in, &sk_handle, pub_key_filename, handle_filename)) { + printf("Error: error reading in public key files '%s' and '%s'\n", pub_key_filename, handle_filename); + return 1; + } + member.state = ON; + ret = client_connect(&member_join, remote_ip, ISSUERPORT); + if (0 >= ret || JOINED != member.state) { + printf("Join process failed!\n"); + return 1; + } else { + printf("Join process was successful\n"); + } + } else { + printf("2 arguments but not join\n"); + } + break; + case 4: + if( 0 == strncasecmp("--send", argv[1], 6) || 0 == strncasecmp("-s", argv[1], 2)) { + msg_len = ecdaa_read_from_file(msg, MAX_MSGSIZE, argv[3]); + if (msg_len < 0) { + printf("Could not open message file %s\n", argv[3]); + return 1; + } + if (0 != read_public_key_from_files(member.pk_in, &sk_handle, pub_key_filename, handle_filename)) { + printf("Error: error reading in public key files '%s' and '%s'\n", pub_key_filename, handle_filename); + return 1; + } + if (0 > ecdaa_read_from_file(member.nonce, NONCE_SIZE, member_nonce_file) || + 0 != ecdaa_member_public_key_FP256BN_deserialize_file(&member.mpk, member_public_key_file, member.nonce, NONCE_SIZE) || + 0 != ecdaa_credential_FP256BN_deserialize_file(&member.cred, member_credential_file)) { + printf("Could not import key files. importing from %s, %s or %s was not successful\n", + member_nonce_file, member_public_key_file, member_credential_file); + return 1; + } + member.state = JOINED; + ret = client_connect(&member_verifymsg, remote_ip, VERIFIERPORT); + if (0 >= ret || JOINED != member.state) { + printf("connection to verifier failed\n"); + } + } else { + printf("3 arguments but not send\n"); + } + break; + default: + printf("Usage: \n Join an issuer's group: %s --join \n", argv[0]); + printf("Send a signed message to the verifier: %s --send \n", argv[0]); + printf("Before sending a DAA-signed message, the member must join a DAA group\n"); + break; } - free_tpm(); return 0; } -int init_tpm() { - TSS2_TCTI_CONTEXT *tctiContext = NULL; - TPM2_HANDLE handle = 0; - const char* passwd = "1234"; - uint16_t passwdlen = strlen(passwd); - TSS2_RC retval = 0; - size_t bufsize = tss2_tcti_getsize_device(); - uint8_t tctiBuffer[bufsize]; - bzero(tctiBuffer, bufsize); - const char* devicePath = "/dev/tpm0"; - - tctiContext = tctiBuffer; - retval = tss2_tcti_init_device(devicePath, strlen(devicePath), tctiContext); - switch (retval & 0xFF) { - case TSS2_RC_SUCCESS: - printf("tcti context established\n"); - break; - default: - printf("tcti context failed\n"); - break; +//int init_tpm() { +// TSS2_TCTI_CONTEXT *tctiContext = NULL; +// member.pk_handle = 0x81010000; +// const char* passwd = NULL; +// uint16_t passwdlen = 0; +// TSS2_RC retval = 0; +// size_t bufsize = tss2_tcti_getsize_device(); +// uint8_t tctiBuffer[bufsize]; +// bzero(tctiBuffer, bufsize); +// const char* devicePath = "/dev/tpm0"; +// +// tctiContext = tctiBuffer; +// retval = tss2_tcti_init_device(devicePath, strlen(devicePath), tctiContext); +// switch (retval & 0xFF) { +// case TSS2_RC_SUCCESS: +// printf("tcti context established\n"); +// break; +// default: +// printf("tcti context failed\n"); +// break; +// } +// //initialize ecdaa tpm context +// if(0 != ecdaa_tpm_context_init(&member.ctx, handle, passwd, passwdlen, tctiContext)) { +// printf("\necdaa context failed\n"); +// return -1; +// } +// printf("\necdaa context initialized\n"); +// return 0; +//} + +int init_tpm() +{ + const char *device_conf = "/dev/tpm0"; + + int init_ret; + + memset(member.tcti_buffer, 0, sizeof(member.tcti_buffer)); + + TSS2_TCTI_CONTEXT *tcti_ctx = (TSS2_TCTI_CONTEXT*)member.tcti_buffer; + + size_t size; + init_ret = Tss2_Tcti_Device_Init(NULL, &size, device_conf); + if (TSS2_RC_SUCCESS != init_ret) { + printf("Failed to get allocation size for tcti context\n"); + return -1; + } + if (size > sizeof(member.tcti_buffer)) { + printf("Error: device TCTI context size larger than pre-allocated buffer\n"); + return -1; + } + init_ret = Tss2_Tcti_Device_Init(tcti_ctx, &size, device_conf); + if (TSS2_RC_SUCCESS != init_ret) { + printf("Error: Unable to initialize device TCTI context\n"); + return -1; } + //initialize ecdaa tpm context - if(0 != ecdaa_tpm_context_init(&member.ctx, handle, NULL, 0, tctiContext)) { + if(0 != ecdaa_tpm_context_init(&member.ctx, member.pk_handle, NULL, 0, tcti_ctx)) { printf("\necdaa context failed\n"); return -1; } @@ -77,108 +172,9 @@ int free_tpm() { return 0; } -int process_member(char *buffer) { - int ret = 0; - - bzero(member.bsn, MAX_BSNSIZE); - strncpy((char *) member.bsn, "Biometric Sensor", 16); - member.bsn_len = 16; - - printf("> MEMBER: %s\n", buffer); - - if (member.state == JOINED && 0 == strncasecmp("ATTEST", buffer, 6)) { - bzero(buffer, MAX_BUFSIZE); - strncpy(buffer, "ATTEST ", 7); - member_attest(buffer); - } else if (member.state == ON && 0 == strncasecmp("GETPUBLIC", buffer, 9)) { - bzero(buffer, MAX_BUFSIZE); - ret = client_connect(&member_getpublic, ISSUERIP, ISSUERPORT); - if (0 >= ret || RCVPUBLIC != member.state) { - printf("process_member: issuer connection failed\n"); - bzero(buffer, MAX_BUFSIZE); - strncpy(buffer, "ERR\n", 4); - } else { - bzero(buffer, MAX_BUFSIZE); - strncpy(buffer, "OK\n", 3); - } - ret = 0; - } else if (0 == strncasecmp("PUBLISH", buffer, 7)) { - bzero(buffer, MAX_BUFSIZE); - member_publish(buffer); - } else if (member.state == RCVPUBLIC && 0 == strncasecmp("JOIN", buffer, 4)) { - member.state = JOIN; - ret = client_connect(&member_join, ISSUERIP, ISSUERPORT); - if (0 >= ret || JOINED != member.state) { - printf("process_member: issuer connection failed\n"); - bzero(buffer, MAX_BUFSIZE); - strncpy(buffer, "ERR\n", 4); - } else { - bzero(buffer, MAX_BUFSIZE); - strncpy(buffer, "OK\n", 3); - } - ret = 0; - } else if (0 == strncasecmp("EXIT", buffer, 4)) { - bzero(buffer, MAX_BUFSIZE); - strncpy(buffer, "OK\n", 3); - ret = 1; - } else if (0 == strncasecmp("SHUTDOWN", buffer, 8)) { - bzero(buffer, MAX_BUFSIZE); - strncpy(buffer, "OK\n", 3); - ret = 2; - } else { - bzero(buffer, MAX_BUFSIZE); - strncpy(buffer, "ERR\n", 4); - ret = 0; - } - - printf("< MEMBER: %s\n", buffer); - return ret; -} - int member_join(char *buffer) { int ret = 0; - switch (member.state) { - case JOIN: - bzero(buffer, MAX_BUFSIZE); - strncpy(buffer, "JOIN\n", 5); - member.state = APPEND; - break; - case APPEND: - if (0 == strncasecmp("JOINSTART", buffer, 9)) { - printf("ISSUER > MEMBER: %s", buffer); - member_joinappend(buffer); - member.state = JOINPROCEED; - } else { - printf("member_join: did not get nonce from issuer\n"); - member.state = RCVPUBLIC; - ret = -1; - } - break; - case JOINPROCEED: - if (0 == strncasecmp("JOINPROCEED", buffer, 11)) { - printf("ISSUER > MEMBER: %s", buffer); - member_joinfinish(buffer); - member.state = JOINED; - ret = 1; - } else { - printf("member_getpublic: did not get credentials from issuer\n"); - member.state = RCVPUBLIC; - ret = -1; - } - break; - default: - ret = -1; - } - if (0 == ret) { - printf("ISSUER < MEMBER: %s", buffer); - } - return ret; -} - -int member_getpublic(char *buffer) { - int ret = 0; - switch (member.state) { case ON: bzero(buffer, MAX_BUFSIZE); @@ -190,7 +186,7 @@ int member_getpublic(char *buffer) { printf("ISSUER > MEMBER: %s", buffer); uint8_t binbuf[MAX_BUFSIZE]; char *current = &buffer[8]; - ecdaa_hextobin(current, binbuf, ECDAA_ISSUER_PUBLIC_KEY_FP256BN_LENGTH); + ecdaa_decode(current, binbuf, ECDAA_ISSUER_PUBLIC_KEY_FP256BN_LENGTH); ret = ecdaa_issuer_public_key_FP256BN_deserialize(&member.ipk, binbuf); if (-1 == ret) { printf("member_getpublic: issuer public key is malformed!\n"); @@ -199,8 +195,10 @@ int member_getpublic(char *buffer) { printf("member_getpublic: signature of issuer public key is invalid\n"); ret = -1; } else { - member.state = RCVPUBLIC; - ret = 1; + bzero(buffer, MAX_BUFSIZE); + strncpy(buffer, "JOIN\n", 5); + member.state = APPEND; + ret = 0; } } else { printf("member_getpublic: did not get public key from issuer\n"); @@ -208,11 +206,31 @@ int member_getpublic(char *buffer) { ret = -1; } break; + case APPEND: + if (0 == strncasecmp("JOINSTART", buffer, 9)) { + printf("ISSUER > MEMBER: %s", buffer); + member_joinappend(buffer); + member.state = JOINPROCEED; + } else { + printf("member_join: did not get nonce from issuer\n"); + member.state = RCVPUBLIC; + ret = -1; + } + break; + case JOINPROCEED: + if (0 == strncasecmp("JOINPROCEED", buffer, 11)) { + printf("ISSUER > MEMBER: %s", buffer); + member_joinfinish(buffer); + member.state = JOINED; + ret = 1; + } else { + printf("member_getpublic: did not get credentials from issuer\n"); + member.state = RCVPUBLIC; + ret = -1; + } + break; default: - printf("member_getpublic: did not get public key from issuer\n"); - member.state = ON; ret = -1; - break; } if (0 == ret) { printf("ISSUER < MEMBER: %s", buffer); @@ -220,39 +238,60 @@ int member_getpublic(char *buffer) { return ret; } -//"ATTEST" > "ATTEST " -int member_attest(char *buffer) { +//"VERIFYMSG" > "VERIFYMSG " +int member_verifymsg(char *buffer) { char *current = buffer; uint8_t binbuf[MAX_BUFSIZE]; - uint8_t msg[MAX_MSGSIZE] = "I am the real host"; - size_t msg_len = strlen((char*)msg); - uint8_t has_nym = member.bsn_len != 0 ? 1 : 0; + uint8_t has_nym = member.bsn_len > 0 ? 1 : 0; struct ecdaa_signature_FP256BN sig; - size_t sig_len = has_nym ? ECDAA_SIGNATURE_FP256BN_WITH_NYM_LENGTH : ECDAA_SIGNATURE_FP256BN_LENGTH; + size_t sig_len = has_nym ? ecdaa_signature_FP256BN_with_nym_length() : ecdaa_signature_FP256BN_length(); + int ret = 0; + + if (0 == strncasecmp("OK", buffer, 2)) { + return 1; + } else if (0 == strncasecmp("ERR", buffer, 3)) { + printf("member_verifymsg: Verifier refused signature\n"); + return 1; + } - ecdaa_signature_TPM_FP256BN_sign(&sig, msg, msg_len, member.bsn, member.bsn_len, &member.cred, ecdaa_rand, &member.ctx); bzero(buffer, MAX_BUFSIZE); - bzero(binbuf, MAX_BUFSIZE); - strncpy(current, "ATTEST ", 7); - current = ¤t[7]; + strncpy(current, "VERIFYMSG ", 10); + current = ¤t[10]; - strncpy(current, (char*) msg, MAX_MSGSIZE); - current[MAX_MSGSIZE] = has_nym == 1 ? '1' : '0'; - current = ¤t[MAX_MSGSIZE + 1]; + ret = ecdaa_encode(msg, current, msg_len); + current = ¤t[2 * MAX_MSGSIZE]; if(has_nym) { + if (0 != ecdaa_signature_TPM_FP256BN_sign(&sig, msg, msg_len, member.bsn, member.bsn_len, &member.cred, ecdaa_rand, &member.ctx)) { + printf("member_verifymsg: Signing message failed\n"); + } + current[0] = '1'; + current = ¤t[1]; strncpy(current, (char *)member.bsn, MAX_BSNSIZE); current = ¤t[MAX_BSNSIZE]; + } else { + if (0 != ecdaa_signature_TPM_FP256BN_sign(&sig, msg, msg_len, NULL, 0, &member.cred, ecdaa_rand, &member.ctx)) { + printf("member_verifymsg: Signing message failed\n"); + } + current[0] = '0'; + current = ¤t[1]; } + bzero(binbuf, MAX_BUFSIZE); ecdaa_signature_FP256BN_serialize(binbuf, &sig, has_nym); - ecdaa_bintohex(binbuf, sig_len, current); - current[2 * sig_len] = '\n'; + ret = ecdaa_encode(binbuf, current, sig_len); + printf("member_verifymsg: has_nym: %u, sig_len: %lu\n",has_nym, sig_len); + printf("member_verifymsg: msg: %s, len: %lu\n",msg, msg_len); + printf("member_verifymsg: bsn: %s, len: %lu\n",(char *)member.bsn, strlen((char *)member.bsn)); + printf("member_verifymsg: sig: %s, len: %lu\n", current, sig_len); + + current[ret] = '\n'; return 0; } //"PUBLISH" > "PUBLISH " int member_publish(char *buffer) { char *current; + int ret = 0; uint8_t binbuf[MAX_BUFSIZE]; bzero(buffer, MAX_BUFSIZE); @@ -261,9 +300,9 @@ int member_publish(char *buffer) { current = &buffer[8]; bzero(binbuf, MAX_BUFSIZE); ecdaa_member_public_key_FP256BN_serialize(binbuf, &member.mpk); - ecdaa_bintohex(binbuf, ECDAA_MEMBER_PUBLIC_KEY_FP256BN_LENGTH, current); + ret = ecdaa_encode(binbuf, current, ECDAA_MEMBER_PUBLIC_KEY_FP256BN_LENGTH); - current[2 * ECDAA_MEMBER_PUBLIC_KEY_FP256BN_LENGTH] = '\n'; + current[ret] = '\n'; return 0; } @@ -272,13 +311,9 @@ int member_publish(char *buffer) { int member_joinappend(char *buffer) { char *current = &buffer[10]; uint8_t binbuf[MAX_BUFSIZE]; - ecdaa_hextobin(current, member.nonce, NONCE_SIZE); - - uint8_t serial_gpk[ECDAA_GROUP_PUBLIC_KEY_FP256BN_LENGTH]; - bzero(serial_gpk, ECDAA_GROUP_PUBLIC_KEY_FP256BN_LENGTH); - ecdaa_issuer_public_key_FP256BN_serialize(serial_gpk, &member.ipk); - - if (0 != ecdaa_member_key_pair_TPM_FP256BN_generate(&member.mpk, serial_gpk, member.nonce, NONCE_SIZE, &member.ctx)) { + int ret = ecdaa_decode(current, member.nonce, NONCE_SIZE); + ecdaa_write_buffer_to_file(member_nonce_file, member.nonce, NONCE_SIZE); + if (0 != ecdaa_member_key_pair_TPM_FP256BN_generate(&member.mpk, member.pk_in, member.nonce, NONCE_SIZE, &member.ctx)) { fprintf(stderr, "Error generating member key-pair\n"); return -1; } @@ -288,8 +323,8 @@ int member_joinappend(char *buffer) { current = &buffer[7]; bzero(binbuf, MAX_BUFSIZE); ecdaa_member_public_key_FP256BN_serialize(binbuf, &member.mpk); - ecdaa_bintohex(binbuf, ECDAA_MEMBER_PUBLIC_KEY_FP256BN_LENGTH, current); - current[2 * ECDAA_MEMBER_PUBLIC_KEY_FP256BN_LENGTH] = '\n'; + ret = ecdaa_encode(binbuf, current, ECDAA_MEMBER_PUBLIC_KEY_FP256BN_LENGTH); + current[ret] = '\n'; return 0; } @@ -300,19 +335,66 @@ int member_joinfinish(char *buffer) { uint8_t binbuf[MAX_BUFSIZE]; int ret = 0; bzero(binbuf, MAX_BUFSIZE); - ecdaa_hextobin(current, binbuf, ECDAA_CREDENTIAL_FP256BN_LENGTH); + ret = ecdaa_decode(current, binbuf, ECDAA_CREDENTIAL_FP256BN_LENGTH); - current = &buffer[12 + 2 * ECDAA_CREDENTIAL_FP256BN_LENGTH + 1]; + current = ¤t[ret]; bincur = &binbuf[ECDAA_CREDENTIAL_FP256BN_LENGTH]; - ecdaa_hextobin(current, bincur, ECDAA_CREDENTIAL_FP256BN_SIGNATURE_LENGTH); + ecdaa_decode(current, bincur, ECDAA_CREDENTIAL_FP256BN_SIGNATURE_LENGTH); ret = ecdaa_credential_FP256BN_deserialize_with_signature(&member.cred, &member.mpk, &member.ipk.gpk, binbuf, bincur); if(-1 == ret) { printf("member_joinfinish: credential is malformed!\n"); ret = -1; } else if(-2 == ret) { - printf("member_joinfinish: siganture of credential is invalid"); + printf("member_joinfinish: siganture of credential is invalid\n"); ret = -1; } + printf("member_joinfinish: writing key-pair and credential to disk\n"); + if(0 != ecdaa_member_public_key_FP256BN_serialize_file(member_public_key_file, &member.mpk) || + 0 != ecdaa_credential_FP256BN_serialize_file(member_credential_file, &member.cred)) { + printf("issuer_setup: Error saving key-pair or credential to disk\n"); + return -1; + } + + return ret; +} + +int read_public_key_from_files(uint8_t *public_key, TPM2_HANDLE *key_handle, const char *pub_key_filename, const char *handle_filename) +{ + int ret = 0; + + FILE *pub_key_file_ptr = fopen(pub_key_filename, "r"); + if (NULL == pub_key_file_ptr) + return -1; + do { + for (unsigned i=0; i < ECP_FP256BN_LENGTH; i++) { + unsigned byt; + if (fscanf(pub_key_file_ptr, "%02X", &byt) != 1) { + ret = -1; + break; + } + public_key[i] = (uint8_t)byt; + } + } while(0); + (void)fclose(pub_key_file_ptr); + if (0 != ret) + return -1; + + FILE *handle_file_ptr = fopen(handle_filename, "r"); + if (NULL == handle_file_ptr) + return -1; + do { + for (int i=(sizeof(TPM2_HANDLE)-1); i >= 0; i--) { + unsigned byt; + if (fscanf(handle_file_ptr, "%02X", &byt) != 1) { + ret = -1; + break; + } + *key_handle += byt<<(i*8); + } + if (0 != ret) + break; + } while(0); + (void)fclose(handle_file_ptr); return ret; } diff --git a/member-tpm.h b/member-tpm.h index f497280..f136025 100644 --- a/member-tpm.h +++ b/member-tpm.h @@ -2,8 +2,8 @@ // Created by root on 11/5/19. // -#ifndef ECDAA_ISSUER_MEMBER_H -#define ECDAA_ISSUER_MEMBER_H +#ifndef ECDAA_MEMBER_TPM_H +#define ECDAA_MEMBER_TPM_H #include #include #include @@ -13,6 +13,12 @@ #include "client.h" #include "common.h" +#define ECP_FP256BN_LENGTH 130 + int process_member(char *buffer); -#endif //ECDAA_ISSUER_ISSUER_H +const char* member_public_key_file = "mpk.bin"; +const char* member_credential_file = "mcred.bin"; +const char* member_nonce_file = "mnonce.bin"; + +#endif //ECDAA_MEMBER_TPM_H