From 1b68bafa161e4c9ad1dad7cab0f230669ce61795 Mon Sep 17 00:00:00 2001 From: David Robson Date: Thu, 24 May 2018 03:19:41 +0000 Subject: [PATCH] Merged PR 846969: Make a iothsm-tpm library that links in TPM functionality. Adds the TPM code from C_SDK fixed up to work with iothsm needs, including adding `hsm_tpm_derive_and_sign_with_identity`, TPM as a device is selectable at runtime by setting "IOTEDGE_USE_TPM_DEVICE" to "ON". --- .gitmodules | 9 +- edgelet/build/windows/test.ps1 | 3 +- edgelet/hsm-sys/README.md | 6 + .../hsm-sys/azure-iot-hsm-c/CMakeLists.txt | 33 +- .../azure-iot-hsm-c/azure-c-shared-utility | 1 - edgelet/hsm-sys/azure-iot-hsm-c/deps/c-shared | 1 + edgelet/hsm-sys/azure-iot-hsm-c/deps/utpm | 1 + .../hsm-sys/azure-iot-hsm-c/src/constants.c | 2 + .../azure-iot-hsm-c/src/edge_sas_key.c | 62 +- .../src/edge_sas_perform_sign_with_key.c | 65 + .../src/edge_sas_perform_sign_with_key.h | 9 + .../src/hsm_client_tpm_device.c | 726 ++++++++++ .../src/hsm_client_tpm_device.h | 7 + ...m_client_tpm.c => hsm_client_tpm_in_mem.c} | 6 +- .../src/hsm_client_tpm_in_mem.h | 8 + .../src/hsm_client_tpm_select.c | 106 ++ .../azure-iot-hsm-c/tests/CMakeLists.txt | 1 + .../edge_hsm_key_intf_sas_ut/CMakeLists.txt | 3 +- .../edge_hsm_key_intf_sas_ut.c | 11 +- .../tests/edge_hsm_tpm_ut/CMakeLists.txt | 3 +- .../tests/edge_hsm_tpm_ut/edge_hsm_tpm_ut.c | 153 +-- .../tests/hsm_client_tpm_ut/CMakeLists.txt | 26 + .../hsm_client_tpm_ut/hsm_client_tpm_ut.c | 1180 +++++++++++++++++ .../tests/hsm_client_tpm_ut/main.c | 11 + edgelet/hsm-sys/build.rs | 40 +- 25 files changed, 2308 insertions(+), 165 deletions(-) delete mode 160000 edgelet/hsm-sys/azure-iot-hsm-c/azure-c-shared-utility create mode 160000 edgelet/hsm-sys/azure-iot-hsm-c/deps/c-shared create mode 160000 edgelet/hsm-sys/azure-iot-hsm-c/deps/utpm create mode 100644 edgelet/hsm-sys/azure-iot-hsm-c/src/edge_sas_perform_sign_with_key.c create mode 100644 edgelet/hsm-sys/azure-iot-hsm-c/src/edge_sas_perform_sign_with_key.h create mode 100644 edgelet/hsm-sys/azure-iot-hsm-c/src/hsm_client_tpm_device.c create mode 100644 edgelet/hsm-sys/azure-iot-hsm-c/src/hsm_client_tpm_device.h rename edgelet/hsm-sys/azure-iot-hsm-c/src/{edge_hsm_client_tpm.c => hsm_client_tpm_in_mem.c} (98%) create mode 100644 edgelet/hsm-sys/azure-iot-hsm-c/src/hsm_client_tpm_in_mem.h create mode 100644 edgelet/hsm-sys/azure-iot-hsm-c/src/hsm_client_tpm_select.c create mode 100644 edgelet/hsm-sys/azure-iot-hsm-c/tests/hsm_client_tpm_ut/CMakeLists.txt create mode 100644 edgelet/hsm-sys/azure-iot-hsm-c/tests/hsm_client_tpm_ut/hsm_client_tpm_ut.c create mode 100644 edgelet/hsm-sys/azure-iot-hsm-c/tests/hsm_client_tpm_ut/main.c diff --git a/.gitmodules b/.gitmodules index a3034c2179f..355f44f00b8 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ -[submodule "edgelet/hsm-sys/azure-iot-hsm-c/azure-c-shared-utility"] - path = edgelet/hsm-sys/azure-iot-hsm-c/azure-c-shared-utility - url = https://github.com/Azure/azure-c-shared-utility +[submodule "edgelet/hsm-sys/azure-iot-hsm-c/deps/azure-c-shared-utility"] + path = edgelet/hsm-sys/azure-iot-hsm-c/deps/c-shared + url = https://github.com/Azure/azure-c-shared-utility.git +[submodule "edgelet/hsm-sys/azure-iot-hsm-c/deps/azure-utpm-c"] + path = edgelet/hsm-sys/azure-iot-hsm-c/deps/utpm + url = https://github.com/Azure/azure-utpm-c.git diff --git a/edgelet/build/windows/test.ps1 b/edgelet/build/windows/test.ps1 index 6cafae99e26..02b44e33f41 100644 --- a/edgelet/build/windows/test.ps1 +++ b/edgelet/build/windows/test.ps1 @@ -22,7 +22,6 @@ $env:IOTEDGE_HOMEDIR = $env:Temp Write-Host "$cargo test --all $(if ($Release) { '--release' }) --manifest-path $ManifestPath" Invoke-Expression "$cargo test --all $(if ($Release) { '--release' }) --manifest-path $ManifestPath" -if ($LastExitCode) -{ +if ($LastExitCode) { Throw "cargo test failed with exit code $LastExitCode" } diff --git a/edgelet/hsm-sys/README.md b/edgelet/hsm-sys/README.md index 9fae758c4c7..70167b969cb 100644 --- a/edgelet/hsm-sys/README.md +++ b/edgelet/hsm-sys/README.md @@ -5,6 +5,12 @@ This crate is the unsafe C to Rust interface for the HSM API library. This crate represents the functions that the HSM API implements. This crate is used by the HSM-RS crate to provide more Rust-friendly interfaces. +## TPM functionality + +The default hsm library built as part of this crate has two modes for the TPM functional interface: +an in-memory keystore, and a TPM device keystore. The default is the in-memory keystore. To enable +the TPM device keystore set an envronment variable `IOTEDGE_USE_TPM_DEVICE` to "ON". + ## Memory allocation The current HSPM API functions expect the calling function to allocate diff --git a/edgelet/hsm-sys/azure-iot-hsm-c/CMakeLists.txt b/edgelet/hsm-sys/azure-iot-hsm-c/CMakeLists.txt index c5e1f0c3f36..6db5e8b5d8b 100644 --- a/edgelet/hsm-sys/azure-iot-hsm-c/CMakeLists.txt +++ b/edgelet/hsm-sys/azure-iot-hsm-c/CMakeLists.txt @@ -9,7 +9,8 @@ set (iothsm_VERSION_MINOR 1) #Use solution folders. set_property(GLOBAL PROPERTY USE_FOLDERS ON) -include_directories(./azure-c-shared-utility/inc) +include_directories(./deps/c-shared/inc) +include_directories(./deps/utpm/inc) include_directories(. ./inc) find_package(OpenSSL REQUIRED) @@ -20,13 +21,16 @@ set(source_c_files ./src/constants.c ./src/edge_hsm_client_crypto.c ./src/edge_hsm_client_store.c - ./src/edge_hsm_client_tpm.c ./src/edge_hsm_client_x509.c ./src/edge_hsm_key_interface.c + ./src/edge_sas_perform_sign_with_key.c ./src/edge_pki_openssl.c ./src/edge_sas_key.c ./src/hsm_certificate_props.c ./src/hsm_client_data.c + ./src/hsm_client_tpm_device.c + ./src/hsm_client_tpm_in_mem.c + ./src/hsm_client_tpm_select.c ./src/hsm_log.c ./src/hsm_utils.c ) @@ -35,6 +39,14 @@ set(source_h_files ./inc/certificate_info.h ./inc/hsm_client_data.h ./inc/hsm_certificate_props.h + ./src/edge_sas_perform_sign_with_key.h + ./src/hsm_client_store.h + ./src/hsm_client_tpm_device.h + ./src/hsm_client_tpm_in_mem.h + ./src/hsm_constants.h + ./src/hsm_key.h + ./src/hsm_log.h + ./src/hsm_utils.h ) if(WIN32) @@ -71,21 +83,22 @@ endif(WIN32) # We want this to always be a shared library and let the dynamic linker on the # target system find the HSM library. if(BUILD_SHARED) - add_library(iothsm SHARED ${source_c_files} ${source_h_files}) + add_library(iothsm SHARED ${source_c_files} ${source_in_mem_store_c_files} ${source_h_files}) else() - add_library(iothsm STATIC ${source_c_files} ${source_h_files}) + add_library(iothsm STATIC ${source_c_files} ${source_in_mem_store_c_files} ${source_h_files}) endif(BUILD_SHARED) if (run_unittests) enable_testing() set(save_ut ${run_unittests}) set(run_unittests OFF CACHE BOOL "unittests" FORCE) - add_subdirectory(./azure-c-shared-utility/testtools/ctest) - add_subdirectory(./azure-c-shared-utility/testtools/testrunner) - add_subdirectory(./azure-c-shared-utility/testtools/umock-c) + add_subdirectory(./deps/c-shared/testtools/ctest) + add_subdirectory(./deps/c-shared/testtools/testrunner) + add_subdirectory(./deps/c-shared/testtools/umock-c) endif(run_unittests) -add_subdirectory(./azure-c-shared-utility EXCLUDE_FROM_ALL) +add_subdirectory(./deps/c-shared EXCLUDE_FROM_ALL) +add_subdirectory(./deps/utpm EXCLUDE_FROM_ALL) if (save_ut) set(run_unittests ${save_ut} CACHE BOOL "unittests" FORCE) @@ -96,9 +109,9 @@ if (${run_unittests}) endif() if(WIN32) - target_link_libraries(iothsm aziotsharedutil $ENV{OPENSSL_ROOT_DIR}/lib/ssleay32.lib $ENV{OPENSSL_ROOT_DIR}/lib/libeay32.lib) + target_link_libraries(iothsm aziotsharedutil utpm $ENV{OPENSSL_ROOT_DIR}/lib/ssleay32.lib $ENV{OPENSSL_ROOT_DIR}/lib/libeay32.lib) else() - target_link_libraries(iothsm aziotsharedutil ${OPENSSL_LIBRARIES}) + target_link_libraries(iothsm aziotsharedutil utpm ${OPENSSL_LIBRARIES}) endif(WIN32) install(TARGETS iothsm DESTINATION lib) diff --git a/edgelet/hsm-sys/azure-iot-hsm-c/azure-c-shared-utility b/edgelet/hsm-sys/azure-iot-hsm-c/azure-c-shared-utility deleted file mode 160000 index f714f0d9e9f..00000000000 --- a/edgelet/hsm-sys/azure-iot-hsm-c/azure-c-shared-utility +++ /dev/null @@ -1 +0,0 @@ -Subproject commit f714f0d9e9f3010395d1b4043984fad38632cb6f diff --git a/edgelet/hsm-sys/azure-iot-hsm-c/deps/c-shared b/edgelet/hsm-sys/azure-iot-hsm-c/deps/c-shared new file mode 160000 index 00000000000..c250e8273cd --- /dev/null +++ b/edgelet/hsm-sys/azure-iot-hsm-c/deps/c-shared @@ -0,0 +1 @@ +Subproject commit c250e8273cd9e1c950daad6ed2f50079ae82f7d8 diff --git a/edgelet/hsm-sys/azure-iot-hsm-c/deps/utpm b/edgelet/hsm-sys/azure-iot-hsm-c/deps/utpm new file mode 160000 index 00000000000..ecde07a099f --- /dev/null +++ b/edgelet/hsm-sys/azure-iot-hsm-c/deps/utpm @@ -0,0 +1 @@ +Subproject commit ecde07a099f9e921e78c42b189876e83dca18570 diff --git a/edgelet/hsm-sys/azure-iot-hsm-c/src/constants.c b/edgelet/hsm-sys/azure-iot-hsm-c/src/constants.c index 07ecadb7018..c2994b1fdc5 100644 --- a/edgelet/hsm-sys/azure-iot-hsm-c/src/constants.c +++ b/edgelet/hsm-sys/azure-iot-hsm-c/src/constants.c @@ -1,3 +1,4 @@ +// Copyright (c) Microsoft. All rights reserved. #include "hsm_constants.h" /* IOTEDGE env variables set by iotedged */ @@ -6,6 +7,7 @@ const char* const ENV_DEVICE_CA_PATH = "IOTEDGE_DEVICE_CA_PATH"; const char* const ENV_DEVICE_CA_CHAIN_PATH = "IOTEDGE_DEVICE_CA_CHAIN_PATH"; const char* const ENV_DEVICE_PK_PATH = "IOTEDGE_DEVICE_PK_PATH"; const char* const ENV_OWNER_CA_PATH = "IOTEDGE_OWNER_CA_PATH"; +const char* const ENV_TPM_SELECT = "IOTEDGE_USE_TPM_DEVICE"; /* HSM directory name under IOTEDGE_HOMEDIR */ const char* const DEFAULT_EDGE_HOME_DIR_UNIX = "/var/lib/iotedge"; // note MacOS is included diff --git a/edgelet/hsm-sys/azure-iot-hsm-c/src/edge_sas_key.c b/edgelet/hsm-sys/azure-iot-hsm-c/src/edge_sas_key.c index 808ab52b486..137cd89fe9d 100644 --- a/edgelet/hsm-sys/azure-iot-hsm-c/src/edge_sas_key.c +++ b/edgelet/hsm-sys/azure-iot-hsm-c/src/edge_sas_key.c @@ -1,7 +1,7 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. #include "azure_c_shared_utility/gballoc.h" -#include "azure_c_shared_utility/buffer_.h" -#include "azure_c_shared_utility/hmacsha256.h" - +#include "edge_sas_perform_sign_with_key.h" #include "hsm_key.h" #include "hsm_log.h" @@ -13,62 +13,6 @@ struct SAS_KEY_TAG }; typedef struct SAS_KEY_TAG SAS_KEY; -static int perform_sign_with_key -( - const unsigned char* key, - size_t key_len, - const unsigned char* data_to_be_signed, - size_t data_to_be_signed_size, - unsigned char** digest, - size_t* digest_size -) -{ - int result; - BUFFER_HANDLE signed_payload_handle; - - if ((signed_payload_handle = BUFFER_new()) == NULL) - { - LOG_ERROR("Error allocating new buffer handle"); - result = 1; - } - else - { - size_t signed_payload_size; - unsigned char *result_digest, *src_digest; - int status = HMACSHA256_ComputeHash(key, key_len, data_to_be_signed, - data_to_be_signed_size, signed_payload_handle); - if (status != HMACSHA256_OK) - { - LOG_ERROR("Error computing HMAC256SHA signature"); - result = 1; - } - else if ((signed_payload_size = BUFFER_length(signed_payload_handle)) == 0) - { - LOG_ERROR("Error computing HMAC256SHA. Signature size is 0"); - result = 1; - } - else if ((src_digest = BUFFER_u_char(signed_payload_handle)) == NULL) - { - LOG_ERROR("Error obtaining underlying uchar buffer"); - result = 1; - } - else if ((result_digest = (unsigned char*)malloc(signed_payload_size)) == NULL) - { - LOG_ERROR("Error allocating memory for digest"); - result = 1; - } - else - { - memcpy(result_digest, src_digest, signed_payload_size); - *digest = result_digest; - *digest_size = signed_payload_size; - result = 0; - } - BUFFER_delete(signed_payload_handle); - } - return result; -} - static int sas_key_sign ( KEY_HANDLE key_handle, diff --git a/edgelet/hsm-sys/azure-iot-hsm-c/src/edge_sas_perform_sign_with_key.c b/edgelet/hsm-sys/azure-iot-hsm-c/src/edge_sas_perform_sign_with_key.c new file mode 100644 index 00000000000..6b75a86315a --- /dev/null +++ b/edgelet/hsm-sys/azure-iot-hsm-c/src/edge_sas_perform_sign_with_key.c @@ -0,0 +1,65 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +#include "azure_c_shared_utility/buffer_.h" +#include "azure_c_shared_utility/gballoc.h" +#include "azure_c_shared_utility/hmacsha256.h" +#include "azure_c_shared_utility/macro_utils.h" + +#include "hsm_log.h" + +int perform_sign_with_key +( + const unsigned char* key, + size_t key_len, + const unsigned char* data_to_be_signed, + size_t data_to_be_signed_size, + unsigned char** digest, + size_t* digest_size +) +{ + int result; + BUFFER_HANDLE signed_payload_handle; + + if ((signed_payload_handle = BUFFER_new()) == NULL) + { + LOG_ERROR("Error allocating new buffer handle"); + result = __FAILURE__; + } + else + { + size_t signed_payload_size; + unsigned char *result_digest, *src_digest; + int status = HMACSHA256_ComputeHash(key, key_len, data_to_be_signed, + data_to_be_signed_size, signed_payload_handle); + if (status != HMACSHA256_OK) + { + LOG_ERROR("Error computing HMAC256SHA signature"); + result = __FAILURE__; + } + else if ((signed_payload_size = BUFFER_length(signed_payload_handle)) == 0) + { + LOG_ERROR("Error computing HMAC256SHA. Signature size is 0"); + result = __FAILURE__; + } + else if ((src_digest = BUFFER_u_char(signed_payload_handle)) == NULL) + { + LOG_ERROR("Error obtaining underlying uchar buffer"); + result = __FAILURE__; + } + else if ((result_digest = (unsigned char*)malloc(signed_payload_size)) == NULL) + { + LOG_ERROR("Error allocating memory for digest"); + result = __FAILURE__; + } + else + { + memcpy(result_digest, src_digest, signed_payload_size); + *digest = result_digest; + *digest_size = signed_payload_size; + result = 0; + } + BUFFER_delete(signed_payload_handle); + } + return result; +} + diff --git a/edgelet/hsm-sys/azure-iot-hsm-c/src/edge_sas_perform_sign_with_key.h b/edgelet/hsm-sys/azure-iot-hsm-c/src/edge_sas_perform_sign_with_key.h new file mode 100644 index 00000000000..a7abab18171 --- /dev/null +++ b/edgelet/hsm-sys/azure-iot-hsm-c/src/edge_sas_perform_sign_with_key.h @@ -0,0 +1,9 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +#include "azure_c_shared_utility/umock_c_prod.h" + +MOCKABLE_FUNCTION(,int, perform_sign_with_key, const unsigned char *, key, size_t, key_len, + const unsigned char *, data_to_be_signed, size_t, data_to_be_signed_size, + unsigned char **, digest, size_t *, digest_size); + diff --git a/edgelet/hsm-sys/azure-iot-hsm-c/src/hsm_client_tpm_device.c b/edgelet/hsm-sys/azure-iot-hsm-c/src/hsm_client_tpm_device.c new file mode 100644 index 00000000000..1ebc3ea439c --- /dev/null +++ b/edgelet/hsm-sys/azure-iot-hsm-c/src/hsm_client_tpm_device.c @@ -0,0 +1,726 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +/// Derived fom azure-iot-sdk-c library's provisioning client. +/// https://github.com/Azure/azure-iot-sdk-c/blob/master/provisioning_client/src/secure_device_tpm.c + +#include +#include +#include "azure_c_shared_utility/gballoc.h" +#include "azure_c_shared_utility/sastoken.h" +#include "azure_c_shared_utility/sha.h" +#include "hsm_log.h" +#include "azure_c_shared_utility/crt_abstractions.h" + +#include "hsm_client_data.h" +#include "edge_sas_perform_sign_with_key.h" +#include "azure_utpm_c/tpm_comm.h" +#include "azure_utpm_c/tpm_codec.h" + +#include "azure_utpm_c/Marshal_fp.h" // for activation blob unmarshaling + +#define EPOCH_TIME_T_VALUE 0 +#define HMAC_LENGTH 32 + +static TPM2B_AUTH NullAuth = { 0 }; +static TSS_SESSION NullPwSession; +static const UINT32 TPM_20_SRK_HANDLE = HR_PERSISTENT | 0x00000001; +static const UINT32 TPM_20_EK_HANDLE = HR_PERSISTENT | 0x00010001; +static const UINT32 DPS_ID_KEY_HANDLE = HR_PERSISTENT | 0x00000100; + +typedef struct HSM_CLIENT_INFO_TAG +{ + TSS_DEVICE tpm_device; + TPM2B_PUBLIC ek_pub; + TPM2B_PUBLIC srk_pub; + + TPM2B_PUBLIC id_key_public; + TPM2B_PRIVATE id_key_dup_blob; + TPM2B_PRIVATE id_key_priv; +} HSM_CLIENT_INFO; + +static TPMS_RSA_PARMS RsaStorageParams = { + { TPM_ALG_AES, 128, TPM_ALG_CFB }, // TPMT_SYM_DEF_OBJECT symmetric + { TPM_ALG_NULL }, // TPMT_RSA_SCHEME scheme + 2048, // TPMI_RSA_KEY_BITS keyBits + 0 // UINT32 exponent +}; + +static TPM2B_PUBLIC* GetEkTemplate () +{ + static TPM2B_PUBLIC EkTemplate = { 0, // size will be computed during marshaling + { + TPM_ALG_RSA, // TPMI_ALG_PUBLIC type + TPM_ALG_SHA256, // TPMI_ALG_HASH nameAlg + { 0 }, // TPMA_OBJECT objectAttributes (set below) + {32, + { 0x83, 0x71, 0x97, 0x67, 0x44, 0x84, 0xb3, 0xf8, + 0x1a, 0x90, 0xcc, 0x8d, 0x46, 0xa5, 0xd7, 0x24, + 0xfd, 0x52, 0xd7, 0x6e, 0x06, 0x52, 0x0b, 0x64, + 0xf2, 0xa1, 0xda, 0x1b, 0x33, 0x14, 0x69, 0xaa } + }, // TPM2B_DIGEST authPolicy + { 0 }, // TPMU_PUBLIC_PARMS parameters (set below) + { 0 } // TPMU_PUBLIC_ID unique + } }; + EkTemplate.publicArea.objectAttributes = ToTpmaObject( + Restricted | Decrypt | FixedTPM | FixedParent | AdminWithPolicy | SensitiveDataOrigin); + EkTemplate.publicArea.parameters.rsaDetail = RsaStorageParams; + return &EkTemplate; +} + +static TPM2B_PUBLIC* GetSrkTemplate() +{ + static TPM2B_PUBLIC SrkTemplate = { 0, // size will be computed during marshaling + { + TPM_ALG_RSA, // TPMI_ALG_PUBLIC type + TPM_ALG_SHA256, // TPMI_ALG_HASH nameAlg + { 0 }, // TPMA_OBJECT objectAttributes (set below) + { 0 }, // TPM2B_DIGEST authPolicy + { 0 }, // TPMU_PUBLIC_PARMS parameters (set before use) + { 0 } // TPMU_PUBLIC_ID unique + } }; + SrkTemplate.publicArea.objectAttributes = ToTpmaObject( + Restricted | Decrypt | FixedTPM | FixedParent | NoDA | UserWithAuth | SensitiveDataOrigin); + SrkTemplate.publicArea.parameters.rsaDetail = RsaStorageParams; + return &SrkTemplate; +} + +#define DPS_UNMARSHAL(Type, pValue) \ +{ \ + TPM_RC rc = Type##_Unmarshal(pValue, &curr_pos, (INT32*)&act_size); \ + if (rc != TPM_RC_SUCCESS) \ + { \ + LOG_ERROR(#Type"_Unmarshal() for " #pValue " failed"); \ + } \ +} + +#define DPS_UNMARSHAL_FLAGGED(Type, pValue) \ +{ \ + TPM_RC rc = Type##_Unmarshal(pValue, &curr_pos, (INT32*)&act_size, TRUE); \ + if (rc != TPM_RC_SUCCESS) \ + { \ + LOG_ERROR(#Type"_Unmarshal() for " #pValue " failed"); \ + } \ +} + +#define DPS_UNMARSHAL_ARRAY(dstPtr, arrSize) \ + DPS_UNMARSHAL(UINT32, &(arrSize)); \ + printf("act_size %d < actSize %d\r\n", act_size, arrSize); \ + if (act_size < arrSize) \ + { \ + LOG_ERROR("Unmarshaling " #dstPtr " failed: Need %d bytes, while only %d left", arrSize, act_size); \ + result = __FAILURE__; \ + } \ + else \ + { \ + dstPtr = curr_pos - sizeof(UINT16); \ + *(UINT16*)dstPtr = (UINT16)arrSize; \ + curr_pos += arrSize; \ + } + +static int dps_umarshal_array +( + unsigned char* dst_ptr, + uint32_t dest_size, + unsigned char* act_buff, + uint32_t act_size +) +{ + int result; + uint8_t* curr_pos = act_buff; + + DPS_UNMARSHAL(UINT32, &(dest_size)); + if (act_size < dest_size) + { + LOG_ERROR("Unmarshaling failed: Need %d bytes, while only %d left", + dest_size, act_size); + result = __FAILURE__; + } + else + { + dst_ptr = act_buff - sizeof(UINT16); + *(UINT16*)dst_ptr = (UINT16)dest_size; + act_buff += dest_size; + result = 0; + } + return result; +} + +static int unmarshal_array +( + uint8_t* dstptr, + uint32_t size, + uint8_t** curr_pos, + uint32_t* curr_size +) +{ + int result; + + TPM_RC tpm_res = UINT32_Unmarshal((uint32_t*)dstptr, curr_pos, (int32_t*)curr_size); + if (tpm_res != TPM_RC_SUCCESS) + { + LOG_ERROR("Failure: unmarshalling array."); + result = __FAILURE__; + } + else if (*curr_size < size) + { + LOG_ERROR("Failure: unmarshalling array need %d bytes, while only %d left.", + size, *curr_size); + result = __FAILURE__; + } + else + { + dstptr = *curr_pos - sizeof(UINT16); + *(UINT16*)dstptr = (UINT16)size; + curr_pos += size; + result = 0; + } + return result; +} + +static int marshal_array_values +( + const unsigned char* key, + size_t key_len, + uint8_t** decrypt_blob, + uint8_t** decrypt_secret, + uint8_t** decrypt_wrap_key, + TPM2B_PRIVATE* enc_key_blob +) +{ + int result = 0; + uint8_t* curr_pos = (uint8_t*)key; + uint32_t act_size = (int32_t)key_len; + uint32_t decrypt_size = 0; + uint32_t decrypt_secret_size = 0; + uint32_t decrypt_key_size = 0; + TPM2B_PUBLIC id_key_Public = { TPM_ALG_NULL }; + UINT16 gratuitousSizeField; // WORKAROUND for the current protocol + + DPS_UNMARSHAL_ARRAY(*decrypt_blob, decrypt_size); + if (result != 0) + { + LOG_ERROR("Failure: decrypting blob"); + } + else + { + DPS_UNMARSHAL_ARRAY(*decrypt_secret, decrypt_secret_size); + if (result != 0) + { + LOG_ERROR("Failure: decrypting secret"); + } + else + { + DPS_UNMARSHAL_ARRAY(*decrypt_wrap_key, decrypt_key_size); + if (result != 0) + { + LOG_ERROR("Failure: decrypting wrap secret"); + } + else + { + DPS_UNMARSHAL_FLAGGED(TPM2B_PUBLIC, &id_key_Public); + if (result != 0) + { + LOG_ERROR("Failure: id key public"); + } + else + { + DPS_UNMARSHAL(UINT16, &gratuitousSizeField); + if (result != 0) + { + LOG_ERROR("Failure: gratuitousSizeField"); + } + else + { + DPS_UNMARSHAL(TPM2B_PRIVATE, enc_key_blob); + if (result != 0) + { + LOG_ERROR("Failure: enc key blob"); + } + } + } + } + } + } + return result; +} + +static int create_tpm_session +( + HSM_CLIENT_INFO* sec_info, + TSS_SESSION* tpm_session +) +{ + int result; + TPMA_SESSION sess_attrib = { 1 }; + if (TSS_StartAuthSession(&sec_info->tpm_device, TPM_SE_POLICY, TPM_ALG_SHA256, sess_attrib, tpm_session) != TPM_RC_SUCCESS) + { + LOG_ERROR("Failure: Starting EK policy session"); + result = __FAILURE__; + } + else if (TSS_PolicySecret(&sec_info->tpm_device, &NullPwSession, TPM_RH_ENDORSEMENT, tpm_session, NULL, 0) != TPM_RC_SUCCESS) + { + LOG_ERROR("Failure: PolicySecret() for EK"); + result = __FAILURE__; + } + else + { + result = 0; + } + return result; +} + +static int insert_key_in_tpm +( + HSM_CLIENT_INFO* sec_info, + const unsigned char* key, + size_t key_len +) +{ + int result; + TSS_SESSION ek_sess = { { TPM_RH_NULL } }; + if (create_tpm_session(sec_info, &ek_sess) != 0) + { + LOG_ERROR("Failure: Starting EK policy session"); + result = __FAILURE__; + } + else + { + TPMT_SYM_DEF_OBJECT Aes128SymDef = { TPM_ALG_AES, 128, TPM_ALG_CFB }; + TPM2B_ID_OBJECT enc_key_blob; + TPM2B_ENCRYPTED_SECRET tpm_enc_secret; + TPM2B_PRIVATE id_key_dup_blob; + TPM2B_ENCRYPTED_SECRET encrypt_wrap_key; + TPM2B_PUBLIC id_key_Public = { TPM_ALG_NULL }; + UINT16 enc_data_size = 0; + TPM2B_DIGEST inner_wrap_key = { 0 }; + TPM2B_PRIVATE id_key_priv; + TPM_HANDLE load_id_key = TPM_ALG_NULL; + + uint8_t* curr_pos = (uint8_t*)key; + uint32_t act_size = (int32_t)key_len; + + DPS_UNMARSHAL(TPM2B_ID_OBJECT, &enc_key_blob); + DPS_UNMARSHAL(TPM2B_ENCRYPTED_SECRET, &tpm_enc_secret); + DPS_UNMARSHAL(TPM2B_PRIVATE, &id_key_dup_blob); + DPS_UNMARSHAL(TPM2B_ENCRYPTED_SECRET, &encrypt_wrap_key); + DPS_UNMARSHAL_FLAGGED(TPM2B_PUBLIC, &id_key_Public); + + // The given TPM may support larger TPM2B_MAX_BUFFER than this API headers define. + // So instead of unmarshaling data in a standalone data structure just reuse the + // original activation buffer (after updating byte order of the UINT16 counter) + DPS_UNMARSHAL(UINT16, &enc_data_size); + + if (TPM2_ActivateCredential(&sec_info->tpm_device, &NullPwSession, &ek_sess, TPM_20_SRK_HANDLE, TPM_20_EK_HANDLE, + &enc_key_blob, &tpm_enc_secret, &inner_wrap_key) != TPM_RC_SUCCESS) + { + LOG_ERROR("Failure: TPM2_ActivateCredential"); + result = __FAILURE__; + } + else if (TPM2_Import(&sec_info->tpm_device, &NullPwSession, TPM_20_SRK_HANDLE, (TPM2B_DATA*)&inner_wrap_key, &id_key_Public, &id_key_dup_blob, &encrypt_wrap_key, &Aes128SymDef, &id_key_priv) != TPM_RC_SUCCESS) + { + LOG_ERROR("Failure: importing dps Id key"); + result = __FAILURE__; + } + else + { + TPM2B_SENSITIVE_CREATE sen_create = { 0 }; + TPM2B_PUBLIC sym_pub = { 0 }; + TPM2B_PRIVATE sym_priv = { 0 }; + + static TPM2B_PUBLIC symTemplate = { 0, // size will be computed during marshaling + { + TPM_ALG_SYMCIPHER, // TPMI_ALG_PUBLIC type + TPM_ALG_SHA256, // TPMI_ALG_HASH nameAlg + { 0 }, // TPMA_OBJECT objectAttributes (set below) + { 0 }, // TPM2B_DIGEST authPolicy + { 0 }, // TPMU_PUBLIC_PARMS parameters (set below) + { 0 } // TPMU_PUBLIC_ID unique + } }; + symTemplate.publicArea.objectAttributes = ToTpmaObject(Decrypt | FixedTPM | FixedParent | UserWithAuth); + symTemplate.publicArea.parameters.symDetail.sym.algorithm = TPM_ALG_AES; + symTemplate.publicArea.parameters.symDetail.sym.keyBits.sym = inner_wrap_key.t.size * 8; + symTemplate.publicArea.parameters.symDetail.sym.mode.sym = TPM_ALG_CFB; + + memcpy(sen_create.sensitive.data.t.buffer, inner_wrap_key.t.buffer, inner_wrap_key.t.size); + sen_create.sensitive.data.t.size = inner_wrap_key.t.size; + + if (TSS_Create(&sec_info->tpm_device, &NullPwSession, TPM_20_SRK_HANDLE, &sen_create, &symTemplate, &sym_priv, &sym_pub) != TPM_RC_SUCCESS) + { + LOG_ERROR("Failed to inject symmetric key data"); + result = __FAILURE__; + } + else if (TPM2_Load(&sec_info->tpm_device, &NullPwSession, TPM_20_SRK_HANDLE, &id_key_priv, &id_key_Public, &load_id_key, NULL) != TPM_RC_SUCCESS) + { + LOG_ERROR("Failed Load Id key."); + result = __FAILURE__; + } + else + { + // Remove old Id key + (void)TPM2_EvictControl(&sec_info->tpm_device, &NullPwSession, TPM_RH_OWNER, DPS_ID_KEY_HANDLE, DPS_ID_KEY_HANDLE); + + if (TPM2_EvictControl(&sec_info->tpm_device, &NullPwSession, TPM_RH_OWNER, load_id_key, DPS_ID_KEY_HANDLE) != TPM_RC_SUCCESS) + { + LOG_ERROR("Failed Load Id key."); + result = __FAILURE__; + } + else if (TPM2_FlushContext(&sec_info->tpm_device, load_id_key) != TPM_RC_SUCCESS) + { + LOG_ERROR("Failed Load Id key."); + result = __FAILURE__; + } + else + { + result = 0; + } + } + } + } + return result; +} + +static int initialize_tpm_device(HSM_CLIENT_INFO* tpm_info) +{ + int result; + if (TSS_CreatePwAuthSession(&NullAuth, &NullPwSession) != TPM_RC_SUCCESS) + { + LOG_ERROR("Failure calling TSS_CreatePwAuthSession"); + result = __FAILURE__; + } + else if (Initialize_TPM_Codec(&tpm_info->tpm_device) != TPM_RC_SUCCESS) + { + LOG_ERROR("Failure initializeing TPM Codec"); + result = __FAILURE__; + } + else if ((TSS_CreatePersistentKey(&tpm_info->tpm_device, TPM_20_EK_HANDLE, &NullPwSession, TPM_RH_ENDORSEMENT, GetEkTemplate(), &tpm_info->ek_pub) ) == 0) + { + LOG_ERROR("Failure calling creating persistent key for Endorsement key"); + result = __FAILURE__; + } + else if (TSS_CreatePersistentKey(&tpm_info->tpm_device, TPM_20_SRK_HANDLE, &NullPwSession, TPM_RH_OWNER, GetSrkTemplate(), &tpm_info->srk_pub) == 0) + { + LOG_ERROR("Failure calling creating persistent key for Storage Root key"); + result = __FAILURE__; + } + else + { + result = 0; + } + return result; +} + +static HSM_CLIENT_HANDLE hsm_client_tpm_create() +{ + HSM_CLIENT_INFO* result; + result = malloc(sizeof(HSM_CLIENT_INFO) ); + if (result == NULL) + { + LOG_ERROR("Failure: malloc HSM_CLIENT_INFO."); + } + else + { + memset(result, 0, sizeof(HSM_CLIENT_INFO)); + if (initialize_tpm_device(result) != 0) + { + LOG_ERROR("Failure initializing tpm device."); + free(result); + result = NULL; + } + } + return (HSM_CLIENT_HANDLE)result; +} + +static void hsm_client_tpm_destroy(HSM_CLIENT_HANDLE handle) +{ + if (handle != NULL) + { + HSM_CLIENT_INFO* hsm_client_info = (HSM_CLIENT_INFO*)handle; + + Deinit_TPM_Codec(&hsm_client_info->tpm_device); + free(hsm_client_info); + } +} + +static int hsm_client_tpm_activate_identity_key +( + HSM_CLIENT_HANDLE handle, + const unsigned char* key, + size_t key_len +) +{ + int result; + if (handle == NULL || key == NULL || key_len == 0) + { + LOG_ERROR("Invalid argument specified handle: %p, key: %p, key_len: %zu", handle, key, key_len); + result = __FAILURE__; + } + else + { + if (insert_key_in_tpm((HSM_CLIENT_INFO*)handle, key, key_len)) + { + LOG_ERROR("Failure inserting key into tpm"); + result = __FAILURE__; + } + else + { + result = 0; + } + } + return result; +} + +static int hsm_client_tpm_get_endorsement_key +( + HSM_CLIENT_HANDLE handle, + unsigned char** key, + size_t* key_len +) +{ + int result; + if (handle == NULL || key == NULL || key_len == NULL) + { + LOG_ERROR("Invalid handle value specified: handle: %p, result: %p, result_len: %p", handle, key, key_len); + result = __FAILURE__; + } + else + { + HSM_CLIENT_INFO* hsm_client_info = (HSM_CLIENT_INFO*)handle; + if (hsm_client_info->ek_pub.publicArea.unique.rsa.t.size == 0) + { + LOG_ERROR("Endorsement key is invalid"); + result = __FAILURE__; + } + else + { + unsigned char data_bytes[1024]; + unsigned char* data_pos = data_bytes; + uint32_t data_length = TPM2B_PUBLIC_Marshal(&hsm_client_info->ek_pub, &data_pos, NULL); + if ((*key = (unsigned char*)malloc(data_length)) == NULL) + { + LOG_ERROR("Failure creating buffer handle"); + result = __FAILURE__; + } + else + { + memcpy(*key, data_bytes, data_length); + *key_len = (size_t)data_length; + result = 0; + } + } + } + return result; +} + +static int hsm_client_tpm_get_storage_key +( + HSM_CLIENT_HANDLE handle, + unsigned char** key, + size_t* key_len +) +{ + int result; + if (handle == NULL || key == NULL || key_len == NULL) + { + LOG_ERROR("Invalid handle value specified: handle: %p, result: %p, result_len: %p", handle, key, key_len); + result = __FAILURE__; + } + else + { + HSM_CLIENT_INFO* hsm_client_info = (HSM_CLIENT_INFO*)handle; + if (hsm_client_info->srk_pub.publicArea.unique.rsa.t.size == 0) + { + LOG_ERROR("storage root key is invalid"); + result = __FAILURE__; + } + else + { + unsigned char data_bytes[1024]; + unsigned char* data_pos = data_bytes; + uint32_t data_length = TPM2B_PUBLIC_Marshal(&hsm_client_info->srk_pub, &data_pos, NULL); + if ((*key = (unsigned char*)malloc(data_length)) == NULL) + { + LOG_ERROR("Failure creating buffer handle"); + result = __FAILURE__; + } + else + { + memcpy(*key, data_bytes, data_length); + *key_len = (size_t)data_length; + result = 0; + } + } + } + return result; +} + +static int hsm_client_tpm_sign_data +( + HSM_CLIENT_HANDLE handle, + const unsigned char* data_to_be_signed, + size_t data_to_be_signed_size, + unsigned char** digest, + size_t* digest_size +) +{ + int result; + + if (handle == NULL || data_to_be_signed == NULL || data_to_be_signed_size == 0 || + digest == NULL || digest_size == NULL) + { + LOG_ERROR("Invalid handle value specified handle: %p, data: %p, data_size: %zu, digest: %p, digest_size: %p", + handle, data_to_be_signed, data_to_be_signed_size, digest, digest_size); + result = __FAILURE__; + } + else + { + BYTE data_signature[1024]; + BYTE* data_copy = (unsigned char*)data_to_be_signed; + HSM_CLIENT_INFO* hsm_client_info = (HSM_CLIENT_INFO*)handle; + + uint32_t sign_len = SignData(&hsm_client_info->tpm_device, + &NullPwSession, data_copy, (UINT32)data_to_be_signed_size, + data_signature, sizeof(data_signature) ); + if (sign_len == 0) + { + LOG_ERROR("Failure signing data from hash"); + result = __FAILURE__; + } + else + { + if ((*digest = (unsigned char*)malloc(sign_len)) == NULL) + { + LOG_ERROR("Failure creating buffer handle"); + result = __FAILURE__; + } + else + { + memcpy(*digest, data_signature, sign_len); + *digest_size = (size_t)sign_len; + result = 0; + } + } + } + return result; +} + +static int hsm_client_tpm_derive_and_sign_with_identity +( + HSM_CLIENT_HANDLE handle, + const unsigned char* data_to_be_signed, + size_t data_to_be_signed_size, + const unsigned char* identity, + size_t identity_size, + unsigned char** digest, + size_t* digest_size +) +{ + int result =0; + if (handle == NULL) + { + LOG_ERROR("Invalid NULL Handle"); + result = __FAILURE__; + } + else if (data_to_be_signed == NULL) + { + LOG_ERROR("data to be signed is null"); + result = __FAILURE__; + } + else if (data_to_be_signed_size == 0) + { + LOG_ERROR("no data to be signed"); + result = __FAILURE__; + } + else if (identity == NULL) + { + LOG_ERROR("identity is NULL"); + result = __FAILURE__; + } + else if (identity_size == 0) + { + LOG_ERROR("identity is empty"); + result = __FAILURE__; + } + else if (digest==NULL) + { + LOG_ERROR("digest is NULL"); + result = __FAILURE__; + } + else if (digest_size == NULL) + { + LOG_ERROR("digest_size is NULL"); + result = __FAILURE__; + } + else + { + *digest = NULL; + *digest_size = 0; + + BYTE data_signature[1024]; + BYTE* data_copy = (unsigned char*)identity; + HSM_CLIENT_INFO* hsm_client_info = (HSM_CLIENT_INFO*)handle; + + uint32_t sign_len = SignData(&hsm_client_info->tpm_device, + &NullPwSession, data_copy, (UINT32)identity_size, + data_signature, sizeof(data_signature) ); + if (sign_len == 0) + { + LOG_ERROR("Failure signing derived key from hash"); + result = __FAILURE__; + } + else + { + // data_signature has the module key + // - use software signing so we don't displace the key in TPM0 + if( perform_sign_with_key(data_signature, sign_len, + data_to_be_signed, data_to_be_signed_size, + digest, digest_size) != 0) + { + LOG_ERROR("Failure signing data from derived key hash"); + result = __FAILURE__; + } + else + { + result =0; + } + + memset(data_signature, 0, 1024); + } + } + return result; +} + +static void hsm_client_tpm_free_buffer(void* buffer) +{ + if (buffer != NULL) + { + free(buffer); + } +} + +int hsm_client_tpm_device_init(void) +{ + return 0; +} + +void hsm_client_tpm_device_deinit(void) +{ +} + +static const HSM_CLIENT_TPM_INTERFACE tpm_interface = +{ + hsm_client_tpm_create, + hsm_client_tpm_destroy, + hsm_client_tpm_activate_identity_key, + hsm_client_tpm_get_endorsement_key, + hsm_client_tpm_get_storage_key, + hsm_client_tpm_sign_data, + hsm_client_tpm_derive_and_sign_with_identity, + hsm_client_tpm_free_buffer +}; + +const HSM_CLIENT_TPM_INTERFACE* hsm_client_tpm_device_interface(void) +{ + return &tpm_interface; +} + diff --git a/edgelet/hsm-sys/azure-iot-hsm-c/src/hsm_client_tpm_device.h b/edgelet/hsm-sys/azure-iot-hsm-c/src/hsm_client_tpm_device.h new file mode 100644 index 00000000000..3f9793f038e --- /dev/null +++ b/edgelet/hsm-sys/azure-iot-hsm-c/src/hsm_client_tpm_device.h @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft. All rights reserved. + +#include "hsm_client_data.h" + +extern int hsm_client_tpm_device_init(void); +extern void hsm_client_tpm_device_deinit(void); +extern const HSM_CLIENT_TPM_INTERFACE* hsm_client_tpm_device_interface(); diff --git a/edgelet/hsm-sys/azure-iot-hsm-c/src/edge_hsm_client_tpm.c b/edgelet/hsm-sys/azure-iot-hsm-c/src/hsm_client_tpm_in_mem.c similarity index 98% rename from edgelet/hsm-sys/azure-iot-hsm-c/src/edge_hsm_client_tpm.c rename to edgelet/hsm-sys/azure-iot-hsm-c/src/hsm_client_tpm_in_mem.c index 54ff714e35c..eeed4472cf3 100644 --- a/edgelet/hsm-sys/azure-iot-hsm-c/src/edge_hsm_client_tpm.c +++ b/edgelet/hsm-sys/azure-iot-hsm-c/src/hsm_client_tpm_in_mem.c @@ -20,7 +20,7 @@ static const HSM_CLIENT_STORE_INTERFACE* g_hsm_store_if = NULL; static const HSM_CLIENT_KEY_INTERFACE* g_hsm_key_if = NULL; static bool g_is_tpm_initialized = false; -int hsm_client_tpm_init(void) +int hsm_client_tpm_store_init(void) { int result; int status; @@ -60,7 +60,7 @@ int hsm_client_tpm_init(void) return result; } -void hsm_client_tpm_deinit(void) +void hsm_client_tpm_store_deinit(void) { if (!g_is_tpm_initialized) { @@ -408,7 +408,7 @@ static const HSM_CLIENT_TPM_INTERFACE edge_tpm_interface = edge_hsm_free_buffer }; -const HSM_CLIENT_TPM_INTERFACE* hsm_client_tpm_interface() +const HSM_CLIENT_TPM_INTERFACE* hsm_client_tpm_store_interface() { return &edge_tpm_interface; } diff --git a/edgelet/hsm-sys/azure-iot-hsm-c/src/hsm_client_tpm_in_mem.h b/edgelet/hsm-sys/azure-iot-hsm-c/src/hsm_client_tpm_in_mem.h new file mode 100644 index 00000000000..be81455bd2b --- /dev/null +++ b/edgelet/hsm-sys/azure-iot-hsm-c/src/hsm_client_tpm_in_mem.h @@ -0,0 +1,8 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +#include "hsm_client_data.h" + +extern int hsm_client_tpm_store_init(void); +extern void hsm_client_tpm_store_deinit(void); +extern const HSM_CLIENT_TPM_INTERFACE* hsm_client_tpm_store_interface(); diff --git a/edgelet/hsm-sys/azure-iot-hsm-c/src/hsm_client_tpm_select.c b/edgelet/hsm-sys/azure-iot-hsm-c/src/hsm_client_tpm_select.c new file mode 100644 index 00000000000..17aeb09ccaf --- /dev/null +++ b/edgelet/hsm-sys/azure-iot-hsm-c/src/hsm_client_tpm_select.c @@ -0,0 +1,106 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +#include +#include +#include +#include "hsm_client_tpm_device.h" +#include "hsm_client_tpm_in_mem.h" + +extern const char* const ENV_TPM_SELECT; + +static int strcmp_i(const char* lhs, const char* rhs) +{ + char lc, rc; + int cmp; + do + { + lc = *lhs++; + rc = *rhs++; + if ((tolower(lc) - tolower(rc)) != 0) + { + cmp = 1; + } + } while (lc != 0 && rc != 0); + + return cmp; +} + +// IF ENV_TPM_SELECT is set and not empty, "NO", "OFF" or "FALSE", then user wants to use the +// TPM device for TPM functionality. +static bool use_tpm_device() +{ + static const char * user_says_no[] = { "", "off", "no", "false" }; + int array_size = sizeof(user_says_no)/sizeof(user_says_no[0]); + bool result; + char * env_use_tpm = getenv(ENV_TPM_SELECT); + if (env_use_tpm != NULL) + { + result = true; + for(int no =0; no < array_size; no++) + { + if (strcmp_i(env_use_tpm, user_says_no[no]) == 0) + { + result = false; + break; + } + } + } + else + { + result = false; + } + + return result; +} + +static bool g_use_tpm_device = false; + +int hsm_client_tpm_init(void) +{ + int result; + if (use_tpm_device()) + { + result = hsm_client_tpm_device_init(); + if (result ==0) + { + g_use_tpm_device = true; + } + } + else + { + result = hsm_client_tpm_store_init(); + if (result ==0) + { + g_use_tpm_device = false; + } + } + return result; +} + +void hsm_client_tpm_deinit(void) +{ + if (g_use_tpm_device) + { + hsm_client_tpm_device_deinit(); + } + else + { + hsm_client_tpm_store_deinit(); + } +} + +const HSM_CLIENT_TPM_INTERFACE* hsm_client_tpm_interface(void) +{ + const HSM_CLIENT_TPM_INTERFACE* result; + if (g_use_tpm_device) + { + result = hsm_client_tpm_device_interface(); + } + else + { + result = hsm_client_tpm_store_interface(); + } + return result; +} + diff --git a/edgelet/hsm-sys/azure-iot-hsm-c/tests/CMakeLists.txt b/edgelet/hsm-sys/azure-iot-hsm-c/tests/CMakeLists.txt index 886bae8b805..e464c347c7e 100644 --- a/edgelet/hsm-sys/azure-iot-hsm-c/tests/CMakeLists.txt +++ b/edgelet/hsm-sys/azure-iot-hsm-c/tests/CMakeLists.txt @@ -16,3 +16,4 @@ add_subdirectory(edge_hsm_crypto_int) # todo modify condition to check for openssl feature add_subdirectory(edge_openssl_int) add_subdirectory(edge_hsm_store_int) +add_subdirectory(hsm_client_tpm_ut) diff --git a/edgelet/hsm-sys/azure-iot-hsm-c/tests/edge_hsm_key_intf_sas_ut/CMakeLists.txt b/edgelet/hsm-sys/azure-iot-hsm-c/tests/edge_hsm_key_intf_sas_ut/CMakeLists.txt index e3709bb303e..4a4d8099e4c 100644 --- a/edgelet/hsm-sys/azure-iot-hsm-c/tests/edge_hsm_key_intf_sas_ut/CMakeLists.txt +++ b/edgelet/hsm-sys/azure-iot-hsm-c/tests/edge_hsm_key_intf_sas_ut/CMakeLists.txt @@ -14,6 +14,7 @@ add_definitions(-DGB_DEBUG_ALLOC) set(${theseTestsName}_test_files ../../src/edge_hsm_key_interface.c + ../../src/edge_sas_perform_sign_with_key.c ../../src/edge_sas_key.c ../../src/hsm_log.c ../../src/constants.c @@ -21,7 +22,7 @@ set(${theseTestsName}_test_files ) set(${theseTestsName}_h_files - + ../../src/edge_sas_perform_sign_with_key.h ) build_c_test_artifacts(${theseTestsName} ON "tests/azure_c_shared_utility_tests") diff --git a/edgelet/hsm-sys/azure-iot-hsm-c/tests/edge_hsm_key_intf_sas_ut/edge_hsm_key_intf_sas_ut.c b/edgelet/hsm-sys/azure-iot-hsm-c/tests/edge_hsm_key_intf_sas_ut/edge_hsm_key_intf_sas_ut.c index ba82a51db3d..1b8342695b6 100644 --- a/edgelet/hsm-sys/azure-iot-hsm-c/tests/edge_hsm_key_intf_sas_ut/edge_hsm_key_intf_sas_ut.c +++ b/edgelet/hsm-sys/azure-iot-hsm-c/tests/edge_hsm_key_intf_sas_ut/edge_hsm_key_intf_sas_ut.c @@ -52,6 +52,7 @@ static void test_hook_gballoc_free(void* ptr) #include "hsm_client_data.h" #include "hsm_key.h" +#include "edge_sas_perform_sign_with_key.h" //############################################################################# // Test defines and data @@ -426,7 +427,7 @@ BEGIN_TEST_SUITE(edge_hsm_key_interface_sas_key_unittests) status = key_if->hsm_client_key_sign(key_handle, data_to_be_signed, data_len, &digest, &digest_size); // assert - ASSERT_ARE_EQUAL_WITH_MSG(int, 1, status, "Line:" TOSTRING(__LINE__)); + ASSERT_ARE_NOT_EQUAL_WITH_MSG(int, 0, status, "Line:" TOSTRING(__LINE__)); } //cleanup @@ -532,11 +533,11 @@ BEGIN_TEST_SUITE(edge_hsm_key_interface_sas_key_unittests) // assert ASSERT_ARE_EQUAL_WITH_MSG(int, 0, status, "Line:" TOSTRING(__LINE__)); - ASSERT_ARE_EQUAL_WITH_MSG(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls(), "Line:" TOSTRING(__LINE__)); - ASSERT_ARE_EQUAL_WITH_MSG(size_t, sizeof(TEST_DERIVED_DIGEST_DATA), digest_size, "Line:" TOSTRING(__LINE__)); + status = memcmp(TEST_DERIVED_DIGEST_DATA, digest, sizeof(TEST_DERIVED_DIGEST_DATA)); ASSERT_ARE_EQUAL_WITH_MSG(int, 0, status, "Line:" TOSTRING(__LINE__)); - + ASSERT_ARE_EQUAL_WITH_MSG(size_t, sizeof(TEST_DERIVED_DIGEST_DATA), digest_size, "Line:" TOSTRING(__LINE__)); + ASSERT_ARE_EQUAL_WITH_MSG(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls(), "Line:" TOSTRING(__LINE__)); // cleanup test_hook_gballoc_free(digest); test_helper_destroy_key(key_handle); @@ -600,7 +601,7 @@ BEGIN_TEST_SUITE(edge_hsm_key_interface_sas_key_unittests) status = key_if->hsm_client_key_derive_and_sign(key_handle, data_to_be_signed, data_len, identity, identity_size, &digest, &digest_size); // assert - ASSERT_ARE_EQUAL_WITH_MSG(int, 1, status, "Line:" TOSTRING(__LINE__)); + ASSERT_ARE_NOT_EQUAL_WITH_MSG(int, 0, status, "Line:" TOSTRING(__LINE__)); } } diff --git a/edgelet/hsm-sys/azure-iot-hsm-c/tests/edge_hsm_tpm_ut/CMakeLists.txt b/edgelet/hsm-sys/azure-iot-hsm-c/tests/edge_hsm_tpm_ut/CMakeLists.txt index 16bab3dec89..47097664939 100644 --- a/edgelet/hsm-sys/azure-iot-hsm-c/tests/edge_hsm_tpm_ut/CMakeLists.txt +++ b/edgelet/hsm-sys/azure-iot-hsm-c/tests/edge_hsm_tpm_ut/CMakeLists.txt @@ -13,13 +13,14 @@ include_directories(../../src) add_definitions(-DGB_DEBUG_ALLOC) set(${theseTestsName}_test_files - ../../src/edge_hsm_client_tpm.c + ../../src/hsm_client_tpm_in_mem.c ../../src/hsm_log.c ../../src/constants.c ${theseTestsName}.c ) set(${theseTestsName}_h_files + ../../src/hsm_client_tpm_in_mem.h ) diff --git a/edgelet/hsm-sys/azure-iot-hsm-c/tests/edge_hsm_tpm_ut/edge_hsm_tpm_ut.c b/edgelet/hsm-sys/azure-iot-hsm-c/tests/edge_hsm_tpm_ut/edge_hsm_tpm_ut.c index d0463c24e2a..cc257c5ef6e 100644 --- a/edgelet/hsm-sys/azure-iot-hsm-c/tests/edge_hsm_tpm_ut/edge_hsm_tpm_ut.c +++ b/edgelet/hsm-sys/azure-iot-hsm-c/tests/edge_hsm_tpm_ut/edge_hsm_tpm_ut.c @@ -83,6 +83,7 @@ MOCKABLE_FUNCTION(, const HSM_CLIENT_KEY_INTERFACE*, hsm_client_key_interface); // Interface(s) under test //############################################################################# #include "hsm_client_data.h" +#include "hsm_client_tpm_in_mem.h" //############################################################################# // Test defines and data @@ -450,7 +451,7 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) /** * Test function for API - * hsm_client_tpm_init + * hsm_client_tpm_store_init */ TEST_FUNCTION(hsm_client_tpm_init_success) { @@ -461,19 +462,19 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) STRICT_EXPECTED_CALL(mocked_hsm_client_store_create(TEST_EDGE_STORE_NAME)); // act - status = hsm_client_tpm_init(); + status = hsm_client_tpm_store_init(); // assert ASSERT_ARE_EQUAL_WITH_MSG(int, 0, status, "Line:" TOSTRING(__LINE__)); ASSERT_ARE_EQUAL_WITH_MSG(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls(), "Line:" TOSTRING(__LINE__)); //cleanup - hsm_client_tpm_deinit(); + hsm_client_tpm_store_deinit(); } /** * Test function for API - * hsm_client_tpm_init + * hsm_client_tpm_store_init */ TEST_FUNCTION(hsm_client_tpm_init_negative) { @@ -494,7 +495,7 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) umock_c_negative_tests_fail_call(i); // act - status = hsm_client_tpm_init(); + status = hsm_client_tpm_store_init(); // assert ASSERT_ARE_NOT_EQUAL_WITH_MSG(int, 0, status, "Line:" TOSTRING(__LINE__)); @@ -506,38 +507,38 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) /** * Test function for API - * hsm_client_tpm_init + * hsm_client_tpm_store_init */ TEST_FUNCTION(hsm_client_tpm_init_multiple_times_fails) { //arrange int status; - (void)hsm_client_tpm_init(); + (void)hsm_client_tpm_store_init(); umock_c_reset_all_calls(); // act - status = hsm_client_tpm_init(); + status = hsm_client_tpm_store_init(); // assert ASSERT_ARE_NOT_EQUAL_WITH_MSG(int, 0, status, "Line:" TOSTRING(__LINE__)); ASSERT_ARE_EQUAL_WITH_MSG(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls(), "Line:" TOSTRING(__LINE__)); //cleanup - hsm_client_tpm_deinit(); + hsm_client_tpm_store_deinit(); } /** * Test function for API - * hsm_client_tpm_deinit + * hsm_client_tpm_store_deinit */ - TEST_FUNCTION(hsm_client_tpm_deinit_success) + TEST_FUNCTION(hsm_client_tpm_store_deinit_success) { //arrange - (void)hsm_client_tpm_init(); + (void)hsm_client_tpm_store_init(); umock_c_reset_all_calls(); // act - hsm_client_tpm_deinit(); + hsm_client_tpm_store_deinit(); // assert ASSERT_ARE_EQUAL_WITH_MSG(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls(), "Line:" TOSTRING(__LINE__)); @@ -547,15 +548,15 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) /** * Test function for API - * hsm_client_tpm_init - * hsm_client_tpm_deinit + * hsm_client_tpm_store_init + * hsm_client_tpm_store_deinit */ TEST_FUNCTION(hsm_client_tpm_init_deinit_init_success) { //arrange int status; - hsm_client_tpm_init(); - hsm_client_tpm_deinit(); + hsm_client_tpm_store_init(); + hsm_client_tpm_store_deinit(); umock_c_reset_all_calls(); EXPECTED_CALL(hsm_client_store_interface()); @@ -563,26 +564,26 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) STRICT_EXPECTED_CALL(mocked_hsm_client_store_create(TEST_EDGE_STORE_NAME)); // act - status = hsm_client_tpm_init(); + status = hsm_client_tpm_store_init(); // assert ASSERT_ARE_EQUAL_WITH_MSG(int, 0, status, "Line:" TOSTRING(__LINE__)); ASSERT_ARE_EQUAL_WITH_MSG(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls(), "Line:" TOSTRING(__LINE__)); //cleanup - hsm_client_tpm_deinit(); + hsm_client_tpm_store_deinit(); } /** * Test function for API - * hsm_client_tpm_interface + * hsm_client_tpm_store_interface */ TEST_FUNCTION(hsm_client_tpm_interface_success) { //arrange // act - const HSM_CLIENT_TPM_INTERFACE* result = hsm_client_tpm_interface(); + const HSM_CLIENT_TPM_INTERFACE* result = hsm_client_tpm_store_interface(); // assert ASSERT_IS_NOT_NULL_WITH_MSG(result, "Line:" TOSTRING(__LINE__)); @@ -606,7 +607,7 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) { //arrange int status; - const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_interface(); + const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_store_interface(); HSM_CLIENT_CREATE hsm_client_tpm_create = interface->hsm_client_tpm_create; umock_c_reset_all_calls(); @@ -626,9 +627,9 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) { //arrange int status; - status = hsm_client_tpm_init(); + status = hsm_client_tpm_store_init(); ASSERT_ARE_EQUAL_WITH_MSG(int, 0, status, "Line:" TOSTRING(__LINE__)); - const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_interface(); + const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_store_interface(); HSM_CLIENT_CREATE hsm_client_tpm_create = interface->hsm_client_tpm_create; HSM_CLIENT_DESTROY hsm_client_tpm_destroy = interface->hsm_client_tpm_destroy; umock_c_reset_all_calls(); @@ -645,7 +646,7 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) //cleanup hsm_client_tpm_destroy(hsm_handle); - hsm_client_tpm_deinit(); + hsm_client_tpm_store_deinit(); } /** @@ -659,9 +660,9 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) int test_result = umock_c_negative_tests_init(); ASSERT_ARE_EQUAL(int, 0, test_result); - status = hsm_client_tpm_init(); + status = hsm_client_tpm_store_init(); ASSERT_ARE_EQUAL_WITH_MSG(int, 0, status, "Line:" TOSTRING(__LINE__)); - const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_interface(); + const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_store_interface(); HSM_CLIENT_CREATE hsm_client_tpm_create = interface->hsm_client_tpm_create; HSM_CLIENT_DESTROY hsm_client_tpm_destroy = interface->hsm_client_tpm_destroy; umock_c_reset_all_calls(); @@ -684,7 +685,7 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) } //cleanup - hsm_client_tpm_deinit(); + hsm_client_tpm_store_deinit(); umock_c_negative_tests_deinit(); } @@ -695,7 +696,7 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) TEST_FUNCTION(edge_hsm_client_tpm_destroy_does_nothing_with_invalid_handle) { //arrange - const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_interface(); + const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_store_interface(); HSM_CLIENT_DESTROY hsm_client_tpm_destroy = interface->hsm_client_tpm_destroy; // act @@ -712,7 +713,7 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) TEST_FUNCTION(edge_hsm_client_tpm_destroy_does_nothing_when_tpm_not_initialized) { //arrange - const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_interface(); + const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_store_interface(); HSM_CLIENT_DESTROY hsm_client_tpm_destroy = interface->hsm_client_tpm_destroy; // act @@ -730,9 +731,9 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) { //arrange int status; - status = hsm_client_tpm_init(); + status = hsm_client_tpm_store_init(); ASSERT_ARE_EQUAL_WITH_MSG(int, 0, status, "Line:" TOSTRING(__LINE__)); - const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_interface(); + const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_store_interface(); HSM_CLIENT_CREATE hsm_client_tpm_create = interface->hsm_client_tpm_create; HSM_CLIENT_DESTROY hsm_client_tpm_destroy = interface->hsm_client_tpm_destroy; HSM_CLIENT_HANDLE hsm_handle = hsm_client_tpm_create(); @@ -749,7 +750,7 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) ASSERT_ARE_EQUAL_WITH_MSG(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls(), "Line:" TOSTRING(__LINE__)); //cleanup - hsm_client_tpm_deinit(); + hsm_client_tpm_store_deinit(); } /** @@ -760,9 +761,9 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) { //arrange int status; - status = hsm_client_tpm_init(); + status = hsm_client_tpm_store_init(); ASSERT_ARE_EQUAL_WITH_MSG(int, 0, status, "Line:" TOSTRING(__LINE__)); - const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_interface(); + const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_store_interface(); HSM_CLIENT_CREATE hsm_client_tpm_create = interface->hsm_client_tpm_create; HSM_CLIENT_DESTROY hsm_client_tpm_destroy = interface->hsm_client_tpm_destroy; HSM_CLIENT_ACTIVATE_IDENTITY_KEY hsm_client_activate_identity_key = interface->hsm_client_activate_identity_key; @@ -779,7 +780,7 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) //cleanup hsm_client_tpm_destroy(hsm_handle); - hsm_client_tpm_deinit(); + hsm_client_tpm_store_deinit(); } /** @@ -790,9 +791,9 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) { //arrange int status; - status = hsm_client_tpm_init(); + status = hsm_client_tpm_store_init(); ASSERT_ARE_EQUAL_WITH_MSG(int, 0, status, "Line:" TOSTRING(__LINE__)); - const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_interface(); + const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_store_interface(); HSM_CLIENT_CREATE hsm_client_tpm_create = interface->hsm_client_tpm_create; HSM_CLIENT_DESTROY hsm_client_tpm_destroy = interface->hsm_client_tpm_destroy; HSM_CLIENT_ACTIVATE_IDENTITY_KEY hsm_client_activate_identity_key = interface->hsm_client_activate_identity_key; @@ -811,7 +812,7 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) //cleanup hsm_client_tpm_destroy(hsm_handle); - hsm_client_tpm_deinit(); + hsm_client_tpm_store_deinit(); } /** @@ -825,9 +826,9 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) int test_result = umock_c_negative_tests_init(); ASSERT_ARE_EQUAL(int, 0, test_result); - status = hsm_client_tpm_init(); + status = hsm_client_tpm_store_init(); ASSERT_ARE_EQUAL_WITH_MSG(int, 0, status, "Line:" TOSTRING(__LINE__)); - const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_interface(); + const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_store_interface(); HSM_CLIENT_CREATE hsm_client_tpm_create = interface->hsm_client_tpm_create; HSM_CLIENT_DESTROY hsm_client_tpm_destroy = interface->hsm_client_tpm_destroy; HSM_CLIENT_ACTIVATE_IDENTITY_KEY hsm_client_activate_identity_key = interface->hsm_client_activate_identity_key; @@ -853,7 +854,7 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) //cleanup hsm_client_tpm_destroy(hsm_handle); - hsm_client_tpm_deinit(); + hsm_client_tpm_store_deinit(); umock_c_negative_tests_deinit(); } @@ -864,7 +865,7 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) TEST_FUNCTION(edge_hsm_client_get_ek_does_nothing_when_tpm_not_initialized) { //arrange - const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_interface(); + const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_store_interface(); HSM_CLIENT_GET_ENDORSEMENT_KEY hsm_client_get_ek = interface->hsm_client_get_ek; int status; unsigned char *test_output_buffer = (unsigned char*)0x5000; @@ -888,9 +889,9 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) TEST_FUNCTION(edge_hsm_client_get_ek_success) { //arrange - int status = hsm_client_tpm_init(); + int status = hsm_client_tpm_store_init(); ASSERT_ARE_EQUAL_WITH_MSG(int, 0, status, "Line:" TOSTRING(__LINE__)); - const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_interface(); + const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_store_interface(); HSM_CLIENT_CREATE hsm_client_tpm_create = interface->hsm_client_tpm_create; HSM_CLIENT_DESTROY hsm_client_tpm_destroy = interface->hsm_client_tpm_destroy; HSM_CLIENT_GET_ENDORSEMENT_KEY hsm_client_get_ek = interface->hsm_client_get_ek; @@ -910,7 +911,7 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) //cleanup hsm_client_tpm_destroy(hsm_handle); - hsm_client_tpm_deinit(); + hsm_client_tpm_store_deinit(); } /** @@ -920,9 +921,9 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) TEST_FUNCTION(edge_hsm_client_get_ek_invalid_param_validation) { //arrange - int status = hsm_client_tpm_init(); + int status = hsm_client_tpm_store_init(); ASSERT_ARE_EQUAL_WITH_MSG(int, 0, status, "Line:" TOSTRING(__LINE__)); - const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_interface(); + const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_store_interface(); HSM_CLIENT_CREATE hsm_client_tpm_create = interface->hsm_client_tpm_create; HSM_CLIENT_DESTROY hsm_client_tpm_destroy = interface->hsm_client_tpm_destroy; HSM_CLIENT_GET_ENDORSEMENT_KEY hsm_client_get_ek = interface->hsm_client_get_ek; @@ -950,7 +951,7 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) //cleanup hsm_client_tpm_destroy(hsm_handle); - hsm_client_tpm_deinit(); + hsm_client_tpm_store_deinit(); } /** @@ -960,7 +961,7 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) TEST_FUNCTION(edge_hsm_client_get_srk_does_nothing_when_tpm_not_initialized) { //arrange - const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_interface(); + const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_store_interface(); HSM_CLIENT_GET_STORAGE_ROOT_KEY hsm_client_get_srk = interface->hsm_client_get_srk; unsigned char *test_output_buffer = (unsigned char*)0x5000; size_t test_output_len = 10; @@ -984,9 +985,9 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) TEST_FUNCTION(edge_hsm_client_get_srk_success) { //arrange - int status = hsm_client_tpm_init(); + int status = hsm_client_tpm_store_init(); ASSERT_ARE_EQUAL_WITH_MSG(int, 0, status, "Line:" TOSTRING(__LINE__)); - const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_interface(); + const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_store_interface(); HSM_CLIENT_CREATE hsm_client_tpm_create = interface->hsm_client_tpm_create; HSM_CLIENT_DESTROY hsm_client_tpm_destroy = interface->hsm_client_tpm_destroy; HSM_CLIENT_GET_STORAGE_ROOT_KEY hsm_client_get_srk = interface->hsm_client_get_srk; @@ -1006,7 +1007,7 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) //cleanup hsm_client_tpm_destroy(hsm_handle); - hsm_client_tpm_deinit(); + hsm_client_tpm_store_deinit(); } /** @@ -1016,9 +1017,9 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) TEST_FUNCTION(edge_hsm_client_get_srk_invalid_param_validation) { //arrange - int status = hsm_client_tpm_init(); + int status = hsm_client_tpm_store_init(); ASSERT_ARE_EQUAL_WITH_MSG(int, 0, status, "Line:" TOSTRING(__LINE__)); - const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_interface(); + const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_store_interface(); HSM_CLIENT_CREATE hsm_client_tpm_create = interface->hsm_client_tpm_create; HSM_CLIENT_DESTROY hsm_client_tpm_destroy = interface->hsm_client_tpm_destroy; HSM_CLIENT_GET_STORAGE_ROOT_KEY hsm_client_get_srk = interface->hsm_client_get_srk; @@ -1046,7 +1047,7 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) //cleanup hsm_client_tpm_destroy(hsm_handle); - hsm_client_tpm_deinit(); + hsm_client_tpm_store_deinit(); } /** @@ -1057,7 +1058,7 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) { //arrange int status; - const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_interface(); + const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_store_interface(); HSM_CLIENT_SIGN_WITH_IDENTITY hsm_client_sign_with_identity = interface->hsm_client_sign_with_identity; unsigned char test_input[] = {'t', 'e', 's', 't'}; unsigned char *test_output_buffer = TEST_OUTPUT_DIGEST_PTR; @@ -1082,9 +1083,9 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) TEST_FUNCTION(edge_hsm_client_sign_with_identity_invalid_param_validation) { //arrange - int status = hsm_client_tpm_init(); + int status = hsm_client_tpm_store_init(); ASSERT_ARE_EQUAL_WITH_MSG(int, 0, status, "Line:" TOSTRING(__LINE__)); - const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_interface(); + const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_store_interface(); HSM_CLIENT_CREATE hsm_client_tpm_create = interface->hsm_client_tpm_create; HSM_CLIENT_DESTROY hsm_client_tpm_destroy = interface->hsm_client_tpm_destroy; HSM_CLIENT_SIGN_WITH_IDENTITY hsm_client_sign_with_identity = interface->hsm_client_sign_with_identity; @@ -1127,7 +1128,7 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) //cleanup hsm_client_tpm_destroy(hsm_handle); - hsm_client_tpm_deinit(); + hsm_client_tpm_store_deinit(); } /** @@ -1137,9 +1138,9 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) TEST_FUNCTION(edge_hsm_client_sign_with_identity_success) { //arrange - int status = hsm_client_tpm_init(); + int status = hsm_client_tpm_store_init(); ASSERT_ARE_EQUAL_WITH_MSG(int, 0, status, "Line:" TOSTRING(__LINE__)); - const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_interface(); + const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_store_interface(); HSM_CLIENT_CREATE hsm_client_tpm_create = interface->hsm_client_tpm_create; HSM_CLIENT_DESTROY hsm_client_tpm_destroy = interface->hsm_client_tpm_destroy; HSM_CLIENT_SIGN_WITH_IDENTITY hsm_client_sign_with_identity = interface->hsm_client_sign_with_identity; @@ -1162,7 +1163,7 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) //cleanup hsm_client_tpm_destroy(hsm_handle); - hsm_client_tpm_deinit(); + hsm_client_tpm_store_deinit(); } /** @@ -1174,9 +1175,9 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) //arrange int test_result = umock_c_negative_tests_init(); ASSERT_ARE_EQUAL(int, 0, test_result); - int status = hsm_client_tpm_init(); + int status = hsm_client_tpm_store_init(); ASSERT_ARE_EQUAL_WITH_MSG(int, 0, status, "Line:" TOSTRING(__LINE__)); - const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_interface(); + const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_store_interface(); HSM_CLIENT_CREATE hsm_client_tpm_create = interface->hsm_client_tpm_create; HSM_CLIENT_DESTROY hsm_client_tpm_destroy = interface->hsm_client_tpm_destroy; HSM_CLIENT_SIGN_WITH_IDENTITY hsm_client_sign_with_identity = interface->hsm_client_sign_with_identity; @@ -1206,7 +1207,7 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) //cleanup hsm_client_tpm_destroy(hsm_handle); - hsm_client_tpm_deinit(); + hsm_client_tpm_store_deinit(); umock_c_negative_tests_deinit(); } @@ -1218,7 +1219,7 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) { //arrange int status; - const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_interface(); + const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_store_interface(); HSM_CLIENT_DERIVE_AND_SIGN_WITH_IDENTITY hsm_client_derive_and_sign_with_identity = interface->hsm_client_derive_and_sign_with_identity; unsigned char test_input[] = {'t', 'e', 's', 't'}; unsigned char *test_output_buffer = NULL; @@ -1243,9 +1244,9 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) TEST_FUNCTION(edge_hsm_client_derive_and_sign_with_identity_invalid_param_validation) { //arrange - int status = hsm_client_tpm_init(); + int status = hsm_client_tpm_store_init(); ASSERT_ARE_EQUAL_WITH_MSG(int, 0, status, "Line:" TOSTRING(__LINE__)); - const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_interface(); + const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_store_interface(); HSM_CLIENT_CREATE hsm_client_tpm_create = interface->hsm_client_tpm_create; HSM_CLIENT_DESTROY hsm_client_tpm_destroy = interface->hsm_client_tpm_destroy; HSM_CLIENT_DERIVE_AND_SIGN_WITH_IDENTITY hsm_client_derive_and_sign_with_identity = interface->hsm_client_derive_and_sign_with_identity; @@ -1305,7 +1306,7 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) //cleanup hsm_client_tpm_destroy(hsm_handle); - hsm_client_tpm_deinit(); + hsm_client_tpm_store_deinit(); } /** @@ -1315,9 +1316,9 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) TEST_FUNCTION(edge_hsm_client_derive_and_sign_with_identity_success) { //arrange - int status = hsm_client_tpm_init(); + int status = hsm_client_tpm_store_init(); ASSERT_ARE_EQUAL_WITH_MSG(int, 0, status, "Line:" TOSTRING(__LINE__)); - const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_interface(); + const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_store_interface(); HSM_CLIENT_CREATE hsm_client_tpm_create = interface->hsm_client_tpm_create; HSM_CLIENT_DESTROY hsm_client_tpm_destroy = interface->hsm_client_tpm_destroy; HSM_CLIENT_DERIVE_AND_SIGN_WITH_IDENTITY hsm_client_derive_and_sign_with_identity = interface->hsm_client_derive_and_sign_with_identity; @@ -1342,7 +1343,7 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) //cleanup hsm_client_tpm_destroy(hsm_handle); - hsm_client_tpm_deinit(); + hsm_client_tpm_store_deinit(); } /** @@ -1354,9 +1355,9 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) //arrange int test_result = umock_c_negative_tests_init(); ASSERT_ARE_EQUAL(int, 0, test_result); - int status = hsm_client_tpm_init(); + int status = hsm_client_tpm_store_init(); ASSERT_ARE_EQUAL_WITH_MSG(int, 0, status, "Line:" TOSTRING(__LINE__)); - const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_interface(); + const HSM_CLIENT_TPM_INTERFACE* interface = hsm_client_tpm_store_interface(); HSM_CLIENT_CREATE hsm_client_tpm_create = interface->hsm_client_tpm_create; HSM_CLIENT_DESTROY hsm_client_tpm_destroy = interface->hsm_client_tpm_destroy; HSM_CLIENT_DERIVE_AND_SIGN_WITH_IDENTITY hsm_client_derive_and_sign_with_identity = interface->hsm_client_derive_and_sign_with_identity; @@ -1388,7 +1389,7 @@ BEGIN_TEST_SUITE(edge_hsm_tpm_unittests) //cleanup hsm_client_tpm_destroy(hsm_handle); - hsm_client_tpm_deinit(); + hsm_client_tpm_store_deinit(); umock_c_negative_tests_deinit(); } diff --git a/edgelet/hsm-sys/azure-iot-hsm-c/tests/hsm_client_tpm_ut/CMakeLists.txt b/edgelet/hsm-sys/azure-iot-hsm-c/tests/hsm_client_tpm_ut/CMakeLists.txt new file mode 100644 index 00000000000..bbf90effdef --- /dev/null +++ b/edgelet/hsm-sys/azure-iot-hsm-c/tests/hsm_client_tpm_ut/CMakeLists.txt @@ -0,0 +1,26 @@ +#Copyright (c) Microsoft. All rights reserved. +#Licensed under the MIT license. See LICENSE file in the project root for full license information. + +#this is CMakeLists.txt for device_auth_ut +cmake_minimum_required(VERSION 2.8.11) + +include_directories(../../src) + +compileAsC11() +set(theseTestsName hsm_client_tpm_ut) + +set(${theseTestsName}_test_files + ${theseTestsName}.c +) + +set(${theseTestsName}_c_files + ../../src/hsm_client_tpm_device.c + ../../src/hsm_log.c + ../../src/constants.c +) + +set(${theseTestsName}_h_files + ../../src/hsm_client_tpm_device.h +) + +build_c_test_artifacts(${theseTestsName} ON "tests") diff --git a/edgelet/hsm-sys/azure-iot-hsm-c/tests/hsm_client_tpm_ut/hsm_client_tpm_ut.c b/edgelet/hsm-sys/azure-iot-hsm-c/tests/hsm_client_tpm_ut/hsm_client_tpm_ut.c new file mode 100644 index 00000000000..6d200d5fed8 --- /dev/null +++ b/edgelet/hsm-sys/azure-iot-hsm-c/tests/hsm_client_tpm_ut/hsm_client_tpm_ut.c @@ -0,0 +1,1180 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +#ifdef __cplusplus +#include +#include +#include +#else +#include +#include +#include +#endif + +static void* my_gballoc_malloc(size_t size) +{ + return malloc(size); +} + +static void my_gballoc_free(void* ptr) +{ + free(ptr); +} + +#include "testrunnerswitcher.h" +#include "umock_c.h" +#include "umocktypes_charptr.h" +#include "umocktypes_stdint.h" +#include "umocktypes_bool.h" +#include "umock_c_negative_tests.h" +#include "azure_c_shared_utility/macro_utils.h" + +#define ENABLE_MOCKS +#include "azure_c_shared_utility/gballoc.h" +#include "azure_c_shared_utility/umock_c_prod.h" +#include "azure_c_shared_utility/crt_abstractions.h" +#include "azure_c_shared_utility/strings.h" +#include "azure_c_shared_utility/sastoken.h" +#include "azure_c_shared_utility/base64.h" +#include "azure_c_shared_utility/sha.h" +#include "azure_c_shared_utility/urlencode.h" + +#include "azure_utpm_c/tpm_codec.h" +#include "azure_utpm_c/Marshal_fp.h" + +#include "edge_sas_perform_sign_with_key.h" + +#include "azure_utpm_c/TpmTypes.h" +#undef ENABLE_MOCKS + +#include "hsm_client_data.h" +#include "hsm_log.h" +#include "hsm_client_tpm_device.h" + +static const char* TEST_STRING_VALUE = "Test_String_Value"; +static const unsigned char TEST_IMPORT_KEY[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10 }; + +static const char* TEST_RSA_KEY = "1234567890"; +static unsigned char TEST_BUFFER[128]; +static unsigned char IDENTITY_BUFFER[128]; + +static uint16_t g_rsa_size; + +#define TEST_BUFFER_SIZE 128 +#define IDENTITY_BUFFER_SIZE 128 +#define TEST_KEY_SIZE 10 + +static void my_STRING_delete(STRING_HANDLE h) +{ + my_gballoc_free((void*)h); +} + +static TPM_HANDLE my_TSS_CreatePersistentKey(TSS_DEVICE* tpm_device, TPM_HANDLE request_handle, TSS_SESSION* sess, TPMI_DH_OBJECT hierarchy, TPM2B_PUBLIC* inPub, TPM2B_PUBLIC* outPub) +{ + (void)tpm_device; + (void)request_handle; + (void)sess; + (void)hierarchy; + (void)inPub; + + (*outPub).publicArea.unique.rsa.t.size = g_rsa_size; + return (TPM_HANDLE)0x1; +} + +static TPM_RC my_TSS_CreatePrimary(TSS_DEVICE *tpm, TSS_SESSION *sess, TPM_HANDLE hierarchy, TPM2B_PUBLIC *inPub, TPM_HANDLE *outHandle, TPM2B_PUBLIC *outPub) +{ + (void)tpm; + (void)sess; + (void)hierarchy; + (void)inPub; + (void)outHandle; + + (*outPub).publicArea.unique.rsa.t.size = g_rsa_size; + return TPM_RC_SUCCESS; +} + +static int my_mallocAndStrcpy_s(char** destination, const char* source) +{ + (void)source; + size_t src_len = strlen(source); + *destination = (char*)my_gballoc_malloc(src_len + 1); + strcpy(*destination, source); + return 0; +} + +static int my_perform_sign_with_key( const unsigned char* key, size_t key_len, + const unsigned char* data_to_be_signed, size_t data_to_be_signed_size, + unsigned char** digest, size_t* digest_size) +{ + (void)key; + (void)key_len; + (void)data_to_be_signed; + (void)data_to_be_signed_size; + *digest = my_gballoc_malloc(1); + *digest_size = 1; + return 0; +} + +/*static BUFFER_HANDLE my_Base64_Decoder(const char* source) +{ + (void)source; + return (BUFFER_HANDLE)my_gballoc_malloc(1); +}*/ + +STRING_HANDLE my_Base64_Encode_Bytes(const unsigned char* source, size_t size) +{ + (void)source; + (void)size; + return (STRING_HANDLE)my_gballoc_malloc(1); +} + +DEFINE_ENUM_STRINGS(UMOCK_C_ERROR_CODE, UMOCK_C_ERROR_CODE_VALUES) + +static void on_umock_c_error(UMOCK_C_ERROR_CODE error_code) +{ + char temp_str[256]; + (void)snprintf(temp_str, sizeof(temp_str), "umock_c reported error :%s", ENUM_TO_STRING(UMOCK_C_ERROR_CODE, error_code)); + ASSERT_FAIL(temp_str); +} + +static TEST_MUTEX_HANDLE g_testByTest; +static TEST_MUTEX_HANDLE g_dllByDll; + +BEGIN_TEST_SUITE(hsm_client_tpm_ut) + + TEST_SUITE_INITIALIZE(suite_init) + { + int result; + + TEST_INITIALIZE_MEMORY_DEBUG(g_dllByDll); + g_testByTest = TEST_MUTEX_CREATE(); + ASSERT_IS_NOT_NULL(g_testByTest); + + (void)umock_c_init(on_umock_c_error); + + result = umocktypes_charptr_register_types(); + ASSERT_ARE_EQUAL(int, 0, result); + result = umocktypes_stdint_register_types(); + ASSERT_ARE_EQUAL(int, 0, result); + result = umocktypes_bool_register_types(); + ASSERT_ARE_EQUAL(int, 0, result); + + REGISTER_UMOCK_ALIAS_TYPE(XDA_HANDLE, void*); + REGISTER_UMOCK_ALIAS_TYPE(BUFFER_HANDLE, void*); + REGISTER_UMOCK_ALIAS_TYPE(TPM_HANDLE, void*); + REGISTER_UMOCK_ALIAS_TYPE(UINT, unsigned int); + REGISTER_UMOCK_ALIAS_TYPE(UINT32, unsigned int); + REGISTER_UMOCK_ALIAS_TYPE(BOOL, int); + REGISTER_UMOCK_ALIAS_TYPE(TPM_PT, unsigned int); + + REGISTER_UMOCK_ALIAS_TYPE(HSM_CLIENT_HANDLE, void*); + REGISTER_UMOCK_ALIAS_TYPE(SECURE_DEVICE_TYPE, int); + REGISTER_UMOCK_ALIAS_TYPE(STRING_HANDLE, void*); + REGISTER_UMOCK_ALIAS_TYPE(OBJECT_ATTR, int); + REGISTER_UMOCK_ALIAS_TYPE(TPM_SE, int); + REGISTER_UMOCK_ALIAS_TYPE(TPMI_DH_OBJECT, void*); + REGISTER_UMOCK_ALIAS_TYPE(TPMI_ALG_HASH, void*); + REGISTER_UMOCK_ALIAS_TYPE(TPMA_SESSION, void*); + REGISTER_UMOCK_ALIAS_TYPE(TPMI_DH_ENTITY, void*); + REGISTER_UMOCK_ALIAS_TYPE(TPMI_DH_CONTEXT, void*); + REGISTER_UMOCK_ALIAS_TYPE(INT32, int); + REGISTER_UMOCK_ALIAS_TYPE(TPMI_RH_PROVISION, void*); + REGISTER_UMOCK_ALIAS_TYPE(TPMI_DH_PERSISTENT, void*); + + REGISTER_GLOBAL_MOCK_RETURN(TSS_CreatePwAuthSession, TPM_RC_SUCCESS); + REGISTER_GLOBAL_MOCK_FAIL_RETURN(TSS_CreatePwAuthSession, TPM_RC_FAILURE); + REGISTER_GLOBAL_MOCK_RETURN(Initialize_TPM_Codec, TPM_RC_SUCCESS); + REGISTER_GLOBAL_MOCK_FAIL_RETURN(Initialize_TPM_Codec, TPM_RC_FAILURE); + REGISTER_GLOBAL_MOCK_RETURN(TPM2_ReadPublic, TPM_RC_SUCCESS); + REGISTER_GLOBAL_MOCK_FAIL_RETURN(TPM2_ReadPublic, TPM_RC_FAILURE); + REGISTER_GLOBAL_MOCK_HOOK(TSS_CreatePrimary, my_TSS_CreatePrimary); + REGISTER_GLOBAL_MOCK_FAIL_RETURN(TSS_CreatePrimary, TPM_RC_FAILURE); + REGISTER_GLOBAL_MOCK_RETURN(TSS_Create, TPM_RC_SUCCESS); + REGISTER_GLOBAL_MOCK_FAIL_RETURN(TSS_Create, TPM_RC_FAILURE); + REGISTER_GLOBAL_MOCK_RETURN(TSS_GetTpmProperty, 1028); + + REGISTER_GLOBAL_MOCK_HOOK(TSS_CreatePersistentKey, my_TSS_CreatePersistentKey); + REGISTER_GLOBAL_MOCK_FAIL_RETURN(TSS_CreatePersistentKey, 0); + + REGISTER_GLOBAL_MOCK_RETURN(TSS_StartAuthSession, TPM_RC_SUCCESS); + REGISTER_GLOBAL_MOCK_FAIL_RETURN(TSS_StartAuthSession, TPM_RC_FAILURE); + REGISTER_GLOBAL_MOCK_RETURN(TSS_PolicySecret, TPM_RC_SUCCESS); + REGISTER_GLOBAL_MOCK_FAIL_RETURN(TSS_PolicySecret, TPM_RC_FAILURE); + REGISTER_GLOBAL_MOCK_RETURN(TPM2_ActivateCredential, TPM_RC_SUCCESS); + REGISTER_GLOBAL_MOCK_FAIL_RETURN(TPM2_ActivateCredential, TPM_RC_FAILURE); + REGISTER_GLOBAL_MOCK_RETURN(TPM2_Import, TPM_RC_SUCCESS); + REGISTER_GLOBAL_MOCK_FAIL_RETURN(TPM2_Import, TPM_RC_FAILURE); + REGISTER_GLOBAL_MOCK_RETURN(TPM2_Load, TPM_RC_SUCCESS); + REGISTER_GLOBAL_MOCK_FAIL_RETURN(TPM2_Load, TPM_RC_FAILURE); + REGISTER_GLOBAL_MOCK_RETURN(TPM2_EvictControl, TPM_RC_SUCCESS); + REGISTER_GLOBAL_MOCK_FAIL_RETURN(TPM2_EvictControl, TPM_RC_FAILURE); + REGISTER_GLOBAL_MOCK_RETURN(TPM2_FlushContext, TPM_RC_SUCCESS); + REGISTER_GLOBAL_MOCK_FAIL_RETURN(TPM2_FlushContext, TPM_RC_FAILURE); + REGISTER_GLOBAL_MOCK_RETURN(TPM2_ReadPublic, TPM_RC_HANDLE); + REGISTER_GLOBAL_MOCK_FAIL_RETURN(TPM2_ReadPublic, TPM_RC_FAILURE); + REGISTER_GLOBAL_MOCK_RETURN(SignData, TEST_BUFFER_SIZE); + REGISTER_GLOBAL_MOCK_FAIL_RETURN(SignData, 0); + + REGISTER_GLOBAL_MOCK_RETURN(STRING_c_str, TEST_STRING_VALUE); + REGISTER_GLOBAL_MOCK_HOOK(STRING_delete, my_STRING_delete); + + REGISTER_GLOBAL_MOCK_HOOK(Base64_Encode_Bytes, my_Base64_Encode_Bytes); + REGISTER_GLOBAL_MOCK_FAIL_RETURN(Base64_Encode_Bytes, NULL); + + REGISTER_GLOBAL_MOCK_HOOK(gballoc_malloc, my_gballoc_malloc); + REGISTER_GLOBAL_MOCK_FAIL_RETURN(gballoc_malloc, NULL); + REGISTER_GLOBAL_MOCK_HOOK(gballoc_free, my_gballoc_free); + REGISTER_GLOBAL_MOCK_HOOK(mallocAndStrcpy_s, my_mallocAndStrcpy_s); + REGISTER_GLOBAL_MOCK_FAIL_RETURN(mallocAndStrcpy_s, __LINE__); + + REGISTER_GLOBAL_MOCK_HOOK(perform_sign_with_key, my_perform_sign_with_key); + REGISTER_GLOBAL_MOCK_FAIL_RETURN(perform_sign_with_key, 1); + + for (size_t index = 0; index < 10; index++) + { + TEST_BUFFER[index] = (unsigned char)(index+1); + } + } + + TEST_SUITE_CLEANUP(suite_cleanup) + { + umock_c_deinit(); + + TEST_MUTEX_DESTROY(g_testByTest); + TEST_DEINITIALIZE_MEMORY_DEBUG(g_dllByDll); + } + + TEST_FUNCTION_INITIALIZE(method_init) + { + if (TEST_MUTEX_ACQUIRE(g_testByTest)) + { + ASSERT_FAIL("Could not acquire test serialization mutex."); + } + umock_c_reset_all_calls(); + g_rsa_size = TEST_KEY_SIZE; + } + + TEST_FUNCTION_CLEANUP(method_cleanup) + { + TEST_MUTEX_RELEASE(g_testByTest); + } + + static int should_skip_index(size_t current_index, const size_t skip_array[], size_t length) + { + int result = 0; + for (size_t index = 0; index < length; index++) + { + if (current_index == skip_array[index]) + { + result = __LINE__; + break; + } + } + return result; + } + + static void setup_hsm_client_tpm_create_mock() + { + OBJECT_ATTR tmp = FixedTPM; + STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); + STRICT_EXPECTED_CALL(TSS_CreatePwAuthSession(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(Initialize_TPM_Codec(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(ToTpmaObject(tmp)) + .IgnoreArgument_attrs(); + STRICT_EXPECTED_CALL(TSS_CreatePersistentKey(IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(ToTpmaObject(tmp)) + .IgnoreArgument_attrs(); + STRICT_EXPECTED_CALL(TSS_CreatePersistentKey(IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + } + + static void setup_hsm_client_tpm_activate_key_mock() + { + OBJECT_ATTR tmp = FixedTPM; + TPM_SE tmp_se = 0; + TPMA_SESSION tmp_session = { 0 }; + TPMI_DH_OBJECT tmp_dh = { 0 }; + TPMI_RH_PROVISION tmp_prov = { 0 }; + TPMI_DH_CONTEXT tmp_dh_ctx = { 0 }; + TPMI_DH_PERSISTENT tmp_dh_per = { 0 }; + + STRICT_EXPECTED_CALL(TSS_StartAuthSession(IGNORED_PTR_ARG, tmp_se, IGNORED_NUM_ARG, tmp_session, IGNORED_PTR_ARG)) + .IgnoreArgument_sessAttrs() + .IgnoreArgument_sessionType(); + STRICT_EXPECTED_CALL(TSS_PolicySecret(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG)); // 4 + + STRICT_EXPECTED_CALL(TPM2B_ID_OBJECT_Unmarshal(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); // 2 + STRICT_EXPECTED_CALL(TPM2B_ENCRYPTED_SECRET_Unmarshal(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(TPM2B_PRIVATE_Unmarshal(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(TPM2B_ENCRYPTED_SECRET_Unmarshal(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(TPM2B_PUBLIC_Unmarshal(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, TRUE)); + STRICT_EXPECTED_CALL(UINT16_Unmarshal(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); // 7 + + STRICT_EXPECTED_CALL(TPM2_ActivateCredential(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(TPM2_Import(IGNORED_PTR_ARG, IGNORED_PTR_ARG, tmp_dh, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)) + .IgnoreArgument_parentHandle(); + + STRICT_EXPECTED_CALL(ToTpmaObject(tmp)).IgnoreArgument_attrs(); // 10 + STRICT_EXPECTED_CALL(TSS_Create(IGNORED_PTR_ARG, IGNORED_PTR_ARG, tmp_dh, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)) + .IgnoreAllArguments(); + + STRICT_EXPECTED_CALL(TPM2_Load(IGNORED_PTR_ARG, IGNORED_PTR_ARG, tmp_dh, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)) + .IgnoreArgument_parentHandle(); // 12 + STRICT_EXPECTED_CALL(TPM2_EvictControl(IGNORED_PTR_ARG, IGNORED_PTR_ARG, tmp_prov, tmp_dh, tmp_dh_per)) + .IgnoreArgument_auth() + .IgnoreArgument_objectHandle() + .IgnoreArgument_persistentHandle(); + STRICT_EXPECTED_CALL(TPM2_EvictControl(IGNORED_PTR_ARG, IGNORED_PTR_ARG, tmp_prov, tmp_dh, tmp_dh_per)) + .IgnoreArgument_auth() + .IgnoreArgument_objectHandle() + .IgnoreArgument_persistentHandle(); + STRICT_EXPECTED_CALL(TPM2_FlushContext(IGNORED_PTR_ARG, tmp_dh_ctx)) // 15 + .IgnoreArgument_flushHandle(); + } + + static void setup_hsm_client_tpm_get_storage_key_mocks() + { + STRICT_EXPECTED_CALL(TPM2B_PUBLIC_Marshal(IGNORED_PTR_ARG, IGNORED_PTR_ARG, NULL)); + STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); + } + + static void setup_hsm_client_tpm_sign_data_mocks() + { + STRICT_EXPECTED_CALL(SignData(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG)); + STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); + } + + static void setup_hsm_client_tpm_get_endorsement_key_mocks() + { + STRICT_EXPECTED_CALL(TPM2B_PUBLIC_Marshal(IGNORED_PTR_ARG, IGNORED_PTR_ARG, NULL)); + STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); + } + + TEST_FUNCTION(hsm_client_tpm_create_succeed) + { + //arrange + setup_hsm_client_tpm_create_mock(); + + //act + const HSM_CLIENT_TPM_INTERFACE* tpm_if = hsm_client_tpm_device_interface(); + HSM_CLIENT_HANDLE sec_handle = tpm_if->hsm_client_tpm_create(); + + //assert + ASSERT_IS_NOT_NULL(sec_handle); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + + //cleanup + tpm_if->hsm_client_tpm_destroy(sec_handle); + } + + TEST_FUNCTION(hsm_client_tpm_create_fail) + { + //arrange + setup_hsm_client_tpm_create_mock(); + + int negativeTestsInitResult = umock_c_negative_tests_init(); + ASSERT_ARE_EQUAL(int, 0, negativeTestsInitResult); + + umock_c_negative_tests_snapshot(); + + size_t calls_cannot_fail[] = { 3, 5 }; + + const HSM_CLIENT_TPM_INTERFACE* tpm_if = hsm_client_tpm_device_interface(); + + //act + size_t count = umock_c_negative_tests_call_count(); + for (size_t index = 0; index < count; index++) + { + if (should_skip_index(index, calls_cannot_fail, sizeof(calls_cannot_fail) / sizeof(calls_cannot_fail[0])) != 0) + { + continue; + } + + umock_c_negative_tests_reset(); + umock_c_negative_tests_fail_call(index); + + char tmp_msg[64]; + sprintf(tmp_msg, "secure_device_riot_create failure in test %zu/%zu", index, count); + + //act + HSM_CLIENT_HANDLE sec_handle = tpm_if->hsm_client_tpm_create(); + + //assert + ASSERT_IS_NULL_WITH_MSG(sec_handle, tmp_msg); + } + + //cleanup + umock_c_negative_tests_deinit(); + } + + TEST_FUNCTION(hsm_client_tpm_destroy_succeed) + { + //arrange + const HSM_CLIENT_TPM_INTERFACE* tpm_if = hsm_client_tpm_device_interface(); + HSM_CLIENT_HANDLE sec_handle = tpm_if->hsm_client_tpm_create(); + umock_c_reset_all_calls(); + + STRICT_EXPECTED_CALL(Deinit_TPM_Codec(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG)); + + //act + tpm_if->hsm_client_tpm_destroy(sec_handle); + + //assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + + //cleanup + } + + TEST_FUNCTION(hsm_client_tpm_destroy_handle_NULL_succeed) + { + //arrange + umock_c_reset_all_calls(); + + //act + const HSM_CLIENT_TPM_INTERFACE* tpm_if = hsm_client_tpm_device_interface(); + tpm_if->hsm_client_tpm_destroy(NULL); + + //assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + + //cleanup + } + + TEST_FUNCTION(hsm_client_tpm_activate_key_handle_NULL_fail) + { + //arrange + + //act + const HSM_CLIENT_TPM_INTERFACE* tpm_if = hsm_client_tpm_device_interface(); + int import_res = tpm_if->hsm_client_activate_identity_key(NULL, TEST_IMPORT_KEY, TEST_KEY_SIZE); + + //assert + ASSERT_ARE_NOT_EQUAL(int, 0, import_res); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + + //cleanup + } + + TEST_FUNCTION(hsm_client_tpm_activate_key_key_NULL_fail) + { + //arrange + const HSM_CLIENT_TPM_INTERFACE* tpm_if = hsm_client_tpm_device_interface(); + HSM_CLIENT_HANDLE sec_handle = tpm_if->hsm_client_tpm_create(); + umock_c_reset_all_calls(); + + //act + int import_res = tpm_if->hsm_client_activate_identity_key(sec_handle, NULL, TEST_KEY_SIZE); + + //assert + ASSERT_ARE_NOT_EQUAL(int, 0, import_res); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + + //cleanup + tpm_if->hsm_client_tpm_destroy(sec_handle); + } + + TEST_FUNCTION(hsm_client_tpm_activate_key_fail) + { + //arrange + const HSM_CLIENT_TPM_INTERFACE* tpm_if = hsm_client_tpm_device_interface(); + HSM_CLIENT_HANDLE sec_handle = tpm_if->hsm_client_tpm_create(); + umock_c_reset_all_calls(); + + int negativeTestsInitResult = umock_c_negative_tests_init(); + ASSERT_ARE_EQUAL(int, 0, negativeTestsInitResult); + + setup_hsm_client_tpm_activate_key_mock(); + + umock_c_negative_tests_snapshot(); + + size_t calls_cannot_fail[] = { 2, 3, 4, 5, 6, 7, 10, 13 }; + + //act + size_t count = umock_c_negative_tests_call_count(); + for (size_t index = 0; index < count; index++) + { + if (should_skip_index(index, calls_cannot_fail, sizeof(calls_cannot_fail) / sizeof(calls_cannot_fail[0])) != 0) + { + continue; + } + + umock_c_negative_tests_reset(); + umock_c_negative_tests_fail_call(index); + + char tmp_msg[64]; + sprintf(tmp_msg, "hsm_client_tpm_activate_key failure in test %zu/%zu", index, count); + + //act + int import_res = tpm_if->hsm_client_activate_identity_key(sec_handle, TEST_IMPORT_KEY, TEST_KEY_SIZE); + + //assert + ASSERT_ARE_NOT_EQUAL_WITH_MSG(int, 0, import_res, tmp_msg); + } + //cleanup + tpm_if->hsm_client_tpm_destroy(sec_handle); + umock_c_negative_tests_deinit(); + } + + TEST_FUNCTION(hsm_client_tpm_activate_key_succeed) + { + //arrange + const HSM_CLIENT_TPM_INTERFACE* tpm_if = hsm_client_tpm_device_interface(); + HSM_CLIENT_HANDLE sec_handle = tpm_if->hsm_client_tpm_create(); + umock_c_reset_all_calls(); + + setup_hsm_client_tpm_activate_key_mock(); + + //act + int import_res = tpm_if->hsm_client_activate_identity_key(sec_handle, TEST_IMPORT_KEY, TEST_KEY_SIZE); + + //assert + ASSERT_ARE_EQUAL(int, 0, import_res); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + + //cleanup + tpm_if->hsm_client_tpm_destroy(sec_handle); + } + + TEST_FUNCTION(hsm_client_tpm_get_endorsement_key_handle_NULL_succeed) + { + unsigned char* key; + size_t key_len; + + //act + const HSM_CLIENT_TPM_INTERFACE* tpm_if = hsm_client_tpm_device_interface(); + int result = tpm_if->hsm_client_get_ek(NULL, &key, &key_len); + + //assert + ASSERT_ARE_NOT_EQUAL(int, 0, result); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + + //cleanup + } + + TEST_FUNCTION(hsm_client_tpm_get_endorsement_key_size_0_fail) + { + g_rsa_size = 0; + unsigned char* key; + size_t key_len; + + //arrange + const HSM_CLIENT_TPM_INTERFACE* tpm_if = hsm_client_tpm_device_interface(); + HSM_CLIENT_HANDLE sec_handle = tpm_if->hsm_client_tpm_create(); + umock_c_reset_all_calls(); + + //act + int result = tpm_if->hsm_client_get_ek(NULL, &key, &key_len); + + //assert + ASSERT_ARE_NOT_EQUAL(int, 0, result); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + + //cleanup + tpm_if->hsm_client_tpm_destroy(sec_handle); + } + + TEST_FUNCTION(hsm_client_tpm_get_endorsement_key_fail) + { + //arrange + unsigned char* key; + size_t key_len; + + const HSM_CLIENT_TPM_INTERFACE* tpm_if = hsm_client_tpm_device_interface(); + HSM_CLIENT_HANDLE sec_handle = tpm_if->hsm_client_tpm_create(); + umock_c_reset_all_calls(); + + int negativeTestsInitResult = umock_c_negative_tests_init(); + ASSERT_ARE_EQUAL(int, 0, negativeTestsInitResult); + + setup_hsm_client_tpm_get_endorsement_key_mocks(); + + umock_c_negative_tests_snapshot(); + + size_t calls_cannot_fail[] = { 0, 2, 4 }; + + //act + size_t count = umock_c_negative_tests_call_count(); + for (size_t index = 0; index < count; index++) + { + if (should_skip_index(index, calls_cannot_fail, sizeof(calls_cannot_fail) / sizeof(calls_cannot_fail[0])) != 0) + { + continue; + } + + umock_c_negative_tests_reset(); + umock_c_negative_tests_fail_call(index); + + char tmp_msg[64]; + sprintf(tmp_msg, "hsm_client_tpm_get_endorsement_key failure in test %zu/%zu", index, count); + + int result = tpm_if->hsm_client_get_ek(NULL, &key, &key_len); + + //assert + ASSERT_ARE_NOT_EQUAL_WITH_MSG(int, 0, result, tmp_msg); + } + //cleanup + tpm_if->hsm_client_tpm_destroy(sec_handle); + umock_c_negative_tests_deinit(); + } + + TEST_FUNCTION(hsm_client_tpm_get_endorsement_key_succeed) + { + //arrange + unsigned char* key; + size_t key_len; + + const HSM_CLIENT_TPM_INTERFACE* tpm_if = hsm_client_tpm_device_interface(); + HSM_CLIENT_HANDLE sec_handle = tpm_if->hsm_client_tpm_create(); + umock_c_reset_all_calls(); + + setup_hsm_client_tpm_get_endorsement_key_mocks(); + + //act + int result = tpm_if->hsm_client_get_ek(sec_handle, &key, &key_len); + + //assert + ASSERT_ARE_EQUAL(int, 0, result); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + + //cleanup + my_gballoc_free(key); + tpm_if->hsm_client_tpm_destroy(sec_handle); + } + + TEST_FUNCTION(hsm_client_tpm_get_storage_key_handle_NULL_fail) + { + //arrange + unsigned char* key; + size_t key_len; + + //act + const HSM_CLIENT_TPM_INTERFACE* tpm_if = hsm_client_tpm_device_interface(); + int result = tpm_if->hsm_client_get_srk(NULL, &key, &key_len); + + //assert + ASSERT_ARE_NOT_EQUAL(int, 0, result); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + + //cleanup + } + + TEST_FUNCTION(hsm_client_tpm_get_storage_key_size_0_fail) + { + unsigned char* key; + size_t key_len; + g_rsa_size = 0; + + //arrange + const HSM_CLIENT_TPM_INTERFACE* tpm_if = hsm_client_tpm_device_interface(); + HSM_CLIENT_HANDLE sec_handle = tpm_if->hsm_client_tpm_create(); + umock_c_reset_all_calls(); + + //act + int result = tpm_if->hsm_client_get_srk(NULL, &key, &key_len); + + //assert + ASSERT_ARE_NOT_EQUAL(int, 0, result); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + + //cleanup + tpm_if->hsm_client_tpm_destroy(sec_handle); + } + + TEST_FUNCTION(hsm_client_tpm_get_storage_key_fail) + { + unsigned char* key; + size_t key_len; + + //arrange + const HSM_CLIENT_TPM_INTERFACE* tpm_if = hsm_client_tpm_device_interface(); + HSM_CLIENT_HANDLE sec_handle = tpm_if->hsm_client_tpm_create(); + umock_c_reset_all_calls(); + + int negativeTestsInitResult = umock_c_negative_tests_init(); + ASSERT_ARE_EQUAL(int, 0, negativeTestsInitResult); + + setup_hsm_client_tpm_get_storage_key_mocks(); + + umock_c_negative_tests_snapshot(); + + size_t calls_cannot_fail[] = { 0, 2, 4 }; + + //act + size_t count = umock_c_negative_tests_call_count(); + for (size_t index = 0; index < count; index++) + { + if (should_skip_index(index, calls_cannot_fail, sizeof(calls_cannot_fail) / sizeof(calls_cannot_fail[0])) != 0) + { + continue; + } + + umock_c_negative_tests_reset(); + umock_c_negative_tests_fail_call(index); + + char tmp_msg[64]; + sprintf(tmp_msg, "hsm_client_tpm_get_storage_key failure in test %zu/%zu", index, count); + + int result = tpm_if->hsm_client_get_srk(NULL, &key, &key_len); + + //assert + ASSERT_ARE_NOT_EQUAL_WITH_MSG(int, 0, result, tmp_msg); + } + + //cleanup + tpm_if->hsm_client_tpm_destroy(sec_handle); + umock_c_negative_tests_deinit(); + } + + TEST_FUNCTION(hsm_client_tpm_get_storage_key_succeed) + { + unsigned char* key; + size_t key_len; + + //arrange + const HSM_CLIENT_TPM_INTERFACE* tpm_if = hsm_client_tpm_device_interface(); + HSM_CLIENT_HANDLE sec_handle = tpm_if->hsm_client_tpm_create(); + umock_c_reset_all_calls(); + + setup_hsm_client_tpm_get_storage_key_mocks(); + + //act + int result = tpm_if->hsm_client_get_srk(sec_handle, &key, &key_len); + + //assert + ASSERT_ARE_EQUAL(int, 0, result); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + + //cleanup + my_gballoc_free(key); + tpm_if->hsm_client_tpm_destroy(sec_handle); + } + + TEST_FUNCTION(hsm_client_tpm_sign_data_handle_fail) + { + unsigned char* key; + size_t key_len; + + //arrange + + //act + const HSM_CLIENT_TPM_INTERFACE* tpm_if = hsm_client_tpm_device_interface(); + int result = tpm_if->hsm_client_sign_with_identity(NULL, TEST_BUFFER, TEST_BUFFER_SIZE, &key, &key_len); + + //assert + ASSERT_ARE_NOT_EQUAL(int, 0, result); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + + //cleanup + } + + TEST_FUNCTION(hsm_client_tpm_sign_data_data_NULL_fail) + { + //arrange + unsigned char* key; + size_t key_len; + + const HSM_CLIENT_TPM_INTERFACE* tpm_if = hsm_client_tpm_device_interface(); + HSM_CLIENT_HANDLE sec_handle = tpm_if->hsm_client_tpm_create(); + umock_c_reset_all_calls(); + + //act + int result = tpm_if->hsm_client_sign_with_identity(sec_handle, NULL, TEST_BUFFER_SIZE, &key, &key_len); + + //assert + ASSERT_ARE_NOT_EQUAL(int, 0, result); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + + //cleanup + tpm_if->hsm_client_tpm_destroy(sec_handle); + } + + TEST_FUNCTION(hsm_client_tpm_sign_data_size_0_fail) + { + unsigned char* key; + size_t key_len; + + //arrange + const HSM_CLIENT_TPM_INTERFACE* tpm_if = hsm_client_tpm_device_interface(); + HSM_CLIENT_HANDLE sec_handle = tpm_if->hsm_client_tpm_create(); + umock_c_reset_all_calls(); + + //act + int result = tpm_if->hsm_client_sign_with_identity(sec_handle, TEST_BUFFER, 0, &key, &key_len); + + //assert + ASSERT_ARE_NOT_EQUAL(int, 0, result); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + + //cleanup + tpm_if->hsm_client_tpm_destroy(sec_handle); + } + + TEST_FUNCTION(hsm_client_tpm_sign_data_digest_null_fail) + { + size_t key_len; + + //arrange + const HSM_CLIENT_TPM_INTERFACE* tpm_if = hsm_client_tpm_device_interface(); + HSM_CLIENT_HANDLE sec_handle = tpm_if->hsm_client_tpm_create(); + umock_c_reset_all_calls(); + + //act + int result = tpm_if->hsm_client_sign_with_identity(sec_handle, TEST_BUFFER, TEST_BUFFER_SIZE, NULL, &key_len); + + //assert + ASSERT_ARE_NOT_EQUAL(int, 0, result); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + + //cleanup + tpm_if->hsm_client_tpm_destroy(sec_handle); + } + + TEST_FUNCTION(hsm_client_tpm_sign_data_digest_size_null_fail) + { + unsigned char* key; + + //arrange + const HSM_CLIENT_TPM_INTERFACE* tpm_if = hsm_client_tpm_device_interface(); + HSM_CLIENT_HANDLE sec_handle = tpm_if->hsm_client_tpm_create(); + umock_c_reset_all_calls(); + + //act + int result = tpm_if->hsm_client_sign_with_identity(sec_handle, TEST_BUFFER, TEST_BUFFER_SIZE, &key, NULL); + + //assert + ASSERT_ARE_NOT_EQUAL(int, 0, result); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + + //cleanup + tpm_if->hsm_client_tpm_destroy(sec_handle); + } + + TEST_FUNCTION(hsm_client_tpm_sign_data_fail) + { + unsigned char* key; + size_t key_len; + + //arrange + const HSM_CLIENT_TPM_INTERFACE* tpm_if = hsm_client_tpm_device_interface(); + HSM_CLIENT_HANDLE sec_handle = tpm_if->hsm_client_tpm_create(); + umock_c_reset_all_calls(); + + int negativeTestsInitResult = umock_c_negative_tests_init(); + ASSERT_ARE_EQUAL(int, 0, negativeTestsInitResult); + + setup_hsm_client_tpm_sign_data_mocks(); + + umock_c_negative_tests_snapshot(); + + size_t count = umock_c_negative_tests_call_count(); + for (size_t index = 0; index < count; index++) + { + umock_c_negative_tests_reset(); + umock_c_negative_tests_fail_call(index); + + char tmp_msg[64]; + sprintf(tmp_msg, "hsm_client_tpm_sign_data failure in test %zu/%zu", index, count); + + //act + int result = tpm_if->hsm_client_sign_with_identity(NULL, TEST_BUFFER, TEST_BUFFER_SIZE, &key, &key_len); + + //assert + ASSERT_ARE_NOT_EQUAL_WITH_MSG(int, 0, result, tmp_msg); + } + + //cleanup + tpm_if->hsm_client_tpm_destroy(sec_handle); + umock_c_negative_tests_deinit(); + } + + TEST_FUNCTION(hsm_client_tpm_sign_data_succeed) + { + unsigned char* key; + size_t key_len; + + //arrange + const HSM_CLIENT_TPM_INTERFACE* tpm_if = hsm_client_tpm_device_interface(); + HSM_CLIENT_HANDLE sec_handle = tpm_if->hsm_client_tpm_create(); + umock_c_reset_all_calls(); + + setup_hsm_client_tpm_sign_data_mocks(); + + //act + int result = tpm_if->hsm_client_sign_with_identity(sec_handle, TEST_BUFFER, TEST_BUFFER_SIZE, &key, &key_len); + + //assert + ASSERT_ARE_EQUAL(int, 0, result); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + + //cleanup + my_gballoc_free(key); + tpm_if->hsm_client_tpm_destroy(sec_handle); + } + + TEST_FUNCTION(hsm_client_tpm_derive_and_sign_handle_fail) + { + unsigned char* key; + size_t key_len; + + //arrange + + //act + const HSM_CLIENT_TPM_INTERFACE* tpm_if = hsm_client_tpm_device_interface(); + int result = tpm_if->hsm_client_derive_and_sign_with_identity(NULL, TEST_BUFFER, TEST_BUFFER_SIZE, + IDENTITY_BUFFER, IDENTITY_BUFFER_SIZE, &key, &key_len); + + //assert + ASSERT_ARE_NOT_EQUAL(int, 0, result); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + + //cleanup + } + + TEST_FUNCTION(hsm_client_tpm_derive_and_sign_data_null_fail) + { + //arrange + unsigned char* key; + size_t key_len; + + const HSM_CLIENT_TPM_INTERFACE* tpm_if = hsm_client_tpm_device_interface(); + HSM_CLIENT_HANDLE sec_handle = tpm_if->hsm_client_tpm_create(); + umock_c_reset_all_calls(); + + //act + int result = tpm_if->hsm_client_derive_and_sign_with_identity(sec_handle, NULL, TEST_BUFFER_SIZE, + IDENTITY_BUFFER, IDENTITY_BUFFER_SIZE, &key, &key_len); + + //assert + ASSERT_ARE_NOT_EQUAL(int, 0, result); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + + //cleanup + tpm_if->hsm_client_tpm_destroy(sec_handle); + } + + TEST_FUNCTION(hsm_client_tpm_derive_and_sign_data_size_0_fail) + { + unsigned char* key; + size_t key_len; + + //arrange + const HSM_CLIENT_TPM_INTERFACE* tpm_if = hsm_client_tpm_device_interface(); + HSM_CLIENT_HANDLE sec_handle = tpm_if->hsm_client_tpm_create(); + umock_c_reset_all_calls(); + + //act + int result = tpm_if->hsm_client_derive_and_sign_with_identity(sec_handle, TEST_BUFFER, 0, + IDENTITY_BUFFER, IDENTITY_BUFFER_SIZE, &key, &key_len); + + //assert + ASSERT_ARE_NOT_EQUAL(int, 0, result); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + + //cleanup + tpm_if->hsm_client_tpm_destroy(sec_handle); + } + + TEST_FUNCTION(hsm_client_tpm_derive_and_sign_identity_null_fail) + { + //arrange + unsigned char* key; + size_t key_len; + + const HSM_CLIENT_TPM_INTERFACE* tpm_if = hsm_client_tpm_device_interface(); + HSM_CLIENT_HANDLE sec_handle = tpm_if->hsm_client_tpm_create(); + umock_c_reset_all_calls(); + + //act + int result = tpm_if->hsm_client_derive_and_sign_with_identity(sec_handle, TEST_BUFFER, TEST_BUFFER_SIZE, + NULL, IDENTITY_BUFFER_SIZE, &key, &key_len); + + //assert + ASSERT_ARE_NOT_EQUAL(int, 0, result); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + + //cleanup + tpm_if->hsm_client_tpm_destroy(sec_handle); + } + + TEST_FUNCTION(hsm_client_tpm_derive_and_sign_identity_size_0_fail) + { + unsigned char* key; + size_t key_len; + + //arrange + const HSM_CLIENT_TPM_INTERFACE* tpm_if = hsm_client_tpm_device_interface(); + HSM_CLIENT_HANDLE sec_handle = tpm_if->hsm_client_tpm_create(); + umock_c_reset_all_calls(); + + //act + int result = tpm_if->hsm_client_derive_and_sign_with_identity(sec_handle, TEST_BUFFER, TEST_BUFFER_SIZE, + IDENTITY_BUFFER, 0, &key, &key_len); + + //assert + ASSERT_ARE_NOT_EQUAL(int, 0, result); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + + //cleanup + tpm_if->hsm_client_tpm_destroy(sec_handle); + } + + TEST_FUNCTION(hsm_client_tpm_derive_and_sign_digest_null_fail) + { + size_t key_len; + + //arrange + const HSM_CLIENT_TPM_INTERFACE* tpm_if = hsm_client_tpm_device_interface(); + HSM_CLIENT_HANDLE sec_handle = tpm_if->hsm_client_tpm_create(); + umock_c_reset_all_calls(); + + //act + int result = tpm_if->hsm_client_derive_and_sign_with_identity(sec_handle, TEST_BUFFER, TEST_BUFFER_SIZE, + IDENTITY_BUFFER, IDENTITY_BUFFER_SIZE, NULL, &key_len); + + //assert + ASSERT_ARE_NOT_EQUAL(int, 0, result); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + + //cleanup + tpm_if->hsm_client_tpm_destroy(sec_handle); + } + + TEST_FUNCTION(hsm_client_tpm_sign_derive_and_sign_digest_size_null_fail) + { + unsigned char* key; + + //arrange + const HSM_CLIENT_TPM_INTERFACE* tpm_if = hsm_client_tpm_device_interface(); + HSM_CLIENT_HANDLE sec_handle = tpm_if->hsm_client_tpm_create(); + umock_c_reset_all_calls(); + + //act + int result = tpm_if->hsm_client_derive_and_sign_with_identity(sec_handle, TEST_BUFFER, TEST_BUFFER_SIZE, + IDENTITY_BUFFER, IDENTITY_BUFFER_SIZE, &key, NULL); + + //assert + ASSERT_ARE_NOT_EQUAL(int, 0, result); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + + //cleanup + tpm_if->hsm_client_tpm_destroy(sec_handle); + } + + TEST_FUNCTION(hsm_client_tpm_derive_and_sign_fail) + { + unsigned char* key; + size_t key_len; + + //arrange + const HSM_CLIENT_TPM_INTERFACE* tpm_if = hsm_client_tpm_device_interface(); + HSM_CLIENT_HANDLE sec_handle = tpm_if->hsm_client_tpm_create(); + umock_c_reset_all_calls(); + + int negativeTestsInitResult = umock_c_negative_tests_init(); + ASSERT_ARE_EQUAL(int, 0, negativeTestsInitResult); + + setup_hsm_client_tpm_sign_data_mocks(); + + umock_c_negative_tests_snapshot(); + + size_t count = umock_c_negative_tests_call_count(); + for (size_t index = 0; index < count; index++) + { + umock_c_negative_tests_reset(); + umock_c_negative_tests_fail_call(index); + + char tmp_msg[64]; + sprintf(tmp_msg, "hsm_client_derive_and_sign_with_identity failure in test %zu/%zu", index, count); + + //act + int result = tpm_if->hsm_client_derive_and_sign_with_identity(NULL, TEST_BUFFER, TEST_BUFFER_SIZE, + IDENTITY_BUFFER, IDENTITY_BUFFER_SIZE, &key, &key_len); + + //assert + ASSERT_ARE_NOT_EQUAL_WITH_MSG(int, 0, result, tmp_msg); + } + + //cleanup + tpm_if->hsm_client_tpm_destroy(sec_handle); + umock_c_negative_tests_deinit(); + } + + TEST_FUNCTION(hsm_client_tpm_derive_and_sign_succeed) + { + unsigned char* key; + size_t key_len; + + //arrange + const HSM_CLIENT_TPM_INTERFACE* tpm_if = hsm_client_tpm_device_interface(); + HSM_CLIENT_HANDLE sec_handle = tpm_if->hsm_client_tpm_create(); + umock_c_reset_all_calls(); + + STRICT_EXPECTED_CALL(SignData(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG)); + STRICT_EXPECTED_CALL(perform_sign_with_key(IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + + //act + int result = tpm_if->hsm_client_derive_and_sign_with_identity(sec_handle, TEST_BUFFER, TEST_BUFFER_SIZE, + IDENTITY_BUFFER, IDENTITY_BUFFER_SIZE, &key, &key_len); + + //assert + ASSERT_ARE_EQUAL(int, 0, result); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + + //cleanup + my_gballoc_free(key); + tpm_if->hsm_client_tpm_destroy(sec_handle); + } + + TEST_FUNCTION(hsm_client_tpm_free_buffer_null_does_nothing) + { + // arrange + const HSM_CLIENT_TPM_INTERFACE* tpm_if = hsm_client_tpm_device_interface(); + + // act + tpm_if->hsm_client_free_buffer(NULL); + + // assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + // cleanup + } + + TEST_FUNCTION(hsm_client_tpm_free_buffer_frees_something) + { + // arrange + const HSM_CLIENT_TPM_INTERFACE* tpm_if = hsm_client_tpm_device_interface(); + void * buffer = my_gballoc_malloc(1); + umock_c_reset_all_calls(); + + STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG)); + // act + tpm_if->hsm_client_free_buffer(buffer); + + // assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + // cleanup + } + + TEST_FUNCTION(hsm_client_tpm_interface_succeed) + { + //arrange + umock_c_reset_all_calls(); + + //act + const HSM_CLIENT_TPM_INTERFACE* tpm_iface = hsm_client_tpm_device_interface(); + + //assert + ASSERT_IS_NOT_NULL(tpm_iface); + ASSERT_IS_NOT_NULL(tpm_iface->hsm_client_tpm_create); + ASSERT_IS_NOT_NULL(tpm_iface->hsm_client_tpm_destroy); + ASSERT_IS_NOT_NULL(tpm_iface->hsm_client_get_ek); + ASSERT_IS_NOT_NULL(tpm_iface->hsm_client_get_srk); + ASSERT_IS_NOT_NULL(tpm_iface->hsm_client_activate_identity_key); + ASSERT_IS_NOT_NULL(tpm_iface->hsm_client_sign_with_identity); + ASSERT_IS_NOT_NULL(tpm_iface->hsm_client_derive_and_sign_with_identity); + ASSERT_IS_NOT_NULL(tpm_iface->hsm_client_free_buffer); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + + //cleanup + } + + END_TEST_SUITE(hsm_client_tpm_ut) diff --git a/edgelet/hsm-sys/azure-iot-hsm-c/tests/hsm_client_tpm_ut/main.c b/edgelet/hsm-sys/azure-iot-hsm-c/tests/hsm_client_tpm_ut/main.c new file mode 100644 index 00000000000..dcd98cd671f --- /dev/null +++ b/edgelet/hsm-sys/azure-iot-hsm-c/tests/hsm_client_tpm_ut/main.c @@ -0,0 +1,11 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +#include "testrunnerswitcher.h" + +int main(void) +{ + size_t failedTestCount = 0; + RUN_TEST_SUITE(hsm_client_tpm_ut, failedTestCount); + return failedTestCount; +} diff --git a/edgelet/hsm-sys/build.rs b/edgelet/hsm-sys/build.rs index b2b5c1e5ffb..2cf731a66b5 100644 --- a/edgelet/hsm-sys/build.rs +++ b/edgelet/hsm-sys/build.rs @@ -8,6 +8,7 @@ use std::process::Command; use cmake::Config; const SSL_OPTION: &str = "use_openssl"; +const USE_EMULATOR: &str = "use_emulator"; trait SetPlatformDefines { fn set_platform_defines(&mut self) -> &mut Self; @@ -17,12 +18,26 @@ trait SetPlatformDefines { impl SetPlatformDefines for Config { #[cfg(windows)] fn set_platform_defines(&mut self) -> &mut Self { + // if the builder chooses to set "use_emulator", use their setting, otherwise, use the + // emulator for debug and a real device for release + let use_emulator = env::var(USE_EMULATOR) + .or_else(|_| { + env::var("PROFILE").and_then(|profile| { + Ok(if profile.to_lowercase() == "release" { + String::from("OFF") + } else { + String::from("ON") + }) + }) + }) + .unwrap(); // C-shared library wants Windows flags (/DWIN32 /D_WINDOWS) for Windows, // and the cmake library overrides this. self.cflag("/DWIN32") .cxxflag("/DWIN32") .cflag("/D_WINDOWS") .cxxflag("/D_WINDOWS") + .define(USE_EMULATOR, use_emulator) } #[cfg(unix)] @@ -35,12 +50,12 @@ impl SetPlatformDefines for Config { } else { "ON" }; - //CMAKE_SYSROOT if let Ok(sysroot) = env::var("SYSROOT") { self.define("run_valgrind", rv) .define("CMAKE_SYSROOT", sysroot) + .define(USE_EMULATOR, "OFF") } else { - self.define("run_valgrind", rv) + self.define("run_valgrind", rv).define(USE_EMULATOR, "OFF") } } @@ -59,10 +74,13 @@ impl SetPlatformDefines for Config { fn main() { // Clone Azure C -shared library - let c_shared_repo = "azure-iot-hsm-c/azure-c-shared-utility"; + let c_shared_repo = "azure-iot-hsm-c/deps/c-shared"; + let utpm_repo = "azure-iot-hsm-c/deps/utpm"; println!("#Start Update C-Shared Utilities"); - if !Path::new(&format!("{}/.git", c_shared_repo)).exists() { + if !Path::new(&format!("{}/.git", c_shared_repo)).exists() + || !Path::new(&format!("{}/.git", utpm_repo)).exists() + { let _ = Command::new("git") .arg("submodule") .arg("update") @@ -86,6 +104,18 @@ fn main() { .profile("Release") .build(); + println!("#Also build micro tpm library"); + let _shared = Config::new(utpm_repo) + .define(SSL_OPTION, "ON") + .define("CMAKE_BUILD_TYPE", "Release") + .define("run_unittests", "OFF") + .define("use_default_uuid", "ON") + .define("skip_samples", "ON") + .set_platform_defines() + .define("run_valgrind", "OFF") + .profile("Release") + .build(); + // make the C libary at azure-iot-hsm-c (currently a subdirectory in this // crate) // Always make the Release version because Rust links to the Release CRT. @@ -118,6 +148,8 @@ fn main() { // library as a static lib which we do only in rust debug builds #[cfg(debug_assertions)] println!("cargo:rustc-link-lib=aziotsharedutil"); + #[cfg(debug_assertions)] + println!("cargo:rustc-link-lib=utpm"); #[cfg(windows)] {