/* SPDX-License-Identifier: BSD-2-Clause */ /******************************************************************************* * Copyright 2018, Fraunhofer SIT sponsored by Infineon Technologies AG * All rights reserved. ******************************************************************************/ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include #include #include "tss2_fapi.h" #include "tpm_json_serialize.h" #include "tpm_json_deserialize.h" #include "ifapi_json_serialize.h" #include "ifapi_json_deserialize.h" #include "fapi_policy.h" #include "util/aux_util.h" #define LOGMODULE tests #include "util/log.h" /* 3 copies from ifapi_helpers.c */ static void cleanup_policy_element(TPMT_POLICYELEMENT *policy) { switch (policy->type) { case POLICYSECRET: SAFE_FREE(policy->element.PolicySecret.objectPath); break; case POLICYAUTHORIZE: SAFE_FREE(policy->element.PolicyAuthorize.keyPath); SAFE_FREE(policy->element.PolicyAuthorize.keyPEM); break; case POLICYAUTHORIZENV: SAFE_FREE( policy->element.PolicyAuthorizeNv.nvPath); SAFE_FREE( policy->element.PolicyAuthorizeNv.policy_buffer); break; case POLICYSIGNED: SAFE_FREE(policy->element.PolicySigned.keyPath); SAFE_FREE(policy->element.PolicySigned.keyPEM); break; case POLICYPCR: SAFE_FREE(policy->element.PolicyPCR.pcrs); break; case POLICYNV: SAFE_FREE(policy->element.PolicyNV.nvPath); break; case POLICYDUPLICATIONSELECT: SAFE_FREE(policy->element.PolicyDuplicationSelect.newParentPath); break; } } static void cleanup_policy_elements(TPML_POLICYELEMENTS *policy) { size_t i, j; if (policy != NULL) { for (i = 0; i < policy->count; i++) { if (policy->elements[i].type == POLICYOR) { /* Policy with sub policies */ TPML_POLICYBRANCHES *branches = policy->elements[i].element.PolicyOr.branches; for (j = 0; j < branches->count; j++) { SAFE_FREE(branches->authorizations[j].name); SAFE_FREE(branches->authorizations[j].description); cleanup_policy_elements(branches->authorizations[j].policy); } SAFE_FREE(branches); } else { cleanup_policy_element(&policy->elements[i]); } } SAFE_FREE(policy); } } /** Free memory allocated during deserialization of policy. * * The object will not be freed (might be declared on the stack). * * @param[in] object The policy to be cleaned up. * */ static void ifapi_cleanup_policy(TPMS_POLICY *policy) { if (policy) { SAFE_FREE(policy->description); SAFE_FREE(policy->policyAuthorizations); cleanup_policy_elements(policy->policy); } } char * normalize(const char *string) { char *string2 = malloc(strlen(string)+1); int i; int j = 0; for(i = 0; string[i] != '\0'; i++) { if ((string[i] != '\n' && string[i] != ' ')) { string2[j] = string[i]; j += 1; } } string2[j] = '\0'; return string2; } #define CHECK_ERROR(TYPE, SRC, RC) \ { \ TYPE out; \ TSS2_RC rc; \ json_object *jso = json_tokener_parse((SRC)); \ assert_non_null(jso); \ rc = ifapi_json_ ## TYPE ## _deserialize (jso, &out); \ assert_int_equal (rc, RC); \ json_object_put(jso); \ } #define CHECK_JSON2(TYPE, SRC, DST, PSERIALIZE) \ { \ TYPE out; \ TSS2_RC rc; \ json_object *jso = json_tokener_parse((SRC)); \ if (!jso) fprintf(stderr, "JSON parsing failed\n"); \ assert_non_null(jso); \ rc = ifapi_json_ ## TYPE ## _deserialize (jso, &out); \ if (rc) fprintf(stderr, "Deserialization failed\n"); \ assert_int_equal (rc, TSS2_RC_SUCCESS); \ json_object_put(jso); \ jso = NULL; \ rc = ifapi_json_ ## TYPE ## _serialize (PSERIALIZE, &jso); \ assert_int_equal (rc, TSS2_RC_SUCCESS); \ assert_non_null(jso); \ const char *jso_string = json_object_to_json_string_ext(jso, JSON_C_TO_STRING_PRETTY); \ assert_non_null(jso_string); \ char *string1 = normalize(jso_string); \ char *string2 = normalize(DST); \ assert_string_equal(string1, string2); \ json_object_put(jso); \ free(string1); \ free(string2); \ } #define CHECK_JSON(TYPE, SRC, DST) \ CHECK_JSON2(TYPE, SRC, DST, &out) #define CHECK_JSON_SIMPLE(TYPE, SRC, DST) \ CHECK_JSON2(TYPE, SRC, DST, out) #define CHECK_JSON_TO_BIN(TYPE, SRC, DST) \ { \ TYPE out; \ TSS2_RC rc; \ TYPE expected = DST; \ json_object *jso = json_tokener_parse((SRC)); \ assert_non_null(jso); \ rc = ifapi_json_ ## TYPE ## _deserialize (jso, &out); \ assert_int_equal (rc, TSS2_RC_SUCCESS); \ json_object_put(jso); \ assert_true(out == expected); \ } #define CHECK_BIN2(TYPE, BIN, PSERIALIZE) \ TYPE BIN ## 2; \ { \ char *jso_string1, *jso_string2; \ json_object *jso = NULL; \ TSS2_RC rc = ifapi_json_ ## TYPE ## _serialize (PSERIALIZE, &jso); \ jso_string1 = strdup(json_object_to_json_string_ext(jso, JSON_C_TO_STRING_PRETTY)); \ assert_int_equal (rc, TSS2_RC_SUCCESS); \ rc = ifapi_json_ ## TYPE ## _deserialize (jso, &BIN ## 2); \ assert_int_equal (rc, TSS2_RC_SUCCESS); \ json_object_put(jso); \ jso = NULL; \ rc = ifapi_json_ ## TYPE ## _serialize (PSERIALIZE ## 2, &jso); \ jso_string2 = strdup(json_object_to_json_string_ext(jso, JSON_C_TO_STRING_PRETTY)); \ assert_int_equal (rc, TSS2_RC_SUCCESS); \ if (strcmp(jso_string1, jso_string2)) { \ fprintf(stderr,"\n jso: %s\n", jso_string1); \ fprintf(stderr,"\n jso: %s\n", jso_string2); \ } \ assert_string_equal(jso_string1, jso_string2); \ json_object_put(jso); \ free(jso_string1); \ free(jso_string2); \ } #define CHECK_BIN(TYPE, BIN) \ CHECK_BIN2(TYPE, BIN, &BIN) #define CHECK_BIN_SIMPLE(TYPE, BIN) \ CHECK_BIN2(TYPE, BIN, BIN) static void check_bin(void **state) { TPM2B_PUBLIC inPublicAES = { .size = 0, .publicArea = { .type = TPM2_ALG_SYMCIPHER, .nameAlg = TPM2_ALG_SHA256, .objectAttributes = (TPMA_OBJECT_USERWITHAUTH | TPMA_OBJECT_SIGN_ENCRYPT | TPMA_OBJECT_DECRYPT), .authPolicy = { .size = 0, }, .parameters.symDetail = { .sym = { .algorithm = TPM2_ALG_AES, .keyBits = {.aes = 128}, .mode = {.aes = TPM2_ALG_CFB}} }, .unique.sym = { .size = 0, .buffer = {} } } }; CHECK_BIN(TPM2B_PUBLIC, inPublicAES); TPM2B_PUBLIC inPublicECC = { .size = 0, .publicArea = { .type = TPM2_ALG_ECC, .nameAlg = TPM2_ALG_SHA1, .objectAttributes = ( TPMA_OBJECT_USERWITHAUTH | TPMA_OBJECT_RESTRICTED | TPMA_OBJECT_SIGN_ENCRYPT | TPMA_OBJECT_FIXEDTPM | TPMA_OBJECT_FIXEDPARENT | TPMA_OBJECT_SENSITIVEDATAORIGIN ), .authPolicy = { .size = 0, }, .parameters.eccDetail = { .symmetric = { .algorithm = TPM2_ALG_NULL, .keyBits.aes = 128, .mode.aes = TPM2_ALG_ECB, }, .scheme = { .scheme = TPM2_ALG_ECDAA, .details = { .ecdaa = { .hashAlg = TPM2_ALG_SHA256 }}, }, .curveID = TPM2_ECC_BN_P256, .kdf = { .scheme = TPM2_ALG_NULL, .details = {} } }, /* .parameters.asymDetail.symmetric.algorithm = TPM2_ALG_NULL, */ .unique.ecc = { .x = { .size = 0, .buffer = {} } , .y = { .size = 0, .buffer = {} } , }, }, }; CHECK_BIN(TPM2B_PUBLIC, inPublicECC); TPM2B_PUBLIC inPublicRSA2 = { .size = 0, .publicArea = { .type = TPM2_ALG_RSA, .nameAlg = TPM2_ALG_SHA1, .objectAttributes = (TPMA_OBJECT_USERWITHAUTH | TPMA_OBJECT_SIGN_ENCRYPT | TPMA_OBJECT_FIXEDTPM | TPMA_OBJECT_FIXEDPARENT | TPMA_OBJECT_SENSITIVEDATAORIGIN), .authPolicy = { .size = 0, }, .parameters.rsaDetail = { .symmetric = { .algorithm = TPM2_ALG_NULL, .keyBits.aes = 128, .mode.aes = TPM2_ALG_CFB}, .scheme = { .scheme = TPM2_ALG_RSAPSS, .details = { .rsapss = { .hashAlg = TPM2_ALG_SHA1 } } }, .keyBits = 2048, .exponent = 0, }, .unique.rsa = { .size = 0, .buffer = {}, }, }, }; CHECK_BIN(TPM2B_PUBLIC, inPublicRSA2); TPMT_SIG_SCHEME ecc_scheme = { .scheme = TPM2_ALG_ECDSA, .details.ecdsa = TPM2_ALG_SHA1 }; CHECK_BIN(TPMT_SIG_SCHEME, ecc_scheme); TPMT_SIG_SCHEME rsa_scheme = { .scheme = TPM2_ALG_NULL }; CHECK_BIN(TPMT_SIG_SCHEME, rsa_scheme); TPMA_NV testNV = 0xffffff0f ; CHECK_BIN_SIMPLE(TPMA_NV, testNV); TPML_PCR_SELECTION pcr_selection = { .count = 3, .pcrSelections = { { .hash = TPM2_ALG_SHA1, .sizeofSelect = 3, .pcrSelect = { 01, 00, 03 }}, { .hash = TPM2_ALG_SHA256, .sizeofSelect = 3, .pcrSelect = { 01 ,00 ,03 }}, { .hash = TPM2_ALG_SHA384, .sizeofSelect = 3, .pcrSelect = { 02, 00, 02 }} } }; CHECK_BIN(TPML_PCR_SELECTION, pcr_selection); IFAPI_IMA_EVENT imaEvent = { .eventData = { .size = 0, .buffer = { 0 } }, .eventName = "Event" }; CHECK_BIN(IFAPI_IMA_EVENT, imaEvent); free(imaEvent2.eventName); } static void check_policy_bin(void **state) { TPMS_PCRVALUE pcr_value; TPML_PCRVALUES *pcr_value_list; TPML_POLICYBRANCHES *or_branch_list; TPMS_POLICYPCR pcr_policy; TPMT_POLICYELEMENT policy_element0; TPMT_POLICYELEMENT policy_element1; TPMT_POLICYELEMENT policy_element_or; TPML_POLICYELEMENTS *policy_elements_or; TPML_POLICYELEMENTS *policy_elements0; TPML_POLICYELEMENTS *policy_elements1; TPMS_POLICY policy; TPMS_POLICYBRANCH branch0; TPMS_POLICYBRANCH branch1; pcr_value.pcr = 16; pcr_value.hashAlg = TPM2_ALG_SHA1; memset(&pcr_value.digest, 0, sizeof(TPMU_HA)); memset(&pcr_policy, 0, sizeof(TPMS_POLICYPCR)); pcr_value_list = calloc(1, sizeof(TPML_PCRVALUES) + sizeof(TPMS_PCRVALUE)); if (pcr_value_list == NULL) { LOG_ERROR("%s", "Out of memory."); return; } pcr_value_list->count = 1; pcr_value_list->pcrs[0] = pcr_value; pcr_policy.pcrs = pcr_value_list; memset(&policy_element0, 0, sizeof(TPMT_POLICYELEMENT)); policy_element0.element.PolicyPCR = pcr_policy; policy_element0.type = POLICYPCR; memset(&policy_element1, 0, sizeof(TPMT_POLICYELEMENT)); policy_element1.element.PolicyPCR = pcr_policy; policy_element1.type = POLICYPCR; policy_elements0 = calloc(1, sizeof(TPML_POLICYELEMENTS) + sizeof(TPMT_POLICYELEMENT)); if (policy_elements0 == NULL) { LOG_ERROR("%s", "Out of memory."); if (pcr_policy.pcrs){ free(pcr_policy.pcrs); } return; } policy_elements0->count = 1; policy_elements0->elements[0] = policy_element0; policy.policy = policy_elements0; policy.description = "hareness description"; policy.policyAuthorizations = NULL; memset(&policy.policyDigests, 0, sizeof(TPML_DIGEST_VALUES)); //CHECK_BIN(TPMS_POLICY, policy); { char *jso_string1, *jso_string2; json_object *jso = NULL; TSS2_RC rc = ifapi_json_TPMS_POLICY_serialize (&policy, &jso); jso_string1 = strdup(json_object_to_json_string_ext(jso, JSON_C_TO_STRING_PRETTY)); assert_int_equal (rc, TSS2_RC_SUCCESS); rc = ifapi_json_TPMS_POLICY_deserialize (jso, &policy); assert_int_equal (rc, TSS2_RC_SUCCESS); json_object_put(jso); jso = NULL; rc = ifapi_json_TPMS_POLICY_serialize (&policy, &jso); jso_string2 = strdup(json_object_to_json_string_ext(jso, JSON_C_TO_STRING_PRETTY)); assert_int_equal (rc, TSS2_RC_SUCCESS); if (strcmp(jso_string1, jso_string2)) { fprintf(stderr,"\n jso: %s\n", jso_string1); fprintf(stderr,"\n jso: %s\n", jso_string2); } assert_string_equal(jso_string1, jso_string2); json_object_put(jso); free(jso_string1); free(jso_string2); } ifapi_cleanup_policy(&policy); or_branch_list = calloc(2, sizeof(TPML_POLICYBRANCHES) + (2 * sizeof(TPMS_POLICYBRANCH))); if (or_branch_list == NULL) { LOG_ERROR("%s", "Out of memory."); return; } or_branch_list->count = 2; policy_elements1 = calloc(1, sizeof(TPML_POLICYELEMENTS) + sizeof(TPMT_POLICYELEMENT)); if (policy_elements1 == NULL) { LOG_ERROR("%s", "Out of memory."); if (or_branch_list){ free(or_branch_list); } return; } policy_elements1->count = 1; policy_elements1->elements[0] = policy_element1; memset(&branch0, 0, sizeof(TPMS_POLICYBRANCH)); memset(&branch1, 0, sizeof(TPMS_POLICYBRANCH)); branch0.policy = policy_elements0; branch0.name = "branch0"; branch0.description = "description branch 0"; branch1.policy = policy_elements1; branch1.name = "branch1"; branch1.description = "description branch 1"; memcpy(&or_branch_list->authorizations[0], &branch0, sizeof(TPMS_POLICYBRANCH)); memcpy(&or_branch_list->authorizations[1], &branch1, sizeof(TPMS_POLICYBRANCH)); //or_policy.pcrs = pcr_branch_list; policy_elements_or = calloc(1, sizeof(TPML_POLICYELEMENTS) + sizeof(TPMT_POLICYELEMENT)); if (policy_elements_or == NULL) { LOG_ERROR("%s", "Out of memory."); if (or_branch_list) { free(or_branch_list); } return; } policy_elements_or->count = 1; memset(&policy_element_or, 0, sizeof(TPMT_POLICYELEMENT)); policy_element_or.element.PolicyOr.branches = or_branch_list; policy_element_or.type = POLICYOR; policy_elements_or->elements[0] = policy_element_or; policy.policy = policy_elements_or; //CHECK_BIN(TPMS_POLICY, policy); { char *jso_string1, *jso_string2; json_object *jso = NULL; TSS2_RC rc = ifapi_json_TPMS_POLICY_serialize (&policy, &jso); jso_string1 = strdup(json_object_to_json_string_ext(jso, JSON_C_TO_STRING_PRETTY)); assert_int_equal (rc, TSS2_RC_SUCCESS); rc = ifapi_json_TPMS_POLICY_deserialize (jso, &policy); assert_int_equal (rc, TSS2_RC_SUCCESS); json_object_put(jso); jso = NULL; rc = ifapi_json_TPMS_POLICY_serialize (&policy, &jso); jso_string2 = strdup(json_object_to_json_string_ext(jso, JSON_C_TO_STRING_PRETTY)); assert_int_equal (rc, TSS2_RC_SUCCESS); if (strcmp(jso_string1, jso_string2)) { fprintf(stderr,"\n jso: %s\n", jso_string1); fprintf(stderr,"\n jso: %s\n", jso_string2); } assert_string_equal(jso_string1, jso_string2); json_object_put(jso); free(jso_string1); free(jso_string2); } ifapi_cleanup_policy(&policy); free(policy_elements_or); free(policy_elements0); free(policy_elements1); free(or_branch_list); free(pcr_value_list); } static void check_json_to_bin(void **state) { CHECK_JSON_TO_BIN(UINT64, "22147483647", 22147483647); CHECK_JSON_TO_BIN(UINT64, "\"0xffffffff\"", 0xffffffff); CHECK_JSON_TO_BIN(UINT64, "\"0xfffffffff\"", 0xfffffffff); CHECK_JSON_TO_BIN(UINT32, "\"0xFfffffff\"", 0xffffffff); CHECK_JSON_TO_BIN(UINT16, "\"0xffff\"", 0xffff); } static void check_json_structs(void **state) { const char *test_json_TPMS_POLICYTEMPLATE = "{\n" " \"templateHash\": \"0011223344556677889900112233445566778899\"\n" "}"; CHECK_JSON(TPMS_POLICYTEMPLATE, test_json_TPMS_POLICYTEMPLATE, test_json_TPMS_POLICYTEMPLATE); const char *test_json_TPM2B_PUBLIC_expected = "{\n" " \"size\":0,\n" " \"publicArea\":{\n" " \"type\":\"ECC\",\n" " \"nameAlg\":\"SHA1\",\n" "\"objectAttributes\":{" " \"fixedTPM\":1," " \"stClear\":0," " \"fixedParent\":1," " \"sensitiveDataOrigin\":1," " \"userWithAuth\":1," " \"adminWithPolicy\":0," " \"noDA\":0," " \"encryptedDuplication\":0," " \"restricted\":1," " \"decrypt\":0," " \"sign\":1" " }," " \"authPolicy\":\"\",\n" " \"parameters\":{\n" " \"symmetric\":{\n" " \"algorithm\":\"NULL\"\n" " },\n" " \"scheme\":{\n" " \"scheme\":\"ECDAA\",\n" " \"details\":{\n" " \"hashAlg\":\"SHA256\",\n" " \"count\":0\n" " }\n" " },\n" " \"curveID\":\"BN_P256\",\n" " \"kdf\":{\n" " \"scheme\":\"NULL\"\n" " }\n" " },\n" " \"unique\":{\n" " \"x\": \"\",\n" " \"y\": \"\"\n" " }\n" " }\n" "}"; const char *test_json_TPM2B_PUBLIC_src= "{" " \"size\":0," " \"publicArea\":{" " \"type\":\"ECC\"," " \"nameAlg\":\"SHA1\"," " \"objectAttributes\":[" " \"fixedTPM\"," " \"fixedParent\"," " \"sensitiveDataOrigin\"," " \"userWithAuth\"," " \"restricted\"," " \"sign\"" " ]," " \"authPolicy\":\"\"," " \"parameters\":{" " \"symmetric\":{" " \"algorithm\":\"NULL\"" " }," " \"scheme\":{" " \"scheme\":\"ECDAA\"," " \"details\":{" " \"hashAlg\":\"SHA256\"," " \"count\":0" " }" " }," " \"curveID\":\"ECC_BN_P256\"," " \"kdf\":{" " \"scheme\":\"NULL\"" " }" " }," " \"unique\":{" " \"x\": \"\",\n" " \"y\": \"\"\n" " }" " }" "}" ""; const char *test_json_TPM2B_PUBLIC_dwnc_src = "{" " \"size\":0," " \"publicArea\":{" " \"type\":\"ecc\"," " \"nameAlg\":\"sha1\"," " \"objectAttributes\":[" " \"fixedTPM\"," " \"fixedParent\"," " \"sensitiveDataOrigin\"," " \"userWithAuth\"," " \"restricted\"," " \"sign\"" " ]," " \"authPolicy\":\"\"," " \"parameters\":{" " \"symmetric\":{" " \"algorithm\":\"null\"" " }," " \"scheme\":{" " \"scheme\":\"ecdaa\"," " \"details\":{" " \"hashAlg\":\"sha256\"," " \"count\":0" " }" " }," " \"curveID\":\"ecc_BN_P256\"," " \"kdf\":{" " \"scheme\":\"null\"" " }" " }," " \"unique\":{" " \"x\": \"\",\n" " \"y\": \"\"\n" " }" " }" " }" "}" ""; CHECK_JSON(TPM2B_PUBLIC, test_json_TPM2B_PUBLIC_src, test_json_TPM2B_PUBLIC_expected); CHECK_JSON(TPM2B_PUBLIC, test_json_TPM2B_PUBLIC_dwnc_src, test_json_TPM2B_PUBLIC_expected); const char *test_json_TPMS_ATTEST_certify_src = "{\n" " \"magic\": \"0xff544347\",\n" " \"type\": \"ST_ATTEST_CERTIFY\",\n" " \"qualifiedSigner\": \"0x00010203040506070809a0a1a2a3a4a5a6a7a8a9\",\n" " \"extraData\": \"0x00010203040506070809b0b1b2b3b4b5b6b7b8b9\",\n" " \"clockInfo\": {\n" " \"clock\": 123,\n" " \"resetCount\": 23,\n" " \"restartCount\": 1,\n" " \"safe\": \"yes\"\n" " },\n" " \"firmwareVersion\": 783,\n" " \"attested\": {\n" " \"name\": \"0x00010203040506070809c0c1c2c3c4c5c6c7c8c9\",\n" " \"qualifiedName\": \"0x00010203040506070809d0d1d2d3d4d5d6d7d8d9\"\n" " }\n" "}"; const char *test_json_TPMS_ATTEST_certify_expt = "{\n" " \"magic\": \"VALUE\",\n" " \"type\": \"ATTEST_CERTIFY\",\n" " \"qualifiedSigner\": \"00010203040506070809a0a1a2a3a4a5a6a7a8a9\",\n" " \"extraData\": \"00010203040506070809b0b1b2b3b4b5b6b7b8b9\",\n" " \"clockInfo\": {\n" " \"clock\": 123,\n" " \"resetCount\": 23,\n" " \"restartCount\": 1,\n" " \"safe\": \"YES\"\n" " },\n" " \"firmwareVersion\": 783,\n" " \"attested\": {\n" " \"name\": \"00010203040506070809c0c1c2c3c4c5c6c7c8c9\",\n" " \"qualifiedName\": \"00010203040506070809d0d1d2d3d4d5d6d7d8d9\"\n" " }\n" "}"; CHECK_JSON(TPMS_ATTEST, test_json_TPMS_ATTEST_certify_src, test_json_TPMS_ATTEST_certify_expt); const char *test_json_TPMS_ATTEST_sessionaudit_src = "{\n" " \"magic\": \"0xff544347\",\n" " \"type\": \"ST_ATTEST_SESSION_AUDIT\",\n" " \"qualifiedSigner\": \"0x00010203040506070809a0a1a2a3a4a5a6a7a8a9\",\n" " \"extraData\": \"0x00010203040506070809b0b1b2b3b4b5b6b7b8b9\",\n" " \"clockInfo\": {\n" " \"clock\": [12345,0],\n" " \"resetCount\": 23,\n" " \"restartCount\": 1,\n" " \"safe\": \"yes\"\n" " },\n" " \"firmwareVersion\": [783783,0],\n" " \"attested\": {\n" " \"exclusiveSession\": \"yes\",\n" " \"sessionDigest\": \"0x00010203040506070809d0d1d2d3d4d5d6d7d8d9\"\n" " }\n" "}"; const char *test_json_TPMS_ATTEST_sessionaudit_expt = "{\n" " \"magic\": \"VALUE\",\n" " \"type\": \"ATTEST_SESSION_AUDIT\",\n" " \"qualifiedSigner\": \"00010203040506070809a0a1a2a3a4a5a6a7a8a9\",\n" " \"extraData\": \"00010203040506070809b0b1b2b3b4b5b6b7b8b9\",\n" " \"clockInfo\": {\n" " \"clock\": 53021371269120,\n" " \"resetCount\": 23,\n" " \"restartCount\": 1,\n" " \"safe\": \"YES\"\n" " },\n" " \"firmwareVersion\": [783783,0],\n" " \"attested\": {\n" " \"exclusiveSession\": \"YES\",\n" " \"sessionDigest\": \"00010203040506070809d0d1d2d3d4d5d6d7d8d9\"\n" " }\n" "}"; CHECK_JSON(TPMS_ATTEST, test_json_TPMS_ATTEST_sessionaudit_src, test_json_TPMS_ATTEST_sessionaudit_expt); const char *test_json_TPMS_ATTEST_certifycreation_src = "{\n" " \"magic\": \"0xff544347\",\n" " \"type\": \"ST_ATTEST_CREATION\",\n" " \"qualifiedSigner\": \"0x00010203040506070809a0a1a2a3a4a5a6a7a8a9\",\n" " \"extraData\": \"0x00010203040506070809b0b1b2b3b4b5b6b7b8b9\",\n" " \"clockInfo\": {\n" " \"clock\": 123,\n" " \"resetCount\": 23,\n" " \"restartCount\": 1,\n" " \"safe\": \"yes\"\n" " },\n" " \"firmwareVersion\": [0,783],\n" " \"attested\": {\n" " \"objectName\": \"0x00010203040506070809c0c1c2c3c4c5c6c7c8c9\",\n" " \"creationHash\": \"0x00010203040506070809d0d1d2d3d4d5d6d7d8d9\"\n" " }\n" "}"; const char *test_json_TPMS_ATTEST_certifycreation_expt = "{\n" " \"magic\": \"VALUE\",\n" " \"type\": \"ATTEST_CREATION\",\n" " \"qualifiedSigner\": \"00010203040506070809a0a1a2a3a4a5a6a7a8a9\",\n" " \"extraData\": \"00010203040506070809b0b1b2b3b4b5b6b7b8b9\",\n" " \"clockInfo\": {\n" " \"clock\": 123,\n" " \"resetCount\": 23,\n" " \"restartCount\": 1,\n" " \"safe\": \"YES\"\n" " },\n" " \"firmwareVersion\": 783,\n" " \"attested\": {\n" " \"objectName\": \"00010203040506070809c0c1c2c3c4c5c6c7c8c9\",\n" " \"creationHash\": \"00010203040506070809d0d1d2d3d4d5d6d7d8d9\"\n" " }\n" "}"; CHECK_JSON(TPMS_ATTEST, test_json_TPMS_ATTEST_certifycreation_src, test_json_TPMS_ATTEST_certifycreation_expt); const char *test_json_TPMS_ATTEST_commandaudit_src = "{\n" " \"magic\": \"0xff544347\",\n" " \"type\": \"ST_ATTEST_COMMAND_AUDIT\",\n" " \"qualifiedSigner\": \"0x00010203040506070809a0a1a2a3a4a5a6a7a8a9\",\n" " \"extraData\": \"0x00010203040506070809b0b1b2b3b4b5b6b7b8b9\",\n" " \"clockInfo\": {\n" " \"clock\": 123,\n" " \"resetCount\": 23,\n" " \"restartCount\": 1,\n" " \"safe\": \"yes\"\n" " },\n" " \"firmwareVersion\": 783,\n" " \"attested\": {\n" " \"auditCounter\": 456,\n" " \"digestAlg\": \"sha1\",\n" " \"auditDigest\": \"0x00010203040506070809c0c1c2c3c4c5c6c7c8c9\",\n" " \"commandDigest\": \"0x00010203040506070809d0d1d2d3d4d5d6d7d8d9\"\n" " }\n" "}"; const char *test_json_TPMS_ATTEST_commandaudit_expt = "{\n" " \"magic\": \"VALUE\",\n" " \"type\": \"ATTEST_COMMAND_AUDIT\",\n" " \"qualifiedSigner\": \"00010203040506070809a0a1a2a3a4a5a6a7a8a9\",\n" " \"extraData\": \"00010203040506070809b0b1b2b3b4b5b6b7b8b9\",\n" " \"clockInfo\": {\n" " \"clock\": 123,\n" " \"resetCount\": 23,\n" " \"restartCount\": 1,\n" " \"safe\": \"YES\"\n" " },\n" " \"firmwareVersion\": 783,\n" " \"attested\": {\n" " \"auditCounter\": 456,\n" " \"digestAlg\": \"SHA1\",\n" " \"auditDigest\": \"00010203040506070809c0c1c2c3c4c5c6c7c8c9\",\n" " \"commandDigest\": \"00010203040506070809d0d1d2d3d4d5d6d7d8d9\"\n" " }\n" "}"; CHECK_JSON(TPMS_ATTEST, test_json_TPMS_ATTEST_commandaudit_src, test_json_TPMS_ATTEST_commandaudit_expt); const char *test_json_TPMS_ATTEST_time_src = "{\n" " \"magic\": \"0xff544347\",\n" " \"type\": \"ST_ATTEST_TIME\",\n" " \"qualifiedSigner\": \"0x00010203040506070809a0a1a2a3a4a5a6a7a8a9\",\n" " \"extraData\": \"0x00010203040506070809b0b1b2b3b4b5b6b7b8b9\",\n" " \"clockInfo\": {\n" " \"clock\": 123,\n" " \"resetCount\": 23,\n" " \"restartCount\": 1,\n" " \"safe\": \"yes\"\n" " },\n" " \"firmwareVersion\": 783,\n" " \"attested\": {\n" " \"time\": {\n" " \"time\": 234,\n" " \"clockInfo\": {\n" " \"clock\": 123,\n" " \"resetCount\": 23,\n" " \"restartCount\": 1,\n" " \"safe\": \"yes\"\n" " }\n" " },\n" " \"firmwareVersion\": 783\n" " }\n" "}"; const char *test_json_TPMS_ATTEST_time_expt = "{\n" " \"magic\": \"VALUE\",\n" " \"type\": \"ATTEST_TIME\",\n" " \"qualifiedSigner\": \"00010203040506070809a0a1a2a3a4a5a6a7a8a9\",\n" " \"extraData\": \"00010203040506070809b0b1b2b3b4b5b6b7b8b9\",\n" " \"clockInfo\": {\n" " \"clock\": 123,\n" " \"resetCount\": 23,\n" " \"restartCount\": 1,\n" " \"safe\": \"YES\"\n" " },\n" " \"firmwareVersion\": 783,\n" " \"attested\": {\n" " \"time\": {\n" " \"time\": 234,\n" " \"clockInfo\": {\n" " \"clock\": 123,\n" " \"resetCount\": 23,\n" " \"restartCount\": 1,\n" " \"safe\": \"YES\"\n" " }\n" " },\n" " \"firmwareVersion\": 783\n" " }\n" "}"; CHECK_JSON(TPMS_ATTEST, test_json_TPMS_ATTEST_time_src, test_json_TPMS_ATTEST_time_expt); const char *test_json_TPMS_ATTEST_certifynv_src = "{\n" " \"magic\": \"0xff544347\",\n" " \"type\": \"ST_ATTEST_NV\",\n" " \"qualifiedSigner\": \"0x00010203040506070809a0a1a2a3a4a5a6a7a8a9\",\n" " \"extraData\": \"0x00010203040506070809b0b1b2b3b4b5b6b7b8b9\",\n" " \"clockInfo\": {\n" " \"clock\": 123,\n" " \"resetCount\": 23,\n" " \"restartCount\": 1,\n" " \"safe\": \"yes\"\n" " },\n" " \"firmwareVersion\": 783,\n" " \"attested\": {\n" " \"indexName\": \"0x00010203040506070809c0c1c2c3c4c5c6c7c8c9\",\n" " \"offset\": 10,\n" " \"nvContents\": \"0x00010203040506070809d0d1d2d3d4d5d6d7d8d9\"\n" " }\n" "}"; const char *test_json_TPMS_ATTEST_certifynv_expt = "{\n" " \"magic\": \"VALUE\",\n" " \"type\": \"ATTEST_NV\",\n" " \"qualifiedSigner\": \"00010203040506070809a0a1a2a3a4a5a6a7a8a9\",\n" " \"extraData\": \"00010203040506070809b0b1b2b3b4b5b6b7b8b9\",\n" " \"clockInfo\": {\n" " \"clock\": 123,\n" " \"resetCount\": 23,\n" " \"restartCount\": 1,\n" " \"safe\": \"YES\"\n" " },\n" " \"firmwareVersion\": 783,\n" " \"attested\": {\n" " \"indexName\": \"00010203040506070809c0c1c2c3c4c5c6c7c8c9\",\n" " \"offset\": 10,\n" " \"nvContents\": \"00010203040506070809d0d1d2d3d4d5d6d7d8d9\"\n" " }\n" "}"; CHECK_JSON(TPMS_ATTEST, test_json_TPMS_ATTEST_certifynv_src, test_json_TPMS_ATTEST_certifynv_expt); const char *test_json_TPMT_KEYEDHASH_SCHEME_hmac_src = "{\n" " \"scheme\": \"HMAC\",\n" " \"details\": {\n" " \"hashAlg\": \"SHA256\"\n" " }\n" "}"; const char *test_json_TPMT_KEYEDHASH_SCHEME_hmac_expt = "{\n" " \"scheme\": \"HMAC\",\n" " \"details\": {\n" " \"hashAlg\": \"SHA256\"\n" " }\n" "}"; CHECK_JSON(TPMT_KEYEDHASH_SCHEME, test_json_TPMT_KEYEDHASH_SCHEME_hmac_src, test_json_TPMT_KEYEDHASH_SCHEME_hmac_expt); const char *test_json_TPMT_KEYEDHASH_SCHEME_xor_src = "{\n" " \"scheme\": \"XOR\",\n" " \"details\": {\n" " \"hashAlg\": \"SHA256\",\n" " \"kdf\": \"MGF1\"\n" " }\n" "}"; const char *test_json_TPMT_KEYEDHASH_SCHEME_xor_expt = "{\n" " \"scheme\": \"XOR\",\n" " \"details\": {\n" " \"hashAlg\": \"SHA256\",\n" " \"kdf\": \"MGF1\"\n" " }\n" "}"; CHECK_JSON(TPMT_KEYEDHASH_SCHEME, test_json_TPMT_KEYEDHASH_SCHEME_xor_src, test_json_TPMT_KEYEDHASH_SCHEME_xor_expt); } static void check_json_constants(void **state) { CHECK_JSON_SIMPLE(TPMI_ALG_HASH, "\"sha1\"", "\"SHA1\""); CHECK_JSON_SIMPLE(TPMI_ALG_HASH, "\"0x04\"", "\"SHA1\""); CHECK_JSON_SIMPLE(TPMI_ALG_HASH, "4", "\"SHA1\""); } static void check_json_numbers(void **state) { CHECK_JSON_SIMPLE(UINT16, "10", "10"); CHECK_JSON_SIMPLE(UINT16, "\"0x0a\"", "10"); CHECK_JSON_SIMPLE(UINT64, "10000000000000000","[2328306,1874919424]"); } static void check_json_bits(void **state) { const char *test_json_TPMA_NV_expected =\ "{" " \"PPWRITE\":0," " \"OWNERWRITE\":1," " \"AUTHWRITE\":1," " \"POLICYWRITE\":1," " \"POLICY_DELETE\":1," " \"WRITELOCKED\":0," " \"WRITEALL\":0," " \"WRITEDEFINE\":0," " \"WRITE_STCLEAR\":0," " \"GLOBALLOCK\":0," " \"PPREAD\":0," " \"OWNERREAD\":1," " \"AUTHREAD\":1," " \"POLICYREAD\":1," " \"NO_DA\":0," " \"ORDERLY\":1," " \"CLEAR_STCLEAR\":1," " \"READLOCKED\":1," " \"WRITTEN\":1," " \"PLATFORMCREATE\":0," " \"READ_STCLEAR\":0," " \"TPM2_NT\":\"COUNTER\"" "}"; const char *test_json_TPMA_NV_src_array =\ "[" " \"nv_ownerwrite\"," " \"nv_authwrite\"," " \"nv_policywrite\"," " \"nv_policy_delete\"," " \"nv_ownerread\"," " \"nv_authread\"," " \"nv_policyread\"," " \"nv_orderly\"," " \"nv_clear_stclear\"," " \"nv_readlocked\"," " \"nv_written\"," " {" " \"TPM2_NT\": \"NT_COUNTER\"" " }" "]"; const char *test_json_TPMA_NV_src_struct =\ "{" " \"TPMA_NV_OWNERWRITE\":\"YES\"," " \"TPMA_NV_AUTHWRITE\":\"yes\"," " \"TPMA_NV_POLICYWRITE\":\"TPM2_YES\"," " \"TPMA_NV_POLICY_DELETE\":\"tpm2_yes\"," " \"TPMA_NV_OWNERREAD\":\"SET\"," " \"TPMA_NV_AUTHREAD\":\"set\"," " \"TPMA_NV_POLICYREAD\":1," " \"TPMA_NV_ORDERLY\":1," " \"TPMA_NV_CLEAR_STCLEAR\":1," " \"TPMA_NV_READLOCKED\":1," " \"TPMA_NV_WRITTEN\":1," " \"TPM2_NT\":1" " }"; CHECK_JSON_SIMPLE(TPMA_NV, test_json_TPMA_NV_src_array, test_json_TPMA_NV_expected); CHECK_JSON_SIMPLE(TPMA_NV, test_json_TPMA_NV_src_struct, test_json_TPMA_NV_expected); } static void check_json_policy(void **state) { const char *test_json_policy_nv_src = \ "{" " \"description\":\"Description pol_nv\"," " \"policyDigests\":[" " ]," " \"policyAuthorizations\":[" " ]," " \"policy\":[" " {" " \"type\": \"POLICYNV\"," " \"nvPath\": \"myNV\"," " \"operandB\": \"01030304\"" " }" " ]" "}"; const char *test_json_policy_nv_expected = \ "{" " \"description\":\"Description pol_nv\"," " \"policyDigests\":[" " ]," " \"policyAuthorizations\":[" " ]," " \"policy\":[" " {" " \"type\": \"POLICYNV\"," " \"nvPath\": \"myNV\"," " \"operandB\": \"01030304\"" " }" " ]" "}"; // CHECK_JSON(TPMS_POLICY, test_json_policy_nv_src, test_json_policy_nv_expected); { TPMS_POLICY out; TSS2_RC rc; json_object *jso = json_tokener_parse(test_json_policy_nv_src); if (!jso) fprintf(stderr, "JSON parsing failed\n"); assert_non_null(jso); rc = ifapi_json_TPMS_POLICY_deserialize (jso, &out); if (rc) fprintf(stderr, "Deserialization failed\n"); assert_int_equal (rc, TSS2_RC_SUCCESS); json_object_put(jso); jso = NULL; rc = ifapi_json_TPMS_POLICY_serialize (&out, &jso); assert_int_equal (rc, TSS2_RC_SUCCESS); assert_non_null(jso); const char *jso_string = json_object_to_json_string_ext(jso, JSON_C_TO_STRING_PRETTY); assert_non_null(jso_string); char *string1 = normalize(jso_string); char *string2 = normalize(test_json_policy_nv_expected); assert_string_equal(string1, string2); json_object_put(jso); ifapi_cleanup_policy(&out); free(string1); free(string2); } const char *test_json_policy_or_src = \ "{" " \"description\":\"hareness description\"," " \"policyDigests\":[" " {" " \"hashAlg\":\"SHA256\"," " \"digest\":\"59215cb6c21a60e26b2cc479334a021113611903795507c1227659e2aef23d16\"" " }" " ]," " \"policy\":[" " {" " \"type\":\"POLICYOR\"," " \"policyDigests\":[" " {" " \"hashAlg\":\"SHA256\"," " \"digest\":\"59215cb6c21a60e26b2cc479334a021113611903795507c1227659e2aef23d16\"" " }" " ]," " \"branches\":[" " {" " \"name\":\"branch1\"," " \"description\":\"description branch 1\"," " \"policy\":[" " {" " \"type\":\"POLICYPCR\"," " \"policyDigests\":[" " {" " \"hashAlg\":\"SHA256\"," " \"digest\":\"17d552f8e39ad882f6b3c09ae139af59616bf6a63f4093d6d20e9e1b9f7cdb6e\"" " }" " ]," " \"pcrs\":[" " {" " \"pcr\":16," " \"hashAlg\":\"SHA1\"," " \"digest\":\"0000000000000000000000000000000000000000\"" " }" " ]" " }" " ]," " \"policyDigests\":[" " {" " \"hashAlg\":\"SHA256\"," " \"digest\":\"17d552f8e39ad882f6b3c09ae139af59616bf6a63f4093d6d20e9e1b9f7cdb6e\"" " }" " ]" " }," " {" " \"name\":\"branch1\"," " \"description\":\"description branch 1\"," " \"policy\":[" " {" " \"type\":\"POLICYPCR\"," " \"policyDigests\":[" " {" " \"hashAlg\":\"SHA256\"," " \"digest\":\"17d552f8e39ad882f6b3c09ae139af59616bf6a63f4093d6d20e9e1b9f7cdb6e\"" " }" " ]," " \"pcrs\":[" " {" " \"pcr\":16," " \"hashAlg\":\"SHA1\"," " \"digest\":\"0000000000000000000000000000000000000000\"" " }" " ]" " }" " ]," " \"policyDigests\":[" " {" " \"hashAlg\":\"SHA256\"," " \"digest\":\"17d552f8e39ad882f6b3c09ae139af59616bf6a63f4093d6d20e9e1b9f7cdb6e\"" " }" " ]" " }" " ]" " }" " ]" "}"; char *test_json_policy_or_expected = strdup(test_json_policy_or_src); if (test_json_policy_or_expected == NULL){ LOG_ERROR("%s", "Out of memory."); return; } // CHECK_JSON(TPMS_POLICY, test_json_policy_or_src, test_json_policy_or_expected); { TPMS_POLICY out; TSS2_RC rc; json_object *jso = json_tokener_parse(test_json_policy_or_src); if (!jso) fprintf(stderr, "JSON parsing failed\n"); assert_non_null(jso); rc = ifapi_json_TPMS_POLICY_deserialize (jso, &out); if (rc) fprintf(stderr, "Deserialization failed\n"); assert_int_equal (rc, TSS2_RC_SUCCESS); json_object_put(jso); jso = NULL; rc = ifapi_json_TPMS_POLICY_serialize (&out, &jso); assert_int_equal (rc, TSS2_RC_SUCCESS); assert_non_null(jso); const char *jso_string = json_object_to_json_string_ext(jso, JSON_C_TO_STRING_PRETTY); assert_non_null(jso_string); char *string1 = normalize(jso_string); char *string2 = normalize(test_json_policy_or_expected); assert_string_equal(string1, string2); json_object_put(jso); ifapi_cleanup_policy(&out); free(string1); free(string2); } free(test_json_policy_or_expected); } static void check_json_tpm2bs(void **state) { CHECK_JSON(TPM2B_DIGEST, "\"0x0102\"", "\"0102\""); CHECK_JSON(TPM2B_DIGEST, "\"0102\"", "\"0102\""); CHECK_JSON(TPM2B_DIGEST, "\"caffee\"", "\"caffee\""); } static void check_error(void **state) { /* Value is > then max value for UINT */ CHECK_ERROR(UINT16, "\"0x10000\"", TSS2_FAPI_RC_BAD_VALUE); CHECK_ERROR(UINT32, "\"0x100000000\"", TSS2_FAPI_RC_BAD_VALUE); /* Digest/list is too large*/ CHECK_ERROR(TPM2B_DIGEST, "\"0x0102222222222222222222222222222222222222222222222222222" "22222222222222222222222222222222222222222222222222222222222222222222222222222\"", TSS2_FAPI_RC_BAD_VALUE); /* Illegal values */ CHECK_ERROR(TPMI_ALG_HASH, "\"SHA9999\"", TSS2_FAPI_RC_BAD_VALUE); CHECK_ERROR(TPM2B_DIGEST, "\"xxxx\"", TSS2_FAPI_RC_BAD_VALUE); CHECK_ERROR(TPM2B_DIGEST, "\"0x010x\"", TSS2_FAPI_RC_BAD_VALUE); } static void check_tpmjson_tofromtxt(void **state) { const char *testcase_alg_id[] = { "\"TPM_ALG_ID_SHA1\"", "\"TPM2_ALG_ID_SHA1\"", "\"ALG_ID_SHA1\"", "\"SHA1\"", "\"ALG_SHA1\"", "\"tpm2_alg_id_sha1\"", "\"sha1\"", "\"0x0004\"" }; const char *expected_ald_id = { "\"SHA1\"" }; for (size_t i = 0; i < sizeof(testcase_alg_id) / sizeof(testcase_alg_id[0]); i++) { CHECK_JSON_SIMPLE(TPM2_ALG_ID, testcase_alg_id[i], expected_ald_id); } const char *testcase_ecc_curve[] = { "\"TPM2_ECC_NIST_P256\"", "\"ECC_NIST_P256\"", "\"NIST_P256\"", "\"0x0003\"", "\"nist_p256\"" }; const char *expected_ecc_curve = { "\"NIST_P256\"" }; for (size_t i = 0; i < sizeof(testcase_ecc_curve) / sizeof(testcase_ecc_curve[0]); i++) { CHECK_JSON_SIMPLE(TPM2_ECC_CURVE, testcase_ecc_curve[i], expected_ecc_curve); } const char *testcase_cc[] = { "\"TPM2_CC_Startup\"", "\"CC_Startup\"", "\"Startup\"", "\"0x00000144\"" }; const char *expected_cc = { "\"Startup\"" }; for (size_t i = 0; i < sizeof(testcase_cc) / sizeof(testcase_cc[0]); i++) { CHECK_JSON_SIMPLE(TPM2_CC, testcase_cc[i], expected_cc); } const char *testcase_eo[] = { "\"TPM2_EO_EQ\"", "\"EO_EQ\"", "\"EQ\"", "\"0x0000\"" }; const char *expected_eo = { "\"EQ\"" }; for (size_t i = 0; i < sizeof(testcase_eo) / sizeof(testcase_eo[0]); i++) { CHECK_JSON_SIMPLE(TPM2_EO, testcase_eo[i], expected_eo); } const char *testcase_st[] = { "\"TPM2_ST_NO_SESSIONS\"", "\"ST_NO_SESSIONS\"", "\"no_SESSIONS\"", "\"0x8001\"" }; const char *expected_st = { "\"NO_SESSIONS\"" }; for (size_t i = 0; i < sizeof(testcase_st) / sizeof(testcase_st[0]); i++) { CHECK_JSON_SIMPLE(TPM2_ST, testcase_st[i], expected_st); } const char *testcase_pt_pcr[] = { "\"TPM2_PT_PCR_EXTEND_L0\"", "\"PT_PCR_EXTEND_L0\"", "\"PCR_EXTEND_L0\"", "\"EXTEND_L0\"" }; const char *expected_pt_pcr = { "\"EXTEND_L0\"" }; for (size_t i = 0; i < sizeof(testcase_pt_pcr) / sizeof(testcase_pt_pcr[0]); i++) { CHECK_JSON_SIMPLE(TPM2_PT_PCR, testcase_pt_pcr[i], expected_pt_pcr); } const char *testcase_alg_public[] = { "\"TPM2_ALG_RSA\"", "\"ALG_RSA\"", "\"RSA\"", "\"0x0001\"" }; const char *expected_alg_public = { "\"RSA\"" }; for (size_t i = 0; i < sizeof(testcase_alg_public) / sizeof(testcase_alg_public[0]); i++) { CHECK_JSON_SIMPLE(TPMI_ALG_PUBLIC, testcase_alg_public[i], expected_alg_public); } } int main(int argc, char *argv[]) { const struct CMUnitTest tests[] = { cmocka_unit_test(check_tpmjson_tofromtxt), cmocka_unit_test(check_json_structs), cmocka_unit_test(check_json_constants), cmocka_unit_test(check_json_numbers), cmocka_unit_test(check_json_bits), cmocka_unit_test(check_json_tpm2bs), cmocka_unit_test(check_json_to_bin), cmocka_unit_test(check_bin), cmocka_unit_test(check_policy_bin), cmocka_unit_test(check_error), cmocka_unit_test(check_json_policy), }; return cmocka_run_group_tests(tests, NULL, NULL); }