/* 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 <ctype.h>

#include "tpm_json_deserialize.h"
#define LOGMODULE fapijson
#include "util/log.h"
#include "util/aux_util.h"

/** Strip a prefix from the input
 *
 * Strip the provided prefixes from the provided
 * input string and return the substring.
 *
 * @param[in] in The input string to strip the prefix from
 * @param[in] ... A list of prefixes to string from the input string
 * @return The prefix cleared substring
 */
static const char *
strip_prefix(const char *in, ...)
{
    va_list ap;
    const char *prefix;

    if (!in)
        return NULL;

    va_start(ap, in);
    while ((prefix = va_arg(ap, const char *)) != NULL) {
        if (strncasecmp(in, prefix, strlen(prefix)) == 0) {
            in = &in[strlen(prefix)];
        }
    }
    va_end(ap);

    return in;
}

/* Deserialize according to the rules of parenttype and then filter against values
   provided in the ... list. */
#define SUBTYPE_FILTER(type, parenttype, ...) \
    TSS2_RC r; \
    type tab[] = { __VA_ARGS__ }; \
    type v; \
    r = ifapi_json_ ## parenttype ## _deserialize(jso, &v); \
    return_if_error(r, "Bad value"); \
    for (size_t i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) { \
        if (v == tab[i]) { \
            *out = v; \
            return TSS2_RC_SUCCESS; \
        } \
    } \
    LOG_ERROR("Bad sub-value"); \
    return TSS2_FAPI_RC_BAD_VALUE;

/** Deserialize a TPMS_EMPTY .
 *
 * @param[out] out not used.
 * @param[in]  jso not used.
 */
TSS2_RC
ifapi_json_TPMS_EMPTY_deserialize(json_object *jso, TPMS_EMPTY *out)
{
    (void)(out);
    (void)(jso);
    LOG_TRACE("call");
    return TSS2_RC_SUCCESS;
}

/** Convert a byte array in character representation to binary.
 *
 * @param[in]  hex the character representation of the byte array
 * @param[in]  vlen the maximal length of the binary byte array.
 * @param[out] val the byte array.
 * @retval TSS2_RC_SUCCESS if the function call was a success.
 * @retval TSS2_FAPI_RC_BAD_VALUE if the character representation is too long.
 */
static TSS2_RC
ifapi_hex_to_byte_ary(const char hex[], UINT32 vlen, BYTE val[])
{
    UINT32 j;

    if (vlen < strlen(hex) / 2) {
        LOG_ERROR("Hex string too long. (%zu > %"PRIu32")", strlen(hex) / 2, vlen);
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    for (j = 0; j < vlen
            && 2 * j < strlen(hex); j++) { //convert hex-Argv to byte array
        if (!isxdigit(hex[2 * j]) || (!(hex[2 * j + 1] == 0)
                                      && !isxdigit(hex[2 * j + 1]))) {
            LOG_ERROR("Error in value (%i)", j);
            return TSS2_FAPI_RC_BAD_VALUE;
        }
        val[j] = hex[2 * j] < 65 ? hex[2 * j] - 48 :
                 hex[2 * j] < 97 ? hex[2 * j] - 65 + 10 : hex[2 * j] - 97 + 10;
        val[j] *= 16;
        if (hex[2 * j + 1] != 0)
            val[j] += hex[2 * j + 1] < 65 ? hex[2 * j + 1] - 48 :
                      hex[2 * j + 1] < 97 ? hex[2 * j + 1] - 65 + 10 : hex[2 * j + 1] - 97 + 10;
    }
    for (; j < vlen; j++) {    //Padd with 0
        val[j] = 0;
    }
    return TSS2_RC_SUCCESS;
}

/** Deserialize a json array of bytes.
 *
 * @param[in] jso the parent object of the json byte array.
 * @param[in] max maximal size of the deserialized object.
 * @param[out] out* Pointer to the deserialized byte array.
 * @param[out] out_size the length of the deserialized byte array.
 * @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_byte_deserialize(
    json_object *jso,
    UINT32 max,
    BYTE *out,
    UINT16 *out_size)
{
    TSS2_RC r;

    json_type jso_type = json_object_get_type(jso);
    if (jso_type == json_type_array) {
        r = ifapi_json_BYTE_array_deserialize(max, jso, out);
        return_if_error(r, "BAD VALUE");
        *out_size = json_object_array_length(jso);
    } else if (jso_type == json_type_string) {
        const char *token = json_object_get_string(jso);
        int itoken = 0;
        if (strncmp(token, "0x", 2) == 0)
            itoken = 2;
        r = ifapi_hex_to_byte_ary(&token[itoken], max, out);
        *out_size = (strlen(token) - itoken) / 2;
        return_if_error(r, "Error convert hex digest to binary.");
    }
    return TSS2_RC_SUCCESS;
}

/** 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;
}

/** Get sub object from a json object.
 *
 * A sub object with a certain name stored in the passed object is returned.
 * If the sub object is not found e second trial with the lower case version
 * of the name will be performed.
 *
 * param[in] jso the object with the sub object.
 * param[in] name  the name of the stored sub object.
 * param[out] sub_jso the pointer to the sub object.
 * @retval true if object was found.
 * @retval false if the object was not found.
 */
bool
ifapi_get_sub_object(json_object *jso, char *name, json_object **sub_jso)
{
    int i;
    if (json_object_object_get_ex(jso, name, sub_jso)) {
        return true;
    } else {
        char name2[strlen(name) + 1];
        for (i = 0; name[i]; i++)
            name2[i] = tolower(name[i]);
        name2[strlen(name)] = '\0';
        return json_object_object_get_ex(jso, name2, sub_jso);
    }
}

/** Get number from a json object.
 *
 * A int64 number is retrieved from a json object which should represent a number.
 *
 * param[in] jso the json object.
 * param[out] num the int64 number.
 * @retval TSS2_RC_SUCCESS if json object represents a number.
 * @retval TSS2_FAPI_RC_BAD_VALUE if the json object does not represent a number.
 */
static TSS2_RC
get_number_from_json(json_object *jso, int64_t *num)
{
    const char *token = json_object_get_string(jso);
    if (!get_number(token, num)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    return TSS2_RC_SUCCESS;
}

/** Get boolean from a json object.
 *
 * A boolean value is retrieved from a json object.
 * The value can be 1, 0, yes, or no.
 *
 * param[in] jso the json object.
 * param[out] value the boolean value.
 * @retval TSS2_RC_SUCCESS if json object represents a boolean.
 * @retval TSS2_FAPI_RC_BAD_VALUE if the json object does not represent a boolean.
 */
static TSS2_RC
get_boolean_from_json(json_object *jso, TPMI_YES_NO *value)
{
    TSS2_RC r = ifapi_json_TPMI_YES_NO_deserialize(jso, value);
    if (r != TSS2_RC_SUCCESS) {
        const char *token = json_object_get_string(jso);
        if (strcasecmp(token, "set") || strcasecmp(token, "on")) {
            *value = 1;
        } else if (strcasecmp(token, "off")) {
            *value = 0;
        } else {
            return_error(TSS2_FAPI_RC_BAD_VALUE, "No boolean value");
        }
    }
    if (*value != 0 && *value != 1) {
        return_error(TSS2_FAPI_RC_BAD_VALUE, "No boolean value.");
    };
    return TSS2_RC_SUCCESS;
}

/** Deserialize json object which represents a pcr selection.
 *
 * @param[in]  jso json array of pcr registers.
 * @param[out] sizeofSelect size of bit mask for used pcr registers.
 * @param[out] pcrSelect byte array with bit mask.
 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
 *         the function.
 */
TSS2_RC
ifapi_json_pcr_selection_deserialize(
    json_object *jso,
    UINT8 *sizeofSelect,
    BYTE pcrSelect[])
{
    LOG_TRACE("call");
    TSS2_RC r;
    size_t i;
    int64_t n;
    int n_byte = 0;
    json_type jso_type = json_object_get_type(jso);

    if (jso_type != json_type_array) {
        return_error(TSS2_FAPI_RC_BAD_VALUE, "Bad value (array of numbers expected).");
    }
    /* Cast (size_t) is necessary to support older version of libjson-c */
    for (i = 0; i < (size_t)json_object_array_length(jso); i++) {
        r = get_number_from_json(json_object_array_get_idx(jso, i), &n);
        return_if_error(r, "Bad PCR value");
        n_byte = n / 8;
        pcrSelect[n_byte] |= (BYTE)(1 << (n % 8));
        if (n_byte > *sizeofSelect)
            *sizeofSelect = n_byte;
    }
    *sizeofSelect = 3;
    return TSS2_RC_SUCCESS;
}

/** Deserialize an array of UINT8.
 *
 * @param[in]  jso object to be deserialized.
 * @param[out] out the deserialized object.
 * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
 *         the function.
 */
TSS2_RC
ifapi_json_UINT8_ARY_deserialize(
    json_object *jso,
    UINT8_ARY *out)
{
    TSS2_RC r;

    const char *hex_string = json_object_get_string(jso);
    out->size = strlen(hex_string) / 2;
    out->buffer = malloc(out->size);
    return_if_null(out->buffer, "Out of memory.", TSS2_FAPI_RC_MEMORY);

    r = ifapi_hex_to_byte_ary(hex_string, out->size, &out->buffer[0]);
    return_if_error(r, "Can't convert hex values.");

    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPMS_PCR_SELECT variable.
 *
 * @param[in]  jso  json object to be deserialized.
 * @param[out] out the deserialized object.
 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
 *         the function.
 */
TSS2_RC
ifapi_json_TPMS_PCR_SELECT_deserialize(json_object *jso,  TPMS_PCR_SELECT *out)
{
    LOG_TRACE("call");

    memset(out, 0, sizeof(TPMS_PCR_SELECT));
    return ifapi_json_pcr_selection_deserialize(jso, &out->sizeofSelect,
            &out->pcrSelect[0]);
}

/** Deserialize a TPMS_PCR_SELECTION variable.
 *
 * @param[in]  jso json object to be deserialized.
 * @param[out] out the deserialized object.
 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
 *         the function.
 */
TSS2_RC
ifapi_json_TPMS_PCR_SELECTION_deserialize(json_object *jso,
        TPMS_PCR_SELECTION *out)
{
    LOG_TRACE("call");
    json_object *jso2;
    TSS2_RC r;

    memset(out, 0, sizeof(TPMS_PCR_SELECTION));
    if (!ifapi_get_sub_object(jso, "hash", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPMI_ALG_HASH_deserialize(jso2, &out->hash);
    return_if_error(r, "BAD VALUE");

    if (!ifapi_get_sub_object(jso, "pcrSelect", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    return ifapi_json_pcr_selection_deserialize(jso2, &out->sizeofSelect,
            &out->pcrSelect[0]);
}

/** Deserialize an array of BYTE structures.
 *
 * @param[in] max the maximal number of bytess to be deserialized.
 * @param[in] jso the JSON object with the byte array.
 * @param[in] out the byte array for deserialization.
 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
 *         the function.
 */
TSS2_RC
ifapi_json_BYTE_array_deserialize(size_t max, json_object *jso, BYTE *out)
{
    LOG_TRACE("call");
    json_type jso_type = json_object_get_type(jso);
    if (jso_type == json_type_array) {
        int size = json_object_array_length(jso);
        if (size > (int)max) {
            LOG_ERROR("Array of BYTE too large (%i > %zu)", size, max);
        }
        for (int i = 0; i < size; i++) {
            json_object *jso2 = json_object_array_get_idx(jso, i);
            TSS2_RC r = ifapi_json_BYTE_deserialize(jso2, &out[i]);
            return_if_error(r, "BAD VALUE");
        }
        return TSS2_RC_SUCCESS;
    } else {
        LOG_ERROR("BAD VALUE");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
}

/** Deserialize a BYTE 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_BYTE_deserialize(json_object *jso, BYTE *out)
{
    LOG_TRACE("call");
    const char *token = json_object_get_string(jso);
    int64_t i64;
    if (!get_number(token, &i64)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    *out = (BYTE) i64;
    if ((int64_t)*out != i64) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    return TSS2_RC_SUCCESS;
}

/** Deserialize a UINT8 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_UINT8_deserialize(json_object *jso, UINT8 *out)
{
    LOG_TRACE("call");
    const char *token = json_object_get_string(jso);
    int64_t i64;
    if (!get_number(token, &i64)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    *out = (UINT8) i64;
    if ((int64_t)*out != i64) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    return TSS2_RC_SUCCESS;
}

/** Deserialize a UINT16 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_UINT16_deserialize(json_object *jso, UINT16 *out)
{
    LOG_TRACE("call");
    const char *token = json_object_get_string(jso);
    int64_t i64;
    if (!get_number(token, &i64)) {
        LOG_ERROR("Bad value %s", json_object_get_string(jso));
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    *out = (UINT16) i64;
    if ((int64_t)*out != i64) {
        LOG_ERROR("Bad value %s", json_object_get_string(jso));
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    return TSS2_RC_SUCCESS;
}

/** Deserialize a UINT32 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_UINT32_deserialize(json_object *jso, UINT32 *out)
{
    LOG_TRACE("call");
    const char *token = json_object_get_string(jso);
    int64_t i64;
    if (!get_number(token, &i64)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    *out = (UINT32) i64;
    if ((int64_t)*out != i64) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    return TSS2_RC_SUCCESS;
}

/** Deserialize a UINT64 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_UINT64_deserialize(json_object *jso, UINT64 *out)
{
    UINT32 tmp;
    LOG_TRACE("call");
    /* json-c allows only 53 bit numbers, therefore 64 bit numbers are split */
    if (json_object_get_type(jso) == json_type_array) {
        if (json_object_array_length(jso) != 2) {
            LOG_ERROR("Bad value");
            return TSS2_FAPI_RC_BAD_VALUE;
        }
        TSS2_RC r = ifapi_json_UINT32_deserialize(json_object_array_get_idx(jso, 0),
                        &tmp);
        return_if_error(r, "BAD VALUE");
        *out = tmp * 0x100000000;

        r = ifapi_json_UINT32_deserialize(json_object_array_get_idx(jso, 1),
                                          &tmp);
        return_if_error(r, "BAD VALUE");
        *out += tmp;
        return TSS2_RC_SUCCESS;
    }

    const char *token = json_object_get_string(jso);
    int64_t i64;
    if (!get_number(token, &i64)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    *out = (UINT64) i64;
    if ((int64_t)*out != i64) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPM2_GENERATED 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_TPM2_GENERATED_deserialize(json_object *jso, TPM2_GENERATED *out)
{
    static const struct { TPM2_GENERATED in; const char *name; } tab[] = {
        { TPM2_GENERATED_VALUE, "VALUE" },
    };

    const char *s = json_object_get_string(jso);
    const char *str = strip_prefix(s, "TPM_", "TPM2_", "GENERATED_", NULL);
    LOG_TRACE("called for %s parsing %s", s, str);

    if (str) {
        for (size_t i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
            if (strcasecmp(str, &tab[i].name[0]) == 0) {
                *out = tab[i].in;
                return TSS2_RC_SUCCESS;
            }
        }
    }

    return ifapi_json_UINT32_deserialize(jso, out);
}

/** Deserialize a TPM2_ALG_ID 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_TPM2_ALG_ID_deserialize(json_object *jso, TPM2_ALG_ID *out)
{
    static const struct { TPM2_ALG_ID in; const char *name; } tab[] = {
        { TPM2_ALG_ERROR, "ERROR" },
        { TPM2_ALG_RSA, "RSA" },
        { TPM2_ALG_SHA, "SHA" },
        { TPM2_ALG_SHA1, "SHA1" },
        { TPM2_ALG_HMAC, "HMAC" },
        { TPM2_ALG_AES, "AES" },
        { TPM2_ALG_MGF1, "MGF1" },
        { TPM2_ALG_KEYEDHASH, "KEYEDHASH" },
        { TPM2_ALG_XOR, "XOR" },
        { TPM2_ALG_SHA256, "SHA256" },
        { TPM2_ALG_SHA384, "SHA384" },
        { TPM2_ALG_SHA512, "SHA512" },
        { TPM2_ALG_NULL, "NULL" },
        { TPM2_ALG_SM3_256, "SM3_256" },
        { TPM2_ALG_SM4, "SM4" },
        { TPM2_ALG_RSASSA, "RSASSA" },
        { TPM2_ALG_RSAES, "RSAES" },
        { TPM2_ALG_RSAPSS, "RSAPSS" },
        { TPM2_ALG_OAEP, "OAEP" },
        { TPM2_ALG_ECDSA, "ECDSA" },
        { TPM2_ALG_ECDH, "ECDH" },
        { TPM2_ALG_ECDAA, "ECDAA" },
        { TPM2_ALG_SM2, "SM2" },
        { TPM2_ALG_ECSCHNORR, "ECSCHNORR" },
        { TPM2_ALG_ECMQV, "ECMQV" },
        { TPM2_ALG_KDF1_SP800_56A, "KDF1_SP800_56A" },
        { TPM2_ALG_KDF2, "KDF2" },
        { TPM2_ALG_KDF1_SP800_108, "KDF1_SP800_108" },
        { TPM2_ALG_ECC, "ECC" },
        { TPM2_ALG_SYMCIPHER, "SYMCIPHER" },
        { TPM2_ALG_CAMELLIA, "CAMELLIA" },
        { TPM2_ALG_CTR, "CTR" },
        { TPM2_ALG_OFB, "OFB" },
        { TPM2_ALG_CBC, "CBC" },
        { TPM2_ALG_CFB, "CFB" },
        { TPM2_ALG_ECB, "ECB" },
    };

    const char *s = json_object_get_string(jso);
    const char *str = strip_prefix(s, "TPM_", "TPM2_", "ALG_", "ID_", NULL);
    LOG_TRACE("called for %s parsing %s", s, str);

    if (str) {
        for (size_t i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
            if (strcasecmp(str, &tab[i].name[0]) == 0) {
                *out = tab[i].in;
                return TSS2_RC_SUCCESS;
            }
        }
    }

    return ifapi_json_UINT16_deserialize(jso, out);
}

/** Deserialize a TPM2_ECC_CURVE 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_TPM2_ECC_CURVE_deserialize(json_object *jso, TPM2_ECC_CURVE *out)
{
    static const struct { TPM2_ECC_CURVE in; const char *name; } tab[] = {
        { TPM2_ECC_NONE, "NONE" },
        { TPM2_ECC_NIST_P192, "NIST_P192" },
        { TPM2_ECC_NIST_P224, "NIST_P224" },
        { TPM2_ECC_NIST_P256, "NIST_P256" },
        { TPM2_ECC_NIST_P384, "NIST_P384" },
        { TPM2_ECC_NIST_P521, "NIST_P521" },
        { TPM2_ECC_BN_P256, "BN_P256" },
        { TPM2_ECC_BN_P638, "BN_P638" },
        { TPM2_ECC_SM2_P256, "SM2_P256" },
    };

    const char *s = json_object_get_string(jso);
    const char *str = strip_prefix(s, "TPM_", "TPM2_", "ECC_", "CURVE_", NULL);
    LOG_TRACE("called for %s parsing %s", s, str);

    if (str) {
        for (size_t i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
            if (strcasecmp(str, &tab[i].name[0]) == 0) {
                *out = tab[i].in;
                return TSS2_RC_SUCCESS;
            }
        }
    }

    return ifapi_json_UINT16_deserialize(jso, out);
}

/** Deserialize a TPM2_CC 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_TPM2_CC_deserialize(json_object *jso, TPM2_CC *out)
{
    static const struct { TPM2_CC in; const char *name; } tab[] = {
        { TPM2_CC_FIRST, "FIRST" },
        { TPM2_CC_NV_UndefineSpaceSpecial, "NV_UndefineSpaceSpecial" },
        { TPM2_CC_EvictControl, "EvictControl" },
        { TPM2_CC_HierarchyControl, "HierarchyControl" },
        { TPM2_CC_NV_UndefineSpace, "NV_UndefineSpace" },
        { TPM2_CC_ChangeEPS, "ChangeEPS" },
        { TPM2_CC_ChangePPS, "ChangePPS" },
        { TPM2_CC_Clear, "Clear" },
        { TPM2_CC_ClearControl, "ClearControl" },
        { TPM2_CC_ClockSet, "ClockSet" },
        { TPM2_CC_HierarchyChangeAuth, "HierarchyChangeAuth" },
        { TPM2_CC_NV_DefineSpace, "NV_DefineSpace" },
        { TPM2_CC_PCR_Allocate, "PCR_Allocate" },
        { TPM2_CC_PCR_SetAuthPolicy, "PCR_SetAuthPolicy" },
        { TPM2_CC_PP_Commands, "PP_Commands" },
        { TPM2_CC_SetPrimaryPolicy, "SetPrimaryPolicy" },
        { TPM2_CC_FieldUpgradeStart, "FieldUpgradeStart" },
        { TPM2_CC_ClockRateAdjust, "ClockRateAdjust" },
        { TPM2_CC_CreatePrimary, "CreatePrimary" },
        { TPM2_CC_NV_GlobalWriteLock, "NV_GlobalWriteLock" },
        { TPM2_CC_GetCommandAuditDigest, "GetCommandAuditDigest" },
        { TPM2_CC_NV_Increment, "NV_Increment" },
        { TPM2_CC_NV_SetBits, "NV_SetBits" },
        { TPM2_CC_NV_Extend, "NV_Extend" },
        { TPM2_CC_NV_Write, "NV_Write" },
        { TPM2_CC_NV_WriteLock, "NV_WriteLock" },
        { TPM2_CC_DictionaryAttackLockReset, "DictionaryAttackLockReset" },
        { TPM2_CC_DictionaryAttackParameters, "DictionaryAttackParameters" },
        { TPM2_CC_NV_ChangeAuth, "NV_ChangeAuth" },
        { TPM2_CC_PCR_Event, "PCR_Event" },
        { TPM2_CC_PCR_Reset, "PCR_Reset" },
        { TPM2_CC_SequenceComplete, "SequenceComplete" },
        { TPM2_CC_SetAlgorithmSet, "SetAlgorithmSet" },
        { TPM2_CC_SetCommandCodeAuditStatus, "SetCommandCodeAuditStatus" },
        { TPM2_CC_FieldUpgradeData, "FieldUpgradeData" },
        { TPM2_CC_IncrementalSelfTest, "IncrementalSelfTest" },
        { TPM2_CC_SelfTest, "SelfTest" },
        { TPM2_CC_Startup, "Startup" },
        { TPM2_CC_Shutdown, "Shutdown" },
        { TPM2_CC_StirRandom, "StirRandom" },
        { TPM2_CC_ActivateCredential, "ActivateCredential" },
        { TPM2_CC_Certify, "Certify" },
        { TPM2_CC_PolicyNV, "PolicyNV" },
        { TPM2_CC_CertifyCreation, "CertifyCreation" },
        { TPM2_CC_Duplicate, "Duplicate" },
        { TPM2_CC_GetTime, "GetTime" },
        { TPM2_CC_GetSessionAuditDigest, "GetSessionAuditDigest" },
        { TPM2_CC_NV_Read, "NV_Read" },
        { TPM2_CC_NV_ReadLock, "NV_ReadLock" },
        { TPM2_CC_ObjectChangeAuth, "ObjectChangeAuth" },
        { TPM2_CC_PolicySecret, "PolicySecret" },
        { TPM2_CC_Rewrap, "Rewrap" },
        { TPM2_CC_Create, "Create" },
        { TPM2_CC_ECDH_ZGen, "ECDH_ZGen" },
        { TPM2_CC_HMAC, "HMAC" },
        { TPM2_CC_Import, "Import" },
        { TPM2_CC_Load, "Load" },
        { TPM2_CC_Quote, "Quote" },
        { TPM2_CC_RSA_Decrypt, "RSA_Decrypt" },
        { TPM2_CC_HMAC_Start, "HMAC_Start" },
        { TPM2_CC_SequenceUpdate, "SequenceUpdate" },
        { TPM2_CC_Sign, "Sign" },
        { TPM2_CC_Unseal, "Unseal" },
        { TPM2_CC_PolicySigned, "PolicySigned" },
        { TPM2_CC_ContextLoad, "ContextLoad" },
        { TPM2_CC_ContextSave, "ContextSave" },
        { TPM2_CC_ECDH_KeyGen, "ECDH_KeyGen" },
        { TPM2_CC_EncryptDecrypt, "EncryptDecrypt" },
        { TPM2_CC_FlushContext, "FlushContext" },
        { TPM2_CC_LoadExternal, "LoadExternal" },
        { TPM2_CC_MakeCredential, "MakeCredential" },
        { TPM2_CC_NV_ReadPublic, "NV_ReadPublic" },
        { TPM2_CC_PolicyAuthorize, "PolicyAuthorize" },
        { TPM2_CC_PolicyAuthValue, "PolicyAuthValue" },
        { TPM2_CC_PolicyCommandCode, "PolicyCommandCode" },
        { TPM2_CC_PolicyCounterTimer, "PolicyCounterTimer" },
        { TPM2_CC_PolicyCpHash, "PolicyCpHash" },
        { TPM2_CC_PolicyLocality, "PolicyLocality" },
        { TPM2_CC_PolicyNameHash, "PolicyNameHash" },
        { TPM2_CC_PolicyOR, "PolicyOR" },
        { TPM2_CC_PolicyTicket, "PolicyTicket" },
        { TPM2_CC_ReadPublic, "ReadPublic" },
        { TPM2_CC_RSA_Encrypt, "RSA_Encrypt" },
        { TPM2_CC_StartAuthSession, "StartAuthSession" },
        { TPM2_CC_VerifySignature, "VerifySignature" },
        { TPM2_CC_ECC_Parameters, "ECC_Parameters" },
        { TPM2_CC_FirmwareRead, "FirmwareRead" },
        { TPM2_CC_GetCapability, "GetCapability" },
        { TPM2_CC_GetRandom, "GetRandom" },
        { TPM2_CC_GetTestResult, "GetTestResult" },
        { TPM2_CC_Hash, "Hash" },
        { TPM2_CC_PCR_Read, "PCR_Read" },
        { TPM2_CC_PolicyPCR, "PolicyPCR" },
        { TPM2_CC_PolicyRestart, "PolicyRestart" },
        { TPM2_CC_ReadClock, "ReadClock" },
        { TPM2_CC_PCR_Extend, "PCR_Extend" },
        { TPM2_CC_PCR_SetAuthValue, "PCR_SetAuthValue" },
        { TPM2_CC_NV_Certify, "NV_Certify" },
        { TPM2_CC_EventSequenceComplete, "EventSequenceComplete" },
        { TPM2_CC_HashSequenceStart, "HashSequenceStart" },
        { TPM2_CC_PolicyPhysicalPresence, "PolicyPhysicalPresence" },
        { TPM2_CC_PolicyDuplicationSelect, "PolicyDuplicationSelect" },
        { TPM2_CC_PolicyGetDigest, "PolicyGetDigest" },
        { TPM2_CC_TestParms, "TestParms" },
        { TPM2_CC_Commit, "Commit" },
        { TPM2_CC_PolicyPassword, "PolicyPassword" },
        { TPM2_CC_ZGen_2Phase, "ZGen_2Phase" },
        { TPM2_CC_EC_Ephemeral, "EC_Ephemeral" },
        { TPM2_CC_PolicyNvWritten, "PolicyNvWritten" },
        { TPM2_CC_PolicyTemplate, "PolicyTemplate" },
        { TPM2_CC_CreateLoaded, "CreateLoaded" },
        { TPM2_CC_PolicyAuthorizeNV, "PolicyAuthorizeNV" },
        { TPM2_CC_EncryptDecrypt2, "EncryptDecrypt2" },
        { TPM2_CC_LAST, "LAST" },
        { TPM2_CC_Vendor_TCG_Test, "Vendor_TCG_Test" },
    };

    const char *s = json_object_get_string(jso);
    const char *str = strip_prefix(s, "TPM_", "TPM2_", "CC_", NULL);
    LOG_TRACE("called for %s parsing %s", s, str);

    if (str) {
        for (size_t i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
            if (strcasecmp(str, &tab[i].name[0]) == 0) {
                *out = tab[i].in;
                return TSS2_RC_SUCCESS;
            }
        }
    }

    return ifapi_json_UINT32_deserialize(jso, out);
}

/** Deserialize a TPM2_EO 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_TPM2_EO_deserialize(json_object *jso, TPM2_EO *out)
{
    static const struct { TPM2_EO in; const char *name; } tab[] = {
        { TPM2_EO_EQ,          "EQ" },
        { TPM2_EO_NEQ,         "NEQ" },
        { TPM2_EO_SIGNED_GT,   "SIGNED_GT" },
        { TPM2_EO_UNSIGNED_GT, "UNSIGNED_GT" },
        { TPM2_EO_SIGNED_LT,   "SIGNED_LT" },
        { TPM2_EO_UNSIGNED_LT, "UNSIGNED_LT" },
        { TPM2_EO_SIGNED_GE,   "SIGNED_GE" },
        { TPM2_EO_UNSIGNED_GE, "UNSIGNED_GE" },
        { TPM2_EO_SIGNED_LE,   "SIGNED_LE" },
        { TPM2_EO_UNSIGNED_LE, "UNSIGNED_LE" },
        { TPM2_EO_BITSET,      "BITSET" },
        { TPM2_EO_BITCLEAR,    "BITCLEAR" },
    };

    const char *s = json_object_get_string(jso);
    const char *str = strip_prefix(s, "TPM_", "TPM2_", "EO_", NULL);
    LOG_TRACE("called for %s parsing %s", s, str);

    if (str) {
        for (size_t i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
            if (strcasecmp(str, &tab[i].name[0]) == 0) {
                *out = tab[i].in;
                return TSS2_RC_SUCCESS;
            }
        }
    }

    return ifapi_json_UINT16_deserialize(jso, out);
}

/** Deserialize a TPM2_ST 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_TPM2_ST_deserialize(json_object *jso, TPM2_ST *out)
{
    static const struct { TPM2_ST in; const char *name; } tab[] = {
        { TPM2_ST_RSP_COMMAND, "RSP_COMMAND" },
        { TPM2_ST_NULL, "NULL" },
        { TPM2_ST_NO_SESSIONS, "NO_SESSIONS" },
        { TPM2_ST_SESSIONS, "SESSIONS" },
        { TPM2_ST_ATTEST_NV, "ATTEST_NV" },
        { TPM2_ST_ATTEST_COMMAND_AUDIT, "ATTEST_COMMAND_AUDIT" },
        { TPM2_ST_ATTEST_SESSION_AUDIT, "ATTEST_SESSION_AUDIT" },
        { TPM2_ST_ATTEST_CERTIFY, "ATTEST_CERTIFY" },
        { TPM2_ST_ATTEST_QUOTE, "ATTEST_QUOTE" },
        { TPM2_ST_ATTEST_TIME, "ATTEST_TIME" },
        { TPM2_ST_ATTEST_CREATION, "ATTEST_CREATION" },
        { TPM2_ST_CREATION, "CREATION" },
        { TPM2_ST_VERIFIED, "VERIFIED" },
        { TPM2_ST_AUTH_SECRET, "AUTH_SECRET" },
        { TPM2_ST_HASHCHECK, "HASHCHECK" },
        { TPM2_ST_AUTH_SIGNED, "AUTH_SIGNED" },
        { TPM2_ST_FU_MANIFEST, "FU_MANIFEST" },
    };

    const char *s = json_object_get_string(jso);
    const char *str = strip_prefix(s, "TPM_", "TPM2_", "ST_", NULL);
    LOG_TRACE("called for %s parsing %s", s, str);

    if (str) {
        for (size_t i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
            if (strcasecmp(str, &tab[i].name[0]) == 0) {
                *out = tab[i].in;
                return TSS2_RC_SUCCESS;
            }
        }
    }

    return ifapi_json_UINT16_deserialize(jso, out);
}

/** Deserialize a TPM2_PT_PCR 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_TPM2_PT_PCR_deserialize(json_object *jso, TPM2_PT_PCR *out)
{
    static const struct { TPM2_PT_PCR in; const char *name; } tab[] = {
        { TPM2_PT_TPM2_PCR_FIRST, "FIRST" },
        { TPM2_PT_PCR_SAVE, "SAVE" },
        { TPM2_PT_PCR_EXTEND_L0, "EXTEND_L0" },
        { TPM2_PT_PCR_RESET_L0, "RESET_L0" },
        { TPM2_PT_PCR_EXTEND_L1, "EXTEND_L1" },
        { TPM2_PT_PCR_RESET_L1, "RESET_L1" },
        { TPM2_PT_PCR_EXTEND_L2, "EXTEND_L2" },
        { TPM2_PT_PCR_RESET_L2, "RESET_L2" },
        { TPM2_PT_PCR_EXTEND_L3, "EXTEND_L3" },
        { TPM2_PT_PCR_RESET_L3, "RESET_L3" },
        { TPM2_PT_PCR_EXTEND_L4, "EXTEND_L4" },
        { TPM2_PT_PCR_RESET_L4, "RESET_L4" },
        { TPM2_PT_PCR_NO_INCREMENT, "NO_INCREMENT" },
        { TPM2_PT_PCR_DRTM_RESET, "DRTM_RESET" },
        { TPM2_PT_PCR_POLICY, "POLICY" },
        { TPM2_PT_PCR_AUTH, "AUTH" },
        { TPM2_PT_TPM2_PCR_LAST, "LAST" }
    };

    const char *s = json_object_get_string(jso);
    const char *str = strip_prefix(s, "TPM_", "TPM2_", "PT_", "PCR_", NULL);
    LOG_TRACE("called for %s parsing %s", s, str);

    if (str) {
        for (size_t i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
            if (strcasecmp(str, &tab[i].name[0]) == 0) {
                *out = tab[i].in;
                return TSS2_RC_SUCCESS;
            }
        }
    }

    return ifapi_json_UINT32_deserialize(jso, out);
}

/*** Table 26 .Definition of Types for HandlesTable ***/

/**  Deserialize a TPM2_HANDLE 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_TPM2_HANDLE_deserialize(json_object *jso, TPM2_HANDLE *out)
{
    LOG_TRACE("call");
    const char *token = json_object_get_string(jso);
    int64_t i64;
    if (get_number(token, &i64)) {
        *out = (TPM2_HANDLE) 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 TPMA_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.
 */
TSS2_RC
ifapi_json_TPMA_OBJECT_deserialize(json_object *jso, TPMA_OBJECT *out)
{
    struct { TPMA_OBJECT in; char *name; } tab[] = {
        { TPMA_OBJECT_FIXEDTPM, "fixedTPM" },
        { TPMA_OBJECT_STCLEAR, "stClear" },
        { TPMA_OBJECT_FIXEDPARENT, "fixedParent" },
        { TPMA_OBJECT_SENSITIVEDATAORIGIN, "sensitiveDataOrigin" },
        { TPMA_OBJECT_USERWITHAUTH, "userWithAuth" },
        { TPMA_OBJECT_ADMINWITHPOLICY, "adminWithPolicy" },
        { TPMA_OBJECT_NODA, "noDA" },
        { TPMA_OBJECT_ENCRYPTEDDUPLICATION, "encryptedDuplication" },
        { TPMA_OBJECT_RESTRICTED, "restricted" },
        { TPMA_OBJECT_DECRYPT, "decrypt" },
        { TPMA_OBJECT_SIGN_ENCRYPT, "sign" },
    };
    size_t n = sizeof(tab) / sizeof(tab[0]);
    size_t i, j;

    TPMI_YES_NO flag;
    TSS2_RC r;

    LOG_TRACE("call");
    memset(out, 0, sizeof(TPMA_OBJECT));
    json_type jso_type = json_object_get_type(jso);
    if (jso_type == json_type_array) {
        /* Cast (size_t) is necessary to support older version of libjson-c */
        for (i = 0; i < (size_t)json_object_array_length(jso); i++) {
            json_object *jso2 = json_object_array_get_idx(jso, i);
            const char *token = strip_prefix(json_object_get_string(jso2),
                                    "TPM_", "TPM2_", "TPMA_", "OBJECT_", NULL);
            if (!token) {
                LOG_ERROR("Bad object; expected array of strings.");
                return TSS2_FAPI_RC_BAD_VALUE;
            }
            for (j = 0; j < n; j++) {
                if (strcasecmp(tab[j].name, token) == 0) {
                    *out |= tab[j].in;
                    break;
                }
            }
            if (j == n) {
                LOG_ERROR("Unknown value: %s", json_object_get_string(jso2));
                return TSS2_FAPI_RC_BAD_VALUE;
            }
        }
    } else if (jso_type == json_type_object) {
        json_object_object_foreach(jso, key, val) {
            const char *token = strip_prefix(key,
                                    "TPM_", "TPM2_", "TPMA_", "OBJECT_", NULL);
            r = get_boolean_from_json(val, &flag);
            return_if_error2(r, "Boolean value expected at key: %s", key);
            for (j = 0; j < n; j++) {
                if (strcasecmp(tab[j].name, token) == 0) {
                    if (flag)
                        *out |= tab[j].in;
                    break;
                }
            }
            if (j == n) {
                LOG_ERROR("Unknown key: %s", key);
                return TSS2_FAPI_RC_BAD_VALUE;
            }
        }
    } else {
        const char *token;
        token = json_object_get_string(jso);
        int64_t i64;
        if (!get_number(token, &i64)) {
            LOG_ERROR("Bad value");
            return TSS2_FAPI_RC_BAD_VALUE;
        }
        *out = (TPMA_OBJECT) i64;
        if ((int64_t)*out != i64) {
            LOG_ERROR("Bad value");
            return TSS2_FAPI_RC_BAD_VALUE;
        }
        return TSS2_RC_SUCCESS;
    }
    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPMA_LOCALITY 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_TPMA_LOCALITY_deserialize(json_object *jso, TPMA_LOCALITY *out)
{
    struct { TPMA_LOCALITY in; char *name; } tab[] = {
        { TPMA_LOCALITY_TPM2_LOC_ZERO, "ZERO" },
        { TPMA_LOCALITY_TPM2_LOC_ONE, "ONE" },
        { TPMA_LOCALITY_TPM2_LOC_TWO, "TWO" },
        { TPMA_LOCALITY_TPM2_LOC_THREE, "THREE" },
        { TPMA_LOCALITY_TPM2_LOC_FOUR, "FOUR" },
    };
    size_t n = sizeof(tab) / sizeof(tab[0]);
    size_t i, j;

    TPMI_YES_NO flag;
    TSS2_RC r;

    LOG_TRACE("call");
    memset(out, 0, sizeof(TPMA_LOCALITY));
    json_type jso_type = json_object_get_type(jso);
    if (jso_type == json_type_array) {
        /* Cast (size_t) is necessary to support older version of libjson-c */
        for (i = 0; i < (size_t)json_object_array_length(jso); i++) {
            json_object *jso2 = json_object_array_get_idx(jso, i);
            const char *token = strip_prefix(json_object_get_string(jso2),
                                    "TPM_", "TPM2_", "TPMA_", "LOCALITY_",
                                    "TPM2_", "LOC_", NULL);
            if (!token) {
                LOG_ERROR("Bad object; expected array of strings.");
                return TSS2_FAPI_RC_BAD_VALUE;
            }
            for (j = 0; j < n; j++) {
                if (strcasecmp(tab[j].name, token) == 0) {
                    *out |= tab[j].in;
                    break;
                }
            }
            if (j == n) {
                LOG_ERROR("Unknown value: %s", json_object_get_string(jso2));
                return TSS2_FAPI_RC_BAD_VALUE;
            }
        }
    } else if (jso_type == json_type_object) {
        json_object_object_foreach(jso, key, val) {
            const char *token = strip_prefix(key,
                                    "TPM_", "TPM2_", "TPMA_", "LOCALITY_",
                                    "TPM2_", "LOC_", NULL);
            if (strcasecmp(token, "extended") == 0) {
                int64_t i64;
                if (!get_number(json_object_get_string(val), &i64)) {
                    LOG_ERROR("Bad value");
                    return TSS2_FAPI_RC_BAD_VALUE;
                }
                if (((i64<<5) & ~TPMA_LOCALITY_EXTENDED_MASK) != 0) {
                    LOG_ERROR("Bad value for extended");
                    return TSS2_FAPI_RC_BAD_VALUE;
                }
                *out |= (TPMA_LOCALITY)(i64<<5);
                continue;
            }
            r = get_boolean_from_json(val, &flag);
            return_if_error2(r, "Boolean value expected at key: %s", key);
            for (j = 0; j < n; j++) {
                if (strcasecmp(tab[j].name, token) == 0) {
                    if (flag)
                        *out |= tab[j].in;
                    break;
                }
            }
            if (j == n) {
                LOG_ERROR("Unknown key: %s", key);
                return TSS2_FAPI_RC_BAD_VALUE;
            }
        }
    } else {
        const char *token;
        token = json_object_get_string(jso);
        int64_t i64;
        if (!get_number(token, &i64)) {
            LOG_ERROR("Bad value");
            return TSS2_FAPI_RC_BAD_VALUE;
        }
        *out = (TPMA_LOCALITY) i64;
        if ((int64_t)*out != i64) {
            LOG_ERROR("Bad value");
            return TSS2_FAPI_RC_BAD_VALUE;
        }
        return TSS2_RC_SUCCESS;
    }
    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPMI_YES_NO 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_TPMI_YES_NO_deserialize(json_object *jso, TPMI_YES_NO *out)
{
    static const struct { TPMI_YES_NO in; const char *name; } tab[] = {
        { NO, "NO" },
        { YES, "YES" },
    };

    const char *s = json_object_get_string(jso);
    const char *str = strip_prefix(s, "TPM_", "TPM2_", "TPMI_", NULL);
    LOG_TRACE("called for %s parsing %s", s, str);

    if (str) {
        for (size_t i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
            if (strcasecmp(str, &tab[i].name[0]) == 0) {
                *out = tab[i].in;
                return TSS2_RC_SUCCESS;
            }
        }
    }

    return ifapi_json_BYTE_deserialize(jso, out);
}

/** Deserialize a TPMI_RH_HIERARCHY 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_TPMI_RH_HIERARCHY_deserialize(json_object *jso,
        TPMI_RH_HIERARCHY *out)
{
    static const struct { TPMI_RH_HIERARCHY in; const char *name; } tab[] = {
        { TPM2_RH_OWNER, "OWNER" },
        { TPM2_RH_PLATFORM, "PLATFORM" },
        { TPM2_RH_ENDORSEMENT, "ENDORSEMENT" },
        { TPM2_RH_NULL, "NULL" },
    };

    const char *s = json_object_get_string(jso);
    const char *str = strip_prefix(s, "TPM_", "TPM2_", "TPMI_", "RH_", "HIERARCHY_", NULL);
    LOG_TRACE("called for %s parsing %s", s, str);

    if (str) {
        for (size_t i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
            if (strcasecmp(str, &tab[i].name[0]) == 0) {
                *out = tab[i].in;
                return TSS2_RC_SUCCESS;
            }
        }
    }

    return ifapi_json_UINT32_deserialize(jso, out);
}

/** Deserialize a TPMI_RH_NV_INDEX json object.
 *
 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
 *         the function.
 */
TSS2_RC
ifapi_json_TPMI_RH_NV_INDEX_deserialize(json_object *jso, TPMI_RH_NV_INDEX *out)
{
    return ifapi_json_TPM2_HANDLE_deserialize(jso, out);
}

/** Deserialize a TPMI_ALG_HASH 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_TPMI_ALG_HASH_deserialize(json_object *jso, TPMI_ALG_HASH *out)
{
    SUBTYPE_FILTER(TPMI_ALG_HASH, TPM2_ALG_ID,
        TPM2_ALG_SHA1, TPM2_ALG_SHA256, TPM2_ALG_SHA384, TPM2_ALG_SHA512, TPM2_ALG_NULL);
}

/** Deserialize a  TPMI_ALG_SYM 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_TPMI_ALG_SYM_deserialize(json_object *jso, TPMI_ALG_SYM *out)
{
    SUBTYPE_FILTER(TPMI_ALG_SYM, TPM2_ALG_ID,
        TPM2_ALG_AES, TPM2_ALG_XOR, TPM2_ALG_NULL);
}

/** Deserialize a TPMI_ALG_SYM_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.
 */
TSS2_RC
ifapi_json_TPMI_ALG_SYM_OBJECT_deserialize(json_object *jso,
        TPMI_ALG_SYM_OBJECT *out)
{
    SUBTYPE_FILTER(TPMI_ALG_SYM_OBJECT, TPM2_ALG_ID,
        TPM2_ALG_AES, TPM2_ALG_NULL);
}

/** Deserialize a TPMI_ALG_SYM_MODE 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_TPMI_ALG_SYM_MODE_deserialize(json_object *jso,
        TPMI_ALG_SYM_MODE *out)
{
    SUBTYPE_FILTER(TPMI_ALG_SYM_MODE, TPM2_ALG_ID,
        TPM2_ALG_CTR, TPM2_ALG_OFB, TPM2_ALG_CBC, TPM2_ALG_CFB, TPM2_ALG_ECB, TPM2_ALG_NULL);
}

/** Deserialize a TPMI_ALG_KDF 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_TPMI_ALG_KDF_deserialize(json_object *jso, TPMI_ALG_KDF *out)
{
    SUBTYPE_FILTER(TPMI_ALG_KDF, TPM2_ALG_ID,
        TPM2_ALG_MGF1, TPM2_ALG_KDF1_SP800_56A, TPM2_ALG_KDF1_SP800_108, TPM2_ALG_NULL);
}

/** Deserialize a TPMI_ALG_SIG_SCHEME 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_TPMI_ALG_SIG_SCHEME_deserialize(json_object *jso,
        TPMI_ALG_SIG_SCHEME *out)
{
    SUBTYPE_FILTER(TPMI_ALG_SIG_SCHEME, TPM2_ALG_ID,
        TPM2_ALG_RSASSA, TPM2_ALG_RSAPSS, TPM2_ALG_ECDSA, TPM2_ALG_ECDAA, TPM2_ALG_SM2,
        TPM2_ALG_ECSCHNORR, TPM2_ALG_HMAC, TPM2_ALG_NULL);
}

/** Deserialize a TPMU_HA json object.
 *
 * This functions expects the Bitfield to be encoded as unsigned int in host-endianess.
 * @param[in]  selector The type of the HA 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_TPMU_HA_deserialize(
    UINT32 selector,
    json_object *jso,
    TPMU_HA *out)
{
    const char *hex_string = json_object_get_string(jso);
    size_t size = strlen(hex_string) / 2;
    size_t hash_size;
    uint8_t *buffer;
    TSS2_RC r;

    LOG_TRACE("call");
    switch (selector) {
    case TPM2_ALG_SHA1:
        hash_size = TPM2_SHA1_DIGEST_SIZE;
        buffer = &out->sha1[0];
        break;
    case TPM2_ALG_SHA256:
        hash_size = TPM2_SHA256_DIGEST_SIZE;
        buffer = &out->sha256[0];
        break;
    case TPM2_ALG_SHA384:
        hash_size = TPM2_SHA384_DIGEST_SIZE;
        buffer = &out->sha384[0];
        break;
    case TPM2_ALG_SHA512:
        hash_size = TPM2_SHA512_DIGEST_SIZE;
        buffer = &out->sha512[0];
        break;
    case TPM2_ALG_NULL: {
            return TSS2_RC_SUCCESS;
        }
    default:
        LOG_TRACE("false");
        return TSS2_FAPI_RC_BAD_VALUE;
    };
    if (hash_size != size) {
        return_error(TSS2_FAPI_RC_BAD_VALUE, "Wrong size of digest.");
    }
    r = ifapi_hex_to_byte_ary(hex_string, size, buffer);
    return_if_error(r, "Can't convert hex values.");

    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPMT_HA 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_TPMT_HA_deserialize(json_object *jso,  TPMT_HA *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, "hashAlg", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPMI_ALG_HASH_deserialize(jso2, &out->hashAlg);
    return_if_error(r, "BAD VALUE");
    if (out->hashAlg != TPM2_ALG_NULL) {
        if (!ifapi_get_sub_object(jso, "digest", &jso2)) {
            LOG_ERROR("BAD VALUE");
            return TSS2_FAPI_RC_BAD_VALUE;
        }
        r = ifapi_json_TPMU_HA_deserialize(out->hashAlg, jso2, &out->digest);
        return_if_error(r, "BAD VALUE");
    }

    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPM2B_DIGEST 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_TPM2B_DIGEST_deserialize(json_object *jso,  TPM2B_DIGEST *out)
{
    TSS2_RC r;
    LOG_TRACE("call");
    return_if_null(out, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);

    UINT16 size = 0;
    r = ifapi_json_byte_deserialize(jso, sizeof(TPMU_HA), (BYTE *)&out->buffer,
                                     &size);
    return_if_error(r, "byte serialize");

    out->size = size;
    return r;
    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPM2B_DATA 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_TPM2B_DATA_deserialize(json_object *jso,  TPM2B_DATA *out)
{
    TSS2_RC r;
    LOG_TRACE("call");
    return_if_null(out, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);

    UINT16 size = 0;
    r = ifapi_json_byte_deserialize(jso, sizeof(TPMT_HA), (BYTE *)&out->buffer,
                                     &size);
    return_if_error(r, "byte serialize");

    out->size = size;
    return r;
    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/*** Table 75 - Definition of Types for TPM2B_NONCE ***/

/** Deserialize a TPM2B_NONCE 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_TPM2B_NONCE_deserialize(json_object *jso, TPM2B_NONCE *out)
{
    LOG_TRACE("call");
    return ifapi_json_TPM2B_DIGEST_deserialize(jso, out);
}

/*** Table 77 - Definition of Types for TPM2B_OPERAND ***/

/** Deserialize a TPM2B_OPERAND 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_TPM2B_OPERAND_deserialize(json_object *jso, TPM2B_OPERAND *out)
{
    LOG_TRACE("call");
    return ifapi_json_TPM2B_DIGEST_deserialize(jso, out);
}

/** Deserialize a TPM2B_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.
 */
TSS2_RC
ifapi_json_TPM2B_EVENT_deserialize(json_object *jso,  TPM2B_EVENT *out)
{
    TSS2_RC r;
    LOG_TRACE("call");
    return_if_null(out, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);

    UINT16 size = 0;
    r = ifapi_json_byte_deserialize(jso, 1024, (BYTE *)&out->buffer, &size);
    return_if_error(r, "byte serialize");

    out->size = size;
    return r;
    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPM2B_MAX_NV_BUFFER 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_TPM2B_MAX_NV_BUFFER_deserialize(json_object *jso,
        TPM2B_MAX_NV_BUFFER *out)
{
    TSS2_RC r;
    LOG_TRACE("call");
    return_if_null(out, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);

    UINT16 size = 0;
    r = ifapi_json_byte_deserialize(jso, TPM2_MAX_NV_BUFFER_SIZE,
                                     (BYTE *)&out->buffer, &size);
    return_if_error(r, "byte serialize");

    out->size = size;
    return r;
    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPM2B_NAME 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_TPM2B_NAME_deserialize(json_object *jso,  TPM2B_NAME *out)
{
    TSS2_RC r;
    LOG_TRACE("call");
    return_if_null(out, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);

    UINT16 size = 0;
    r = ifapi_json_byte_deserialize(jso, sizeof(TPMU_NAME), (BYTE *)&out->name,
                                     &size);
    return_if_error(r, "byte serialize");

    out->size = size;
    return r;
    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPMT_TK_CREATION 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_TPMT_TK_CREATION_deserialize(json_object *jso,
                                        TPMT_TK_CREATION *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, "tag", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPM2_ST_deserialize(jso2, &out->tag);
    return_if_error(r, "BAD VALUE");
    if (out != NULL && out->tag != TPM2_ST_CREATION) {
        LOG_ERROR("BAD VALUE %zu != %zu", (size_t)out->tag, (size_t)TPM2_ST_CREATION);
    }

    if (!ifapi_get_sub_object(jso, "hierarchy", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPMI_RH_HIERARCHY_deserialize(jso2, &out->hierarchy);
    return_if_error(r, "BAD VALUE");

    if (!ifapi_get_sub_object(jso, "digest", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPM2B_DIGEST_deserialize(jso2, &out->digest);
    return_if_error(r, "BAD VALUE");
    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPMT_TK_VERIFIED 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_TPMT_TK_VERIFIED_deserialize(json_object *jso,
                                        TPMT_TK_VERIFIED *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, "tag", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPM2_ST_deserialize(jso2, &out->tag);
    return_if_error(r, "BAD VALUE");
    if (out != NULL && out->tag != TPM2_ST_VERIFIED) {
        LOG_ERROR("BAD VALUE %zu != %zu", (size_t)out->tag, (size_t)TPM2_ST_VERIFIED);
    }

    if (!ifapi_get_sub_object(jso, "hierarchy", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPMI_RH_HIERARCHY_deserialize(jso2, &out->hierarchy);
    return_if_error(r, "BAD VALUE");

    if (!ifapi_get_sub_object(jso, "digest", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPM2B_DIGEST_deserialize(jso2, &out->digest);
    return_if_error(r, "BAD VALUE");
    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPML_DIGEST_VALUES 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_TPML_DIGEST_VALUES_deserialize(json_object *jso,
        TPML_DIGEST_VALUES *out)
{
    TSS2_RC r;
    LOG_TRACE("call");
    return_if_null(out, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);

    json_type jso_type = json_object_get_type(jso);
    if (jso_type == json_type_array) {
        if (json_object_array_length(jso) > (int)TPM2_NUM_PCR_BANKS) {
            /* Cast (size_t) is necessary to support older version of libjson-c */
            LOG_ERROR("Too many bytes for array (%zu > %zu)",
                      (size_t)json_object_array_length(jso), (size_t)TPM2_NUM_PCR_BANKS);
            return TSS2_FAPI_RC_BAD_VALUE;
        }
        out->count = json_object_array_length(jso);
        size_t i;
        /* Cast (size_t) is necessary to support older version of libjson-c */
        for (i = 0; i < (size_t)json_object_array_length(jso); i++) {
            json_object *jso3 = json_object_array_get_idx(jso, i);
            r = ifapi_json_TPMT_HA_deserialize(jso3, &out->digests[i]);
            return_if_error(r, "BAD VALUE");
        }
        return TSS2_RC_SUCCESS;
    } else {
        LOG_ERROR("BAD VALUE");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPML_PCR_SELECTION 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_TPML_PCR_SELECTION_deserialize(json_object *jso,
        TPML_PCR_SELECTION *out)
{
    TSS2_RC r;
    LOG_TRACE("call");
    return_if_null(out, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);

    json_type jso_type = json_object_get_type(jso);
    if (jso_type == json_type_array) {
        if (json_object_array_length(jso) > (int)TPM2_NUM_PCR_BANKS) {
            /* Cast (size_t) is necessary to support older version of libjson-c */
            LOG_ERROR("Too many bytes for array (%zu > %zu)",
                      (size_t)json_object_array_length(jso), (size_t)TPM2_NUM_PCR_BANKS);
            return TSS2_FAPI_RC_BAD_VALUE;
        }
        out->count = json_object_array_length(jso);
        size_t i;
        /* Cast (size_t) is necessary to support older version of libjson-c */
        for (i = 0; i < (size_t)json_object_array_length(jso); i++) {
            json_object *jso3 = json_object_array_get_idx(jso, i);
            r = ifapi_json_TPMS_PCR_SELECTION_deserialize(jso3, &out->pcrSelections[i]);
            return_if_error(r, "BAD VALUE");
        }
        return TSS2_RC_SUCCESS;
    } else {
        LOG_ERROR("BAD VALUE");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPMS_CLOCK_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_TPMS_CLOCK_INFO_deserialize(json_object *jso,  TPMS_CLOCK_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, "clock", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_UINT64_deserialize(jso2, &out->clock);
    return_if_error(r, "BAD VALUE");

    if (!ifapi_get_sub_object(jso, "resetCount", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_UINT32_deserialize(jso2, &out->resetCount);
    return_if_error(r, "BAD VALUE");

    if (!ifapi_get_sub_object(jso, "restartCount", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_UINT32_deserialize(jso2, &out->restartCount);
    return_if_error(r, "BAD VALUE");

    if (!ifapi_get_sub_object(jso, "safe", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPMI_YES_NO_deserialize(jso2, &out->safe);
    return_if_error(r, "BAD VALUE");
    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPMS_TIME_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_TPMS_TIME_INFO_deserialize(json_object *jso,  TPMS_TIME_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, "time", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_UINT64_deserialize(jso2, &out->time);
    return_if_error(r, "BAD VALUE");

    if (!ifapi_get_sub_object(jso, "clockInfo", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPMS_CLOCK_INFO_deserialize(jso2, &out->clockInfo);
    return_if_error(r, "BAD VALUE");
    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPMS_TIME_ATTEST_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_TPMS_TIME_ATTEST_INFO_deserialize(json_object *jso,
        TPMS_TIME_ATTEST_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, "time", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPMS_TIME_INFO_deserialize(jso2, &out->time);
    return_if_error(r, "BAD VALUE");

    if (!ifapi_get_sub_object(jso, "firmwareVersion", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_UINT64_deserialize(jso2, &out->firmwareVersion);
    return_if_error(r, "BAD VALUE");
    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPMS_CERTIFY_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_TPMS_CERTIFY_INFO_deserialize(json_object *jso,
        TPMS_CERTIFY_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, "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, "qualifiedName", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPM2B_NAME_deserialize(jso2, &out->qualifiedName);
    return_if_error(r, "BAD VALUE");
    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPMS_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_TPMS_QUOTE_INFO_deserialize(json_object *jso,  TPMS_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, "pcrSelect", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPML_PCR_SELECTION_deserialize(jso2, &out->pcrSelect);
    return_if_error(r, "BAD VALUE");

    if (!ifapi_get_sub_object(jso, "pcrDigest", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPM2B_DIGEST_deserialize(jso2, &out->pcrDigest);
    return_if_error(r, "BAD VALUE");
    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPMS_COMMAND_AUDIT_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_TPMS_COMMAND_AUDIT_INFO_deserialize(json_object *jso,
        TPMS_COMMAND_AUDIT_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, "auditCounter", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_UINT64_deserialize(jso2, &out->auditCounter);
    return_if_error(r, "BAD VALUE");

    if (!ifapi_get_sub_object(jso, "digestAlg", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPM2_ALG_ID_deserialize(jso2, &out->digestAlg);
    return_if_error(r, "BAD VALUE");

    if (!ifapi_get_sub_object(jso, "auditDigest", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPM2B_DIGEST_deserialize(jso2, &out->auditDigest);
    return_if_error(r, "BAD VALUE");

    if (!ifapi_get_sub_object(jso, "commandDigest", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPM2B_DIGEST_deserialize(jso2, &out->commandDigest);
    return_if_error(r, "BAD VALUE");
    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPMS_SESSION_AUDIT_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_TPMS_SESSION_AUDIT_INFO_deserialize(json_object *jso,
        TPMS_SESSION_AUDIT_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, "exclusiveSession", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPMI_YES_NO_deserialize(jso2, &out->exclusiveSession);
    return_if_error(r, "BAD VALUE");

    if (!ifapi_get_sub_object(jso, "sessionDigest", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPM2B_DIGEST_deserialize(jso2, &out->sessionDigest);
    return_if_error(r, "BAD VALUE");
    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPMS_CREATION_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_TPMS_CREATION_INFO_deserialize(json_object *jso,
        TPMS_CREATION_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, "objectName", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPM2B_NAME_deserialize(jso2, &out->objectName);
    return_if_error(r, "BAD VALUE");

    if (!ifapi_get_sub_object(jso, "creationHash", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPM2B_DIGEST_deserialize(jso2, &out->creationHash);
    return_if_error(r, "BAD VALUE");
    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPMS_NV_CERTIFY_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_TPMS_NV_CERTIFY_INFO_deserialize(json_object *jso,
        TPMS_NV_CERTIFY_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, "indexName", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPM2B_NAME_deserialize(jso2, &out->indexName);
    return_if_error(r, "BAD VALUE");

    if (!ifapi_get_sub_object(jso, "offset", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_UINT16_deserialize(jso2, &out->offset);
    return_if_error(r, "BAD VALUE");

    if (!ifapi_get_sub_object(jso, "nvContents", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPM2B_MAX_NV_BUFFER_deserialize(jso2, &out->nvContents);
    return_if_error(r, "BAD VALUE");
    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPMI_ST_ATTEST 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_TPMI_ST_ATTEST_deserialize(json_object *jso, TPMI_ST_ATTEST *out)
{
    SUBTYPE_FILTER(TPMI_ST_ATTEST, TPM2_ST,
        TPM2_ST_ATTEST_CERTIFY, TPM2_ST_ATTEST_QUOTE, TPM2_ST_ATTEST_SESSION_AUDIT,
        TPM2_ST_ATTEST_COMMAND_AUDIT, TPM2_ST_ATTEST_TIME, TPM2_ST_ATTEST_CREATION,
        TPM2_ST_ATTEST_NV);
}

/** Deserialize a TPMU_ATTEST json object.
 *
 * This functions expects the Bitfield to be encoded as unsigned int in host-endianess.
 * @param[in]  selector The type the attest.
 * @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_TPMU_ATTEST_deserialize(
    UINT32 selector,
    json_object *jso,
    TPMU_ATTEST *out)
{
    LOG_TRACE("call");
    switch (selector) {
    case TPM2_ST_ATTEST_CERTIFY:
        return ifapi_json_TPMS_CERTIFY_INFO_deserialize(jso, &out->certify);
    case TPM2_ST_ATTEST_CREATION:
        return ifapi_json_TPMS_CREATION_INFO_deserialize(jso, &out->creation);
    case TPM2_ST_ATTEST_QUOTE:
        return ifapi_json_TPMS_QUOTE_INFO_deserialize(jso, &out->quote);
    case TPM2_ST_ATTEST_COMMAND_AUDIT:
        return ifapi_json_TPMS_COMMAND_AUDIT_INFO_deserialize(jso, &out->commandAudit);
    case TPM2_ST_ATTEST_SESSION_AUDIT:
        return ifapi_json_TPMS_SESSION_AUDIT_INFO_deserialize(jso, &out->sessionAudit);
    case TPM2_ST_ATTEST_TIME:
        return ifapi_json_TPMS_TIME_ATTEST_INFO_deserialize(jso, &out->time);
    case TPM2_ST_ATTEST_NV:
        return ifapi_json_TPMS_NV_CERTIFY_INFO_deserialize(jso, &out->nv);
    default:
        LOG_TRACE("false");
        return TSS2_FAPI_RC_BAD_VALUE;
    };
}

/** Deserialize a TPMS_ATTEST 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_TPMS_ATTEST_deserialize(json_object *jso,  TPMS_ATTEST *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, "magic", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPM2_GENERATED_deserialize(jso2, &out->magic);
    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_TPMI_ST_ATTEST_deserialize(jso2, &out->type);
    return_if_error(r, "BAD VALUE");

    if (!ifapi_get_sub_object(jso, "qualifiedSigner", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPM2B_NAME_deserialize(jso2, &out->qualifiedSigner);
    return_if_error(r, "BAD VALUE");

    if (!ifapi_get_sub_object(jso, "extraData", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPM2B_DATA_deserialize(jso2, &out->extraData);
    return_if_error(r, "BAD VALUE");

    if (!ifapi_get_sub_object(jso, "clockInfo", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPMS_CLOCK_INFO_deserialize(jso2, &out->clockInfo);
    return_if_error(r, "BAD VALUE");

    if (!ifapi_get_sub_object(jso, "firmwareVersion", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_UINT64_deserialize(jso2, &out->firmwareVersion);
    return_if_error(r, "BAD VALUE");
    if (!ifapi_get_sub_object(jso, "attested", &jso2)) {
        LOG_ERROR("BAD VALUE");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPMU_ATTEST_deserialize(out->type, jso2, &out->attested);
    return_if_error(r, "BAD VALUE");

    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPMI_AES_KEY_BITS json object.
 *
 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
 *         the function.
 */
TSS2_RC
ifapi_json_TPMI_AES_KEY_BITS_deserialize(json_object *jso, TPMI_AES_KEY_BITS *out)
{
    SUBTYPE_FILTER(TPMI_AES_KEY_BITS, UINT16,
        128, 192, 256);
}

/** Deserialize a TPMU_SYM_KEY_BITS json object.
 *
 * This functions expects the Bitfield to be encoded as unsigned int in host-endianess.
 * @param[in]  selector The type the symmetric algorithm.
 * @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_TPMU_SYM_KEY_BITS_deserialize(
    UINT32 selector,
    json_object *jso,
    TPMU_SYM_KEY_BITS *out)
{
    LOG_TRACE("call");
    switch (selector) {
    case TPM2_ALG_AES:
        return ifapi_json_TPMI_AES_KEY_BITS_deserialize(jso, &out->aes);
    case TPM2_ALG_XOR:
        return ifapi_json_TPMI_ALG_HASH_deserialize(jso, &out->exclusiveOr);

    case TPM2_ALG_NULL: {
            return TSS2_RC_SUCCESS;
        }
    default:
        LOG_TRACE("false");
        return TSS2_FAPI_RC_BAD_VALUE;
    };
}

/** Deserialize a TPMU_SYM_MODE json object.
 *
 * This functions expects the Bitfield to be encoded as unsigned int in host-endianess.
 * @param[in]  selector The type the symmetric algorithm.
 * @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_TPMU_SYM_MODE_deserialize(
    UINT32 selector,
    json_object *jso,
    TPMU_SYM_MODE *out)
{
    LOG_TRACE("call");
    switch (selector) {
    case TPM2_ALG_AES:
        return ifapi_json_TPMI_ALG_SYM_MODE_deserialize(jso, &out->aes);

    case TPM2_ALG_NULL: {
            return TSS2_RC_SUCCESS;
        }
    default:
        LOG_TRACE("false");
        return TSS2_FAPI_RC_BAD_VALUE;
    };
}

/** Deserialize a TPMT_SYM_DEF 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_TPMT_SYM_DEF_deserialize(json_object *jso,  TPMT_SYM_DEF *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, "algorithm", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPMI_ALG_SYM_deserialize(jso2, &out->algorithm);
    return_if_error(r, "BAD VALUE");
    if (out->algorithm != TPM2_ALG_NULL) {
        if (!ifapi_get_sub_object(jso, "keyBits", &jso2)) {
            LOG_ERROR("BAD VALUE");
            return TSS2_FAPI_RC_BAD_VALUE;
        }
        r = ifapi_json_TPMU_SYM_KEY_BITS_deserialize(out->algorithm, jso2,
                &out->keyBits);
        return_if_error(r, "BAD VALUE");
    }

    if (out->algorithm != TPM2_ALG_NULL) {
        if (!ifapi_get_sub_object(jso, "mode", &jso2)) {
            LOG_ERROR("BAD VALUE");
            return TSS2_FAPI_RC_BAD_VALUE;
        }
        r = ifapi_json_TPMU_SYM_MODE_deserialize(out->algorithm, jso2, &out->mode);
        return_if_error(r, "BAD VALUE");
    }

    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPMT_SYM_DEF_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.
 */
TSS2_RC
ifapi_json_TPMT_SYM_DEF_OBJECT_deserialize(json_object *jso,
        TPMT_SYM_DEF_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, "algorithm", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPMI_ALG_SYM_OBJECT_deserialize(jso2, &out->algorithm);
    return_if_error(r, "BAD VALUE");
    if (out->algorithm != TPM2_ALG_NULL) {
        if (!ifapi_get_sub_object(jso, "keyBits", &jso2)) {
            LOG_ERROR("BAD VALUE");
            return TSS2_FAPI_RC_BAD_VALUE;
        }
        r = ifapi_json_TPMU_SYM_KEY_BITS_deserialize(out->algorithm, jso2,
                &out->keyBits);
        return_if_error(r, "BAD VALUE");
    }

    if (out->algorithm != TPM2_ALG_NULL) {
        if (!ifapi_get_sub_object(jso, "mode", &jso2)) {
            LOG_ERROR("BAD VALUE");
            return TSS2_FAPI_RC_BAD_VALUE;
        }
        r = ifapi_json_TPMU_SYM_MODE_deserialize(out->algorithm, jso2, &out->mode);
        return_if_error(r, "BAD VALUE");
    }

    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPMS_SYMCIPHER_PARMS 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_TPMS_SYMCIPHER_PARMS_deserialize(json_object *jso,
        TPMS_SYMCIPHER_PARMS *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, "sym", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPMT_SYM_DEF_OBJECT_deserialize(jso2, &out->sym);
    return_if_error(r, "BAD VALUE");
    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPMS_SCHEME_HASH 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_TPMS_SCHEME_HASH_deserialize(json_object *jso,
                                        TPMS_SCHEME_HASH *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, "hashAlg", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPMI_ALG_HASH_deserialize(jso2, &out->hashAlg);
    return_if_error(r, "BAD VALUE");
    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPMS_SCHEME_ECDAA 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_TPMS_SCHEME_ECDAA_deserialize(json_object *jso,
        TPMS_SCHEME_ECDAA *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, "hashAlg", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPMI_ALG_HASH_deserialize(jso2, &out->hashAlg);
    return_if_error(r, "BAD VALUE");

    if (!ifapi_get_sub_object(jso, "count", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_UINT16_deserialize(jso2, &out->count);
    return_if_error(r, "BAD VALUE");
    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPMI_ALG_KEYEDHASH_SCHEME 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_TPMI_ALG_KEYEDHASH_SCHEME_deserialize(json_object *jso,
        TPMI_ALG_KEYEDHASH_SCHEME *out)
{
    SUBTYPE_FILTER(TPMI_ALG_KEYEDHASH_SCHEME, TPM2_ALG_ID,
        TPM2_ALG_HMAC, TPM2_ALG_XOR, TPM2_ALG_NULL);
}

/*** Table 144 - Definition of Types for HMAC_SIG_SCHEME ***/

/** Deserialize a TPMS_SCHEME_HMAC 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_TPMS_SCHEME_HMAC_deserialize(json_object *jso, TPMS_SCHEME_HMAC *out)
{
    LOG_TRACE("call");
    return ifapi_json_TPMS_SCHEME_HASH_deserialize(jso, out);
}

/** Deserialize a TPMS_SCHEME_XOR 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_TPMS_SCHEME_XOR_deserialize(json_object *jso,  TPMS_SCHEME_XOR *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, "hashAlg", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPMI_ALG_HASH_deserialize(jso2, &out->hashAlg);
    return_if_error(r, "BAD VALUE");

    if (!ifapi_get_sub_object(jso, "kdf", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPMI_ALG_KDF_deserialize(jso2, &out->kdf);
    return_if_error(r, "BAD VALUE");
    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPMU_SCHEME_KEYEDHASH json object.
 *
 * This functions expects the Bitfield to be encoded as unsigned int in host-endianess.
 * @param[in]  selector The type the keyedhash scheme.
 * @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_TPMU_SCHEME_KEYEDHASH_deserialize(
    UINT32 selector,
    json_object *jso,
    TPMU_SCHEME_KEYEDHASH *out)
{
    LOG_TRACE("call");
    switch (selector) {
    case TPM2_ALG_HMAC:
        return ifapi_json_TPMS_SCHEME_HMAC_deserialize(jso, &out->hmac);
    case TPM2_ALG_XOR:
        return ifapi_json_TPMS_SCHEME_XOR_deserialize(jso, &out->exclusiveOr);

    case TPM2_ALG_NULL: {
            return TSS2_RC_SUCCESS;
        }
    default:
        LOG_TRACE("false");
        return TSS2_FAPI_RC_BAD_VALUE;
    };
}

/** Deserialize a TPMT_KEYEDHASH_SCHEME 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_TPMT_KEYEDHASH_SCHEME_deserialize(json_object *jso,
        TPMT_KEYEDHASH_SCHEME *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, "scheme", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPMI_ALG_KEYEDHASH_SCHEME_deserialize(jso2, &out->scheme);
    return_if_error(r, "BAD VALUE");
    if (out->scheme != TPM2_ALG_NULL) {
        if (!ifapi_get_sub_object(jso, "details", &jso2)) {
            LOG_ERROR("BAD VALUE");
            return TSS2_FAPI_RC_BAD_VALUE;
        }
        r = ifapi_json_TPMU_SCHEME_KEYEDHASH_deserialize(out->scheme, jso2,
                &out->details);
        return_if_error(r, "BAD VALUE");
    }

    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/*** Table 148 - Definition of  Types for RSA Signature Schemes ***/

/** Deserialize a TPMS_SIG_SCHEME_RSASSA 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_TPMS_SIG_SCHEME_RSASSA_deserialize(json_object *jso,
        TPMS_SIG_SCHEME_RSASSA *out)
{
    LOG_TRACE("call");
    return ifapi_json_TPMS_SCHEME_HASH_deserialize(jso, out);
}

/** Deserialize a TPMS_SIG_SCHEME_RSAPSS 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_TPMS_SIG_SCHEME_RSAPSS_deserialize(json_object *jso,
        TPMS_SIG_SCHEME_RSAPSS *out)
{
    LOG_TRACE("call");
    return ifapi_json_TPMS_SCHEME_HASH_deserialize(jso, out);
}

/*** Table 149 - Definition of  Types for ECC Signature Schemes ***/

/** Deserialize a TPMS_SIG_SCHEME_ECDSA 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_TPMS_SIG_SCHEME_ECDSA_deserialize(json_object *jso,
        TPMS_SIG_SCHEME_ECDSA *out)
{
    LOG_TRACE("call");
    return ifapi_json_TPMS_SCHEME_HASH_deserialize(jso, out);
}

/** Deserialize a TPMS_SIG_SCHEME_SM2 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_TPMS_SIG_SCHEME_SM2_deserialize(json_object *jso,
        TPMS_SIG_SCHEME_SM2 *out)
{
    LOG_TRACE("call");
    return ifapi_json_TPMS_SCHEME_HASH_deserialize(jso, out);
}

/** Deserialize a TPMS_SIG_SCHEME_ECSCHNORR 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_TPMS_SIG_SCHEME_ECSCHNORR_deserialize(json_object *jso,
        TPMS_SIG_SCHEME_ECSCHNORR *out)
{
    LOG_TRACE("call");
    return ifapi_json_TPMS_SCHEME_HASH_deserialize(jso, out);
}

/** Deserialize a TPMS_SIG_SCHEME_ECDAA 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_TPMS_SIG_SCHEME_ECDAA_deserialize(json_object *jso,
        TPMS_SIG_SCHEME_ECDAA *out)
{
    LOG_TRACE("call");
    return ifapi_json_TPMS_SCHEME_ECDAA_deserialize(jso, out);
}

/** Deserialize a TPMU_SIG_SCHEME json object.
 *
 * This functions expects the Bitfield to be encoded as unsigned int in host-endianess.
 * @param[in]  selector The type the signature scheme.
 * @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_TPMU_SIG_SCHEME_deserialize(
    UINT32 selector,
    json_object *jso,
    TPMU_SIG_SCHEME *out)
{
    LOG_TRACE("call");
    switch (selector) {
    case TPM2_ALG_RSASSA:
        return ifapi_json_TPMS_SIG_SCHEME_RSASSA_deserialize(jso, &out->rsassa);
    case TPM2_ALG_RSAPSS:
        return ifapi_json_TPMS_SIG_SCHEME_RSAPSS_deserialize(jso, &out->rsapss);
    case TPM2_ALG_ECDSA:
        return ifapi_json_TPMS_SIG_SCHEME_ECDSA_deserialize(jso, &out->ecdsa);
    case TPM2_ALG_ECDAA:
        return ifapi_json_TPMS_SIG_SCHEME_ECDAA_deserialize(jso, &out->ecdaa);
    case TPM2_ALG_SM2:
        return ifapi_json_TPMS_SIG_SCHEME_SM2_deserialize(jso, &out->sm2);
    case TPM2_ALG_ECSCHNORR:
        return ifapi_json_TPMS_SIG_SCHEME_ECSCHNORR_deserialize(jso, &out->ecschnorr);
    case TPM2_ALG_HMAC:
        return ifapi_json_TPMS_SCHEME_HMAC_deserialize(jso, &out->hmac);

    case TPM2_ALG_NULL: {
            return TSS2_RC_SUCCESS;
        }
    default:
        LOG_TRACE("false");
        return TSS2_FAPI_RC_BAD_VALUE;
    };
}

/** Deserialize a TPMT_SIG_SCHEME 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_TPMT_SIG_SCHEME_deserialize(json_object *jso,  TPMT_SIG_SCHEME *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, "scheme", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPMI_ALG_SIG_SCHEME_deserialize(jso2, &out->scheme);
    return_if_error(r, "BAD VALUE");
    if (out->scheme != TPM2_ALG_NULL) {
        if (!ifapi_get_sub_object(jso, "details", &jso2)) {
            LOG_ERROR("BAD VALUE");
            return TSS2_FAPI_RC_BAD_VALUE;
        }
        r = ifapi_json_TPMU_SIG_SCHEME_deserialize(out->scheme, jso2, &out->details);
        return_if_error(r, "BAD VALUE");
    }

    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/*** Table 152 - Definition of Types for  Encryption Schemes ***/

/** Deserialize a TPMS_ENC_SCHEME_OAEP 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_TPMS_ENC_SCHEME_OAEP_deserialize(json_object *jso,
        TPMS_ENC_SCHEME_OAEP *out)
{
    LOG_TRACE("call");
    return ifapi_json_TPMS_SCHEME_HASH_deserialize(jso, out);
}

/** Deserialize a TPMS_ENC_SCHEME_RSAES 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_TPMS_ENC_SCHEME_RSAES_deserialize(json_object *jso,
        TPMS_ENC_SCHEME_RSAES *out)
{
    LOG_TRACE("call");
    return ifapi_json_TPMS_EMPTY_deserialize(jso, out);
}

/*** Table 153 - Definition of Types for  ECC Key Exchange ***/

/** Deserialize a TPMS_KEY_SCHEME_ECDH 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_TPMS_KEY_SCHEME_ECDH_deserialize(json_object *jso,
        TPMS_KEY_SCHEME_ECDH *out)
{
    LOG_TRACE("call");
    return ifapi_json_TPMS_SCHEME_HASH_deserialize(jso, out);
}

/*** Table 154 - Definition of Types for KDF Schemes ***/

/** Deserialize a TPMS_SCHEME_MGF1 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_TPMS_SCHEME_MGF1_deserialize(json_object *jso, TPMS_SCHEME_MGF1 *out)
{
    LOG_TRACE("call");
    return ifapi_json_TPMS_SCHEME_HASH_deserialize(jso, out);
}

/** Deserialize a TPMS_SCHEME_KDF1_SP800_56A 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_TPMS_SCHEME_KDF1_SP800_56A_deserialize(json_object *jso,
        TPMS_SCHEME_KDF1_SP800_56A *out)
{
    LOG_TRACE("call");
    return ifapi_json_TPMS_SCHEME_HASH_deserialize(jso, out);
}

/** Deserialize a TPMS_SCHEME_KDF1_SP800_108 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_TPMS_SCHEME_KDF1_SP800_108_deserialize(json_object *jso,
        TPMS_SCHEME_KDF1_SP800_108 *out)
{
    LOG_TRACE("call");
    return ifapi_json_TPMS_SCHEME_HASH_deserialize(jso, out);
}

/** Deserialize a TPMU_KDF_SCHEME json object.
 *
 * This functions expects the Bitfield to be encoded as unsigned int in host-endianess.
 * @param[in]  selector The type the KDF scheme.
 * @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_TPMU_KDF_SCHEME_deserialize(
    UINT32 selector,
    json_object *jso,
    TPMU_KDF_SCHEME *out)
{
    LOG_TRACE("call");
    switch (selector) {
    case TPM2_ALG_MGF1:
        return ifapi_json_TPMS_SCHEME_MGF1_deserialize(jso, &out->mgf1);
    case TPM2_ALG_KDF1_SP800_56A:
        return ifapi_json_TPMS_SCHEME_KDF1_SP800_56A_deserialize(jso,
                &out->kdf1_sp800_56a);
    case TPM2_ALG_KDF1_SP800_108:
        return ifapi_json_TPMS_SCHEME_KDF1_SP800_108_deserialize(jso,
                &out->kdf1_sp800_108);

    case TPM2_ALG_NULL: {
            return TSS2_RC_SUCCESS;
        }
    default:
        LOG_TRACE("false");
        return TSS2_FAPI_RC_BAD_VALUE;
    };
}

/** Deserialize a TPMT_KDF_SCHEME 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_TPMT_KDF_SCHEME_deserialize(json_object *jso,  TPMT_KDF_SCHEME *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, "scheme", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPMI_ALG_KDF_deserialize(jso2, &out->scheme);
    return_if_error(r, "BAD VALUE");
    if (out->scheme != TPM2_ALG_NULL) {
        if (!ifapi_get_sub_object(jso, "details", &jso2)) {
            LOG_ERROR("BAD VALUE");
            return TSS2_FAPI_RC_BAD_VALUE;
        }
        r = ifapi_json_TPMU_KDF_SCHEME_deserialize(out->scheme, jso2, &out->details);
        return_if_error(r, "BAD VALUE");
    }

    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPMU_ASYM_SCHEME 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 type the scheme.
 * @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_TPMU_ASYM_SCHEME_deserialize(
    UINT32 selector,
    json_object *jso,
    TPMU_ASYM_SCHEME *out)
{
    LOG_TRACE("call");
    switch (selector) {
    case TPM2_ALG_ECDH:
        return ifapi_json_TPMS_KEY_SCHEME_ECDH_deserialize(jso, &out->ecdh);
    case TPM2_ALG_RSASSA:
        return ifapi_json_TPMS_SIG_SCHEME_RSASSA_deserialize(jso, &out->rsassa);
    case TPM2_ALG_RSAPSS:
        return ifapi_json_TPMS_SIG_SCHEME_RSAPSS_deserialize(jso, &out->rsapss);
    case TPM2_ALG_ECDSA:
        return ifapi_json_TPMS_SIG_SCHEME_ECDSA_deserialize(jso, &out->ecdsa);
    case TPM2_ALG_ECDAA:
        return ifapi_json_TPMS_SIG_SCHEME_ECDAA_deserialize(jso, &out->ecdaa);
    case TPM2_ALG_SM2:
        return ifapi_json_TPMS_SIG_SCHEME_SM2_deserialize(jso, &out->sm2);
    case TPM2_ALG_ECSCHNORR:
        return ifapi_json_TPMS_SIG_SCHEME_ECSCHNORR_deserialize(jso, &out->ecschnorr);
    case TPM2_ALG_RSAES:
        return ifapi_json_TPMS_ENC_SCHEME_RSAES_deserialize(jso, &out->rsaes);
    case TPM2_ALG_OAEP:
        return ifapi_json_TPMS_ENC_SCHEME_OAEP_deserialize(jso, &out->oaep);

    case TPM2_ALG_NULL: {
            return TSS2_RC_SUCCESS;
        }
    default:
        LOG_TRACE("false");
        return TSS2_FAPI_RC_BAD_VALUE;
    };
}

/** Deserialize a TPMI_ALG_RSA_SCHEME 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_TPMI_ALG_RSA_SCHEME_deserialize(json_object *jso,
        TPMI_ALG_RSA_SCHEME *out)
{
    SUBTYPE_FILTER(TPMI_ALG_RSA_SCHEME, TPM2_ALG_ID,
        TPM2_ALG_RSAES, TPM2_ALG_OAEP, TPM2_ALG_RSASSA, TPM2_ALG_RSAPSS, TPM2_ALG_NULL);
}

/** Deserialize a TPMT_RSA_SCHEME 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_TPMT_RSA_SCHEME_deserialize(json_object *jso,  TPMT_RSA_SCHEME *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, "scheme", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPMI_ALG_RSA_SCHEME_deserialize(jso2, &out->scheme);
    return_if_error(r, "BAD VALUE");
    if (out->scheme != TPM2_ALG_NULL) {
        if (!ifapi_get_sub_object(jso, "details", &jso2)) {
            LOG_ERROR("BAD VALUE");
            return TSS2_FAPI_RC_BAD_VALUE;
        }
        r = ifapi_json_TPMU_ASYM_SCHEME_deserialize(out->scheme, jso2, &out->details);
        return_if_error(r, "BAD VALUE");
    }

    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPMI_ALG_RSA_DECRYPT 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_TPMI_ALG_RSA_DECRYPT_deserialize(json_object *jso,
        TPMI_ALG_RSA_DECRYPT *out)
{
    SUBTYPE_FILTER(TPMI_ALG_RSA_DECRYPT, TPM2_ALG_ID,
        TPM2_ALG_RSAES, TPM2_ALG_OAEP, TPM2_ALG_NULL);
}

/** Deserialize a TPMT_RSA_DECRYPT 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_TPMT_RSA_DECRYPT_deserialize(json_object *jso,
                                        TPMT_RSA_DECRYPT *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, "scheme", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPMI_ALG_RSA_DECRYPT_deserialize(jso2, &out->scheme);
    return_if_error(r, "BAD VALUE");
    if (out->scheme != TPM2_ALG_NULL) {
        if (!ifapi_get_sub_object(jso, "details", &jso2)) {
            LOG_ERROR("BAD VALUE");
            return TSS2_FAPI_RC_BAD_VALUE;
        }
        r = ifapi_json_TPMU_ASYM_SCHEME_deserialize(out->scheme, jso2, &out->details);
        return_if_error(r, "BAD VALUE");
    }

    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPM2B_PUBLIC_KEY_RSA 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_TPM2B_PUBLIC_KEY_RSA_deserialize(json_object *jso,
        TPM2B_PUBLIC_KEY_RSA *out)
{
    TSS2_RC r;
    LOG_TRACE("call");
    return_if_null(out, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);

    UINT16 size = 0;
    r = ifapi_json_byte_deserialize(jso, TPM2_MAX_RSA_KEY_BYTES,
                                     (BYTE *)&out->buffer, &size);
    return_if_error(r, "byte serialize");

    out->size = size;
    return r;
    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPMI_RSA_KEY_BITS json object.
 *
 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
 *         the function.
 */
TSS2_RC
ifapi_json_TPMI_RSA_KEY_BITS_deserialize(json_object *jso,
        TPMI_RSA_KEY_BITS *out)
{
    SUBTYPE_FILTER(TPMI_RSA_KEY_BITS, UINT16,
        1024, 2048);
}

/** Deserialize a TPM2B_ECC_PARAMETER 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_TPM2B_ECC_PARAMETER_deserialize(json_object *jso,
        TPM2B_ECC_PARAMETER *out)
{
    TSS2_RC r;
    LOG_TRACE("call");
    return_if_null(out, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);

    UINT16 size = 0;
    r = ifapi_json_byte_deserialize(jso, TPM2_MAX_ECC_KEY_BYTES,
                                     (BYTE *)&out->buffer, &size);
    return_if_error(r, "byte serialize");

    out->size = size;
    return r;
    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPMS_ECC_POINT 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_TPMS_ECC_POINT_deserialize(json_object *jso,  TPMS_ECC_POINT *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, "x", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPM2B_ECC_PARAMETER_deserialize(jso2, &out->x);
    return_if_error(r, "BAD VALUE");

    if (!ifapi_get_sub_object(jso, "y", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPM2B_ECC_PARAMETER_deserialize(jso2, &out->y);
    return_if_error(r, "BAD VALUE");
    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPMI_ALG_ECC_SCHEME 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_TPMI_ALG_ECC_SCHEME_deserialize(json_object *jso,
        TPMI_ALG_ECC_SCHEME *out)
{
    SUBTYPE_FILTER(TPMI_ALG_ECC_SCHEME, TPM2_ALG_ID,
        TPM2_ALG_ECDSA, TPM2_ALG_ECDAA, TPM2_ALG_SM2, TPM2_ALG_ECSCHNORR,
        TPM2_ALG_ECDH, TPM2_ALG_NULL);
}

/** Deserialize a TPMI_ECC_CURVE json object.
 *
 * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
 *         the function.
 */
TSS2_RC
ifapi_json_TPMI_ECC_CURVE_deserialize(json_object *jso, TPMI_ECC_CURVE *out)
{
    SUBTYPE_FILTER(TPMI_ECC_CURVE, TPM2_ECC_CURVE,
        TPM2_ECC_NONE, TPM2_ECC_NIST_P192, TPM2_ECC_NIST_P224, TPM2_ECC_NIST_P256,
        TPM2_ECC_NIST_P384, TPM2_ECC_NIST_P521, TPM2_ECC_BN_P256, TPM2_ECC_BN_P638,
        TPM2_ECC_SM2_P256);
}

/** Deserialize a TPMT_ECC_SCHEME 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_TPMT_ECC_SCHEME_deserialize(json_object *jso,  TPMT_ECC_SCHEME *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, "scheme", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPMI_ALG_ECC_SCHEME_deserialize(jso2, &out->scheme);
    return_if_error(r, "BAD VALUE");
    if (out->scheme != TPM2_ALG_NULL) {
        if (!ifapi_get_sub_object(jso, "details", &jso2)) {
            LOG_ERROR("BAD VALUE");
            return TSS2_FAPI_RC_BAD_VALUE;
        }
        r = ifapi_json_TPMU_ASYM_SCHEME_deserialize(out->scheme, jso2, &out->details);
        return_if_error(r, "BAD VALUE");
    }

    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPMS_SIGNATURE_RSA 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_TPMS_SIGNATURE_RSA_deserialize(json_object *jso,
        TPMS_SIGNATURE_RSA *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, "hash", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPMI_ALG_HASH_deserialize(jso2, &out->hash);
    return_if_error(r, "BAD VALUE");

    if (!ifapi_get_sub_object(jso, "sig", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPM2B_PUBLIC_KEY_RSA_deserialize(jso2, &out->sig);
    return_if_error(r, "BAD VALUE");
    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/*** Table 175 - Definition of Types for  Signature ***/

/** Deserialize a TPMS_SIGNATURE_RSASSA 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_TPMS_SIGNATURE_RSASSA_deserialize(json_object *jso,
        TPMS_SIGNATURE_RSASSA *out)
{
    LOG_TRACE("call");
    return ifapi_json_TPMS_SIGNATURE_RSA_deserialize(jso, out);
}

/** Deserialize a TPMS_SIGNATURE_RSAPSS 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_TPMS_SIGNATURE_RSAPSS_deserialize(json_object *jso,
        TPMS_SIGNATURE_RSAPSS *out)
{
    LOG_TRACE("call");
    return ifapi_json_TPMS_SIGNATURE_RSA_deserialize(jso, out);
}

/** Deserialize a TPMS_SIGNATURE_ECC 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_TPMS_SIGNATURE_ECC_deserialize(json_object *jso,
        TPMS_SIGNATURE_ECC *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, "hash", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPMI_ALG_HASH_deserialize(jso2, &out->hash);
    return_if_error(r, "BAD VALUE");

    if (!ifapi_get_sub_object(jso, "signatureR", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPM2B_ECC_PARAMETER_deserialize(jso2, &out->signatureR);
    return_if_error(r, "BAD VALUE");

    if (!ifapi_get_sub_object(jso, "signatureS", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPM2B_ECC_PARAMETER_deserialize(jso2, &out->signatureS);
    return_if_error(r, "BAD VALUE");
    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/*** Table 177 - Definition of Types for  TPMS_SIGNATURE_ECC ***/

/** Deserialize a TPMS_SIGNATURE_ECDSA 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_TPMS_SIGNATURE_ECDSA_deserialize(json_object *jso,
        TPMS_SIGNATURE_ECDSA *out)
{
    LOG_TRACE("call");
    return ifapi_json_TPMS_SIGNATURE_ECC_deserialize(jso, out);
}

/** Deserialize a TPMS_SIGNATURE_ECDAA 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_TPMS_SIGNATURE_ECDAA_deserialize(json_object *jso,
        TPMS_SIGNATURE_ECDAA *out)
{
    LOG_TRACE("call");
    return ifapi_json_TPMS_SIGNATURE_ECC_deserialize(jso, out);
}

/** Deserialize a TPMS_SIGNATURE_SM2 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_TPMS_SIGNATURE_SM2_deserialize(json_object *jso,
        TPMS_SIGNATURE_SM2 *out)
{
    LOG_TRACE("call");
    return ifapi_json_TPMS_SIGNATURE_ECC_deserialize(jso, out);
}

/** Deserialize a TPMS_SIGNATURE_ECSCHNORR 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_TPMS_SIGNATURE_ECSCHNORR_deserialize(json_object *jso,
        TPMS_SIGNATURE_ECSCHNORR *out)
{
    LOG_TRACE("call");
    return ifapi_json_TPMS_SIGNATURE_ECC_deserialize(jso, out);
}

/** Deserialize a TPMU_SIGNATURE json object.
 *
 * This functions expects the Bitfield to be encoded as unsigned int in host-endianess.
 * @param[in]  selector The type the signature.
 * @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_TPMU_SIGNATURE_deserialize(
    UINT32 selector,
    json_object *jso,
    TPMU_SIGNATURE *out)
{
    LOG_TRACE("call");
    switch (selector) {
    case TPM2_ALG_RSASSA:
        return ifapi_json_TPMS_SIGNATURE_RSASSA_deserialize(jso, &out->rsassa);
    case TPM2_ALG_RSAPSS:
        return ifapi_json_TPMS_SIGNATURE_RSAPSS_deserialize(jso, &out->rsapss);
    case TPM2_ALG_ECDSA:
        return ifapi_json_TPMS_SIGNATURE_ECDSA_deserialize(jso, &out->ecdsa);
    case TPM2_ALG_ECDAA:
        return ifapi_json_TPMS_SIGNATURE_ECDAA_deserialize(jso, &out->ecdaa);
    case TPM2_ALG_SM2:
        return ifapi_json_TPMS_SIGNATURE_SM2_deserialize(jso, &out->sm2);
    case TPM2_ALG_ECSCHNORR:
        return ifapi_json_TPMS_SIGNATURE_ECSCHNORR_deserialize(jso, &out->ecschnorr);
    case TPM2_ALG_HMAC:
        return ifapi_json_TPMT_HA_deserialize(jso, &out->hmac);

    case TPM2_ALG_NULL: {
            return TSS2_RC_SUCCESS;
        }
    default:
        LOG_TRACE("false");
        return TSS2_FAPI_RC_BAD_VALUE;
    };
}

/** Deserialize a TPMT_SIGNATURE 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_TPMT_SIGNATURE_deserialize(json_object *jso,  TPMT_SIGNATURE *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, "sigAlg", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPMI_ALG_SIG_SCHEME_deserialize(jso2, &out->sigAlg);
    return_if_error(r, "BAD VALUE");
    if (out->sigAlg != TPM2_ALG_NULL) {
        if (!ifapi_get_sub_object(jso, "signature", &jso2)) {
            LOG_ERROR("BAD VALUE");
            return TSS2_FAPI_RC_BAD_VALUE;
        }
        r = ifapi_json_TPMU_SIGNATURE_deserialize(out->sigAlg, jso2, &out->signature);
        return_if_error(r, "BAD VALUE");
    }

    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPM2B_ENCRYPTED_SECRET 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_TPM2B_ENCRYPTED_SECRET_deserialize(json_object *jso,
        TPM2B_ENCRYPTED_SECRET *out)
{
    TSS2_RC r;
    LOG_TRACE("call");
    return_if_null(out, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);

    UINT16 size = 0;
    r = ifapi_json_byte_deserialize(jso, sizeof(TPMU_ENCRYPTED_SECRET),
                                     (BYTE *)&out->secret, &size);
    return_if_error(r, "byte serialize");

    out->size = size;
    return r;
    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPMI_ALG_PUBLIC 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_TPMI_ALG_PUBLIC_deserialize(json_object *jso, TPMI_ALG_PUBLIC *out)
{
    SUBTYPE_FILTER(TPMI_ALG_PUBLIC, TPM2_ALG_ID,
        TPM2_ALG_RSA, TPM2_ALG_KEYEDHASH, TPM2_ALG_ECC, TPM2_ALG_SYMCIPHER, TPM2_ALG_NULL);
}

/** Deserialize a TPMU_PUBLIC_ID json object.
 *
 * This functions expects the Bitfield to be encoded as unsigned int in host-endianess.
 * @param[in]  selector The type the public ID.
 * @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_TPMU_PUBLIC_ID_deserialize(
    UINT32 selector,
    json_object *jso,
    TPMU_PUBLIC_ID *out)
{
    LOG_TRACE("call");
    switch (selector) {
    case TPM2_ALG_KEYEDHASH:
        return ifapi_json_TPM2B_DIGEST_deserialize(jso, &out->keyedHash);
    case TPM2_ALG_SYMCIPHER:
        return ifapi_json_TPM2B_DIGEST_deserialize(jso, &out->sym);
    case TPM2_ALG_RSA:
        return ifapi_json_TPM2B_PUBLIC_KEY_RSA_deserialize(jso, &out->rsa);
    case TPM2_ALG_ECC:
        return ifapi_json_TPMS_ECC_POINT_deserialize(jso, &out->ecc);
    default:
        LOG_TRACE("false");
        return TSS2_FAPI_RC_BAD_VALUE;
    };
}

/** Deserialize a TPMS_KEYEDHASH_PARMS 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_TPMS_KEYEDHASH_PARMS_deserialize(json_object *jso,
        TPMS_KEYEDHASH_PARMS *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, "scheme", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPMT_KEYEDHASH_SCHEME_deserialize(jso2, &out->scheme);
    return_if_error(r, "BAD VALUE");
    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPMS_RSA_PARMS 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_TPMS_RSA_PARMS_deserialize(json_object *jso,  TPMS_RSA_PARMS *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, "symmetric", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPMT_SYM_DEF_OBJECT_deserialize(jso2, &out->symmetric);
    return_if_error(r, "BAD VALUE");

    if (!ifapi_get_sub_object(jso, "scheme", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPMT_RSA_SCHEME_deserialize(jso2, &out->scheme);
    return_if_error(r, "BAD VALUE");

    if (!ifapi_get_sub_object(jso, "keyBits", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPMI_RSA_KEY_BITS_deserialize(jso2, &out->keyBits);
    return_if_error(r, "BAD VALUE");

    if (!ifapi_get_sub_object(jso, "exponent", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_UINT32_deserialize(jso2, &out->exponent);
    return_if_error(r, "BAD VALUE");
    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPMS_ECC_PARMS 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_TPMS_ECC_PARMS_deserialize(json_object *jso,  TPMS_ECC_PARMS *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, "symmetric", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPMT_SYM_DEF_OBJECT_deserialize(jso2, &out->symmetric);
    return_if_error(r, "BAD VALUE");

    if (!ifapi_get_sub_object(jso, "scheme", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPMT_ECC_SCHEME_deserialize(jso2, &out->scheme);
    return_if_error(r, "BAD VALUE");

    if (!ifapi_get_sub_object(jso, "curveID", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPMI_ECC_CURVE_deserialize(jso2, &out->curveID);
    return_if_error(r, "BAD VALUE");

    if (!ifapi_get_sub_object(jso, "kdf", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPMT_KDF_SCHEME_deserialize(jso2, &out->kdf);
    return_if_error(r, "BAD VALUE");
    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPMU_PUBLIC_PARMS json object.
 *
 * This functions expects the Bitfield to be encoded as unsigned int in host-endianess.
 * @param[in]  selector The type the public params.
 * @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_TPMU_PUBLIC_PARMS_deserialize(
    UINT32 selector,
    json_object *jso,
    TPMU_PUBLIC_PARMS *out)
{
    LOG_TRACE("call");
    switch (selector) {
    case TPM2_ALG_KEYEDHASH:
        return ifapi_json_TPMS_KEYEDHASH_PARMS_deserialize(jso, &out->keyedHashDetail);
    case TPM2_ALG_SYMCIPHER:
        return ifapi_json_TPMS_SYMCIPHER_PARMS_deserialize(jso, &out->symDetail);
    case TPM2_ALG_RSA:
        return ifapi_json_TPMS_RSA_PARMS_deserialize(jso, &out->rsaDetail);
    case TPM2_ALG_ECC:
        return ifapi_json_TPMS_ECC_PARMS_deserialize(jso, &out->eccDetail);
    default:
        LOG_TRACE("false");
        return TSS2_FAPI_RC_BAD_VALUE;
    };
}

/** Deserialize a TPMT_PUBLIC 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_TPMT_PUBLIC_deserialize(json_object *jso,  TPMT_PUBLIC *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, "type", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPMI_ALG_PUBLIC_deserialize(jso2, &out->type);
    return_if_error(r, "BAD VALUE");

    if (!ifapi_get_sub_object(jso, "nameAlg", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPMI_ALG_HASH_deserialize(jso2, &out->nameAlg);
    return_if_error(r, "BAD VALUE");

    if (!ifapi_get_sub_object(jso, "objectAttributes", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPMA_OBJECT_deserialize(jso2, &out->objectAttributes);
    return_if_error(r, "BAD VALUE");

    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, "parameters", &jso2)) {
        LOG_ERROR("BAD VALUE");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPMU_PUBLIC_PARMS_deserialize(out->type, jso2, &out->parameters);
    return_if_error(r, "BAD VALUE");

    if (!ifapi_get_sub_object(jso, "unique", &jso2)) {
        LOG_ERROR("BAD VALUE");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPMU_PUBLIC_ID_deserialize(out->type, jso2, &out->unique);
    return_if_error(r, "BAD VALUE");

    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPM2B_PUBLIC 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_TPM2B_PUBLIC_deserialize(json_object *jso, TPM2B_PUBLIC *out)
{
    json_object *jso2;
    TSS2_RC res;
    LOG_TRACE("call");
    if (!ifapi_get_sub_object(jso, "size", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    res = ifapi_json_UINT16_deserialize(jso2, &out->size);
    return_if_error(res, "BAD VALUE");
    if (!ifapi_get_sub_object(jso, "publicArea", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    res = ifapi_json_TPMT_PUBLIC_deserialize(jso2, &out->publicArea);
    return_if_error(res, "BAD VALUE");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPM2B_PRIVATE 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_TPM2B_PRIVATE_deserialize(json_object *jso,  TPM2B_PRIVATE *out)
{
    TSS2_RC r;
    LOG_TRACE("call");
    return_if_null(out, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);

    UINT16 size = 0;
    r = ifapi_json_byte_deserialize(jso, sizeof(_PRIVATE), (BYTE *)&out->buffer,
                                     &size);
    return_if_error(r, "byte serialize");

    out->size = size;
    return r;
    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPM2_NT 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_TPM2_NT_deserialize(json_object *jso, TPM2_NT *out)
{
    static const struct { TPM2_NT in; const char *name; } tab[] = {
        { TPM2_NT_ORDINARY, "ORDINARY" },
        { TPM2_NT_COUNTER, "COUNTER" },
        { TPM2_NT_BITS, "BITS" },
        { TPM2_NT_EXTEND, "EXTEND" },
        { TPM2_NT_PIN_FAIL, "PIN_FAIL" },
        { TPM2_NT_PIN_PASS, "PIN_PASS" },
    };

    const char *s = json_object_get_string(jso);
    const char *str = strip_prefix(s, "TPM_", "TPM2_", "NT_", NULL);
    LOG_TRACE("called for %s parsing %s", s, str);

    if (str) {
        for (size_t i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
            if (strcasecmp(str, &tab[i].name[0]) == 0) {
                *out = tab[i].in;
                return TSS2_RC_SUCCESS;
            }
        }
    }

    return ifapi_json_UINT8_deserialize(jso, out);
}

/** Deserialize a TPMA_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.
 */
TSS2_RC
ifapi_json_TPMA_NV_deserialize(json_object *jso, TPMA_NV *out)
{
    struct { TPMA_NV in; char *name; } tab[] = {
        { TPMA_NV_PPWRITE, "PPWRITE" },
        { TPMA_NV_OWNERWRITE, "OWNERWRITE" },
        { TPMA_NV_AUTHWRITE, "AUTHWRITE" },
        { TPMA_NV_POLICYWRITE, "POLICYWRITE" },
        { TPMA_NV_POLICY_DELETE, "POLICY_DELETE" },
        { TPMA_NV_WRITELOCKED, "WRITELOCKED" },
        { TPMA_NV_WRITEALL, "WRITEALL" },
        { TPMA_NV_WRITEDEFINE, "WRITEDEFINE" },
        { TPMA_NV_WRITE_STCLEAR, "WRITE_STCLEAR" },
        { TPMA_NV_GLOBALLOCK, "GLOBALLOCK" },
        { TPMA_NV_PPREAD, "PPREAD" },
        { TPMA_NV_OWNERREAD, "OWNERREAD" },
        { TPMA_NV_AUTHREAD, "AUTHREAD" },
        { TPMA_NV_POLICYREAD, "POLICYREAD" },
        { TPMA_NV_NO_DA, "NO_DA" },
        { TPMA_NV_ORDERLY, "ORDERLY" },
        { TPMA_NV_CLEAR_STCLEAR, "CLEAR_STCLEAR" },
        { TPMA_NV_READLOCKED, "READLOCKED" },
        { TPMA_NV_WRITTEN, "WRITTEN" },
        { TPMA_NV_PLATFORMCREATE, "PLATFORMCREATE" },
        { TPMA_NV_READ_STCLEAR, "READ_STCLEAR" },
        { TPM2_NT_ORDINARY << 4, "ORDINARY" },
        { TPM2_NT_COUNTER << 4, "COUNTER" },
        { TPM2_NT_BITS << 4, "BITS" },
        { TPM2_NT_EXTEND << 4, "EXTEND" },
        { TPM2_NT_PIN_FAIL << 4, "PIN_FAIL" },
        { TPM2_NT_PIN_PASS << 4, "PIN_PASS" },
    };
    size_t n = sizeof(tab) / sizeof(tab[0]);
    size_t i, j;

    TPMI_YES_NO flag;
    TSS2_RC r;

    LOG_TRACE("call");
    memset(out, 0, sizeof(TPMA_NV));
    json_type jso_type = json_object_get_type(jso);
    if (jso_type == json_type_array) {
        /* Cast (size_t) is necessary to support older version of libjson-c */
        for (i = 0; i < (size_t)json_object_array_length(jso); i++) {
            json_object *jso2 = json_object_array_get_idx(jso, i);
            if (json_object_get_type(jso2) == json_type_object) {
                if (!json_object_object_get_ex(jso2, "TPM2_NT", &jso2)) {
                    LOG_ERROR("Found object in array without TPM2_NT");
                    return TSS2_FAPI_RC_BAD_VALUE;
                }
                TPM2_NT out2;
                TSS2_RC r = ifapi_json_TPM2_NT_deserialize(jso2, &out2);
                return_if_error(r, "Bad value");
                *out |= out2 << 4;
                continue;
            }
            const char *token = strip_prefix(json_object_get_string(jso2),
                                    "TPM_", "TPM2_", "TPMA_", "NV_",
                                    "TPM2_", "NT_", NULL);
            if (!token) {
                LOG_ERROR("Bad object; expected array of strings.");
                return TSS2_FAPI_RC_BAD_VALUE;
            }
            for (j = 0; j < n; j++) {
                if (strcasecmp(tab[j].name, token) == 0) {
                    *out |= tab[j].in;
                    break;
                }
            }
            if (j == n) {
                LOG_ERROR("Unknown value: %s", json_object_get_string(jso2));
                return TSS2_FAPI_RC_BAD_VALUE;
            }
        }
    } else if (jso_type == json_type_object) {
        json_object_object_foreach(jso, key, val) {
            const char *token = strip_prefix(key, "TPM_", "TPM2_", "TPMA_", "NV_", "TPM2_", NULL);
            if (strcasecmp(token, "NT") == 0) {
                TPM2_NT out2;
                TSS2_RC r = ifapi_json_TPM2_NT_deserialize(val, &out2);
                return_if_error(r, "Bad value");
                *out |= out2 << 4;
                continue;
            }
            token = strip_prefix(token, "NT_", NULL);
            r = get_boolean_from_json(val, &flag);
            return_if_error2(r, "Boolean value expected at key: %s", key);
            for (j = 0; j < n; j++) {
                if (strcasecmp(tab[j].name, token) == 0) {
                    if (flag)
                        *out |= tab[j].in;
                    break;
                }
            }
            if (j == n) {
                LOG_ERROR("Unknown key: %s", key);
                return TSS2_FAPI_RC_BAD_VALUE;
            }
        }
    } else {
        const char *token;
        token = json_object_get_string(jso);
        int64_t i64;
        if (!get_number(token, &i64)) {
            LOG_ERROR("Bad value");
            return TSS2_FAPI_RC_BAD_VALUE;
        }
        *out = (TPMA_NV) i64;
        if ((int64_t)*out != i64) {
            LOG_ERROR("Bad value");
            return TSS2_FAPI_RC_BAD_VALUE;
        }
        return TSS2_RC_SUCCESS;
    }
    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPMS_NV_PUBLIC 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_TPMS_NV_PUBLIC_deserialize(json_object *jso,  TPMS_NV_PUBLIC *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, "nvIndex", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPMI_RH_NV_INDEX_deserialize(jso2, &out->nvIndex);
    return_if_error(r, "BAD VALUE");

    if (!ifapi_get_sub_object(jso, "nameAlg", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPMI_ALG_HASH_deserialize(jso2, &out->nameAlg);
    return_if_error(r, "BAD VALUE");

    if (!ifapi_get_sub_object(jso, "attributes", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPMA_NV_deserialize(jso2, &out->attributes);
    return_if_error(r, "BAD VALUE");

    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, "dataSize", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_UINT16_deserialize(jso2, &out->dataSize);
    return_if_error(r, "BAD VALUE");

    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPM2B_NV_PUBLIC 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_TPM2B_NV_PUBLIC_deserialize(json_object *jso, TPM2B_NV_PUBLIC *out)
{
    json_object *jso2;
    TSS2_RC res;
    LOG_TRACE("call");
    if (!ifapi_get_sub_object(jso, "size", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    res = ifapi_json_UINT16_deserialize(jso2, &out->size);
    return_if_error(res, "BAD VALUE");
    if (!ifapi_get_sub_object(jso, "nvPublic", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    res = ifapi_json_TPMS_NV_PUBLIC_deserialize(jso2, &out->nvPublic);
    return_if_error(res, "BAD VALUE");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPMS_CREATION_DATA 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_TPMS_CREATION_DATA_deserialize(json_object *jso,
        TPMS_CREATION_DATA *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, "pcrSelect", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPML_PCR_SELECTION_deserialize(jso2, &out->pcrSelect);
    return_if_error(r, "BAD VALUE");

    if (!ifapi_get_sub_object(jso, "pcrDigest", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPM2B_DIGEST_deserialize(jso2, &out->pcrDigest);
    return_if_error(r, "BAD VALUE");

    if (!ifapi_get_sub_object(jso, "locality", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPMA_LOCALITY_deserialize(jso2, &out->locality);
    return_if_error(r, "BAD VALUE");

    if (!ifapi_get_sub_object(jso, "parentNameAlg", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPM2_ALG_ID_deserialize(jso2, &out->parentNameAlg);
    return_if_error(r, "BAD VALUE");

    if (!ifapi_get_sub_object(jso, "parentName", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPM2B_NAME_deserialize(jso2, &out->parentName);
    return_if_error(r, "BAD VALUE");

    if (!ifapi_get_sub_object(jso, "parentQualifiedName", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPM2B_NAME_deserialize(jso2, &out->parentQualifiedName);
    return_if_error(r, "BAD VALUE");

    if (!ifapi_get_sub_object(jso, "outsideInfo", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    r = ifapi_json_TPM2B_DATA_deserialize(jso2, &out->outsideInfo);
    return_if_error(r, "BAD VALUE");
    LOG_TRACE("true");
    return TSS2_RC_SUCCESS;
}

/** Deserialize a TPM2B_CREATION_DATA 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_TPM2B_CREATION_DATA_deserialize(json_object *jso,
        TPM2B_CREATION_DATA *out)
{
    json_object *jso2;
    TSS2_RC res;
    LOG_TRACE("call");
    if (!ifapi_get_sub_object(jso, "size", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    res = ifapi_json_UINT16_deserialize(jso2, &out->size);
    return_if_error(res, "BAD VALUE");
    if (!ifapi_get_sub_object(jso, "creationData", &jso2)) {
        LOG_ERROR("Bad value");
        return TSS2_FAPI_RC_BAD_VALUE;
    }
    res = ifapi_json_TPMS_CREATION_DATA_deserialize(jso2, &out->creationData);
    return_if_error(res, "BAD VALUE");
    return TSS2_RC_SUCCESS;
}
