blob: 443dbb4d97f81ee5811b6c16d327dee657026acf [file] [log] [blame]
/* SPDX-License-Identifier: BSD-2-Clause */
/*******************************************************************************
* Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG
* All rights reserved.
******************************************************************************/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <string.h>
#include "tpm_json_deserialize.h"
#include "ifapi_json_deserialize.h"
#include "fapi_policy.h"
#include "ifapi_config.h"
#include "ifapi_helpers.h"
#define LOGMODULE fapijson
#include "util/log.h"
#include "util/aux_util.h"
#include "tss2_mu.h"
static char *tss_const_prefixes[] = { "TPM2_ALG_", "TPM2_", "TPM_", "TPMA_", "POLICY", NULL };
/** Get the index of a sub string after a certain prefix.
*
* The prefixes from table tss_const_prefixes will be used for case
* insensitive comparison.
*
* param[in] token the token with a potential prefix.
* @retval the position of the sub string after the prefix.
* @retval 0 if no prefix is found.
*/
static int
get_token_start_idx(const char *token)
{
int itoken = 0;
char *entry;
int i;
for (i = 0, entry = tss_const_prefixes[0]; entry != NULL;
i++, entry = tss_const_prefixes[i]) {
if (strncasecmp(token, entry, strlen(entry)) == 0) {
itoken += strlen(entry);
break;
}
}
return itoken;
}
/** Get number from a string.
*
* A string which represents a number or hex number (prefix 0x) is converted
* to an int64 number.
*
* param[in] token the string representing the number.
* param[out] num the converted number.
* @retval true if token represents a number
* @retval false if token does not represent a number.
*/
static bool
get_number(const char *token, int64_t *num)
{
int itoken = 0;
int pos = 0;
if (strncmp(token, "0x", 2) == 0) {
itoken = 2;
sscanf(&token[itoken], "%"PRIx64"%n", num, &pos);
} else {
sscanf(&token[itoken], "%"PRId64"%n", num, &pos);
}
if ((size_t)pos == strlen(token) - itoken)
return true;
else
return false;
}
/** Deserialize a character string.
*
* @param[in] jso json string object.
* @param[out] out the pointer to the created string.
* @retval TSS2_RC_SUCCESS if the function call was a success.
* @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
*/
TSS2_RC
ifapi_json_char_deserialize(
json_object *jso,
char **out)
{
*out = strdup(json_object_get_string(jso));
return_if_null(*out, "Out of memory.", TSS2_FAPI_RC_MEMORY);
return TSS2_RC_SUCCESS;
}
/** Deserialize a IFAPI_KEY json object.
*
* @param[in] jso the json object to be deserialized.
* @param[out] out the deserialzed binary object.
* @retval TSS2_RC_SUCCESS if the function call was a success.
* @retval TSS2_FAPI_RC_BAD_VALUE if the json object can't be deserialized.
* @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
* @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
*/
TSS2_RC
ifapi_json_IFAPI_KEY_deserialize(json_object *jso, IFAPI_KEY *out)
{
json_object *jso2;
TSS2_RC r;
LOG_TRACE("call");
return_if_null(out, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
if (!ifapi_get_sub_object(jso, "persistent_handle", &jso2)) {
LOG_ERROR("Bad value");
return TSS2_FAPI_RC_BAD_VALUE;
}
r = ifapi_json_UINT32_deserialize(jso2, &out->persistent_handle);
return_if_error(r, "BAD VALUE");
if (ifapi_get_sub_object(jso, "with_auth", &jso2)) {
r = ifapi_json_TPMI_YES_NO_deserialize(jso2, &out->with_auth);
return_if_error(r, "BAD VALUE");
} else {
out->with_auth = TPM2_NO;
}
if (!ifapi_get_sub_object(jso, "public", &jso2)) {
LOG_ERROR("Bad value");
return TSS2_FAPI_RC_BAD_VALUE;
}
r = ifapi_json_TPM2B_PUBLIC_deserialize(jso2, &out->public);
return_if_error(r, "BAD VALUE");
if (!ifapi_get_sub_object(jso, "serialization", &jso2)) {
LOG_ERROR("Bad value");
return TSS2_FAPI_RC_BAD_VALUE;
}
r = ifapi_json_UINT8_ARY_deserialize(jso2, &out->serialization);
return_if_error(r, "BAD VALUE");
if (!ifapi_get_sub_object(jso, "private", &jso2)) {
memset(&out->private, 0, sizeof(UINT8_ARY));
} else {
r = ifapi_json_UINT8_ARY_deserialize(jso2, &out->private);
return_if_error(r, "BAD VALUE");
}
if (!ifapi_get_sub_object(jso, "appData", &jso2)) {
memset(&out->appData, 0, sizeof(UINT8_ARY));
} else {
r = ifapi_json_UINT8_ARY_deserialize(jso2, &out->appData);
return_if_error(r, "BAD VALUE");
}
if (!ifapi_get_sub_object(jso, "policyInstance", &jso2)) {
LOG_ERROR("Bad value");
return TSS2_FAPI_RC_BAD_VALUE;
}
r = ifapi_json_char_deserialize(jso2, &out->policyInstance);
return_if_error(r, "BAD VALUE");
if (ifapi_get_sub_object(jso, "creationData", &jso2)) {
r = ifapi_json_TPM2B_CREATION_DATA_deserialize(jso2, &out->creationData);
return_if_error(r, "BAD VALUE");
} else {
memset(&out->creationData, 0, sizeof(TPM2B_CREATION_DATA));
}
if (ifapi_get_sub_object(jso, "creationTicket", &jso2)) {
r = ifapi_json_TPMT_TK_CREATION_deserialize(jso2, &out->creationTicket);
return_if_error(r, "BAD VALUE");
} else {
memset(&out->creationData, 0, sizeof(TPMT_TK_CREATION));
}
if (!ifapi_get_sub_object(jso, "description", &jso2)) {
LOG_ERROR("Bad value");
return TSS2_FAPI_RC_BAD_VALUE;
}
r = ifapi_json_char_deserialize(jso2, &out->description);
return_if_error(r, "BAD VALUE");
if (!ifapi_get_sub_object(jso, "certificate", &jso2)) {
LOG_ERROR("Bad value");
return TSS2_FAPI_RC_BAD_VALUE;
}
r = ifapi_json_char_deserialize(jso2, &out->certificate);
return_if_error(r, "BAD VALUE");
if (out->public.publicArea.type != TPM2_ALG_KEYEDHASH) {
/* Keyed hash objects to not need a signing scheme. */
if (!ifapi_get_sub_object(jso, "signing_scheme", &jso2)) {
LOG_ERROR("Bad value");
return TSS2_FAPI_RC_BAD_VALUE;
}
r = ifapi_json_TPMT_SIG_SCHEME_deserialize(jso2, &out->signing_scheme);
return_if_error(r, "BAD VALUE");
}
if (!ifapi_get_sub_object(jso, "name", &jso2)) {
LOG_ERROR("Bad value");
return TSS2_FAPI_RC_BAD_VALUE;
}
r = ifapi_json_TPM2B_NAME_deserialize(jso2, &out->name);
return_if_error(r, "BAD VALUE");
if (ifapi_get_sub_object(jso, "reset_count", &jso2)) {
r = ifapi_json_UINT32_deserialize(jso2, &out->reset_count);
return_if_error(r, "BAD VALUE");
} else {
out->reset_count = 0;
}
LOG_TRACE("true");
return TSS2_RC_SUCCESS;
}
/** Deserialize a import data to create a IFAPI_KEY json object.
*
* @param[in] jso the json object to be deserialized.
* @param[out] out the deserialzed binary object.
* @retval TSS2_RC_SUCCESS if the function call was a success.
* @retval TSS2_FAPI_RC_BAD_VALUE if the json object can't be deserialized.
* @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
* @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
*/
TSS2_RC
ifapi_json_import_IFAPI_KEY_deserialize(json_object *jso, IFAPI_KEY *out)
{
json_object *jso2;
TSS2_RC r;
UINT8_ARY public_blob = { .size = 0, .buffer = NULL };
UINT8_ARY private_blob = { .size = 0, .buffer = NULL };
TPM2B_PRIVATE private;
size_t offset = 0;
TPMI_YES_NO noauth;
LOG_TRACE("call");
return_if_null(out, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
memset(out, 0, sizeof(IFAPI_KEY));
if (ifapi_get_sub_object(jso, "noauth", &jso2)) {
r = ifapi_json_TPMI_YES_NO_deserialize(jso2, &noauth);
return_if_error(r, "BAD VALUE");
if (noauth == TPM2_YES)
out->with_auth = TPM2_NO;
else
out->with_auth = TPM2_YES;
} else {
out->with_auth = TPM2_YES;
}
if (!ifapi_get_sub_object(jso, "public", &jso2)) {
LOG_ERROR("Bad value");
return TSS2_FAPI_RC_BAD_VALUE;
}
r = ifapi_json_UINT8_ARY_deserialize(jso2, &public_blob);
return_if_error(r, "BAD VALUE");
/* Get structure with public data from binary blob. */
r = Tss2_MU_TPM2B_PUBLIC_Unmarshal(public_blob.buffer, public_blob.size,
&offset, &out->public);
return_if_error(r, "Invalid public data.");
SAFE_FREE(public_blob.buffer);
if (!ifapi_get_sub_object(jso, "private", &jso2)) {
memset(&out->private, 0, sizeof(UINT8_ARY));
} else {
/* Deserialize complete binary blob. */
r = ifapi_json_UINT8_ARY_deserialize(jso2, &private_blob);
return_if_error(r, "BAD VALUE");
offset = 0;
/* Extract private data from blob with size. */
r = Tss2_MU_TPM2B_PRIVATE_Unmarshal(private_blob.buffer, private_blob.size,
&offset, &private);
goto_if_error(r, "BAD VALUE", error_cleanup);
SAFE_FREE(private_blob.buffer);
/* Copy private data into object structure. */
out->private.size = private.size;
out->private.buffer = malloc(private.size);
goto_if_null2(out->private.buffer, "Out of memory", r, TSS2_FAPI_RC_MEMORY,
error_cleanup);
memcpy(out->private.buffer, &private.buffer[0], private.size);
}
strdup_check(out->policyInstance, "", r, error_cleanup);
strdup_check(out->description, "", r, error_cleanup);
strdup_check(out->certificate, "", r, error_cleanup);
LOG_TRACE("true");
return TSS2_RC_SUCCESS;
error_cleanup:
SAFE_FREE(public_blob.buffer);
SAFE_FREE(private_blob.buffer);
return r;
}
/** Deserialize a IFAPI_EXT_PUB_KEY json object.
*
* @param[in] jso the json object to be deserialized.
* @param[out] out the deserialzed binary object.
* @retval TSS2_RC_SUCCESS if the function call was a success.
* @retval TSS2_FAPI_RC_BAD_VALUE if the json object can't be deserialized.
* @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
* @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
*/
TSS2_RC
ifapi_json_IFAPI_EXT_PUB_KEY_deserialize(json_object *jso,
IFAPI_EXT_PUB_KEY *out)
{
json_object *jso2;
TSS2_RC r;
LOG_TRACE("call");
return_if_null(out, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
if (!ifapi_get_sub_object(jso, "pem_ext_public", &jso2)) {
LOG_ERROR("Bad value");
return TSS2_FAPI_RC_BAD_VALUE;
}
r = ifapi_json_char_deserialize(jso2, &out->pem_ext_public);
return_if_error(r, "BAD VALUE");
if (ifapi_get_sub_object(jso, "certificate", &jso2)) {
r = ifapi_json_char_deserialize(jso2, &out->certificate);
return_if_error(r, "BAD VALUE");
} else {
out->certificate = NULL;
}
if (ifapi_get_sub_object(jso, "public", &jso2)) {
r = ifapi_json_TPM2B_PUBLIC_deserialize(jso2, &out->public);
return_if_error(r, "BAD VALUE");
} else {
memset(&out->public, 0, sizeof(TPM2B_PUBLIC));
}
LOG_TRACE("true");
return TSS2_RC_SUCCESS;
}
/** Deserialize a IFAPI_NV json object.
*
* @param[in] jso the json object to be deserialized.
* @param[out] out the deserialzed binary object.
* @retval TSS2_RC_SUCCESS if the function call was a success.
* @retval TSS2_FAPI_RC_BAD_VALUE if the json object can't be deserialized.
* @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
* @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
*/
TSS2_RC
ifapi_json_IFAPI_NV_deserialize(json_object *jso, IFAPI_NV *out)
{
json_object *jso2;
TSS2_RC r;
LOG_TRACE("call");
return_if_null(out, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
if (!ifapi_get_sub_object(jso, "appData", &jso2)) {
memset(&out->appData, 0, sizeof(UINT8_ARY));
} else {
r = ifapi_json_UINT8_ARY_deserialize(jso2, &out->appData);
return_if_error(r, "BAD VALUE");
}
if (ifapi_get_sub_object(jso, "with_auth", &jso2)) {
r = ifapi_json_TPMI_YES_NO_deserialize(jso2, &out->with_auth);
return_if_error(r, "BAD VALUE");
} else {
out->with_auth = TPM2_NO;
}
if (!ifapi_get_sub_object(jso, "public", &jso2)) {
LOG_ERROR("Bad value");
return TSS2_FAPI_RC_BAD_VALUE;
}
r = ifapi_json_TPM2B_NV_PUBLIC_deserialize(jso2, &out->public);
return_if_error(r, "BAD VALUE");
if (!ifapi_get_sub_object(jso, "serialization", &jso2)) {
LOG_ERROR("Bad value");
return TSS2_FAPI_RC_BAD_VALUE;
}
r = ifapi_json_UINT8_ARY_deserialize(jso2, &out->serialization);
return_if_error(r, "BAD VALUE");
if (!ifapi_get_sub_object(jso, "hierarchy", &jso2)) {
LOG_ERROR("Bad value");
return TSS2_FAPI_RC_BAD_VALUE;
}
r = ifapi_json_UINT32_deserialize(jso2, &out->hierarchy);
return_if_error(r, "BAD VALUE");
if (!ifapi_get_sub_object(jso, "policyInstance", &jso2)) {
LOG_ERROR("Bad value");
return TSS2_FAPI_RC_BAD_VALUE;
}
r = ifapi_json_char_deserialize(jso2, &out->policyInstance);
return_if_error(r, "BAD VALUE");
if (!ifapi_get_sub_object(jso, "description", &jso2)) {
LOG_ERROR("Bad value");
return TSS2_FAPI_RC_BAD_VALUE;
}
r = ifapi_json_char_deserialize(jso2, &out->description);
return_if_error(r, "BAD VALUE");
return_if_error(r, "BAD VALUE");
if (ifapi_get_sub_object(jso, "event_log", &jso2)) {
r = ifapi_json_char_deserialize(jso2, &out->event_log);
return_if_error(r, "BAD VALUE");
} else {
out->event_log = NULL;
}
LOG_TRACE("true");
return TSS2_RC_SUCCESS;
}
/** Deserialize a IFAPI_NV json object.
*
* @param[in] jso the json object to be deserialized.
* @param[out] out the deserialzed binary object.
* @retval TSS2_RC_SUCCESS if the function call was a success.
* @retval TSS2_FAPI_RC_BAD_VALUE if the json object can't be deserialized.
* @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
* @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
*/
TSS2_RC
ifapi_json_IFAPI_HIERARCHY_deserialize(json_object *jso, IFAPI_HIERARCHY *out)
{
json_object *jso2;
TSS2_RC r;
LOG_TRACE("call");
return_if_null(out, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
if (ifapi_get_sub_object(jso, "with_auth", &jso2)) {
r = ifapi_json_TPMI_YES_NO_deserialize(jso2, &out->with_auth);
return_if_error(r, "BAD VALUE");
} else {
out->with_auth = TPM2_NO;
}
if (!ifapi_get_sub_object(jso, "authPolicy", &jso2)) {
LOG_ERROR("Bad value");
return TSS2_FAPI_RC_BAD_VALUE;
}
r = ifapi_json_TPM2B_DIGEST_deserialize(jso2, &out->authPolicy);
return_if_error(r, "BAD VALUE");
if (!ifapi_get_sub_object(jso, "description", &jso2)) {
LOG_ERROR("Bad value");
return TSS2_FAPI_RC_BAD_VALUE;
}
r = ifapi_json_char_deserialize(jso2, &out->description);
return_if_error(r, "BAD VALUE");
if (ifapi_get_sub_object(jso, "esysHandle", &jso2)) {
r = ifapi_json_UINT32_deserialize(jso2, &out->esysHandle);
return_if_error(r, "BAD VALUE");
} else {
out->esysHandle = ESYS_TR_RH_OWNER;
}
LOG_TRACE("true");
return TSS2_RC_SUCCESS;
}
/** Deserialize a FAPI_QUOTE_INFO json object.
*
* @param[in] jso the json object to be deserialized.
* @param[out] out the deserialzed binary object.
* @retval TSS2_RC_SUCCESS if the function call was a success.
* @retval TSS2_FAPI_RC_BAD_VALUE if the json object can't be deserialized.
* @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
*/
TSS2_RC
ifapi_json_FAPI_QUOTE_INFO_deserialize(json_object *jso, FAPI_QUOTE_INFO *out)
{
json_object *jso2;
TSS2_RC r;
LOG_TRACE("call");
return_if_null(out, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
if (!ifapi_get_sub_object(jso, "sig_scheme", &jso2)) {
LOG_ERROR("Bad value");
return TSS2_FAPI_RC_BAD_VALUE;
}
r = ifapi_json_TPMT_SIG_SCHEME_deserialize(jso2, &out->sig_scheme);
return_if_error(r, "BAD VALUE");
if (!ifapi_get_sub_object(jso, "attest", &jso2)) {
LOG_ERROR("Bad value");
return TSS2_FAPI_RC_BAD_VALUE;
}
r = ifapi_json_TPMS_ATTEST_deserialize(jso2, &out->attest);
return_if_error(r, "BAD VALUE");
LOG_TRACE("true");
return TSS2_RC_SUCCESS;
}
/** Deserialize a IFAPI_DUPLICATE json object.
*
* @param[in] jso the json object to be deserialized.
* @param[out] out the deserialzed binary object.
* @retval TSS2_RC_SUCCESS if the function call was a success.
* @retval TSS2_FAPI_RC_BAD_VALUE if the json object can't be deserialized.
* @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
* @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
*/
TSS2_RC
ifapi_json_IFAPI_DUPLICATE_deserialize(json_object *jso, IFAPI_DUPLICATE *out)
{
json_object *jso2;
TSS2_RC r;
LOG_TRACE("call");
return_if_null(out, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
if (!ifapi_get_sub_object(jso, "duplicate", &jso2)) {
LOG_ERROR("Bad value");
return TSS2_FAPI_RC_BAD_VALUE;
}
r = ifapi_json_TPM2B_PRIVATE_deserialize(jso2, &out->duplicate);
return_if_error(r, "BAD VALUE");
if (!ifapi_get_sub_object(jso, "encrypted_seed", &jso2)) {
LOG_ERROR("Bad value");
return TSS2_FAPI_RC_BAD_VALUE;
}
r = ifapi_json_TPM2B_ENCRYPTED_SECRET_deserialize(jso2, &out->encrypted_seed);
return_if_error(r, "BAD VALUE");
if (ifapi_get_sub_object(jso, "certificate", &jso2)) {
r = ifapi_json_char_deserialize(jso2, &out->certificate);
return_if_error(r, "BAD VALUE");
} else {
out->certificate = NULL;
}
if (!ifapi_get_sub_object(jso, "public", &jso2)) {
LOG_ERROR("Bad value");
return TSS2_FAPI_RC_BAD_VALUE;
}
r = ifapi_json_TPM2B_PUBLIC_deserialize(jso2, &out->public);
return_if_error(r, "BAD VALUE");
if (!ifapi_get_sub_object(jso, "public_parent", &jso2)) {
LOG_ERROR("Bad value");
return TSS2_FAPI_RC_BAD_VALUE;
}
r = ifapi_json_TPM2B_PUBLIC_deserialize(jso2, &out->public_parent);
return_if_error(r, "BAD VALUE");
if (ifapi_get_sub_object(jso, "policy", &jso2)) {
out->policy = calloc(1, sizeof(TPMS_POLICY));
goto_if_null2(out->policy, "Out of memory.", r, TSS2_FAPI_RC_MEMORY,
error_cleanup);
r = ifapi_json_TPMS_POLICY_deserialize(jso2, out->policy);
goto_if_error(r, "Deserialize policy.", error_cleanup);
} else {
out->policy = NULL;
}
return TSS2_RC_SUCCESS;
error_cleanup:
SAFE_FREE(out->policy);
return r;
}
/** Deserialize a IFAPI_OBJECT_TYPE_CONSTANT json object.
*
* @param[in] jso the json object to be deserialized.
* @param[out] out the deserialzed binary object.
* @retval TSS2_RC_SUCCESS if the function call was a success.
* @retval TSS2_FAPI_RC_BAD_VALUE if the json object can't be deserialized.
*/
TSS2_RC
ifapi_json_IFAPI_OBJECT_TYPE_CONSTANT_deserialize(json_object *jso,
IFAPI_OBJECT_TYPE_CONSTANT *out)
{
LOG_TRACE("call");
const char *token = json_object_get_string(jso);
int64_t i64;
if (get_number(token, &i64)) {
*out = (IFAPI_OBJECT_TYPE_CONSTANT) i64;
if ((int64_t)*out != i64) {
LOG_ERROR("Bad value");
return TSS2_FAPI_RC_BAD_VALUE;
}
return TSS2_RC_SUCCESS;
} else {
LOG_ERROR("Bad value");
return TSS2_FAPI_RC_BAD_VALUE;
}
}
/** Deserialize a IFAPI_OBJECT json object.
*
* @param[in] jso the json object to be deserialized.
* @param[out] out the deserialzed binary object.
* @retval TSS2_RC_SUCCESS if the function call was a success.
* @retval TSS2_FAPI_RC_BAD_VALUE if the json object can't be deserialized.
* @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
* @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
* @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
*/
TSS2_RC
ifapi_json_IFAPI_OBJECT_deserialize(json_object *jso, IFAPI_OBJECT *out)
{
json_object *jso2;
TSS2_RC r;
LOG_TRACE("call");
return_if_null(out, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
if (!ifapi_get_sub_object(jso, "objectType", &jso2)) {
LOG_ERROR("Bad value");
return TSS2_FAPI_RC_BAD_VALUE;
}
r = ifapi_json_IFAPI_OBJECT_TYPE_CONSTANT_deserialize(jso2, &out->objectType);
return_if_error(r, "BAD VALUE");
switch (out->objectType) {
case IFAPI_NV_OBJ:
r = ifapi_json_IFAPI_NV_deserialize(jso, &out->misc.nv);
return_if_error(r, "BAD VALUE");
break;
case IFAPI_DUPLICATE_OBJ:
r = ifapi_json_IFAPI_DUPLICATE_deserialize(jso, &out->misc.key_tree);
return_if_error(r, "BAD VALUE");
break;
case IFAPI_EXT_PUB_KEY_OBJ:
r = ifapi_json_IFAPI_EXT_PUB_KEY_deserialize(jso, &out->misc.ext_pub_key);
return_if_error(r, "BAD VALUE");
break;
case IFAPI_HIERARCHY_OBJ:
r = ifapi_json_IFAPI_HIERARCHY_deserialize(jso, &out->misc.hierarchy);
return_if_error(r, "BAD VALUE");
r = ifapi_set_name_hierarchy_object(out);
return_if_error(r, "Bad hierarchy.");
break;
case IFAPI_KEY_OBJ:
r = ifapi_json_IFAPI_KEY_deserialize(jso, &out->misc.key);
return_if_error(r, "BAD VALUE");
break;
default:
goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Invalid call deserialize",
cleanup);
}
if (ifapi_get_sub_object(jso, "system", &jso2)) {
r = ifapi_json_TPMI_YES_NO_deserialize(jso2, &out->system);
return_if_error(r, "BAD VALUE");
} else {
out->system = TPM2_NO;
}
if (ifapi_get_sub_object(jso, "policy", &jso2)) {
out->policy = calloc(1, sizeof(TPMS_POLICY));
goto_if_null2(out->policy, "Out of memory.", r, TSS2_FAPI_RC_MEMORY,
cleanup);
r = ifapi_json_TPMS_POLICY_deserialize(jso2, out->policy);
goto_if_error(r, "Deserialize policy.", cleanup);
} else {
out->policy = NULL;
}
return TSS2_RC_SUCCESS;
cleanup:
SAFE_FREE(out->policy);
return r;
}
/** Deserialize a IFAPI_EVENT_TYPE json object.
*
* @param[in] jso the json object to be deserialized.
* @param[out] out the deserialzed binary object.
* @retval TSS2_RC_SUCCESS if the function call was a success.
* @retval TSS2_FAPI_RC_BAD_VALUE if the json object can't be deserialized.
*/
TSS2_RC
ifapi_json_IFAPI_EVENT_TYPE_deserialize(json_object *jso, IFAPI_EVENT_TYPE *out)
{
LOG_TRACE("call");
return ifapi_json_IFAPI_EVENT_TYPE_deserialize_txt(jso, out);
}
typedef struct {
IFAPI_EVENT_TYPE in;
char *name;
} IFAPI_IFAPI_EVENT_TYPE_ASSIGN;
static IFAPI_IFAPI_EVENT_TYPE_ASSIGN deserialize_IFAPI_EVENT_TYPE_tab[] = {
{ IFAPI_IMA_EVENT_TAG, "ima-legacy" },
{ IFAPI_TSS_EVENT_TAG, "tss2" },
};
/** Deserialize a json object of type IFAPI_EVENT_TYPE.
*
* @param[in] jso the json object to be deserialized.
* @param[out] out the deserialzed binary object.
* @retval TSS2_RC_SUCCESS if the function call was a success.
* @retval TSS2_FAPI_RC_BAD_VALUE if the json object can't be deserialized.
*/
TSS2_RC
ifapi_json_IFAPI_EVENT_TYPE_deserialize_txt(json_object *jso,
IFAPI_EVENT_TYPE *out)
{
LOG_TRACE("call");
const char *token = json_object_get_string(jso);
int64_t i64;
if (get_number(token, &i64)) {
*out = (IFAPI_EVENT_TYPE) i64;
if ((int64_t)*out != i64) {
LOG_ERROR("Bad value");
return TSS2_FAPI_RC_BAD_VALUE;
}
return TSS2_RC_SUCCESS;
} else {
int itoken = get_token_start_idx(token);
size_t i;
size_t n = sizeof(deserialize_IFAPI_EVENT_TYPE_tab) /
sizeof(deserialize_IFAPI_EVENT_TYPE_tab[0]);
size_t size = strlen(token) - itoken;
for (i = 0; i < n; i++) {
if (strncasecmp(&token[itoken],
&deserialize_IFAPI_EVENT_TYPE_tab[i].name[0],
size) == 0) {
*out = deserialize_IFAPI_EVENT_TYPE_tab[i].in;
return TSS2_RC_SUCCESS;
}
}
return_error(TSS2_FAPI_RC_BAD_VALUE, "Undefined constant.");
}
}
/** Deserialize a IFAPI_TSS_EVENT json object.
*
* @param[in] jso the json object to be deserialized.
* @param[out] out the deserialzed binary object.
* @retval TSS2_RC_SUCCESS if the function call was a success.
* @retval TSS2_FAPI_RC_BAD_VALUE if the json object can't be deserialized.
* @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
* @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
*/
TSS2_RC
ifapi_json_IFAPI_TSS_EVENT_deserialize(json_object *jso, IFAPI_TSS_EVENT *out)
{
json_object *jso2;
TSS2_RC r;
LOG_TRACE("call");
return_if_null(out, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
if (!ifapi_get_sub_object(jso, "data", &jso2)) {
LOG_ERROR("Bad value");
return TSS2_FAPI_RC_BAD_VALUE;
}
r = ifapi_json_TPM2B_EVENT_deserialize(jso2, &out->data);
return_if_error(r, "BAD VALUE");
if (!ifapi_get_sub_object(jso, "event", &jso2)) {
out->event = NULL;
} else {
/* out->event is a special case. It can be an arbitrary
JSON object. Since FAPI does not access its internals
we just store its string represenation here. */
out->event = strdup(json_object_to_json_string_ext(jso2,
JSON_C_TO_STRING_PRETTY));
return_if_null(out->event, "OOM", TSS2_FAPI_RC_MEMORY);
}
LOG_TRACE("true");
return TSS2_RC_SUCCESS;
}
/** Deserialize a IFAPI_IMA_EVENT json object.
*
* @param[in] jso the json object to be deserialized.
* @param[out] out the deserialzed binary object.
* @retval TSS2_RC_SUCCESS if the function call was a success.
* @retval TSS2_FAPI_RC_BAD_VALUE if the json object can't be deserialized.
* @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
* @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
*/
TSS2_RC
ifapi_json_IFAPI_IMA_EVENT_deserialize(json_object *jso, IFAPI_IMA_EVENT *out)
{
json_object *jso2;
TSS2_RC r;
LOG_TRACE("call");
return_if_null(out, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
if (!ifapi_get_sub_object(jso, "eventData", &jso2)) {
LOG_ERROR("Bad value");
return TSS2_FAPI_RC_BAD_VALUE;
}
r = ifapi_json_TPM2B_DIGEST_deserialize(jso2, &out->eventData);
return_if_error(r, "BAD VALUE");
if (!ifapi_get_sub_object(jso, "eventName", &jso2)) {
LOG_ERROR("Bad value");
return TSS2_FAPI_RC_BAD_VALUE;
}
r = ifapi_json_char_deserialize(jso2, &out->eventName);
return_if_error(r, "BAD VALUE");
LOG_TRACE("true");
return TSS2_RC_SUCCESS;
}
/** Deserialize a IFAPI_EVENT_UNION json object.
*
* This functions expects the Bitfield to be encoded as unsigned int in host-endianess.
* @param[in] jso the json object to be deserialized.
* @param[in] selector the event type.
* @param[out] out the deserialzed binary object.
* @retval TSS2_RC_SUCCESS if the function call was a success.
* @retval TSS2_FAPI_RC_BAD_VALUE if the json object can't be deserialized.
* @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
* @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
*/
TSS2_RC
ifapi_json_IFAPI_EVENT_UNION_deserialize(
UINT32 selector,
json_object *jso,
IFAPI_EVENT_UNION *out)
{
LOG_TRACE("call");
switch (selector) {
case IFAPI_TSS_EVENT_TAG:
return ifapi_json_IFAPI_TSS_EVENT_deserialize(jso, &out->tss_event);
case IFAPI_IMA_EVENT_TAG:
return ifapi_json_IFAPI_IMA_EVENT_deserialize(jso, &out->ima_event);
default:
LOG_TRACE("false");
return TSS2_FAPI_RC_BAD_VALUE;
};
}
/** Deserialize a IFAPI_EVENT json object.
*
* @param[in] jso the json object to be deserialized.
* @param[out] out the deserialzed binary object.
* @retval TSS2_RC_SUCCESS if the function call was a success.
* @retval TSS2_FAPI_RC_BAD_VALUE if the json object can't be deserialized.
* @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
* @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
*/
TSS2_RC
ifapi_json_IFAPI_EVENT_deserialize(json_object *jso, IFAPI_EVENT *out)
{
json_object *jso2;
TSS2_RC r;
LOG_TRACE("call");
return_if_null(out, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
if (!ifapi_get_sub_object(jso, "recnum", &jso2)) {
LOG_ERROR("Bad value");
return TSS2_FAPI_RC_BAD_VALUE;
}
r = ifapi_json_UINT32_deserialize(jso2, &out->recnum);
return_if_error(r, "BAD VALUE");
if (!ifapi_get_sub_object(jso, "pcr", &jso2)) {
LOG_ERROR("Bad value");
return TSS2_FAPI_RC_BAD_VALUE;
}
r = ifapi_json_TPM2_HANDLE_deserialize(jso2, &out->pcr);
return_if_error(r, "BAD VALUE");
if (!ifapi_get_sub_object(jso, "digests", &jso2)) {
LOG_ERROR("Bad value");
return TSS2_FAPI_RC_BAD_VALUE;
}
r = ifapi_json_TPML_DIGEST_VALUES_deserialize(jso2, &out->digests);
return_if_error(r, "BAD VALUE");
if (!ifapi_get_sub_object(jso, "type", &jso2)) {
LOG_ERROR("Bad value");
return TSS2_FAPI_RC_BAD_VALUE;
}
r = ifapi_json_IFAPI_EVENT_TYPE_deserialize(jso2, &out->type);
return_if_error(r, "BAD VALUE");
if (!ifapi_get_sub_object(jso, "sub_event", &jso2)) {
LOG_ERROR("Bad value");
return TSS2_FAPI_RC_BAD_VALUE;
}
r = ifapi_json_IFAPI_EVENT_UNION_deserialize(out->type, jso2, &out->sub_event);
return_if_error(r, "BAD VALUE");
LOG_TRACE("true");
return TSS2_RC_SUCCESS;
}