[go: nahoru, domu]

FAPI: Add initial implementation of tss2-fapi.so

This implements a new interface and library for the
TCG TSS Feature API specification.

Co-authored-by: Andreas Fuchs <andreas.fuchs@sit.fraunhofer.de>
Co-authored-by: Lukas Jäger <lukas.jaeger@sit.fraunhofer.de>

Signed-off-by: Juergen Repp <juergen.repp@sit.fraunhofer.de>
Signed-off-by: Lukas Jäger <lukas.jaeger@sit.fraunhofer.de>
Signed-off-by: Andreas Fuchs <andreas.fuchs@sit.fraunhofer.de>
diff --git a/.ci/docker.run b/.ci/docker.run
index 00edb33..9e5783f 100755
--- a/.ci/docker.run
+++ b/.ci/docker.run
@@ -5,6 +5,8 @@
 
 source $TRAVIS_BUILD_DIR/.ci/docker-prelude.sh
 
+export CONFIGURE_OPTIONS=
+
 if [ -d build ]; then
   rm -rf build
 fi
@@ -24,6 +26,10 @@
     export WITH_CRYPTO="ossl"
 fi
 
+if [ "$WITH_CRYPTO" != "ossl" ]; then
+    export CONFIGURE_OPTIONS="$CONFIGURE_OPTIONS --disable-fapi"
+fi
+
 ./bootstrap
 
 # Is it a fuzz run, if so build the fuzz test and exit.
@@ -44,7 +50,7 @@
 echo "PWD: $(pwd)"
 echo "ls -la ../ $(ls -la ../)"
 
-../configure --enable-tcti-partial-reads=$WITH_TCTI_PARTIAL --enable-tcti-device-async=$WITH_TCTI_ASYNC --with-crypto=$WITH_CRYPTO
+../configure --enable-tcti-partial-reads=$WITH_TCTI_PARTIAL --enable-tcti-device-async=$WITH_TCTI_ASYNC --with-crypto=$WITH_CRYPTO $CONFIGURE_OPTIONS
 make -j$(nproc)
 popd
 
@@ -53,13 +59,13 @@
 pushd ./build
 
 if [ "$CC" == "gcc" ]; then
-  export CONFIGURE_OPTIONS="--enable-code-coverage";
+  export CONFIGURE_OPTIONS="$CONFIGURE_OPTIONS --enable-code-coverage";
 fi
 
 if [ "$SCANBUILD" == "yes" ]; then
   scan-build --status-bugs ../configure --enable-tcti-partial-reads=$WITH_TCTI_PARTIAL --enable-tcti-device-async=$WITH_TCTI_ASYNC --enable-unit --enable-integration --with-crypto=$WITH_CRYPTO $CONFIGURE_OPTIONS
 elif [ "$CC" == "clang" ]; then
-  ../configure --enable-tcti-partial-reads=$WITH_TCTI_PARTIAL --enable-tcti-device-async=$WITH_TCTI_ASYNC --enable-unit --enable-integration --with-crypto=$WITH_CRYPTO
+  ../configure --enable-tcti-partial-reads=$WITH_TCTI_PARTIAL --enable-tcti-device-async=$WITH_TCTI_ASYNC --enable-unit --enable-integration --with-crypto=$WITH_CRYPTO $CONFIGURE_OPTIONS
 else
   ../configure --with-sanitizer=undefined --enable-tcti-partial-reads=$WITH_TCTI_PARTIAL --enable-tcti-device-async=$WITH_TCTI_ASYNC --enable-unit --enable-integration --with-crypto=$WITH_CRYPTO $CONFIGURE_OPTIONS
 fi
diff --git a/.ci/download-deps.sh b/.ci/download-deps.sh
index 5094376..93283f2 100755
--- a/.ci/download-deps.sh
+++ b/.ci/download-deps.sh
@@ -3,5 +3,5 @@
 
 function get_deps() {
 
-    echo "no deps"
+	echo "no deps"
 }
diff --git a/Dockerfile b/Dockerfile
index 19301fb..61e07b9 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -4,6 +4,11 @@
 WORKDIR /tmp/tpm2-tss
 ENV LD_LIBRARY_PATH /usr/local/lib
 
+# Install libjson-c
+RUN apt-get update && apt-get install -y --no-install-recommends \
+       libjson-c-dev \
+       && rm -rf /var/lib/apt/lists/*
+
 # Fuzzing
 FROM base AS fuzzing
 ENV GEN_FUZZ 1
diff --git a/Doxyfile.in b/Doxyfile.in
index b626871..254ee71 100644
--- a/Doxyfile.in
+++ b/Doxyfile.in
@@ -782,6 +782,8 @@
                          @top_srcdir@/README.md \
                          @top_srcdir@/include/tss2/tss2_esys.h \
                          @top_srcdir@/src/tss2-esys \
+                         @top_srcdir@/include/tss2/tss2_fapi.h \
+                         @top_srcdir@/src/tss2-fapi \
                          @top_srcdir@/test/integration/esys-audit.int.c \
                          @top_srcdir@/test/integration/esys-certify-creation.int.c \
                          @top_srcdir@/test/integration/esys-certify.int.c \
@@ -847,7 +849,35 @@
                          @top_srcdir@/test/integration/esys-tr-getName-hierarchy.int.c \
                          @top_srcdir@/test/integration/esys-unseal-password-auth.int.c \
                          @top_srcdir@/test/integration/esys-verify-signature.int.c \
-                         @top_srcdir@/test/integration/esys-zgen-2phase.int.c
+                         @top_srcdir@/test/integration/esys-zgen-2phase.int.c \
+                         @top_srcdir@/test/integration/fapi-data-crypt-rsa.int.c \
+                         @top_srcdir@/test/integration/fapi-key-change-auth.int.c \
+                         @top_srcdir@/test/integration/fapi-key-create-policy-authorize-sign.int.c \
+                         @top_srcdir@/test/integration/fapi-key-create-policy-secret-nv-sign.int.c \
+                         @top_srcdir@/test/integration/fapi-key-create-sign-policy-provision.int.c \
+                         @top_srcdir@/test/integration/fapi-nv-set-bits.int.c \
+                         @top_srcdir@/test/integration/fapi-quote.int.c \
+                         @top_srcdir@/test/integration/fapi-ext-public-key.int.c \
+                         @top_srcdir@/test/integration/fapi-key-create-ecc-sign.int.c \
+                         @top_srcdir@/test/integration/fapi-key-create-policy-nv-sign.int.c \
+                         @top_srcdir@/test/integration/fapi-key-create-policy-signed.int.c \
+                         @top_srcdir@/test/integration/fapi-nv-extend.int.c \
+                         @top_srcdir@/test/integration/fapi-nv-written-policy.int.c \
+                         @top_srcdir@/test/integration/fapi-rsa-duplicate.int.c \
+                         @top_srcdir@/test/integration/fapi-get-random.int.c \
+                         @top_srcdir@/test/integration/fapi-key-create-policies-sign.int.c \
+                         @top_srcdir@/test/integration/fapi-key-create-policy-or-sign.int.c \
+                         @top_srcdir@/test/integration/fapi-key-create-sign.int.c \
+                         @top_srcdir@/test/integration/fapi-nv-increment.int.c \
+                         @top_srcdir@/test/integration/fapi-pcr-test.int.c \
+                         @top_srcdir@/test/integration/fapi-unseal.int.c \
+                         @top_srcdir@/test/integration/fapi-info.int.c \
+                         @top_srcdir@/test/integration/fapi-key-create-policy-authorize-nv-sign.int.c \
+                         @top_srcdir@/test/integration/fapi-key-create-policy-pcr-sign.int.c \
+                         @top_srcdir@/test/integration/fapi-key-create-sign-password-provision.int.c \
+                         @top_srcdir@/test/integration/fapi-nv-ordinary.int.c \
+                         @top_srcdir@/test/integration/fapi-platform-certificates.int.c
+
 # This tag can be used to specify the character encoding of the source files
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
 # libiconv (or the iconv built into libc) for the transcoding. See the libiconv
diff --git a/INSTALL.md b/INSTALL.md
index dc2b93a..d6aacb6 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -48,7 +48,8 @@
   uthash-dev \
   autoconf \
   doxygen \
-  libltdl-dev
+  libjson-c-dev \
+  libini-config-dev
 ```
 Note: In some Ubuntu versions, the lcov and autoconf-archive packages are incompatible with each other. It is recommended to download autoconf-archive directly from upstream and copy `ax_code_coverage.m4` and `ax_prog_doxygen.m4` to the `m4/` subdirectory of your tpm2-tss directory.
 
diff --git a/Makefile-test.am b/Makefile-test.am
index 531e045..6ad6390 100644
--- a/Makefile-test.am
+++ b/Makefile-test.am
@@ -4,7 +4,7 @@
 # All rights reserved.
 
 TESTS_CFLAGS = $(AM_CFLAGS) $(LIBCRYPTO_CFLAGS) -I$(srcdir)/src/tss2-mu \
-    -I$(srcdir)/src/tss2-sys -I$(srcdir)/src/tss2-esys \
+    -I$(srcdir)/src/tss2-sys -I$(srcdir)/src/tss2-esys  -I$(srcdir)/src/tss2-fapi \
     -Wno-unused-parameter -Wno-missing-field-initializers
 TESTS_LDADD = $(check_LTLIBRARIES) $(lib_LTLIBRARIES) \
     $(LIBCRYPTO_LIBS) $(libutil)
@@ -18,7 +18,9 @@
 else
 INT_LOG_COMPILER = $(srcdir)/script/int-log-compiler.sh
 endif
-EXTRA_DIST += $(srcdir)/script/int-log-compiler.sh $(srcdir)/script/int-log-compiler-ptpm.sh
+EXTRA_DIST += $(srcdir)/script/int-log-compiler.sh $(srcdir)/script/int-log-compiler-ptpm.sh \
+              $(srcdir)/script/ekca/create_ca.sh  $(srcdir)/script/ekca/ek.cnf \
+              $(srcdir)/script/ekca/intermed-ca.cnf $(srcdir)/script/ekca/root-ca.cnf
 AM_TESTS_ENVIRONMENT = PATH="$(PATH)"
 
 check-programs: $(check_PROGRAMS)
@@ -41,6 +43,22 @@
 test_helper_tpm_dumpstate_CFLAGS = $(TESTS_CFLAGS) -I$(srcdir)/test/integration
 test_helper_tpm_dumpstate_LDFLAGS = $(TESTS_LDFLAGS)
 test_helper_tpm_dumpstate_LDADD = $(TESTS_LDADD)
+
+check_PROGRAMS += test/helper/tpm_getek
+test_helper_tpm_getek_CFLAGS = $(TESTS_CFLAGS) -I$(srcdir)/test/integration
+test_helper_tpm_getek_LDFLAGS = $(TESTS_LDFLAGS) -lcrypto
+test_helper_tpm_getek_LDADD = $(TESTS_LDADD)
+
+check_PROGRAMS += test/helper/tpm_getek_ecc
+test_helper_tpm_getek_ecc_CFLAGS = $(TESTS_CFLAGS) -I$(srcdir)/test/integration
+test_helper_tpm_getek_ecc_LDFLAGS = $(TESTS_LDFLAGS) -lcrypto
+test_helper_tpm_getek_ecc_LDADD = $(TESTS_LDADD)
+
+
+check_PROGRAMS += test/helper/tpm_writeekcert
+test_helper_tpm_writeekcert_CFLAGS = $(TESTS_CFLAGS) -I$(srcdir)/test/integration
+test_helper_tpm_writeekcert_LDFLAGS = $(TESTS_LDFLAGS)
+test_helper_tpm_writeekcert_LDADD = $(TESTS_LDADD)
 endif #ENABLE_INTEGRATION
 
 if UNIT
@@ -81,6 +99,11 @@
     test/unit/esys-crypto
 
 endif ESAPI
+if FAPI
+fapiLDFLAGS = -ljson-c
+TESTS_UNIT += \
+    test/unit/fapi-json
+endif FAPI
 endif #UNIT
 
 if ENABLE_INTEGRATION
@@ -224,16 +247,74 @@
 
 else # TESTPTPM
 TESTS_INTEGRATION += $(ESYS_TESTS_INTEGRATION_MANDATORY) $(ESYS_TESTS_INTEGRATION_OPTIONAL) $(ESYS_TESTS_INTEGRATION_DESTRUCTIVE)
+
 endif # TESTPTPM
 
 endif #ESAPI
+
+if FAPI
+TESTS_CFLAGS +=  -DTOP_SOURCEDIR"=\"$(top_srcdir)\""
+FAPI_TESTS_INTEGRATION = \
+    test/integration/fapi-data-crypt-rsa.int \
+    test/integration/fapi-rsa-duplicate.int \
+    test/integration/fapi-ext-public-key.int \
+    test/integration/fapi-get-random.int \
+    test/integration/fapi-platform-certificates.int \
+    test/integration/fapi-key-create-sign.int \
+    test/integration/fapi-key-create-sign-password-provision.int \
+    test/integration/fapi-key-create-sign-ecc.int \
+    test/integration/fapi-key-create-policy-authorize-sign.int \
+    test/integration/fapi-key-create-policy-authorize-nv-sign.int \
+    test/integration/fapi-key-create-policy-secret-nv-sign.int \
+    test/integration/fapi-key-create-policy-pcr-sign.int \
+    test/integration/fapi-key-create-policy-signed.int \
+    test/integration/fapi-key-create-policy-nv-sign.int \
+    test/integration/fapi-key-create-policy-or-sign.int \
+    test/integration/fapi-key-create-policy-password-sign.int \
+    test/integration/fapi-key-create-policy-countertimer-sign.int \
+    test/integration/fapi-key-create-policy-physical-presence-sign.int \
+    test/integration/fapi-key-create-policy-locality-sign.int \
+    test/integration/fapi-key-create-policy-command-code-sign.int \
+    test/integration/fapi-key-create-policy-auth-value-sign.int \
+    test/integration/fapi-key-create-ecc-sign.int \
+    test/integration/fapi-key-change-auth.int \
+    test/integration/fapi-key-create-sign-persistent.int \
+    test/integration/fapi-key-create-sign-password.int \
+    test/integration/fapi-key-create-ecc-sign-password.int \
+    test/integration/fapi-key-create-sign-password-da.int \
+    test/integration/fapi-key-create-ecc-sign-password-da.int \
+    test/integration/fapi-nv-authorizenv-cphash.int \
+    test/integration/fapi-nv-ordinary.int \
+    test/integration/fapi-nv-written-policy.int \
+    test/integration/fapi-nv-extend.int \
+    test/integration/fapi-nv-increment.int \
+    test/integration/fapi-nv-set-bits.int \
+    test/integration/fapi-pcr-test.int \
+    test/integration/fapi-quote.int \
+    test/integration/fapi-info.int \
+    test/integration/fapi-unseal.int
+
+if TESTPTPM
+if PTPMDESTRUCTIVE
+FAPI_TESTS_INTEGRATION += test/integration/fapi-key-create-sign-policy-provision.int
+endif
+endif #TESTPTM
+
+TESTS_INTEGRATION += $(FAPI_TESTS_INTEGRATION)
+
+endif #FAPI
+
 endif #ENABLE_INTEGRATION
 
 CLEANFILES += \
     test/integration/*.int_state* \
     test/integration/*.log \
+    test/integration/*.int_ek* \
+    test/integration/*.int_*-ca.pem \
     test/tpmclient/*.int_state* \
     test/tpmclient/*.log \
+    test/tpmclient/*.int_ek* \
+    test/tpmclient/*.int_*-ca.pem \
     test/unit/*.log
 
 if UNIT
@@ -392,7 +473,7 @@
 test_unit_esys_nulltcti_CFLAGS = $(CMOCKA_CFLAGS) $(TESTS_CFLAGS) $(TSS2_ESYS_CFLAGS_CRYPTO)
 test_unit_esys_nulltcti_LDADD = $(CMOCKA_LIBS)  $(TESTS_LDADD) $(LIBADD_DL)
 test_unit_esys_nulltcti_LDFLAGS = $(TESTS_LDFLAGS) $(TSS2_ESYS_LDFLAGS_CRYPTO) \
-    $(LIBDL_LDFLAGS) -Wl,--wrap=Tss2_TctiLdr_Initialize
+    $(LIBDL_LDFLAGS) -Wl,--wrap=Tss2_TctiLdr_Initialize -Wl,--wrap=Tss2_TctiLdr_Finalize
 test_unit_esys_nulltcti_SOURCES = test/unit/esys-nulltcti.c \
                                   src/tss2-esys/esys_context.c \
                                   src/tss2-esys/esys_iutil.c \
@@ -410,6 +491,21 @@
                                 src/tss2-esys/esys_crypto.c \
                                 $(TSS2_ESYS_SRC_CRYPTO)
 endif # ESAPI
+
+if FAPI
+
+test_unit_fapi_json_CFLAGS = $(CMOCKA_CFLAGS) $(TESTS_CFLAGS)
+test_unit_fapi_json_LDADD = $(CMOCKA_LIBS)  $(TESTS_LDADD)
+test_unit_fapi_json_LDFLAGS = $(TESTS_LDFLAGS) -ljson-c
+test_unit_fapi_json_SOURCES = test/unit/fapi-json.c \
+                              src/tss2-fapi/ifapi_json_deserialize.c \
+                              src/tss2-fapi/ifapi_json_serialize.c \
+                              src/tss2-fapi/ifapi_policy_json_deserialize.c \
+                              src/tss2-fapi/ifapi_policy_json_serialize.c \
+                              src/tss2-fapi/tpm_json_deserialize.c \
+                              src/tss2-fapi/tpm_json_serialize.c
+
+endif # FAPI
 endif # UNIT
 
 if ENABLE_INTEGRATION
@@ -1203,6 +1299,303 @@
 test_integration_sapi_command_cancel_int_LDADD   = $(TESTS_LDADD)
 test_integration_sapi_command_cancel_int_SOURCES = test/integration/main-sapi.c \
     test/integration/sapi-command-cancel.int.c src/util/log.c
+
+if FAPI
+test_integration_fapi_get_random_int_CFLAGS  = $(TESTS_CFLAGS)
+test_integration_fapi_get_random_int_LDADD   = $(TESTS_LDADD)
+test_integration_fapi_get_random_int_LDFLAGS = $(TESTS_LDFLAGS)
+test_integration_fapi_get_random_int_SOURCES = \
+    test/integration/fapi-get-random.int.c \
+    test/integration/main-fapi.c test/integration/test-fapi.h
+
+test_integration_fapi_platform_certificates_int_CFLAGS  = $(TESTS_CFLAGS)
+test_integration_fapi_platform_certificates_int_LDADD   = $(TESTS_LDADD)
+test_integration_fapi_platform_certificates_int_LDFLAGS = $(TESTS_LDFLAGS)
+test_integration_fapi_platform_certificates_int_SOURCES = \
+    test/integration/fapi-platform-certificates.int.c \
+    test/integration/main-fapi.c test/integration/test-fapi.h
+
+test_integration_fapi_key_create_sign_int_CFLAGS  = $(TESTS_CFLAGS)
+test_integration_fapi_key_create_sign_int_LDADD   = $(TESTS_LDADD)
+test_integration_fapi_key_create_sign_int_LDFLAGS = $(TESTS_LDFLAGS)
+test_integration_fapi_key_create_sign_int_SOURCES = \
+    test/integration/fapi-key-create-sign.int.c \
+    test/integration/main-fapi.c test/integration/test-fapi.h
+
+test_integration_fapi_key_create_sign_password_provision_int_CFLAGS  = $(TESTS_CFLAGS)
+test_integration_fapi_key_create_sign_password_provision_int_LDADD   = $(TESTS_LDADD)
+test_integration_fapi_key_create_sign_password_provision_int_LDFLAGS = $(TESTS_LDFLAGS)
+test_integration_fapi_key_create_sign_password_provision_int_SOURCES = \
+    test/integration/fapi-key-create-sign-password-provision.int.c \
+    test/integration/main-fapi.c test/integration/test-fapi.h
+
+test_integration_fapi_key_create_sign_policy_provision_int_CFLAGS  = $(TESTS_CFLAGS) \
+ -DFAPI_PROFILE=\"P_RSA_sh_policy\"
+test_integration_fapi_key_create_sign_policy_provision_int_LDADD   = $(TESTS_LDADD)
+test_integration_fapi_key_create_sign_policy_provision_int_LDFLAGS = $(TESTS_LDFLAGS)
+test_integration_fapi_key_create_sign_policy_provision_int_SOURCES = \
+    test/integration/fapi-key-create-sign-policy-provision.int.c \
+    test/integration/main-fapi.c test/integration/test-fapi.h
+
+test_integration_fapi_key_create_sign_ecc_int_CFLAGS  = $(TESTS_CFLAGS) \
+ -DFAPI_PROFILE=\"P_ECC\"
+test_integration_fapi_key_create_sign_ecc_int_LDADD   = $(TESTS_LDADD)
+test_integration_fapi_key_create_sign_ecc_int_LDFLAGS = $(TESTS_LDFLAGS)
+test_integration_fapi_key_create_sign_ecc_int_SOURCES = \
+    test/integration/fapi-key-create-sign.int.c \
+    test/integration/main-fapi.c test/integration/test-fapi.h
+
+test_integration_fapi_key_create_sign_password_int_CFLAGS  = $(TESTS_CFLAGS) \
+ -DFAPI_PASSWORD
+test_integration_fapi_key_create_sign_password_int_LDADD   = $(TESTS_LDADD)
+test_integration_fapi_key_create_sign_password_int_LDFLAGS = $(TESTS_LDFLAGS)
+test_integration_fapi_key_create_sign_password_int_SOURCES = \
+    test/integration/fapi-key-create-sign.int.c \
+    test/integration/main-fapi.c test/integration/test-fapi.h
+
+test_integration_fapi_key_create_sign_password_da_int_CFLAGS  = $(TESTS_CFLAGS) \
+ -DFAPI_PASSWORD -DFAPI_DA
+test_integration_fapi_key_create_sign_password_da_int_LDADD   = $(TESTS_LDADD)
+test_integration_fapi_key_create_sign_password_da_int_LDFLAGS = $(TESTS_LDFLAGS)
+test_integration_fapi_key_create_sign_password_da_int_SOURCES = \
+    test/integration/fapi-key-create-sign.int.c \
+    test/integration/main-fapi.c test/integration/test-fapi.h
+
+test_integration_fapi_key_create_sign_persistent_int_CFLAGS  = $(TESTS_CFLAGS) \
+   -DFAPI_PROFILE=\"P_RSA_EK_persistent\"
+test_integration_fapi_key_create_sign_persistent_int_LDADD   = $(TESTS_LDADD)
+test_integration_fapi_key_create_sign_persistent_int_LDFLAGS = $(TESTS_LDFLAGS)
+test_integration_fapi_key_create_sign_persistent_int_SOURCES = \
+    test/integration/fapi-key-create-sign.int.c \
+    test/integration/main-fapi.c test/integration/test-fapi.h
+
+test_integration_fapi_key_create_policy_authorize_sign_int_CFLAGS  = $(TESTS_CFLAGS) \
+    -DFAPI_PROFILE=\"P_RSA256\"
+test_integration_fapi_key_create_policy_authorize_sign_int_LDADD   = $(TESTS_LDADD)
+test_integration_fapi_key_create_policy_authorize_sign_int_LDFLAGS = $(TESTS_LDFLAGS)
+test_integration_fapi_key_create_policy_authorize_sign_int_SOURCES = \
+    test/integration/fapi-key-create-policy-authorize-sign.int.c \
+    test/integration/main-fapi.c test/integration/test-fapi.h
+
+test_integration_fapi_key_create_policy_authorize_nv_sign_int_CFLAGS  = $(TESTS_CFLAGS)
+test_integration_fapi_key_create_policy_authorize_nv_sign_int_LDADD   = $(TESTS_LDADD)
+test_integration_fapi_key_create_policy_authorize_nv_sign_int_LDFLAGS = $(TESTS_LDFLAGS)
+test_integration_fapi_key_create_policy_authorize_nv_sign_int_SOURCES = \
+    test/integration/fapi-key-create-policy-authorize-nv-sign.int.c \
+    test/integration/main-fapi.c test/integration/test-fapi.h
+
+test_integration_fapi_key_create_policy_secret_nv_sign_int_CFLAGS  = $(TESTS_CFLAGS) \
+    -DFAPI_PROFILE=\"P_RSA256\"
+test_integration_fapi_key_create_policy_secret_nv_sign_int_LDADD   = $(TESTS_LDADD)
+test_integration_fapi_key_create_policy_secret_nv_sign_int_LDFLAGS = $(TESTS_LDFLAGS)
+test_integration_fapi_key_create_policy_secret_nv_sign_int_SOURCES = \
+    test/integration/fapi-key-create-policy-secret-nv-sign.int.c \
+    test/integration/main-fapi.c test/integration/test-fapi.h
+
+test_integration_fapi_key_create_policy_pcr_sign_int_CFLAGS  = $(TESTS_CFLAGS)
+test_integration_fapi_key_create_policy_pcr_sign_int_LDADD   = $(TESTS_LDADD)
+test_integration_fapi_key_create_policy_pcr_sign_int_LDFLAGS = $(TESTS_LDFLAGS)
+test_integration_fapi_key_create_policy_pcr_sign_int_SOURCES = \
+    test/integration/fapi-key-create-policy-pcr-sign.int.c \
+    test/integration/main-fapi.c test/integration/test-fapi.h
+
+test_integration_fapi_key_create_policy_signed_int_CFLAGS  = $(TESTS_CFLAGS)
+test_integration_fapi_key_create_policy_signed_int_LDADD   = $(TESTS_LDADD)
+test_integration_fapi_key_create_policy_signed_int_LDFLAGS = $(TESTS_LDFLAGS)
+test_integration_fapi_key_create_policy_signed_int_SOURCES = \
+    test/integration/fapi-key-create-policy-signed.int.c \
+    test/integration/main-fapi.c test/integration/test-fapi.h
+
+
+test_integration_fapi_key_create_policy_nv_sign_int_CFLAGS  = $(TESTS_CFLAGS)
+test_integration_fapi_key_create_policy_nv_sign_int_LDADD   = $(TESTS_LDADD)
+test_integration_fapi_key_create_policy_nv_sign_int_LDFLAGS = $(TESTS_LDFLAGS)
+test_integration_fapi_key_create_policy_nv_sign_int_SOURCES = \
+    test/integration/fapi-key-create-policy-nv-sign.int.c \
+    test/integration/main-fapi.c test/integration/test-fapi.h
+
+test_integration_fapi_key_create_policy_or_sign_int_CFLAGS  = $(TESTS_CFLAGS)
+test_integration_fapi_key_create_policy_or_sign_int_LDADD   = $(TESTS_LDADD)
+test_integration_fapi_key_create_policy_or_sign_int_LDFLAGS = $(TESTS_LDFLAGS)
+test_integration_fapi_key_create_policy_or_sign_int_SOURCES = \
+    test/integration/fapi-key-create-policy-or-sign.int.c \
+    test/integration/main-fapi.c test/integration/test-fapi.h
+
+test_integration_fapi_key_create_policy_password_sign_int_CFLAGS  = $(TESTS_CFLAGS) \
+    -DTEST_POLICY_PASSWORD -DTEST_PASSWORD
+test_integration_fapi_key_create_policy_password_sign_int_LDADD   = $(TESTS_LDADD)
+test_integration_fapi_key_create_policy_password_sign_int_LDFLAGS = $(TESTS_LDFLAGS)
+test_integration_fapi_key_create_policy_password_sign_int_SOURCES = \
+    test/integration/fapi-key-create-policies-sign.int.c \
+    test/integration/main-fapi.c test/integration/test-fapi.h
+
+test_integration_fapi_key_create_policy_countertimer_sign_int_CFLAGS  = $(TESTS_CFLAGS) \
+    -DTEST_POLICY_COUNTERTIMER
+test_integration_fapi_key_create_policy_countertimer_sign_int_LDADD   = $(TESTS_LDADD)
+test_integration_fapi_key_create_policy_countertimer_sign_int_LDFLAGS = $(TESTS_LDFLAGS)
+test_integration_fapi_key_create_policy_countertimer_sign_int_SOURCES = \
+    test/integration/fapi-key-create-policies-sign.int.c \
+    test/integration/main-fapi.c test/integration/test-fapi.h
+
+test_integration_fapi_key_create_policy_physical_presence_sign_int_CFLAGS  = $(TESTS_CFLAGS) \
+    -DTEST_POLICY_PHYSICAL_PRESENCE
+test_integration_fapi_key_create_policy_physical_presence_sign_int_LDADD   = $(TESTS_LDADD)
+test_integration_fapi_key_create_policy_physical_presence_sign_int_LDFLAGS = $(TESTS_LDFLAGS)
+test_integration_fapi_key_create_policy_physical_presence_sign_int_SOURCES = \
+    test/integration/fapi-key-create-policies-sign.int.c \
+    test/integration/main-fapi.c test/integration/test-fapi.h
+
+test_integration_fapi_key_create_policy_locality_sign_int_CFLAGS  = $(TESTS_CFLAGS) \
+    -DTEST_POLICY_LOCALITY
+test_integration_fapi_key_create_policy_locality_sign_int_LDADD   = $(TESTS_LDADD)
+test_integration_fapi_key_create_policy_locality_sign_int_LDFLAGS = $(TESTS_LDFLAGS)
+test_integration_fapi_key_create_policy_locality_sign_int_SOURCES = \
+    test/integration/fapi-key-create-policies-sign.int.c \
+    test/integration/main-fapi.c test/integration/test-fapi.h
+
+test_integration_fapi_key_create_policy_command_code_sign_int_CFLAGS  = $(TESTS_CFLAGS) \
+    -DTEST_POLICY_COMMAND_CODE
+test_integration_fapi_key_create_policy_command_code_sign_int_LDADD   = $(TESTS_LDADD)
+test_integration_fapi_key_create_policy_command_code_sign_int_LDFLAGS = $(TESTS_LDFLAGS)
+test_integration_fapi_key_create_policy_command_code_sign_int_SOURCES = \
+    test/integration/fapi-key-create-policies-sign.int.c \
+    test/integration/main-fapi.c test/integration/test-fapi.h
+
+test_integration_fapi_key_create_policy_auth_value_sign_int_CFLAGS  = $(TESTS_CFLAGS) \
+ -DTEST_POLICY_AUTH_VALUE -DTEST_PASSWORD
+test_integration_fapi_key_create_policy_auth_value_sign_int_LDADD   = $(TESTS_LDADD)
+test_integration_fapi_key_create_policy_auth_value_sign_int_LDFLAGS = $(TESTS_LDFLAGS)
+test_integration_fapi_key_create_policy_auth_value_sign_int_SOURCES = \
+    test/integration/fapi-key-create-policies-sign.int.c \
+    test/integration/main-fapi.c test/integration/test-fapi.h
+
+test_integration_fapi_key_create_ecc_sign_int_CFLAGS  = $(TESTS_CFLAGS) \
+ -DFAPI_PROFILE=\"P_ECC\"
+test_integration_fapi_key_create_ecc_sign_int_LDADD   = $(TESTS_LDADD)
+test_integration_fapi_key_create_ecc_sign_int_LDFLAGS = $(TESTS_LDFLAGS)
+test_integration_fapi_key_create_ecc_sign_int_SOURCES = \
+    test/integration/fapi-key-create-ecc-sign.int.c \
+    test/integration/main-fapi.c test/integration/test-fapi.h
+
+test_integration_fapi_key_create_ecc_sign_password_int_CFLAGS  = $(TESTS_CFLAGS) \
+ -DFAPI_PASSWORD  -DFAPI_PROFILE=\"P_ECC\"
+test_integration_fapi_key_create_ecc_sign_password_int_LDADD   = $(TESTS_LDADD)
+test_integration_fapi_key_create_ecc_sign_password_int_LDFLAGS = $(TESTS_LDFLAGS)
+test_integration_fapi_key_create_ecc_sign_password_int_SOURCES = \
+    test/integration/fapi-key-create-ecc-sign.int.c \
+    test/integration/main-fapi.c test/integration/test-fapi.h
+
+test_integration_fapi_key_create_ecc_sign_password_da_int_CFLAGS  = $(TESTS_CFLAGS) \
+ -DFAPI_PASSWORD -DFAPI_DA  -DFAPI_PROFILE=\"P_ECC\"
+test_integration_fapi_key_create_ecc_sign_password_da_int_LDADD   = $(TESTS_LDADD)
+test_integration_fapi_key_create_ecc_sign_password_da_int_LDFLAGS = $(TESTS_LDFLAGS)
+test_integration_fapi_key_create_ecc_sign_password_da_int_SOURCES = \
+    test/integration/fapi-key-create-ecc-sign.int.c \
+    test/integration/main-fapi.c test/integration/test-fapi.h
+
+test_integration_fapi_key_change_auth_int_CFLAGS  = $(TESTS_CFLAGS)
+test_integration_fapi_key_change_auth_int_LDADD   = $(TESTS_LDADD)
+test_integration_fapi_key_change_auth_int_LDFLAGS = $(TESTS_LDFLAGS)
+test_integration_fapi_key_change_auth_int_SOURCES = \
+    test/integration/fapi-key-change-auth.int.c \
+    test/integration/main-fapi.c test/integration/test-fapi.h
+
+test_integration_fapi_nv_ordinary_int_CFLAGS  = $(TESTS_CFLAGS)
+test_integration_fapi_nv_ordinary_int_LDADD   = $(TESTS_LDADD)
+test_integration_fapi_nv_ordinary_int_LDFLAGS = $(TESTS_LDFLAGS)
+test_integration_fapi_nv_ordinary_int_SOURCES = \
+    test/integration/fapi-nv-ordinary.int.c \
+    test/integration/main-fapi.c test/integration/test-fapi.h
+
+test_integration_fapi_nv_authorizenv_cphash_int_CFLAGS  = $(TESTS_CFLAGS)
+test_integration_fapi_nv_authorizenv_cphash_int_LDADD   = $(TESTS_LDADD)
+test_integration_fapi_nv_authorizenv_cphash_int_LDFLAGS = $(TESTS_LDFLAGS)
+test_integration_fapi_nv_authorizenv_cphash_int_SOURCES = \
+    test/integration/fapi-nv-authorizenv-cphash.int.c \
+    test/integration/main-fapi.c test/integration/test-fapi.h
+
+test_integration_fapi_nv_extend_int_CFLAGS  = $(TESTS_CFLAGS)
+test_integration_fapi_nv_extend_int_LDADD   = $(TESTS_LDADD)
+test_integration_fapi_nv_extend_int_LDFLAGS = $(TESTS_LDFLAGS)
+test_integration_fapi_nv_extend_int_SOURCES = \
+    test/integration/fapi-nv-extend.int.c \
+    test/integration/main-fapi.c test/integration/test-fapi.h
+
+test_integration_fapi_nv_increment_int_CFLAGS  = $(TESTS_CFLAGS)
+test_integration_fapi_nv_increment_int_LDADD   = $(TESTS_LDADD)
+test_integration_fapi_nv_increment_int_LDFLAGS = $(TESTS_LDFLAGS)
+test_integration_fapi_nv_increment_int_SOURCES = \
+    test/integration/fapi-nv-increment.int.c \
+    test/integration/main-fapi.c test/integration/test-fapi.h
+
+test_integration_fapi_nv_set_bits_int_CFLAGS  = $(TESTS_CFLAGS)
+test_integration_fapi_nv_set_bits_int_LDADD   = $(TESTS_LDADD)
+test_integration_fapi_nv_set_bits_int_LDFLAGS = $(TESTS_LDFLAGS)
+test_integration_fapi_nv_set_bits_int_SOURCES = \
+    test/integration/fapi-nv-set-bits.int.c \
+    test/integration/main-fapi.c test/integration/test-fapi.h
+
+test_integration_fapi_nv_written_policy_int_CFLAGS  = $(TESTS_CFLAGS)
+test_integration_fapi_nv_written_policy_int_LDADD   = $(TESTS_LDADD)
+test_integration_fapi_nv_written_policy_int_LDFLAGS = $(TESTS_LDFLAGS)
+test_integration_fapi_nv_written_policy_int_SOURCES = \
+    test/integration/fapi-nv-written-policy.int.c \
+    test/integration/main-fapi.c test/integration/test-fapi.h
+
+test_integration_fapi_ext_public_key_int_CFLAGS  = $(TESTS_CFLAGS) \
+  -DFAPI_NONTPM
+test_integration_fapi_ext_public_key_int_LDADD   = $(TESTS_LDADD)
+test_integration_fapi_ext_public_key_int_LDFLAGS = $(TESTS_LDFLAGS)
+test_integration_fapi_ext_public_key_int_SOURCES = \
+    test/integration/fapi-ext-public-key.int.c \
+    test/integration/main-fapi.c test/integration/test-fapi.h
+
+test_integration_fapi_data_crypt_rsa_int_CFLAGS  = $(TESTS_CFLAGS)
+test_integration_fapi_data_crypt_rsa_int_LDADD   = $(TESTS_LDADD)
+test_integration_fapi_data_crypt_rsa_int_LDFLAGS = $(TESTS_LDFLAGS)
+test_integration_fapi_data_crypt_rsa_int_SOURCES = \
+    test/integration/fapi-data-crypt-rsa.int.c \
+    test/integration/main-fapi.c test/integration/test-fapi.h
+
+test_integration_fapi_rsa_duplicate_int_CFLAGS  = $(TESTS_CFLAGS)
+test_integration_fapi_rsa_duplicate_int_LDADD   = $(TESTS_LDADD)
+test_integration_fapi_rsa_duplicate_int_LDFLAGS = $(TESTS_LDFLAGS)
+test_integration_fapi_rsa_duplicate_int_SOURCES = \
+    test/integration/fapi-rsa-duplicate.int.c \
+    test/integration/main-fapi.c test/integration/test-fapi.h
+
+
+test_integration_fapi_pcr_test_int_CFLAGS  = $(TESTS_CFLAGS)
+test_integration_fapi_pcr_test_int_LDADD   = $(TESTS_LDADD)
+test_integration_fapi_pcr_test_int_LDFLAGS = $(TESTS_LDFLAGS)
+test_integration_fapi_pcr_test_int_SOURCES = \
+    test/integration/fapi-pcr-test.int.c \
+    test/integration/main-fapi.c test/integration/test-fapi.h
+
+test_integration_fapi_quote_int_CFLAGS  = $(TESTS_CFLAGS)
+test_integration_fapi_quote_int_LDADD   = $(TESTS_LDADD)
+test_integration_fapi_quote_int_LDFLAGS = $(TESTS_LDFLAGS) -ljson-c
+test_integration_fapi_quote_int_SOURCES = \
+    test/integration/fapi-quote.int.c \
+    test/integration/main-fapi.c test/integration/test-fapi.h
+
+test_integration_fapi_info_int_CFLAGS  = $(TESTS_CFLAGS)
+test_integration_fapi_info_int_LDADD   = $(TESTS_LDADD)
+test_integration_fapi_info_int_LDFLAGS = $(TESTS_LDFLAGS)
+test_integration_fapi_info_int_SOURCES = \
+    test/integration/fapi-info.int.c \
+    test/integration/main-fapi.c test/integration/test-fapi.h
+
+test_integration_fapi_unseal_int_CFLAGS  = $(TESTS_CFLAGS)
+test_integration_fapi_unseal_int_LDADD   = $(TESTS_LDADD)
+test_integration_fapi_unseal_int_LDFLAGS = $(TESTS_LDFLAGS)
+test_integration_fapi_unseal_int_SOURCES = \
+    test/integration/fapi-unseal.int.c \
+    test/integration/main-fapi.c test/integration/test-fapi.h
+
+
+endif #FAPI
+
 endif #ENABLE_INTEGRATION
 
 check-ptpm:
diff --git a/Makefile.am b/Makefile.am
index 9867e22..8115be5 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -382,6 +382,151 @@
 endif # HAVE_LD_VERSION_SCRIPT
 src_tss2_rc_libtss2_rc_la_SOURCES = $(TSS2_RC_SRC)
 
+
+### TCG TSS FAPI spec library ###
+if FAPI
+fapiconfdir = @sysconfdir@/tpm2-tss
+fapiconf_DATA = fapi-config.json
+
+EXTRA_DIST += dist/fapi-config.json.in
+CLEANFILES += fapi-config.json
+
+# We have to do this ourselves, in order to get absolute paths
+fapi-config.json: dist/fapi-config.json.in
+	$(AM_V_GEN) $(SED) \
+		-e 's|[@]prefix@|$(prefix)|g' \
+		-e 's|[@]datarootdir@|$(datarootdir)|g' \
+		-e 's|[@]datadir@|$(datadir)|g' \
+		-e 's|[@]sysconfdir@|$(sysconfdir)|g' \
+		-e 's|[@]sharedstatedir@|$(sharedstatedir)|g' \
+		-e 's|[@]localstatedir@|$(localstatedir)|g' \
+		-e 's|[@]runstatedir@|$(runstatedir)|g' \
+		-e 's|[@]userstatedir@|$(userstatedir)|g' \
+		< "$<" > "$@"
+
+tmpfilesddir = @tmpfilesdir@
+tmpfilesd_DATA = fapi-tmpfiles.conf
+
+EXTRA_DIST += dist/fapi-tmpfiles.conf.in
+CLEANFILES += fapi-tmpfiles.conf
+
+# We have to do this ourselves, in order to get absolute paths
+fapi-tmpfiles.conf: dist/fapi-tmpfiles.conf.in
+	$(AM_V_GEN) $(SED) \
+		-e 's|[@]runstatedir@|$(runstatedir)|g' \
+		< "$<" > "$@"
+
+EXTRA_DIST += dist/fapi-profiles/P_RSA2048SHA256.json \
+              dist/fapi-profiles/P_ECCP256SHA256.json
+
+fapiprofilesdir = @sysconfdir@/tpm2-tss/fapi-profiles
+fapiprofiles_DATA = dist/fapi-profiles/P_RSA2048SHA256.json \
+                    dist/fapi-profiles/P_ECCP256SHA256.json
+
+EXTRA_DIST += dist/keep
+
+fapikeystoredir = @localstatedir@/tpm2-tss/system/keystore
+fapikeystore_DATA = dist/keep
+
+fapieventlogdir = @runstatedir@/tpm2-tss/eventlog
+fapieventlog_DATA = dist/keep
+
+libtss2_fapi = src/tss2-fapi/libtss2-fapi.la
+tss2_HEADERS += $(srcdir)/include/tss2/tss2_fapi.h
+lib_LTLIBRARIES += $(libtss2_fapi)
+pkgconfig_DATA += lib/tss2-fapi.pc
+EXTRA_DIST +=  \
+    lib/tss2-fapi.map \
+    lib/tss2-fapi.def \
+    test/data/fapi/P_RSA_EK_persistent.json \
+    test/data/fapi/P_RSA.json \
+    test/data/fapi/P_RSA_sh_policy.json \
+    test/data/fapi/P_RSA256.json \
+    test/data/fapi/P_ECC.json \
+    test/data/fapi/policy/pol_pcr16_0.json \
+    test/data/fapi/policy/pol_pcr16_0_fail.json \
+    test/data/fapi/policy/pol_pcr16_0_or.json \
+    test/data/fapi/policy/pol_nv.json \
+    test/data/fapi/policy/pol_nv_written.json \
+    test/data/fapi/policy/pol_signed.json \
+    test/data/fapi/policy/pol_authorize.json \
+    test/data/fapi/policy/pol_authorize_nv.json \
+    test/data/fapi/policy/pol_secret.json \
+    test/data/fapi/policy/pol_password.json \
+    test/data/fapi/policy/pol_auth_value.json \
+    test/data/fapi/policy/pol_command_code.json \
+    test/data/fapi/policy/pol_locality.json \
+    test/data/fapi/policy/pol_physical_presence.json \
+    test/data/fapi/policy/pol_duplicate.json \
+    test/data/fapi/policy/pol_nv_change_auth.json \
+    test/data/fapi/policy/pol_countertimer.json \
+    test/data/fapi/policy/pol_name_hash.json \
+    test/data/fapi/policy/pol_pcr16_read.json \
+    test/data/fapi/policy/pol_action.json \
+    test/data/fapi/policy/pol_cphash.json
+
+src_tss2_fapi_libtss2_fapi_la_LIBADD  = $(libtss2_sys) $(libtss2_mu) $(libtss2_esys) \
+    $(libutil) $(libtss2_tctildr)
+
+src_tss2_fapi_libtss2_fapi_la_SOURCES = $(TSS2_FAPI_SRC)
+src_tss2_fapi_libtss2_fapi_la_CFLAGS  = $(AM_CFLAGS) -I$(srcdir)/src/tss2-fapi
+src_tss2_fapi_libtss2_fapi_la_LDFLAGS = $(AM_LDFLAGS) -ldl  -lssl -lcrypto C -ljson-c $(CURL_LIBS)
+if HAVE_LD_VERSION_SCRIPT
+src_tss2_fapi_libtss2_fapi_la_LDFLAGS += -Wl,--version-script=$(srcdir)/lib/tss2-fapi.map
+endif # HAVE_LD_VERSION_SCRIPT
+
+
+if DOXYMAN
+DOXYMAN3 += \
+    doxygen-doc/man/Fapi_AuthorizePolicy.3 \
+    doxygen-doc/man/Fapi_ChangeAuth.3 \
+    doxygen-doc/man/Fapi_CreateKey.3 \
+    doxygen-doc/man/Fapi_CreateNv.3 \
+    doxygen-doc/man/Fapi_CreateSeal.3 \
+    doxygen-doc/man/Fapi_Decrypt.3 \
+    doxygen-doc/man/Fapi_Delete.3 \
+    doxygen-doc/man/Fapi_Encrypt.3 \
+    doxygen-doc/man/Fapi_ExportKey.3 \
+    doxygen-doc/man/Fapi_ExportPolicy.3 \
+    doxygen-doc/man/Fapi_Finalize.3 \
+    doxygen-doc/man/Fapi_Free.3 \
+    doxygen-doc/man/Fapi_GetAppData.3 \
+    doxygen-doc/man/Fapi_GetCertificate.3 \
+    doxygen-doc/man/Fapi_GetDescription.3 \
+    doxygen-doc/man/Fapi_GetInfo.3 \
+    doxygen-doc/man/Fapi_GetPlatformCertificates.3 \
+    doxygen-doc/man/Fapi_GetPollHandles.3 \
+    doxygen-doc/man/Fapi_GetRandom.3 \
+    doxygen-doc/man/Fapi_GetTcti.3 \
+    doxygen-doc/man/Fapi_GetTpmBlobs.3 \
+    doxygen-doc/man/Fapi_Import.3 \
+    doxygen-doc/man/Fapi_Initialize.3 \
+    doxygen-doc/man/Fapi_List.3 \
+    doxygen-doc/man/Fapi_NvExtend.3 \
+    doxygen-doc/man/Fapi_NvIncrement.3 \
+    doxygen-doc/man/Fapi_NvRead.3 \
+    doxygen-doc/man/Fapi_NvSetBits.3 \
+    doxygen-doc/man/Fapi_NvWrite.3 \
+    doxygen-doc/man/Fapi_PcrExtend.3 \
+    doxygen-doc/man/Fapi_PcrRead.3 \
+    doxygen-doc/man/Fapi_Provision.3 \
+    doxygen-doc/man/Fapi_Quote.3 \
+    doxygen-doc/man/Fapi_SetAppData.3 \
+    doxygen-doc/man/Fapi_SetAuthCB.3 \
+    doxygen-doc/man/Fapi_SetBranchCB.3 \
+    doxygen-doc/man/Fapi_SetCertificate.3 \
+    doxygen-doc/man/Fapi_SetDescription.3 \
+    doxygen-doc/man/Fapi_SetSignCB.3 \
+    doxygen-doc/man/Fapi_Sign.3 \
+    doxygen-doc/man/FapiTestgroup.3 \
+    doxygen-doc/man/Fapi_Unseal.3 \
+    doxygen-doc/man/Fapi_VerifyQuote.3 \
+    doxygen-doc/man/Fapi_VerifySignature.3 \
+    doxygen-doc/man/Fapi_WriteAuthorizeNv.3
+endif #DOXYMAN
+
+endif #FAPI
+
 ### Man Pages
 man3_MANS = \
     man/man3/Tss2_Tcti_Device_Init.3 \
@@ -416,6 +561,11 @@
 	-rm $(DESTDIR)$(udevrulesdir)/$(udevrulesprefix)tpm-udev.rules
 endif
 
+install-exec-hook:
+	[ -d "$(DESTDIR)$(fapikeystoredir)" ] && \
+		chown tss:tss "$(DESTDIR)$(fapikeystoredir)" && \
+		chmod 775 "$(DESTDIR)$(fapikeystoredir)" || true
+
 uninstall-hook:
 	cd $(DESTDIR)$(man3dir) && \
 		[ -L Tss2_TctiLdr_Initialize_Ex.3 ] && \
diff --git a/bootstrap b/bootstrap
index d3efce1..39c8508 100755
--- a/bootstrap
+++ b/bootstrap
@@ -58,6 +58,10 @@
   src_esys_listvar "src/tss2-esys/" "*.c" "TSS2_ESYS_C" src/tss2-esys/esys_crypto_ossl.c  src/tss2-esys/esys_crypto_gcrypt.c
   printf "TSS2_ESYS_SRC = \$(TSS2_ESYS_H) \$(TSS2_ESYS_C)\n"
 
+  src_listvar "src/tss2-fapi/" "*.h" "TSS2_FAPI_H"
+  src_listvar "src/tss2-fapi/" "*.c" "TSS2_FAPI_C"
+  printf "TSS2_FAPI_SRC = \$(TSS2_FAPI_H) \$(TSS2_FAPI_C)\n"
+
   src_listvar "src/tss2-mu" "*.c" "TSS2_MU_C"
   src_listvar "src/tss2-mu" "*.h" "TSS2_MU_H"
   printf "TSS2_MU_SRC = \$(TSS2_MU_C) \$(TSS2_MU_H)\n"
diff --git a/configure.ac b/configure.ac
index a1c88f6..cd50451 100644
--- a/configure.ac
+++ b/configure.ac
@@ -15,7 +15,7 @@
 
 AC_CONFIG_HEADERS([config.h])
 
-AC_CONFIG_FILES([Makefile Doxyfile lib/tss2-sys.pc lib/tss2-esys.pc lib/tss2-mu.pc lib/tss2-tcti-device.pc lib/tss2-tcti-mssim.pc lib/tss2-rc.pc lib/tss2-tctildr.pc])
+AC_CONFIG_FILES([Makefile Doxyfile lib/tss2-sys.pc lib/tss2-esys.pc lib/tss2-mu.pc lib/tss2-tcti-device.pc lib/tss2-tcti-mssim.pc lib/tss2-rc.pc lib/tss2-tctildr.pc lib/tss2-fapi.pc])
 
 # propagate configure arguments to distcheck
 AC_SUBST([DISTCHECK_CONFIGURE_FLAGS],[$ac_configure_args])
@@ -45,6 +45,21 @@
 esac
 AC_SUBST([LIBSOCKET_LDFLAGS])
 
+AC_DEFINE_UNQUOTED([SYSCONFDIR], ["${sysconfdir}"], [System config dir])
+AC_SUBST(confdir, $sysconfdir/tpm2-tss)
+
+AC_ARG_WITH([userstatedir],
+            [AS_HELP_STRING([--with-userstatedir=<dir>],
+                            [sets the relative path in the user's home (default is ".local/share")])],,
+            [with_userstatedir=.local/share])
+AC_SUBST(userstatedir, $with_userstatedir)
+
+AC_ARG_WITH([tmpfilesdir],
+            [AS_HELP_STRING([--with-tmpfilesdir=<dir>],
+                            [sets the tpmfiles.d directory (default is "${sysconfdir}/tmpfiles.d")])],,
+            [with_tmpfilesdir="${sysconfdir}/tmpfiles.d"])
+AC_SUBST(tmpfilesdir, $with_tmpfilesdir)
+
 AC_CHECK_FUNCS([strndup])
 AC_ARG_ENABLE([unit],
             [AS_HELP_STRING([--enable-unit],
@@ -65,6 +80,24 @@
 
 AM_CONDITIONAL(ESAPI, test "x$enable_esapi" = "xyes")
 
+AC_CHECK_FUNCS([reallocarray])
+AC_ARG_ENABLE([fapi],
+            [AS_HELP_STRING([--enable-fapi],
+                            [build the fapi layer (default is yes)])],
+            [enable_fapi=$enableval],
+            [enable_fapi=yes])
+
+AM_CONDITIONAL(FAPI, test "x$enable_fapi" = "xyes")
+
+AC_ARG_ENABLE([fapi-async-tests],
+    AS_HELP_STRING([--enable-fapi-async-tests],
+               [Force fapi to spin asynchronously. (NOT FOR PRODUCTION!)]),,
+    [enable_fapi_async_tests=no])
+AS_IF([test "x$enable_fapi_async_tests" = "xyes"],
+    AC_DEFINE([TEST_FAPI_ASYNC], [1], [FAPI forced async spinning]))
+AS_IF([test "x$enable_fapi_async_tests" = "xyes"],
+    AC_MSG_WARN("FAPI compiled with asynchronous spinning testing. NOT FOR PRODUCTION!"))
+
 AC_ARG_ENABLE([tcti-device-async],
     AS_HELP_STRING([--enable-tcti-device-async],
 	           [Enable asynchronus operation on TCTI device
@@ -107,6 +140,18 @@
 AC_SUBST([TSS2_ESYS_CFLAGS_CRYPTO])
 AC_SUBST([TSS2_ESYS_LDFLAGS_CRYPTO])
 
+AS_IF([test "x$enable_fapi" != xno -a "x$enable_esapi" = "xno"],
+    AC_MSG_ERROR([ESAPI has to be enabled to compile FAPI.]))
+
+AS_IF([test "x$enable_fapi" != xno -a "x$with_crypto" != "xossl"],
+    AC_MSG_ERROR([FAPI has to be compiled with OpenSSL]))
+
+AS_IF([test "x$enable_fapi" = xyes ],
+    AC_CHECK_HEADER([json-c/json.h], [], [AC_MSG_ERROR([libjson-c (header) not found])], []))
+
+AS_IF([test "x$enable_fapi" = xyes ],
+    PKG_CHECK_MODULES([CURL], [libcurl]))
+
 AC_ARG_WITH([tctidefaultmodule],
             [AS_HELP_STRING([--with-tctidefaultmodule],
 [The default TCTI module for ESAPI. (Default: libtss2-tcti-default.so)])],
@@ -387,6 +432,7 @@
 AC_MSG_RESULT([
     $PACKAGE_NAME $VERSION
     esapi:              $enable_esapi
+    fapi:               $enable_fapi
     tctidefaultmodule:  $with_tctidefaultmodule
     tctidefaultconfig:  $with_tctidefaultconfig
     unit:               $enable_unit
@@ -397,4 +443,9 @@
     tcti-device-async:  $enable_tcti_device_async
     tcti-partial-read:  $enable_tcti_partial_reads
     crypto backend:     $with_crypto
+    sysconfdir:         $sysconfdir
+    localstatedir:      $localstatedir
+    runstatedir:        $runstatedir
+    tmpfilesdir:        $tmpfilesdir
+    userstatedir:       [\$HOME/]$with_userstatedir
 ])
diff --git a/dist/fapi-config.json.in b/dist/fapi-config.json.in
new file mode 100644
index 0000000..a76b6b2
--- /dev/null
+++ b/dist/fapi-config.json.in
@@ -0,0 +1,9 @@
+{
+     "profile_name": "P_RSA2048SHA256",
+     "profile_dir": "@sysconfdir@/tpm2-tss/fapi-profiles/",
+     "user_dir": "~/@userstatedir@/tpm2-tss/user/keystore",
+     "system_dir": "@localstatedir@/tpm2-tss/system/keystore",
+     "tcti": "",
+     "system_pcrs" : [],
+     "log_dir" : "@runstatedir@/tpm2-tss/eventlog/",
+}
diff --git a/dist/fapi-profiles/P_ECCP256SHA256.json b/dist/fapi-profiles/P_ECCP256SHA256.json
new file mode 100644
index 0000000..5b099d8
--- /dev/null
+++ b/dist/fapi-profiles/P_ECCP256SHA256.json
@@ -0,0 +1,38 @@
+{
+    "type": "TPM2_ALG_ECC",
+    "nameAlg":"TPM2_ALG_SHA256",
+    "srk_template": "system,restricted,decrypt",
+    "srk_persistent": 0,
+    "ek_template":  "system,restricted,decrypt",
+    "ecc_signing_scheme": {
+        "scheme":"TPM2_ALG_ECDSA",
+        "details":{
+            "hashAlg":"TPM2_ALG_SHA1"
+        },
+    },
+    "rsa_signing_scheme": {
+        "scheme":"TPM2_ALG_NULL"
+    },
+    "rsa_decrypt_scheme": {
+        "scheme":"TPM2_ALG_OAEP",
+        "details":{
+            "hashAlg":"TPM2_ALG_SHA1"
+        }
+    },
+    "sym_mode":"TPM2_ALG_CFB",
+    "sym_parameters": {
+        "algorithm":"TPM2_ALG_AES",
+        "keyBits":"128",
+        "mode":"TPM2_ALG_CFB"
+    },
+    "sym_block_size": 16,
+    "pcr_selection": [
+       { "hash": "TPM2_ALG_SHA1",
+         "pcrSelect": [ 9, 15 , 13]
+       },
+       { "hash": "TPM2_ALG_SHA256",
+         "pcrSelect": [ 8, 16, 14 ]
+       }
+    ],
+    "curveID": "TPM2_ECC_NIST_P256"
+}
diff --git a/dist/fapi-profiles/P_RSA2048SHA256.json b/dist/fapi-profiles/P_RSA2048SHA256.json
new file mode 100644
index 0000000..659ba1d
--- /dev/null
+++ b/dist/fapi-profiles/P_RSA2048SHA256.json
@@ -0,0 +1,42 @@
+{
+    "type": "TPM2_ALG_RSA",
+    "nameAlg":"TPM2_ALG_SHA256",
+    "srk_template": "system,restricted,decrypt",
+    "srk_persistent": 0,
+    "ek_template":  "system,restricted,decrypt",
+    "ecc_signing_scheme": {
+        "scheme":"TPM2_ALG_ECDSA",
+        "details":{
+            "hashAlg":"TPM2_ALG_SHA256"
+        },
+    },
+    "rsa_signing_scheme": {
+        "scheme":"TPM2_ALG_RSAPSS",
+        "details":{
+            "hashAlg":"TPM2_ALG_SHA256"
+        }
+    },
+    "rsa_decrypt_scheme": {
+        "scheme":"TPM2_ALG_OAEP",
+        "details":{
+            "hashAlg":"TPM2_ALG_SHA256"
+        }
+    },
+    "sym_mode":"TPM2_ALG_CFB",
+    "sym_parameters": {
+        "algorithm":"TPM2_ALG_AES",
+        "keyBits":"128",
+        "mode":"TPM2_ALG_CFB"
+    },
+    "sym_block_size": 16,
+    "pcr_selection": [
+        { "hash": "TPM2_ALG_SHA1",
+          "pcrSelect": [ 9, 15, 13 ]
+        },
+        { "hash": "TPM2_ALG_SHA256",
+          "pcrSelect": [ 8, 16, 14 ]
+        }
+    ],
+    "exponent": 0,
+    "keyBits": 2048
+}
diff --git a/dist/fapi-tmpfiles.conf.in b/dist/fapi-tmpfiles.conf.in
new file mode 100644
index 0000000..c49a874
--- /dev/null
+++ b/dist/fapi-tmpfiles.conf.in
@@ -0,0 +1,2 @@
+#Type   Path                                    Mode User Group Age         Argument
+d       @runstatedir@/tpm2-tss/eventlog/        775  tss  tss   -           -
diff --git a/dist/keep b/dist/keep
new file mode 100644
index 0000000..58293ad
--- /dev/null
+++ b/dist/keep
@@ -0,0 +1 @@
+Placeholder to create and keep directory
diff --git a/doc/doxygen.dox b/doc/doxygen.dox
index 8872b7b..a7b7c2c 100644
--- a/doc/doxygen.dox
+++ b/doc/doxygen.dox
@@ -1013,8 +1013,8 @@
 /*!
  \defgroup iesys_crypto Internal Cryptographic Backend
  \ingroup iesys
- The types and functions used internally be ESAPI for cryptographic operations.
- There may exist multiple implementations of these functions for different
+ The types and functions used internally by ESAPI for cryptographic operations.
+ Multiple implementations of these functions may exist for different
  cryptographic backends.
  \{
  \def IESYS_CRYPTO_CONTEXT_BLOB
@@ -1057,6 +1057,12 @@
 
 /*!
  \defgroup Testgroup Testing
+ Description of the test plan.
+*/
+
+/*!
+ \defgroup EsysTestgroup Esys-Testing
+ \ingroup Testgroup
  \{
  @brief \{
  For every integration test a function with a name corresponding to the name of the source code
@@ -1149,3 +1155,437 @@
  \}
  \}
 */
+
+/*!
+ \defgroup fapi Feature API
+ Feature API (FAPI) as described in the [TSS 2.0 Feature API (FAPI) Specification](https://trustedcomputinggroup.org/wp-content/uploads/todo.pdf).
+ This API provides a very abstract view on TPM functionalities most suitable for 80 percent of applications. In mostly uses standard types in its parameter list. Policies are encoded in JSON, whereas most key material is encoded as PEM.
+ Both the synchronous and asynchronous API are exposed through a single library: libtss2-fapi.
+ In order to perform an asynchronous invocation of FAPI functions, the following code serves as a template:
+ do { r = Fapi_GetPollHandles(fc, &ph, &nph);
+      if (r == TSS2_RC_SUCCESS) { poll(ph, nph, -1); Fapi_Free(ph); }
+      r = Fapi_*_Finish(fc, ...); } while (r == TSS2_FAPI_RC_TRY_AGAIN);
+ \{
+ \typedef FAPI_CONTEXT
+ Reference to the FAPI_CONTEXT that holds data for the connection to the TPM as
+ well as the metadata for TPM Resource as well as links to the key- and policy
+ store or key material for encrypted sessions.
+ \defgroup Fapi_Initialize Fapi_Initialize
+ FAPI functions to invoke Initialize either as one-call or in an asynchronous manner.
+ \{
+ \fn Fapi_Initialize(FAPI_CONTEXT **context, char const *uri)
+ \fn Fapi_Initialize_Async(FAPI_CONTEXT **context, char const *uri)
+ \fn Fapi_Initialize_Finish(FAPI_CONTEXT **context)
+ \}
+ \defgroup Fapi_Finalize Fapi_Finalize
+ FAPI function to invoke Finalize.
+ \{
+ \fn Fapi_Finalize(FAPI_CONTEXT **context)
+ \}
+ \defgroup Fapi_GetTcti Fapi_GetTcti
+ FAPI function to retrieve the TSS2_TCTI_CONTEXT currently used by the corresponding FAPI_CONTEXT.
+ \{
+ \fn Fapi_GetTcti(FAPI_CONTEXT *context, TSS2_TCTI_CONTEXT **tcti)
+ \}
+ \defgroup Fapi_GetPollHandles Fapi_GetPollHandles
+ FAPI function to retrieve the poll handles currently used by the corresponding FAPI_CONTEXT.
+ \{
+ \fn Fapi_GetPollHandles(FAPI_CONTEXT *context, FAPI_POLL_HANDLE **handles, size_t *num_handles)
+ \}
+ \defgroup Fapi_Free Fapi_Free
+ FAPI function to invoke Free.
+ \{
+ \fn Fapi_Free( \fn *ptr)
+ \}
+ \defgroup Fapi_GetInfo Fapi_GetInfo
+ FAPI functions to invoke GetInfo either as one-call or in an asynchronous manner.
+ \{
+ \fn Fapi_GetInfo(FAPI_CONTEXT *context, char **info)
+ \fn Fapi_GetInfo_Async(FAPI_CONTEXT *context)
+ \fn Fapi_GetInfo_Finish(FAPI_CONTEXT *context, char **info)
+ \}
+ \defgroup Fapi_Provision Fapi_Provision
+ FAPI functions to invoke Provision either as one-call or in an asynchronous manner.
+ \{
+ \fn Fapi_Provision(FAPI_CONTEXT *context, char const *policyPathEh, char const *authValueEh, char const *policyPathSh, char const *authValueSh, char const *authValueLockout)
+ \fn Fapi_Provision_Async(FAPI_CONTEXT *context, char const *policyPathEh, char const *authValueEh, char const *policyPathSh, char const *authValueSh, char const *authValueLockout)
+ \fn Fapi_Provision_Finish(FAPI_CONTEXT *context)
+ \}
+ \defgroup Fapi_GetPlatformCertificates Fapi_GetPlatformCertificates
+ FAPI functions to invoke GetPlatformCertificates either as one-call or in an asynchronous manner.
+ \{
+ \fn Fapi_GetPlatformCertificates(FAPI_CONTEXT *context, uint8_t **certificates, size_t *certificatesSize)
+ \fn Fapi_GetPlatformCertificates_Async(FAPI_CONTEXT *context)
+ \fn Fapi_GetPlatformCertificates_Finish(FAPI_CONTEXT *context, uint8_t **certificates, size_t *certificatesSize)
+ \}
+ \defgroup Fapi_GetRandom Fapi_GetRandom
+ FAPI functions to invoke GetRandom either as one-call or in an asynchronous manner.
+ \{
+ \fn Fapi_GetRandom(FAPI_CONTEXT *context, size_t numBytes, uint8_t **data)
+ \fn Fapi_GetRandom_Async(FAPI_CONTEXT *context, size_t numBytes)
+ \fn Fapi_GetRandom_Finish(FAPI_CONTEXT *context, uint8_t **data)
+ \}
+ \defgroup Fapi_Import Fapi_Import
+ FAPI functions to invoke Import either as one-call or in an asynchronous manner.
+ \{
+ \fn Fapi_Import(FAPI_CONTEXT *context, char const *path, char const *importData)
+ \fn Fapi_Import_Async(FAPI_CONTEXT *context, char const *path, char const *importData)
+ \fn Fapi_Import_Finish(FAPI_CONTEXT *context)
+ \}
+ \defgroup Fapi_List Fapi_List
+ FAPI functions to invoke List either as one-call or in an asynchronous manner.
+ \{
+ \fn Fapi_List(FAPI_CONTEXT *context, char const *searchPath, char **pathList)
+ \fn Fapi_List_Async(FAPI_CONTEXT *context, char const *searchPath)
+ \fn Fapi_List_Finish(FAPI_CONTEXT *context, char **pathlist)
+ \}
+ \defgroup Fapi_Delete Fapi_Delete
+ FAPI functions to invoke Delete either as one-call or in an asynchronous manner.
+ \{
+ \fn Fapi_Delete(FAPI_CONTEXT *context, char const *path)
+ \fn Fapi_Delete_Async(FAPI_CONTEXT *context, char const *path)
+ \fn Fapi_Delete_Finish(FAPI_CONTEXT *context)
+ \}
+ \defgroup Fapi_ChangeAuth Fapi_ChangeAuth
+ FAPI functions to invoke ChangeAuth either as one-call or in an asynchronous manner.
+ \{
+ \fn Fapi_ChangeAuth(FAPI_CONTEXT *context, char const *entityPath, char const *authValue)
+ \fn Fapi_ChangeAuth_Async(FAPI_CONTEXT *context, char const *entityPath, char const *authValue)
+ \fn Fapi_ChangeAuth_Finish(FAPI_CONTEXT *context)
+ \}
+ \defgroup Fapi_SetDescription Fapi_SetDescription
+ FAPI functions to invoke SetDescription either as one-call or in an asynchronous manner.
+ \{
+ \fn Fapi_SetDescription(FAPI_CONTEXT *context, char const *path, char const *description)
+ \fn Fapi_SetDescription_Async(FAPI_CONTEXT *context, char const *path, char const *description)
+ \fn Fapi_SetDescription_Finish(FAPI_CONTEXT *context)
+ \}
+ \defgroup Fapi_GetDescription Fapi_GetDescription
+ FAPI functions to invoke GetDescription either as one-call or in an asynchronous manner.
+ \{
+ \fn Fapi_GetDescription(FAPI_CONTEXT *context, char const *path, char **description)
+ \fn Fapi_GetDescription_Async(FAPI_CONTEXT *context, char const *path)
+ \fn Fapi_GetDescription_Finish(FAPI_CONTEXT *context, char **description)
+ \}
+ \defgroup Fapi_SetAppData Fapi_SetAppData
+ FAPI functions to invoke SetAppData either as one-call or in an asynchronous manner.
+ \{
+ \fn Fapi_SetAppData(FAPI_CONTEXT *context, char const *path, uint8_t const *appData, size_t appDataSize)
+ \fn Fapi_SetAppData_Async(FAPI_CONTEXT *context, char const *path, uint8_t const *appData, size_t appDataSize)
+ \fn Fapi_SetAppData_Finish(FAPI_CONTEXT *context)
+ \}
+ \defgroup Fapi_GetAppData Fapi_GetAppData
+ FAPI functions to invoke GetAppData either as one-call or in an asynchronous manner.
+ \{
+ \fn Fapi_GetAppData(FAPI_CONTEXT *context, char const *path, uint8_t **appData, size_t *appDataSize)
+ \fn Fapi_GetAppData_Async(FAPI_CONTEXT *context, char const *path)
+ \fn Fapi_GetAppData_Finish(FAPI_CONTEXT *context, uint8_t **appData, size_t *appDataSize)
+ \}
+ \defgroup Fapi_GetTpmBlobs Fapi_GetTpmBlobs
+ FAPI functions to invoke GetTPMBlobs either as one-call or in an asynchronous manner.
+ \{
+ \fn Fapi_GetTpmBlobs(FAPI_CONTEXT *context, char const *path, uint8_t **tpm2bPublic, size_t *tpm2bPublicSize, uint8_t **tpm2bPrivate, size_t *tpm2bPrivateSize, char **policy)
+ \fn Fapi_GetTpmBlobs_Async(FAPI_CONTEXT *context, char const *path)
+ \fn Fapi_GetTpmBlobs_Finish(FAPI_CONTEXT *context, uint8_t **tpm2bPublic, size_t *tpm2bPublicSize, uint8_t **tpm2bPrivate, size_t *tpm2bPrivateSize, char **policy)
+ \}
+ \defgroup Fapi_CreateKey Fapi_CreateKey
+ FAPI functions to invoke CreateKey either as one-call or in an asynchronous manner.
+ \{
+ \fn Fapi_CreateKey(FAPI_CONTEXT *context, char const *path, char const *type, char const *policyPath, char const *authvalue)
+ \fn Fapi_CreateKey_Async(FAPI_CONTEXT *context, char const *keyPath, char const *type, char const *policyPath, char const *authvalue)
+ \fn Fapi_CreateKey_Finish(FAPI_CONTEXT *context)
+ \}
+ \defgroup Fapi_Sign Fapi_Sign
+ FAPI functions to invoke Sign either as one-call or in an asynchronous manner.
+ \{
+ \fn Fapi_Sign(FAPI_CONTEXT *context, char const *keyPath, char const *padding, uint8_t const *digest, size_t digestSize, uint8_t **signature, size_t *signatureSize, char **publicKey, char **certificate)
+ \fn Fapi_Sign_Async(FAPI_CONTEXT *context, char const *keyPath, char const *padding, uint8_t const *digest, size_t digestSize)
+ \fn Fapi_Sign_Finish(FAPI_CONTEXT *context, uint8_t **signature, size_t *signatureSize, char **publicKey, char **certificate)
+ \}
+ \defgroup Fapi_VerifySignature Fapi_VerifySignature
+ FAPI functions to invoke VerifySignature either as one-call or in an asynchronous manner.
+ \{
+ \fn Fapi_VerifySignature(FAPI_CONTEXT *context, char const *keyPath, uint8_t const *digest, size_t digestSize, uint8_t const *signature, size_t signatureSize)
+ \fn Fapi_VerifySignature_Async(FAPI_CONTEXT *context, char const *keyPath, uint8_t const *digest, size_t digestSize, uint8_t const *signature, size_t signatureSize)
+ \fn Fapi_VerifySignature_Finish(FAPI_CONTEXT *context)
+ \}
+ \defgroup Fapi_Encrypt Fapi_Encrypt
+ FAPI functions to invoke Encrypt either as one-call or in an asynchronous manner.
+ \{
+ \fn Fapi_Encrypt(FAPI_CONTEXT *context, char const *keyPath, char const *policyPath, uint8_t const *plaintext, size_t plaintextSize, char **cipherText)
+ \fn Fapi_Encrypt_Async(FAPI_CONTEXT *context, char const *keyPath, char const *policyPath, uint8_t const *plaintext, size_t plaintextSize)
+ \fn Fapi_Encrypt_Finish(FAPI_CONTEXT *context, char **cipherText)
+ \}
+ \defgroup Fapi_Decrypt Fapi_Decrypt
+ FAPI functions to invoke Decrypt either as one-call or in an asynchronous manner.
+ \{
+ \fn Fapi_Decrypt(FAPI_CONTEXT *context, char const *cipherText, uint8_t **plainText, size_t *plainTextSize)
+ \fn Fapi_Decrypt_Async(FAPI_CONTEXT *context, char const *cipherText)
+ \fn Fapi_Decrypt_Finish(FAPI_CONTEXT *context, uint8_t **plainText, size_t *plainTextSize)
+ \}
+ \defgroup Fapi_SetCertificate Fapi_SetCertificate
+ FAPI functions to invoke SetCertificate either as one-call or in an asynchronous manner.
+ \{
+ \fn Fapi_SetCertificate(FAPI_CONTEXT *context, char const *path, char const *x509certData)
+ \fn Fapi_SetCertificate_Async(FAPI_CONTEXT *context, char const *path, char const *x509certData)
+ \fn Fapi_SetCertificate_Finish(FAPI_CONTEXT *context)
+ \}
+ \defgroup Fapi_GetCertificate Fapi_GetCertificate
+ FAPI functions to invoke GetCertificate either as one-call or in an asynchronous manner.
+ \{
+ \fn Fapi_GetCertificate(FAPI_CONTEXT *context, char const *path, char **x509certData)
+ \fn Fapi_GetCertificate_Async(FAPI_CONTEXT *context, char const *path)
+ \fn Fapi_GetCertificate_Finish(FAPI_CONTEXT *context, char **x509certData)
+ \}
+ \defgroup Fapi_ExportKey Fapi_ExportKey
+ FAPI functions to invoke ExportKey either as one-call or in an asynchronous manner.
+ \{
+ \fn Fapi_ExportKey(FAPI_CONTEXT *context, char const *pathOfKeyToDuplicate, char const *pathToPublicKeyOfNewParent, char **exportedData)
+ \fn Fapi_ExportKey_Async(FAPI_CONTEXT *context, char const *pathOfKeyToDuplicate, char const *pathToPublicKeyOfNewParent)
+ \fn Fapi_ExportKey_Finish(FAPI_CONTEXT *context, char **exportedData)
+ \}
+ \defgroup Fapi_CreateSeal Fapi_CreateSeal
+ FAPI functions to invoke CreateSeal either as one-call or in an asynchronous manner.
+ \{
+ \fn Fapi_CreateSeal(FAPI_CONTEXT *context, char const *path, char const *type, size_t size, char const *policyPath, char const *authValue, uint8_t const *data)
+ \fn Fapi_CreateSeal_Async(FAPI_CONTEXT *context, char const *path, char const *type, size_t size, char const *policyPath, char const *authValue, uint8_t const *data)
+ \fn Fapi_CreateSeal_Finish(FAPI_CONTEXT *context)
+ \}
+ \defgroup Fapi_Unseal Fapi_Unseal
+ FAPI functions to invoke Unseal either as one-call or in an asynchronous manner.
+ \{
+ \fn Fapi_Unseal(FAPI_CONTEXT *context, char const *path, uint8_t **data, size_t *size)
+ \fn Fapi_Unseal_Async(FAPI_CONTEXT *context, char const *path)
+ \fn Fapi_Unseal_Finish(FAPI_CONTEXT *context, uint8_t **data, size_t *size)
+ \}
+ \defgroup Fapi_ExportPolicy Fapi_ExportPolicy
+ FAPI functions to invoke ExportPolicy either as one-call or in an asynchronous manner.
+ \{
+ \fn Fapi_ExportPolicy(FAPI_CONTEXT *context, char const *path, char **jsonPolicy)
+ \fn Fapi_ExportPolicy_Async(FAPI_CONTEXT *context, char const *path)
+ \fn Fapi_ExportPolicy_Finish(FAPI_CONTEXT *context, char **jsonPolicy)
+ \}
+ \defgroup Fapi_AuthorizePolicy Fapi_AuthorizePolicy
+ FAPI functions to invoke AuthorizePolicy either as one-call or in an asynchronous manner.
+ \{
+ \fn Fapi_AuthorizePolicy(FAPI_CONTEXT *context, char const *policyPath, char const *keyPath, uint8_t const *policyRef, size_t policyRefSize)
+ \fn Fapi_AuthorizePolicy_Async(FAPI_CONTEXT *context, char const *policyPath, char const *keyPath, uint8_t const *policyRef, size_t policyRefSize)
+ \fn Fapi_AuthorizePolicy_Finish(FAPI_CONTEXT *context)
+ \}
+ \defgroup Fapi_WriteAuthorizeNv Fapi_WriteAuthorizeNv
+ FAPI functions to invoke WriteAuthorizeNv either as one-call or in an asynchronous manner.
+ \{
+ \fn Fapi_WriteAuthorizeNv(FAPI_CONTEXT *context, char const *nvPath, char const *policyPath)
+ \fn Fapi_WriteAuthorizeNv_Async(FAPI_CONTEXT *context, char const *nvPath, char const *policyPath)
+ \fn Fapi_WriteAuthorizeNv_Finish(FAPI_CONTEXT *context)
+ \}
+ \defgroup Fapi_PcrRead Fapi_PcrRead
+ FAPI functions to invoke PcrRead either as one-call or in an asynchronous manner.
+ \{
+ \fn Fapi_PcrRead(FAPI_CONTEXT *context, uint32_t pcrIndex, uint8_t **pcrValue, size_t *pcrValueSize, char **pcrLog)
+ \fn Fapi_PcrRead_Async(FAPI_CONTEXT *context, uint32_t pcrIndex)
+ \fn Fapi_PcrRead_Finish(FAPI_CONTEXT *context, uint8_t **pcrValue, size_t *pcrValueSize, char **pcrLog)
+ \}
+ \defgroup Fapi_PcrExtend Fapi_PcrExtend
+ FAPI functions to invoke PcrExtend either as one-call or in an asynchronous manner.
+ \{
+ \fn Fapi_PcrExtend(FAPI_CONTEXT *context, uint32_t pcr, uint8_t const *data, size_t dataSize, char const *logData)
+ \fn Fapi_PcrExtend_Async(FAPI_CONTEXT *context, uint32_t pcr, uint8_t const *data, size_t dataSize, char const *logData)
+ \fn Fapi_PcrExtend_Finish(FAPI_CONTEXT *context)
+ \}
+ \defgroup Fapi_Quote Fapi_Quote
+ FAPI functions to invoke Quote either as one-call or in an asynchronous manner.
+ \{
+ \fn Fapi_Quote(FAPI_CONTEXT *context, uint32_t *pcrList, size_t pcrListSize, char const *keyPath, char const *quoteType, uint8_t const *qualifyingData, size_t qualifyingDataSize, char **quoteInfo, uint8_t **signature, size_t *signatureSize, char **pcrLog, char **certificate)
+ \fn Fapi_Quote_Async(FAPI_CONTEXT *context, uint32_t *pcrList, size_t pcrListSize, char const *keyPath, char const *quoteType, uint8_t const *qualifyingData, size_t qualifyingDataSize)
+ \fn Fapi_Quote_Finish(FAPI_CONTEXT *context, char **quoteInfo, uint8_t **signature, size_t *signatureSize, char **pcrLog, char **certificate)
+ \}
+ \defgroup Fapi_VerifyQuote Fapi_VerifyQuote
+ FAPI functions to invoke VerifyQuote either as one-call or in an asynchronous manner.
+ \{
+ \fn Fapi_VerifyQuote(FAPI_CONTEXT *context, char const *publicKeyPath, uint8_t const *qualifyingData, size_t qualifyingDataSize, char const *quoteInfo, uint8_t const *signature, size_t signatureSize, char const *pcrLog)
+ \fn Fapi_VerifyQuote_Async(FAPI_CONTEXT *context, char const *publicKeyPath, uint8_t const *qualifyingData, size_t qualifyingDataSize, char const *quoteInfo, uint8_t const *signature, size_t signatureSize, char const *pcrLog)
+ \fn Fapi_VerifyQuote_Finish(FAPI_CONTEXT *context)
+ \}
+ \defgroup Fapi_CreateNv Fapi_CreateNv
+ FAPI functions to invoke CreateNv either as one-call or in an asynchronous manner.
+ \{
+ \fn Fapi_CreateNv(FAPI_CONTEXT *context, char const *path, char const *type, size_t size, char const *policyPath, char const *authValue)
+ \fn Fapi_CreateNv_Async(FAPI_CONTEXT *context, char const *path, char const *type, size_t size, char const *policyPath, char const *authValue)
+ \fn Fapi_CreateNv_Finish(FAPI_CONTEXT *context)
+ \}
+ \defgroup Fapi_NvRead Fapi_NvRead
+ FAPI functions to invoke NvRead either as one-call or in an asynchronous manner.
+ \{
+ \fn Fapi_NvRead(FAPI_CONTEXT *context, char const *path, uint8_t **data, size_t *size)
+ \fn Fapi_NvRead_Async(FAPI_CONTEXT *context, char const *path)
+ \fn Fapi_NvRead_Finish(FAPI_CONTEXT *context, uint8_t **data, size_t *size)
+ \}
+ \defgroup Fapi_NvWrite Fapi_NvWrite
+ FAPI functions to invoke NvWrite either as one-call or in an asynchronous manner.
+ \{
+ \fn Fapi_NvWrite(FAPI_CONTEXT *context, char const *path, uint8_t const *data, size_t size)
+ \fn Fapi_NvWrite_Async(FAPI_CONTEXT *context, char const *path, uint8_t const *data, size_t size)
+ \fn Fapi_NvWrite_Finish(FAPI_CONTEXT *context)
+ \}
+ \defgroup Fapi_NvExtend Fapi_NvExtend
+ FAPI functions to invoke NvExtend either as one-call or in an asynchronous manner.
+ \{
+ \fn Fapi_NvExtend(FAPI_CONTEXT *context, char const *path, uint8_t const *data, size_t size)
+ \fn Fapi_NvExtend_Async(FAPI_CONTEXT *context, char const *path, uint8_t const *data, size_t size)
+ \fn Fapi_NvExtend_Finish(FAPI_CONTEXT *context)
+ \}
+ \defgroup Fapi_NvIncrement Fapi_NvIncrement
+ FAPI functions to invoke NvIncrement either as one-call or in an asynchronous manner.
+ \{
+ \fn Fapi_NvIncrement(FAPI_CONTEXT *context, char const *path)
+ \fn Fapi_NvIncrement_Async(FAPI_CONTEXT *context, char const *path)
+ \fn Fapi_NvIncrement_Finish(FAPI_CONTEXT *context)
+ \}
+ \defgroup Fapi_NvSetBits Fapi_NvSetBits
+ FAPI functions to invoke NvSetBits either as one-call or in an asynchronous manner.
+ \{
+ \fn Fapi_NvSetBits(FAPI_CONTEXT *context, char const *path, uint64_t bitmap)
+ \fn Fapi_NvSetBits_Async(FAPI_CONTEXT *context, char const *path, uint64_t bitmap)
+ \fn Fapi_NvSetBits_Finish(FAPI_CONTEXT *context)
+ \}
+ \defgroup Fapi_SetAuthCB Fapi_SetAuthCB
+ FAPI functions to invoke SetAuthCB.
+ \{
+ \fn Fapi_SetAuthCB(FAPI_CONTEXT *context, Fapi_CB_Auth callback,  \fn *userData)
+ \typedef (*Fapi_CB_Auth)(FAPI_CONTEXT *context, char const *description, char **auth,  \fn *userData)
+ \}
+ \defgroup Fapi_SetBranchCB Fapi_SetBranchCB
+ FAPI functions to invoke SetBranchCB.
+ \{
+ \fn Fapi_SetBranchCB(FAPI_CONTEXT *context, Fapi_CB_Branch callback,  \fn *userData)
+ \typedef (*Fapi_CB_Branch)(FAPI_CONTEXT *context, char const *description, char const **branchNames, size_t numBranches, size_t *selectedBranch,  \fn *userData)
+ \}
+ \defgroup Fapi_SetSignCB Fapi_SetSignCB
+ FAPI functions to invoke SetSignCB.
+ \{
+ \fn Fapi_SetSignCB(FAPI_CONTEXT *context, Fapi_CB_Sign callback,  \fn *userData)
+ \typedef (*Fapi_CB_Sign)(FAPI_CONTEXT *context, char const *description, char const *publicKey, char const *publicKeyHint, uint32_t hashAlg, uint8_t const *dataToSign, size_t dataToSignSize, uint8_t **signature, size_t *signatureSize,  \fn *userData)
+ \}
+ \}
+*/
+
+/*!
+ \defgroup ifapi Internals of Feature API
+ \ingroup fapi
+ This module holds internal APIs of the FAPI implementation.
+
+ Async programming style:
+
+ The tss2-fapi implementation uses an asynchronous programming style internally.
+ This means that whenever a piece of code performs a potentially blocking operation
+ it will instead return TSS2_FAPI_RC_TRY_AGAIN (similarly to ESAPI). Then this function
+ is called again once the Poll returns ok.
+ In order to carry the state of execution information over between the different invocation
+ of the same function, the current state is stored in a state variable and all variables
+ are stored in some kind of context variables.
+ On the next entry to the function the state is evaluated using a swtich() statement and
+ execution is resumed.
+
+ In order to understand the functional flow of code in FAPI, one can read the functions
+ continuously over all fallthrough; and statecase(); statements. The statecase
+ statements are the re-entry points of each function. The return_try_again() and FAPI_SYNC()
+ statements are the preempt statements.
+ \{
+ \}
+*/
+
+/*!
+ \defgroup fapi_crypto Internal Cryptographic Backend
+ \ingroup ifapi
+ The types and functions used internally by FAPI for cryptographic operations.
+ Multiple implementations of these functions for different
+ cryptographic backends may exist.
+ \{
+ \def IFAPI_CRYPTO_CONTEXT_BLOB
+ \fn TPMI_ALG_HASH ifapi_get_sig_hash_alg(const IFAPI_KEY_PROFILE *profile,
+    TPMT_PUBLIC *tpmPublic)
+ \fn TPMI_ALG_HASH ifapi_get_sig_hash_alg(const IFAPI_KEY_PROFILE *profile,
+    TPMT_PUBLIC *tpmPublic)
+ \fn TSS2_RC ifapi_get_profile_sig_scheme(const IFAPI_KEY_PROFILE *profile,
+    const TPMT_PUBLIC *tpmPublic, TPMT_SIG_SCHEME *signatureScheme)
+ \fn TSS2_RC ifapi_der_sig_to_tpm(const TPMT_PUBLIC *tpmPublic,
+    const unsigned char *signature, size_t signatureSize,
+    TPMI_ALG_HASH hashAlgorithm, TPMT_SIGNATURE *tpmSignature)
+ \fn TSS2_RC ifapi_tpm_ecc_sig_to_der(const TPMT_SIGNATURE *tpmSignature,
+    uint8_t **signature, size_t *signatureSize)
+ \fn TSS2_RC ifapi_pub_pem_key_from_tpm(const TPM2B_PUBLIC *tpmPublicKey,
+    char **pemKey, int *pemKeySize)
+ \fn TSS2_RC ifapi_verify_signature(const IFAPI_OBJECT *keyObject,
+    const uint8_t *signature, size_t signatureSize, const uint8_t *digest,
+    size_t digestSize)
+ \fn TSS2_RC ifapi_verify_signature_quote(const IFAPI_OBJECT *keyObject,
+    const uint8_t *signature, size_t signatureSize, const uint8_t *digest,
+    size_t digestSize, const TPMT_SIG_SCHEME *signatureScheme)
+ \fn TSS2_RC ifapi_crypto_hash_start(IFAPI_CRYPTO_CONTEXT_BLOB **context,
+    TPM2_ALG_ID hashAlgorithm)
+ \fn TSS2_RC ifapi_crypto_hash_update(IFAPI_CRYPTO_CONTEXT_BLOB *context,
+    const uint8_t *buffer, size_t size)
+ \fn TSS2_RC ifapi_crypto_hash_finish(IFAPI_CRYPTO_CONTEXT_BLOB **context,
+    uint8_t *digest, size_t *digestSize);
+ \fn void ifapi_crypto_hash_abort(IFAPI_CRYPTO_CONTEXT_BLOB **context)
+ \fn TSS2_RC ifapi_cert_to_pem(const uint8_t *certBuffer, size_t certBufferSize,
+    char **pemCert, TPM2_ALG_ID *certAlgorithmId)
+ \fn size_t ifapi_hash_get_digest_size(TPM2_ALG_ID hashAlgorithm)
+ \fn TSS2_RC ifapi_get_tpm2b_public_from_pem(const IFAPI_KEY_PROFILE *profile,
+    const char *pemKey, TPM2B_PUBLIC *tpmPublic)
+ \fn TSS2_RC ifapi_crypto_aes_encrypt(const uint8_t *key, size_t keySize,
+    const uint8_t *iv, uint8_t *buffer, size_t bufferSize)
+ \fn TSS2_RC ifapi_crypto_aes_decrypt(const uint8_t *key, size_t keySize,
+    const uint8_t *iv, uint8_t *buffer, size_t bufferSize)
+ \fn TSS2_RC ifapi_get_hash_alg_for_size(uint16_t size, TPMI_ALG_HASH *hashAlgorithm)
+ \fn TPM2_ALG_ID ifapi_get_signature_algorithm_from_pem(const char *pemKey)
+\}
+*/
+
+/*!
+ \defgroup ifapi_config FAPI configuration module
+ \ingroup ifapi
+ Provides functions and types for the FAPI configuration and its initialization
+ \{
+  \def IFAPI_CONFIG
+  \fn TSS2_RC ifapi_config_initialize_async(IFAPI_IO *io)
+  \fn TSS2_RC ifapi_config_initialize_finish(IFAPI_IO *io, IFAPI_CONFIG *config)
+ \}
+*/
+
+/*!
+ \defgroup FapiTestgroup Fapi-Testing
+ Testing of FAPI functionality. The tested FAPI functions are listed in each
+ of the testcase functions' descriptions.
+ \ingroup Testgroup
+ \{
+ \fn test_fapi_info(FAPI_CONTEXT *context)
+ \fn test_fapi_data_crypt_rsa(FAPI_CONTEXT *context)
+ \fn test_fapi_duplicate(FAPI_CONTEXT *context)
+ \fn test_fapi_change_key_auth(FAPI_CONTEXT *context)
+ \fn test_fapi_key_create_policy_signed(FAPI_CONTEXT *context)
+ \fn test_fapi_key_create_sign_password_provision(FAPI_CONTEXT *context)
+ \fn test_fapi_key_create_ecc(FAPI_CONTEXT *context)
+ \fn test_fapi_nv_ordinary(FAPI_CONTEXT *context)
+ \fn test_fapi_quote(FAPI_CONTEXT *context)
+ \fn test_fapi_key_create_policy_authorize_sign(FAPI_CONTEXT *context)
+ \fn test_fapi_policy_authorize_nv(FAPI_CONTEXT *context)
+ \fn test_fapi_nv_set_bits(FAPI_CONTEXT *context)
+ \fn test_fapi_policy_secret(FAPI_CONTEXT *context)
+ \fn test_fapi_nv_written(FAPI_CONTEXT *context)
+ \fn test_fapi_nv_increment(FAPI_CONTEXT *context)
+ \fn test_fapi_get_random(FAPI_CONTEXT *context)
+ \fn test_fapi_pcr_test(FAPI_CONTEXT *context)
+ \fn test_fapi_policy_password(FAPI_CONTEXT *context)
+ \fn test_fapi_key_create_policy_or_sign(FAPI_CONTEXT *context)
+ \fn test_fapi_key_create_policy_nv_sign(FAPI_CONTEXT *context)
+ \fn test_fapi_nv_extend(FAPI_CONTEXT *context)
+ \fn test_fapi_ext_public_key(FAPI_CONTEXT *context)
+ \fn test_fapi_get_platform_certificates(FAPI_CONTEXT *context)
+ \fn test_fapi_seal(FAPI_CONTEXT *context)
+ \fn test_fapi_key_create_sign_policy_provision(FAPI_CONTEXT *context)
+ \fn test_fapi_key_create(FAPI_CONTEXT *context)
+ \fn test_fapi_key_create_policy_pcr_sign(FAPI_CONTEXT *context)
+ \}
+*/
diff --git a/include/tss2/tss2_common.h b/include/tss2/tss2_common.h
index 587866d..9206ba2 100644
--- a/include/tss2/tss2_common.h
+++ b/include/tss2/tss2_common.h
@@ -95,6 +95,30 @@
 #define TSS2_BASE_RC_MULTIPLE_DECRYPT_SESSIONS 25U /* More than one session with TPMA_SESSION_DECRYPT bit set */
 #define TSS2_BASE_RC_MULTIPLE_ENCRYPT_SESSIONS 26U /* More than one session with TPMA_SESSION_ENCRYPT bit set */
 #define TSS2_BASE_RC_RSP_AUTH_FAILED           27U /* Response HMAC from TPM did not verify */
+#define TSS2_BASE_RC_NO_CONFIG                 28U
+#define TSS2_BASE_RC_BAD_PATH                  29U
+#define TSS2_BASE_RC_NOT_DELETABLE             30U
+#define TSS2_BASE_RC_PATH_ALREADY_EXISTS       31U
+#define TSS2_BASE_RC_KEY_NOT_FOUND             32U
+#define TSS2_BASE_RC_SIGNATURE_VERIFICATION_FAILED 33U
+#define TSS2_BASE_RC_HASH_MISMATCH             34U
+#define TSS2_BASE_RC_KEY_NOT_DUPLICABLE        35U
+#define TSS2_BASE_RC_PATH_NOT_FOUND            36U
+#define TSS2_BASE_RC_NO_CERT                   37U
+#define TSS2_BASE_RC_NO_PCR                    38U
+#define TSS2_BASE_RC_PCR_NOT_RESETTABLE        39U
+#define TSS2_BASE_RC_BAD_TEMPLATE              40U
+#define TSS2_BASE_RC_AUTHORIZATION_FAILED      41U
+#define TSS2_BASE_RC_AUTHORIZATION_UNKNOWN     42U
+#define TSS2_BASE_RC_NV_NOT_READABLE           43U
+#define TSS2_BASE_RC_NV_TOO_SMALL              44U
+#define TSS2_BASE_RC_NV_NOT_WRITEABLE          45U
+#define TSS2_BASE_RC_POLICY_UNKNOWN            46U
+#define TSS2_BASE_RC_NV_WRONG_TYPE             47U
+#define TSS2_BASE_RC_NAME_ALREADY_EXISTS       48U
+#define TSS2_BASE_RC_NO_TPM                    49U
+#define TSS2_BASE_RC_BAD_KEY                   50U
+#define TSS2_BASE_RC_NO_HANDLE                 51U
 
 /* Base return codes in the range 0xf800 - 0xffff are reserved for
  * implementation-specific purposes.
@@ -228,4 +252,76 @@
 #define TSS2_ESYS_RC_RSP_AUTH_FAILED             ((TSS2_RC)(TSS2_ESAPI_RC_LAYER | \
                                                         TSS2_BASE_RC_RSP_AUTH_FAILED))
 
+/* FAPI Error Codes */
+
+#define TSS2_FAPI_RC_GENERAL_FAILURE             ((TSS2_RC)(TSS2_FEATURE_RC_LAYER | \
+                                                      TSS2_BASE_RC_GENERAL_FAILURE))
+#define TSS2_FAPI_RC_NOT_IMPLEMENTED             ((TSS2_RC)(TSS2_FEATURE_RC_LAYER | \
+                                                      TSS2_BASE_RC_NOT_IMPLEMENTED))
+#define TSS2_FAPI_RC_BAD_REFERENCE               ((TSS2_RC)(TSS2_FEATURE_RC_LAYER | \
+                                                      TSS2_BASE_RC_BAD_REFERENCE))
+#define TSS2_FAPI_RC_BAD_SEQUENCE                ((TSS2_RC)(TSS2_FEATURE_RC_LAYER | \
+                                                      TSS2_BASE_RC_BAD_SEQUENCE))
+#define TSS2_FAPI_RC_IO_ERROR                    ((TSS2_RC)(TSS2_FEATURE_RC_LAYER | \
+                                                      TSS2_BASE_RC_IO_ERROR))
+#define TSS2_FAPI_RC_BAD_VALUE                   ((TSS2_RC)(TSS2_FEATURE_RC_LAYER | \
+                                                      TSS2_BASE_RC_BAD_VALUE))
+#define TSS2_FAPI_RC_NO_DECRYPT_PARAM            ((TSS2_RC)(TSS2_FEATURE_RC_LAYER | \
+                                                      TSS2_BASE_RC_NO_DECRYPT_PARAM))
+#define TSS2_FAPI_RC_NO_ENCRYPT_PARAM            ((TSS2_RC)(TSS2_FEATURE_RC_LAYER | \
+                                                      TSS2_BASE_RC_NO_ENCRYPT_PARAM))
+#define TSS2_FAPI_RC_MEMORY                      ((TSS2_RC)(TSS2_FEATURE_RC_LAYER | \
+                                                      TSS2_BASE_RC_MEMORY))
+#define TSS2_FAPI_RC_BAD_CONTEXT                 ((TSS2_RC)(TSS2_FEATURE_RC_LAYER | \
+                                                        TSS2_BASE_RC_BAD_CONTEXT))
+#define TSS2_FAPI_RC_NO_CONFIG                   ((TSS2_RC)(TSS2_FEATURE_RC_LAYER | \
+                                                        TSS2_BASE_RC_NO_CONFIG))
+#define TSS2_FAPI_RC_BAD_PATH                    ((TSS2_RC)(TSS2_FEATURE_RC_LAYER | \
+                                                        TSS2_BASE_RC_BAD_PATH))
+#define TSS2_FAPI_RC_NOT_DELETABLE               ((TSS2_RC)(TSS2_FEATURE_RC_LAYER | \
+                                                        TSS2_BASE_RC_NOT_DELETABLE))
+#define TSS2_FAPI_RC_PATH_ALREADY_EXISTS         ((TSS2_RC)(TSS2_FEATURE_RC_LAYER | \
+                                                        TSS2_BASE_RC_PATH_ALREADY_EXISTS))
+#define TSS2_FAPI_RC_KEY_NOT_FOUND               ((TSS2_RC)(TSS2_FEATURE_RC_LAYER | \
+                                                        TSS2_BASE_RC_KEY_NOT_FOUND))
+#define TSS2_FAPI_RC_SIGNATURE_VERIFICATION_FAILED ((TSS2_RC)(TSS2_FEATURE_RC_LAYER | \
+                                                        TSS2_BASE_RC_SIGNATURE_VERIFICATION_FAILED))
+#define TSS2_FAPI_RC_HASH_MISMATCH               ((TSS2_RC)(TSS2_FEATURE_RC_LAYER | \
+                                                        TSS2_BASE_RC_HASH_MISMATCH))
+#define TSS2_FAPI_RC_KEY_NOT_DUPLICABLE          ((TSS2_RC)(TSS2_FEATURE_RC_LAYER | \
+                                                        TSS2_BASE_RC_KEY_NOT_DUPLICABLE))
+#define TSS2_FAPI_RC_PATH_NOT_FOUND              ((TSS2_RC)(TSS2_FEATURE_RC_LAYER | \
+                                                        TSS2_BASE_RC_PATH_NOT_FOUND))
+#define TSS2_FAPI_RC_NO_CERT                     ((TSS2_RC)(TSS2_FEATURE_RC_LAYER | \
+                                                        TSS2_BASE_RC_NO_CERT))
+#define TSS2_FAPI_RC_NO_PCR                      ((TSS2_RC)(TSS2_FEATURE_RC_LAYER | \
+                                                        TSS2_BASE_RC_NO_PCR))
+#define TSS2_FAPI_RC_PCR_NOT_RESETTABLE          ((TSS2_RC)(TSS2_FEATURE_RC_LAYER | \
+                                                        TSS2_BASE_RC_PCR_NOT_RESETTABLE))
+#define TSS2_FAPI_RC_BAD_TEMPLATE                ((TSS2_RC)(TSS2_FEATURE_RC_LAYER | \
+                                                        TSS2_BASE_RC_BAD_TEMPLATE))
+#define TSS2_FAPI_RC_AUTHORIZATION_FAILED        ((TSS2_RC)(TSS2_FEATURE_RC_LAYER | \
+                                                        TSS2_BASE_RC_AUTHORIZATION_FAILED))
+#define TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN       ((TSS2_RC)(TSS2_FEATURE_RC_LAYER | \
+                                                        TSS2_BASE_RC_AUTHORIZATION_UNKNOWN))
+#define TSS2_FAPI_RC_NV_NOT_READABLE             ((TSS2_RC)(TSS2_FEATURE_RC_LAYER | \
+                                                        TSS2_BASE_RC_NV_NOT_READABLE))
+#define TSS2_FAPI_RC_NV_TOO_SMALL                ((TSS2_RC)(TSS2_FEATURE_RC_LAYER | \
+                                                        TSS2_BASE_RC_NV_TOO_SMALL))
+#define TSS2_FAPI_RC_NV_NOT_WRITEABLE            ((TSS2_RC)(TSS2_FEATURE_RC_LAYER | \
+                                                        TSS2_BASE_RC_NV_NOT_WRITEABLE))
+#define TSS2_FAPI_RC_POLICY_UNKNOWN              ((TSS2_RC)(TSS2_FEATURE_RC_LAYER | \
+                                                        TSS2_BASE_RC_POLICY_UNKNOWN))
+#define TSS2_FAPI_RC_NV_WRONG_TYPE               ((TSS2_RC)(TSS2_FEATURE_RC_LAYER | \
+                                                        TSS2_BASE_RC_NV_WRONG_TYPE))
+#define TSS2_FAPI_RC_NAME_ALREADY_EXISTS         ((TSS2_RC)(TSS2_FEATURE_RC_LAYER | \
+                                                        TSS2_BASE_RC_NAME_ALREADY_EXISTS))
+#define TSS2_FAPI_RC_NO_TPM                      ((TSS2_RC)(TSS2_FEATURE_RC_LAYER | \
+                                                        TSS2_BASE_RC_NO_TPM))
+#define TSS2_FAPI_RC_TRY_AGAIN                   ((TSS2_RC)(TSS2_FEATURE_RC_LAYER | \
+                                                        TSS2_BASE_RC_TRY_AGAIN))
+#define TSS2_FAPI_RC_BAD_KEY                     ((TSS2_RC)(TSS2_FEATURE_RC_LAYER | \
+                                                        TSS2_BASE_RC_BAD_KEY))
+#define TSS2_FAPI_RC_NO_HANDLE                   ((TSS2_RC)(TSS2_FEATURE_RC_LAYER | \
+                                                        TSS2_BASE_RC_NO_HANDLE))
 #endif /* TSS2_COMMON_H */
diff --git a/include/tss2/tss2_fapi.h b/include/tss2/tss2_fapi.h
new file mode 100644
index 0000000..c706f6e
--- /dev/null
+++ b/include/tss2/tss2_fapi.h
@@ -0,0 +1,706 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ *******************************************************************************/
+#ifndef TSS2_FAPI_H
+#define TSS2_FAPI_H
+
+#include "tss2_tcti.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Type definitions */
+
+typedef struct FAPI_CONTEXT FAPI_CONTEXT;
+
+/* Context functions */
+
+TSS2_RC Fapi_Initialize(
+    FAPI_CONTEXT  **context,
+    char     const *uri);
+
+TSS2_RC Fapi_Initialize_Async(
+    FAPI_CONTEXT  **context,
+    char     const *uri);
+
+TSS2_RC Fapi_Initialize_Finish(
+    FAPI_CONTEXT  **context);
+
+void Fapi_Finalize(
+    FAPI_CONTEXT  **context);
+
+TSS2_RC Fapi_GetTcti(
+    FAPI_CONTEXT       *context,
+    TSS2_TCTI_CONTEXT **tcti);
+
+void Fapi_Free(
+    void           *ptr);
+
+#if defined(__linux__) || defined(__unix__) || defined(__APPLE__) || defined (__QNXNTO__) || defined (__VXWORKS__)
+#if defined (__VXWORKS__)
+#include <sys/poll.h>
+#else
+#include <poll.h>
+#endif
+typedef struct pollfd FAPI_POLL_HANDLE;
+#elif defined(_WIN32)
+#include <windows.h>
+typedef HANDLE FAPI_POLL_HANDLE;
+#else
+typedef void FAPI_POLL_HANDLE;
+#ifndef FAPI_SUPPRESS_POLL_WARNINGS
+#pragma message "Info: Platform not supported for FAPI_POLL_HANDLES"
+#endif
+#endif
+
+TSS2_RC Fapi_GetPollHandles(
+    FAPI_CONTEXT      *context,
+    FAPI_POLL_HANDLE **handles,
+    size_t            *num_handles);
+
+TSS2_RC Fapi_GetInfo(
+    FAPI_CONTEXT   *context,
+    char          **info);
+
+TSS2_RC Fapi_GetInfo_Async(
+    FAPI_CONTEXT   *context);
+
+TSS2_RC Fapi_GetInfo_Finish(
+    FAPI_CONTEXT   *context,
+    char          **info);
+
+/* General functions */
+
+TSS2_RC Fapi_Provision(
+    FAPI_CONTEXT   *context,
+    char     const *authValueEh,
+    char     const *authValueSh,
+    char     const *authValueLockout);
+
+TSS2_RC Fapi_Provision_Async(
+    FAPI_CONTEXT   *context,
+    char     const *authValueEh,
+    char     const *authValueSh,
+    char     const *authValueLockout);
+
+TSS2_RC Fapi_Provision_Finish(
+    FAPI_CONTEXT   *context);
+
+TSS2_RC Fapi_GetPlatformCertificates(
+    FAPI_CONTEXT   *context,
+    uint8_t       **certificates,
+    size_t         *certificatesSize);
+
+TSS2_RC Fapi_GetPlatformCertificates_Async(
+    FAPI_CONTEXT   *context);
+
+TSS2_RC Fapi_GetPlatformCertificates_Finish(
+    FAPI_CONTEXT   *context,
+    uint8_t       **certificates,
+    size_t         *certificatesSize);
+
+TSS2_RC Fapi_GetRandom(
+    FAPI_CONTEXT   *context,
+    size_t          numBytes,
+    uint8_t       **data);
+
+TSS2_RC Fapi_GetRandom_Async(
+    FAPI_CONTEXT   *context,
+    size_t          numBytes);
+
+TSS2_RC Fapi_GetRandom_Finish(
+    FAPI_CONTEXT   *context,
+    uint8_t       **data);
+
+TSS2_RC Fapi_Import(
+    FAPI_CONTEXT   *context,
+    char     const *path,
+    char     const *importData);
+
+TSS2_RC Fapi_Import_Async(
+    FAPI_CONTEXT   *context,
+    char     const *path,
+    char     const *importData);
+
+TSS2_RC Fapi_Import_Finish(
+    FAPI_CONTEXT   *context);
+
+TSS2_RC Fapi_List(
+    FAPI_CONTEXT   *context,
+    char     const *searchPath,
+    char          **pathList);
+
+TSS2_RC Fapi_List_Async(
+    FAPI_CONTEXT   *context,
+    char     const *searchPath);
+
+TSS2_RC Fapi_List_Finish(
+    FAPI_CONTEXT   *context,
+    char          **pathList);
+
+TSS2_RC Fapi_Delete(
+    FAPI_CONTEXT   *context,
+    char     const *path);
+
+TSS2_RC Fapi_Delete_Async(
+    FAPI_CONTEXT   *context,
+    char     const *path);
+
+TSS2_RC Fapi_Delete_Finish(
+    FAPI_CONTEXT   *context);
+
+TSS2_RC Fapi_ChangeAuth(
+    FAPI_CONTEXT   *context,
+    char     const *entityPath,
+    char     const *authValue);
+
+TSS2_RC Fapi_ChangeAuth_Async(
+    FAPI_CONTEXT   *context,
+    char     const *entityPath,
+    char     const *authValue);
+
+TSS2_RC Fapi_ChangeAuth_Finish(
+    FAPI_CONTEXT   *context);
+
+TSS2_RC Fapi_SetDescription(
+    FAPI_CONTEXT   *context,
+    char     const *path,
+    char     const *description);
+
+TSS2_RC Fapi_SetDescription_Async(
+    FAPI_CONTEXT   *context,
+    char     const *path,
+    char     const *description);
+
+TSS2_RC Fapi_SetDescription_Finish(
+    FAPI_CONTEXT   *context);
+
+TSS2_RC Fapi_GetDescription(
+    FAPI_CONTEXT   *context,
+    char     const *path,
+    char          **description);
+
+TSS2_RC Fapi_GetDescription_Async(
+    FAPI_CONTEXT   *context,
+    char     const *path);
+
+TSS2_RC Fapi_GetDescription_Finish(
+    FAPI_CONTEXT   *context,
+    char          **description);
+
+TSS2_RC Fapi_SetAppData(
+    FAPI_CONTEXT   *context,
+    char     const *path,
+    uint8_t  const *appData,
+    size_t          appDataSize);
+
+TSS2_RC Fapi_SetAppData_Async(
+    FAPI_CONTEXT   *context,
+    char     const *path,
+    uint8_t  const *appData,
+    size_t          appDataSize);
+
+TSS2_RC Fapi_SetAppData_Finish(
+    FAPI_CONTEXT   *context);
+
+TSS2_RC Fapi_GetAppData(
+    FAPI_CONTEXT   *context,
+    char     const *path,
+    uint8_t       **appData,
+    size_t         *appDataSize);
+
+TSS2_RC Fapi_GetAppData_Async(
+    FAPI_CONTEXT   *context,
+    char     const *path);
+
+TSS2_RC Fapi_GetAppData_Finish(
+    FAPI_CONTEXT   *context,
+    uint8_t       **appData,
+    size_t         *appDataSize);
+
+TSS2_RC Fapi_GetTpmBlobs(
+    FAPI_CONTEXT   *context,
+    char     const *path,
+    uint8_t       **tpm2bPublic,
+    size_t         *tpm2bPublicSize,
+    uint8_t       **tpm2bPrivate,
+    size_t         *tpm2bPrivateSize,
+    char          **policy);
+
+TSS2_RC Fapi_GetTpmBlobs_Async(
+    FAPI_CONTEXT   *context,
+    char     const *path);
+
+TSS2_RC Fapi_GetTpmBlobs_Finish(
+    FAPI_CONTEXT   *context,
+    uint8_t       **tpm2bPublic,
+    size_t         *tpm2bPublicSize,
+    uint8_t       **tpm2bPrivate,
+    size_t         *tpm2bPrivateSize,
+    char          **policy);
+
+/* Key functions */
+
+TSS2_RC Fapi_CreateKey(
+    FAPI_CONTEXT   *context,
+    char     const *path,
+    char     const *type,
+    char     const *policyPath,
+    char     const *authValue);
+
+TSS2_RC Fapi_CreateKey_Async(
+    FAPI_CONTEXT   *context,
+    char     const *path,
+    char     const *type,
+    char     const *policyPath,
+    char     const *authValue);
+
+TSS2_RC Fapi_CreateKey_Finish(
+    FAPI_CONTEXT   *context);
+
+TSS2_RC Fapi_Sign(
+    FAPI_CONTEXT   *context,
+    char     const *keyPath,
+    char     const *padding,
+    uint8_t  const *digest,
+    size_t          digestSize,
+    uint8_t       **signature,
+    size_t         *signatureSize,
+    char          **publicKey,
+    char          **certificate);
+
+TSS2_RC Fapi_Sign_Async(
+    FAPI_CONTEXT   *context,
+    char     const *keyPath,
+    char     const *padding,
+    uint8_t  const *digest,
+    size_t         digestSize);
+
+TSS2_RC Fapi_Sign_Finish(
+    FAPI_CONTEXT   *context,
+    uint8_t       **signature,
+    size_t         *signatureSize,
+    char          **publicKey,
+    char          **certificate);
+
+TSS2_RC Fapi_VerifySignature(
+    FAPI_CONTEXT   *context,
+    char     const *keyPath,
+    uint8_t  const *digest,
+    size_t          digestSize,
+    uint8_t  const *signature,
+    size_t          signatureSize);
+
+TSS2_RC Fapi_VerifySignature_Async(
+    FAPI_CONTEXT   *context,
+    char     const *keyPath,
+    uint8_t  const *digest,
+    size_t          digestSize,
+    uint8_t  const *signature,
+    size_t          signatureSize);
+
+TSS2_RC Fapi_VerifySignature_Finish(
+    FAPI_CONTEXT   *context);
+
+TSS2_RC Fapi_Encrypt(
+    FAPI_CONTEXT   *context,
+    char     const *keyPath,
+    char     const *policyPath,
+    uint8_t  const *plainText,
+    size_t          plainTextSize,
+    char          **cipherText);
+
+TSS2_RC Fapi_Encrypt_Async(
+    FAPI_CONTEXT   *context,
+    char     const *keyPath,
+    char     const *policyPath,
+    uint8_t  const *plainText,
+    size_t          plainTextSize);
+
+TSS2_RC Fapi_Encrypt_Finish(
+    FAPI_CONTEXT   *context,
+    char          **cipherText);
+
+TSS2_RC Fapi_Decrypt(
+    FAPI_CONTEXT   *context,
+    char     const *cipherText,
+    uint8_t       **plainText,
+    size_t         *plainTextSize);
+
+TSS2_RC Fapi_Decrypt_Async(
+    FAPI_CONTEXT   *context,
+    char     const *cipherText);
+
+TSS2_RC Fapi_Decrypt_Finish(
+    FAPI_CONTEXT   *context,
+    uint8_t       **plainText,
+    size_t         *plainTextSize);
+
+TSS2_RC Fapi_SetCertificate(
+    FAPI_CONTEXT   *context,
+    char     const *path,
+    char     const *x509certData);
+
+TSS2_RC Fapi_SetCertificate_Async(
+    FAPI_CONTEXT   *context,
+    char     const *path,
+    char     const *x509certData);
+
+TSS2_RC Fapi_SetCertificate_Finish(
+    FAPI_CONTEXT   *context);
+
+TSS2_RC Fapi_GetCertificate(
+    FAPI_CONTEXT   *context,
+    char     const *path,
+    char          **x509certData);
+
+TSS2_RC Fapi_GetCertificate_Async(
+    FAPI_CONTEXT   *context,
+    char     const *path);
+
+TSS2_RC Fapi_GetCertificate_Finish(
+    FAPI_CONTEXT   *context,
+    char          **x509certData);
+
+TSS2_RC Fapi_ExportKey(
+    FAPI_CONTEXT   *context,
+    char     const *pathOfKeyToDuplicate,
+    char     const *pathToPublicKeyOfNewParent,
+    char          **exportedData);
+
+TSS2_RC Fapi_ExportKey_Async(
+    FAPI_CONTEXT   *context,
+    char     const *pathOfKeyToDuplicate,
+    char     const *pathToPublicKeyOfNewParent);
+
+TSS2_RC Fapi_ExportKey_Finish(
+    FAPI_CONTEXT   *context,
+    char          **exportedData);
+
+/* Seal functions */
+
+TSS2_RC Fapi_CreateSeal(
+    FAPI_CONTEXT   *context,
+    char     const *path,
+    char     const *type,
+    size_t          size,
+    char     const *policyPath,
+    char     const *authValue,
+    uint8_t  const *data);
+
+TSS2_RC Fapi_CreateSeal_Async(
+    FAPI_CONTEXT   *context,
+    char     const *path,
+    char     const *type,
+    size_t          size,
+    char     const *policyPath,
+    char     const *authValue,
+    uint8_t  const *data);
+
+TSS2_RC Fapi_CreateSeal_Finish(
+    FAPI_CONTEXT   *context);
+
+TSS2_RC Fapi_Unseal(
+    FAPI_CONTEXT   *context,
+    char     const *path,
+    uint8_t       **data,
+    size_t         *size);
+
+TSS2_RC Fapi_Unseal_Async(
+    FAPI_CONTEXT   *context,
+    char     const *path);
+
+TSS2_RC Fapi_Unseal_Finish(
+    FAPI_CONTEXT   *context,
+    uint8_t       **data,
+    size_t         *size);
+
+/* Policy functions */
+
+TSS2_RC Fapi_ExportPolicy(
+    FAPI_CONTEXT   *context,
+    char     const *path,
+    char          **jsonPolicy);
+
+TSS2_RC Fapi_ExportPolicy_Async(
+    FAPI_CONTEXT   *context,
+    char     const *path);
+
+TSS2_RC Fapi_ExportPolicy_Finish(
+    FAPI_CONTEXT   *context,
+    char          **jsonPolicy);
+
+TSS2_RC Fapi_AuthorizePolicy(
+    FAPI_CONTEXT   *context,
+    char     const *policyPath,
+    char     const *keyPath,
+    uint8_t  const *policyRef,
+    size_t          policyRefSize);
+
+TSS2_RC Fapi_AuthorizePolicy_Async(
+    FAPI_CONTEXT   *context,
+    char     const *policyPath,
+    char     const *keyPath,
+    uint8_t  const *policyRef,
+    size_t          policyRefSize);
+
+TSS2_RC Fapi_AuthorizePolicy_Finish(
+    FAPI_CONTEXT   *context);
+
+TSS2_RC Fapi_WriteAuthorizeNv(
+    FAPI_CONTEXT   *context,
+    char     const *nvPath,
+    char     const *policyPath);
+
+TSS2_RC Fapi_WriteAuthorizeNv_Async(
+    FAPI_CONTEXT   *context,
+    char     const *nvPath,
+    char     const *policyPath);
+
+TSS2_RC Fapi_WriteAuthorizeNv_Finish(
+    FAPI_CONTEXT   *context);
+
+/* Attestation functions */
+
+TSS2_RC Fapi_PcrRead(
+    FAPI_CONTEXT   *context,
+    uint32_t        pcrIndex,
+    uint8_t       **pcrValue,
+    size_t         *pcrValueSize,
+    char          **pcrLog);
+
+TSS2_RC Fapi_PcrRead_Async(
+    FAPI_CONTEXT   *context,
+    uint32_t        pcrIndex);
+
+TSS2_RC Fapi_PcrRead_Finish(
+    FAPI_CONTEXT   *context,
+    uint8_t       **pcrValue,
+    size_t         *pcrValueSize,
+    char          **pcrLog);
+
+TSS2_RC Fapi_PcrExtend(
+    FAPI_CONTEXT   *context,
+    uint32_t        pcr,
+    uint8_t  const *data,
+    size_t          dataSize,
+    char     const *logData);
+
+TSS2_RC Fapi_PcrExtend_Async(
+    FAPI_CONTEXT   *context,
+    uint32_t        pcr,
+    uint8_t  const *data,
+    size_t          dataSize,
+    char     const *logData);
+
+TSS2_RC Fapi_PcrExtend_Finish(
+    FAPI_CONTEXT   *context);
+
+
+TSS2_RC Fapi_Quote(
+    FAPI_CONTEXT   *context,
+    uint32_t       *pcrList,
+    size_t          pcrListSize,
+    char     const *keyPath,
+    char     const *quoteType,
+    uint8_t  const *qualifyingData,
+    size_t          qualifyingDataSize,
+    char          **quoteInfo,
+    uint8_t       **signature,
+    size_t         *signatureSize,
+    char          **pcrLog,
+    char          **certificate);
+
+TSS2_RC Fapi_Quote_Async(
+    FAPI_CONTEXT   *context,
+    uint32_t       *pcrList,
+    size_t          pcrListSize,
+    char     const *keyPath,
+    char     const *quoteType,
+    uint8_t  const *qualifyingData,
+    size_t          qualifyingDataSize);
+
+TSS2_RC Fapi_Quote_Finish(
+    FAPI_CONTEXT  *context,
+    char         **quoteInfo,
+    uint8_t      **signature,
+    size_t        *signatureSize,
+    char          **pcrLog,
+    char          **certificate);
+
+TSS2_RC Fapi_VerifyQuote(
+    FAPI_CONTEXT   *context,
+    char     const *publicKeyPath,
+    uint8_t  const *qualifyingData,
+    size_t          qualifyingDataSize,
+    char     const *quoteInfo,
+    uint8_t  const *signature,
+    size_t          signatureSize,
+    char     const *pcrLog);
+
+TSS2_RC Fapi_VerifyQuote_Async(
+    FAPI_CONTEXT   *context,
+    char     const *publicKeyPath,
+    uint8_t  const *qualifyingData,
+    size_t          qualifyingDataSize,
+    char     const *quoteInfo,
+    uint8_t  const *signature,
+    size_t          signatureSize,
+    char     const *pcrLog);
+
+TSS2_RC Fapi_VerifyQuote_Finish(
+    FAPI_CONTEXT   *context);
+
+/* NV functions */
+
+TSS2_RC Fapi_CreateNv(
+    FAPI_CONTEXT *context,
+    char   const *path,
+    char   const *type,
+    size_t        size,
+    char   const *policyPath,
+    char   const *authValue);
+
+TSS2_RC Fapi_CreateNv_Async(
+    FAPI_CONTEXT *context,
+    char   const *path,
+    char   const *type,
+    size_t        size,
+    char   const *policyPath,
+    char   const *authValue);
+
+TSS2_RC Fapi_CreateNv_Finish(
+    FAPI_CONTEXT *context);
+
+TSS2_RC Fapi_NvRead(
+    FAPI_CONTEXT   *context,
+    char     const *path,
+    uint8_t      **data,
+    size_t        *size,
+    char         **logData);
+
+TSS2_RC Fapi_NvRead_Async(
+    FAPI_CONTEXT   *context,
+    char     const *path);
+
+TSS2_RC Fapi_NvRead_Finish(
+    FAPI_CONTEXT   *context,
+    uint8_t       **data,
+    size_t         *size,
+    char          **logData);
+
+TSS2_RC Fapi_NvWrite(
+    FAPI_CONTEXT  *context,
+    char    const *path,
+    uint8_t const *data,
+    size_t         size);
+
+TSS2_RC Fapi_NvWrite_Async(
+    FAPI_CONTEXT  *context,
+    char    const *path,
+    uint8_t const *data,
+    size_t         size);
+
+TSS2_RC Fapi_NvWrite_Finish(
+    FAPI_CONTEXT   *context);
+
+TSS2_RC Fapi_NvExtend(
+    FAPI_CONTEXT  *context,
+    char    const *path,
+    uint8_t const *data,
+    size_t         size,
+    char    const *logData);
+
+TSS2_RC Fapi_NvExtend_Async(
+    FAPI_CONTEXT  *context,
+    char    const *path,
+    uint8_t const *data,
+    size_t         size,
+    char    const *logData);
+
+TSS2_RC Fapi_NvExtend_Finish(
+    FAPI_CONTEXT  *context);
+
+TSS2_RC Fapi_NvIncrement(
+    FAPI_CONTEXT   *context,
+    char     const *path);
+
+TSS2_RC Fapi_NvIncrement_Async(
+    FAPI_CONTEXT   *context,
+    char     const *path);
+
+TSS2_RC Fapi_NvIncrement_Finish(
+    FAPI_CONTEXT   *context);
+
+TSS2_RC Fapi_NvSetBits(
+    FAPI_CONTEXT   *context,
+    char     const *path,
+    uint64_t        bitmap);
+
+TSS2_RC Fapi_NvSetBits_Async(
+    FAPI_CONTEXT   *context,
+    char     const *path,
+    uint64_t        bitmap);
+
+TSS2_RC Fapi_NvSetBits_Finish(
+    FAPI_CONTEXT   *context);
+
+typedef TSS2_RC (*Fapi_CB_Auth)(
+    FAPI_CONTEXT   *context,
+    char     const *description,
+    char          **auth,
+    void           *userData);
+
+TSS2_RC Fapi_SetAuthCB(
+    FAPI_CONTEXT   *context,
+    Fapi_CB_Auth    callback,
+    void           *userData);
+
+typedef TSS2_RC (*Fapi_CB_Branch)(
+    FAPI_CONTEXT   *context,
+    char     const *description,
+    char    const **branchNames,
+    size_t          numBranches,
+    size_t         *selectedBranch,
+    void           *userData);
+
+TSS2_RC Fapi_SetBranchCB(
+    FAPI_CONTEXT   *context,
+    Fapi_CB_Branch  callback,
+    void           *userData);
+
+typedef TSS2_RC (*Fapi_CB_Sign)(
+    FAPI_CONTEXT   *context,
+    char     const *description,
+    char     const *publicKey,
+    char     const *publicKeyHint,
+    uint32_t        hashAlg,
+    uint8_t  const *dataToSign,
+    size_t          dataToSignSize,
+    uint8_t       **signature,
+    size_t         *signatureSize,
+    void           *userData);
+
+TSS2_RC Fapi_SetSignCB(
+    FAPI_CONTEXT   *context,
+    Fapi_CB_Sign    callback,
+    void           *userData);
+
+typedef TSS2_RC (*Fapi_CB_PolicyAction)(
+    FAPI_CONTEXT   *context,
+    char     const *action,
+    void           *userData);
+
+TSS2_RC Fapi_SetPolicyActionCB(
+    FAPI_CONTEXT        *context,
+    Fapi_CB_PolicyAction callback,
+    void                *userData);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TSS2_FAPI_H */
diff --git a/include/tss2/tss2_tpm2_types.h b/include/tss2/tss2_tpm2_types.h
index 69063cb..cfc92f7 100644
--- a/include/tss2/tss2_tpm2_types.h
+++ b/include/tss2/tss2_tpm2_types.h
@@ -71,6 +71,7 @@
 
 #define TPM2_ALG_ERROR               ((TPM2_ALG_ID) 0x0000)
 #define TPM2_ALG_RSA                 ((TPM2_ALG_ID) 0x0001)
+#define TPM2_ALG_TDES                ((TPM2_ALG_ID) 0x0003)
 #define TPM2_ALG_SHA                 ((TPM2_ALG_ID) 0x0004)
 #define TPM2_ALG_SHA1                ((TPM2_ALG_ID) 0x0004)
 #define TPM2_ALG_HMAC                ((TPM2_ALG_ID) 0x0005)
@@ -513,6 +514,7 @@
 #define TPM2_PT_VENDOR_COMMANDS          ((TPM2_PT) (TPM2_PT_FIXED + 43)) /* number of vendor commands that are implemented */
 #define TPM2_PT_NV_BUFFER_MAX            ((TPM2_PT) (TPM2_PT_FIXED + 44)) /* the maximum data size in one NV write command */
 #define TPM2_PT_MODES                    ((TPM2_PT) (TPM2_PT_FIXED + 45)) /* a TPMA_MODES value indicating that the TPM is designed for these modes. */
+#define TPM2_PT_MAX_CAP_BUFFER           ((TPM2_PT) (TPM2_PT_FIXED + 46)) /* the maximum size of a TPMS_CAPABILITY_DATA structure returned in TPM2_GetCapability(). */
 #define TPM2_PT_VAR                      ((TPM2_PT) (TPM2_PT_GROUP * 2)) /* the group of variable properties returned as TPMS_TAGGED_PROPERTY. The properties in this group change because of a Protected Capability other than a firmware update. The values are not necessarily persistent across all power transitions. */
 #define TPM2_PT_PERMANENT                ((TPM2_PT) (TPM2_PT_VAR + 0)) /* TPMA_PERMANENT */
 #define TPM2_PT_STARTUP_CLEAR            ((TPM2_PT) (TPM2_PT_VAR + 1)) /* TPMA_STARTUP_CLEAR */
@@ -538,7 +540,7 @@
 
 /* Definition of UINT32 TPM2_PT_PCR Constants <INOUT S> */
 typedef UINT32 TPM2_PT_PCR;
-#define TPM2_PT_TPM2_PCR_FIRST   ((TPM2_PT_PCR) 0x00000000) /* bottom of the range of TPM2_PT_PCR properties */
+#define TPM2_PT_TPM2_PCR_FIRST        ((TPM2_PT_PCR) 0x00000000) /* bottom of the range of TPM2_PT_PCR properties */
 #define TPM2_PT_PCR_SAVE         ((TPM2_PT_PCR) 0x00000000) /* a SET bit in the TPMS_PCR_SELECT indicates that the PCR is saved and restored by TPM2_SU_STATE */
 #define TPM2_PT_PCR_EXTEND_L0    ((TPM2_PT_PCR) 0x00000001) /* a SET bit in the TPMS_PCR_SELECT indicates that the PCR may be extended from locality 0This property is only present if a locality other than 0 is implemented. */
 #define TPM2_PT_PCR_RESET_L0     ((TPM2_PT_PCR) 0x00000002) /* a SET bit in the TPMS_PCR_SELECT indicates that the PCR may be reset by TPM2_PCR_Reset from locality 0 */
@@ -560,7 +562,7 @@
 #define TPM2_PT_PCR_DRTM_RESET   ((TPM2_PT_PCR) 0x00000012) /* a SET bit in the TPMS_PCR_SELECT indicates that the PCR is reset by a DRTM event. These PCR are reset to 1 on TPM2_Startup and reset to 0 on a _TPM_Hash_End event following a _TPM_Hash_Start event. */
 #define TPM2_PT_PCR_POLICY       ((TPM2_PT_PCR) 0x00000013) /* a SET bit in the TPMS_PCR_SELECT indicates that the PCR is controlled by policy. This property is only present if the TPM supports policy control of a PCR. */
 #define TPM2_PT_PCR_AUTH         ((TPM2_PT_PCR) 0x00000014) /* a SET bit in the TPMS_PCR_SELECT indicates that the PCR is controlled by an authorization value. This property is only present if the TPM supports authorization control of a PCR. */
-#define TPM2_PT_TPM2_PCR_LAST    ((TPM2_PT_PCR) 0x00000014) /* top of the range of TPM2_PT_PCR properties of the implementation. If the TPM receives a request for a PCR property with a value larger than this the TPM will return a zero length list and set the moreData parameter to NO. NOTE This is an implementation-specific value. The value shown reflects the reference code implementation. */
+#define TPM2_PT_TPM2_PCR_LAST         ((TPM2_PT_PCR) 0x00000014) /* top of the range of TPM2_PT_PCR properties of the implementation. If the TPM receives a request for a PCR property with a value larger than this the TPM will return a zero length list and set the moreData parameter to NO. NOTE This is an implementation-specific value. The value shown reflects the reference code implementation. */
 /* NOTE: The following values are reserved:
  * 0x00000015 is reserved for the next 2nd TPM2_PT_PCR_POLICY set.
  * 0x00000016 is reserved for the next 2nd TPM2_PT_PCR_AUTH set.
diff --git a/lib/tss2-fapi.def b/lib/tss2-fapi.def
new file mode 100644
index 0000000..04559ab
--- /dev/null
+++ b/lib/tss2-fapi.def
@@ -0,0 +1,121 @@
+LIBRARY tss2-fapi
+EXPORTS
+    Fapi_Initialize
+    Fapi_Initialize_Async
+    Fapi_Initialize_Finish
+    Fapi_Finalize
+    Fapi_Free
+    Fapi_GetTcti
+    Fapi_GetPollHandles
+    Fapi_GetInfo
+    Fapi_GetInfo_Async
+    Fapi_GetInfo_Finish
+    Fapi_Provision
+    Fapi_Provision_Async
+    Fapi_Provision_Finish
+    Fapi_GetPlatformCertificates
+    Fapi_GetPlatformCertificates_Async
+    Fapi_GetPlatformCertificates_Finish
+    Fapi_GetRandom
+    Fapi_GetRandom_Async
+    Fapi_GetRandom_Finish
+    Fapi_Import
+    Fapi_Import_Async
+    Fapi_Import_Finish
+    Fapi_List
+    Fapi_List_Async
+    Fapi_List_Finish
+    Fapi_Delete
+    Fapi_Delete_Async
+    Fapi_Delete_Finish
+    Fapi_ChangeAuth
+    Fapi_ChangeAuth_Async
+    Fapi_ChangeAuth_Finish
+    Fapi_SetDescription
+    Fapi_SetDescription_Async
+    Fapi_SetDescription_Finish
+    Fapi_GetDescription
+    Fapi_GetDescription_Async
+    Fapi_GetDescription_Finish
+    Fapi_SetAppData
+    Fapi_SetAppData_Async
+    Fapi_SetAppData_Finish
+    Fapi_GetAppData
+    Fapi_GetAppData_Async
+    Fapi_GetAppData_Finish
+    Fapi_GetTpmBlobs
+    Fapi_GetTpmBlobs_Async
+    Fapi_GetTpmBlobs_Finish
+    Fapi_CreateKey
+    Fapi_CreateKey_Async
+    Fapi_CreateKey_Finish
+    Fapi_Sign
+    Fapi_Sign_Async
+    Fapi_Sign_Finish
+    Fapi_VerifySignature
+    Fapi_VerifySignature_Async
+    Fapi_VerifySignature_Finish
+    Fapi_Encrypt
+    Fapi_Encrypt_Async
+    Fapi_Encrypt_Finish
+    Fapi_Decrypt
+    Fapi_Decrypt_Async
+    Fapi_Decrypt_Finish
+    Fapi_SetCertificate
+    Fapi_SetCertificate_Async
+    Fapi_SetCertificate_Finish
+    Fapi_GetCertificate
+    Fapi_GetCertificate_Async
+    Fapi_GetCertificate_Finish
+    Fapi_ExportKey
+    Fapi_ExportKey_Async
+    Fapi_ExportKey_Finish
+    Fapi_CreateSeal
+    Fapi_CreateSeal_Async
+    Fapi_CreateSeal_Finish
+    Fapi_Unseal
+    Fapi_Unseal_Async
+    Fapi_Unseal_Finish
+    Fapi_ExportPolicy
+    Fapi_ExportPolicy_Async
+    Fapi_ExportPolicy_Finish
+    Fapi_AuthorizePolicy
+    Fapi_AuthorizePolicy_Async
+    Fapi_AuthorizePolicy_Finish
+    Fapi_WriteAuthorizeNv
+    Fapi_WriteAuthorizeNv_Async
+    Fapi_WriteAuthorizeNv_Finish
+    Fapi_PcrRead
+    Fapi_PcrRead_Async
+    Fapi_PcrRead_Finish
+    Fapi_PcrExtend
+    Fapi_PcrExtend_Async
+    Fapi_PcrExtend_Finish
+    Fapi_Quote
+    Fapi_Quote_Async
+    Fapi_Quote_Finish
+    Fapi_VerifyQuote
+    Fapi_VerifyQuote_Async
+    Fapi_VerifyQuote_Finish
+    Fapi_CreateNv
+    Fapi_CreateNv_Async
+    Fapi_CreateNv_Finish
+    Fapi_NvRead
+    Fapi_NvRead_Async
+    Fapi_NvRead_Finish
+    Fapi_NvWrite
+    Fapi_NvWrite_Async
+    Fapi_NvWrite_Finish
+    Fapi_NvExtend
+    Fapi_NvExtend_Async
+    Fapi_NvExtend_Finish
+    Fapi_NvIncrement
+    Fapi_NvIncrement_Async
+    Fapi_NvIncrement_Finish
+    Fapi_NvSetBits
+    Fapi_NvSetBits_Async
+    Fapi_NvSetBits_Finish
+    Fapi_SetAuthCB
+    Fapi_SetBranchCB
+    Fapi_SetSignCB
+    Fapi_SetPolicyActionCB
diff --git a/lib/tss2-fapi.map b/lib/tss2-fapi.map
new file mode 100644
index 0000000..b1b1e31
--- /dev/null
+++ b/lib/tss2-fapi.map
@@ -0,0 +1,124 @@
+{
+    global:
+        Fapi_Initialize;
+        Fapi_Initialize_Async;
+        Fapi_Initialize_Finish;
+        Fapi_Finalize;
+        Fapi_Free;
+        Fapi_GetTcti;
+        Fapi_GetPollHandles;
+        Fapi_GetInfo;
+        Fapi_GetInfo_Async;
+        Fapi_GetInfo_Finish;
+        Fapi_Provision;
+        Fapi_Provision_Async;
+        Fapi_Provision_Finish;
+        Fapi_GetPlatformCertificates;
+        Fapi_GetPlatformCertificates_Async;
+        Fapi_GetPlatformCertificates_Finish;
+        Fapi_GetRandom;
+        Fapi_GetRandom_Async;
+        Fapi_GetRandom_Finish;
+        Fapi_Import;
+        Fapi_Import_Async;
+        Fapi_Import_Finish;
+        Fapi_List;
+        Fapi_List_Async;
+        Fapi_List_Finish;
+        Fapi_Delete;
+        Fapi_Delete_Async;
+        Fapi_Delete_Finish;
+        Fapi_ChangeAuth;
+        Fapi_ChangeAuth_Async;
+        Fapi_ChangeAuth_Finish;
+        Fapi_SetDescription;
+        Fapi_SetDescription_Async;
+        Fapi_SetDescription_Finish;
+        Fapi_GetDescription;
+        Fapi_GetDescription_Async;
+        Fapi_GetDescription_Finish;
+        Fapi_SetAppData;
+        Fapi_SetAppData_Async;
+        Fapi_SetAppData_Finish;
+        Fapi_GetAppData;
+        Fapi_GetAppData_Async;
+        Fapi_GetAppData_Finish;
+        Fapi_GetTpmBlobs;
+        Fapi_GetTpmBlobs_Async;
+        Fapi_GetTpmBlobs_Finish;
+        Fapi_CreateKey;
+        Fapi_CreateKey_Async;
+        Fapi_CreateKey_Finish;
+        Fapi_Sign;
+        Fapi_Sign_Async;
+        Fapi_Sign_Finish;
+        Fapi_VerifySignature;
+        Fapi_VerifySignature_Async;
+        Fapi_VerifySignature_Finish;
+        Fapi_Encrypt;
+        Fapi_Encrypt_Async;
+        Fapi_Encrypt_Finish;
+        Fapi_Decrypt;
+        Fapi_Decrypt_Async;
+        Fapi_Decrypt_Finish;
+        Fapi_SetCertificate;
+        Fapi_SetCertificate_Async;
+        Fapi_SetCertificate_Finish;
+        Fapi_GetCertificate;
+        Fapi_GetCertificate_Async;
+        Fapi_GetCertificate_Finish;
+        Fapi_ExportKey;
+        Fapi_ExportKey_Async;
+        Fapi_ExportKey_Finish;
+        Fapi_CreateSeal;
+        Fapi_CreateSeal_Async;
+        Fapi_CreateSeal_Finish;
+        Fapi_Unseal;
+        Fapi_Unseal_Async;
+        Fapi_Unseal_Finish;
+        Fapi_ExportPolicy;
+        Fapi_ExportPolicy_Async;
+        Fapi_ExportPolicy_Finish;
+        Fapi_AuthorizePolicy;
+        Fapi_AuthorizePolicy_Async;
+        Fapi_AuthorizePolicy_Finish;
+        Fapi_WriteAuthorizeNv;
+        Fapi_WriteAuthorizeNv_Async;
+        Fapi_WriteAuthorizeNv_Finish;
+        Fapi_PcrRead;
+        Fapi_PcrRead_Async;
+        Fapi_PcrRead_Finish;
+        Fapi_PcrExtend;
+        Fapi_PcrExtend_Async;
+        Fapi_PcrExtend_Finish;
+        Fapi_Quote;
+        Fapi_Quote_Async;
+        Fapi_Quote_Finish;
+        Fapi_VerifyQuote;
+        Fapi_VerifyQuote_Async;
+        Fapi_VerifyQuote_Finish;
+        Fapi_CreateNv;
+        Fapi_CreateNv_Async;
+        Fapi_CreateNv_Finish;
+        Fapi_NvRead;
+        Fapi_NvRead_Async;
+        Fapi_NvRead_Finish;
+        Fapi_NvWrite;
+        Fapi_NvWrite_Async;
+        Fapi_NvWrite_Finish;
+        Fapi_NvExtend;
+        Fapi_NvExtend_Async;
+        Fapi_NvExtend_Finish;
+        Fapi_NvIncrement;
+        Fapi_NvIncrement_Async;
+        Fapi_NvIncrement_Finish;
+        Fapi_NvSetBits;
+        Fapi_NvSetBits_Async;
+        Fapi_NvSetBits_Finish;
+        Fapi_SetAuthCB;
+        Fapi_SetBranchCB;
+        Fapi_SetSignCB;
+        Fapi_SetPolicyActionCB;
+    local:
+        *;
+};
diff --git a/lib/tss2-fapi.pc.in b/lib/tss2-fapi.pc.in
new file mode 100644
index 0000000..8fcc5cd
--- /dev/null
+++ b/lib/tss2-fapi.pc.in
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: tss2-FAPI
+Description: TPM2 Feature API library.
+URL: https://github.com/tpm2-software/tpm2-tss
+Version: @VERSION@
+Requires: tss2-mu tss2-esys tss2-tctildr
+Cflags: -I${includedir}
+Libs: -ltss2-fapi -L${libdir}
diff --git a/script/ekca/create_ca.sh b/script/ekca/create_ca.sh
new file mode 100755
index 0000000..aac18f4
--- /dev/null
+++ b/script/ekca/create_ca.sh
@@ -0,0 +1,185 @@
+#!/bin/bash
+
+# set -x
+
+set -euf
+
+echo "Creating ekcert for $1 => $3"
+echo "Creating ekcert for $2 => $4"
+
+EKCADIR="$(dirname $(realpath ${0}))/"
+
+CA_DIR="$(mktemp -d ekca-XXXXXX)"
+
+pushd "$CA_DIR"
+
+mkdir root-ca
+pushd root-ca
+
+mkdir certreqs certs crl newcerts private
+touch root-ca.index
+echo 00 > root-ca.crlnum
+echo 1000 > root-ca.serial
+echo "123456" > pass.txt
+
+cp "${EKCADIR}/root-ca.cnf" ./
+export OPENSSL_CONF=./root-ca.cnf
+
+openssl req -new -out root-ca.req.pem -passout file:pass.txt
+
+#openssl req -verify -in root-ca.req.pem \
+#    -noout -text \
+#    -reqopt no_version,no_pubkey,no_sigdump \
+#    -nameopt multiline -passin file:pass.txt
+
+openssl ca -selfsign \
+    -in root-ca.req.pem \
+    -out root-ca.cert.pem \
+    -extensions root-ca_ext \
+    -startdate `date +%y%m%d000000Z -u -d -1day` \
+    -enddate `date +%y%m%d000000Z -u -d +10years+1day` \
+    -passin file:pass.txt -batch
+
+#openssl x509 -in ./root-ca.cert.pem \
+#    -noout -text \
+#    -certopt no_version,no_pubkey,no_sigdump \
+#    -nameopt multiline
+
+openssl verify -verbose -CAfile root-ca.cert.pem \
+    root-ca.cert.pem
+
+popd #root-ca
+
+mkdir intermed-ca
+pushd intermed-ca
+
+mkdir certreqs certs crl newcerts private
+touch intermed-ca.index
+echo 00 > intermed-ca.crlnum
+echo 2000 > intermed-ca.serial
+echo "abcdef" > pass.txt
+
+cp "${EKCADIR}/intermed-ca.cnf" ./
+export OPENSSL_CONF=./intermed-ca.cnf
+
+openssl req -new -out intermed-ca.req.pem -passout file:pass.txt
+
+openssl req -new \
+    -key private/intermed-ca.key.pem \
+    -out intermed-ca.req.pem \
+    -passin file:pass.txt
+
+#openssl req  -verify -in intermed-ca.req.pem \
+#    -noout -text \
+#    -reqopt no_version,no_pubkey,no_sigdump \
+#    -nameopt multiline
+
+cp intermed-ca.req.pem  \
+    ../root-ca/certreqs/
+
+pushd ../root-ca
+export OPENSSL_CONF=./root-ca.cnf
+
+openssl ca \
+    -in certreqs/intermed-ca.req.pem \
+    -out certs/intermed-ca.cert.pem \
+    -extensions intermed-ca_ext \
+    -startdate `date +%y%m%d000000Z -u -d -1day` \
+    -enddate `date +%y%m%d000000Z -u -d +5years+1day` \
+    -passin file:pass.txt -batch
+
+#openssl x509 -in certs/intermed-ca.cert.pem \
+#    -noout -text \
+#    -certopt no_version,no_pubkey,no_sigdump \
+#    -nameopt multiline
+
+openssl verify -verbose -CAfile root-ca.cert.pem \
+    certs/intermed-ca.cert.pem
+
+cp certs/intermed-ca.cert.pem \
+    ../intermed-ca
+
+popd #root-ca
+
+popd #intermed-ca
+
+mkdir ek
+pushd ek
+
+cp "${EKCADIR}/ek.cnf" ./
+export OPENSSL_CONF=ek.cnf
+echo "abc123" > pass.txt
+
+cp "$1" ../intermed-ca/certreqs/ek.pub.pem
+
+openssl req -new -nodes -newkey rsa:2048 -passin file:pass.txt -out ../intermed-ca/certreqs/nonsense.csr.pem
+
+#openssl req  -verify -in ../intermed-ca/certreqs/nonsense.csr.pem \
+#    -noout -text \
+#    -reqopt no_version,no_pubkey,no_sigdump \
+#    -nameopt multiline
+
+pushd ../intermed-ca
+export OPENSSL_CONF=./intermed-ca.cnf
+
+openssl x509 -req -in certreqs/nonsense.csr.pem -force_pubkey certreqs/ek.pub.pem -out certs/ek.cert.der \
+    -outform DER -extfile ../ek/ek.cnf -extensions ek_ext -set_serial 12345 \
+    -CA intermed-ca.cert.pem -CAkey private/intermed-ca.key.pem -passin file:pass.txt
+
+#openssl x509 -req -in csrs/oemProvCertTPM.csr -extfile configs/oemProvCertTPM.cnf -extensions ext -CA certs/oemSubCA2Cert.pem -CAkey privateKeys/oemSubCA2.key -passin file:passphrase.txt -set_serial 12345 -days $validity_oem_prov_cert -force_pubkey pc.pub.pem -out certs/oemProvCertTPM.pem
+
+cp certs/ek.cert.der ../ek
+
+popd #intermed-ca
+
+#openssl x509 -in ek.cert.der -inform DER -text -noout
+#openssl rsa -in ek.pub.pem -pubin -text -noout
+#openssl asn1parse -in ek.cert.der -inform DER
+
+popd #EK
+
+# ECC Certificate
+
+mkdir ekecc
+pushd ekecc
+
+cp "${EKCADIR}/ek.cnf" ./
+export OPENSSL_CONF=ek.cnf
+echo "abc123" > pass.txt
+
+cp "$2" ../intermed-ca/certreqs/ekecc.pub.pem
+
+openssl req -new -nodes -newkey rsa:2048 -passin file:pass.txt -out ../intermed-ca/certreqs/nonsense.csr.pem
+
+#openssl req  -verify -in ../intermed-ca/certreqs/nonsense.csr.pem \
+#    -noout -text \
+#    -reqopt no_version,no_pubkey,no_sigdump \
+#    -nameopt multiline
+
+pushd ../intermed-ca
+export OPENSSL_CONF=./intermed-ca.cnf
+
+openssl x509 -req -in certreqs/nonsense.csr.pem -force_pubkey certreqs/ekecc.pub.pem -out certs/ekecc.cert.der \
+    -outform DER -extfile ../ek/ek.cnf -extensions ek_ext -set_serial 12345 \
+    -CA intermed-ca.cert.pem -CAkey private/intermed-ca.key.pem -passin file:pass.txt
+
+#openssl x509 -req -in csrs/oemProvCertTPM.csr -extfile configs/oemProvCertTPM.cnf -extensions ext -CA certs/oemSubCA2Cert.pem -CAkey privateKeys/oemSubCA2.key -passin file:passphrase.txt -set_serial 12345 -days $validity_oem_prov_cert -force_pubkey pc.pub.pem -out certs/oemProvCertTPM.pem
+
+cp certs/ekecc.cert.der ../ek
+
+popd #intermed-ca
+
+#openssl x509 -in ek.cert.der -inform DER -text -no out
+#openssl rsa -in ek.pub.pem -pubin -text -noout
+#openssl asn1parse -in ek.cert.der -inform DER
+
+popd #EK
+
+popd #CA_DIR
+
+cp "${CA_DIR}/ek/ek.cert.der" "$3"
+cp "${CA_DIR}/ek/ekecc.cert.der" "$4"
+cp "${CA_DIR}/intermed-ca/intermed-ca.cert.pem" "$5"
+cp "${CA_DIR}/root-ca/root-ca.cert.pem" "$6"
+
+rm -rf $CA_DIR
diff --git a/script/ekca/ek.cnf b/script/ekca/ek.cnf
new file mode 100644
index 0000000..60cd380
--- /dev/null
+++ b/script/ekca/ek.cnf
@@ -0,0 +1,64 @@
+oid_section = tcg_oids
+
+[ tcg_oids ]
+tcg-sv-tpm20            = 2.23.133.1.2
+tcg-at-tpmManufacturer  = 2.23.133.2.1
+tcg-at-tpmModel         = 2.23.133.2.2
+tcg-at-tpmVersion       = 2.23.133.2.3
+tcg-at-tpmSpecification = 2.23.133.2.16
+tcg-at-tpmSecurityAssertions = 2.23.133.2.18
+tcg-kp-EKCertificate    = 2.23.133.8.1
+
+[ req ]
+prompt                  = no
+distinguished_name      = distinguished_name
+subjectAltName          = subject_alt_name
+
+[ distinguished_name ]
+commonName              = this-tpm-sim
+organizationName        = tpm2-tss-testsuit
+
+[ req_ext ]
+subjectKeyIdentifier    = hash
+
+[ ek_ext ]
+certificatePolicies     = @polsect
+subjectAltName          = dirName:subAltName
+basicConstraints        = critical, CA:FALSE
+subjectDirectoryAttributes = ASN1:SEQUENCE:subDirAttr
+authorityKeyIdentifier  = keyid:always
+authorityInfoAccess     = caIssuers;URI.0:http://tpm2-software.github.io
+keyUsage                = critical, keyEncipherment
+#extendedKeyUsage        = tcg-kp-EKCertificate
+extendedKeyUsage        = 2.23.133.8.1
+
+[ polsect ]
+policyIdentifier = anyPolicy
+CPS.1="http://my.host.name/"
+
+[ subAltName ]
+#TPMManufacturer = 'TSS2'
+.2.23.133.2.1 = id:54535332
+.2.23.133.2.2 = tpmsimulator
+.2.23.133.2.3 = id:00020008
+
+#TODO: Remove
+[ subAltName1 ]
+C=DE
+O=Testing
+OU=whatever
+commonName=abc
+
+[ subDirAttr ]
+tcg-at-tpmSpecification = SEQUENCE:tpmspec
+#tcg-at-tpmSecurityAssertions = SEQUENCE:secassert
+
+[ tpmspec ]
+family = UTF8:2.0
+level = INT:0
+revision = INT:138
+
+#[ secassert ]
+#version = INT:0
+#fieldUpgradable = BOOL:false
+#...
diff --git a/script/ekca/intermed-ca.cnf b/script/ekca/intermed-ca.cnf
new file mode 100644
index 0000000..0b0853a
--- /dev/null
+++ b/script/ekca/intermed-ca.cnf
@@ -0,0 +1,153 @@
+#
+# OpenSSL configuration for the Intermediate Certification Authority.
+#
+
+#
+# This definition doesn't work if HOME isn't defined.
+CA_HOME                 = .
+RANDFILE                = $ENV::CA_HOME/private/.rnd
+oid_section             = new_oids
+
+#
+# XMPP address Support
+[ new_oids ]
+xmppAddr          = 1.3.6.1.5.5.7.8.5
+dnsSRV            = 1.3.6.1.5.5.7.8.7
+
+#
+# Default Certification Authority
+[ ca ]
+default_ca              = intermed_ca
+
+#
+# Intermediate Certification Authority
+[ intermed_ca ]
+dir                     = $ENV::CA_HOME
+certs                   = $dir/certs
+serial                  = $dir/intermed-ca.serial
+database                = $dir/intermed-ca.index
+new_certs_dir           = $dir/newcerts
+certificate             = $dir/intermed-ca.cert.pem
+private_key             = $dir/private/intermed-ca.key.pem
+default_days            = 730 # Two years
+crl                     = $dir/crl/intermed-ca.crl
+crl_dir                 = $dir/crl
+crlnumber               = $dir/intermed-ca.crlnum
+name_opt                = multiline, align
+cert_opt                = no_pubkey
+copy_extensions         = copy
+crl_extensions          = crl_ext
+default_crl_days        = 30
+default_md              = sha256
+preserve                = no
+email_in_dn             = no
+policy                  = policy
+unique_subject          = no
+
+#
+# Distinguished Name Policy
+[ policy ]
+countryName             = optional
+stateOrProvinceName     = optional
+localityName            = optional
+organizationName        = optional
+organizationalUnitName  = optional
+commonName              = supplied
+
+#
+# Distinguished Name Policy for Personal Certificates
+[ user_policy ]
+countryName             = supplied
+stateOrProvinceName     = optional
+localityName            = supplied
+organizationName        = optional
+organizationalUnitName  = optional
+commonName              = supplied
+emailAddress            = supplied
+#xmppAddr               = optional # Added to SubjAltName by req
+
+#
+# Intermediate CA request options
+[ req ]
+default_bits            = 2048
+default_keyfile         = private/intermed-ca.key.pem
+encrypt_key             = yes
+default_md              = sha256
+string_mask             = utf8only
+utf8                    = yes
+prompt                  = no
+req_extensions          = req_ext
+distinguished_name      = distinguished_name
+subjectAltName          = subject_alt_name
+
+#
+# Intermediate CA Request Extensions
+[ req_ext ]
+subjectKeyIdentifier    = hash
+subjectAltName          = @subject_alt_name
+
+#
+# Distinguished Name (DN)
+[ distinguished_name ]
+organizationName        = tpm2-software
+commonName              = intermed ek ca
+
+#
+# Server Certificate Extensions
+[ server_ext ]
+basicConstraints        = CA:FALSE
+keyUsage                = critical, digitalSignature, keyEncipherment
+extendedKeyUsage        = critical, serverAuth, clientAuth
+subjectKeyIdentifier    = hash
+authorityKeyIdentifier  = keyid:always
+issuerAltName           = issuer:copy
+authorityInfoAccess     = @auth_info_access
+crlDistributionPoints   = crl_dist
+
+#
+# Client Certificate Extensions
+[ client_ext ]
+basicConstraints        = CA:FALSE
+keyUsage                = critical, digitalSignature
+extendedKeyUsage        = critical, clientAuth
+subjectKeyIdentifier    = hash
+authorityKeyIdentifier  = keyid:always
+issuerAltName           = issuer:copy
+authorityInfoAccess     = @auth_info_access
+crlDistributionPoints   = crl_dist
+
+#
+# User Certificate Extensions
+[ user_ext ]
+basicConstraints        = CA:FALSE
+keyUsage                = critical, digitalSignature
+extendedKeyUsage        = critical, clientAuth, emailProtection
+subjectKeyIdentifier    = hash
+authorityKeyIdentifier  = keyid:always
+issuerAltName           = issuer:copy
+authorityInfoAccess     = @auth_info_access
+crlDistributionPoints   = crl_dist
+
+#
+# CRL Certificate Extensions
+[ crl_ext ]
+authorityKeyIdentifier  = keyid:always
+issuerAltName           = issuer:copy
+
+#
+# Certificate Authorities Alternative Names
+[ subject_alt_name ]
+URI                     = http://ca.example.net/
+email                   = certmaster@example.net
+
+#
+# Certificate download addresses for the intermediate CA
+[ auth_info_access ]
+caIssuers;URI           = http://ca.example.net/certs/example.net_Intermediate_Certification_Authority.cert.pem
+
+#
+# CRL Download address for the intermediate CA
+[ crl_dist ]
+fullname                = URI:http://ca.example.net/crl/example.net_Intermediate_Certification_Authority.crl
+
+# EOF
diff --git a/script/ekca/root-ca.cnf b/script/ekca/root-ca.cnf
new file mode 100644
index 0000000..25b2770
--- /dev/null
+++ b/script/ekca/root-ca.cnf
@@ -0,0 +1,131 @@
+#
+# OpenSSL configuration for the Root Certification Authority.
+#
+
+#
+# This definition doesn't work if HOME isn't defined.
+CA_HOME                 = .
+RANDFILE                = $ENV::CA_HOME/private/.rnd
+
+#
+# Default Certification Authority
+[ ca ]
+default_ca              = root_ca
+
+#
+# Root Certification Authority
+[ root_ca ]
+dir                     = $ENV::CA_HOME
+certs                   = $dir/certs
+serial                  = $dir/root-ca.serial
+database                = $dir/root-ca.index
+new_certs_dir           = $dir/newcerts
+certificate             = $dir/root-ca.cert.pem
+private_key             = $dir/private/root-ca.key.pem
+default_days            = 1826 # Five years
+crl                     = $dir/root-ca.crl
+crl_dir                 = $dir/crl
+crlnumber               = $dir/root-ca.crlnum
+name_opt                = multiline, align
+cert_opt                = no_pubkey
+copy_extensions         = copy
+crl_extensions          = crl_ext
+default_crl_days        = 180
+default_md              = sha256
+preserve                = no
+email_in_dn             = no
+policy                  = policy
+unique_subject          = no
+
+#
+# Distinguished Name Policy for CAs
+[ policy ]
+countryName             = optional
+stateOrProvinceName     = optional
+localityName            = optional
+organizationName        = supplied
+organizationalUnitName  = optional
+commonName              = supplied
+
+#
+# Root CA Request Options
+[ req ]
+default_bits            = 4096
+default_keyfile         = private/root-ca.key.pem
+encrypt_key             = yes
+default_md              = sha256
+string_mask             = utf8only
+utf8                    = yes
+prompt                  = no
+req_extensions          = root-ca_req_ext
+distinguished_name      = distinguished_name
+subjectAltName          = @subject_alt_name
+
+#
+# Root CA Request Extensions
+[ root-ca_req_ext ]
+subjectKeyIdentifier    = hash
+subjectAltName          = @subject_alt_name
+
+#
+# Distinguished Name (DN)
+[ distinguished_name ]
+organizationName        = example.net
+commonName              = example.net Root Certification Authority
+
+#
+# Root CA Certificate Extensions
+[ root-ca_ext ]
+basicConstraints        = critical, CA:true
+keyUsage                = critical, keyCertSign, cRLSign
+nameConstraints         = critical, @name_constraints
+subjectKeyIdentifier    = hash
+subjectAltName          = @subject_alt_name
+authorityKeyIdentifier  = keyid:always
+issuerAltName           = issuer:copy
+authorityInfoAccess     = @auth_info_access
+crlDistributionPoints   = crl_dist
+
+#
+# Intermediate CA Certificate Extensions
+[ intermed-ca_ext ]
+basicConstraints        = critical, CA:true, pathlen:0
+keyUsage                = critical, keyCertSign, cRLSign
+subjectKeyIdentifier    = hash
+subjectAltName          = @subject_alt_name
+authorityKeyIdentifier  = keyid:always
+issuerAltName           = issuer:copy
+authorityInfoAccess     = @auth_info_access
+crlDistributionPoints   = crl_dist
+
+#
+# CRL Certificate Extensions
+[ crl_ext ]
+authorityKeyIdentifier  = keyid:always
+issuerAltName           = issuer:copy
+
+#
+# Certificate Authorities Alternative Names
+[ subject_alt_name ]
+URI                     = http://ca.example.net/
+email                   = certmaster@example.net
+
+#
+# Name Constraints
+[ name_constraints ]
+permitted;DNS.1         = example.net
+permitted;DNS.2         = example.org
+permitted;DNS.3         = lan
+permitted;DNS.4         = onion
+permitted;email.1       = example.net
+permitted;email.2       = example.org
+
+#
+# Certificate download addresses for the root CA
+[ auth_info_access ]
+caIssuers;URI           = http://ca.example.net/certs/example.net_Root_Certification_Authority.cert.pem
+
+#
+# CRL Download address for the root CA
+[ crl_dist ]
+fullname                = URI:http://ca.example.net/crl/example.net_Root_Certification_Authority.crl
diff --git a/script/int-log-compiler-ptpm.sh b/script/int-log-compiler-ptpm.sh
index 2dc45c9..63a5303 100755
--- a/script/int-log-compiler-ptpm.sh
+++ b/script/int-log-compiler-ptpm.sh
@@ -88,7 +88,7 @@
     G_MESSAGES_DEBUG=all ./test/helper/tpm_transientempty
 if [ $? -ne 0 ]; then
     echo "TPM transient area not empty => skipping"
-    ret=77
+    ret=99
     break
 fi
 
@@ -97,6 +97,7 @@
 
 env TPM20TEST_TCTI_NAME="device" \
     TPM20TEST_DEVICE_FILE=${PTPM} \
+    TPM20TEST_TCTI="device:${PTPM}" \
     G_MESSAGES_DEBUG=all ./test/helper/tpm_dumpstate>$TPMSTATE_FILE1
 if [ $? -ne 0 ]; then
     echo "Error during dumpstate"
@@ -107,12 +108,14 @@
 echo "Execute the test script"
 env TPM20TEST_TCTI_NAME="device" \
     TPM20TEST_DEVICE_FILE=${PTPM} \
+    TPM20TEST_TCTI="device:${PTPM}" \
     G_MESSAGES_DEBUG=all $@
 ret=$?
 echo "Script returned $ret"
 
 env TPM20TEST_TCTI_NAME="device" \
     TPM20TEST_DEVICE_FILE=${PTPM} \
+    TPM20TEST_TCTI="device:${PTPM}" \
     G_MESSAGES_DEBUG=all ./test/helper/tpm_dumpstate>$TPMSTATE_FILE2
 if [ $? -ne 0 ]; then
     echo "Error during dumpstate"
diff --git a/script/int-log-compiler.sh b/script/int-log-compiler.sh
index f5d622a..a7a17d7 100755
--- a/script/int-log-compiler.sh
+++ b/script/int-log-compiler.sh
@@ -228,6 +228,7 @@
 env TPM20TEST_TCTI_NAME="socket" \
     TPM20TEST_SOCKET_ADDRESS="127.0.0.1" \
     TPM20TEST_SOCKET_PORT="${SIM_PORT_DATA}" \
+    TPM20TEST_TCTI="mssim:host=127.0.0.1,port=${SIM_PORT_DATA}" \
     G_MESSAGES_DEBUG=all ./test/helper/tpm_startup
 if [ $? -ne 0 ]; then
     echo "TPM_StartUp failed"
@@ -235,13 +236,81 @@
     break
 fi
 
+EKPUB_FILE=${TEST_BIN}_ekpub.pem
+EKCERT_FILE=${TEST_BIN}_ekcert.crt
+INTERMEDCA_FILE=${TEST_BIN}_intermed-ca.pem
+ROOTCA_FILE=${TEST_BIN}_root-ca.pem
+
 env TPM20TEST_TCTI_NAME="socket" \
     TPM20TEST_SOCKET_ADDRESS="127.0.0.1" \
     TPM20TEST_SOCKET_PORT="${SIM_PORT_DATA}" \
+    TPM20TEST_TCTI="mssim:host=127.0.0.1,port=${SIM_PORT_DATA}" \
+    G_MESSAGES_DEBUG=all ./test/helper/tpm_getek>$EKPUB_FILE
+if [ $? -ne 0 ]; then
+    echo "TPM_getek failed"
+    ret=99
+    break
+fi
+
+EKECCPUB_FILE=${TEST_BIN}_ekeccpub.pem
+EKECCCERT_FILE=${TEST_BIN}_ekecccert.crt
+INTERMEDCA_FILE=${TEST_BIN}_intermedecc-ca.pem
+ROOTCA_FILE=${TEST_BIN}_root-ca.pem
+
+env TPM20TEST_TCTI_NAME="socket" \
+    TPM20TEST_SOCKET_ADDRESS="127.0.0.1" \
+    TPM20TEST_SOCKET_PORT="${SIM_PORT_DATA}" \
+    TPM20TEST_TCTI="mssim:host=127.0.0.1,port=${SIM_PORT_DATA}" \
+    G_MESSAGES_DEBUG=all ./test/helper/tpm_getek_ecc>$EKECCPUB_FILE
+if [ $? -ne 0 ]; then
+    echo "TPM_getek_ecc failed"
+    ret=99
+    break
+fi
+
+SCRIPTDIR="$(dirname $(realpath $0))/"
+${SCRIPTDIR}/ekca/create_ca.sh "${EKPUB_FILE}" "${EKECCPUB_FILE}" "${EKCERT_FILE}" \
+                               "${EKECCCERT_FILE}" "${INTERMEDCA_FILE}" "${ROOTCA_FILE}" >${TEST_BIN}_ca.log 2>&1
+if [ $? -ne 0 ]; then
+    echo "ek-cert ca failed"
+    ret=99
+    break
+fi
+
+#hd $EKCERT_FILE
+#openssl x509 -in $EKCERT_FILE -inform DER -text -noout
+
+cat $EKCERT_FILE | \
+env TPM20TEST_TCTI_NAME="socket" \
+    TPM20TEST_SOCKET_ADDRESS="127.0.0.1" \
+    TPM20TEST_SOCKET_PORT="${SIM_PORT_DATA}" \
+    TPM20TEST_TCTI="mssim:host=127.0.0.1,port=${SIM_PORT_DATA}" \
+    G_MESSAGES_DEBUG=all ./test/helper/tpm_writeekcert 1C00002
+if [ $? -ne 0 ]; then
+    echo "TPM_writeekcert failed"
+    ret=99
+    break
+fi
+
+cat $EKECCCERT_FILE | \
+env TPM20TEST_TCTI_NAME="socket" \
+    TPM20TEST_SOCKET_ADDRESS="127.0.0.1" \
+    TPM20TEST_SOCKET_PORT="${SIM_PORT_DATA}" \
+    TPM20TEST_TCTI="mssim:host=127.0.0.1,port=${SIM_PORT_DATA}" \
+    G_MESSAGES_DEBUG=all ./test/helper/tpm_writeekcert 1C0000A
+if [ $? -ne 0 ]; then
+    echo "TPM_writeekcert failed"
+    ret=99
+fi
+
+env TPM20TEST_TCTI_NAME="socket" \
+    TPM20TEST_SOCKET_ADDRESS="127.0.0.1" \
+    TPM20TEST_SOCKET_PORT="${SIM_PORT_DATA}" \
+    TPM20TEST_TCTI="mssim:host=127.0.0.1,port=${SIM_PORT_DATA}" \
     G_MESSAGES_DEBUG=all ./test/helper/tpm_transientempty
 if [ $? -ne 0 ]; then
     echo "TPM transient area not empty => skipping"
-    ret=77
+    ret=99
     break
 fi
 
@@ -251,6 +320,7 @@
 env TPM20TEST_TCTI_NAME="socket" \
     TPM20TEST_SOCKET_ADDRESS="127.0.0.1" \
     TPM20TEST_SOCKET_PORT="${SIM_PORT_DATA}" \
+    TPM20TEST_TCTI="mssim:host=127.0.0.1,port=${SIM_PORT_DATA}" \
     G_MESSAGES_DEBUG=all ./test/helper/tpm_dumpstate>$TPMSTATE_FILE1
 if [ $? -ne 0 ]; then
     echo "Error during dumpstate"
@@ -262,6 +332,9 @@
 env TPM20TEST_TCTI_NAME="socket" \
     TPM20TEST_SOCKET_ADDRESS="127.0.0.1" \
     TPM20TEST_SOCKET_PORT="${SIM_PORT_DATA}" \
+    TPM20TEST_TCTI="mssim:host=127.0.0.1,port=${SIM_PORT_DATA}" \
+    INTERMEDCA=$INTERMEDCA_FILE \
+    ROOTCA=$ROOTCA_FILE \
     G_MESSAGES_DEBUG=all $@
 ret=$?
 echo "Script returned $ret"
@@ -270,6 +343,7 @@
 env TPM20TEST_TCTI_NAME="socket" \
     TPM20TEST_SOCKET_ADDRESS="127.0.0.1" \
     TPM20TEST_SOCKET_PORT="${SIM_PORT_DATA}" \
+    TPM20TEST_TCTI="mssim:host=127.0.0.1,port=${SIM_PORT_DATA}" \
     G_MESSAGES_DEBUG=all ./test/helper/tpm_dumpstate>$TPMSTATE_FILE2
 if [ $? -ne 0 ]; then
     echo "Error during dumpstate"
@@ -295,6 +369,7 @@
 env TPM20TEST_TCTI_NAME="socket" \
     TPM20TEST_SOCKET_ADDRESS="127.0.0.1" \
     TPM20TEST_SOCKET_PORT="${SIM_PORT_DATA}" \
+    TPM20TEST_TCTI="mssim:host=127.0.0.1,port=${SIM_PORT_DATA}" \
     G_MESSAGES_DEBUG=all ./test/helper/tpm_dumpstate>$TPMSTATE_FILE2
 if [ $? -ne 0 ]; then
     echo "Error during dumpstate"
@@ -322,4 +397,5 @@
 # teardown
 daemon_stop ${SIM_PID_FILE}
 rm -rf ${SIM_TMP_DIR} ${SIM_PID_FILE}
+
 exit $ret
diff --git a/src/tss2-esys/esys_free.c b/src/tss2-esys/esys_free.c
index d5bac86..5a2ee64 100644
--- a/src/tss2-esys/esys_free.c
+++ b/src/tss2-esys/esys_free.c
@@ -15,4 +15,4 @@
     if (__ptr != NULL) {
         free(__ptr);
     }
-}
\ No newline at end of file
+}
diff --git a/src/tss2-esys/esys_tr.c b/src/tss2-esys/esys_tr.c
index e79f839..61b5440 100644
--- a/src/tss2-esys/esys_tr.c
+++ b/src/tss2-esys/esys_tr.c
@@ -604,7 +604,7 @@
  * PlolicyAuthValue are used for a session.
  * @param esys_context [in,out] The ESYS_CONTEXT.
  * @param esys_handle [in,out] The ESYS_TRsess for which to retrieve the nonce.
- * @param auth_needed [out] The boolean indicating whether auth value will be 
+ * @param neeed [out] The boolean indicating whether auth value will be
  *                    needed.
  * @retval TSS2_RC_SUCCESS on Success.
  * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
@@ -626,7 +626,7 @@
         return_if_error(TSS2_ESYS_RC_BAD_TR,
                         "Auth value needed for non-session object requested.");
     }
-    
+
     if (esys_object->rsrc.misc.rsrc_session.type_policy_session == POLICY_AUTH ||
         esys_object->rsrc.misc.rsrc_session.type_policy_session == POLICY_PASSWORD)
         *auth_needed = TPM2_YES;
diff --git a/src/tss2-fapi/api/Fapi_AuthorizePolicy.c b/src/tss2-fapi/api/Fapi_AuthorizePolicy.c
new file mode 100644
index 0000000..b776716
--- /dev/null
+++ b/src/tss2-fapi/api/Fapi_AuthorizePolicy.c
@@ -0,0 +1,329 @@
+/* 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 "tss2_fapi.h"
+#include "fapi_int.h"
+#include "fapi_util.h"
+#include "tss2_esys.h"
+#include "fapi_policy.h"
+#include "fapi_crypto.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+/** One-Call function for Fapi_AuthorizePolicy
+ *
+ * If a current policy happens to be a PolicyAuthorize, then for it to be used,
+ * the user must first satisfy a policy authorized by a having been signed (and
+ * made into a ticket) by an authorized party.
+ *
+ * @param[in, out] context The FAPI context
+ * @param[in] policyPath The path to the policy file
+ * @param[in] keyPath The path to the signing key
+ * @param[in] policyRef A byte buffer that is included in the signature. May be
+ * 						NULL
+ * @param[in] policyRefSize The size of policyRef. Must be 0 if policyRef is
+ * 						NULL
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context, policyPath or keyPath
+ *         is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_PATH: if policyPath or keyPath does not
+ *         map to a FAPI policy or key object.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_AuthorizePolicy(
+    FAPI_CONTEXT  *context,
+    char    const *policyPath,
+    char    const *keyPath,
+    uint8_t const *policyRef,
+    size_t         policyRefSize)
+{
+    TSS2_RC r, r2;
+
+    LOG_TRACE("called for context:%p", context);
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(policyPath);
+    check_not_null(keyPath);
+
+    /* Check whether TCTI and ESYS are initialized */
+    return_if_null(context->esys, "Command can't be executed in none TPM mode.",
+                   TSS2_FAPI_RC_NO_TPM);
+
+    /* If the async state automata of FAPI shall be tested, then we must not set
+       the timeouts of ESYS to blocking mode.
+       During testing, the mssim tcti will ensure multiple re-invocations.
+       Usually however the synchronous invocations of FAPI shall instruct ESYS
+       to block until a result is available. */
+#ifndef TEST_FAPI_ASYNC
+    r = Esys_SetTimeout(context->esys, TSS2_TCTI_TIMEOUT_BLOCK);
+    return_if_error_reset_state(r, "Set Timeout to blocking");
+#endif /* TEST_FAPI_ASYNC */
+
+    r = Fapi_AuthorizePolicy_Async(context, policyPath, keyPath,
+                                   policyRef, policyRefSize);
+    return_if_error_reset_state(r, "Policy_AuthorizeNewpolicy");
+
+    do {
+        /* We wait for file I/O to be ready if the FAPI state automata
+           are in a file I/O state. */
+        r = ifapi_io_poll(&context->io);
+        return_if_error(r, "Something went wrong with IO polling");
+
+        /* Repeatedly call the finish function, until FAPI has transitioned
+           through all execution stages / states of this invocation. */
+        r = Fapi_AuthorizePolicy_Finish(context);
+    } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
+
+    /* Reset the ESYS timeout to non-blocking, immediate response. */
+    r2 = Esys_SetTimeout(context->esys, 0);
+    return_if_error(r2, "Set Timeout to non-blocking");
+
+    return_if_error_reset_state(r, "PolicyAuthorizeNewPolicy");
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous function for Fapi_AuthorizePolicy
+ *
+ * If a current policy happens to be a PolicyAuthorize, then for it to be used,
+ * the user must first satisfy a policy authorized by a having been signed (and
+ * made into a ticket) by an authorized party.
+ *
+ * Call Fapi_AuthorizePolicy_Finish to finish the execution of this command.
+ *
+ * @param[in, out] context The FAPI context
+ * @param[in] policyPath The path to the policy file
+ * @param[in] keyPath The path to the signing key
+ * @param[in] policyRef A byte buffer that is included in the signature. May be
+ * 						NULL
+ * @param[in] policyRefSize The size of policyRef. Must be 0 if policyRef is
+ * 						NULL
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context, policyPath or keyPath
+ *         is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_PATH: if policyPath or keyPath does not
+ *         map to a FAPI policy or key object.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_AuthorizePolicy_Async(
+    FAPI_CONTEXT  *context,
+    char    const *policyPath,
+    char    const *keyPath,
+    uint8_t const *policyRef,
+    size_t         policyRefSize)
+{
+    LOG_TRACE("called for context:%p", context);
+    LOG_TRACE("policyPath: %s", policyPath);
+    LOG_TRACE("keyPath: %s", keyPath);
+    if (policyRef) {
+        LOGBLOB_TRACE(policyRef, policyRefSize, "policyRef");
+    } else {
+        LOG_TRACE("policyRef: (null) policyRefSize: %zi", policyRefSize);
+    }
+
+    TSS2_RC r;
+    IFAPI_Fapi_AuthorizePolicy *policy;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(policyPath);
+    check_not_null(keyPath);
+
+    r = ifapi_session_init(context);
+    return_if_error(r, "Initialize AuthorizePolicy");
+
+    policy = &context->cmd.Policy_AuthorizeNewPolicy;
+    strdup_check(policy->policyPath, policyPath, r, error_cleanup);
+    strdup_check(policy->signingKeyPath, keyPath, r, error_cleanup);
+    if (policyRef) {
+        FAPI_COPY_DIGEST(&policy->policyRef.buffer[0],
+                         policy->policyRef.size, policyRef, policyRefSize);
+    } else {
+        policy->policyRef.size = 0;
+    }
+    r = ifapi_session_init(context);
+    goto_if_error(r, "Initialize PolicyAuthorizeNewPolicy", error_cleanup);
+
+    context->state = AUTHORIZE_NEW_LOAD_KEY;
+
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+error_cleanup:
+    SAFE_FREE(policy->policyPath);
+    SAFE_FREE(policy->signingKeyPath);
+    return r;
+}
+
+/** Asynchronous finish function for Fapi_AuthorizePolicy
+ *
+ * This function should be called after a previous Fapi_AuthorizePolicy_Async.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
+ *         complete. Call this function again later.
+ */
+TSS2_RC
+Fapi_AuthorizePolicy_Finish(
+    FAPI_CONTEXT *context)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+    TPMI_ALG_HASH hashAlg;
+    IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext;
+    size_t hashSize;
+    size_t digestIdx;
+    TPM2B_DIGEST aHash;
+    char *publicKey = NULL;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+
+    /* Helpful alias pointers */
+    IFAPI_Fapi_AuthorizePolicy * command =
+        &context->cmd.Policy_AuthorizeNewPolicy;
+    TPMS_POLICYAUTHORIZATION *authorization = &command->authorization;
+    TPMS_POLICY_HARNESS *policyHarness = &context->policy.harness;
+    TPMT_SIGNATURE *signature;
+    IFAPI_OBJECT ** keyObject = &context->Key_Sign.key_object;
+
+    switch (context->state) {
+        statecase(context->state, AUTHORIZE_NEW_LOAD_KEY);
+            r = ifapi_load_key(context, command->signingKeyPath,
+                               keyObject);
+            return_try_again(r);
+            goto_if_error(r, "Fapi sign.", cleanup);
+
+            context->state = AUTHORIZE_NEW_CALCULATE_POLICY;
+            fallthrough;
+
+        statecase(context->state, AUTHORIZE_NEW_CALCULATE_POLICY);
+            /*
+             * NameAlg of signing key will be used to compute the aHash digest.
+             * This NameAlg will also be used to compute the policy digest.
+             * Thus the NameAlg must be equal to the NameAlg of the object to
+             * be authorized.
+             */
+            hashAlg = (*keyObject)->misc.key.public.publicArea.nameAlg;
+
+            if (!(hashSize = ifapi_hash_get_digest_size(hashAlg))) {
+                goto_error(r, TSS2_ESYS_RC_NOT_IMPLEMENTED,
+                           "Unsupported hash algorithm (%" PRIu16 ")",
+                           cleanup, hashAlg);
+            }
+
+            r = ifapi_calculate_tree(context,
+                                     command->policyPath, policyHarness,
+                                     hashAlg, &digestIdx, &hashSize);
+            return_try_again(r);
+            goto_if_error(r, "Fapi calculate tree.", cleanup);
+
+            /* Compute aHash from policy digest and policyRef */
+            r = ifapi_crypto_hash_start(&cryptoContext, hashAlg);
+            goto_if_error(r, "crypto hash start", cleanup);
+
+            HASH_UPDATE_BUFFER(cryptoContext,
+                               &policyHarness->
+                               policyDigests.digests[digestIdx].digest, hashSize,
+                               r, cleanup);
+            if (command->policyRef.size > 0) {
+                HASH_UPDATE_BUFFER(cryptoContext,
+                                   &command->policyRef.buffer[0],
+                                   command->policyRef.size, r, cleanup);
+            }
+            r = ifapi_crypto_hash_finish(&cryptoContext,
+                                         (uint8_t *) & aHash.buffer[0], &hashSize);
+            goto_if_error(r, "crypto hash finish", cleanup);
+
+            aHash.size = hashSize;
+            context->state = AUTHORIZE_NEW_KEY_SIGN_POLICY;
+            fallthrough;
+
+        statecase(context->state, AUTHORIZE_NEW_KEY_SIGN_POLICY);
+            r = ifapi_key_sign(context, *keyObject, NULL,
+                               &aHash, &signature, &publicKey, NULL);
+            return_try_again(r);
+            goto_if_error(r, "Fapi sign.", cleanup);
+
+            SAFE_FREE(publicKey);
+            authorization->signature = *signature;
+            authorization->policyRef = command->policyRef;
+            strdup_check(authorization->type, "tpm", r, cleanup);
+            authorization->key =
+                (*keyObject)->misc.key.public.publicArea;
+            SAFE_FREE(signature);
+            ifapi_cleanup_ifapi_object(*keyObject);
+
+            ifapi_extend_authorization(policyHarness, authorization);
+            goto_if_null(policyHarness->policyAuthorizations,
+                         "Out of memory", TSS2_FAPI_RC_MEMORY, cleanup);
+            context->state = AUTHORIZE_NEW_WRITE_POLICY;
+            fallthrough;
+
+        statecase(context->state, AUTHORIZE_NEW_WRITE_POLICY_PREPARE);
+            r = ifapi_policy_store_store_async(&context->pstore, &context->io,
+                                               command->policyPath, policyHarness);
+            goto_if_error_reset_state(r, "Could not open: %s", cleanup,
+                    command->policyPath);
+            fallthrough;
+
+        statecase(context->state, AUTHORIZE_NEW_WRITE_POLICY);
+            /* Save policy with computed digest */
+            r = ifapi_policy_store_store_finish(&context->pstore, &context->io);
+            return_try_again(r);
+            return_if_error_reset_state(r, "write_finish failed");
+            fallthrough;
+
+        statecase(context->state, AUTHORIZE_NEW_CLEANUP)
+            r = ifapi_cleanup_session(context);
+            try_again_or_error_goto(r, "Cleanup", cleanup);
+
+            context->state = _FAPI_STATE_INIT;
+            break;
+
+       statecasedefault(context->state);
+    }
+
+cleanup:
+    ifapi_session_clean(context);
+    ifapi_cleanup_policy_harness(policyHarness);
+    ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
+    ifapi_cleanup_ifapi_object(context->loadKey.key_object);
+    ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
+    SAFE_FREE(command->policyPath);
+    SAFE_FREE(command->signingKeyPath);
+    LOG_TRACE("finsihed");
+    return r;
+}
diff --git a/src/tss2-fapi/api/Fapi_ChangeAuth.c b/src/tss2-fapi/api/Fapi_ChangeAuth.c
new file mode 100644
index 0000000..ddb2325
--- /dev/null
+++ b/src/tss2-fapi/api/Fapi_ChangeAuth.c
@@ -0,0 +1,475 @@
+/* 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 <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#include "tss2_fapi.h"
+#include "fapi_int.h"
+#include "fapi_util.h"
+#include "tss2_esys.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+#include "fapi_crypto.h"
+
+/** One-Call function for Fapi_ChangeAuth
+ *
+ * Changes the Authorization data of an entity found at keyPath. The parameter
+ * authValue is a 0-terminated UTF-8 encoded password.
+ * If it is longer than the digest size of the entity's nameAlg, it will be
+ * hashed according the the TPM specification part 1, rev 138, section 19.6.4.3.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] entityPath The path to the entity to modify
+ * @param [in] authValue The new 0-terminated password to set for the entity.
+ *             May be NULL
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or entityPath is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_PATH: if entityPath does not map to a FAPI entity.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_STORAGE_ERROR: If the entity with the new password
+ *         cannot be saved.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_ChangeAuth(
+    FAPI_CONTEXT *context,
+    char   const *entityPath,
+    char   const *authValue)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r, r2;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(entityPath);
+
+    /* Check whether TCTI and ESYS are initialized */
+    return_if_null(context->esys, "Command can't be executed in none TPM mode.",
+                   TSS2_FAPI_RC_NO_TPM);
+
+    /* If the async state automata of FAPI shall be tested, then we must not set
+       the timeouts of ESYS to blocking mode.
+       During testing, the mssim tcti will ensure multiple re-invocations.
+       Usually however the synchronous invocations of FAPI shall instruct ESYS
+       to block until a result is available. */
+#ifndef TEST_FAPI_ASYNC
+    r = Esys_SetTimeout(context->esys, TSS2_TCTI_TIMEOUT_BLOCK);
+    return_if_error_reset_state(r, "Set Timeout to blocking");
+#endif /* TEST_FAPI_ASYNC */
+
+    r = Fapi_ChangeAuth_Async(context, entityPath, authValue);
+    return_if_error_reset_state(r, "Entity_ChangeAuth");
+
+    do {
+        /* We wait for file I/O to be ready if the FAPI state automata
+           are in a file I/O state. */
+        r = ifapi_io_poll(&context->io);
+        return_if_error(r, "Something went wrong with IO polling");
+
+        /* Repeatedly call the finish function, until FAPI has transitioned
+           through all execution stages / states of this invocation. */
+        r = Fapi_ChangeAuth_Finish(context);
+    } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
+
+    /* Reset the ESYS timeout to non-blocking, immediate response. */
+    r2 = Esys_SetTimeout(context->esys, 0);
+    return_if_error(r2, "Set Timeout to non-blocking");
+
+    return_if_error_reset_state(r, "Entity_ChangeAuth");
+
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous function for Fapi_ChangeAuth
+ *
+ * Changes the Authorization data of an entity found at keyPath. The parameter
+ * authValue is a 0-terminated UTF-8 encoded password.
+ * If it is longer than the digest size of the entity's nameAlg, it will be
+ * hashed according the the TPM specification part 1, rev 138, section 19.6.4.3.
+ *
+ * Call Fapi_ChangeAuth_Finish to finish the execution of this command.
+
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] entityPath The path to the entity to modify
+ * @param [in] authValue The new 0-terminated password to set for the entity.
+ *         May be NULL
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or entityPath is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_PATH: if entityPath does not map to a FAPI entity.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_STORAGE_ERROR: If the entity with the new password
+ *         cannot be saved.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_ChangeAuth_Async(
+    FAPI_CONTEXT  *context,
+    char    const *entityPath,
+    char    const *authValue)
+{
+    LOG_TRACE("called for context:%p", context);
+    LOG_TRACE("entityPath: %s", entityPath);
+    LOG_TRACE("authValue: %s", authValue);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(entityPath);
+
+    /* Helpful pointers */
+    IFAPI_Entity_ChangeAuth * command = &(context->cmd.Entity_ChangeAuth);
+
+    r = ifapi_session_init(context);
+    return_if_error(r, "Initialize Entity_ChangeAuth");
+
+    context->loadKey.parent_handle = ESYS_TR_NONE;
+    command->handle = ESYS_TR_NONE;
+    memset(&command->object, 0, sizeof(IFAPI_OBJECT));
+    strdup_check(command->entityPath, entityPath, r, error_cleanup);
+    if(authValue != NULL) {
+        strdup_check(command->authValue, authValue, r, error_cleanup);
+    } else {
+        strdup_check(command->authValue, "", r, error_cleanup);
+    }
+    command->handle = ESYS_TR_NONE;
+
+    r = ifapi_get_sessions_async(context,
+                                 IFAPI_SESSION_GENEK | IFAPI_SESSION1,
+                                 TPMA_SESSION_DECRYPT, 0);
+    goto_if_error_reset_state(r, "Create sessions", error_cleanup);
+
+    if (strlen(command->authValue) > sizeof(TPMU_HA)) {
+        LOG_ERROR("authValue to big. (Should be <= %zu", sizeof(TPMU_HA));
+        r = TSS2_FAPI_RC_BAD_VALUE;
+        goto error_cleanup;
+    }
+
+    /* Copy new auth value to appropriate structure in context */
+    if (command->authValue) {
+        command->newAuthValue.size =
+            strlen(command->authValue);
+        memcpy(&command->newAuthValue.buffer[0],
+               command->authValue,
+               command->newAuthValue.size);
+    } else {
+        command->newAuthValue.size = 0;
+    }
+
+    context->state = ENTITY_CHANGE_AUTH_WAIT_FOR_SESSION;
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+
+error_cleanup:
+    SAFE_FREE(command->entityPath);
+    SAFE_FREE(command->authValue);
+    return r;
+}
+
+/** Asynchronous finish function for Fapi_ChangeAuth
+ *
+ * This function should be called after a previous Fapi_ChangeAuth_Async.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
+ *         complete. Call this function again later.
+ */
+TSS2_RC
+Fapi_ChangeAuth_Finish(
+    FAPI_CONTEXT *context)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+    ESYS_TR auth_session;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+
+    /* Helpful pointers */
+    IFAPI_Entity_ChangeAuth * command = &(context->cmd.Entity_ChangeAuth);
+    IFAPI_OBJECT * object = &command->object;
+    const IFAPI_PROFILE *profile;
+
+    switch (context->state) {
+        statecase(context->state, ENTITY_CHANGE_AUTH_WAIT_FOR_SESSION)
+            r = ifapi_profiles_get(&context->profiles, command->entityPath,
+                    &profile);
+            goto_if_error_reset_state(r, " FAPI create session", error_cleanup);
+
+            r = ifapi_get_sessions_finish(context, profile);
+            return_try_again(r);
+
+            goto_if_error_reset_state(r, " FAPI create session", error_cleanup);
+
+            if (ifapi_path_type_p(command->entityPath,
+                    IFAPI_NV_PATH)) {
+                r = ifapi_keystore_load_async(&context->keystore, &context->io,
+                        command->entityPath);
+                return_if_error_reset_state(r, "Could not open: %s",
+                        command->entityPath);
+
+                context->state = ENTITY_CHANGE_AUTH_WAIT_FOR_NV_READ;
+                return TSS2_FAPI_RC_TRY_AGAIN;
+            }
+
+            command->hierarchy_handle =
+                ifapi_get_hierary_handle(command->entityPath);
+
+            if (command->hierarchy_handle) {
+                context->state = ENTITY_CHANGE_AUTH_HIERARCHY_READ;
+                r = ifapi_keystore_load_async(&context->keystore, &context->io,
+                        command->entityPath);
+                return_if_error_reset_state(r, "Could not open: %s",
+                        command->entityPath);
+
+                return TSS2_FAPI_RC_TRY_AGAIN;
+            }
+
+            r = ifapi_load_keys_async(context, command->entityPath);
+            goto_if_error(r, "Load keys.", error_cleanup);
+
+            context->state = ENTITY_CHANGE_AUTH_WAIT_FOR_KEY;
+            fallthrough;
+
+        statecase(context->state, ENTITY_CHANGE_AUTH_WAIT_FOR_KEY)
+            r = ifapi_load_keys_finish(context, IFAPI_NOT_FLUSH_PARENT,
+                    &command->handle,
+                    &command->key_object);
+            return_try_again(r);
+
+            context->state = ENTITY_CHANGE_AUTH_WAIT_FOR_KEY_AUTH;
+            fallthrough;
+
+        statecase(context->state, ENTITY_CHANGE_AUTH_WAIT_FOR_KEY_AUTH)
+            /* Authorize the object with the old authorization */
+            object = command->key_object;
+            r = ifapi_authorize_object(context, object, &auth_session);
+
+            return_try_again(r);
+            goto_if_error_reset_state(r, "Authorize key.", error_cleanup);
+
+            r = Esys_ObjectChangeAuth_Async(context->esys,
+                    command->handle,
+                    context->loadKey.parent_handle,
+                    auth_session,
+                    ESYS_TR_NONE, ESYS_TR_NONE,
+                    &command->newAuthValue);
+            goto_if_error(r, "Error: Sign", error_cleanup);
+
+            context->state = ENTITY_CHANGE_AUTH_AUTH_SENT;
+            fallthrough;
+
+        statecase(context->state, ENTITY_CHANGE_AUTH_AUTH_SENT)
+            r = Esys_ObjectChangeAuth_Finish(context->esys,
+                    &command->newPrivate);
+            return_try_again(r);
+
+            goto_if_error(r, "Error: Entity ChangeAuth", error_cleanup);
+
+            object = command->key_object;
+            object->misc.key.private.size = command->newPrivate->size;
+
+            /* Old private buffer will be overwritten*/
+            free(object->misc.key.private.buffer);
+            object->misc.key.private.buffer = malloc(object->misc.key.private.size);
+            goto_if_null2(object->misc.key.private.buffer, "Out of memory.",
+                    r, TSS2_FAPI_RC_MEMORY, error_cleanup);
+
+            memcpy(object->misc.key.private.buffer,
+                    &command->newPrivate->buffer[0],
+                    object->misc.key.private.size);
+            free(command->newPrivate);
+            r = Esys_FlushContext_Async(context->esys,
+                    command->handle);
+            goto_if_error(r, "Error: FlushContext", error_cleanup);
+
+            command->handle = ESYS_TR_NONE;
+            context->state = ENTITY_CHANGE_AUTH_WAIT_FOR_FLUSH;
+            return TSS2_FAPI_RC_TRY_AGAIN;
+
+        statecase(context->state, ENTITY_CHANGE_AUTH_WAIT_FOR_FLUSH)
+            r = Esys_FlushContext_Finish(context->esys);
+            return_try_again(r);
+
+            goto_if_error(r, "Error: ObjectChangeAuth", error_cleanup);
+
+            if (! context->loadKey.parent_handle_persistent
+                    && context->loadKey.parent_handle != ESYS_TR_NONE) {
+                r = Esys_FlushContext_Async(context->esys, context->loadKey.parent_handle);
+                goto_if_error(r, "Flush parent", error_cleanup);
+
+                context->loadKey.parent_handle = ESYS_TR_NONE;
+                return TSS2_FAPI_RC_TRY_AGAIN;
+            }
+
+            /* Serialize key with new private data */
+            object = command->key_object;
+
+            if (strlen(command->authValue) > 0)
+                object->misc.key.with_auth = TPM2_YES;
+            else
+                object->misc.key.with_auth = TPM2_NO;
+            fallthrough;
+
+        statecase(context->state, ENTITY_CHANGE_AUTH_WRITE_PREPARE)
+            /* Perform esys serialization if necessary */
+            r = ifapi_esys_serialize_object(context->esys, object);
+            goto_if_error(r, "Prepare serialization", error_cleanup);
+
+            /* Start writing the NV object to the key store */
+            r = ifapi_keystore_store_async(&context->keystore, &context->io,
+                    command->entityPath,
+                    object);
+            goto_if_error_reset_state(r, "Could not open: %sh", error_cleanup,
+                    command->entityPath);
+            fallthrough;
+
+        statecase(context->state, ENTITY_CHANGE_AUTH_WRITE)
+            /* Finish writing the object to the key store */
+            r = ifapi_keystore_store_finish(&context->keystore, &context->io);
+            return_try_again(r);
+            return_if_error_reset_state(r, "write_finish failed");
+
+            fallthrough;
+
+        statecase(context->state, ENTITY_CHANGE_AUTH_CLEANUP)
+            r = ifapi_cleanup_session(context);
+            try_again_or_error_goto(r, "Cleanup", error_cleanup);
+
+            context->state = _FAPI_STATE_INIT;
+            LOG_TRACE("success");
+            r = TSS2_RC_SUCCESS;
+            break;
+
+        statecase(context->state, ENTITY_CHANGE_AUTH_WAIT_FOR_NV_READ)
+            /* Get object from file */
+            r = ifapi_keystore_load_finish(&context->keystore, &context->io,
+                    &command->object);
+            return_try_again(r);
+            return_if_error_reset_state(r, "read_finish failed");
+
+            r = ifapi_initialize_object(context->esys, &command->object);
+            goto_if_error_reset_state(r, "Initialize NV object", error_cleanup);
+
+            context->state = ENTITY_CHANGE_AUTH_WAIT_FOR_NV_AUTH;
+            fallthrough;
+
+        statecase(context->state, ENTITY_CHANGE_AUTH_WAIT_FOR_NV_AUTH)
+            /* Authorize the object with with the policies
+               auth value and command code */
+            r = ifapi_authorize_object(context, object, &auth_session);
+            return_try_again(r);
+            goto_if_error(r, "Authorize NV object.", error_cleanup);
+
+            r = Esys_NV_ChangeAuth_Async(context->esys,
+                    context->nv_cmd.nv_object.handle,
+                    auth_session,
+                    ESYS_TR_NONE,
+                    ESYS_TR_NONE,
+                    &command->newAuthValue);
+            goto_if_error(r, "Error: NV_ChangeAuth", error_cleanup);
+
+            context->state = ENTITY_CHANGE_AUTH_WAIT_FOR_NV_CHANGE_AUTH;
+            fallthrough;
+
+        statecase(context->state, ENTITY_CHANGE_AUTH_WAIT_FOR_NV_CHANGE_AUTH)
+            r = Esys_NV_ChangeAuth_Finish(context->esys);
+            return_try_again(r);
+
+            goto_if_error(r, "Error: Entity ChangeAuth", error_cleanup);
+
+            if (strlen(command->authValue) > 0)
+                object->misc.nv.with_auth = TPM2_YES;
+            else
+                object->misc.nv.with_auth = TPM2_NO;
+
+            context->state =  ENTITY_CHANGE_AUTH_WRITE_PREPARE;
+            return TSS2_FAPI_RC_TRY_AGAIN;
+
+            statecase(context->state, ENTITY_CHANGE_AUTH_HIERARCHY_READ)
+                r = ifapi_keystore_load_finish(&context->keystore, &context->io, object);
+            return_try_again(r);
+            return_if_error_reset_state(r, "read_finish failed");
+
+            r = ifapi_initialize_object(context->esys, &command->object);
+            goto_if_error_reset_state(r, "Initialize NV object", error_cleanup);
+
+            command->object.handle
+                = command->hierarchy_handle;
+
+            context->state = ENTITY_CHANGE_AUTH_HIERARCHY_AUTHORIZE;
+            fallthrough;
+
+        statecase(context->state, ENTITY_CHANGE_AUTH_HIERARCHY_AUTHORIZE)
+            r = ifapi_authorize_object(context, &command->object, &auth_session);
+            return_try_again(r);
+            goto_if_error(r, "Authorize hierarchy.", error_cleanup);
+
+            context->state = ENTITY_CHANGE_AUTH_HIERARCHY_CHANGE_AUTH;
+            fallthrough;
+
+        statecase(context->state, ENTITY_CHANGE_AUTH_HIERARCHY_CHANGE_AUTH)
+            r = ifapi_change_auth_hierarchy(context,
+                    command->hierarchy_handle,
+                    &command->object,
+                    &command->newAuthValue);
+            return_try_again(r);
+            goto_if_error(r, "Change auth hierarchy.", error_cleanup);
+
+            context->state = ENTITY_CHANGE_AUTH_WRITE_PREPARE;
+            return TSS2_FAPI_RC_TRY_AGAIN;
+
+        statecasedefault(context->state);
+    }
+
+error_cleanup:
+    /* In error cases object might not be flushed. */
+    if (context->loadKey.parent_handle != ESYS_TR_NONE)
+        Esys_FlushContext(context->esys, context->loadKey.parent_handle);
+    if (command->handle != ESYS_TR_NONE)
+        Esys_FlushContext(context->esys, command->handle);
+    ifapi_session_clean(context);
+    ifapi_cleanup_ifapi_object(object);
+    ifapi_cleanup_ifapi_object(context->loadKey.key_object);
+    ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
+    ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
+    ifapi_cleanup_ifapi_object(command->key_object);
+    SAFE_FREE(command->entityPath);
+    SAFE_FREE(command->authValue);
+    LOG_TRACE("finsihed");
+    return r;
+}
diff --git a/src/tss2-fapi/api/Fapi_CreateKey.c b/src/tss2-fapi/api/Fapi_CreateKey.c
new file mode 100644
index 0000000..0e90bdb
--- /dev/null
+++ b/src/tss2-fapi/api/Fapi_CreateKey.c
@@ -0,0 +1,228 @@
+/* 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 <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#include "tss2_fapi.h"
+#include "fapi_int.h"
+#include "fapi_util.h"
+#include "fapi_policy.h"
+#include "tss2_esys.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+/** One-Call function for Fapi_CreateKey
+ *
+ * Creates a key inside the TPM based on the Key type, using the supplied
+ * policy and authValue. The key is then stored either in the FAPI metadata
+ * store or the TPM.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] path The path where the new key is stored
+ * @param [in] type The type of the new key. May be NULL
+ * @param [in] policyPath The path to the policy that is associated with the new
+ *        key. May be NULL
+ * @param [in] authValue The authorization value for the new key. May be NULL
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or path is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_PATH: if policyPath is non-NULL and does not map to
+ *         a FAPI policy.
+ * @retval TSS2_FAPI_RC_KEY_NOT_FOUND: if the parent key does not map to a FAPI
+ *         key.
+ * @retval TSS2_FAPI_RC_PATH_ALREADY_EXISTS: if a file already exists at path.
+ * @retval TSS2_FAPI_RC_BAD_VALUE: if the keyType is non-NULL and invalid.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_CreateKey(
+    FAPI_CONTEXT *context,
+    char   const *path,
+    char   const *type,
+    char   const *policyPath,
+    char   const *authValue)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r, r2;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(path);
+
+    /* Check whether TCTI and ESYS are initialized */
+    return_if_null(context->esys, "Command can't be executed in none TPM mode.",
+                   TSS2_FAPI_RC_NO_TPM);
+
+    /* If the async state automata of FAPI shall be tested, then we must not set
+       the timeouts of ESYS to blocking mode.
+       During testing, the mssim tcti will ensure multiple re-invocations.
+       Usually however the synchronous invocations of FAPI shall instruct ESYS
+       to block until a result is available. */
+#ifndef TEST_FAPI_ASYNC
+    r = Esys_SetTimeout(context->esys, TSS2_TCTI_TIMEOUT_BLOCK);
+    return_if_error_reset_state(r, "Set Timeout to blocking");
+#endif /* TEST_FAPI_ASYNC */
+
+    r = Fapi_CreateKey_Async(context, path, type, policyPath, authValue);
+    return_if_error_reset_state(r, "Key_Create");
+
+    do {
+        /* We wait for file I/O to be ready if the FAPI state automata
+           are in a file I/O state. */
+        r = ifapi_io_poll(&context->io);
+        return_if_error(r, "Something went wrong with IO polling");
+
+        /* Repeatedly call the finish function, until FAPI has transitioned
+           through all execution stages / states of this invocation. */
+        r = Fapi_CreateKey_Finish(context);
+    } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
+
+    /* Reset the ESYS timeout to non-blocking, immediate response. */
+    r2 = Esys_SetTimeout(context->esys, 0);
+    return_if_error(r2, "Set Timeout to non-blocking");
+
+    return_if_error_reset_state(r, "Key_Create");
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous function for Fapi_CreateKey
+ *
+ * Creates a key inside the TPM based on the Key type, using the supplied
+ * policy and authValue. The key is then stored either in the FAPI metadata
+ * store or the TPM.
+ *
+ * Call Fapi_CreateKey_Finish to finish the execution of this command.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] path The path where the new key is stored
+ * @param [in] type The type of the new key. May be NULL
+ * @param [in] policyPath The path to the policy that is associated with the new
+ *        key. May be NULL
+ * @param [in] authValue The authorization value for the new key. May be NULL
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or path is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_PATH: if policyPath is non-NULL and does not map to
+ *         a FAPI policy.
+ * @retval TSS2_FAPI_RC_KEY_NOT_FOUND: if the parent key does not map to a FAPI
+ *         key.
+ * @retval TSS2_FAPI_RC_PATH_ALREADY_EXISTS: if a file already exists at path.
+ * @retval TSS2_FAPI_RC_BAD_VALUE: if the keyType is non-NULL and invalid.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_CreateKey_Async(
+    FAPI_CONTEXT *context,
+    char   const *path,
+    char   const *type,
+    char   const *policyPath,
+    char   const *authValue)
+{
+    LOG_TRACE("called for context:%p", context);
+    LOG_TRACE("path: %s", path);
+    LOG_TRACE("type: %s", type);
+    LOG_TRACE("policyPath: %s", policyPath);
+    LOG_TRACE("authValue: %s", authValue);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(path);
+
+    r = ifapi_session_init(context);
+    return_if_error(r, "Initialize CreateKey");
+
+    r = ifapi_key_create_prepare_auth(context, path, policyPath, authValue);
+    return_if_error(r, "Key create.");
+
+    r = ifapi_set_key_flags(type ? type : "",
+                            (policyPath && strcmp(policyPath, "") != 0) ? true : false,
+                            &context->cmd.Key_Create.public_templ);
+    return_if_error(r, "Set key flags for key");
+
+    context->state = KEY_CREATE;
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous finish function for Fapi_CreateKey
+ *
+ * This function should be called after a previous Fapi_CreateKey_Async.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
+ *         complete. Call this function again later.
+ */
+TSS2_RC
+Fapi_CreateKey_Finish(
+    FAPI_CONTEXT *context)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+
+    /* Helpful alias pointers */
+    IFAPI_Key_Create * command = &context->cmd.Key_Create;
+
+    switch (context->state) {
+        statecase(context->state, KEY_CREATE);
+            LOG_TRACE("KEY_CREATE");
+            r = ifapi_key_create(context, &command->public_templ);
+            return_try_again(r);
+            goto_if_error(r, "Key create", error_cleanup);
+
+            ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
+            ifapi_cleanup_ifapi_object(context->loadKey.key_object);
+            ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
+            context->state = _FAPI_STATE_INIT;
+            LOG_TRACE("finsihed");
+            return TSS2_RC_SUCCESS;
+
+        statecasedefault(context->state);
+    }
+
+error_cleanup:
+    context->cmd.Key_Create.state = KEY_CREATE_INIT;
+    ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
+    ifapi_cleanup_ifapi_object(context->loadKey.key_object);
+    ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
+    LOG_TRACE("finished");
+    return r;
+}
diff --git a/src/tss2-fapi/api/Fapi_CreateNv.c b/src/tss2-fapi/api/Fapi_CreateNv.c
new file mode 100644
index 0000000..d8b31c1
--- /dev/null
+++ b/src/tss2-fapi/api/Fapi_CreateNv.c
@@ -0,0 +1,413 @@
+/* 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 <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "tss2_fapi.h"
+#include "fapi_int.h"
+#include "fapi_util.h"
+#include "fapi_policy.h"
+#include "tss2_esys.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+/** One-Call function for Fapi_CreateNv
+ *
+ * This command creates an NV index in the TPM using a given path and type.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] path The path to the new NV index
+ * @param [in] type The intended type of the new NV index. May be NULL
+ * @param [in] size The size of the new NV index in bytes. May be 0 if the size
+ *             is inferred from the type
+ * @param [in] policyPath The path to the policy that is associated with the new
+ *             NV index. May be NULL
+ * @param [in] authValue The authorization value that is associated with the new
+ *             NV index. May be NULL
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or path is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_PATH_ALREADY_EXISTS: if an NV index already exists at
+ *         path.
+ * @retval TSS2_FAPI_RC_BAD_VALUE: if type is non-NULL but invalid or does not
+ *         match the size.
+ * @retval TSS2_FAPI_RC_BAD_PATH: if policyPath is non-NULL and does not map to
+ *         a FAPI policy or if path dos not refer to a valid NV index path.
+ * @retval TSS2_FAPI_RC_STORAGE_ERROR: if the FAPI storage cannot be updated.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_CreateNv(
+    FAPI_CONTEXT *context,
+    char   const *path,
+    char   const *type,
+    size_t size,
+    char   const *policyPath,
+    char   const *authValue)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r, r2;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(path);
+
+    /* Check whether TCTI and ESYS are initialized */
+    return_if_null(context->esys, "Command can't be executed in none TPM mode.",
+                   TSS2_FAPI_RC_NO_TPM);
+
+    /* If the async state automata of FAPI shall be tested, then we must not set
+       the timeouts of ESYS to blocking mode.
+       During testing, the mssim tcti will ensure multiple re-invocations.
+       Usually however the synchronous invocations of FAPI shall instruct ESYS
+       to block until a result is available. */
+#ifndef TEST_FAPI_ASYNC
+    r = Esys_SetTimeout(context->esys, TSS2_TCTI_TIMEOUT_BLOCK);
+    return_if_error_reset_state(r, "Set Timeout to blocking");
+#endif /* TEST_FAPI_ASYNC */
+
+    r = Fapi_CreateNv_Async(context, path, type, size,
+                            policyPath, authValue);
+    return_if_error_reset_state(r, "NV_CreateWithTemplate");
+
+    do {
+        /* We wait for file I/O to be ready if the FAPI state automata
+           are in a file I/O state. */
+        r = ifapi_io_poll(&context->io);
+        return_if_error(r, "Something went wrong with IO polling");
+
+        /* Repeatedly call the finish function, until FAPI has transitioned
+           through all execution stages / states of this invocation. */
+        r = Fapi_CreateNv_Finish(context);
+    } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
+
+    /* Reset the ESYS timeout to non-blocking, immediate response. */
+    r2 = Esys_SetTimeout(context->esys, 0);
+    return_if_error(r2, "Set Timeout to non-blocking");
+
+    return_if_error_reset_state(r, "NV_CreateWithTemplate");
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous function for Fapi_CreateNv
+ *
+ * This command creates an NV index in the TPM using a given path and type.
+ *
+ * Call Fapi_CreateNv_Finish to finish the execution of this command.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] path The path to the new NV index
+ * @param [in] type The intended type of the new NV index. May be NULL
+ * @param [in] size The size of the new NV index in bytes. May be 0 if the size
+ *             is inferred from the type
+ * @param [in] policyPath The path to the policy that is associated with the new
+ *             NV index. May be NULL
+ * @param [in] authValue The authorization value that is associated with the new
+ *             NV index. May be NULL
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or path is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_PATH_ALREADY_EXISTS: if an NV index already exists at
+ *         path.
+ * @retval TSS2_FAPI_RC_BAD_VALUE: if type is non-NULL but invalid or does not
+ *         match the size.
+ * @retval TSS2_FAPI_RC_BAD_PATH: if policyPath is non-NULL and does not map to
+ *         a FAPI policy or if path dos not refer to a valid NV index path.
+ * @retval TSS2_FAPI_RC_STORAGE_ERROR: if the FAPI storage cannot be updated.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_CreateNv_Async(
+    FAPI_CONTEXT *context,
+    char   const *path,
+    char   const *type,
+    size_t size,
+    char   const *policyPath,
+    char   const *authValue)
+{
+    LOG_TRACE("called for context:%p", context);
+    LOG_TRACE("path: %s", path);
+    LOG_TRACE("type: %s", type);
+    LOG_TRACE("size: %zi", size);
+    LOG_TRACE("policyPath: %s", policyPath);
+    LOG_TRACE("authValue: %s", authValue);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(path);
+
+    /* Helpful alias pointers */
+    IFAPI_NV_Cmds * nvCmd = &(context->nv_cmd);
+    TPM2B_AUTH *auth = &nvCmd->auth;
+    IFAPI_NV * miscNv = &(nvCmd->nv_object.misc.nv);
+
+    r = ifapi_session_init(context);
+    return_if_error(r, "Initialize NV_CreateNv");
+
+    /* First check whether an existing object would be overwritten */
+    r = ifapi_keystore_check_overwrite(&context->keystore, &context->io,
+                                       path);
+    return_if_error2(r, "Check overwrite %s", path);
+
+    memset(&context->nv_cmd, 0, sizeof(IFAPI_NV_Cmds));
+    if (authValue) {
+        if (strlen(authValue) > sizeof(TPMU_HA)) {
+            return_error(TSS2_FAPI_RC_BAD_VALUE, "AuthValue too long");
+        }
+
+        auth->size = strlen(authValue);
+        memcpy(&auth->buffer[0], authValue, auth->size);
+    } else {
+        auth->size = 0;
+    }
+    strdup_check(nvCmd->nvPath, path, r, error_cleanup);
+    nvCmd->numBytes = size;
+    nvCmd->nv_object.objectType = IFAPI_NV_OBJ;
+    strdup_check(miscNv->policyInstance, policyPath, r, error_cleanup);
+
+    r = ifapi_set_nv_flags(type ? type : "", &nvCmd->public_templ,
+                           policyPath);
+    goto_if_error(r, "Set key flags for NV object", error_cleanup);
+
+    context->state = NV_CREATE_READ_PROFILE;
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+error_cleanup:
+    SAFE_FREE(nvCmd->nvPath);
+    SAFE_FREE(miscNv->policyInstance);
+    return r;
+}
+
+/** Asynchronous finish function for Fapi_CreateNv
+ *
+ * This function should be called after a previous Fapi_CreateNv_Async.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
+ *         complete. Call this function again later.
+ */
+TSS2_RC
+Fapi_CreateNv_Finish(
+    FAPI_CONTEXT *context)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+    ESYS_TR nvHandle;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+
+    /* Helpful alias pointers */
+    IFAPI_NV_Cmds * nvCmd = &(context->nv_cmd);
+    TPM2B_AUTH *auth = &nvCmd->auth;
+    IFAPI_OBJECT *hierarchy = &nvCmd->auth_object;
+    IFAPI_NV * miscNv = &(nvCmd->nv_object.misc.nv);
+    TPM2B_NV_PUBLIC *publicInfo = &miscNv->public;
+    TPM2B_DIGEST * authPolicy = &(miscNv->public.nvPublic.authPolicy);
+    TPMS_POLICY_HARNESS * policyHarness = &(context->policy.harness);
+    TPMS_POLICY_HARNESS ** nvCmdPolicyHarness = &nvCmd->nv_object.policy_harness;
+    ESYS_TR auth_session;
+
+    switch (context->state) {
+        statecase(context->state, NV_CREATE_READ_PROFILE)
+            r = ifapi_merge_profile_into_nv_template(context,
+                    &nvCmd->public_templ);
+            goto_if_error_reset_state(r, "Merge profile", error_cleanup);
+
+            /* Store information from template in context */
+            miscNv->description = NULL;
+            publicInfo->nvPublic = nvCmd->public_templ.public;
+            if (nvCmd->public_templ.hierarchy == TPM2_RH_OWNER) {
+                miscNv->hierarchy = ESYS_TR_RH_OWNER;
+            } else {
+                goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Wrong hierarchy", error_cleanup);
+            }
+            r = ifapi_keystore_load_async(&context->keystore, &context->io, "HS");
+            return_if_error_reset_state(r, "Could not open storage hierarchy  HS");
+            fallthrough;
+
+        statecase(context->state, NV_CREATE_READ_HIERARCHY)
+            r = ifapi_keystore_load_finish(&context->keystore, &context->io,
+                                           &nvCmd->auth_object);
+            return_try_again(r);
+            goto_if_error_reset_state(r, "read_finish failed", error_cleanup);
+
+            r = ifapi_initialize_object(context->esys, &nvCmd->auth_object);
+            goto_if_error_reset_state(r, "Initialize NV object", error_cleanup);
+
+            nvCmd->auth_object.handle
+                =  miscNv->hierarchy;
+            if (miscNv->policyInstance &&
+                    strcmp(miscNv->policyInstance, "") != 0)
+                nvCmd->skip_policy_computation = false;
+            else
+                nvCmd->skip_policy_computation = true;
+            fallthrough;
+
+        statecase(context->state, NV_CREATE_CALCULATE_POLICY)
+            if (!nvCmd->skip_policy_computation) {
+                r = ifapi_calculate_tree(context,
+                                         miscNv->policyInstance,
+                                         policyHarness,
+                                         miscNv->public.nvPublic.nameAlg,
+                                         &context->policy.digest_idx,
+                                         &context->policy.hash_size);
+                return_try_again(r);
+
+                goto_if_error2(r, "Calculate policy tree %s", error_cleanup,
+                               context->cmd.Key_Create.policyPath);
+
+                /* Store the calculated policy in the NV object */
+                *nvCmdPolicyHarness = calloc(1,
+                        sizeof(TPMS_POLICY_HARNESS));
+                goto_if_null(*nvCmdPolicyHarness,
+                        "Out of memory,", TSS2_FAPI_RC_MEMORY, error_cleanup);
+                **(nvCmdPolicyHarness) = *policyHarness;
+
+                authPolicy->size =
+                    context->policy.hash_size;
+                memcpy(&authPolicy->buffer[0],
+                       &policyHarness->policyDigests.digests[context->policy.digest_idx].digest,
+                       context->policy.hash_size);
+                LOGBLOB_TRACE(
+                    &authPolicy->buffer[0],
+                    context->policy.hash_size, "Create Key Policy");
+            }
+            fallthrough;
+
+        statecase(context->state, NV_CREATE_GET_INDEX)
+            r = ifapi_get_nv_start_index(nvCmd->nvPath,
+                                         &publicInfo->nvPublic.nvIndex);
+            goto_if_error_reset_state(r, "FAPI get handle index.", error_cleanup);
+
+            r = ifapi_get_free_handle_async(context, &publicInfo->nvPublic.nvIndex);
+            goto_if_error_reset_state(r, "FAPI get handle index.", error_cleanup);
+            nvCmd->maxNvIndex = publicInfo->nvPublic.nvIndex + 100;
+            context->state = NV_CREATE_FIND_INDEX;
+            fallthrough;
+
+        statecase(context->state, NV_CREATE_FIND_INDEX)
+            r = ifapi_get_free_handle_finish(context, &publicInfo->nvPublic.nvIndex,
+                                             nvCmd->maxNvIndex);
+            return_try_again(r);
+
+            goto_if_error_reset_state(r, "FAPI get handle index.", error_cleanup);
+
+            context->primary_state = PRIMARY_INIT;
+            r = ifapi_get_sessions_async(context,
+                                         IFAPI_SESSION_GENEK | IFAPI_SESSION1,
+                                         0, 0);
+            goto_if_error_reset_state(r, "Create sessions", error_cleanup);
+            fallthrough;
+
+        statecase(context->state, NV_CREATE_WAIT_FOR_SESSION)
+            r = ifapi_get_sessions_finish(context, &context->profiles.default_profile);
+            return_try_again(r);
+
+            goto_if_error_reset_state(r, " FAPI create session", error_cleanup);
+
+            context->state = NV_CREATE_AUTHORIZE_HIERARCHY;
+            fallthrough;
+
+        statecase(context->state, NV_CREATE_AUTHORIZE_HIERARCHY)
+            r = ifapi_authorize_object(context, &nvCmd->auth_object, &auth_session);
+            FAPI_SYNC(r, "Authorize hierarchy.", error_cleanup);
+
+            r = Esys_NV_DefineSpace_Async(context->esys,
+                                          hierarchy->handle,
+                                          auth_session,
+                                          ESYS_TR_NONE,
+                                          ESYS_TR_NONE,
+                                          auth,
+                                          publicInfo);
+            goto_if_error_reset_state(r, " Fapi_CreateNv_Async", error_cleanup);
+            fallthrough;
+
+        statecase(context->state, NV_CREATE_AUTH_SENT)
+            r = Esys_NV_DefineSpace_Finish(context->esys, &nvHandle);
+            return_try_again(r);
+
+            goto_if_error_reset_state(r, "FAPI CreateWithTemplate_Finish", error_cleanup);
+
+            nvCmd->nv_object.handle = nvHandle;
+            if (nvCmd->auth.size > 0)
+                miscNv->with_auth = TPM2_YES;
+            else
+                miscNv->with_auth = TPM2_NO;
+
+            /* Perform esys serialization if necessary */
+            r = ifapi_esys_serialize_object(context->esys, &nvCmd->nv_object);
+            goto_if_error(r, "Prepare serialization", error_cleanup);
+
+            /* Start writing the NV object to the key store */
+            r = ifapi_keystore_store_async(&context->keystore, &context->io,
+                                           nvCmd->nvPath,
+                                           &nvCmd->nv_object);
+            goto_if_error_reset_state(r, "Could not open: %sh", error_cleanup,
+                                      nvCmd->nvPath);
+            context->state = NV_CREATE_WRITE;
+            fallthrough;
+
+        statecase(context->state, NV_CREATE_WRITE)
+            /* Finish writing the NV object to the key store */
+            r = ifapi_keystore_store_finish(&context->keystore, &context->io);
+            return_try_again(r);
+            return_if_error_reset_state(r, "write_finish failed");
+
+            break;
+
+        statecasedefault(context->state);
+    }
+
+    context->state =  _FAPI_STATE_INIT;
+    LOG_DEBUG("success");
+    r = TSS2_RC_SUCCESS;
+
+error_cleanup:
+    ifapi_cleanup_ifapi_object(&nvCmd->nv_object);
+    ifapi_cleanup_ifapi_object(&nvCmd->auth_object);
+    ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
+    ifapi_cleanup_ifapi_object(context->loadKey.key_object);
+    ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
+    SAFE_FREE(miscNv->policyInstance);
+    SAFE_FREE(nvCmd->nvPath);
+    ifapi_session_clean(context);
+    LOG_TRACE("finsihed");
+    return r;
+}
diff --git a/src/tss2-fapi/api/Fapi_CreateSeal.c b/src/tss2-fapi/api/Fapi_CreateSeal.c
new file mode 100644
index 0000000..c3f99f9
--- /dev/null
+++ b/src/tss2-fapi/api/Fapi_CreateSeal.c
@@ -0,0 +1,242 @@
+/* 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 <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#include "tss2_fapi.h"
+#include "fapi_int.h"
+#include "fapi_util.h"
+#include "fapi_policy.h"
+#include "tss2_esys.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+/** One-Call function for Fapi_CreateSeal
+ *
+ * Creates a sealed object and stores it in the FAPI metadata store. If no data
+ * is provided, the TPM generates random data to fill the sealed object.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] path The path to the new sealed object
+ * @param [in] type The type of the new sealed object. May be NULL
+ * @param [in] size The size of the new sealed object. Must not be 0
+ * @param [in] policyPath The path to the policy that is associated with the new
+ *             sealed object. May be NULL
+ * @param [in] authValue The authorization value for the new sealed object. May
+ *             be NULL
+ * @param [in] data The data that is to be sealed within the new object. May be
+ *             NULL
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context, or path is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_KEY_NOT_FOUND: if the parent key does not map to a
+ *         FAPI key.
+ * @retval TSS2_FAPI_RC_BAD_PATH: if policyPath is non-NULL and does not map to
+ *         a FAPI key.
+ * @retval TSS2_FAPI_RC_PATH_ALREADY_EXISTS: if a sealed object already exists
+ *         at path.
+ * @retval TSS2_FAPI_RC_BAD_VALUE: if the keyType is invalid.
+ * @retval TSS2_FAPI_RC_STORAGE_ERROR: if the FAPI storage cannot be updated.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_CreateSeal(
+    FAPI_CONTEXT *context,
+    char    const *path,
+    char    const *type,
+    size_t         size,
+    char    const *policyPath,
+    char    const *authValue,
+    uint8_t const *data)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r, r2;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(path);
+
+    /* Check whether TCTI and ESYS are initialized */
+    return_if_null(context->esys, "Command can't be executed in none TPM mode.",
+                   TSS2_FAPI_RC_NO_TPM);
+
+    /* If the async state automata of FAPI shall be tested, then we must not set
+       the timeouts of ESYS to blocking mode.
+       During testing, the mssim tcti will ensure multiple re-invocations.
+       Usually however the synchronous invocations of FAPI shall instruct ESYS
+       to block until a result is available. */
+#ifndef TEST_FAPI_ASYNC
+    r = Esys_SetTimeout(context->esys, TSS2_TCTI_TIMEOUT_BLOCK);
+    return_if_error_reset_state(r, "Set Timeout to blocking");
+#endif /* TEST_FAPI_ASYNC */
+
+    r = Fapi_CreateSeal_Async(context, path, type, size, policyPath,
+                              authValue, data);
+    return_if_error_reset_state(r, "CreateSeal");
+
+    do {
+        /* We wait for file I/O to be ready if the FAPI state automata
+           are in a file I/O state. */
+        r = ifapi_io_poll(&context->io);
+        return_if_error(r, "Something went wrong with IO polling");
+
+        /* Repeatedly call the finish function, until FAPI has transitioned
+           through all execution stages / states of this invocation. */
+        r = Fapi_CreateSeal_Finish(context);
+    } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
+
+    /* Reset the ESYS timeout to non-blocking, immediate response. */
+    r2 = Esys_SetTimeout(context->esys, 0);
+    return_if_error(r2, "Set Timeout to non-blocking");
+
+    return_if_error_reset_state(r, "CreateSeal");
+
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous function for Fapi_CreateSeal
+ *
+ * Creates a sealed object and stores it in the FAPI metadata store. If no data
+ * is provided, the TPM generates random data to fill the sealed object.
+ *
+ * Call Fapi_CreateSeal_Finish to finish the execution of this command.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] path The path to the new sealed object
+ * @param [in] type The type of the new sealed object. May be NULL
+ * @param [in] size The size of the new sealed object. Must not be 0
+ * @param [in] policyPath The path to the policy that is associated with the new
+ *             sealed object. May be NULL
+ * @param [in] authValue The authorization value for the new sealed object. May
+ *             be NULL
+ * @param [in] data The data that is to be sealed within the new object. May be
+ *             NULL
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context, or path is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_KEY_NOT_FOUND: if the parent key does not map to a
+ *         FAPI key.
+ * @retval TSS2_FAPI_RC_BAD_PATH: if policyPath is non-NULL and does not map to
+ *         a FAPI key.
+ * @retval TSS2_FAPI_RC_PATH_ALREADY_EXISTS: if a sealed object already exists
+ *         at path.
+ * @retval TSS2_FAPI_RC_BAD_VALUE: if the keyType is invalid.
+ * @retval TSS2_FAPI_RC_STORAGE_ERROR: if the FAPI storage cannot be updated.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_CreateSeal_Async(
+    FAPI_CONTEXT *context,
+    char    const *path,
+    char    const *type,
+    size_t         size,
+    char    const *policyPath,
+    char    const *authValue,
+    uint8_t const *data)
+{
+    LOG_TRACE("called for context:%p", context);
+    LOG_TRACE("path: %s", path);
+    LOG_TRACE("type: %s", type);
+    LOG_TRACE("size: %zi", size);
+    LOG_TRACE("policyPath: %s", policyPath);
+    LOG_TRACE("authValue: %s", authValue);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(path);
+
+    r = ifapi_session_init(context);
+    return_if_error(r, "Initialize CreateSeal");
+
+    memset(&context->cmd.Key_Create.public_templ, 0, sizeof(IFAPI_KEY_TEMPLATE));
+
+    r = ifapi_key_create_prepare_sensitive(context, path, policyPath, size,
+                                           authValue, data);
+    return_if_error(r, "Key create.");
+
+    r = ifapi_set_key_flags(type ? type : "",
+                            (policyPath && strcmp(policyPath, "") != 0) ? true : false,
+                            &context->cmd.Key_Create.public_templ);
+    return_if_error(r, "Set key flags for key");
+
+    context->cmd.Key_Create.public_templ.public.publicArea.objectAttributes  &=
+        ~TPMA_OBJECT_SENSITIVEDATAORIGIN;
+
+    context->state = CREATE_SEAL;
+
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous finish function for Fapi_CreateSeal
+ *
+ * This function should be called after a previous Fapi_CreateSeal.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
+ *         complete. Call this function again later.
+ */
+TSS2_RC
+Fapi_CreateSeal_Finish(
+    FAPI_CONTEXT *context)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+
+    switch (context->state) {
+        statecase(context->state, CREATE_SEAL);
+            r = ifapi_key_create(context, &context->cmd.Key_Create.public_templ);
+            return_try_again(r);
+            goto_if_error(r, "Key create", error_cleanup);
+            break;
+
+        statecasedefault(context->state);
+    }
+
+error_cleanup:
+    ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
+    ifapi_cleanup_ifapi_object(context->loadKey.key_object);
+    ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
+    context->state = _FAPI_STATE_INIT;
+    LOG_TRACE("finsihed");
+    return r;
+}
diff --git a/src/tss2-fapi/api/Fapi_Decrypt.c b/src/tss2-fapi/api/Fapi_Decrypt.c
new file mode 100644
index 0000000..c427733
--- /dev/null
+++ b/src/tss2-fapi/api/Fapi_Decrypt.c
@@ -0,0 +1,530 @@
+/* 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 <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#include "tss2_fapi.h"
+#include "fapi_int.h"
+#include "fapi_util.h"
+#include "tss2_esys.h"
+#include "fapi_crypto.h"
+#include "fapi_policy.h"
+#include "ifapi_policyutil_execute.h"
+#include "ifapi_json_deserialize.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+/** One-Call function for Fapi_Decrypt
+ *
+ * Decrypts data that was previously encrypted with Fapi_Encrypt.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] cipherText The ciphertext to decrypt
+ * @param [out] plainText the decrypted ciphertext. May be NULL
+ *              (callee-allocated)
+ * @param [out] plainTextSize The size of the ciphertext in bytes. May be NULL
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or cipherText is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_KEY_NOT_FOUND: if can’t find the key necessary to decrypt
+ *         the file.
+ * @retval TSS2_FAPI_RC_BAD_KEY: if the decryption key is unsuitable for the
+ *         requested operation.
+ * @retval TSS2_FAPI_RC_BAD_VALUE: if the decryption fails
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_Decrypt(
+    FAPI_CONTEXT *context,
+    char   const *cipherText,
+    uint8_t     **plainText,
+    size_t       *plainTextSize)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r, r2;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(cipherText);
+
+    /* Check whether TCTI and ESYS are initialized */
+    return_if_null(context->esys, "Command can't be executed in none TPM mode.",
+                   TSS2_FAPI_RC_NO_TPM);
+
+    /* If the async state automata of FAPI shall be tested, then we must not set
+       the timeouts of ESYS to blocking mode.
+       During testing, the mssim tcti will ensure multiple re-invocations.
+       Usually however the synchronous invocations of FAPI shall instruct ESYS
+       to block until a result is available. */
+#ifndef TEST_FAPI_ASYNC
+    r = Esys_SetTimeout(context->esys, TSS2_TCTI_TIMEOUT_BLOCK);
+    return_if_error_reset_state(r, "Set Timeout to blocking");
+#endif /* TEST_FAPI_ASYNC */
+
+    r = Fapi_Decrypt_Async(context, cipherText);
+    return_if_error_reset_state(r, "Data_Encrypt");
+
+    do {
+        /* We wait for file I/O to be ready if the FAPI state automata
+           are in a file I/O state. */
+        r = ifapi_io_poll(&context->io);
+        return_if_error(r, "Something went wrong with IO polling");
+
+        /* Repeatedly call the finish function, until FAPI has transitioned
+           through all execution stages / states of this invocation. */
+        r = Fapi_Decrypt_Finish(context, plainText, plainTextSize);
+    } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
+
+    /* Reset the ESYS timeout to non-blocking, immediate response. */
+    r2 = Esys_SetTimeout(context->esys, 0);
+    return_if_error(r2, "Set Timeout to non-blocking");
+
+    return_if_error_reset_state(r, "Data_Decrypt");
+
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous function for Fapi_Decrypt
+ *
+ * Decrypts data that was previously encrypted with Fapi_Encrypt.
+ *
+ * Call Fapi_Decrypt_Finish to finish the execution of this command.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] cipherText The ciphertext to decrypt
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or cipherText is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_KEY_NOT_FOUND: if can’t find the key necessary to decrypt
+ *         the file.
+ * @retval TSS2_FAPI_RC_BAD_KEY: if the decryption key is unsuitable for the
+ *         requested operation.
+ * @retval TSS2_FAPI_RC_BAD_VALUE: if the decryption fails
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_Decrypt_Async(
+    FAPI_CONTEXT *context,
+    char   const *cipherText)
+{
+    LOG_TRACE("called for context:%p", context);
+    LOG_TRACE("cipherText: %s", cipherText);
+
+    TSS2_RC r;
+    json_object *jso = NULL;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(cipherText);
+
+    /* Helpful alias pointers */
+    IFAPI_Data_EncryptDecrypt * command = &(context->cmd.Data_EncryptDecrypt);
+    IFAPI_ENCRYPTED_DATA *encData = &command->enc_data;
+
+    r = ifapi_session_init(context);
+    return_if_error(r, "Initialize Decrypt");
+
+    encData->cipher.buffer = NULL;
+    command->out_data = NULL;
+    jso = json_tokener_parse(cipherText);
+    return_if_null(jso, "Json error.", TSS2_FAPI_RC_BAD_VALUE);
+    command->object_handle = ESYS_TR_NONE;
+
+    r = ifapi_json_IFAPI_ENCRYPTED_DATA_deserialize(jso,
+            encData);
+    goto_if_error(r, "Invalid cipher object.", error_cleanup);
+
+    command->in_data =
+        &encData->cipher.buffer[0];
+    command->numBytes =
+        encData->cipher.size;
+
+    /* No sub path in keystore will be used (first param == NULL */
+    r = ifapi_get_entities(&context->keystore, NULL,
+                           &command->pathlist,
+                           &command->numPaths);
+    goto_if_error(r, "get entities.", error_cleanup);
+
+    /* Start with the last path */
+    command->path_idx =
+        command->numPaths;
+
+    r = ifapi_get_sessions_async(context,
+                                 IFAPI_SESSION_GENEK | IFAPI_SESSION1,
+                                 TPMA_SESSION_DECRYPT, 0);
+    goto_if_error_reset_state(r, "Create sessions", error_cleanup);
+
+    json_object_put(jso);
+    context->state = DATA_DECRYPT_WAIT_FOR_SESSION;
+    LOG_TRACE("finsihed");
+    return r;
+
+error_cleanup:
+    if (jso)
+        json_object_put(jso);
+    SAFE_FREE(encData->cipher.buffer);
+
+    return r;
+}
+
+/** Asynchronous finish function for Fapi_Decrypt
+ *
+ * This function should be called after a previous Fapi_Decrypt.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [out] plainText the decrypted ciphertext. May be NULL
+ *              (callee-allocated)
+ * @param [out] plainTextSize The size of the ciphertext in bytes. May be NULL
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context, plainText or plainTextSize
+ *         is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
+ *         complete. Call this function again later.
+ */
+TSS2_RC
+Fapi_Decrypt_Finish(
+    FAPI_CONTEXT *context,
+    uint8_t     **plainText,
+    size_t       *plainTextSize)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+    char *path;
+    UINT32 pathIdx;
+    TPM2B_PUBLIC_KEY_RSA *tpmPlainText = NULL;
+    TPM2B_SENSITIVE_DATA *sym_key = NULL;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+
+    /* Helpful alias pointers */
+    IFAPI_OBJECT *encKeyObject = NULL;
+    IFAPI_Data_EncryptDecrypt * command = &(context->cmd.Data_EncryptDecrypt);
+    IFAPI_ENCRYPTED_DATA *encData = &command->enc_data;
+
+    switch(context->state) {
+        statecase(context->state, DATA_DECRYPT_WAIT_FOR_SESSION);
+            r = ifapi_get_sessions_finish(context, &context->profiles.default_profile);
+            return_try_again(r);
+
+            goto_if_error_reset_state(r, " FAPI create session", error_cleanup);
+            context->state = DATA_DECRYPT_SEARCH_KEY;
+            fallthrough;
+
+        statecase(context->state, DATA_DECRYPT_SEARCH_KEY);
+            r = ifapi_keystore_search_obj(&context->keystore, &context->io,
+                                          &command->enc_data.key_name,
+                                          &path);
+            return_try_again(r);
+            goto_if_error(r, "Search Key", error_cleanup);
+
+            r = ifapi_load_keys_async(context, path);
+            goto_if_error(r, "Load keys.", error_cleanup);
+            LOG_TRACE("Key found.");
+
+            SAFE_FREE(path);
+            context->state = DATA_DECRYPT_WAIT_FOR_KEY;
+            fallthrough;
+
+        statecase(context->state, DATA_DECRYPT_WAIT_FOR_KEY);
+            r = ifapi_load_keys_finish(context, IFAPI_FLUSH_PARENT,
+                                       &command->key_handle,
+                                       &command->key_object);
+            return_try_again(r);
+
+            goto_if_error_reset_state(r, " Load key.", error_cleanup);
+
+            encKeyObject = command->key_object;
+
+            /* Symmetric decryption */
+            if (command->enc_data.type == IFAPI_SYM_BULK_ENCRYPTION
+                    &&
+                    encKeyObject->misc.key.public.publicArea.type == TPM2_ALG_SYMCIPHER) {
+                r = Esys_TRSess_SetAttributes(context->esys, context->session1,
+                                              TPMA_SESSION_CONTINUESESSION,
+                                              0xff);
+
+                goto_if_error_reset_state(r, "Set session attributes.", error_cleanup);
+
+                r = ifapi_sym_encrypt_decrypt_async(context,
+                                                    command->in_data,
+                                                    command->in_dataSize,
+                                                    TPM2_YES); /**< decrypt (not encrypt) */
+                goto_if_error(r, "Symmetric decryption error.", error_cleanup);
+                context-> state = DATA_DECRYPT_WAIT_FOR_SYM_ENCRYPTION;
+                return TSS2_FAPI_RC_TRY_AGAIN;
+            }
+
+            if (command->enc_data.type == IFAPI_ASYM_BULK_ENCRYPTION
+                    &&
+                    encKeyObject->misc.key.public.publicArea.type == TPM2_ALG_RSA) {
+                context-> state = DATA_DECRYPT_AUTHORIZE_KEY;
+                return TSS2_FAPI_RC_TRY_AGAIN;
+            } else {
+                goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Invalid mode", error_cleanup);
+                break;
+            }
+
+        statecase(context->state, DATA_DECRYPT_AUTHORIZE_KEY);
+            r = ifapi_authorize_object(context, command->key_object, &command->auth_session);
+            return_try_again(r);
+            goto_if_error(r, "Authorize signature key.", error_cleanup);
+
+            TPM2B_PRIVATE private;
+
+            private.size = encData->sym_private.size;
+            memcpy(&private.buffer[0], encData->sym_private.buffer, private.size);
+
+            r = Esys_Load_Async(context->esys, command->key_handle,
+                                command->auth_session,
+                                ESYS_TR_NONE, ESYS_TR_NONE,
+                                &private, &encData->sym_public);
+            goto_if_error(r, "Load async", error_cleanup);
+            context->state = DATA_DECRYPT_WAIT_FOR_SEAL_KEY;
+            fallthrough;
+
+        statecase(context->state, DATA_DECRYPT_WAIT_FOR_SEAL_KEY);
+            r = Esys_Load_Finish(context->esys,
+                                 &command->object_handle);
+            return_try_again(r);
+            goto_if_error(r, "Load_Finish", error_cleanup);
+            context->state = DATA_DECRYPT_FLUSH_KEY;
+            fallthrough;
+
+        statecase(context->state, DATA_DECRYPT_FLUSH_KEY);
+            r = Esys_FlushContext_Async(context->esys,
+                                        command->key_handle);
+            goto_if_error(r, "Error: FlushContext", error_cleanup);
+
+            context->state = DATA_DECRYPT_WAIT_FOR_FLUSH;
+            fallthrough;
+
+        statecase(context->state, DATA_DECRYPT_WAIT_FOR_FLUSH);
+            r = Esys_FlushContext_Finish(context->esys);
+            return_try_again(r);
+
+            goto_if_error(r, "Error: FlushContext", error_cleanup);
+            command->key_handle = ESYS_TR_NONE;
+
+            if (!encData->sym_policy_harness.policy) {
+                /* Object can be unsealed without authorization */
+                context->state = DATA_DECRYPT_UNSEAL_OBJECT;
+                return TSS2_FAPI_RC_TRY_AGAIN;
+            }
+            r = ifapi_policyutil_execute_prepare(context,
+                                                 encData->sym_public.publicArea.nameAlg,
+                                                 &encData->sym_policy_harness);
+            return_if_error(r, "Prepare policy execution.");
+
+            context->policy.util_current_policy = context->policy.util_current_policy->prev;
+            command->auth_session = ESYS_TR_NONE;
+
+            fallthrough;
+
+        statecase(context->state, DATA_DECRYPT_EXEC_POLICY);
+            r = ifapi_policyutil_execute(context, &command->auth_session);
+            return_try_again(r);
+            goto_if_error(r, "Execute policy", error_cleanup);
+
+            /* Clear continue session flag, so policy session will be flushed after
+               authorization */
+            r = Esys_TRSess_SetAttributes(context->esys, command->auth_session, 0,
+                                          TPMA_SESSION_CONTINUESESSION);
+            goto_if_error(r, "Esys_TRSess_SetAttributes", error_cleanup);
+
+            fallthrough;
+
+        statecase(context->state, DATA_DECRYPT_UNSEAL_OBJECT);
+            r = Esys_Unseal_Async(context->esys,
+                                  command->object_handle,
+                                  command->auth_session,
+                                  ESYS_TR_NONE, ESYS_TR_NONE);
+            goto_if_error(r, "Error esys Unseal ", error_cleanup);
+            context->state = DATA_DECRYPT_WAIT_FOR_UNSEAL;
+            fallthrough;
+
+        statecase(context->state, DATA_DECRYPT_WAIT_FOR_UNSEAL);
+            r = Esys_Unseal_Finish(context->esys, &sym_key);
+            return_try_again(r);
+            goto_if_error(r, "Unseal_Finish", error_cleanup);
+
+            r = ifapi_crypto_aes_decrypt(&sym_key->buffer[0], encData->sym_key_size,
+                                         &encData->sym_iv.buffer[0],
+                                         encData->cipher.buffer,
+                                         encData->cipher.size);
+            SAFE_FREE(sym_key);
+            goto_if_error(r, "Error esys Unseal ", error_cleanup);
+            if (plainText)
+                *plainText =  encData->cipher.buffer;
+            if (plainTextSize)
+                *plainTextSize =  encData->cipher.size;
+
+            r = Esys_FlushContext_Async(context->esys,
+                                        command->object_handle);
+            goto_if_error(r, "Error: FlushContext", error_cleanup);
+
+            context->state = DATA_DECRYPT_FLUSH_SYM_OBJECT;
+            fallthrough;
+
+        statecase(context->state, DATA_DECRYPT_FLUSH_SYM_OBJECT);
+            r = Esys_FlushContext_Finish(context->esys);
+            return_try_again(r);
+            goto_if_error(r, "Flush object", error_cleanup);
+
+            context->state = DATA_DECRYPT_CLEANUP;
+            return TSS2_FAPI_RC_TRY_AGAIN;
+
+        statecase(context->state, DATA_DECRYPT_NULL_AUTH_SENT);
+            /* This is used later on to differentiate two cases. see below */
+            fallthrough;
+
+        statecase(context->state, DATA_DECRYPT_WAIT_FOR_RSA_DECRYPTION);
+            r =  Esys_RSA_Decrypt_Finish(context->esys, &tpmPlainText);
+
+            return_try_again(r);
+
+            /* Retry with authorization callback after trial with null auth */
+            encKeyObject = command->key_object;
+            if (((r & ~TPM2_RC_N_MASK) == TPM2_RC_BAD_AUTH)
+                    && (encKeyObject->misc.key.public.publicArea.objectAttributes &
+                        TPMA_OBJECT_NODA)
+                    &&  context->state == DATA_DECRYPT_NULL_AUTH_SENT) {
+                context->state = DATA_DECRYPT_WAIT_FOR_RSA_DECRYPTION;
+
+                r = ifapi_set_auth(context, encKeyObject, "Decrypt Key");
+                goto_if_error_reset_state(r, " Fapi_Decrypt", error_cleanup);
+
+                TPM2B_PUBLIC_KEY_RSA *auxData = (TPM2B_PUBLIC_KEY_RSA *)&context->aux_data;
+                TPM2B_DATA null_data = {.size = 0, .buffer = {} };
+                const IFAPI_PROFILE *profile;
+
+                pathIdx = command->path_idx;
+                path = command->pathlist[pathIdx];
+
+                r = ifapi_profiles_get(&context->profiles, path, &profile);
+                goto_if_error(r, "Retrieving profiles data", error_cleanup);
+
+                r = Esys_RSA_Decrypt_Async(context->esys,
+                                           command->key_handle,
+                                           context->session1, ESYS_TR_NONE, ESYS_TR_NONE,
+                                           auxData,
+                                           &profile->rsa_decrypt_scheme,
+                                           &null_data);
+                goto_if_error(r, "Error esys rsa decrypt", error_cleanup);
+
+                return TSS2_FAPI_RC_TRY_AGAIN;
+            }
+
+            goto_if_error_reset_state(r, "RSA decryption.", error_cleanup);
+
+            if (plainTextSize)
+                *plainTextSize = tpmPlainText->size;
+            if (plainText) {
+                *plainText = malloc(tpmPlainText->size);
+                goto_if_null(*plainText, "Out of memory", TSS2_FAPI_RC_MEMORY, error_cleanup);
+
+                memcpy(*plainText, &tpmPlainText->buffer[0], tpmPlainText->size);
+                free(tpmPlainText);
+            }
+            context-> state = DATA_DECRYPT_FLUSH_KEY;
+            return TSS2_FAPI_RC_TRY_AGAIN;
+
+        statecase(context->state, DATA_DECRYPT_WAIT_FOR_SYM_ENCRYPTION);
+            r = ifapi_sym_encrypt_decrypt_finish(context, plainText, plainTextSize,
+                                                 TPM2_YES);
+            return_try_again(r);
+
+            goto_if_error_reset_state(r, "Symmetric encryption.", error_cleanup);
+
+            fallthrough;
+
+        statecase(context->state, DATA_DECRYPT_CLEANUP)
+            r = ifapi_cleanup_session(context);
+            try_again_or_error_goto(r, "Cleanup", error_cleanup);
+
+            break;
+
+        statecasedefault(context->state);
+    }
+
+    context->state =  _FAPI_STATE_INIT;
+
+    /* Cleanup of local objects */
+    SAFE_FREE(tpmPlainText);
+
+    /* Cleanup of command related objects */
+    ifapi_cleanup_ifapi_object(command->key_object);
+    for (size_t i = 0; i < command->numPaths; i++) {
+        SAFE_FREE(command->pathlist[i]);
+    }
+    SAFE_FREE(command->pathlist);
+
+    /* Cleanup of encryption data related objects */
+    ifapi_cleanup_policy_harness(&encData->sym_policy_harness);
+    SAFE_FREE(encData->sym_private.buffer);
+
+    /* Cleanup of context related objects */
+    ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
+    ifapi_cleanup_ifapi_object(context->loadKey.key_object);
+
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+
+error_cleanup:
+    /* Cleanup of local objects */
+    SAFE_FREE(tpmPlainText);
+
+    /* Cleanup of command related objects */
+    ifapi_cleanup_ifapi_object(command->key_object);
+    ifapi_cleanup_policy_harness(&encData->sym_policy_harness);
+    for (size_t i = 0; i < command->numPaths; i++) {
+        SAFE_FREE(command->pathlist[i]);
+    }
+    SAFE_FREE(command->pathlist);
+
+    /* Cleanup of encryption data related objects */
+    SAFE_FREE(encData->cipher.buffer);
+    SAFE_FREE(encData->sym_private.buffer);
+
+    /* Cleanup of context related objects */
+    if (command->key_handle != ESYS_TR_NONE)
+        Esys_FlushContext(context->esys, command->key_handle);
+    ifapi_session_clean(context);
+    ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
+    ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
+    ifapi_cleanup_ifapi_object(context->loadKey.key_object);
+
+    return r;
+}
diff --git a/src/tss2-fapi/api/Fapi_Delete.c b/src/tss2-fapi/api/Fapi_Delete.c
new file mode 100644
index 0000000..019f285
--- /dev/null
+++ b/src/tss2-fapi/api/Fapi_Delete.c
@@ -0,0 +1,439 @@
+/* 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 <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "tss2_fapi.h"
+#include "fapi_int.h"
+#include "fapi_util.h"
+#include "tss2_esys.h"
+#include "ifapi_json_serialize.h"
+#include "ifapi_json_deserialize.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+
+/** One-Call function for Fapi_Delete
+ *
+ * Deletes a given key, policy or NV index from the system.
+ *
+ * @param[in, out] context The ESAPI_CONTEXT
+ * @param[in] path The path to the entity that is to be deleted
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or path is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_PATH: if path does not map to a FAPI entity.
+ * @retval TSS2_FAPI_RC_NOT_DELETABLE: if the entity is not deletable or the
+ *         path is read-only.
+ * @retval TSS2_FAPI_RC_STORAGE_ERROR: if the FAPI storage cannot be updated.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_Delete(
+    FAPI_CONTEXT   *context,
+    char     const *path)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(path);
+
+    r = Fapi_Delete_Async(context, path);
+    return_if_error_reset_state(r, "Entity_Delete");
+
+    do {
+        /* We wait for file I/O to be ready if the FAPI state automata
+           are in a file I/O state. */
+        r = ifapi_io_poll(&context->io);
+        return_if_error(r, "Something went wrong with IO polling");
+
+        /* Repeatedly call the finish function, until FAPI has transitioned
+           through all execution stages / states of this invocation. */
+        r = Fapi_Delete_Finish(context);
+    } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
+
+    return_if_error_reset_state(r, "Entity_Delete");
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous function for Fapi_Delete
+ *
+ * Deletes a given key, policy or NV index from the system.
+
+ * Call Fapi_Delete_Finish to finish the execution of this command.
+ *
+ * @param[in, out] context The ESAPI_CONTEXT
+ * @param[in] path The path to the entity that is to be deleted
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or path is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_PATH: if path does not map to a FAPI entity.
+ * @retval TSS2_FAPI_RC_NOT_DELETABLE: if the entity is not deletable or the
+ *         path is read-only.
+ * @retval TSS2_FAPI_RC_STORAGE_ERROR: if the FAPI storage cannot be updated.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_Delete_Async(
+    FAPI_CONTEXT   *context,
+    char     const *path)
+{
+    LOG_TRACE("called for context:%p", context);
+    LOG_TRACE("path: %s", path);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(path);
+
+    /* Helpful alias pointers */
+    IFAPI_Entity_Delete * command = &(context->cmd.Entity_Delete);
+    IFAPI_OBJECT *object = &command->object;
+    IFAPI_OBJECT *authObject = &command->auth_object;
+
+    strdup_check(command->path, path, r, error_cleanup);
+
+    r = ifapi_keystore_list_all(&context->keystore, path, &command->pathlist,
+                               &command->numPaths);
+    return_if_error(r, "get entities.");
+
+    command->path_idx = command->numPaths;
+
+    if (command->numPaths == 0) {
+        goto_error(r, TSS2_FAPI_RC_BAD_PATH, "No objects found.", error_cleanup);
+    }
+
+    object->objectType = IFAPI_OBJ_NONE;
+    authObject->objectType = IFAPI_OBJ_NONE;
+
+    if (ifapi_path_type_p(path, IFAPI_EXT_PATH) ||
+        (ifapi_path_type_p(path, IFAPI_POLICY_PATH))) {
+        /* No session will be needed these files can be deleted without
+           interaction with the TPM */
+        r = ifapi_non_tpm_mode_init(context);
+        return_if_error(r, "Initialize Entity_Delete");
+
+        context->state =  ENTITY_DELETE_GET_FILE;
+    } else {
+        /* Check whether TCTI and ESYS are initialized */
+        return_if_null(context->esys, "Command can't be executed in none TPM mode.",
+                       TSS2_FAPI_RC_NO_TPM);
+
+        /* If the async state automata of FAPI shall be tested, then we must not set
+           the timeouts of ESYS to blocking mode.
+           During testing, the mssim tcti will ensure multiple re-invocations.
+           Usually however the synchronous invocations of FAPI shall instruct ESYS
+           to block until a result is available. */
+#ifndef TEST_FAPI_ASYNC
+        r = Esys_SetTimeout(context->esys, TSS2_TCTI_TIMEOUT_BLOCK);
+        return_if_error_reset_state(r, "Set Timeout to blocking");
+#endif /* TEST_FAPI_ASYNC */
+
+        /* A TPM session will be created to enable object authorization */
+        r = ifapi_session_init(context);
+        return_if_error(r, "Initialize Entity_Delete");
+
+        r = ifapi_get_sessions_async(context,
+                                 IFAPI_SESSION_GENEK | IFAPI_SESSION1,
+                                 0, 0);
+        goto_if_error_reset_state(r, "Create sessions", error_cleanup);
+
+        context->state = ENTITY_DELETE_WAIT_FOR_SESSION;
+    }
+
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+
+error_cleanup:
+    SAFE_FREE(command->path);
+    if (Esys_FlushContext(context->esys, context->session1) != TSS2_RC_SUCCESS) {
+        LOG_ERROR("Cleanup session failed.");
+    }
+    return r;
+}
+
+
+/** Asynchronous finish function for Fapi_Delete
+ *
+ * This function should be called after a previous Fapi_Delete_Async.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
+ *         complete. Call this function again later.
+ */
+TSS2_RC
+Fapi_Delete_Finish(
+    FAPI_CONTEXT   *context)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+    ESYS_TR authIndex;
+    ESYS_TR auth_session;
+    char *path;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+
+    /* Helpful alias pointers */
+    IFAPI_Entity_Delete * command = &(context->cmd.Entity_Delete);
+    IFAPI_OBJECT *object = &command->object;
+    IFAPI_OBJECT *authObject = &command->auth_object;
+
+    switch (context->state) {
+        statecase(context->state, ENTITY_DELETE_WAIT_FOR_SESSION);
+            r = ifapi_get_sessions_finish(context, &context->profiles.default_profile);
+            return_try_again(r);
+            goto_if_error(r, "Create FAPI session.", error_cleanup);
+            context->state = ENTITY_DELETE_GET_FILE;
+            fallthrough;
+
+        statecase(context->state, ENTITY_DELETE_GET_FILE);
+            /* Use last path in the path list */
+            command->path_idx -= 1;
+            path =  command->pathlist[command->path_idx];
+            LOG_TRACE("Delete object: %s %zu", path, command->path_idx);
+
+            if (ifapi_path_type_p(path, IFAPI_EXT_PATH)) {
+                /* External keyfile can be deleted directly */
+                context->state = ENTITY_DELETE_FILE;
+                return TSS2_FAPI_RC_TRY_AGAIN;
+            }
+
+            if (ifapi_path_type_p(path, IFAPI_POLICY_PATH)) {
+                /* Policy file can be deleted directly */
+                context->state = ENTITY_DELETE_POLICY;
+                return TSS2_FAPI_RC_TRY_AGAIN;
+            }
+
+            r = ifapi_keystore_load_async(&context->keystore, &context->io, path);
+            return_if_error2(r, "Could not open: %s", path);
+
+            context->state = ENTITY_DELETE_READ;
+            fallthrough;
+
+        statecase(context->state, ENTITY_DELETE_READ);
+            r = ifapi_keystore_load_finish(&context->keystore, &context->io, object);
+            return_try_again(r);
+            return_if_error_reset_state(r, "read_finish failed");
+
+            r = ifapi_initialize_object(context->esys, object);
+            goto_if_error_reset_state(r, "Initialize NV object", error_cleanup);
+
+            if (object->objectType == IFAPI_KEY_OBJ) {
+                command->is_key = true;
+                context->state =  ENTITY_DELETE_KEY;
+                return TSS2_FAPI_RC_TRY_AGAIN;
+
+            } else  if (object->objectType == IFAPI_NV_OBJ) {
+                command->is_key = false;
+
+                if (object->misc.nv.hierarchy == ESYS_TR_RH_OWNER) {
+                    authIndex = ESYS_TR_RH_OWNER;
+                    ifapi_init_hierarchy_object(authObject, authIndex);
+                } else {
+                    *authObject = *object;
+                    authIndex = object->handle;
+                }
+                command->auth_index = authIndex;
+                context->state = ENTITY_DELETE_AUTHORIZE_NV;
+            } else {
+                context->state = ENTITY_DELETE_FILE;
+                return TSS2_FAPI_RC_TRY_AGAIN;
+            }
+            fallthrough;
+
+        statecase(context->state, ENTITY_DELETE_AUTHORIZE_NV);
+            r = ifapi_authorize_object(context, authObject, &auth_session);
+            return_try_again(r);
+            goto_if_error(r, "Authorize NV object.", error_cleanup);
+
+            r = Esys_NV_UndefineSpace_Async(context->esys,
+                                            command->auth_index,
+                                            object->handle,
+                                            auth_session,
+                                            ESYS_TR_NONE,
+                                            ESYS_TR_NONE);
+            goto_if_error_reset_state(r, " Fapi_NV_UndefineSpace_Async", error_cleanup);
+
+            context->state = ENTITY_DELETE_NULL_AUTH_SENT_FOR_NV;
+            return TSS2_FAPI_RC_TRY_AGAIN;
+
+        statecase(context->state, ENTITY_DELETE_KEY);
+            if (object->misc.key.persistent_handle) {
+                r = Esys_EvictControl_Async(context->esys, ESYS_TR_RH_OWNER,
+                                            object->handle,
+                                            context->session1,
+                                            ESYS_TR_NONE, ESYS_TR_NONE,
+                                            object->misc.key.persistent_handle);
+                goto_if_error(r, "Evict Control", error_cleanup);
+                context->state = ENTITY_DELETE_NULL_AUTH_SENT_FOR_KEY;
+            } else {
+                context->state = ENTITY_DELETE_FILE;
+                return TSS2_FAPI_RC_TRY_AGAIN;
+            }
+            fallthrough;
+
+        statecase(context->state, ENTITY_DELETE_AUTH_SENT_FOR_KEY);
+            fallthrough;
+        statecase(context->state, ENTITY_DELETE_NULL_AUTH_SENT_FOR_KEY);
+            r = Esys_EvictControl_Finish(context->esys,
+                                         &command->new_object_handle);
+            return_try_again(r);
+            if ((r & ~TPM2_RC_N_MASK) == TPM2_RC_BAD_AUTH) {
+                if (context->state == ENTITY_DELETE_NULL_AUTH_SENT_FOR_KEY) {
+                    ifapi_init_hierarchy_object(authObject,
+                                                TPM2_RH_OWNER);
+                    r = ifapi_set_auth(context, authObject,
+                                       "Owner Authorization");
+                    goto_if_error_reset_state(r, "Set owner authorization", error_cleanup);
+
+                    context->state = ENTITY_DELETE_AUTH_SENT_FOR_KEY;
+                    return TSS2_FAPI_RC_TRY_AGAIN;
+                }
+            }
+            goto_if_error_reset_state(r, "FAPI Entity_Delete", error_cleanup);
+
+            context->state = ENTITY_DELETE_FILE;
+            return TSS2_FAPI_RC_TRY_AGAIN;
+            break;
+
+        statecase(context->state, ENTITY_DELETE_AUTH_SENT_FOR_NV);
+            fallthrough;
+        statecase(context->state, ENTITY_DELETE_NULL_AUTH_SENT_FOR_NV);
+            r = Esys_NV_UndefineSpace_Finish(context->esys);
+            return_try_again(r);
+
+            if ((r & ~TPM2_RC_N_MASK) == TPM2_RC_BAD_AUTH) {
+                if (context->state == ENTITY_DELETE_NULL_AUTH_SENT_FOR_NV) {
+                    r = ifapi_set_auth(context, authObject, "Entity Delete object");
+                    goto_if_error_reset_state(r, " Fapi_NV_UndefineSpace", error_cleanup);
+
+                    r = Esys_NV_UndefineSpace_Async(context->esys,
+                                                    command->auth_index,
+                                                    object->handle,
+                                                    context->session1,
+                                                    context->session2,
+                                                    ESYS_TR_NONE);
+                    goto_if_error_reset_state(r, "FAPI Entity_Delete", error_cleanup);
+
+                    context->state = ENTITY_DELETE_AUTH_SENT_FOR_NV;
+                    return TSS2_FAPI_RC_TRY_AGAIN;
+                }
+            }
+            goto_if_error_reset_state(r, "FAPI NV_UndefineSpace", error_cleanup);
+
+            LOG_TRACE("NV Object undefined.");
+            context->state = ENTITY_DELETE_FILE;
+            return TSS2_FAPI_RC_TRY_AGAIN;
+            break;
+
+        statecase(context->state, ENTITY_DELETE_POLICY);
+            path = command->pathlist[command->path_idx];
+            LOG_TRACE("Delete: %s", path);
+
+            r = ifapi_policy_delete(&context->pstore, path);
+            goto_if_error_reset_state(r, "Could not delete: %s", error_cleanup, path);
+
+            if (command->path_idx > 0)
+                context->state = ENTITY_DELETE_GET_FILE;
+            else
+                context->state = ENTITY_DELETE_REMOVE_DIRS;
+            return TSS2_FAPI_RC_TRY_AGAIN;
+
+        statecase(context->state, ENTITY_DELETE_FILE);
+            path = command->pathlist[command->path_idx];
+            LOG_TRACE("Delete: %s", path);
+            ifapi_cleanup_ifapi_object(object);
+            ifapi_cleanup_ifapi_object(authObject);
+
+            r = ifapi_keystore_delete(&context->keystore, path);
+            goto_if_error_reset_state(r, "Could not delete: %s", error_cleanup, path);
+
+            if (command->path_idx > 0) {
+                context->state = ENTITY_DELETE_GET_FILE;
+                return TSS2_FAPI_RC_TRY_AGAIN;
+            }
+            context->state = ENTITY_DELETE_REMOVE_DIRS;
+            fallthrough;
+
+        statecase(context->state, ENTITY_DELETE_REMOVE_DIRS);
+            r = ifapi_keystore_remove_directories(&context->keystore, command->path);
+            goto_if_error(r, "Error while removing directories", error_cleanup);
+
+            context->state =  _FAPI_STATE_INIT;
+
+            LOG_DEBUG("success");
+            r = TSS2_RC_SUCCESS;
+            break;
+
+        statecasedefault(context->state);
+    }
+
+    /* Reset the ESYS timeout to non-blocking, immediate response. */
+    if (context->esys) {
+        r = Esys_SetTimeout(context->esys, 0);
+        goto_if_error(r, "Set Timeout to non-blocking", error_cleanup);
+    }
+
+    SAFE_FREE(command->path);
+    ifapi_cleanup_ifapi_object(authObject);
+    ifapi_cleanup_ifapi_object(object);
+    for (size_t i = 0; i < command->numPaths; i++) {
+        SAFE_FREE(command->pathlist[i]);
+    }
+    SAFE_FREE(command->pathlist);
+    ifapi_session_clean(context);
+    ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
+    ifapi_cleanup_ifapi_object(context->loadKey.key_object);
+    ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
+    LOG_TRACE("finsihed");
+    return r;
+
+error_cleanup:
+    Esys_SetTimeout(context->esys, 0);
+    ifapi_cleanup_ifapi_object(object);
+    SAFE_FREE(command->path);
+    for (size_t i = 0; i < command->numPaths; i++) {
+        SAFE_FREE(command->pathlist[i]);
+    }
+    SAFE_FREE(command->pathlist);
+    ifapi_session_clean(context);
+    ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
+    return r;
+}
diff --git a/src/tss2-fapi/api/Fapi_Encrypt.c b/src/tss2-fapi/api/Fapi_Encrypt.c
new file mode 100644
index 0000000..65c2c62
--- /dev/null
+++ b/src/tss2-fapi/api/Fapi_Encrypt.c
@@ -0,0 +1,527 @@
+/* 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 <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#include "tss2_fapi.h"
+#include "fapi_int.h"
+#include "fapi_util.h"
+#include "tss2_esys.h"
+#include "ifapi_json_serialize.h"
+#include "fapi_policy.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+#include "fapi_crypto.h"
+
+#define IV_SIZE 16
+
+/** One-Call function for Fapi_Encrypt
+ *
+ * Encrypts the provided data with a given target key.
+ * If keypath is an asymmetric key and a plainText with
+ * size >= TPM2_MAX_SYM_SIZE is provided, Fapi_Encrypt() will bulk-encrypt the
+ * plainText with an intermediate symmetric key and then “seal” this
+ * intermediate symmetric key with keyPath as a KEYEDHASH TPM object. This
+ * keyPath may refer to the local TPM or to a public key of a remote TPM where
+ * the KEYEDHASH can be imported. The decrypt operation performs a TPM2_Unseal.
+ * ciphertext output contains a reference to the decryption key, the sealed
+ * symmetric key (if any), the policy instance, and the encrypted plainText.
+ *
+ * If plainText has a size <= TPM2_MAX_SYM_SIZE the plainText is sealed
+ * directly for keyPath.
+ *
+ * If encrypting for the local TPM (if keyPath is not from the external
+ * hierarchy), a storage key (symmetric or asymmetric) is required as keyPath
+ * (aka parent key) and the data intermediate symmetric key is created using
+ * TPM2_Create() as a KEYEDHASH object.
+ *
+ * If encrypting for a remote TPM, an asymmetric storage key is required as
+ * keyPath (aka parent key), and the data/intermediate symmetric key is
+ * encrypted such that it can be used in a TPM2_Import operation.
+ *
+ * @param [in,out] context The FAPI_CONTEXT
+ * @param [in] keyPath THe path to the encryption key
+ * @param [in] policyPath The path to the policy the sealed data will be
+ *        associated with. May be NULL
+ * @param [in] plainText The plaintext data to encrypt
+ * @param [in] plainTextSize The size of the plainText in bytes
+ * @param [out] cipherText The JSON-encoded ciphertext
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context, keyPath, plainText, or
+ *         cipherText is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_KEY_NOT_FOUND: if keyPath does not map to a FAPI key.
+ * @retval TSS2_FAPI_RC_BAD_KEY: if the key at keyPath is unsuitable for
+ *         encryption.
+ * @retval TSS2_RC_BAD_VALUE: if plainTextSize is 0.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_Encrypt(
+    FAPI_CONTEXT  *context,
+    char    const *keyPath,
+    char    const *policyPath,
+    uint8_t const *plainText,
+    size_t         plainTextSize,
+    char         **cipherText)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r, r2;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(keyPath);
+    check_not_null(plainText);
+    check_not_null(cipherText);
+
+    /* Check whether TCTI and ESYS are initialized */
+    return_if_null(context->esys, "Command can't be executed in none TPM mode.",
+                   TSS2_FAPI_RC_NO_TPM);
+
+    /* If the async state automata of FAPI shall be tested, then we must not set
+       the timeouts of ESYS to blocking mode.
+       During testing, the mssim tcti will ensure multiple re-invocations.
+       Usually however the synchronous invocations of FAPI shall instruct ESYS
+       to block until a result is available. */
+#ifndef TEST_FAPI_ASYNC
+    r = Esys_SetTimeout(context->esys, TSS2_TCTI_TIMEOUT_BLOCK);
+    return_if_error_reset_state(r, "Set Timeout to blocking");
+#endif /* TEST_FAPI_ASYNC */
+
+    r = Fapi_Encrypt_Async(context, keyPath, policyPath, plainText, plainTextSize);
+    return_if_error_reset_state(r, "Data_Encrypt");
+
+    do {
+        /* We wait for file I/O to be ready if the FAPI state automata
+           are in a file I/O state. */
+        r = ifapi_io_poll(&context->io);
+        return_if_error(r, "Something went wrong with IO polling");
+
+        /* Repeatedly call the finish function, until FAPI has transitioned
+           through all execution stages / states of this invocation. */
+        r = Fapi_Encrypt_Finish(context, cipherText);
+    } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
+
+    /* Reset the ESYS timeout to non-blocking, immediate response. */
+    r2 = Esys_SetTimeout(context->esys, 0);
+    return_if_error(r2, "Set Timeout to non-blocking");
+
+    return_if_error_reset_state(r, "Data_Encrypt");
+
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous function for Fapi_Encrypt
+ *
+ * Encrypts the provided data with a given target key.
+ * If keypath is an asymmetric key and a plainText with
+ * size >= TPM2_MAX_SYM_SIZE is provided, Fapi_Encrypt() will bulk-encrypt the
+ * plainText with an intermediate symmetric key and then “seal” this
+ * intermediate symmetric key with keyPath as a KEYEDHASH TPM object. This
+ * keyPath may refer to the local TPM or to a public key of a remote TPM where
+ * the KEYEDHASH can be imported. The decrypt operation performs a TPM2_Unseal.
+ * ciphertext output contains a reference to the decryption key, the sealed
+ * symmetric key (if any), the policy instance, and the encrypted plainText.
+ *
+ * If plainText has a size <= TPM2_MAX_SYM_SIZE the plainText is sealed
+ * directly for keyPath.
+ *
+ * If encrypting for the local TPM (if keyPath is not from the external
+ * hierarchy), a storage key (symmetric or asymmetric) is required as keyPath
+ * (aka parent key) and the data intermediate symmetric key is created using
+ * TPM2_Create() as a KEYEDHASH object.
+ *
+ * If encrypting for a remote TPM, an asymmetric storage key is required as
+ * keyPath (aka parent key), and the data/intermediate symmetric key is
+ * encrypted such that it can be used in a TPM2_Import operation.
+ *
+ * Call Fapi_Encrypt_Finish to finish the execution of this command.
+ *
+ * @param [in,out] context The FAPI_CONTEXT
+ * @param [in] keyPath The path to the encryption key
+ * @param [in] policyPath The path to the policy the sealed data will be
+ *        associated with. May be NULL
+ * @param [in] plainText The plainText data to encrypt
+ * @param [in] plainTextSize The size of the plainText in bytes
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context, keyPath or plainText is
+ *         NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_KEY_NOT_FOUND: if keyPath does not map to a FAPI key.
+ * @retval TSS2_FAPI_RC_BAD_KEY: if the key at keyPath is unsuitable for
+ *         encryption.
+ * @retval TSS2_RC_BAD_VALUE: if plainTextSize is 0.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_Encrypt_Async(
+    FAPI_CONTEXT  *context,
+    char    const *keyPath,
+    char    const *policyPath,
+    uint8_t const *plainText,
+    size_t         plainTextSize)
+{
+    LOG_TRACE("called for context:%p", context);
+    LOG_TRACE("keyPath: %s", keyPath);
+    LOG_TRACE("policyPath: %s", policyPath);
+    if (plainText) {
+        LOGBLOB_TRACE(plainText, plainTextSize, "plainText");
+    } else {
+        LOG_TRACE("plainText: (null) plainTextSize: %zi", plainTextSize);
+    }
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(keyPath);
+    check_not_null(plainText);
+
+    /* Helpful alias pointers */
+    IFAPI_Data_EncryptDecrypt * command = &(context->cmd.Data_EncryptDecrypt);
+
+    r = ifapi_session_init(context);
+    return_if_error(r, "Initialize Encrypt");
+
+    uint8_t * inData = malloc(plainTextSize);
+    goto_if_null(inData, "Out of memory", r, error_cleanup);
+    memcpy(inData, plainText, plainTextSize);
+    command->in_data = inData;
+
+    strdup_check(command->keyPath, keyPath, r, error_cleanup);
+    strdup_check(command->policyPath, policyPath, r, error_cleanup);
+
+    command->in_dataSize = plainTextSize;
+    command->key_handle = ESYS_TR_NONE;
+
+    context->state = DATA_ENCRYPT_WAIT_FOR_PROFILE;
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+error_cleanup:
+    SAFE_FREE(inData);
+    SAFE_FREE(command->keyPath);
+    SAFE_FREE(command->policyPath);
+    return r;
+}
+
+/** Asynchronous finish function for Fapi_Encrypt
+ *
+ * This function should be called after a previous Fapi_Encrypt_Async.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [out] cipherText The JSON-encoded ciphertext
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or ciphertext is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
+ *         complete. Call this function again later.
+ */
+TSS2_RC
+Fapi_Encrypt_Finish(
+    FAPI_CONTEXT  *context,
+    char         **cipherText)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+    uint8_t *cipher;
+    size_t cipherSize;
+    json_object *jso = NULL;
+    const char *jso_string = NULL;
+    uint8_t *data;
+    size_t key_length;
+    ESYS_TR auth_session;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(cipherText);
+
+    /* Helpful alias pointers */
+    IFAPI_Data_EncryptDecrypt * command = &context->cmd.Data_EncryptDecrypt;
+    IFAPI_ENCRYPTED_DATA *encData = &command->enc_data;
+    TPM2B_SENSITIVE_DATA * sensitiveData = &command->sym_sensitive.sensitive.data;
+    TPMS_POLICY_HARNESS *policyHarness = NULL;
+    const IFAPI_PROFILE *profile;
+    IFAPI_OBJECT *encKeyObject;
+    TPM2B_PUBLIC_KEY_RSA *tpmCipherText = NULL;
+
+    switch (context->state) {
+        statecase(context->state, DATA_ENCRYPT_WAIT_FOR_PROFILE);
+            command->outPublic = NULL;
+            command->outPrivate = NULL;
+
+            r = ifapi_get_sessions_async(context,
+                                         IFAPI_SESSION_GENEK | IFAPI_SESSION1,
+                                         TPMA_SESSION_ENCRYPT | TPMA_SESSION_DECRYPT, 0);
+            goto_if_error_reset_state(r, "Create sessions", error_cleanup);
+
+            context->state = DATA_ENCRYPT_WAIT_FOR_SESSION;
+            fallthrough;
+
+        statecase(context->state, DATA_ENCRYPT_WAIT_FOR_SESSION);
+            r = ifapi_profiles_get(&context->profiles, command->keyPath,
+                                   &profile);
+            goto_if_error_reset_state(r, " FAPI create session", error_cleanup);
+
+            r = ifapi_get_sessions_finish(context, profile);
+            return_try_again(r);
+
+            goto_if_error_reset_state(r, " FAPI create session", error_cleanup);
+
+            r = ifapi_load_keys_async(context, command->keyPath);
+            goto_if_error(r, "Load keys.", error_cleanup);
+
+            context->state = DATA_ENCRYPT_WAIT_FOR_KEY;
+            fallthrough;
+
+        statecase(context->state, DATA_ENCRYPT_WAIT_FOR_KEY);
+            r = ifapi_load_keys_finish(context, IFAPI_FLUSH_PARENT,
+                                       &command->key_handle,
+                                       &command->key_object);
+            return_try_again(r);
+
+            goto_if_error_reset_state(r, " Load key.", error_cleanup);
+
+            encKeyObject = command->key_object;
+
+            if (encKeyObject->misc.key.public.publicArea.type == TPM2_ALG_SYMCIPHER) {
+                r = ifapi_sym_encrypt_decrypt_async(context,
+                                                    command->in_data,
+                                                    command->in_dataSize,
+                                                    TPM2_NO); /**< encrypt (not decrypt) */
+                goto_if_error(r, "Symmetric encryption error.", error_cleanup);
+                context-> state = DATA_ENCRYPT_WAIT_FOR_SYM_ENCRYPTION;
+                return TSS2_FAPI_RC_TRY_AGAIN;
+            } else if (encKeyObject->misc.key.public.publicArea.type == TPM2_ALG_RSA) {
+
+                TPM2B_PUBLIC_KEY_RSA *rsa_message = (TPM2B_PUBLIC_KEY_RSA *)&context->aux_data;
+                rsa_message->size =  command->in_dataSize;
+
+                r =  ifapi_load_sym_key_template(&command->sym_template);
+                goto_if_error_reset_state(r, "Load template.", error_cleanup);
+
+                context-> state = DATA_ENCRYPT_GEN_SYM_KEY;
+            }
+            fallthrough;
+
+        statecase(context->state, DATA_ENCRYPT_GEN_SYM_KEY);
+            /* Generate random key which will be sealed by currently loaded key */
+            memset(&command->sym_sensitive, 0,
+                   sizeof(TPM2B_SENSITIVE_CREATE));
+            memset(&command->sym_outsideInfo, 0,
+                   sizeof(TPM2B_DATA));
+            memset(&command->sym_creationPCR, 0,
+                   sizeof(TPML_PCR_SELECTION));
+            sensitiveData->size = 16;
+            encData->sym_key_size =
+                sensitiveData->size;
+            /* Generate random data for key and IV_SIZE bytes for iv */
+            r = ifapi_get_random(context, encData->sym_key_size + IV_SIZE,
+                                 &command->sym_key);
+            return_try_again(r);
+            goto_if_error(r, "Get random", error_cleanup);
+
+            r = ifapi_get_name(&context->loadKey.auth_object.misc.key.public.publicArea,
+                               &encData->key_name);
+            goto_if_error(r, "Compute key name.", error_cleanup);
+
+
+            memcpy(&sensitiveData->buffer[0],
+                   command->sym_key,
+                   sensitiveData->size);
+            encData->sym_iv.size = IV_SIZE;
+            memcpy(&encData->sym_iv.buffer[0],
+                   &command->sym_key[encData->sym_key_size], IV_SIZE);
+
+            SAFE_FREE(command->sym_key);
+            if (!command->policyPath ||
+                    strcmp(command->policyPath, "") == 0) {
+                context->state = DATA_ENCRYPT_AUTHORIZE;
+                return TSS2_FAPI_RC_TRY_AGAIN;
+            } else {
+                context-> state = DATA_ENCRYPT_CALCULATE_POLICY;
+            }
+            fallthrough;
+
+        statecase(context->state, DATA_ENCRYPT_CALCULATE_POLICY);
+            r =  ifapi_calculate_policy_for_key(context,
+                                                command->policyPath,
+                                                &command->sym_template,
+                                                &policyHarness);
+            return_try_again(r);
+            goto_if_error(r, "Calculate policy for sealed key", error_cleanup);
+
+            if (policyHarness) {
+                command->enc_data.sym_policy_harness = *policyHarness;
+                SAFE_FREE(policyHarness);
+            }
+
+            context-> state = DATA_ENCRYPT_AUTHORIZE;
+            fallthrough;
+
+        statecase(context->state, DATA_ENCRYPT_AUTHORIZE);
+        r = ifapi_authorize_object(context, command->key_object, &auth_session);
+            return_try_again(r);
+            goto_if_error(r, "Authorize key.", error_cleanup);
+
+            r = Esys_Create_Async(context->esys,
+                                  command->key_handle,
+                                  auth_session,
+                                  ESYS_TR_NONE, ESYS_TR_NONE,
+                                  &command->sym_sensitive,
+                                  &command->sym_template.public,
+                                  &command->sym_outsideInfo,
+                                  &command->sym_creationPCR);
+
+            goto_if_error(r, "Create_Async", error_cleanup);
+            fallthrough;
+
+        statecase(context->state, DATA_ENCRYPT_WAIT_FOR_SEAL);
+            r = Esys_Create_Finish(context->esys,
+                                   &command->outPrivate,
+                                   &command->outPublic,
+                                   NULL, NULL, NULL);
+            return_try_again(r);
+            goto_if_error(r, "Create_Finish", error_cleanup);
+
+            command->enc_data.sym_public
+                = *command->outPublic;
+            command->enc_data.sym_private.size
+                = command->outPrivate->size;
+            command->enc_data.sym_private.buffer =
+                &command->outPrivate->buffer[0];
+
+            key_length = sensitiveData->size;
+            data = malloc(command->in_dataSize);
+            goto_if_null2(data, "Out of memory.", r, TSS2_FAPI_RC_MEMORY, error_cleanup);
+
+            memcpy(data, command->in_data,
+                   command->in_dataSize);
+            r = ifapi_crypto_aes_encrypt(
+                    &sensitiveData->buffer[0],
+                    key_length,
+                    &encData->sym_iv.buffer[0],
+                    data, command->in_dataSize);
+            goto_if_error(r, "AES encryption", error_cleanup);
+
+            encData->type = IFAPI_ASYM_BULK_ENCRYPTION;
+            encData->cipher.size =  command->in_dataSize;
+            encData->cipher.buffer = data;
+            context-> state = DATA_ENCRYPT_FLUSH_KEY;
+            return TSS2_FAPI_RC_TRY_AGAIN;
+
+        statecase(context->state, DATA_ENCRYPT_WAIT_FOR_RSA_ENCRYPTION);
+            r =  Esys_RSA_Encrypt_Finish(context->esys, &tpmCipherText);
+
+            return_try_again(r);
+
+            goto_if_error_reset_state(r, "RSA encryption.", error_cleanup);
+
+            encData->type = IFAPI_ASYM_ENCRYPTION;
+            encData->cipher.size = tpmCipherText->size;
+            encData->cipher.buffer = malloc(encData->cipher.size);
+            goto_if_null2(encData->cipher.buffer, "Out of memory", r, TSS2_FAPI_RC_MEMORY,
+                          error_cleanup);
+
+            memcpy(&encData->cipher.buffer[0], &tpmCipherText->buffer[0],
+                   encData->cipher.size);
+
+            r = ifapi_get_name(&context->loadKey.auth_object.misc.key.public.publicArea,
+                               &encData->key_name);
+            goto_if_error(r, "Compute key name.", error_cleanup);
+
+            context-> state = DATA_ENCRYPT_FLUSH_KEY;
+            return TSS2_FAPI_RC_TRY_AGAIN;
+
+        statecase(context->state, DATA_ENCRYPT_WAIT_FOR_SYM_ENCRYPTION);
+            r = ifapi_sym_encrypt_decrypt_finish(context, &cipher, &cipherSize,  TPM2_NO);
+
+            return_try_again(r);
+            goto_if_error_reset_state(r, "Symmetric encryption.", error_cleanup);
+            fallthrough;
+
+        statecase(context->state, DATA_ENCRYPT_FLUSH_KEY);
+
+            r = Esys_FlushContext_Async(context->esys,
+                                        command->key_handle);
+            goto_if_error(r, "Error: FlushContext", error_cleanup);
+            fallthrough;
+
+        statecase(context->state, DATA_ENCRYPT_WAIT_FOR_FLUSH);
+            r = Esys_FlushContext_Finish(context->esys);
+            return_try_again(r);
+
+            goto_if_error(r, "Error: FlushContext", error_cleanup);
+            command->key_handle = ESYS_TR_NONE;
+            fallthrough;
+
+        statecase(context->state, DATA_ENCRYPT_CLEAN)
+            r = ifapi_cleanup_session(context);
+            try_again_or_error_goto(r, "Cleanup", error_cleanup);
+
+            break;
+
+        statecasedefault(context->state);
+    }
+
+    r = ifapi_json_IFAPI_ENCRYPTED_DATA_serialize(
+            &command->enc_data, &jso);
+    goto_if_error(r, "Error serialize FAPI cipher", error_cleanup);
+
+    jso_string = json_object_to_json_string_ext(jso, JSON_C_TO_STRING_PRETTY);
+    goto_if_null2(jso_string, "Converting json to string", r, TSS2_FAPI_RC_MEMORY,
+                  error_cleanup);
+
+    strdup_check(*cipherText, jso_string, r, error_cleanup);
+    context->state = _FAPI_STATE_INIT;
+
+error_cleanup:
+    if (command->key_handle != ESYS_TR_NONE)
+        Esys_FlushContext(context->esys,  command->key_handle);
+    ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
+    ifapi_cleanup_ifapi_object(context->loadKey.key_object);
+    ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
+    ifapi_cleanup_ifapi_object(command->key_object);
+    ifapi_cleanup_policy_harness(&command->enc_data.sym_policy_harness);
+    json_object_put(jso);
+    SAFE_FREE(command->keyPath);
+    SAFE_FREE(command->in_data);
+    SAFE_FREE(command->policyPath);
+    SAFE_FREE(command->out_data);
+    SAFE_FREE(command->outPrivate);
+    SAFE_FREE(command->outPublic);
+    SAFE_FREE(encData->cipher.buffer);
+    ifapi_session_clean(context);
+    LOG_TRACE("finsihed");
+    return r;
+}
diff --git a/src/tss2-fapi/api/Fapi_ExportKey.c b/src/tss2-fapi/api/Fapi_ExportKey.c
new file mode 100644
index 0000000..ab7ee18
--- /dev/null
+++ b/src/tss2-fapi/api/Fapi_ExportKey.c
@@ -0,0 +1,405 @@
+/* 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 <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#include "tss2_fapi.h"
+#include "fapi_int.h"
+#include "fapi_util.h"
+#include "tss2_esys.h"
+#include "fapi_crypto.h"
+#include "fapi_policy.h"
+#include "ifapi_json_serialize.h"
+#include "ifapi_json_deserialize.h"
+#include "tpm_json_deserialize.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+/** One-Call function for Fapi_ExportKey
+ *
+ * Given a key it will (if the key is a storage key) duplicate the key and
+ * package up the duplicated key and all keys below it into a file ready to move to
+ * a new TPM.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] pathOfKeyToDuplicate The path to the root of the subtree to
+ *             export.
+ * @param [in] pathToPublicKeyOfNewParent The path to the public key of the new
+ *             parent. May be NULL
+ * @param [out] exportedData The exported subtree
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context, pathOfKeyToDuplicate
+ *         or exportedData is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_KEY_NOT_FOUND: if pathOfKeyToDuplicate or
+ *         pathToPublicKeyOfNewParent does not map to a . FAPI object.
+ * @retval TSS2_FAPI_RC_BAD_KEY: if the key at pathToPublicKeyOfNewParent is not
+ *         suitable for the requeste operation.
+ * @retval TSS2_FAPI_RC_KEY_NOT_DUPLICABLE: if the key is not a duplicable key.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_ExportKey(
+    FAPI_CONTEXT *context,
+    char   const *pathOfKeyToDuplicate,
+    char   const *pathToPublicKeyOfNewParent,
+    char        **exportedData)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r, r2;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(pathOfKeyToDuplicate);
+    check_not_null(exportedData);
+
+    /* Check whether TCTI and ESYS are initialized */
+    return_if_null(context->esys, "Command can't be executed in none TPM mode.",
+                   TSS2_FAPI_RC_NO_TPM);
+
+    /* If the async state automata of FAPI shall be tested, then we must not set
+       the timeouts of ESYS to blocking mode.
+       During testing, the mssim tcti will ensure multiple re-invocations.
+       Usually however the synchronous invocations of FAPI shall instruct ESYS
+       to block until a result is available. */
+#ifndef TEST_FAPI_ASYNC
+    r = Esys_SetTimeout(context->esys, TSS2_TCTI_TIMEOUT_BLOCK);
+    return_if_error_reset_state(r, "Set Timeout to blocking");
+#endif /* TEST_FAPI_ASYNC */
+
+    r = Fapi_ExportKey_Async(context, pathOfKeyToDuplicate,
+                             pathToPublicKeyOfNewParent);
+    return_if_error_reset_state(r, "ExportKey");
+
+    do {
+        /* We wait for file I/O to be ready if the FAPI state automata
+           are in a file I/O state. */
+        r = ifapi_io_poll(&context->io);
+        return_if_error(r, "Something went wrong with IO polling");
+
+        /* Repeatedly call the finish function, until FAPI has transitioned
+           through all execution stages / states of this invocation. */
+        r = Fapi_ExportKey_Finish(context, exportedData);
+    } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
+
+    /* Reset the ESYS timeout to non-blocking, immediate response. */
+    r2 = Esys_SetTimeout(context->esys, 0);
+    return_if_error(r2, "Set Timeout to non-blocking");
+
+    return_if_error_reset_state(r, "ExportKey");
+
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous function for Fapi_ExportKey
+ *
+ * Given a key it will (if the key is a storage key) duplicate the key and
+ * package up the duplicated key and all keys below it into a file ready to move to
+ * a new TPM.
+ *
+ * Call Fapi_ExportKey_Finish to finish the execution of this command.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] pathOfKeyToDuplicate The path to the root of the subtree to
+ *             export.
+ * @param [in] pathToPublicKeyOfNewParent The path to the public key of the new
+ *             parent
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or pathOfKeyToDuplicate
+ *         is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_KEY_NOT_FOUND: if pathOfKeyToDuplicate or
+ *         pathToPublicKeyOfNewParent does not map to a . FAPI object.
+ * @retval TSS2_FAPI_RC_BAD_KEY: if the key at pathToPublicKeyOfNewParent is not
+ *         suitable for the requeste operation.
+ * @retval TSS2_FAPI_RC_KEY_NOT_DUPLICABLE: if the key is not a duplicable key.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_ExportKey_Async(
+    FAPI_CONTEXT *context,
+    char   const *pathOfKeyToDuplicate,
+    char   const *pathToPublicKeyOfNewParent)
+{
+    LOG_TRACE("called for context:%p", context);
+    LOG_TRACE("pathOfKeyToDuplicate: %s", pathOfKeyToDuplicate);
+    LOG_TRACE("pathToPublicKeyOfNewParent: %s", pathToPublicKeyOfNewParent);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(pathOfKeyToDuplicate);
+
+    /* Helpful alias pointers */
+    IFAPI_ExportKey * command = &context->cmd.ExportKey;
+
+    r = ifapi_session_init(context);
+    return_if_error(r, "Initialize NV_CreateNv");
+
+    command->pathOfKeyToDuplicate = NULL;
+    command->pathToPublicKeyOfNewParent = NULL;
+
+    strdup_check(command->pathOfKeyToDuplicate, pathOfKeyToDuplicate,
+                 r, error_cleanup);
+    strdup_check(command->pathToPublicKeyOfNewParent,
+                 pathToPublicKeyOfNewParent, r, error_cleanup);
+
+    if (!pathToPublicKeyOfNewParent) {
+        /* Only public key of KeyToDuplocate will be exported */
+        r = ifapi_keystore_load_async(&context->keystore, &context->io,
+                                      pathOfKeyToDuplicate);
+        return_if_error2(r, "Could not open: %s", pathOfKeyToDuplicate);
+
+        context->state = EXPORT_KEY_READ_PUB_KEY;
+    } else {
+        /* The public key of the new parent is needed for duplication */
+        r = ifapi_keystore_load_async(&context->keystore, &context->io,
+                                      pathToPublicKeyOfNewParent);
+        return_if_error2(r, "Could not open: %s", pathToPublicKeyOfNewParent);
+
+        context->state = EXPORT_KEY_READ_PUB_KEY_PARENT;
+    }
+    LOG_TRACE("finsihed");
+    return r;
+
+ error_cleanup:
+    SAFE_FREE(command->pathOfKeyToDuplicate);
+    SAFE_FREE(command->pathToPublicKeyOfNewParent);
+    return r;
+}
+
+/** Asynchronous finish function for Fapi_ExportKey
+ *
+ * This function should be called after a previous Fapi_ExportKey_Async.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [out] exportedData The exported subtree
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or exportedData is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
+ *         complete. Call this function again later.
+ */
+TSS2_RC
+Fapi_ExportKey_Finish(
+    FAPI_CONTEXT *context,
+    char        **exportedData)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+    json_object *jsoOut = NULL;
+    int sizePem;
+    TPM2B_ENCRYPTED_SECRET *encryptedSeed = NULL;
+    TPM2B_PRIVATE *duplicate = NULL;
+    IFAPI_OBJECT commandObject = {0};
+    IFAPI_OBJECT parentKeyObject = {0};
+    ESYS_TR auth_session;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(exportedData);
+
+    /* Helpful alias pointers */
+    IFAPI_ExportKey * command = &context->cmd.ExportKey;
+    IFAPI_OBJECT *pubKey = &command->pub_key;
+    IFAPI_OBJECT *exportTree = &command->export_tree;
+    IFAPI_DUPLICATE * keyTree = &exportTree->misc.key_tree;
+    pubKey->misc.ext_pub_key.certificate = NULL;
+
+    switch (context->state) {
+        statecase(context->state, EXPORT_KEY_READ_PUB_KEY);
+            r = ifapi_keystore_load_finish(&context->keystore, &context->io,
+                                           &commandObject);
+            return_try_again(r);
+            return_if_error_reset_state(r, "read_finish failed");
+
+            if (commandObject.objectType != IFAPI_KEY_OBJ) {
+                /* No key object was loaded */
+                ifapi_cleanup_ifapi_object(&commandObject);
+                goto_error(r, TSS2_FAPI_RC_BAD_PATH, "%s is not a key object.",
+                           cleanup, command->pathOfKeyToDuplicate);
+            }
+
+            pubKey->objectType = IFAPI_EXT_PUB_KEY_OBJ;
+            pubKey->misc.ext_pub_key.public = commandObject.misc.key.public;
+
+            r = ifapi_pub_pem_key_from_tpm(&pubKey->misc.ext_pub_key.public,
+                                           &pubKey->misc.ext_pub_key.pem_ext_public,
+                                           &sizePem);
+            goto_if_error(r, "Convert public TPM key to pem.", cleanup);
+
+            r = ifapi_json_IFAPI_OBJECT_serialize(pubKey, &jsoOut);
+            goto_if_error(r, "Error serialize FAPI KEY object", cleanup);
+
+            *exportedData = strdup(json_object_to_json_string_ext(jsoOut,
+                                                                  JSON_C_TO_STRING_PRETTY));
+            goto_if_null2(*exportedData, "Converting json to string", r,
+                          TSS2_FAPI_RC_MEMORY, cleanup);
+
+            break;
+
+        statecase(context->state, EXPORT_KEY_READ_PUB_KEY_PARENT);
+            r = ifapi_keystore_load_finish(&context->keystore, &context->io,
+                    &parentKeyObject);
+            if (r != TSS2_RC_SUCCESS) {
+                ifapi_cleanup_ifapi_object(&parentKeyObject);
+            }
+            return_try_again(r);
+            return_if_error_reset_state(r, "read_finish failed");
+
+            if (parentKeyObject.objectType != IFAPI_EXT_PUB_KEY_OBJ) {
+                goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "No public key in %s",
+                           cleanup, command->pathToPublicKeyOfNewParent);
+            }
+            command->public_parent = parentKeyObject.misc.ext_pub_key.public;
+            ifapi_cleanup_ifapi_object(&parentKeyObject);
+            r = ifapi_get_sessions_async(context,
+                                         IFAPI_SESSION_GENEK | IFAPI_SESSION1,
+                                         TPMA_SESSION_DECRYPT, 0);
+            goto_if_error_reset_state(r, "Create sessions", cleanup);
+
+            context->state = EXPORT_KEY_WAIT_FOR_KEY;
+            fallthrough;
+
+        statecase(context->state, EXPORT_KEY_WAIT_FOR_KEY);
+            r = ifapi_load_key(context, command->pathOfKeyToDuplicate,
+                               &command->key_object);
+            return_try_again(r);
+            goto_if_error(r, "Fapi load key.", cleanup);
+
+            context->duplicate_key = command->key_object;
+            r = Esys_LoadExternal_Async(context->esys,
+                                        ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
+                                        NULL,   &command->public_parent,
+                                        TPM2_RH_OWNER);
+            goto_if_error(r, "LoadExternal_Async", cleanup);
+
+            context->state = EXPORT_KEY_WAIT_FOR_EXT_KEY;
+            fallthrough;
+
+        statecase(context->state, EXPORT_KEY_WAIT_FOR_EXT_KEY);
+            r = Esys_LoadExternal_Finish(context->esys,
+                                         &command->handle_ext_key);
+            try_again_or_error_goto(r, "Load external key.", cleanup);
+
+            context->state = EXPORT_KEY_WAIT_FOR_AUTHORIZATON;
+            fallthrough;
+
+        statecase(context->state, EXPORT_KEY_WAIT_FOR_AUTHORIZATON);
+
+            r = ifapi_authorize_object(context, command->key_object, &auth_session);
+            return_try_again(r);
+            goto_if_error(r, "Authorize key.", cleanup);
+
+            TPM2B_DATA encryptionKey;
+            TPMT_SYM_DEF_OBJECT symmetric;
+
+            symmetric.algorithm = TPM2_ALG_NULL;
+            encryptionKey.size = 0;
+
+            r = Esys_Duplicate_Async(context->esys,
+                                     command->key_object->handle,
+                                     command->handle_ext_key,
+                                     auth_session,
+                                     ESYS_TR_NONE, ESYS_TR_NONE,
+                                     &encryptionKey, &symmetric);
+            goto_if_error(r, "Duplicate", cleanup);
+
+            context->state = EXPORT_KEY_WAIT_FOR_DUPLICATE;
+            fallthrough;
+
+        statecase(context->state,  EXPORT_KEY_WAIT_FOR_DUPLICATE);
+            exportTree->objectType = IFAPI_DUPLICATE_OBJ;
+            r = Esys_Duplicate_Finish(context->esys, NULL, &duplicate, &encryptedSeed);
+            try_again_or_error_goto(r, "Duplicate", cleanup);
+
+            keyTree->encrypted_seed = *encryptedSeed;
+            SAFE_FREE(encryptedSeed);
+            keyTree->duplicate = *duplicate;
+            SAFE_FREE(duplicate);
+            keyTree->public =
+                command->key_object->misc.key.public;
+            keyTree->public_parent = command->public_parent;
+            r = ifapi_get_json(context, exportTree, exportedData);
+            goto_if_error2(r, "get JSON for exported data.", cleanup);
+
+            context->state = EXPORT_KEY_WAIT_FOR_FLUSH1;
+            fallthrough;
+
+        statecase(context->state, EXPORT_KEY_WAIT_FOR_FLUSH1);
+            r = ifapi_flush_object(context, command->key_object->handle);
+            return_try_again(r);
+            goto_if_error(r, "Flush key", cleanup);
+
+            context->state = EXPORT_KEY_WAIT_FOR_FLUSH2;
+            fallthrough;
+
+        statecase(context->state, EXPORT_KEY_WAIT_FOR_FLUSH2);
+            r = ifapi_flush_object(context, command->handle_ext_key);
+            return_try_again(r);
+            goto_if_error(r, "Flush key", cleanup);
+            fallthrough;
+
+        statecase(context->state, EXPORT_KEY_CLEANUP)
+            r = ifapi_cleanup_session(context);
+            try_again_or_error_goto(r, "Cleanup", cleanup);
+
+            break;
+
+        statecasedefault(context->state);
+    }
+
+cleanup:
+    if (command->key_object) {
+        ifapi_cleanup_ifapi_object(command->key_object);
+    }
+    if (jsoOut != NULL) {
+        json_object_put(jsoOut);
+    }
+    context->duplicate_key = NULL;
+    context->state = _FAPI_STATE_INIT;
+    ifapi_cleanup_ifapi_object(&parentKeyObject);
+    ifapi_cleanup_ifapi_object(&commandObject);
+    ifapi_session_clean(context);
+    ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
+    ifapi_cleanup_ifapi_object(context->loadKey.key_object);
+    ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
+    SAFE_FREE(pubKey->misc.ext_pub_key.pem_ext_public);
+    SAFE_FREE(pubKey->misc.ext_pub_key.certificate);
+    SAFE_FREE(command->pathOfKeyToDuplicate);
+    SAFE_FREE(command->pathToPublicKeyOfNewParent);
+    LOG_TRACE("finsihed");
+    return r;
+}
diff --git a/src/tss2-fapi/api/Fapi_ExportPolicy.c b/src/tss2-fapi/api/Fapi_ExportPolicy.c
new file mode 100644
index 0000000..f5bc945
--- /dev/null
+++ b/src/tss2-fapi/api/Fapi_ExportPolicy.c
@@ -0,0 +1,258 @@
+/* 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 "tss2_fapi.h"
+#include "fapi_int.h"
+#include "fapi_util.h"
+#include "tss2_esys.h"
+#include "fapi_policy.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+/** One-Call function for Fapi_ExportPolicy
+ *
+ * Exports a policy to a JSON encoded byte buffer.
+ *
+ * @param [in,out] context The FAPI_CONTEXT
+ * @param [in] path The path to the policy that is to be exported
+ * @param [out] jsonPolicy The byte buffer the JSON-encoded policy is exported
+ *              to
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context, path or jsonPolicy is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_PATH: if path does not map to a FAPI policy.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_ExportPolicy(
+    FAPI_CONTEXT *context,
+    char   const *path,
+    char        **jsonPolicy)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r, r2;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(path);
+    check_not_null(jsonPolicy);
+
+    /* Check whether TCTI and ESYS are initialized */
+    return_if_null(context->esys, "Command can't be executed in none TPM mode.",
+                   TSS2_FAPI_RC_NO_TPM);
+
+    /* If the async state automata of FAPI shall be tested, then we must not set
+       the timeouts of ESYS to blocking mode.
+       During testing, the mssim tcti will ensure multiple re-invocations.
+       Usually however the synchronous invocations of FAPI shall instruct ESYS
+       to block until a result is available. */
+#ifndef TEST_FAPI_ASYNC
+    r = Esys_SetTimeout(context->esys, TSS2_TCTI_TIMEOUT_BLOCK);
+    return_if_error_reset_state(r, "Set Timeout to blocking");
+#endif /* TEST_FAPI_ASYNC */
+
+    r = Fapi_ExportPolicy_Async(context, path);
+    return_if_error_reset_state(r, "PolicyExport");
+
+    do {
+        /* We wait for file I/O to be ready if the FAPI state automata
+           are in a file I/O state. */
+        r = ifapi_io_poll(&context->io);
+        return_if_error(r, "Something went wrong with IO polling");
+
+        /* Repeatedly call the finish function, until FAPI has transitioned
+           through all execution stages / states of this invocation. */
+        r = Fapi_ExportPolicy_Finish(context, jsonPolicy);
+    } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
+
+    /* Reset the ESYS timeout to non-blocking, immediate response. */
+    r2 = Esys_SetTimeout(context->esys, 0);
+    return_if_error(r2, "Set Timeout to non-blocking");
+
+    return_if_error_reset_state(r, "PolicyExport");
+
+    return TSS2_RC_SUCCESS;
+
+}
+
+/** Asynchronous function for Fapi_ExportPolicy
+ *
+ * Exports a policy to a JSON encoded byte buffer.
+ *
+ * Call Fapi_ExportPolicy_Finish to finish the execution of this command.
+ *
+ * @param [in,out] context The FAPI_CONTEXT
+ * @param [in] path The path to the policy that is to be exported
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or path is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_PATH: if path does not map to a FAPI policy.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_ExportPolicy_Async(
+    FAPI_CONTEXT *context,
+    char   const *path)
+{
+    LOG_TRACE("called for context:%p", context);
+    LOG_TRACE("path: %s", path);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(path);
+
+    /* Helpful alias pointers */
+    IFAPI_ExportPolicy * command = &context->cmd.ExportPolicy;
+
+    r = ifapi_session_init(context);
+    return_if_error(r, "Initialize PolicyExport");
+
+    if (ifapi_path_type_p(path, IFAPI_POLICY_PATH)) {
+        context->state = POLICY_EXPORT_READ_POLICY;
+    } else {
+        context->state = POLICY_EXPORT_READ_OBJECT;
+    }
+    strdup_check(command->path, path, r ,error_cleanup);
+    memset(&command->object, 0, sizeof(IFAPI_OBJECT));
+
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+error_cleanup:
+    SAFE_FREE(command->path);
+    return r;
+}
+
+/** Asynchronous finish function for Fapi_ExportPolicy
+ *
+ * This function should be called after a previous Fapi_ExportPolicy_Async.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [out] jsonPolicy The byte buffer the JSON-encoded policy is exported
+ *              to
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or jsonPolicy is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
+ *         complete. Call this function again later.
+ */
+TSS2_RC
+Fapi_ExportPolicy_Finish(
+    FAPI_CONTEXT *context,
+    char        **jsonPolicy)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TPMS_POLICY_HARNESS harness = {0};
+    json_object *jso = NULL;
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(jsonPolicy);
+
+    /* Helpful alias pointers */
+    IFAPI_ExportPolicy * command = &context->cmd.ExportPolicy;
+
+    switch (context->state) {
+        statecase(context->state, POLICY_EXPORT_READ_POLICY);
+            r = ifapi_policy_store_load_async(&context->pstore, &context->io,
+                                              command->path);
+            goto_if_error2(r, "Can't open: %s", error_cleanup,
+                    command->path);
+            fallthrough;
+
+        statecase(context->state, POLICY_EXPORT_READ_POLICY_FINISH);
+            r = ifapi_policy_store_load_finish(&context->pstore, &context->io, &harness);
+            return_try_again(r);
+            return_if_error_reset_state(r, "read_finish failed");
+
+            r = ifapi_json_TPMS_POLICY_HARNESS_serialize(&harness, &jso);
+            goto_if_error(r, "Serialize policy", error_cleanup);
+
+            strdup_check(*jsonPolicy,
+                    json_object_to_json_string_ext(jso, JSON_C_TO_STRING_PRETTY),
+                    r, error_cleanup);
+
+            break;
+        statecase(context->state, POLICY_EXPORT_READ_OBJECT);
+            memset(&command->object, 0, sizeof(IFAPI_OBJECT));
+            r = ifapi_keystore_load_async(&context->keystore, &context->io,
+                                          command->path);
+            return_if_error2(r, "Could not open: %s", command->path);
+            fallthrough;
+
+        statecase(context->state, POLICY_EXPORT_READ_OBJECT_FINISH);
+            r = ifapi_keystore_load_finish(&context->keystore, &context->io,
+                                           &command->object);
+            return_try_again(r);
+            return_if_error_reset_state(r, "read_finish failed");
+
+            goto_if_null2(command->object.policy_harness,
+                          "Object has no policy",
+                          r, TSS2_FAPI_RC_BAD_PATH, error_cleanup);
+
+            r = ifapi_json_TPMS_POLICY_HARNESS_serialize(context->
+                cmd.ExportPolicy.object.policy_harness, &jso);
+            goto_if_error(r, "Serialize policy", error_cleanup);
+
+            strdup_check(*jsonPolicy,
+                    json_object_to_json_string_ext(jso, JSON_C_TO_STRING_PRETTY),
+                    r, error_cleanup);
+            break;
+
+        statecasedefault(context->state);
+    }
+    goto_if_null2(*jsonPolicy, "Out of memory.", r, TSS2_FAPI_RC_MEMORY, error_cleanup);
+
+    context->state = _FAPI_STATE_INIT;
+    if (jso)
+        json_object_put(jso);
+    ifapi_cleanup_ifapi_object(&command->object);
+    ifapi_cleanup_policy_harness(&harness);
+    ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
+    ifapi_cleanup_ifapi_object(context->loadKey.key_object);
+    ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
+    SAFE_FREE(command->path);
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+
+error_cleanup:
+    if (command->object.objectType)
+        ifapi_cleanup_ifapi_object(&command->object);
+    if (jso)
+        json_object_put(jso);
+    ifapi_cleanup_policy_harness(&harness);
+    ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
+    ifapi_cleanup_ifapi_object(context->loadKey.key_object);
+    ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
+    SAFE_FREE(command->path);
+    context->state = _FAPI_STATE_INIT;
+    return r;
+}
diff --git a/src/tss2-fapi/api/Fapi_Finalize.c b/src/tss2-fapi/api/Fapi_Finalize.c
new file mode 100644
index 0000000..e90aae8
--- /dev/null
+++ b/src/tss2-fapi/api/Fapi_Finalize.c
@@ -0,0 +1,85 @@
+/* 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
+
+#ifndef NO_DL
+#include <dlfcn.h>
+#endif /* NO_DL */
+#include <stdlib.h>
+
+#include<unistd.h>
+
+#include "tss2_fapi.h"
+#include "tss2_tctildr.h"
+#include "fapi_int.h"
+#include "fapi_util.h"
+#include "tss2_esys.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+/** One-Call function for Fapi_Finalize
+ *
+ * Fapi_Finalize() finalizes a context by closing IPC/RPC connections and freeing
+ * its consumed memory.
+ *
+ * @param [in] context The FAPI_CONTEXT
+ */
+void
+Fapi_Finalize(
+    FAPI_CONTEXT **context)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    if (!context || !*context) {
+        LOG_WARNING("Attempting to free NULL context");
+        return;
+    }
+
+    LOG_DEBUG("called: context: %p, *context: %p", context,
+              (context != NULL) ? *context : NULL);
+
+    ifapi_profiles_finalize(&(*context)->profiles);
+
+    TSS2_TCTI_CONTEXT *tcti = NULL;
+
+    if ((*context)->esys) {
+        Esys_GetTcti((*context)->esys, &tcti);
+        Esys_Finalize(&((*context)->esys));
+        if (tcti) {
+            LOG_TRACE("Finalizing TCTI");
+            Tss2_TctiLdr_Finalize(&tcti);
+        }
+    }
+
+    SAFE_FREE((*context)->pstore.policydir);
+    SAFE_FREE((*context)->keystore.systemdir);
+    SAFE_FREE((*context)->keystore.userdir);
+    SAFE_FREE((*context)->keystore.defaultprofile);
+
+    SAFE_FREE((*context)->cmd.Provision.root_crt);
+    SAFE_FREE((*context)->cmd.Provision.intermed_crt);
+    SAFE_FREE((*context)->cmd.Provision.pem_cert);
+
+    SAFE_FREE((*context)->config.profile_dir);
+    SAFE_FREE((*context)->config.user_dir);
+    SAFE_FREE((*context)->config.keystore_dir);
+    SAFE_FREE((*context)->config.profile_name);
+    SAFE_FREE((*context)->config.tcti);
+    SAFE_FREE((*context)->config.log_dir);
+    ifapi_profiles_finalize(&(*context)->profiles);
+
+    SAFE_FREE((*context)->eventlog.log_dir);
+
+    ifapi_free_objects(*context);
+    free(*context);
+    *context = NULL;
+
+    LOG_DEBUG("finished");
+}
diff --git a/src/tss2-fapi/api/Fapi_Free.c b/src/tss2-fapi/api/Fapi_Free.c
new file mode 100644
index 0000000..37ce751
--- /dev/null
+++ b/src/tss2-fapi/api/Fapi_Free.c
@@ -0,0 +1,27 @@
+/* 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 <stdlib.h>
+
+/*
+ * Fapi_Free is a helper function that is a wrapper around free().
+ * This allows programs that are built using a different version
+ * of the C runtime to free memory that has been allocated by the
+ * esys library on Windows.
+ *
+ * @param [in] ptr A pointer to the object that is to be freed.
+ */
+void
+Fapi_Free(void *ptr)
+{
+    if (ptr != NULL) {
+        free(ptr);
+    }
+}
diff --git a/src/tss2-fapi/api/Fapi_GetAppData.c b/src/tss2-fapi/api/Fapi_GetAppData.c
new file mode 100644
index 0000000..dbaac27
--- /dev/null
+++ b/src/tss2-fapi/api/Fapi_GetAppData.c
@@ -0,0 +1,224 @@
+/* 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 <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#include "tss2_fapi.h"
+#include "fapi_int.h"
+#include "fapi_util.h"
+#include "tss2_esys.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+/** One-Call function for Fapi_GetAppData
+ *
+ * Every object has a description field that can be retrieved in order to obtain
+ * additional information in its “path” entry.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] path The path to the object for which the appData is returned
+ * @param [out] appData A copy of the appData. May be NULL (callee-allocated)
+ * @param [out] appDataSize The size of the returned AppData. May be NULL
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or path is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_PATH: if path does not map to a FAPI entity.
+ * @retval TSS2_FAPI_RC_STORAGE_ERROR: if the updated data cannot be loaded.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_GetAppData(
+    FAPI_CONTEXT *context,
+    char   const *path,
+    uint8_t    **appData,
+    size_t      *appDataSize)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r, r2;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(path);
+
+    /* Check whether TCTI and ESYS are initialized */
+    return_if_null(context->esys, "Command can't be executed in none TPM mode.",
+                   TSS2_FAPI_RC_NO_TPM);
+
+    /* If the async state automata of FAPI shall be tested, then we must not set
+       the timeouts of ESYS to blocking mode.
+       During testing, the mssim tcti will ensure multiple re-invocations.
+       Usually however the synchronous invocations of FAPI shall instruct ESYS
+       to block until a result is available. */
+#ifndef TEST_FAPI_ASYNC
+    r = Esys_SetTimeout(context->esys, TSS2_TCTI_TIMEOUT_BLOCK);
+    return_if_error_reset_state(r, "Set Timeout to blocking");
+#endif /* TEST_FAPI_ASYNC */
+
+    r = Fapi_GetAppData_Async(context, path);
+    return_if_error_reset_state(r, "Path_SetDescription");
+
+    do {
+        /* We wait for file I/O to be ready if the FAPI state automata
+           are in a file I/O state. */
+        r = ifapi_io_poll(&context->io);
+        return_if_error(r, "Something went wrong with IO polling");
+
+        /* Repeatedly call the finish function, until FAPI has transitioned
+           through all execution stages / states of this invocation. */
+        r = Fapi_GetAppData_Finish(context, appData, appDataSize);
+    } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
+
+    /* Reset the ESYS timeout to non-blocking, immediate response. */
+    r2 = Esys_SetTimeout(context->esys, 0);
+    return_if_error(r2, "Set Timeout to non-blocking");
+
+    return_if_error_reset_state(r, "Path_SetDescription");
+
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous function for Fapi_GetAppData
+ *
+ * Every object has a description field that can be retrieved in order to obtain
+ * additional information in its “path” entry.
+ *
+ * Call Fapi_GetAppData_Finish to finish the execution of this command.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] path The path to the object for which the appData is returned
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or path is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_PATH: if path does not map to a FAPI entity.
+ * @retval TSS2_FAPI_RC_STORAGE_ERROR: if the updated data cannot be loaded.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_GetAppData_Async(
+    FAPI_CONTEXT *context,
+    char   const *path)
+{
+    LOG_TRACE("called for context:%p", context);
+    LOG_TRACE("path: %s", path);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(path);
+
+    r = ifapi_session_init(context);
+    return_if_error(r, "Initialize GetAppData");
+
+    r = ifapi_keystore_load_async(&context->keystore, &context->io, path);
+    return_if_error2(r, "Could not open: %s", path);
+
+    context->state =  PATH_GET_DESCRIPTION_READ;
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous finish function for Fapi_GetAppData
+ *
+ * This function should be called after a previous Fapi_GetAppData_Async.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [out] appData A copy of the appData. May be Null (callee-allocated)
+ * @param [out] appDataSize The size of the returned AppData. May be NULL
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
+ *         complete. Call this function again later.
+ */
+TSS2_RC
+Fapi_GetAppData_Finish(
+    FAPI_CONTEXT *context,
+    uint8_t     **appData,
+    size_t       *appDataSize)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+    IFAPI_OBJECT object;
+    UINT8_ARY *objAppData;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+
+    switch (context->state) {
+        statecase(context->state, PATH_GET_DESCRIPTION_READ);
+            r = ifapi_keystore_load_finish(&context->keystore, &context->io, &object);
+            return_try_again(r);
+            return_if_error_reset_state(r, "read_finish failed");
+
+            switch (object.objectType) {
+                case IFAPI_KEY_OBJ:
+                    objAppData = &object.misc.key.appData;
+                    break;
+                case IFAPI_NV_OBJ:
+                    objAppData = &object.misc.nv.appData;
+                    break;
+                default:
+                    goto_error(r, TSS2_FAPI_RC_BAD_PATH, "Object has no app data.", cleanup);
+            }
+
+            if (appData) {
+                if (objAppData->size) {
+                    *appData = malloc(objAppData->size);
+                    goto_if_null2(*appData, "Out of memory.", r, TSS2_FAPI_RC_MEMORY,
+                                  cleanup);
+                    memcpy(*appData, &objAppData->buffer[0],
+                           objAppData->size);
+                } else {
+                    *appData = NULL;
+                }
+            }
+            if (appDataSize)
+                *appDataSize = objAppData->size;
+
+            context->state = _FAPI_STATE_INIT;
+            r = TSS2_RC_SUCCESS;
+            break;
+
+        statecasedefault(context->state);
+    }
+
+cleanup:
+    ifapi_cleanup_ifapi_object(&object);
+    ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
+    ifapi_cleanup_ifapi_object(context->loadKey.key_object);
+    ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
+    LOG_TRACE("finsihed");
+    return r;
+}
diff --git a/src/tss2-fapi/api/Fapi_GetCertificate.c b/src/tss2-fapi/api/Fapi_GetCertificate.c
new file mode 100644
index 0000000..0db21ab
--- /dev/null
+++ b/src/tss2-fapi/api/Fapi_GetCertificate.c
@@ -0,0 +1,209 @@
+/* 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 <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+
+#include "tss2_fapi.h"
+#include "fapi_int.h"
+#include "fapi_util.h"
+#include "tss2_esys.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+#include "fapi_crypto.h"
+
+/** One-Call function for Fapi_GetCertificate
+ *
+ * Gets an x.509 certificate for the key at a given path.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] path The path to the key whose certificate is created
+ * @param [out] x509certData The PEM-encoded certificate
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context, path or x509CertData is
+ *         NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_PATH_NOT_FOUND: if path does not map to a FAPI entity.
+ * @retval TSS2_FAPI_RC_BAD_KEY: if the key is unsuitable for the requested
+ *         operation.
+ * @retval TSS2_FAPI_RC_NO_CERTIFICATE: if there is not a x.509 cert associated
+ *         with the path of the key.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_GetCertificate(
+    FAPI_CONTEXT *context,
+    char const   *path,
+    char        **x509certData)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(path);
+    check_not_null(x509certData);
+
+    r = Fapi_GetCertificate_Async(context, path);
+    return_if_error_reset_state(r, "Key_GetCertificate");
+
+    do {
+        /* We wait for file I/O to be ready if the FAPI state automata
+           are in a file I/O state. */
+        r = ifapi_io_poll(&context->io);
+        return_if_error(r, "Something went wrong with IO polling");
+
+        /* Repeatedly call the finish function, until FAPI has transitioned
+           through all execution stages / states of this invocation. */
+        r = Fapi_GetCertificate_Finish(context, x509certData);
+    } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
+
+    return_if_error_reset_state(r, "Key_GetCertificate");
+
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous function for Fapi_GetCertificate
+ *
+ * Gets an x.509 certificate for the key at a given path.
+ *
+ * Call Fapi_GetCertificate_Finish to finish the execution of this command.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] path The path to the key whose certificate is created
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or path is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_PATH_NOT_FOUND: if path does not map to a FAPI entity.
+ * @retval TSS2_FAPI_RC_BAD_KEY: if the key is unsuitable for the requested
+ *         operation.
+ * @retval TSS2_FAPI_RC_NO_CERTIFICATE: if there is not a x.509 cert associated
+ *         with the path of the key.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_GetCertificate_Async(
+    FAPI_CONTEXT   *context,
+    char    const  *path)
+
+{
+    LOG_TRACE("called for context:%p", context);
+    LOG_TRACE("path: %s", path);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(path);
+
+    /* Helpful alias pointers */
+    IFAPI_Key_SetCertificate * command = &context->cmd.Key_SetCertificate;
+
+    r = ifapi_non_tpm_mode_init(context);
+    return_if_error(r, "Initialize GetCertificate");
+
+    command->key_path = path;
+    r = ifapi_keystore_load_async(&context->keystore, &context->io, path);
+    return_if_error2(r, "Could not open: %s", path);
+
+    context->state =  KEY_GET_CERTIFICATE_READ;
+
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous finish function for Fapi_GetCertificate
+ *
+ * This function should be called after a previous Fapi_GetCertificate_Async.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [out] x509certData The PEM-encoded certificate
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or x509certData is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
+ *         complete. Call this function again later.
+ */
+TSS2_RC
+Fapi_GetCertificate_Finish(
+    FAPI_CONTEXT  *context,
+    char         **x509certData)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(x509certData);
+
+    /* Helpful alias pointers */
+    IFAPI_Key_SetCertificate * command = &context->cmd.Key_SetCertificate;
+    IFAPI_OBJECT *keyObject =  &command->key_object;
+
+    switch (context->state) {
+        statecase(context->state, KEY_GET_CERTIFICATE_READ)
+            r = ifapi_keystore_load_finish(&context->keystore, &context->io, keyObject);
+            return_try_again(r);
+            return_if_error_reset_state(r, "read_finish failed");
+
+            r = ifapi_initialize_object(context->esys, keyObject);
+            goto_if_error_reset_state(r, "Initialize NV object", error_cleanup);
+
+            if (keyObject->objectType == IFAPI_EXT_PUB_KEY_OBJ) {
+                strdup_check(*x509certData, keyObject->misc.ext_pub_key.certificate,
+                        r, error_cleanup);
+            }
+            else if (x509certData) {
+                strdup_check(*x509certData, keyObject->misc.key.certificate,
+                        r, error_cleanup);
+            }
+
+            context->state = _FAPI_STATE_INIT;
+            r = TSS2_RC_SUCCESS;
+            break;
+
+        statecasedefault(context->state);
+    }
+
+error_cleanup:
+    if (keyObject->objectType) {
+        ifapi_cleanup_ifapi_object(keyObject);
+    }
+    ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
+    ifapi_cleanup_ifapi_object(context->loadKey.key_object);
+    ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
+
+    LOG_TRACE("finsihed");
+    return r;
+}
diff --git a/src/tss2-fapi/api/Fapi_GetDescription.c b/src/tss2-fapi/api/Fapi_GetDescription.c
new file mode 100644
index 0000000..53c9461
--- /dev/null
+++ b/src/tss2-fapi/api/Fapi_GetDescription.c
@@ -0,0 +1,197 @@
+/* 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 <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#include "tss2_fapi.h"
+#include "fapi_int.h"
+#include "fapi_util.h"
+#include "tss2_esys.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+/** One-Call function for Fapi_GetDescription
+ *
+ * Returns the description of a previously stored object.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] path The path of the object for which the description is loaded
+ * @param [out] description The description of the object
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context, path or description is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_PATH: if path does not map to a FAPI entity.
+ * @retval TSS2_FAPI_RC_STORAGE_ERROR: if the updated data cannot be loaded.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_GetDescription(
+    FAPI_CONTEXT *context,
+    char   const *path,
+    char        **description)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r, r2;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(path);
+    check_not_null(description);
+
+    /* Check whether TCTI and ESYS are initialized */
+    return_if_null(context->esys, "Command can't be executed in none TPM mode.",
+                   TSS2_FAPI_RC_NO_TPM);
+
+    /* If the async state automata of FAPI shall be tested, then we must not set
+       the timeouts of ESYS to blocking mode.
+       During testing, the mssim tcti will ensure multiple re-invocations.
+       Usually however the synchronous invocations of FAPI shall instruct ESYS
+       to block until a result is available. */
+#ifndef TEST_FAPI_ASYNC
+    r = Esys_SetTimeout(context->esys, TSS2_TCTI_TIMEOUT_BLOCK);
+    return_if_error_reset_state(r, "Set Timeout to blocking");
+#endif /* TEST_FAPI_ASYNC */
+
+    r = Fapi_GetDescription_Async(context, path);
+    return_if_error_reset_state(r, "Path_SetDescription");
+
+    do {
+        /* We wait for file I/O to be ready if the FAPI state automata
+           are in a file I/O state. */
+        r = ifapi_io_poll(&context->io);
+        return_if_error(r, "Something went wrong with IO polling");
+
+        /* Repeatedly call the finish function, until FAPI has transitioned
+           through all execution stages / states of this invocation. */
+        r = Fapi_GetDescription_Finish(context, description);
+    } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
+
+    /* Reset the ESYS timeout to non-blocking, immediate response. */
+    r2 = Esys_SetTimeout(context->esys, 0);
+    return_if_error(r2, "Set Timeout to non-blocking");
+
+    return_if_error_reset_state(r, "Path_SetDescription");
+
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous function for Fapi_GetDescription
+ *
+ * Returns the description of a previously stored object.
+ *
+ * Call Fapi_GetDescription_Finish to finish the execution of this command.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] path The path of the object for which the description is loaded
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or path is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_PATH: if path does not map to a FAPI entity.
+ * @retval TSS2_FAPI_RC_STORAGE_ERROR: if the updated data cannot be loaded.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_GetDescription_Async(
+    FAPI_CONTEXT *context,
+    char   const *path)
+{
+    LOG_TRACE("called for context:%p", context);
+    LOG_TRACE("path: %s", path);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(path);
+
+    r = ifapi_session_init(context);
+    return_if_error(r, "Initialize GetDescription");
+
+    r = ifapi_keystore_load_async(&context->keystore, &context->io, path);
+    return_if_error2(r, "Could not open: %s", path);
+
+    context->state =  PATH_GET_DESCRIPTION_READ;
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous finish function for Fapi_GetDescription
+ *
+ * This function should be called after a previous Fapi_GetDescription_Async.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [out] description The description of the object
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or description is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
+ *         complete. Call this function again later.
+ */
+TSS2_RC
+Fapi_GetDescription_Finish(
+    FAPI_CONTEXT *context,
+    char        **description)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+    IFAPI_OBJECT object;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(description);
+
+    switch (context->state) {
+        statecase(context->state, PATH_GET_DESCRIPTION_READ);
+            r = ifapi_keystore_load_finish(&context->keystore, &context->io, &object);
+            return_try_again(r);
+            return_if_error_reset_state(r, "read_finish failed");
+
+            r = ifapi_get_description(&object, description);
+            ifapi_cleanup_ifapi_object(&object);
+
+            return_if_error_reset_state(r, "Get description");
+
+            context->state = _FAPI_STATE_INIT;
+            r = TSS2_RC_SUCCESS;
+            break;
+
+        statecasedefault(context->state);
+    }
+    LOG_TRACE("finsihed");
+    ifapi_cleanup_ifapi_object(&object);
+    ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
+    ifapi_cleanup_ifapi_object(context->loadKey.key_object);
+    ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
+    return r;
+}
diff --git a/src/tss2-fapi/api/Fapi_GetInfo.c b/src/tss2-fapi/api/Fapi_GetInfo.c
new file mode 100644
index 0000000..7d2e202
--- /dev/null
+++ b/src/tss2-fapi/api/Fapi_GetInfo.c
@@ -0,0 +1,254 @@
+/* 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 <json-c/json_util.h>
+#include <json-c/json_tokener.h>
+#include <string.h>
+
+#include "ifapi_json_serialize.h"
+#include "tss2_fapi.h"
+#include "fapi_int.h"
+#include "fapi_util.h"
+#include "tss2_esys.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+typedef struct {
+    char *description;
+    TPMI_POLICYTYPE capability;
+    UINT32 property;
+    UINT32 max;
+} IFAPI_INFO_CAP;
+
+static IFAPI_INFO_CAP info_cap_tab[] = {
+    { "algorithms", TPM2_CAP_ALGS,  TPM2_ALG_FIRST, TPM2_MAX_CAP_ALGS},
+    { "handles-transient", TPM2_CAP_HANDLES, TPM2_TRANSIENT_FIRST, TPM2_MAX_CAP_HANDLES},
+    { "handles-persistent", TPM2_CAP_HANDLES, TPM2_PERSISTENT_FIRST, TPM2_MAX_CAP_HANDLES},
+    { "handles-permanent", TPM2_CAP_HANDLES, TPM2_PERMANENT_FIRST, TPM2_MAX_CAP_HANDLES},
+    { "handles-pcr", TPM2_CAP_HANDLES, TPM2_PCR_FIRST, TPM2_MAX_CAP_HANDLES},
+    { "handles-nv-index", TPM2_CAP_HANDLES, TPM2_NV_INDEX_FIRST, TPM2_MAX_CAP_HANDLES},
+    { "handles-loaded-session", TPM2_CAP_HANDLES, TPM2_LOADED_SESSION_FIRST, TPM2_MAX_CAP_HANDLES},
+    { "handles-action-session", TPM2_CAP_HANDLES, TPM2_ACTIVE_SESSION_FIRST, TPM2_MAX_CAP_HANDLES},
+    { "handles-saved-session", TPM2_CAP_HANDLES, TPM2_ACTIVE_SESSION_FIRST, TPM2_MAX_CAP_HANDLES},
+    { "properties-fixed", TPM2_CAP_TPM_PROPERTIES, TPM2_PT_FIXED, TPM2_MAX_TPM_PROPERTIES },
+    { "properties-variable", TPM2_CAP_TPM_PROPERTIES, TPM2_PT_VAR, TPM2_MAX_TPM_PROPERTIES },
+    { "commands", TPM2_CAP_COMMANDS, TPM2_CC_FIRST, TPM2_MAX_CAP_CC },
+    { "pp-commands", TPM2_CAP_PP_COMMANDS, TPM2_CC_FIRST, TPM2_MAX_CAP_CC },
+    { "audit-commands", TPM2_CAP_AUDIT_COMMANDS, TPM2_CC_FIRST, TPM2_MAX_CAP_CC },
+    { "pcrs", TPM2_CAP_PCRS, 0, TPM2_NUM_PCR_BANKS },
+    { "pcr-properties", TPM2_CAP_PCR_PROPERTIES, TPM2_PCR_FIRST, TPM2_MAX_PCR_PROPERTIES },
+    { "ecc-curves", TPM2_CAP_ECC_CURVES, 0, TPM2_MAX_ECC_CURVES },
+};
+
+/** One-Call function for Fapi_GetInfo
+ *
+ * Returns a UTF-8 encoded string that identifies the versions of FAPI, TPM,
+ * configurations and other relevant information.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [out] info The byte buffer for the information string
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or info is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_GetInfo(
+    FAPI_CONTEXT *context,
+    char        **info)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r, r2;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(info);
+
+    /* Check whether TCTI and ESYS are initialized */
+    return_if_null(context->esys, "Command can't be executed in none TPM mode.",
+                   TSS2_FAPI_RC_NO_TPM);
+
+    /* If the async state automata of FAPI shall be tested, then we must not set
+       the timeouts of ESYS to blocking mode.
+       During testing, the mssim tcti will ensure multiple re-invocations.
+       Usually however the synchronous invocations of FAPI shall instruct ESYS
+       to block until a result is available. */
+#ifndef TEST_FAPI_ASYNC
+    r = Esys_SetTimeout(context->esys, TSS2_TCTI_TIMEOUT_BLOCK);
+    return_if_error_reset_state(r, "Set Timeout to blocking");
+#endif /* TEST_FAPI_ASYNC */
+
+    r = Fapi_GetInfo_Async(context);
+    return_if_error_reset_state(r, "GetTPMInfo");
+
+    do {
+        /* We wait for file I/O to be ready if the FAPI state automata
+           are in a file I/O state. */
+        r = ifapi_io_poll(&context->io);
+        return_if_error(r, "Something went wrong with IO polling");
+
+        /* Repeatedly call the finish function, until FAPI has transitioned
+           through all execution stages / states of this invocation. */
+        r = Fapi_GetInfo_Finish(context, info);
+    } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
+
+    /* Reset the ESYS timeout to non-blocking, immediate response. */
+    r2 = Esys_SetTimeout(context->esys, 0);
+    return_if_error(r2, "Set Timeout to non-blocking");
+
+    return_if_error_reset_state(r, "GetTPMInfo");
+
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous function for Fapi_GetInfo
+ *
+ * Returns a UTF-8 encoded string that identifies the versions of FAPI, TPM,
+ * configurations and other relevant information.
+ *
+ * Call Fapi_GetInfo_Finish to finish the execution of this command.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_GetInfo_Async(
+    FAPI_CONTEXT *context)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+
+    /* Helpful alias pointers */
+    IFAPI_GetInfo * command = &context->cmd.GetInfo;
+
+    r = ifapi_session_init(context);
+    return_if_error(r, "Initialize GetInfo");
+    memset(command, 0, sizeof(IFAPI_INFO));
+    r = ifapi_capability_init(context);
+
+    return_if_error(r, "Capability init");
+    command->idx_info_cap = 0;
+    context->state = GET_INFO_GET_CAP;
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous finish function for Fapi_GetInfo
+ *
+ * This function should be called after a previous Fapi_GetInfo_Async.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [out] info The byte buffer for the information string
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or info is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
+ *         complete. Call this function again later.
+ */
+TSS2_RC
+Fapi_GetInfo_Finish(
+    FAPI_CONTEXT *context,
+    char        **info)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+    json_object *jso = NULL;
+    size_t capIdx;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(info);
+
+    /* Helpful alias pointers */
+    IFAPI_GetInfo * command = &context->cmd.GetInfo;
+    IFAPI_INFO *infoObj = &command->info_obj;
+    TPMS_CAPABILITY_DATA *capabilityData = NULL;
+
+    switch (context->state) {
+    case  GET_INFO_GET_CAP:
+        /* Initialize the propert for the first ESAPI call */
+        command->property
+            = info_cap_tab[command->idx_info_cap].property;
+        fallthrough;
+
+    case  GET_INFO_GET_CAP_MORE:
+        fallthrough;
+
+    case  GET_INFO_WAIT_FOR_CAP:
+        /* State will be set by sub routine */
+        capIdx = command->idx_info_cap;
+        r = ifapi_capability_get(context,
+                                 info_cap_tab[capIdx].capability,
+                                 info_cap_tab[capIdx].max,
+                                 &capabilityData);
+        return_try_again(r);
+        goto_if_error(r, "Get capability", cleanup);
+
+        infoObj->cap[capIdx].description =  info_cap_tab[capIdx].description;
+        infoObj->cap[capIdx].capability =  capabilityData;
+        command->property_count = 0;
+        command->idx_info_cap += 1;
+        if  (command->idx_info_cap <  sizeof(info_cap_tab)
+             / sizeof(info_cap_tab[0])) {
+            /* Not all capablities have been collected */
+            context->state = GET_INFO_GET_CAP;
+            return TSS2_FAPI_RC_TRY_AGAIN;
+        }
+
+        infoObj->fapi_version = "OSSTSS 2.2.x";
+        infoObj->fapi_config = "Properties of config have to specified by TCG";
+        r = ifapi_json_IFAPI_INFO_serialize(infoObj, &jso);
+        goto_if_error(r, "Error serialize info object", cleanup);
+
+        *info = strdup(json_object_to_json_string_ext(jso, JSON_C_TO_STRING_PRETTY));
+        goto_if_null2(*info, "Out of memory.", r, TSS2_FAPI_RC_MEMORY, cleanup);
+
+        context->state = _FAPI_STATE_INIT;
+        r = TSS2_RC_SUCCESS;
+        break;
+
+    statecasedefault(context->state);
+    }
+
+cleanup:
+    json_object_put(jso);
+    for (capIdx = 0; capIdx < IFAPI_MAX_CAP_INFO; capIdx++) {
+        SAFE_FREE(infoObj->cap[capIdx].capability);
+    }
+    LOG_TRACE("finsihed");
+    return r;
+}
diff --git a/src/tss2-fapi/api/Fapi_GetPlatformCertificates.c b/src/tss2-fapi/api/Fapi_GetPlatformCertificates.c
new file mode 100644
index 0000000..e9008e7
--- /dev/null
+++ b/src/tss2-fapi/api/Fapi_GetPlatformCertificates.c
@@ -0,0 +1,227 @@
+/* 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 <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#include "tss2_fapi.h"
+#include "fapi_int.h"
+#include "fapi_util.h"
+#include "tss2_esys.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+/** One-Call function for Fapi_GetPlatformCertificates
+ *
+ * Platform certificates for TPM 2.0 can consist not only of a single certificate
+ * but a series of so-called delta certificates.
+ * This function returns the set of Platform certificates concatenated in
+ * a continuous buffer.
+ *
+ * @param [in,out] context The FAPI_CONTEXT
+ * @param [out] certificates The platform certificates
+ * @param [out] certificatesSize The size of the buffer with the certificates.
+ *              May be NULL
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or certificates is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for internal
+ *         operations or return parameters.
+ */
+TSS2_RC
+Fapi_GetPlatformCertificates(
+    FAPI_CONTEXT *context,
+    uint8_t **certificates,
+    size_t *certificatesSize)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r, r2;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(certificates);
+
+    /* Check whether TCTI and ESYS are initialized */
+    return_if_null(context->esys, "Command can't be executed in none TPM mode.",
+                   TSS2_FAPI_RC_NO_TPM);
+
+    /* If the async state automata of FAPI shall be tested, then we must not set
+       the timeouts of ESYS to blocking mode.
+       During testing, the mssim tcti will ensure multiple re-invocations.
+       Usually however the synchronous invocations of FAPI shall instruct ESYS
+       to block until a result is available. */
+#ifndef TEST_FAPI_ASYNC
+    r = Esys_SetTimeout(context->esys, TSS2_TCTI_TIMEOUT_BLOCK);
+    return_if_error_reset_state(r, "Set Timeout to blocking");
+#endif /* TEST_FAPI_ASYNC */
+
+    r = Fapi_GetPlatformCertificates_Async(context);
+    return_if_error_reset_state(r, "Path_PlatformGetCertificate");
+
+    do {
+        /* We wait for file I/O to be ready if the FAPI state automata
+           are in a file I/O state. */
+        r = ifapi_io_poll(&context->io);
+        return_if_error(r, "Something went wrong with IO polling");
+
+        /* Repeatedly call the finish function, until FAPI has transitioned
+           through all execution stages / states of this invocation. */
+        r = Fapi_GetPlatformCertificates_Finish(context, certificates,
+                certificatesSize);
+    } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
+
+    /* Reset the ESYS timeout to non-blocking, immediate response. */
+    r2 = Esys_SetTimeout(context->esys, 0);
+    return_if_error(r2, "Set Timeout to non-blocking");
+
+    return_if_error_reset_state(r, "Path_PlatformGetCertificate");
+
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous function for Fapi_GetPlatformCertificates
+ *
+ * Platform certificates for TPM 2.0 can consist not only of a single certificate
+ * but a series of so-called delta certificates.
+ * This function returns the set of Platform certificates concatenated in
+ * a continuous buffer.
+ *
+ * Call Fapi_GetPlatformCertificates_Finish to finish the execution of this
+ * command.
+ *
+ * @param [in,out] context The FAPI_CONTEXT
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for internal
+ *         operations or return parameters.
+ */
+TSS2_RC
+Fapi_GetPlatformCertificates_Async(
+    FAPI_CONTEXT *context)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+
+    r = ifapi_session_init(context);
+    return_if_error(r, "Initialize Fapi_GetPlatformCertificates");
+
+    context->state = GET_PLATFORM_CERTIFICATE;
+
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous finish function for Fapi_GetPlatformCertificates
+ *
+ * This function should be called after a previous
+ * Fapi_GetPlatformCertificates_Async.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [out] certificates The platform certificates
+ * @param [out] certificatesSize The size of the buffer with the certificates.
+ *              May be NULL
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or certificates is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
+ *         complete. Call this function again later.
+ */
+TSS2_RC
+Fapi_GetPlatformCertificates_Finish(
+    FAPI_CONTEXT *context,
+    uint8_t **certificates,
+    size_t *certificatesSize)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    NODE_OBJECT_T *cert_list = NULL;
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(certificates);
+    *certificates = NULL;
+
+    switch (context->state) {
+        statecase(context->state, GET_PLATFORM_CERTIFICATE);
+            r = ifapi_get_certificates(context, MIN_PLATFORM_CERT_HANDLE,
+                                       MAX_PLATFORM_CERT_HANDLE,
+                                       &cert_list);
+            return_try_again(r);
+            goto_if_error(r, "Get certificates.", error);
+
+            if (cert_list) {
+                /* Concatenate the founc certificates */
+                size_t size;
+                NODE_OBJECT_T *cert = cert_list;
+                size = 0;
+                while (cert) {
+                    size += cert->size;
+                    cert = cert->next;
+                }
+                if (certificatesSize)
+                    *certificatesSize = size;
+                *certificates = malloc(size);
+                goto_if_null2(*certificates, "Out of memory.",
+                        r, TSS2_FAPI_RC_MEMORY, error);
+
+                size = 0;
+                while (cert) {
+                    memcpy(&cert[size], cert->object, cert->size);
+                    size +=  cert->size;
+                    cert = cert->next;
+                }
+            } else {
+                if (certificatesSize)
+                    *certificatesSize = 0;
+                goto_error(r, TSS2_FAPI_RC_NO_CERT,
+                        "No platform certificates available.", error);
+            }
+            break;
+        statecasedefault(context->state);
+    }
+    ifapi_free_object_list(cert_list);
+    SAFE_FREE(context->cmd.Provision.capabilityData);
+    context->state =  _FAPI_STATE_INIT;
+    LOG_TRACE("finished");
+    return TSS2_RC_SUCCESS;
+
+ error:
+    context->state =  _FAPI_STATE_INIT;
+    ifapi_free_object_list(cert_list);
+    SAFE_FREE(context->cmd.Provision.capabilityData);
+    SAFE_FREE(*certificates);
+    return r;
+}
diff --git a/src/tss2-fapi/api/Fapi_GetPollHandles.c b/src/tss2-fapi/api/Fapi_GetPollHandles.c
new file mode 100644
index 0000000..2fd87ae
--- /dev/null
+++ b/src/tss2-fapi/api/Fapi_GetPollHandles.c
@@ -0,0 +1,88 @@
+/* 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 <stdlib.h>
+#include <string.h>
+
+#include "tss2_fapi.h"
+#include "fapi_int.h"
+#include "fapi_util.h"
+#include "tss2_esys.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+/** Retrieve handles for polling
+ *
+ * Returns an array of handles that can be polled on to get notified when
+ * data from the TPM or from a disk operation is available.
+ *
+ * The corresponding code should look similar to follows:
+ * do { r = Fapi_GetPollHandles(fc, &ph, &nph);
+        if (r == TSS2_RC_SUCCESS) { poll(ph, nph, -1); Fapi_Free(ph); }
+ *      r = Fapi_*_Finish(fc, ...); } while (r == TSS2_FAPI_RC_TRY_AGAIN);
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [out] handles An array of poll handle entries
+ * @param [out] num_handles The size of the array in handles
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or data is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has no asynchronous
+ *         operation pending.
+ * @retval TSS2_FAPI_RC_NO_HANDLE: if there are no handles to poll on
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_GetPollHandles(
+    FAPI_CONTEXT *context,
+    FAPI_POLL_HANDLE **handles,
+    size_t            *num_handles)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(handles);
+    check_not_null(num_handles);
+
+    if (context->state == _FAPI_STATE_INIT) {
+        LOG_ERROR("PollHandles can only be returned while an operation is running");
+        return TSS2_FAPI_RC_BAD_SEQUENCE;
+    }
+
+    /* First we check for poll handles from IO operations. */
+    r = ifapi_io_poll_handles(&context->io, handles, num_handles);
+    if (r == TSS2_RC_SUCCESS) {
+        LOG_DEBUG("Returning %zi IO poll handles.", *num_handles);
+        return r;
+    }
+    if (r != TSS2_FAPI_RC_NO_HANDLE)
+        return_if_error(r, "Retrieving poll handles failed");
+
+    /* Then we check for poll handles from ESYS operations. */
+    /* If we are running in none-TPM mode then we are already done trying. */
+    return_if_null(context->esys, "No non-TPM based poll handles found.",
+                   TSS2_FAPI_RC_NO_HANDLE);
+
+    r = Esys_GetPollHandles(context->esys, handles, num_handles);
+    if (r) {
+        LOG_DEBUG("Returning TSS2_FAPI_RC_NO_HANDLE");
+        return TSS2_FAPI_RC_NO_HANDLE;
+    }
+
+    LOG_DEBUG("Returning %zi ESYS poll handles.", *num_handles);
+    LOG_TRACE("finished");
+    return r;
+}
diff --git a/src/tss2-fapi/api/Fapi_GetRandom.c b/src/tss2-fapi/api/Fapi_GetRandom.c
new file mode 100644
index 0000000..17ecd36
--- /dev/null
+++ b/src/tss2-fapi/api/Fapi_GetRandom.c
@@ -0,0 +1,215 @@
+/* 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 <stdlib.h>
+#include <string.h>
+
+#include "tss2_fapi.h"
+#include "fapi_int.h"
+#include "fapi_util.h"
+#include "tss2_esys.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+/** One-Call function for Fapi_GetRandom
+ *
+ * Creates an array with a specified number of bytes. May execute the underlying
+ * TPM command multiple times if the requested number of bytes is too big.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] numBytes The number of bytes requested from the TPM
+ * @param [out] data The array of random bytes returned from the TPM
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or data is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_VALUE: if numBytes is 0.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_GetRandom(
+    FAPI_CONTEXT *context,
+    size_t        numBytes,
+    uint8_t     **data)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r, r2;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(data);
+
+    /* Check whether TCTI and ESYS are initialized */
+    return_if_null(context->esys, "Command can't be executed in none TPM mode.",
+                   TSS2_FAPI_RC_NO_TPM);
+
+    /* If the async state automata of FAPI shall be tested, then we must not set
+       the timeouts of ESYS to blocking mode.
+       During testing, the mssim tcti will ensure multiple re-invocations.
+       Usually however the synchronous invocations of FAPI shall instruct ESYS
+       to block until a result is available. */
+#ifndef TEST_FAPI_ASYNC
+    r = Esys_SetTimeout(context->esys, TSS2_TCTI_TIMEOUT_BLOCK);
+    return_if_error_reset_state(r, "Set Timeout to blocking");
+#endif /* TEST_FAPI_ASYNC */
+
+    r = Fapi_GetRandom_Async(context, numBytes);
+    return_if_error_reset_state(r, "GetRandom");
+
+    do {
+        /* We wait for file I/O to be ready if the FAPI state automata
+           are in a file I/O state. */
+        r = ifapi_io_poll(&context->io);
+        return_if_error(r, "Something went wrong with IO polling");
+
+        /* Repeatedly call the finish function, until FAPI has transitioned
+           through all execution stages / states of this invocation. */
+        r = Fapi_GetRandom_Finish(context, data);
+    } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
+
+    /* Reset the ESYS timeout to non-blocking, immediate response. */
+    r2 = Esys_SetTimeout(context->esys, 0);
+    return_if_error(r2, "Set Timeout to non-blocking");
+
+    return_if_error_reset_state(r, "GetRandom");
+
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous function for Fapi_GetRandom
+ *
+ * Creates an array with a specified number of bytes. May execute the underlying
+ * TPM command multiple times if the requested number of bytes is too big.
+ *
+ * Call Fapi_GetRandom_Finish to finish the execution of this command.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] numBytes The number of bytes requested from the TPM
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_VALUE: if numBytes is 0.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_GetRandom_Async(
+    FAPI_CONTEXT *context,
+    size_t        numBytes)
+{
+    LOG_TRACE("called for context:%p", context);
+    LOG_TRACE("numBytes: %zu", numBytes);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+
+    /* Helpful alias pointers */
+    IFAPI_GetRandom * command = &context->get_random;
+
+    r = ifapi_session_init(context);
+    return_if_error(r, "Initialize GetRandom");
+
+    command->numBytes = numBytes;
+    command->data = NULL;
+
+    r = ifapi_get_sessions_async(context,
+                                 IFAPI_SESSION_GENEK | IFAPI_SESSION1,
+                                 TPMA_SESSION_ENCRYPT | TPMA_SESSION_DECRYPT, 0);
+    return_if_error_reset_state(r, "Create FAPI session");
+    context->state = GET_RANDOM_WAIT_FOR_SESSION;
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous finish function for Fapi_GetRandom
+ *
+ * This function should be called after a previous Fapi_GetRandom_Async.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [out] data The array of random bytes returned from the TPM
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or data is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
+ *         complete. Call this function again later.
+ */
+TSS2_RC
+Fapi_GetRandom_Finish(
+    FAPI_CONTEXT *context,
+    uint8_t     **data)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(data);
+
+    /* Helpful alias pointers */
+    IFAPI_GetRandom * command = &context->get_random;
+
+    switch (context->state) {
+        statecase(context->state, GET_RANDOM_WAIT_FOR_SESSION);
+            r = ifapi_get_sessions_finish(context, &context->profiles.default_profile);
+            return_try_again(r);
+            goto_if_error_reset_state(r, " FAPI create session", error_cleanup);
+
+            context->get_random_state = GET_RANDOM_INIT;
+            context->state = GET_RANDOM_WAIT_FOR_RANDOM;
+            fallthrough;
+
+        statecase(context->state, GET_RANDOM_WAIT_FOR_RANDOM);
+            r = ifapi_get_random(context, command->numBytes, data);
+            return_try_again(r);
+            goto_if_error_reset_state(r, " FAPI GetRandom", error_cleanup);
+            fallthrough;
+
+            statecase(context->state, GET_RANDOM_CLEANUP)
+            r = ifapi_cleanup_session(context);
+            try_again_or_error_goto(r, "Cleanup", error_cleanup);
+
+            break;
+
+        statecasedefault(context->state);
+    }
+
+    context->state = _FAPI_STATE_INIT;
+    ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
+    ifapi_session_clean(context);
+    LOG_TRACE("finished");
+    return TSS2_RC_SUCCESS;
+
+error_cleanup:
+    ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
+    ifapi_session_clean(context);
+    SAFE_FREE(context->get_random.data);
+    LOG_TRACE("finsihed");
+    return r;
+}
diff --git a/src/tss2-fapi/api/Fapi_GetTcti.c b/src/tss2-fapi/api/Fapi_GetTcti.c
new file mode 100644
index 0000000..1081dc5
--- /dev/null
+++ b/src/tss2-fapi/api/Fapi_GetTcti.c
@@ -0,0 +1,57 @@
+/* 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 "tss2_fapi.h"
+#include "tss2_esys.h"
+#include "tss2_tcti.h"
+
+#include "fapi_int.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+/** One-Call function for Fapi_GetTcti
+ *
+ * Fapi_GetTcti returns the TSS2_TCTI_CONTEXT currently used by the provided FAPI_CONTEXT.
+ * The purpose is to enable advanced access to the TPM that is currently being talked to.
+ * It is especially useful in combination with Fapi_GetTpmBlobs().
+ *
+ * Note: The application must ensure that this TSS2_TCTI_CONTEXT is not being used in parallel to
+ *       the processing of a FAPI command.
+ *
+ * @param [in,out] context The FAPI_CONTEXT
+ * @param [out] tcti The TSS2_TCTI_CONTEXT used to talk to the current TPM.
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context, tcti is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ */
+TSS2_RC
+Fapi_GetTcti(
+    FAPI_CONTEXT       *context,
+    TSS2_TCTI_CONTEXT **tcti)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(tcti);
+
+    if (!context->esys)
+        return_error(TSS2_FAPI_RC_NO_TPM, "Fapi is running in non-TPM mode");
+
+    r = Esys_GetTcti(context->esys, tcti);
+    return_if_error(r, "Esys_GetTcti");
+
+    LOG_DEBUG("finished");
+    return r;
+}
diff --git a/src/tss2-fapi/api/Fapi_GetTpmBlobs.c b/src/tss2-fapi/api/Fapi_GetTpmBlobs.c
new file mode 100644
index 0000000..e20ea10
--- /dev/null
+++ b/src/tss2-fapi/api/Fapi_GetTpmBlobs.c
@@ -0,0 +1,263 @@
+/* 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 <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "tss2_mu.h"
+#include "tss2_fapi.h"
+#include "fapi_int.h"
+#include "fapi_util.h"
+#include "tss2_esys.h"
+#include "ifapi_policy_json_serialize.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+
+/** One-Call function for Fapi_GetTpmBlobs
+ *
+ * Get the public and private blobs of a TPM object. They can be loaded with a
+ * lower-level API such as the SAPI or the ESAPI.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] path The path to the key for which the blobs will be returned
+ * @param [out] tpm2bPublic The returned public area of the object. May be NULL
+ * @param [out] tpm2bPublicSize The size of tpm2bPublic in bytes. May be NULL
+ * @param [out] tpm2bPrivate The returned private area of the object. May be
+ *              NULL
+ * @param [out] tpm2bPrivateSize The size of tpm2bPrivate in bytes. May be NULL
+ * @param [out] policy The policy that is associated with the object encoded in
+ *              JSON. May be NULL
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or path is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_PATH: if path does not map to a FAPI entity.
+ * @retval TSS2_FAPI_RC_STORAGE_ERROR: If the updated data cannot be saved.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_GetTpmBlobs(
+    FAPI_CONTEXT   *context,
+    char     const *path,
+    uint8_t       **tpm2bPublic,
+    size_t         *tpm2bPublicSize,
+    uint8_t       **tpm2bPrivate,
+    size_t         *tpm2bPrivateSize,
+    char          **policy)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r, r2;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(path);
+
+    /* Check whether TCTI and ESYS are initialized */
+    return_if_null(context->esys, "Command can't be executed in none TPM mode.",
+                   TSS2_FAPI_RC_NO_TPM);
+
+    /* If the async state automata of FAPI shall be tested, then we must not set
+       the timeouts of ESYS to blocking mode.
+       During testing, the mssim tcti will ensure multiple re-invocations.
+       Usually however the synchronous invocations of FAPI shall instruct ESYS
+       to block until a result is available. */
+#ifndef TEST_FAPI_ASYNC
+    r = Esys_SetTimeout(context->esys, TSS2_TCTI_TIMEOUT_BLOCK);
+    return_if_error_reset_state(r, "Set Timeout to blocking");
+#endif /* TEST_FAPI_ASYNC */
+
+    r = Fapi_GetTpmBlobs_Async(context, path);
+    return_if_error_reset_state(r, "Entity_GetTPMBlobs");
+
+    do {
+        /* We wait for file I/O to be ready if the FAPI state automata
+           are in a file I/O state. */
+        r = ifapi_io_poll(&context->io);
+        return_if_error(r, "Something went wrong with IO polling");
+
+        /* Repeatedly call the finish function, until FAPI has transitioned
+           through all execution stages / states of this invocation. */
+        r = Fapi_GetTpmBlobs_Finish(context, tpm2bPublic, tpm2bPublicSize, tpm2bPrivate,
+                                    tpm2bPrivateSize, policy);
+    } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
+
+    /* Reset the ESYS timeout to non-blocking, immediate response. */
+    r2 = Esys_SetTimeout(context->esys, 0);
+    return_if_error(r2, "Set Timeout to non-blocking");
+
+    return_if_error_reset_state(r, "Entity_GetTPMBlobs");
+
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous function for Fapi_GetTpmBlobs
+ *
+ * Get the public and private blobs of a TPM object. They can be loaded with a
+ * lower-level API such as the SAPI or the ESAPI.
+ *
+ * Call Fapi_GetTpmBlobs_Finish to finish the execution of this command.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] path The path to the key for which the blobs will be returned
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or path is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_PATH: if path does not map to a FAPI entity.
+ * @retval TSS2_FAPI_RC_STORAGE_ERROR: If the updated data cannot be saved.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_GetTpmBlobs_Async(
+    FAPI_CONTEXT   *context,
+    char     const *path)
+{
+    LOG_TRACE("called for context:%p", context);
+    LOG_TRACE("path: %s", path);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(path);
+
+    r = ifapi_session_init(context);
+    return_if_error(r, "Initialize GetTPMBlobc");
+
+    r = ifapi_keystore_load_async(&context->keystore, &context->io, path);
+    return_if_error2(r, "Could not open: %s", path);
+
+    context->state = ENTITY_GET_TPM_BLOBS_READ;
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous finish function for Fapi_GetTpmBlobs
+ *
+ * This function should be called after a previous Fapi_GetTpmBlobs_Async.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [out] tpm2bPublic The returned public area of the object. May be NULL
+ * @param [out] tpm2bPublicSize The size of tpm2bPublic in bytes. May be NULL
+ * @param [out] tpm2bPrivate The returned private area of the object. May be
+ *              NULL
+ * @param [out] tpm2bPrivateSize The size of tpm2bPrivate in bytes. May be NULL
+ * @param [out] policy The policy that is associated with the object encoded in
+ *              JSON. May be NULL
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
+ *         complete. Call this function again later.
+ */
+TSS2_RC
+Fapi_GetTpmBlobs_Finish(
+    FAPI_CONTEXT   *context,
+    uint8_t       **tpm2bPublic,
+    size_t         *tpm2bPublicSize,
+    uint8_t       **tpm2bPrivate,
+    size_t         *tpm2bPrivateSize,
+    char          **policy)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+    IFAPI_OBJECT object;
+    UINT16 private_size;
+    size_t offset;
+    json_object *jso = NULL;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+
+    switch (context->state) {
+        statecase(context->state, ENTITY_GET_TPM_BLOBS_READ);
+            r = ifapi_keystore_load_finish(&context->keystore, &context->io, &object);
+            return_try_again(r);
+            return_if_error_reset_state(r, "read_finish failed");
+
+            if (object.objectType != IFAPI_KEY_OBJ) {
+                goto_error(r, TSS2_FAPI_RC_BAD_PATH, "No key object.", error_cleanup);
+            }
+
+            if (tpm2bPublic && tpm2bPublicSize) {
+                *tpm2bPublic = malloc(sizeof(uint8_t) * sizeof(TPM2B_PUBLIC));
+                goto_if_null(*tpm2bPublic, "Out of memory.",
+                        TSS2_FAPI_RC_MEMORY, error_cleanup);
+                offset = 0;
+                r = Tss2_MU_TPM2B_PUBLIC_Marshal(&object.misc.key.public,
+                        *tpm2bPublic, sizeof(TPM2B_PUBLIC), &offset);
+                goto_if_error_reset_state(r, "FAPI marshal TPM2B_PUBLIC",
+                        error_cleanup);
+
+                *tpm2bPublicSize = offset;
+                goto_if_error(r, "Marshaling TPM2B_PUBLIC", error_cleanup);
+            }
+            if (tpm2bPrivate && tpm2bPrivateSize) {
+                private_size = object.misc.key.private.size;
+                *tpm2bPrivateSize = private_size + sizeof(UINT16);
+                *tpm2bPrivate = malloc(*tpm2bPrivateSize);
+                goto_if_null(*tpm2bPrivate, "Out of memory.",
+                        TSS2_FAPI_RC_MEMORY, error_cleanup);
+                offset = 0;
+                r = Tss2_MU_UINT16_Marshal(private_size,
+                                           *tpm2bPrivate, sizeof(TPM2B_PRIVATE), &offset);
+                goto_if_error_reset_state(r, "FAPI marshal UINT16", error_cleanup);
+
+                memcpy(*tpm2bPrivate + offset, &object.misc.key.private.buffer[0], private_size);
+            }
+            if (object.policy_harness && policy) {
+                json_object *jso = NULL;
+                r = ifapi_json_TPMS_POLICY_HARNESS_serialize(
+                        object.policy_harness, &jso);
+                goto_if_error(r, "Serialize policy", error_cleanup);
+
+                strdup_check(*policy,
+                        json_object_to_json_string_ext(jso, JSON_C_TO_STRING_PRETTY),
+                        r, error_cleanup);
+                json_object_put(jso);
+            }
+            ifapi_cleanup_ifapi_object(&object);
+            context->state = _FAPI_STATE_INIT;
+            LOG_TRACE("finsihed");
+            return TSS2_RC_SUCCESS;
+
+        statecasedefault(context->state);
+    }
+error_cleanup:
+    if (jso)
+        json_object_put(jso);
+    ifapi_cleanup_ifapi_object(&object);
+    ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
+    ifapi_cleanup_ifapi_object(context->loadKey.key_object);
+    ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
+    LOG_TRACE("finsihed");
+    return r;
+}
diff --git a/src/tss2-fapi/api/Fapi_Import.c b/src/tss2-fapi/api/Fapi_Import.c
new file mode 100644
index 0000000..fa7772d
--- /dev/null
+++ b/src/tss2-fapi/api/Fapi_Import.c
@@ -0,0 +1,450 @@
+/* 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 <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <libgen.h>
+
+#include "tss2_fapi.h"
+#include "fapi_int.h"
+#include "fapi_util.h"
+#include "tss2_esys.h"
+#include "ifapi_json_deserialize.h"
+#include "ifapi_policy_json_deserialize.h"
+#include "tpm_json_deserialize.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+#include "fapi_crypto.h"
+
+/** One-Call function for Fapi_Import
+ *
+ * Imports a JSON encoded policy, policy template or key and stores it at the
+ * given path.
+ *
+ * @param [in,out] context The FAPI_CONTEXT
+ * @param [in] path the path to which the object is imported
+ * @param [in] importData The data that is imported
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context, path or importData
+ *         is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_PATH: If path does not map to a FAPI policy or key.
+ * @retval TSS2_FAPI_RC_PATH_ALREADY_EXISTS: if a policy or key already exists
+ *         at path.
+ * @retval TSS2_FAPI_RC_BAD_VALUE: if importData contains invalid data.
+ * @retval TSS2_FAPI_RC_STORAGE_ERROR: if the FAPI storage cannot be updated.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_Import(
+    FAPI_CONTEXT *context,
+    char   const *path,
+    char   const *importData)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(path);
+    check_not_null(importData);
+
+    r = Fapi_Import_Async(context, path, importData);
+    return_if_error_reset_state(r, "Entity_Import");
+
+    do {
+        /* We wait for file I/O to be ready if the FAPI state automata
+           are in a file I/O state. */
+        r = ifapi_io_poll(&context->io);
+        return_if_error(r, "Something went wrong with IO polling");
+
+        /* Repeatedly call the finish function, until FAPI has transitioned
+           through all execution stages / states of this invocation. */
+        r = Fapi_Import_Finish(context);
+    } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
+
+    return_if_error_reset_state(r, "Entity_Import");
+
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous function for Fapi_Import
+ *
+ * Imports a JSON encoded policy, policy template or key and stores it at the
+ * given path.
+ *
+ * Call Fapi_Import_Finish to finish the execution of this command.
+ *
+ * @param [in,out] context The FAPI_CONTEXT
+ * @param [in] path the path to which the object is imported
+ * @param [in] importData The data that is imported
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context, path or importData
+ *         is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_PATH: If path does not map to a FAPI policy or key.
+ * @retval TSS2_FAPI_RC_PATH_ALREADY_EXISTS: if a policy or key already exists
+ *         at path.
+ * @retval TSS2_FAPI_RC_BAD_VALUE: if importData contains invalid data.
+ * @retval TSS2_FAPI_RC_STORAGE_ERROR: if the FAPI storage cannot be updated.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_Import_Async(
+    FAPI_CONTEXT *context,
+    char   const *path,
+    char   const *importData)
+{
+    LOG_TRACE("called for context:%p", context);
+    LOG_TRACE("path: %s", path);
+    LOG_TRACE("importData: %s", importData);
+
+    TSS2_RC r;
+    json_object *jso = NULL;
+    json_object *jso2;
+    size_t pos = 0;
+    TPMS_POLICY_HARNESS policyHarness;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(path);
+    check_not_null(importData);
+
+    /* Helpful alias pointers */
+    IFAPI_ImportKey * command = &context->cmd.ImportKey;
+    IFAPI_OBJECT *object = &command->object;
+    IFAPI_EXT_PUB_KEY * extPubKey = &object->misc.ext_pub_key;
+    IFAPI_DUPLICATE * keyTree = &object->misc.key_tree;
+
+    if (context->state != _FAPI_STATE_INIT) {
+        return_error(TSS2_FAPI_RC_BAD_SEQUENCE, "Invalid State");
+    }
+
+    command->jso_string = NULL;
+    strdup_check(command->out_path, path, r, cleanup_error);
+    memset(&command->object, 0, sizeof(IFAPI_OBJECT));
+    extPubKey->pem_ext_public = NULL;
+
+    if (strncmp(importData, IFAPI_PEM_PUBLIC_STRING,
+                sizeof(IFAPI_PEM_PUBLIC_STRING) - 1) == 0) {
+        object->objectType = IFAPI_EXT_PUB_KEY_OBJ;
+        strdup_check(extPubKey->pem_ext_public, importData, r, cleanup_error);
+        extPubKey->certificate = NULL;
+
+       TPM2_ALG_ID rsaOrEcc = ifapi_get_signature_algorithm_from_pem(
+               extPubKey->pem_ext_public);
+        r = ifapi_initialize_sign_public(rsaOrEcc, &extPubKey->public);
+        goto_if_error(r, "Could not initialize key template", cleanup_error);
+
+        r =  ifapi_get_tpm2b_public_from_pem(extPubKey->pem_ext_public,
+                                             &extPubKey->public);
+        goto_if_error(r, "Convert PEM public key into TPM public key.", cleanup_error);
+
+        command->new_object = *object;
+        if (strncmp("/", path, 1) == 0)
+            pos = 1;
+        if (strncmp(&path[pos], IFAPI_PUB_KEY_DIR, strlen(IFAPI_PUB_KEY_DIR)) != 0) {
+            SAFE_FREE(command->out_path);
+            r = ifapi_asprintf(&command->out_path,
+                               "%s%s%s", IFAPI_PUB_KEY_DIR, IFAPI_FILE_DELIM,
+                               &path[pos]);
+            goto_if_error(r, "Allocate path name", cleanup_error);
+
+        }
+        r = ifapi_non_tpm_mode_init(context);
+        return_if_error(r, "Initialize Import in none TPM mode");
+
+        context->state = IMPORT_KEY_WRITE_OBJECT_PREPARE;
+
+    } else if (strcmp(importData, IFAPI_PEM_PRIVATE_KEY) == 0) {
+          return_error(TSS2_FAPI_RC_NOT_IMPLEMENTED, "Invalid import data");
+
+    } else {
+        /* Check whether TCTI and ESYS are initialized */
+        return_if_null(context->esys, "Command can't be executed in none TPM mode.",
+                       TSS2_FAPI_RC_NO_TPM);
+
+        /* If the async state automata of FAPI shall be tested, then we must not set
+       the timeouts of ESYS to blocking mode.
+       During testing, the mssim tcti will ensure multiple re-invocations.
+       Usually however the synchronous invocations of FAPI shall instruct ESYS
+       to block until a result is available. */
+#ifndef TEST_FAPI_ASYNC
+        r = Esys_SetTimeout(context->esys, TSS2_TCTI_TIMEOUT_BLOCK);
+        return_if_error_reset_state(r, "Set Timeout to blocking");
+#endif /* TEST_FAPI_ASYNC */
+
+        r = ifapi_session_init(context);
+        return_if_error(r, "Initialize Import");
+
+        /* Otherwise a JSON object has to be checked whether a key or policy is passed */
+        jso = json_tokener_parse(importData);
+        return_if_null(jso, "Json error.", TSS2_FAPI_RC_BAD_VALUE);
+
+        if (ifapi_get_sub_object(jso, IFAPI_JSON_TAG_POLICY, &jso2)) {
+            /* Create policy object */
+            r = ifapi_json_TPMS_POLICY_HARNESS_deserialize(jso, &policyHarness);
+            goto_if_error(r, "Serialize policy", cleanup_error);
+
+            r = ifapi_policy_store_store_async(&context->pstore, &context->io,
+                    command->out_path, &policyHarness);
+            goto_if_error_reset_state(r, "Could not open: %s", cleanup_error,
+                    command->out_path);
+
+            ifapi_cleanup_policy_harness(&policyHarness);
+
+            context->state = IMPORT_KEY_WRITE_POLICY;
+
+            r = TSS2_RC_SUCCESS;
+        } else {
+            /* Write key object */
+            r = ifapi_json_IFAPI_OBJECT_deserialize(jso, object);
+            goto_if_error(r, "Invalid object.", cleanup_error);
+
+            switch (object->objectType) {
+            case IFAPI_EXT_PUB_KEY_OBJ:
+                /* Write json string stored in importData */
+                   /* Start writing the EK to the key store */
+                r = ifapi_keystore_store_async(&context->keystore, &context->io,
+                        command->out_path, object);
+                goto_if_error_reset_state(r, "Could not open: %sh", cleanup_error,
+                        command->out_path);
+
+                context->state = IMPORT_KEY_WRITE;
+                break;
+
+            case IFAPI_DUPLICATE_OBJ:
+                r = ifapi_get_name(
+                        &keyTree->public_parent.publicArea,
+                        &command->parent_name);
+                goto_if_error2(r, "Get parent name", cleanup_error);
+
+                context->state = IMPORT_KEY_SEARCH;
+                break;
+
+            default:
+                goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Invalid object type",
+                           cleanup_error);
+                break;
+            }
+            command->parent_path = NULL;
+        }
+    }
+    json_object_put(jso);
+    LOG_TRACE("finsihed");
+    return r;
+
+cleanup_error:
+    if(jso)
+        json_object_put(jso);
+    context->state = _FAPI_STATE_INIT;
+    ifapi_cleanup_policy_harness(&policyHarness);
+    SAFE_FREE(command->jso_string);
+    SAFE_FREE(extPubKey->pem_ext_public);
+    SAFE_FREE(command->out_path);
+    return r;
+}
+
+/** Asynchronous finish function for Fapi_Import_
+ *
+ * This function should be called after a previous Fapi_Import_Async.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
+ *         complete. Call this function again later.
+ */
+TSS2_RC
+Fapi_Import_Finish(
+    FAPI_CONTEXT *context)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+    ESYS_TR session;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+
+    /* Helpful alias pointers */
+    IFAPI_ImportKey * command = &context->cmd.ImportKey;
+    IFAPI_OBJECT *newObject = &command->new_object;
+    IFAPI_OBJECT *object = &command->object;
+    IFAPI_DUPLICATE * keyTree = &object->misc.key_tree;
+
+    switch (context->state) {
+        statecase(context->state, IMPORT_KEY_WRITE_POLICY);
+            r = ifapi_policy_store_store_finish(&context->pstore, &context->io);
+            return_try_again(r);
+            return_if_error_reset_state(r, "write_finish failed");
+
+            context->state =  _FAPI_STATE_INIT;
+            break;
+
+        statecase(context->state, IMPORT_KEY_WRITE);
+            r = ifapi_keystore_store_finish(&context->keystore, &context->io);
+            return_try_again(r);
+            return_if_error_reset_state(r, "write_finish failed");
+
+            context->state =  _FAPI_STATE_INIT;
+            break;
+
+        statecase(context->state, IMPORT_KEY_SEARCH);
+            r = ifapi_keystore_search_obj(&context->keystore, &context->io,
+                                          &command->parent_name,
+                                          &command->parent_path);
+            return_try_again(r);
+            goto_if_error(r, "Search Key", error_cleanup);
+
+            context->state = IMPORT_KEY_LOAD_PARENT;
+            fallthrough;
+
+        statecase(context->state, IMPORT_KEY_LOAD_PARENT);
+            r = ifapi_load_key(context, command->parent_path,
+                               &command->parent_object);
+            return_try_again(r);
+            goto_if_error(r, "Fapi load key.", error_cleanup);
+
+            context->state = IMPORT_KEY_AUTHORIZE_PARENT;
+            fallthrough;
+
+        statecase(context->state, IMPORT_KEY_AUTHORIZE_PARENT);
+            r = ifapi_authorize_object(context, command->parent_object, &session);
+            return_try_again(r);
+            goto_if_error(r, "Authorize key.", error_cleanup);
+
+            TPMT_SYM_DEF_OBJECT symmetric;
+            symmetric.algorithm = TPM2_ALG_NULL;
+            r = Esys_Import_Async(context->esys,
+                  command->parent_object->handle,
+                  session,
+                  ESYS_TR_NONE, ESYS_TR_NONE,
+                  NULL, &keyTree->public,
+                  &keyTree->duplicate,
+                  &keyTree->encrypted_seed,
+                  &symmetric);
+            goto_if_error(r, "Import Async", error_cleanup);
+
+            context->state = IMPORT_KEY_IMPORT;
+            fallthrough;
+
+        statecase(context->state, IMPORT_KEY_IMPORT);
+            r = Esys_Import_Finish(context->esys, &command->private);
+            try_again_or_error_goto(r, "Import", error_cleanup);
+
+            context->state = IMPORT_KEY_WAIT_FOR_FLUSH;
+            fallthrough;
+
+        statecase(context->state, IMPORT_KEY_WAIT_FOR_FLUSH);
+            r = ifapi_flush_object(context, command->parent_object->handle);
+            ifapi_cleanup_ifapi_object(command->parent_object);
+            return_try_again(r);
+            goto_if_error(r, "Flush key", error_cleanup);
+
+            memset(newObject, 0, sizeof(IFAPI_OBJECT));
+            newObject->objectType = IFAPI_KEY_OBJ;
+            newObject->misc.key.public = keyTree->public;
+            newObject->misc.key.private.size =  command->private->size;
+            newObject->misc.key.private.buffer  = &command->private->buffer[0];
+            newObject->misc.key.policyInstance = NULL;
+            newObject->misc.key.description = NULL;
+            newObject->misc.key.certificate = NULL;
+            r = ifapi_get_profile_sig_scheme(&context->profiles.default_profile,
+                                             &keyTree->public.publicArea,
+                                             &newObject->misc.key.signing_scheme);
+            goto_if_error(r, "Get signing scheme.", error_cleanup);
+            fallthrough;
+
+        statecase(context->state, IMPORT_KEY_WRITE_OBJECT_PREPARE);
+            /* Perform esys serialization if necessary */
+            r = ifapi_esys_serialize_object(context->esys, newObject);
+            goto_if_error(r, "Prepare serialization", error_cleanup);
+
+            /* Start writing the NV object to the key store */
+            r = ifapi_keystore_store_async(&context->keystore, &context->io,
+                                           command->out_path,
+                                           newObject);
+            goto_if_error_reset_state(r, "Could not open: %sh", error_cleanup,
+                                      context->nv_cmd.nvPath);
+
+            context->state = IMPORT_KEY_WRITE_OBJECT;
+            fallthrough;
+
+        statecase(context->state, IMPORT_KEY_WRITE_OBJECT);
+            /* Finish writing the object to the key store */
+            r = ifapi_keystore_store_finish(&context->keystore, &context->io);
+            return_try_again(r);
+            return_if_error_reset_state(r, "write_finish failed");
+
+            fallthrough;
+
+        statecase(context->state, IMPORT_KEY_CLEANUP)
+            r = ifapi_cleanup_session(context);
+            try_again_or_error_goto(r, "Cleanup", error_cleanup);
+
+            break;
+
+        statecasedefault(context->state);
+    }
+
+    /* Reset the ESYS timeout to non-blocking, immediate response. */
+    if (context->esys) {
+        r = Esys_SetTimeout(context->esys, 0);
+        goto_if_error(r, "Set Timeout to non-blocking", error_cleanup);
+    }
+
+    context->state = _FAPI_STATE_INIT;
+    SAFE_FREE(command->out_path);
+    SAFE_FREE(command->parent_path);
+    ifapi_cleanup_ifapi_object(&command->object);
+    SAFE_FREE(command->private);
+    ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
+    if (context->loadKey.key_object){
+        ifapi_cleanup_ifapi_object(context->loadKey.key_object);
+    }
+    LOG_TRACE("finished");
+    return TSS2_RC_SUCCESS;
+
+error_cleanup:
+    SAFE_FREE(command->out_path);
+    SAFE_FREE(command->parent_path);
+    ifapi_cleanup_ifapi_object(&command->object);
+    SAFE_FREE(command->private);
+    Esys_SetTimeout(context->esys, 0);
+    ifapi_session_clean(context);
+    ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
+    ifapi_cleanup_ifapi_object(context->loadKey.key_object);
+    ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
+    return r;
+}
diff --git a/src/tss2-fapi/api/Fapi_Initialize.c b/src/tss2-fapi/api/Fapi_Initialize.c
new file mode 100644
index 0000000..47503a2
--- /dev/null
+++ b/src/tss2-fapi/api/Fapi_Initialize.c
@@ -0,0 +1,277 @@
+/* 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 <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#ifndef NO_DL
+#include <dlfcn.h>
+#endif /* NO_DL */
+
+#include "tss2_tcti.h"
+#include "tss2_tctildr.h"
+#include "tss2_esys.h"
+#include "tss2_fapi.h"
+#include "fapi_int.h"
+#include "fapi_util.h"
+#include "ifapi_json_deserialize.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+/** One-Call function for Fapi_Initialize
+ *
+ * Initializes a FAPI_CONTEXT that holds all the state and metadata information
+ * during an interaction with the TPM.
+ *
+ * @param context [out] The FAPI_CONTEXT
+ * @param uri [in] Unused in this version of the FAPI. Must be NULL
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
+ * @retval TSS2_FAPI_RC_BAD_VALUE: if uri is not NULL.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_Initialize(
+    FAPI_CONTEXT **context,
+    char const *uri)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r = TSS2_RC_SUCCESS;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    if (uri != NULL) {
+        LOG_ERROR("uri is not NULL");
+        return TSS2_FAPI_RC_BAD_VALUE;
+    }
+
+    r = Fapi_Initialize_Async(context, uri);
+    return_if_error(r,  "FAPI Async call initialize");
+    check_oom(*context);
+
+    do {
+        /* We wait for file I/O to be ready if the FAPI state automata
+           are in a file I/O state. */
+        r = ifapi_io_poll(&(*context)->io);
+        return_if_error(r, "Something went wrong with IO polling");
+
+        /* Repeatedly call the finish function, until FAPI has transitioned
+           through all execution stages / states of this invocation. */
+        r = Fapi_Initialize_Finish(context);
+    } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
+
+    LOG_TRACE("finsihed");
+    return r;
+}
+
+/** Asynchronous function for Fapi_Initialize
+ *
+ * Initializes a FAPI_CONTEXT that holds all the state and metadata information
+ * during an interaction with the TPM.
+ *
+ * Call Fapi_Initialize to finish the execution of this command.
+ *
+ * @param context [out] The FAPI_CONTEXT
+ * @param uri [in] Unused in this version of the FAPI. Must be NULL
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
+ * @retval TSS2_FAPI_RC_BAD_VALUE: if uri is not NULL.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_Initialize_Async(
+    FAPI_CONTEXT **context,
+    char const *uri)
+{
+    LOG_TRACE("called for context:%p", context);
+    LOG_TRACE("uri: %s", uri);
+
+    TSS2_RC r = TSS2_RC_SUCCESS;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    if (uri != NULL) {
+        LOG_ERROR("uri is not NULL");
+        return TSS2_FAPI_RC_BAD_VALUE;
+    }
+
+    *context = NULL;
+
+    /* Allocate memory for the FAPI context
+     * After this errors must jump to cleanup_return instead of returning. */
+    *context = calloc(1, sizeof(FAPI_CONTEXT));
+    return_if_null(*context, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+    memset(*context, 0, sizeof(FAPI_CONTEXT));
+
+    /* Initialize the context */
+    r = ifapi_config_initialize_async(&(*context)->io);
+    goto_if_error(r, "Could not initialize FAPI context", cleanup_return);
+
+    (*context)->state = INITIALIZE_READ;
+
+cleanup_return:
+    if (r)
+        SAFE_FREE(*context);
+    LOG_TRACE("finsihed");
+    return r;
+}
+
+/** Asynchronous finish function for Fapi_Initialize
+ *
+ * This function should be called after a previous Fapi_Initialize_Async.
+ *
+ * @param [out] context The FAPI_CONTEXT
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
+ *         complete. Call this function again later.
+ */
+TSS2_RC
+Fapi_Initialize_Finish(
+    FAPI_CONTEXT **context)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+    TPMI_YES_NO moreData;
+    TSS2_TCTI_CONTEXT *fapi_tcti = NULL;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(*context);
+
+    /* Helpful alias pointers */
+    TPMS_CAPABILITY_DATA **capability = &(*context)->cmd.Initialize.capability;
+
+    switch ((*context)->state) {
+    statecase((*context)->state, INITIALIZE_READ);
+        r = ifapi_config_initialize_finish(&(*context)->io, &(*context)->config);
+        return_try_again(r);
+        goto_if_error(r, "Could not finish initialization", cleanup_return);
+
+        r = ifapi_eventlog_initialize(&((*context)->eventlog), (*context)->config.log_dir);
+        goto_if_error(r, "Initializing evenlog module", cleanup_return);
+
+        r = ifapi_keystore_initialize(&((*context)->keystore),
+                                      (*context)->config.keystore_dir,
+                                      (*context)->config.user_dir,
+                                      (*context)->config.profile_name);
+        goto_if_error2(r, "Keystore could not be initialized.", cleanup_return);
+
+        /* Policy directory will be placed in keystore dir */
+        r = ifapi_policy_store_initialize(&((*context)->pstore),
+                                          (*context)->config.keystore_dir);
+        goto_if_error2(r, "Keystore could not be initialized.", cleanup_return);
+
+//        (*context)->config.user_dir = (*context)->keystore.userdir;
+
+        (*context)->state = INITIALIZE_INIT_TCTI;
+        fallthrough;
+
+    statecase((*context)->state, INITIALIZE_INIT_TCTI);
+        if (strcasecmp((*context)->config.tcti, "none") == 0) {
+            /* FAPI will be used in none TPM mode */
+            (*context)->esys =  NULL;
+            (*context)->state = INITIALIZE_READ_PROFILE_INIT;
+            return TSS2_FAPI_RC_TRY_AGAIN;
+        }
+
+        r = Tss2_TctiLdr_Initialize((*context)->config.tcti, &fapi_tcti);
+        goto_if_error(r, "Initializing TCTI.", cleanup_return);
+        r = Esys_Initialize(&((*context)->esys), fapi_tcti, NULL);
+        goto_if_error(r, "Initialize esys context.", cleanup_return);
+
+        r = Esys_Startup((*context)->esys, TPM2_SU_CLEAR);
+        if (r != TSS2_RC_SUCCESS && r != TPM2_RC_INITIALIZE) {
+            LOG_ERROR("Esys_Startup FAILED! Response Code : 0x%x", r);
+            return r;
+        }
+        (*context)->state = INITIALIZE_GET_CAP;
+        fallthrough;
+
+    statecase((*context)->state, INITIALIZE_GET_CAP);
+        /* Determine the maximal value for transfer of nv data */
+        r = Esys_GetCapability_Async((*context)->esys, ESYS_TR_NONE, ESYS_TR_NONE,
+                                     ESYS_TR_NONE,
+                                     TPM2_CAP_TPM_PROPERTIES, TPM2_PT_NV_BUFFER_MAX, 1);
+        goto_if_error(r, "Error json deserialize", cleanup_return);
+
+        (*context)->state = INITIALIZE_WAIT_FOR_CAP;
+        fallthrough;
+
+    statecase((*context)->state, INITIALIZE_WAIT_FOR_CAP);
+        r = Esys_GetCapability_Finish((*context)->esys, &moreData, capability);
+        return_try_again(r);
+        goto_if_error(r, "Get capability data.", cleanup_return);
+
+        if ((*capability)->data.tpmProperties.count == 1 &&
+                (*capability)->data.tpmProperties.tpmProperty[0].property ==
+                TPM2_PT_NV_BUFFER_MAX) {
+            (*context)->nv_buffer_max = (*capability)->data.tpmProperties.tpmProperty[0].value;
+            if ((*context)->nv_buffer_max > IFAPI_MAX_BUFFER_SIZE)
+                (*context)->nv_buffer_max = IFAPI_MAX_BUFFER_SIZE;
+        } else {
+            (*context)->nv_buffer_max = 64;
+        }
+        fallthrough;
+
+    statecase((*context)->state, INITIALIZE_READ_PROFILE_INIT);
+        r = ifapi_profiles_initialize_async(&(*context)->profiles, &(*context)->io,
+                                            (*context)->config.profile_dir,
+                                            (*context)->config.profile_name);
+        return_if_error(r, "Read profile");
+
+        (*context)->state = INITIALIZE_READ_PROFILE;
+        fallthrough;
+
+    statecase((*context)->state, INITIALIZE_READ_PROFILE);
+        r = ifapi_profiles_initialize_finish(&(*context)->profiles, &(*context)->io);
+        FAPI_SYNC(r, "Read profile.", cleanup_return);
+
+        LOG_DEBUG("success: *context %p", *context);
+        break;
+
+    statecasedefault((*context)->state);
+    }
+
+    (*context)->state = _FAPI_STATE_INIT;
+    SAFE_FREE(*capability);
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+
+cleanup_return:
+    if ((*context)->esys) {
+        Esys_GetTcti((*context)->esys, &fapi_tcti);
+        Esys_Finalize(&(*context)->esys);
+    }
+    if (fapi_tcti) {
+        Tss2_TctiLdr_Finalize(&fapi_tcti);
+    }
+    free(*context);
+    *context = NULL;
+
+    return r;
+}
diff --git a/src/tss2-fapi/api/Fapi_List.c b/src/tss2-fapi/api/Fapi_List.c
new file mode 100644
index 0000000..cb7860d
--- /dev/null
+++ b/src/tss2-fapi/api/Fapi_List.c
@@ -0,0 +1,207 @@
+/* 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 <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <dirent.h>
+
+#include "tss2_fapi.h"
+#include "fapi_int.h"
+#include "fapi_util.h"
+#include "tss2_esys.h"
+#include "ifapi_keystore.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+/** One-Call function for Fapi_List
+ *
+ * Enumerates all objects in the metadatastore in a fiven path and returns them
+ * in a list of complete paths from the root with the values separated by
+ * colons.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] searchPath The path that identifies the root of the search
+ * @param [out] pathList A colon-separated list of all objects in the root path
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context, searchPath, pathlist is
+ *         NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_PATH: if searchPath does not map to a FAPI entity.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_List(
+    FAPI_CONTEXT *context,
+    char   const *searchPath,
+    char        **pathList)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(searchPath);
+    check_not_null(pathList);
+
+    r = Fapi_List_Async(context, searchPath);
+    return_if_error_reset_state(r, "Entities_List");
+
+    do {
+        /* We wait for file I/O to be ready if the FAPI state automata
+           are in a file I/O state. */
+        r = ifapi_io_poll(&context->io);
+        return_if_error(r, "Something went wrong with IO polling");
+
+        /* Repeatedly call the finish function, until FAPI has transitioned
+           through all execution stages / states of this invocation. */
+        r = Fapi_List_Finish(context, pathList);
+    } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
+
+    return_if_error_reset_state(r, "Entities_List");
+
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous function for Fapi_List
+ *
+ * Enumerates all objects in the metadatastore in a fiven path and returns them
+ * in a list of complete paths from the root with the values separated by
+ * colons.
+ *
+ * Call Fapi_List_Finish to finish the execution of this command.
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] searchPath The path that identifies the root of the search
+ *
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or searchPath is
+ *         NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_PATH: if searchPath does not map to a FAPI entity.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_List_Async(
+    FAPI_CONTEXT *context,
+    char   const *searchPath)
+{
+    LOG_TRACE("called for context:%p", context);
+    LOG_TRACE("searchPath: %s", searchPath);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(searchPath);
+
+    /* Helpful alias pointers */
+    IFAPI_Entities_List * command = &context->cmd.Entities_List;
+
+    r = ifapi_non_tpm_mode_init(context);
+    return_if_error(r, "Initialize List");
+
+    strdup_check(command->searchPath, searchPath, r, error_cleanup);
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+error_cleanup:
+    SAFE_FREE(command->searchPath);
+    return r;
+}
+
+/** Asynchronous finish function for Fapi_List
+ *
+ * This function should be called after a previous Fapi_List_Async.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [out] pathList A colon-separated list of all objects in the root path
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or pathList is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
+ *         complete. Call this function again later.
+ */
+TSS2_RC
+Fapi_List_Finish(
+    FAPI_CONTEXT *context,
+    char        **pathList)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    size_t sizePathList = 0;
+    size_t numPaths = 0;
+    char **pathArray = NULL;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(pathList);
+
+    /* Helpful alias pointers */
+    IFAPI_Entities_List * command = &context->cmd.Entities_List;
+
+    r = ifapi_keystore_list_all(&context->keystore, command->searchPath,
+                                &pathArray, &numPaths);
+    return_if_error(r, "get entities.");
+
+    if (numPaths == 0)
+        goto cleanup;
+
+    /* Determine size of char string to be returnded */
+    for (size_t i = 0; i < numPaths; i++)
+        sizePathList += strlen(pathArray[i]);
+
+    /* Allocate path list plus colon separators plus \0-terminator */
+    *pathList = malloc(sizePathList + (numPaths - 1) + 1);
+    goto_if_null2(*pathList, "Out of memory", r, TSS2_FAPI_RC_MEMORY,  cleanup);
+
+    (*pathList)[0] = '\0';
+    (*pathList)[sizePathList + numPaths - 1] = '\0';
+
+    for (size_t i = 0; i < numPaths; i++) {
+        strcat(*pathList, pathArray[i]);
+        if (i < numPaths - 1)
+            strcat(*pathList, IFAPI_LIST_DELIM);
+    }
+
+cleanup:
+    SAFE_FREE(command->searchPath);
+    if (numPaths == 0 && (r == TSS2_RC_SUCCESS)) {
+        return_error2(TSS2_FAPI_RC_PATH_NOT_FOUND,
+                      "Path not found: %s", command->searchPath);
+    }
+    if (numPaths > 0) {
+        for (size_t i = 0; i < numPaths; i++){
+            SAFE_FREE(pathArray[i]);
+        }
+    }
+    SAFE_FREE(pathArray);
+    LOG_TRACE("finsihed");
+    return r;
+}
diff --git a/src/tss2-fapi/api/Fapi_NvExtend.c b/src/tss2-fapi/api/Fapi_NvExtend.c
new file mode 100644
index 0000000..433f951
--- /dev/null
+++ b/src/tss2-fapi/api/Fapi_NvExtend.c
@@ -0,0 +1,454 @@
+/* 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 <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "tss2_fapi.h"
+#include "ifapi_json_serialize.h"
+#include "fapi_crypto.h"
+#include "fapi_int.h"
+#include "fapi_util.h"
+#include "tss2_esys.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+/** One-Call function for Fapi_NvExtend
+ *
+ * Performs an extend operation on an NV index with the type extend.
+ *
+ * @param [in, out] context the FAPI context
+ * @param [in] nvPath The path to the NV index that is extended
+ * @param [in] data The data to extend on the NV index
+ * @param [in] dataSize The size of the data to extend. Must be smaller than
+ *             1024
+ * @param [in] logData A JSON representation of the data that is written to the
+ *         event log. May be NULL
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context, nvPath, or data is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_PATH: if nvPath is not found.
+ * @retval TSS2_FAPI_RC_NV_WRONG_TYPE: if the NV is not an extendable index.
+ * @retval TSS2_FAPI_RC_POLICY_UNKNOWN: if the policy is unknown.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_NvExtend(
+    FAPI_CONTEXT  *context,
+    char    const *nvPath,
+    uint8_t const *data,
+    size_t         dataSize,
+    char    const *logData)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r, r2;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(nvPath);
+    check_not_null(data);
+
+    /* Check whether TCTI and ESYS are initialized */
+    return_if_null(context->esys, "Command can't be executed in none TPM mode.",
+                   TSS2_FAPI_RC_NO_TPM);
+
+    /* If the async state automata of FAPI shall be tested, then we must not set
+       the timeouts of ESYS to blocking mode.
+       During testing, the mssim tcti will ensure multiple re-invocations.
+       Usually however the synchronous invocations of FAPI shall instruct ESYS
+       to block until a result is available. */
+#ifndef TEST_FAPI_ASYNC
+    r = Esys_SetTimeout(context->esys, TSS2_TCTI_TIMEOUT_BLOCK);
+    return_if_error_reset_state(r, "Set Timeout to blocking");
+#endif /* TEST_FAPI_ASYNC */
+
+    r = Fapi_NvExtend_Async(context, nvPath, data, dataSize, logData);
+    return_if_error_reset_state(r, "NV_Extend");
+
+    do {
+        /* We wait for file I/O to be ready if the FAPI state automata
+           are in a file I/O state. */
+        r = ifapi_io_poll(&context->io);
+        return_if_error(r, "Something went wrong with IO polling");
+
+        /* Repeatedly call the finish function, until FAPI has transitioned
+           through all execution stages / states of this invocation. */
+        r = Fapi_NvExtend_Finish(context);
+    } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
+
+    /* Reset the ESYS timeout to non-blocking, immediate response. */
+    r2 = Esys_SetTimeout(context->esys, 0);
+    return_if_error(r2, "Set Timeout to non-blocking");
+
+    return_if_error_reset_state(r, "NV_Extend");
+
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous function for Fapi_NvExtend
+ *
+ * Performs an extend operation on an NV index with the type extend.
+ *
+ * Call Fapi_NvExtend_Finish to finish the execution of this command.
+ *
+ * @param [in, out] context the FAPI context
+ * @param [in] nvPath The path to the NV index that is extended
+ * @param [in] data The data to extend on the NV index
+ * @param [in] dataSize The size of the data to extend. Must be smaller than
+ *             1024
+ * @param [in] logData A JSON representation of the data that is written to the
+ *         event log. May be NULL
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context, nvPath, or data is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_PATH: if nvPath is not found.
+ * @retval TSS2_FAPI_RC_NV_WRONG_TYPE: if the NV is not an extendable index.
+ * @retval TSS2_FAPI_RC_POLICY_UNKNOWN: if the policy is unknown.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_NvExtend_Async(
+    FAPI_CONTEXT  *context,
+    char    const *nvPath,
+    uint8_t const *data,
+    size_t         dataSize,
+    char    const *logData)
+{
+    LOG_TRACE("called for context:%p", context);
+    LOG_TRACE("nvPath: %s", nvPath);
+    if (data) {
+        LOGBLOB_TRACE(data, dataSize, "data");
+    } else {
+        LOG_TRACE("data: (null) dataSize: %zi", dataSize);
+    }
+    LOG_TRACE("logData: %s", logData);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(nvPath);
+    check_not_null(data);
+
+    /* Helpful alias pointers */
+    IFAPI_NV_Cmds * command = &context->nv_cmd;
+
+    memset(command, 0 ,sizeof(IFAPI_NV_Cmds));
+    command->offset = 0;
+    command->data = malloc(dataSize);
+    goto_if_null2(command->data, "Out of memory", r, TSS2_FAPI_RC_MEMORY,
+            error_cleanup);
+    strdup_check(command->nvPath, nvPath, r, error_cleanup);
+    strdup_check(command->logData, logData, r, error_cleanup);
+
+    command->numBytes = dataSize;
+    if (context->state == _FAPI_STATE_INIT)
+        ifapi_session_init(context);
+
+    r = ifapi_keystore_load_async(&context->keystore, &context->io, command->nvPath);
+    goto_if_error2(r, "Could not open: %s", error_cleanup, command->nvPath);
+
+    context->state = NV_EXTEND_READ;
+    LOG_TRACE("finsihed");
+    return r;
+error_cleanup:
+    SAFE_FREE(command->data);
+    SAFE_FREE(command->nvPath);
+    SAFE_FREE(command->logData);
+    return r;
+}
+
+/** Asynchronous finish function for Fapi_NvExtend
+ *
+ * This function should be called after a previous Fapi_NvExtend.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
+ *         complete. Call this function again later.
+ */
+TSS2_RC
+Fapi_NvExtend_Finish(
+    FAPI_CONTEXT  *context)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+    ESYS_TR authIndex;
+    json_object *jso = NULL;
+    IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext = NULL;
+    TPMI_ALG_HASH hashAlg;
+    size_t hashSize;
+    ESYS_TR auth_session;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+
+    /* Helpful alias pointers */
+    IFAPI_NV_Cmds * command = &context->nv_cmd;
+    TPM2B_MAX_NV_BUFFER *auxData = (TPM2B_MAX_NV_BUFFER *)&context->aux_data;
+    size_t dataIdx = command->data_idx;
+    ESYS_TR nvIndex =  command->esys_handle;
+    const uint8_t *data = command->data;
+    IFAPI_OBJECT *object = &command->nv_object;
+    IFAPI_OBJECT *authObject = &command->auth_object;
+    IFAPI_EVENT *event = &command->pcr_event;
+
+    switch (context->state) {
+    statecase(context->state, NV_EXTEND_READ)
+        /* First check whether the file in object store can be updated. */
+        r = ifapi_keystore_check_writeable(&context->keystore, &context->io, command->nvPath);
+        goto_if_error_reset_state(r, "Check whether update object store is possible.", error_cleanup);
+
+        r = ifapi_keystore_load_finish(&context->keystore, &context->io, object);
+        return_try_again(r);
+        return_if_error_reset_state(r, "read_finish failed");
+
+        if (object->objectType != IFAPI_NV_OBJ)
+            goto_error(r, TSS2_FAPI_RC_BAD_PATH, "%s is no NV object.", error_cleanup,
+                       command->nvPath);
+
+        r = ifapi_initialize_object(context->esys, object);
+        goto_if_error_reset_state(r, "Initialize NV object", error_cleanup);
+
+        /* Store object info in context */
+        nvIndex = command->nv_object.handle;
+        command->esys_handle =  context->nv_cmd.nv_object.handle;
+        command->nv_obj = object->misc.nv;
+
+        if (object->misc.nv.public.nvPublic.attributes & TPMA_NV_PPWRITE) {
+            ifapi_init_hierarchy_object(authObject, ESYS_TR_RH_PLATFORM);
+            authIndex = ESYS_TR_RH_PLATFORM;
+        } else {
+            if (object->misc.nv.public.nvPublic.attributes & TPMA_NV_OWNERWRITE) {
+                ifapi_init_hierarchy_object(authObject, ESYS_TR_RH_OWNER);
+                authIndex = ESYS_TR_RH_OWNER;
+            } else {
+                authIndex = nvIndex;
+            }
+            *authObject = *object;
+        }
+        command->auth_index = authIndex;
+        context->primary_state = PRIMARY_INIT;
+        r = ifapi_get_sessions_async(context,
+                                     IFAPI_SESSION_GENEK | IFAPI_SESSION1,
+                                     TPMA_SESSION_DECRYPT, 0);
+        goto_if_error_reset_state(r, "Create sessions", error_cleanup);
+
+
+        context->state = NV_EXTEND_WAIT_FOR_SESSION;
+        return TSS2_FAPI_RC_TRY_AGAIN;
+
+    statecase(context->state, NV_EXTEND_WAIT_FOR_SESSION)
+//TODO: Pass the namealg of the NV index into the session to be created
+        r = ifapi_get_sessions_finish(context, &context->profiles.default_profile);
+        return_try_again(r);
+
+        goto_if_error_reset_state(r, " FAPI create session", error_cleanup);
+
+        if (command->numBytes > context->nv_buffer_max)
+            auxData->size = context->nv_buffer_max;
+        else
+            auxData->size = command->numBytes;
+        memcpy(&auxData->buffer[0], &data[0], auxData->size);
+        command->data_idx = auxData->size;
+
+        /* Authorization needed if NO_DA is not  set */
+        if (!(object->misc.nv.public.nvPublic.attributes & TPMA_NV_NO_DA)) {
+            r = ifapi_set_auth(context, authObject, "NV Extend");
+            goto_if_error_reset_state(r, "Fapi_NV_UndefineSpace", error_cleanup);
+        }
+        context->state = NV_EXTEND_AUTHORIZE;
+        fallthrough;
+
+    statecase(context->state, NV_EXTEND_AUTHORIZE)
+        r = ifapi_authorize_object(context, authObject, &auth_session);
+        return_try_again(r);
+        goto_if_error(r, "Authorize NV object.", error_cleanup);
+
+        r = Esys_NV_Extend_Async(context->esys,
+                                 command->auth_index,
+                                 nvIndex,
+                                 auth_session,
+                                 ESYS_TR_NONE,
+                                 ESYS_TR_NONE,
+                                 auxData);
+        goto_if_error_reset_state(r, " Fapi_NvExtend_Async", error_cleanup);
+
+        command->bytesRequested = auxData->size;
+        command->data = (uint8_t *)data;
+
+        context->state = NV_EXTEND_AUTH_SENT;
+        return TSS2_FAPI_RC_TRY_AGAIN;
+
+    statecase(context->state, NV_EXTEND_AUTH_SENT)
+
+        r = Esys_NV_Extend_Finish(context->esys);
+        return_try_again(r);
+
+        goto_if_error_reset_state(r, "FAPI NV_Extend_Finish", error_cleanup);
+
+        command->numBytes -= context->nv_cmd.bytesRequested;
+
+        if (command->numBytes > 0) {
+            if (command->numBytes > context->nv_buffer_max)
+                auxData->size = context->nv_buffer_max;
+            else
+                auxData->size = command->numBytes;
+            memcpy(&auxData->buffer[0], &data[dataIdx], auxData->size);
+            r = Esys_NV_Extend_Async(context->esys,
+                                     command->auth_index,
+                                     nvIndex,
+                                     context->session1,
+                                     ESYS_TR_NONE,
+                                     ESYS_TR_NONE,
+                                     auxData);
+            goto_if_error_reset_state(r, "FAPI NV_Extend", error_cleanup);
+
+            command->bytesRequested = auxData->size;
+            return TSS2_FAPI_RC_TRY_AGAIN;
+        }
+
+        /* Compute Digest of the current event */
+        hashAlg = object->misc.nv.public.nvPublic.nameAlg;
+        r = ifapi_crypto_hash_start(&cryptoContext, hashAlg);
+        return_if_error(r, "crypto hash start");
+
+        HASH_UPDATE_BUFFER(cryptoContext,
+                           &auxData->buffer[0], auxData->size,
+                           r, error_cleanup);
+
+        r = ifapi_crypto_hash_finish(&cryptoContext,
+                                     (uint8_t *)
+                                     &event->digests.digests[0].digest,
+                                     &hashSize);
+        return_if_error(r, "crypto hash finish");
+
+        event->digests.digests[0].hashAlg = hashAlg;
+        event->digests.count = 1;
+        event->pcr = object->misc.nv.public.nvPublic.nvIndex;
+        event->type = IFAPI_TSS_EVENT_TAG;
+        memcpy(&event->sub_event.tss_event.data.buffer[0],
+               &auxData->buffer[0], auxData->size);
+        event->sub_event.tss_event.data.size = auxData->size;
+        if (command->logData) {
+            strdup_check(event->sub_event.tss_event.event, command->logData,
+                    r, error_cleanup);
+        } else {
+            event->sub_event.tss_event.event = NULL;
+        }
+
+        /* Event log of the NV object has to be extended */
+        if (command->nv_object.misc.nv.event_log) {
+            command->jso_event_log
+                = json_tokener_parse(command->nv_object.misc.nv.event_log);
+            goto_if_null2(command->jso_event_log, "Out of memory", r,
+                          TSS2_FAPI_RC_MEMORY,
+                          error_cleanup);
+            json_type jsoType = json_object_get_type(command->jso_event_log);
+            /* libjson-c does not deliver an array if array has only one element */
+            if (jsoType != json_type_array) {
+                json_object *jsonArray = json_object_new_array();
+                json_object_array_add(jsonArray, command->jso_event_log);
+                command->jso_event_log = jsonArray;
+            }
+        } else {
+            /* First event */
+            command->jso_event_log = json_object_new_array();
+        }
+        command->pcr_event.recnum =
+            json_object_array_length(command->jso_event_log) + 1;
+
+        r = ifapi_json_IFAPI_EVENT_serialize(&command->pcr_event, &jso);
+        goto_if_error(r, "Error serialize event", error_cleanup);
+
+        json_object_array_add(command->jso_event_log, jso);
+        SAFE_FREE(object->misc.nv.event_log);
+        strdup_check(object->misc.nv.event_log,
+            json_object_to_json_string_ext(command->jso_event_log,
+                                                    JSON_C_TO_STRING_PRETTY),
+            r, error_cleanup);
+
+        /* Perform esys serialization if necessary */
+        r = ifapi_esys_serialize_object(context->esys, &command->nv_object);
+        goto_if_error(r, "Prepare serialization", error_cleanup);
+
+        /* Start writing the NV object to the key store */
+        r = ifapi_keystore_store_async(&context->keystore, &context->io,
+                                       command->nvPath,
+                                       &command->nv_object);
+
+        goto_if_error_reset_state(r, "Could not open: %sh", error_cleanup,
+                                  command->nvPath);
+
+        fallthrough;
+
+    statecase(context->state, NV_EXTEND_WRITE)
+        /* Finish writing the NV object to the key store */
+        r = ifapi_keystore_store_finish(&context->keystore, &context->io);
+        return_try_again(r);
+        return_if_error_reset_state(r, "write_finish failed");
+        fallthrough;
+
+    statecase(context->state, NV_EXTEND_CLEANUP)
+        r = ifapi_cleanup_session(context);
+        try_again_or_error_goto(r, "Cleanup", error_cleanup);
+
+        context->state = _FAPI_STATE_INIT;
+        r = TSS2_RC_SUCCESS;
+
+        break;
+
+    statecasedefault(context->state);
+    }
+
+error_cleanup:
+    if (command->jso_event_log)
+        json_object_put(command->jso_event_log);
+    ifapi_cleanup_ifapi_object(object);
+    ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
+    ifapi_cleanup_ifapi_object(context->loadKey.key_object);
+    ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
+    if (cryptoContext) {
+        ifapi_crypto_hash_abort(&cryptoContext);
+    }
+    if (event)
+        ifapi_cleanup_event(event);
+    SAFE_FREE(command->data);
+    SAFE_FREE(command->nvPath);
+    SAFE_FREE(command->logData);
+    SAFE_FREE(object->misc.nv.event_log);
+    ifapi_session_clean(context);
+    LOG_TRACE("finsihed");
+    return r;
+}
diff --git a/src/tss2-fapi/api/Fapi_NvIncrement.c b/src/tss2-fapi/api/Fapi_NvIncrement.c
new file mode 100644
index 0000000..f1b5e2e
--- /dev/null
+++ b/src/tss2-fapi/api/Fapi_NvIncrement.c
@@ -0,0 +1,311 @@
+/* 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 <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "tss2_fapi.h"
+#include "fapi_int.h"
+#include "fapi_util.h"
+#include "tss2_esys.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+/** One-Call function for Fapi_NvIncrement
+ *
+ * Increments an NV index that is a counter by 1.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] nvPath The path to the NV index that is incremented.
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or nvPath is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_PATH: if nvPath is not found.
+ * @retval TSS2_FAPI_RC_NV_WRONG_TYPE: if the NV index type is not
+ *         TPM2_NT_COUNTER.
+ * @retval TSS2_FAPI_RC_NV_NOT_WRITEABLE: if the NV index is not writeable.
+ * @retval TSS2_FAPI_RC_POLICY_UNKNOWN: if the policy is unknown.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_NvIncrement(
+    FAPI_CONTEXT *context,
+    char   const *nvPath)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r, r2;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(nvPath);
+
+    /* Check whether TCTI and ESYS are initialized */
+    return_if_null(context->esys, "Command can't be executed in none TPM mode.",
+                   TSS2_FAPI_RC_NO_TPM);
+
+    /* If the async state automata of FAPI shall be tested, then we must not set
+       the timeouts of ESYS to blocking mode.
+       During testing, the mssim tcti will ensure multiple re-invocations.
+       Usually however the synchronous invocations of FAPI shall instruct ESYS
+       to block until a result is available. */
+#ifndef TEST_FAPI_ASYNC
+    r = Esys_SetTimeout(context->esys, TSS2_TCTI_TIMEOUT_BLOCK);
+    return_if_error_reset_state(r, "Set Timeout to blocking");
+#endif /* TEST_FAPI_ASYNC */
+
+    r = Fapi_NvIncrement_Async(context, nvPath);
+    return_if_error_reset_state(r, "NV_Increment");
+
+    do {
+        /* We wait for file I/O to be ready if the FAPI state automata
+           are in a file I/O state. */
+        r = ifapi_io_poll(&context->io);
+        return_if_error(r, "Something went wrong with IO polling");
+
+        /* Repeatedly call the finish function, until FAPI has transitioned
+           through all execution stages / states of this invocation. */
+        r = Fapi_NvIncrement_Finish(context);
+    } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
+
+    /* Reset the ESYS timeout to non-blocking, immediate response. */
+    r2 = Esys_SetTimeout(context->esys, 0);
+    return_if_error(r2, "Set Timeout to non-blocking");
+
+    return_if_error_reset_state(r, "NV_Increment");
+
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous function for Fapi_NvIncrement
+ *
+ * Increments an NV index that is a counter by 1.
+ *
+ * Call Fapi_NvIncrement_Finish to finish the execution of this command.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] nvPath The path to the NV index that is incremented.
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or nvPath is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_PATH: if nvPath is not found.
+ * @retval TSS2_FAPI_RC_NV_WRONG_TYPE: if the NV index type is not
+ *         TPM2_NT_COUNTER.
+ * @retval TSS2_FAPI_RC_NV_NOT_WRITEABLE: if the NV index is not writeable.
+ * @retval TSS2_FAPI_RC_POLICY_UNKNOWN: if the policy is unknown.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_NvIncrement_Async(
+    FAPI_CONTEXT *context,
+    char   const *nvPath)
+{
+    LOG_TRACE("called for context:%p", context);
+    LOG_TRACE("nvPath: %s", nvPath);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(nvPath);
+
+    /* Helpful alias pointers */
+    IFAPI_NV_Cmds * command = &context->nv_cmd;
+
+    r = ifapi_session_init(context);
+    return_if_error(r, "Initialize NV_Increment");
+
+    memset(&context->nv_cmd, 0, sizeof(IFAPI_NV_Cmds));
+    strdup_check(command->nvPath, nvPath, r, error_cleanup);
+
+    command->rdata = NULL;
+    r = ifapi_keystore_load_async(&context->keystore, &context->io, command->nvPath);
+    goto_if_error2(r, "Could not open: %s", error_cleanup, command->nvPath);
+
+    context->state = NV_INCREMENT_READ;
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+error_cleanup:
+    SAFE_FREE(command->nvPath);
+    return r;
+}
+
+/** Asynchronous finish function for Fapi_NvIncrement
+ *
+ * This function should be called after a previous Fapi_NvIncrement_Async.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
+ *         complete. Call this function again later.
+ */
+TSS2_RC
+Fapi_NvIncrement_Finish(
+    FAPI_CONTEXT *context)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+    json_object *jso = NULL;
+    ESYS_TR authIndex;
+    ESYS_TR auth_session;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+
+    /* Helpful alias pointers */
+    IFAPI_NV_Cmds * command = &context->nv_cmd;
+    IFAPI_OBJECT *object = &command->nv_object;
+    ESYS_TR nvIndex =  command->esys_handle;
+    IFAPI_OBJECT *authObject = &command->auth_object;
+
+    switch (context->state) {
+    statecase(context->state, NV_INCREMENT_READ)
+        /* First check whether the file in object store can be updated. */
+        r = ifapi_keystore_check_writeable(&context->keystore, &context->io, command->nvPath);
+        goto_if_error_reset_state(r, "Check whether update object store is possible.", error_cleanup);
+
+        r = ifapi_keystore_load_finish(&context->keystore, &context->io, object);
+        return_try_again(r);
+        return_if_error_reset_state(r, "read_finish failed");
+
+        if (object->objectType != IFAPI_NV_OBJ)
+            goto_error(r, TSS2_FAPI_RC_BAD_PATH, "%s is no NV object.", error_cleanup,
+                       command->nvPath);
+
+        r = ifapi_initialize_object(context->esys, object);
+        goto_if_error_reset_state(r, "Initialize NV object", error_cleanup);
+
+        nvIndex =  command->nv_object.handle;
+        command->esys_handle = context->nv_cmd.nv_object.handle;
+        command->nv_obj = object->misc.nv;
+
+        /* Determine auth object */
+        if (object->misc.nv.public.nvPublic.attributes & TPMA_NV_PPREAD) {
+            ifapi_init_hierarchy_object(authObject, ESYS_TR_RH_PLATFORM);
+            authIndex = ESYS_TR_RH_PLATFORM;
+        } else {
+            if (object->misc.nv.public.nvPublic.attributes & TPMA_NV_OWNERREAD) {
+                ifapi_init_hierarchy_object(authObject, ESYS_TR_RH_OWNER);
+                authIndex = ESYS_TR_RH_OWNER;
+            } else {
+                authIndex = nvIndex;
+            }
+            *authObject = *object;
+        }
+        command->auth_index = authIndex;
+        context->primary_state = PRIMARY_INIT;
+
+        /* Prepare Session */
+        r = ifapi_get_sessions_async(context,
+            IFAPI_SESSION_GENEK | IFAPI_SESSION1,
+            0, 0);
+        goto_if_error_reset_state(r, "Create sessions", error_cleanup);
+
+        context->state = NV_INCREMENT_WAIT_FOR_SESSION;
+        fallthrough;
+
+    statecase(context->state, NV_INCREMENT_WAIT_FOR_SESSION)
+//TODO: Pass the namealg of the NV index into the session to be created
+        r = ifapi_get_sessions_finish(context, &context->profiles.default_profile);
+        return_try_again(r);
+
+        goto_if_error_reset_state(r, " FAPI create session", error_cleanup);
+
+        context->state = NV_INCREMENT_AUTHORIZE;
+        fallthrough;
+
+    statecase(context->state, NV_INCREMENT_AUTHORIZE)
+        r = ifapi_authorize_object(context, authObject, &auth_session);
+        return_try_again(r);
+        goto_if_error(r, "Authorize NV object.", error_cleanup);
+
+        /* Prepare increment */
+        r = Esys_NV_Increment_Async(context->esys,  command->auth_index,
+                                    nvIndex,
+                                    auth_session,
+                                    ESYS_TR_NONE, ESYS_TR_NONE);
+
+        goto_if_error_reset_state(r, " Fapi_NvIncrement_Async", error_cleanup);
+
+        context->state = NV_INCREMENT_AUTH_SENT;
+        fallthrough;
+
+    statecase(context->state, NV_INCREMENT_AUTH_SENT)
+        r = Esys_NV_Increment_Finish(context->esys);
+        return_try_again(r);
+
+        goto_if_error_reset_state(r, "FAPI NV_Increment_Finish", error_cleanup);
+
+        /* Perform esys serialization if necessary */
+        r = ifapi_esys_serialize_object(context->esys, &command->nv_object);
+        goto_if_error(r, "Prepare serialization", error_cleanup);
+
+        /* Start writing the NV object to the key store */
+        r = ifapi_keystore_store_async(&context->keystore, &context->io,
+                                       command->nvPath,
+                                       &command->nv_object);
+        goto_if_error_reset_state(r, "Could not open: %sh", error_cleanup,
+                                  command->nvPath);
+
+        context->state = NV_INCREMENT_WRITE;
+        fallthrough;
+
+    statecase(context->state, NV_INCREMENT_WRITE)
+        /* Finish writing the NV object to the key store */
+        r = ifapi_keystore_store_finish(&context->keystore, &context->io);
+        return_try_again(r);
+        return_if_error_reset_state(r, "write_finish failed");
+        fallthrough;
+
+    statecase(context->state, NV_INCREMENT_CLEANUP)
+        r = ifapi_cleanup_session(context);
+        try_again_or_error_goto(r, "Cleanup", error_cleanup);
+
+        context->state =  _FAPI_STATE_INIT;
+        r =  TSS2_RC_SUCCESS;
+        break;
+
+    statecasedefault(context->state);
+    }
+
+error_cleanup:
+    ifapi_cleanup_ifapi_object(&command->nv_object);
+    ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
+    ifapi_cleanup_ifapi_object(context->loadKey.key_object);
+    ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
+    SAFE_FREE(command->nvPath);
+    SAFE_FREE(jso);
+    ifapi_session_clean(context);
+    LOG_TRACE("finsihed");
+    return r;
+}
diff --git a/src/tss2-fapi/api/Fapi_NvRead.c b/src/tss2-fapi/api/Fapi_NvRead.c
new file mode 100644
index 0000000..673e496
--- /dev/null
+++ b/src/tss2-fapi/api/Fapi_NvRead.c
@@ -0,0 +1,295 @@
+/* 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 <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "tss2_fapi.h"
+#include "fapi_int.h"
+#include "fapi_util.h"
+#include "tss2_esys.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+/** One-Call function for Fapi_NvRead
+ *
+ * Reads data from an NV index within the TPM.
+ * The FAPI will automatically do the multiple reads if the NV index is larger
+ * than the TPM's TPM2_MAX_NV_BUFFER_SIZE.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] nvPath The path of the NV index to read
+ * @param [out] data The data that was read from the NV index
+ * @param [out] size The size of data in bytes. May be NULL
+ * @param [out] logData The log data of the NV index if the index is of type
+ * 							"extend". May be NULL
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context, nvPath or data is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_PATH: if nvPath is not found.
+ * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED: if authorization fails.
+ * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN: if don’t know how to authenticate.
+ * @retval TSS2_FAPI_RC_NV_NOT_READABLE: if the NV is not a readable index.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_NvRead(
+    FAPI_CONTEXT   *context,
+    char     const *nvPath,
+    uint8_t       **data,
+    size_t         *size,
+    char          **logData)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r, r2;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(nvPath);
+    check_not_null(data);
+
+    /* Check whether TCTI and ESYS are initialized */
+    return_if_null(context->esys, "Command can't be executed in none TPM mode.",
+                   TSS2_FAPI_RC_NO_TPM);
+
+    /* If the async state automata of FAPI shall be tested, then we must not set
+       the timeouts of ESYS to blocking mode.
+       During testing, the mssim tcti will ensure multiple re-invocations.
+       Usually however the synchronous invocations of FAPI shall instruct ESYS
+       to block until a result is available. */
+#ifndef TEST_FAPI_ASYNC
+    r = Esys_SetTimeout(context->esys, TSS2_TCTI_TIMEOUT_BLOCK);
+    return_if_error_reset_state(r, "Set Timeout to blocking");
+#endif /* TEST_FAPI_ASYNC */
+
+    r = Fapi_NvRead_Async(context, nvPath);
+    return_if_error_reset_state(r, "NV_Read");
+
+    do {
+        /* We wait for file I/O to be ready if the FAPI state automata
+           are in a file I/O state. */
+        r = ifapi_io_poll(&context->io);
+        return_if_error(r, "Something went wrong with IO polling");
+
+        /* Repeatedly call the finish function, until FAPI has transitioned
+           through all execution stages / states of this invocation. */
+        r = Fapi_NvRead_Finish(context, data, size, logData);
+    } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
+
+    /* Reset the ESYS timeout to non-blocking, immediate response. */
+    r2 = Esys_SetTimeout(context->esys, 0);
+    return_if_error(r2, "Set Timeout to non-blocking");
+
+    return_if_error_reset_state(r, "NV_Read");
+
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous function for Fapi_NvRead
+ *
+ * Reads data from an NV index within the TPM.
+ * The FAPI will automatically do the multiple reads if the NV index is larger
+ * than the TPM's TPM2_MAX_NV_BUFFER_SIZE.
+ *
+ * Call Fapi_NvRead_Finish to finish the execution of this command.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] nvPath The path of the NV index to read
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or nvPath is NULL. *
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_PATH: if nvPath is not found.
+ * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED: if authorization fails.
+ * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN: if don’t know how to authenticate.
+ * @retval TSS2_FAPI_RC_NV_NOT_READABLE: if the NV is not a readable index.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_NvRead_Async(
+    FAPI_CONTEXT   *context,
+    char     const *nvPath)
+{
+    LOG_TRACE("called for context:%p", context);
+    LOG_TRACE("nvPath: %s", nvPath);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(nvPath);
+
+    /* Helpful alias pointers */
+    IFAPI_NV_Cmds * command = &context->nv_cmd;
+
+    r = ifapi_session_init(context);
+    return_if_error(r, "Initialize NvRead");
+
+    memset(command, 0, sizeof(IFAPI_NV_Cmds));
+    strdup_check(command->nvPath, nvPath, r, error_cleanup);
+
+    r = ifapi_keystore_load_async(&context->keystore, &context->io, command->nvPath);
+    goto_if_error_reset_state(r, "Could not open: %s", error_cleanup, command->nvPath);
+
+    context->state = NV_READ_READ;
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+error_cleanup:
+    SAFE_FREE(command->nvPath);
+    return r;
+}
+
+/** Asynchronous finish function for Fapi_NvRead
+ *
+ * This function should be called after a previous Fapi_NvRead_Async.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [out] data The data that was read from the NV index
+ * @param [out] size The size of data in bytes. May be NULL
+ * @param [out] logData The log data of the NV index if the index is of type
+ * 							"extend". May be NULL
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or data is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
+ *         complete. Call this function again later.
+ */
+TSS2_RC
+Fapi_NvRead_Finish(
+    FAPI_CONTEXT   *context,
+    uint8_t       **data,
+    size_t         *size,
+    char          **logData)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+    ESYS_TR authIndex;
+    size_t readSize;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(data);
+
+    /* Helpful alias pointers */
+    IFAPI_NV_Cmds * command = &context->nv_cmd;
+    IFAPI_OBJECT *object = &command->nv_object;
+    IFAPI_OBJECT *authObject = &command->auth_object;
+
+    switch (context->state) {
+    statecase(context->state, NV_READ_READ)
+        r = ifapi_keystore_load_finish(&context->keystore, &context->io, object);
+        return_try_again(r);
+        return_if_error_reset_state(r, "read_finish failed");
+
+        if (object->objectType != IFAPI_NV_OBJ)
+            goto_error(r, TSS2_FAPI_RC_BAD_PATH, "%s is no NV object.", error_cleanup,
+                       command->nvPath);
+
+        r = ifapi_initialize_object(context->esys, object);
+        goto_if_error_reset_state(r, "Initialize NV object", error_cleanup);
+
+        command->esys_handle = object->handle;
+        command->nv_obj = object->misc.nv;
+
+        if (size)
+            *size = object->misc.nv.public.nvPublic.dataSize;
+        command->numBytes = object->misc.nv.public.nvPublic.dataSize;
+
+        /* Determine auth object */
+        if (object->misc.nv.public.nvPublic.attributes & TPMA_NV_PPREAD) {
+            ifapi_init_hierarchy_object(authObject, ESYS_TR_RH_PLATFORM);
+            authIndex = ESYS_TR_RH_PLATFORM;
+        } else {
+            if (object->misc.nv.public.nvPublic.attributes & TPMA_NV_OWNERREAD) {
+                ifapi_init_hierarchy_object(authObject, ESYS_TR_RH_OWNER);
+                authIndex = ESYS_TR_RH_OWNER;
+            } else {
+                authIndex = object->handle;
+            }
+            *authObject = *object;
+        }
+        command->auth_index = authIndex;
+        context->primary_state = PRIMARY_INIT;
+
+        /* Prepare Session */
+        r = ifapi_get_sessions_async(context,
+                                     IFAPI_SESSION_GENEK | IFAPI_SESSION1,
+                                     TPMA_SESSION_ENCRYPT, 0);
+        goto_if_error_reset_state(r, "Create sessions", error_cleanup);
+
+        context->state = NV_READ_WAIT_FOR_SESSION;
+        return TSS2_FAPI_RC_TRY_AGAIN;
+
+    statecase(context->state, NV_READ_WAIT_FOR_SESSION)
+//TODO: Pass the namealg of the NV index into the session to be created
+        r = ifapi_get_sessions_finish(context, &context->profiles.default_profile);
+        return_try_again(r);
+        goto_if_error_reset_state(r, " FAPI create session", error_cleanup);
+
+        command->nv_read_state = NV_READ_INIT;
+
+        context->state = NV_READ_WAIT;
+        fallthrough;
+
+    statecase(context->state, NV_READ_WAIT)
+        if (data) {
+            r = ifapi_nv_read(context, data, &readSize);
+            return_try_again(r);
+
+            goto_if_error_reset_state(r, " FAPI NV_Read", error_cleanup);
+        }
+
+        if (logData) {
+            strdup_check(*logData, object->misc.nv.event_log, r, error_cleanup);
+        }
+        fallthrough;
+
+    statecase(context->state, NV_READ_CLEANUP)
+        r = ifapi_cleanup_session(context);
+        try_again_or_error_goto(r, "Cleanup", error_cleanup);
+
+        context->state =  _FAPI_STATE_INIT;
+        break;
+
+    statecasedefault(context->state);
+    }
+
+error_cleanup:
+    ifapi_cleanup_ifapi_object(&command->nv_object);
+    ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
+    ifapi_cleanup_ifapi_object(context->loadKey.key_object);
+    ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
+    SAFE_FREE(command->nvPath);
+    //SAFE_FREE(context->nv_cmd.tes);
+    ifapi_session_clean(context);
+    LOG_TRACE("finsihed");
+    return r;
+}
diff --git a/src/tss2-fapi/api/Fapi_NvSetBits.c b/src/tss2-fapi/api/Fapi_NvSetBits.c
new file mode 100644
index 0000000..2ebb790
--- /dev/null
+++ b/src/tss2-fapi/api/Fapi_NvSetBits.c
@@ -0,0 +1,322 @@
+/* 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 <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "tss2_fapi.h"
+#include "fapi_int.h"
+#include "fapi_util.h"
+#include "tss2_esys.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+/** One-Call function for Fapi_NvSetBits
+ *
+ * Sets bits in an NV index that was created as a bit field. Any number of bits
+ * from 0 to 64 may be SET.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] nvPath The path to the NV index where bits are set
+ * @param [in] bitmap The map of the bits to set
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or nvPath is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_PATH: if nvPath is not found.
+ * @retval TSS2_FAPI_RC_NV_WRONG_TYPE: if the NV index type is not
+ *         TPM2_NT_COUNTER.
+ * @retval TSS2_FAPI_RC_NV_NOT_WRITEABLE: if the NV is not a writeable index.
+ * @retval TSS2_FAPI_RC_POLICY_UNKNOWN: if the policy is unknown.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_NvSetBits(
+    FAPI_CONTEXT *context,
+    char   const *nvPath,
+    uint64_t      bitmap)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r, r2;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(nvPath);
+
+    /* Check whether TCTI and ESYS are initialized */
+    return_if_null(context->esys, "Command can't be executed in none TPM mode.",
+                   TSS2_FAPI_RC_NO_TPM);
+
+    /* If the async state automata of FAPI shall be tested, then we must not set
+       the timeouts of ESYS to blocking mode.
+       During testing, the mssim tcti will ensure multiple re-invocations.
+       Usually however the synchronous invocations of FAPI shall instruct ESYS
+       to block until a result is available. */
+#ifndef TEST_FAPI_ASYNC
+    r = Esys_SetTimeout(context->esys, TSS2_TCTI_TIMEOUT_BLOCK);
+    return_if_error_reset_state(r, "Set Timeout to blocking");
+#endif /* TEST_FAPI_ASYNC */
+
+    r = Fapi_NvSetBits_Async(context, nvPath, bitmap);
+    return_if_error_reset_state(r, "NV_SetBits");
+
+    do {
+        /* We wait for file I/O to be ready if the FAPI state automata
+           are in a file I/O state. */
+        r = ifapi_io_poll(&context->io);
+        return_if_error(r, "Something went wrong with IO polling");
+
+        /* Repeatedly call the finish function, until FAPI has transitioned
+           through all execution stages / states of this invocation. */
+        r = Fapi_NvSetBits_Finish(context);
+    } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
+
+    /* Reset the ESYS timeout to non-blocking, immediate response. */
+    r2 = Esys_SetTimeout(context->esys, 0);
+    return_if_error(r2, "Set Timeout to non-blocking");
+
+    return_if_error_reset_state(r, "NV_SetBits");
+
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous function for Fapi_NvSetBits
+ *
+ * Sets bits in an NV index that was created as a bit field. Any number of bits
+ * from 0 to 64 may be SET.
+ *
+ * Call Fapi_NvSetBits_Finish to finish the execution of this command.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] nvPath The path to the NV index where bits are set
+ * @param [in] bitmap The map of the bits to set
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or nvPath is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_PATH: if nvPath is not found.
+ * @retval TSS2_FAPI_RC_NV_WRONG_TYPE: if the NV index type is not
+ *         TPM2_NT_COUNTER.
+ * @retval TSS2_FAPI_RC_NV_NOT_WRITEABLE: if the NV is not a writeable index.
+ * @retval TSS2_FAPI_RC_POLICY_UNKNOWN: if the policy is unknown.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_NvSetBits_Async(
+    FAPI_CONTEXT *context,
+    char   const *nvPath,
+    uint64_t      bitmap)
+{
+    LOG_TRACE("called for context:%p", context);
+    LOG_TRACE("nvPath: %s", nvPath);
+    LOG_TRACE("bitmap: 0x%" PRIx64, bitmap);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(nvPath);
+
+    /* Helpful alias pointers */
+    IFAPI_NV_Cmds * command = &context->nv_cmd;
+
+    r = ifapi_session_init(context);
+    return_if_error(r, "Initialize NV_SetBits");
+
+    /* Store the parameter in the FAPI context */
+    memset(&context->nv_cmd, 0, sizeof(IFAPI_NV_Cmds));
+    memset(&command->nv_object, 0, sizeof(IFAPI_OBJECT));
+    strdup_check(command->nvPath, nvPath, r, error_cleanup);
+    command->bitmap = bitmap;
+    command->rdata = NULL;
+
+    r = ifapi_keystore_load_async(&context->keystore, &context->io, command->nvPath);
+    goto_if_error2(r, "Could not open: %s", error_cleanup, command->nvPath);
+
+    context->state = NV_SET_BITS_READ;
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+error_cleanup:
+    SAFE_FREE(command->nvPath);
+    return r;
+}
+
+/** Asynchronous finish function for Fapi_NnSetBits
+ *
+ * This function should be called after a previous Fapi_NvSetBIts_Async.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
+ *         complete. Call this function again later.
+ */
+TSS2_RC
+Fapi_NvSetBits_Finish(
+    FAPI_CONTEXT *context)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+    json_object *jso = NULL;
+    ESYS_TR authIndex;
+    ESYS_TR auth_session;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+
+    /* Helpful alias pointers */
+    IFAPI_NV_Cmds * command = &context->nv_cmd;
+    IFAPI_OBJECT *object = &command->nv_object;
+    ESYS_TR nvIndex =  command->esys_handle;
+    IFAPI_OBJECT *authObject = &command->auth_object;
+
+    switch (context->state) {
+    statecase(context->state, NV_SET_BITS_READ)
+        /* First check whether the file in object store can be updated. */
+        r = ifapi_keystore_check_writeable(&context->keystore, &context->io, command->nvPath);
+        goto_if_error_reset_state(r, "Check whether update object store is possible.", error_cleanup);
+
+        r = ifapi_keystore_load_finish(&context->keystore, &context->io, object);
+        return_try_again(r);
+        return_if_error_reset_state(r, "read_finish failed");
+
+        if (object->objectType != IFAPI_NV_OBJ)
+            goto_error(r, TSS2_FAPI_RC_BAD_PATH, "%s is no NV object.", error_cleanup,
+                       command->nvPath);
+
+        r = ifapi_initialize_object(context->esys, object);
+        goto_if_error_reset_state(r, "Initialize NV object", error_cleanup);
+
+        nvIndex =  command->nv_object.handle;
+        command->esys_handle = object->handle;
+        command->nv_obj = object->misc.nv;
+
+        /* Determine auth object */
+        if (object->misc.nv.public.nvPublic.attributes & TPMA_NV_PPREAD) {
+            ifapi_init_hierarchy_object(authObject, ESYS_TR_RH_PLATFORM);
+            authIndex = ESYS_TR_RH_PLATFORM;
+        } else {
+            if (object->misc.nv.public.nvPublic.attributes & TPMA_NV_OWNERREAD) {
+                ifapi_init_hierarchy_object(authObject, ESYS_TR_RH_OWNER);
+                authIndex = ESYS_TR_RH_OWNER;
+            } else {
+                authIndex = nvIndex;
+            }
+            *authObject = *object;
+        }
+        command->auth_index = authIndex;
+        context->primary_state = PRIMARY_INIT;
+
+        /* Prepare Session */
+        r = ifapi_get_sessions_async(context,
+                                     IFAPI_SESSION_GENEK | IFAPI_SESSION1,
+                                     0, 0);
+        goto_if_error_reset_state(r, "Create sessions", error_cleanup);
+
+        context->state = NV_SET_BITS_WAIT_FOR_SESSION;
+        fallthrough;
+
+    statecase(context->state, NV_SET_BITS_WAIT_FOR_SESSION)
+//TODO: Pass the namealg of the NV index into the session to be created
+        r = ifapi_get_sessions_finish(context, &context->profiles.default_profile);
+        return_try_again(r);
+
+        goto_if_error_reset_state(r, " FAPI create session", error_cleanup);
+
+        context->state = NV_SET_BITS_AUTHORIZE;
+        fallthrough;
+
+    statecase(context->state, NV_SET_BITS_AUTHORIZE)
+        r = ifapi_authorize_object(context, authObject, &auth_session);
+        return_try_again(r);
+        goto_if_error(r, "Authorize NV object.", error_cleanup);
+
+        r = Esys_NV_SetBits_Async(context->esys,  command->auth_index, nvIndex,
+                                  auth_session,
+                                  ESYS_TR_NONE, ESYS_TR_NONE,
+                                  command->bitmap);
+
+        goto_if_error_reset_state(r, " Fapi_NvSetBits_Async", error_cleanup);
+
+        context->state = NV_SET_BITS_AUTH_SENT;
+        fallthrough;
+
+    statecase(context->state, NV_SET_BITS_AUTH_SENT)
+        r = Esys_NV_SetBits_Finish(context->esys);
+
+        return_try_again(r);
+
+        goto_if_error_reset_state(r, "FAPI NV_SetBits_Finish", error_cleanup);
+
+        context->state = NV_SET_BITS_WRITE;
+
+        r = ifapi_esys_serialize_object(context->esys, object);
+        goto_if_error(r, "Prepare serialization", error_cleanup);
+
+        /* Start writing the NV object to the key store */
+        r = ifapi_keystore_store_async(&context->keystore, &context->io,
+                                       command->nvPath,
+                                       object);
+        goto_if_error_reset_state(r, "Could not open: %sh", error_cleanup,
+                                  command->nvPath);
+        fallthrough;
+
+    statecase(context->state, NV_SET_BITS_WRITE)
+        /* Finish writing the NV object to the key store */
+        r = ifapi_keystore_store_finish(&context->keystore, &context->io);
+        return_try_again(r);
+        return_if_error_reset_state(r, "write_finish failed");
+        fallthrough;
+
+    statecase(context->state, NV_SET_BITS_CLEANUP)
+        r = ifapi_cleanup_session(context);
+        try_again_or_error_goto(r, "Cleanup", error_cleanup);
+
+        context->state =  _FAPI_STATE_INIT;
+        LOG_DEBUG("success");
+        r =  TSS2_RC_SUCCESS;
+
+        break;
+
+    statecasedefault(context->state);
+    }
+
+error_cleanup:
+    SAFE_FREE(command->nvPath);
+    SAFE_FREE(jso);
+    ifapi_session_clean(context);
+    ifapi_cleanup_ifapi_object(object);
+    ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
+    ifapi_cleanup_ifapi_object(context->loadKey.key_object);
+    ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
+    LOG_TRACE("finsihed");
+    return r;
+}
diff --git a/src/tss2-fapi/api/Fapi_NvWrite.c b/src/tss2-fapi/api/Fapi_NvWrite.c
new file mode 100644
index 0000000..67edd93
--- /dev/null
+++ b/src/tss2-fapi/api/Fapi_NvWrite.c
@@ -0,0 +1,289 @@
+/* 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 <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "tss2_fapi.h"
+#include "fapi_int.h"
+#include "fapi_util.h"
+#include "tss2_esys.h"
+#include "fapi_policy.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+/** One-Call function for Fapi_NvWrite
+ *
+ * Writes data to a "regular" (not pin, extend or counter) NV index.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] nvPath The path of the NV index to write
+ * @param [in] data The data to write to the NV index
+ * @param [in] size The size of data in bytes
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context, nvPath, or data is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_PATH: if nvPath is not found.
+ * @retval TSS2_FAPI_RC_NV_EXCEEDED: if the NV is not large enough for the data
+ *         to be written.
+ * @retval TSS2_FAPI_RC_NV_WRONG_TYPE: if the NV index is not a "regular" one.
+ * @retval TSS2_FAPI_RC_NV_NOT_WRITEABLE: if the NV is not a writeable index.
+ * @retval TSS2_FAPI_RC_POLICY_UNKNOWN: if the policy is unknown.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_NvWrite(
+    FAPI_CONTEXT  *context,
+    char    const *nvPath,
+    uint8_t const *data,
+    size_t         size)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r, r2;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(nvPath);
+    check_not_null(data);
+
+    /* Check whether TCTI and ESYS are initialized */
+    return_if_null(context->esys, "Command can't be executed in none TPM mode.",
+                   TSS2_FAPI_RC_NO_TPM);
+
+    /* If the async state automata of FAPI shall be tested, then we must not set
+       the timeouts of ESYS to blocking mode.
+       During testing, the mssim tcti will ensure multiple re-invocations.
+       Usually however the synchronous invocations of FAPI shall instruct ESYS
+       to block until a result is available. */
+#ifndef TEST_FAPI_ASYNC
+    r = Esys_SetTimeout(context->esys, TSS2_TCTI_TIMEOUT_BLOCK);
+    return_if_error_reset_state(r, "Set Timeout to blocking");
+#endif /* TEST_FAPI_ASYNC */
+
+    r = Fapi_NvWrite_Async(context, nvPath, data, size);
+    return_if_error_reset_state(r, "NV_Write");
+
+    do {
+        /* We wait for file I/O to be ready if the FAPI state automata
+           are in a file I/O state. */
+        r = ifapi_io_poll(&context->io);
+        return_if_error(r, "Something went wrong with IO polling");
+
+        /* Repeatedly call the finish function, until FAPI has transitioned
+           through all execution stages / states of this invocation. */
+        r = Fapi_NvWrite_Finish(context);
+    } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
+
+    /* Reset the ESYS timeout to non-blocking, immediate response. */
+    r2 = Esys_SetTimeout(context->esys, 0);
+    return_if_error(r2, "Set Timeout to non-blocking");
+
+    return_if_error_reset_state(r, "NV_Write");
+
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous function for Fapi_NvWrite
+ *
+ * Writes data to a "regular" (not pin, extend or counter) NV index.
+ *
+ * Call Fapi_NvWrite_Finish to finish the execution of this command.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] nvPath The path of the NV index to write
+ * @param [in] data The data to write to the NV index
+ * @param [in] size The size of data in bytes
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context, nvPath, or data is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_PATH: if nvPath is not found.
+ * @retval TSS2_FAPI_RC_NV_EXCEEDED: if the NV is not large enough for the data
+ *         to be written.
+ * @retval TSS2_FAPI_RC_NV_WRONG_TYPE: if the NV index is not a "regular" one.
+ * @retval TSS2_FAPI_RC_NV_NOT_WRITEABLE: if the NV is not a writeable index.
+ * @retval TSS2_FAPI_RC_POLICY_UNKNOWN: if the policy is unknown.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_NvWrite_Async(
+    FAPI_CONTEXT  *context,
+    char    const *nvPath,
+    uint8_t const *data,
+    size_t         size)
+{
+    LOG_TRACE("called for context:%p", context);
+    LOG_TRACE("nvPath: %s", nvPath);
+    if (data) {
+        LOGBLOB_TRACE(data, size, "data");
+    } else {
+        LOG_TRACE("data: (null) size: %zi", size);
+    }
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(nvPath);
+    check_not_null(data);
+
+    /* Helpful alias pointers */
+    IFAPI_NV_Cmds * command = &context->nv_cmd;
+
+    r = ifapi_session_init(context);
+    return_if_error(r, "Initialize NV_Write");
+
+    /* Initialize the command */
+    uint8_t * commandData = NULL;
+    memset(&context->nv_cmd, 0, sizeof(IFAPI_NV_Cmds));
+    command->offset = 0;
+    command->data = NULL;
+    strdup_check(command->nvPath, nvPath, r, error_cleanup);
+
+    commandData = malloc(size);
+    goto_if_null2(commandData, "Out of memory", r, TSS2_FAPI_RC_MEMORY,
+            error_cleanup);
+    memcpy(commandData, data, size);
+    command->data = commandData;
+
+    context->primary_state = PRIMARY_INIT;
+    r = ifapi_get_sessions_async(context,
+                                 IFAPI_SESSION_GENEK | IFAPI_SESSION1,
+                                 TPMA_SESSION_DECRYPT, 0);
+    goto_if_error_reset_state(r, "Create sessions", error_cleanup);
+
+    context->state = NV_WRITE_WAIT_FOR_SESSION;
+    command->numBytes = size;
+    if (context->state == _FAPI_STATE_INIT)
+        ifapi_session_init(context);
+    context->state = NV_WRITE_WAIT_FOR_SESSION;
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+
+error_cleanup:
+    SAFE_FREE(command->nvPath);
+    SAFE_FREE(command->data);
+    return r;
+}
+
+/** Asynchronous finish function for Fapi_NvWrite
+ *
+ * This function should be called after a previous Fapi_NvWrite.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
+ *         complete. Call this function again later.
+ */
+TSS2_RC
+Fapi_NvWrite_Finish(
+    FAPI_CONTEXT  *context)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+    json_object *jso = NULL;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+
+    /* Helpful alias pointers */
+    IFAPI_NV_Cmds * command = &context->nv_cmd;
+
+    switch (context->state) {
+    statecase(context->state, NV_WRITE_WAIT_FOR_SESSION);
+//TODO: Pass the namealg of the NV index into the session to be created
+        r = ifapi_get_sessions_finish(context, &context->profiles.default_profile);
+        return_try_again(r);
+        goto_if_error_reset_state(r, " FAPI create session", error_cleanup);
+
+        context->state = NV_WRITE_READ;
+        fallthrough;
+
+    statecase(context->state, NV_WRITE_READ);
+        /* First check whether the file in object store can be updated. */
+        r = ifapi_keystore_check_writeable(&context->keystore, &context->io, command->nvPath);
+        goto_if_error_reset_state(r, "Check whether update object store is possible.", error_cleanup);
+
+        r = ifapi_nv_write(context, command->nvPath, command->offset,
+                           command->data, command->numBytes);
+
+        return_try_again(r);
+
+        goto_if_error_reset_state(r, " FAPI NV Write", error_cleanup);
+
+
+        /* Perform esys serialization if necessary */
+        r = ifapi_esys_serialize_object(context->esys, &command->nv_object);
+        goto_if_error(r, "Prepare serialization", error_cleanup);
+
+        /* Start writing the NV object to the key store */
+        r = ifapi_keystore_store_async(&context->keystore, &context->io,
+                                       command->nvPath,
+                                       &command->nv_object);
+        goto_if_error_reset_state(r, "Could not open: %sh", error_cleanup,
+                                  command->nvPath);
+
+        context->state = NV_WRITE_WRITE;
+        fallthrough;
+
+    statecase(context->state, NV_WRITE_WRITE);
+        /* Finish writing the NV object to the key store */
+        r = ifapi_keystore_store_finish(&context->keystore, &context->io);
+        return_try_again(r);
+        return_if_error_reset_state(r, "write_finish failed");
+        fallthrough;
+
+    statecase(context->state, NV_WRITE_CLEANUP)
+        r = ifapi_cleanup_session(context);
+        try_again_or_error_goto(r, "Cleanup", error_cleanup);
+
+        context->state =  _FAPI_STATE_INIT;
+        break;
+
+    statecasedefault(context->state);
+    }
+
+error_cleanup:
+    ifapi_cleanup_ifapi_object(&command->nv_object);
+    ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
+    ifapi_cleanup_ifapi_object(context->loadKey.key_object);
+    ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
+    SAFE_FREE(context->nv_cmd.write_data);
+    SAFE_FREE(command->nvPath);
+    SAFE_FREE(command->data);
+    SAFE_FREE(jso);
+    ifapi_session_clean(context);
+
+    LOG_TRACE("finsihed");
+    return r;
+}
diff --git a/src/tss2-fapi/api/Fapi_PcrExtend.c b/src/tss2-fapi/api/Fapi_PcrExtend.c
new file mode 100644
index 0000000..8c664f2
--- /dev/null
+++ b/src/tss2-fapi/api/Fapi_PcrExtend.c
@@ -0,0 +1,286 @@
+/* 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 "tss2_fapi.h"
+#include "fapi_int.h"
+#include "fapi_util.h"
+#include "tss2_esys.h"
+#include "ifapi_json_serialize.h"
+#include "fapi_crypto.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+/** One-Call function for Fapi_PcrExtend
+ *
+ * Performs an extend operation on a given PCR.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] pcr The PCR to extend
+ * @param [in] data The data that is to be extended on the PCR
+ * @param [in] dataSize The size of data in bytes
+ * @param [in] logData A JSON representation of data to be written to the PCR's
+ *             event log. May be NULL
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or data is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_NO_PCR: if no such PCR exists on this TPM.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_PcrExtend(
+    FAPI_CONTEXT   *context,
+    uint32_t        pcr,
+    uint8_t  const *data,
+    size_t          dataSize,
+    char     const *logData)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r, r2;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(data);
+
+    /* Check whether TCTI and ESYS are initialized */
+    return_if_null(context->esys, "Command can't be executed in none TPM mode.",
+                   TSS2_FAPI_RC_NO_TPM);
+
+    /* If the async state automata of FAPI shall be tested, then we must not set
+       the timeouts of ESYS to blocking mode.
+       During testing, the mssim tcti will ensure multiple re-invocations.
+       Usually however the synchronous invocations of FAPI shall instruct ESYS
+       to block until a result is available. */
+#ifndef TEST_FAPI_ASYNC
+    r = Esys_SetTimeout(context->esys, TSS2_TCTI_TIMEOUT_BLOCK);
+    return_if_error_reset_state(r, "Set Timeout to blocking");
+#endif /* TEST_FAPI_ASYNC */
+
+    r = Fapi_PcrExtend_Async(context, pcr, data, dataSize, logData);
+    return_if_error_reset_state(r, "PcrExtend");
+
+    do {
+        /* We wait for file I/O to be ready if the FAPI state automata
+           are in a file I/O state. */
+        r = ifapi_io_poll(&context->io);
+        return_if_error(r, "Something went wrong with IO polling");
+
+        /* Repeatedly call the finish function, until FAPI has transitioned
+           through all execution stages / states of this invocation. */
+        r = Fapi_PcrExtend_Finish(context);
+    } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
+
+    /* Reset the ESYS timeout to non-blocking, immediate response. */
+    r2 = Esys_SetTimeout(context->esys, 0);
+    return_if_error(r2, "Set Timeout to non-blocking");
+
+    return_if_error_reset_state(r, "PcrExtend");
+
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous function for Fapi_PcrExtend
+ *
+ * Performs an extend operation on a given PCR.
+ *
+ * Call Fapi_PcrExtend_Finish to finish the execution of this command.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] pcr The PCR to extend
+ * @param [in] data The data that is to be extended on the PCR
+ * @param [in] dataSize The size of data in bytes
+ * @param [in] logData A JSON representation of data to be written to the PCR's
+ *             event log. May be NULL
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or data is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_NO_PCR: if no such PCR exists on this TPM.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_PcrExtend_Async(
+    FAPI_CONTEXT   *context,
+    uint32_t        pcr,
+    uint8_t  const *data,
+    size_t          dataSize,
+    char     const *logData)
+{
+    LOG_TRACE("called for context:%p", context);
+    LOG_TRACE("pcr: %u", pcr);
+    if (data) {
+        LOGBLOB_TRACE(data, dataSize, "data");
+    } else {
+        LOG_TRACE("data: (null) dataSize: %zi", dataSize);
+    }
+    LOG_TRACE("logData: %s", logData);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(data);
+
+    /* Helpful alias pointers */
+    IFAPI_PCR * command = &context->cmd.pcr;
+
+    r = ifapi_session_init(context);
+    goto_if_error(r, "Initialize PcrExtend", error_cleanup);
+
+    if (dataSize > 1024 || dataSize == 0) {
+        goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
+                "Event size must be > 1024 and != 0", error_cleanup);
+    }
+
+    strdup_check(command->logData, logData, r, error_cleanup);
+    command->event.size = dataSize;
+    memcpy(&command->event.buffer[0], data, dataSize);
+    command->pcrIndex = pcr;
+
+    r = Esys_GetCapability_Async(context->esys,
+                                 ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
+                                 TPM2_CAP_PCRS, 0, 1);
+    goto_if_error(r, "Esys_GetCapability_Async", error_cleanup);
+    context->state = PCR_EXTEND_WAIT_FOR_GET_CAP;
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+error_cleanup:
+    SAFE_FREE(command->logData);
+    return r;
+}
+
+/** Asynchronous finish function for Fapi_PcrExtend
+ *
+ * This function should be called after a previous Fapi_PcrExtend_Async.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
+ *         complete. Call this function again later.
+ */
+TSS2_RC
+Fapi_PcrExtend_Finish(
+    FAPI_CONTEXT   *context)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+    TPMI_YES_NO moreData;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+
+    /* Helpful alias pointers */
+    IFAPI_PCR * command = &context->cmd.pcr;
+    TPMS_CAPABILITY_DATA **capabilityData = &command->capabilityData;
+    IFAPI_EVENT * pcrEvent = &command->pcr_event;
+    IFAPI_TSS_EVENT * subEvent = &pcrEvent->sub_event.tss_event;
+
+    switch (context->state) {
+        statecase(context->state, PCR_EXTEND_WAIT_FOR_GET_CAP);
+            r = Esys_GetCapability_Finish(context->esys, &moreData, capabilityData);
+            return_try_again(r);
+            goto_if_error_reset_state(r, "GetCapablity_Finish", error_cleanup);
+
+            /* Prepare Session */
+            r = ifapi_get_sessions_async(context,
+                                         IFAPI_SESSION_GENEK | IFAPI_SESSION1,
+                                         0, 0);
+            goto_if_error_reset_state(r, "Create sessions", error_cleanup);
+
+            context->state = PCR_EXTEND_WAIT_FOR_SESSION;
+            fallthrough;
+
+        statecase(context->state, PCR_EXTEND_WAIT_FOR_SESSION);
+            r = ifapi_get_sessions_finish(context, &context->profiles.default_profile);
+            return_try_again(r);
+            goto_if_error_reset_state(r, " FAPI create session", error_cleanup);
+
+            r = Esys_PCR_Event_Async(context->esys, command->pcrIndex,
+                                     context->session1, ESYS_TR_NONE, ESYS_TR_NONE,
+                                     &command->event);
+            return_if_error(r, "Esys_PCR_Event_Async");
+            command->event_digests = NULL;
+
+            context->state = PCR_EXTEND_FINISH;
+            fallthrough;
+
+        statecase(context->state, PCR_EXTEND_FINISH);
+            r = Esys_PCR_Event_Finish(context->esys, &command->event_digests);
+            return_try_again(r);
+            goto_if_error_reset_state(r, "PCR_Extend_Finish", error_cleanup);
+
+            pcrEvent->digests = *command->event_digests;
+            pcrEvent->pcr = command->pcrIndex;
+            pcrEvent->type = IFAPI_TSS_EVENT_TAG;
+            subEvent->data = command->event;
+            if (command->logData) {
+                strdup_check(subEvent->event,
+                    command->logData, r, error_cleanup);
+            } else {
+                subEvent->event = NULL;
+            }
+
+            r = ifapi_eventlog_append_async(&context->eventlog, &context->io,
+                                            &command->pcr_event);
+            goto_if_error(r, "Error ifapi_eventlog_append_async", error_cleanup);
+
+            context->state = PCR_EXTEND_APPEND_EVENT_LOG;
+            fallthrough;
+
+        statecase(context->state, PCR_EXTEND_APPEND_EVENT_LOG);
+            r = ifapi_eventlog_append_finish(&context->eventlog, &context->io);
+            return_try_again(r);
+            goto_if_error(r, "ifapi_eventlog_append_async", error_cleanup);
+
+            SAFE_FREE(command->event_digests);
+            fallthrough;
+
+        statecase(context->state, PCR_EXTEND_CLEANUP)
+            r = ifapi_cleanup_session(context);
+            try_again_or_error_goto(r, "Cleanup", error_cleanup);
+
+            context->state =  _FAPI_STATE_INIT;
+            break;
+
+        statecasedefault(context->state);
+    }
+
+error_cleanup:
+    SAFE_FREE(*capabilityData);
+    SAFE_FREE(command->event_digests);
+    SAFE_FREE(command->logData);
+    ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
+    ifapi_cleanup_ifapi_object(context->loadKey.key_object);
+    ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
+    ifapi_cleanup_event(pcrEvent);
+    ifapi_session_clean(context);
+    LOG_TRACE("finsihed");
+    return r;
+}
diff --git a/src/tss2-fapi/api/Fapi_PcrRead.c b/src/tss2-fapi/api/Fapi_PcrRead.c
new file mode 100644
index 0000000..5a0afdf
--- /dev/null
+++ b/src/tss2-fapi/api/Fapi_PcrRead.c
@@ -0,0 +1,242 @@
+/* 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 "tss2_fapi.h"
+#include "fapi_int.h"
+#include "fapi_util.h"
+#include "tss2_esys.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+/** One-Call function for Fapi_PcrRead
+ *
+ * Reads from a given PCR and returns the value and the event log.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] pcrIndex The index of the PCR to read
+ * @param [out] pcrValue The value of the PCR. May be NULL
+ * @param [out] pcrValueSize The size of value in bytes. May be NULL
+ * @param [out] pcrLog The PCR log. May be NULL
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context, pcrValue or pcrValueSize
+ *              is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_VALUE: if pcrIndex is invalid.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_PcrRead(
+    FAPI_CONTEXT *context,
+    uint32_t      pcrIndex,
+    uint8_t     **pcrValue,
+    size_t       *pcrValueSize,
+    char        **pcrLog)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r, r2;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+
+    /* Check whether TCTI and ESYS are initialized */
+    return_if_null(context->esys, "Command can't be executed in none TPM mode.",
+                   TSS2_FAPI_RC_NO_TPM);
+
+    /* If the async state automata of FAPI shall be tested, then we must not set
+       the timeouts of ESYS to blocking mode.
+       During testing, the mssim tcti will ensure multiple re-invocations.
+       Usually however the synchronous invocations of FAPI shall instruct ESYS
+       to block until a result is available. */
+#ifndef TEST_FAPI_ASYNC
+    r = Esys_SetTimeout(context->esys, TSS2_TCTI_TIMEOUT_BLOCK);
+    return_if_error_reset_state(r, "Set Timeout to blocking");
+#endif /* TEST_FAPI_ASYNC */
+
+    r = Fapi_PcrRead_Async(context, pcrIndex);
+    return_if_error_reset_state(r, "PCR_ReadWithLog");
+
+    do {
+        /* We wait for file I/O to be ready if the FAPI state automata
+           are in a file I/O state. */
+        r = ifapi_io_poll(&context->io);
+        return_if_error(r, "Something went wrong with IO polling");
+
+        /* Repeatedly call the finish function, until FAPI has transitioned
+           through all execution stages / states of this invocation. */
+        r = Fapi_PcrRead_Finish(context, pcrValue, pcrValueSize, pcrLog);
+    } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
+
+    /* Reset the ESYS timeout to non-blocking, immediate response. */
+    r2 = Esys_SetTimeout(context->esys, 0);
+    return_if_error(r2, "Set Timeout to non-blocking");
+
+    return_if_error_reset_state(r, "NV_ReadWithLog");
+
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous function for Fapi_PcrRead
+ *
+ * Reads from a given PCR and returns the value and the event log.
+ *
+ * Call Fapi_PcrRead_Finish to finish the execution of this command.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] pcrIndex The index of the PCR to read
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_VALUE: if pcrIndex is invalid.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_PcrRead_Async(
+    FAPI_CONTEXT *context,
+    uint32_t      pcrIndex)
+{
+    LOG_TRACE("called for context:%p", context);
+    LOG_TRACE("pcrIndex: %" PRIu32, pcrIndex);
+
+    TSS2_RC r;
+    TPML_PCR_SELECTION pcr_selection;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+
+    /* Helpful alias pointers */
+    IFAPI_PCR * command = &context->cmd.pcr;
+
+    r = ifapi_session_init(context);
+    return_if_error(r, "Initialize PcrRead");
+
+    pcr_selection = context->profiles.default_profile.pcr_selection;
+
+    r = ifapi_filter_pcr_selection_by_index(&pcr_selection, &pcrIndex, 1);
+    return_if_error(r, "PCR selection");
+
+    r = Esys_PCR_Read_Async(context->esys,
+                            ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
+                            &pcr_selection);
+    return_if_error(r, "PCR Read");
+
+    /* Used for retrieving the eventlog during finish*/
+    command->pcrIndex = pcrIndex;
+
+    context->state = PCR_READ_READ_PCR;
+
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous finish function for Fapi_PcrRead
+ *
+ * This function should be called after a previous Fapi_PcrRead_Async.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [out] pcrValue The value of the PCR. May be NULL
+ * @param [out] pcrValueSize The size of value in bytes. May be NULL
+ * @param [out] pcrLog The PCR log. May be NULL
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context, pcrValue or pcrValueSize
+ *         is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
+ *         complete. Call this function again later.
+ */
+TSS2_RC
+Fapi_PcrRead_Finish(
+    FAPI_CONTEXT *context,
+    uint8_t     **pcrValue,
+    size_t       *pcrValueSize,
+    char        **pcrLog)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+
+    /* Helpful alias pointers */
+    IFAPI_PCR * command = &context->cmd.pcr;
+
+    command->pcrValues = NULL;
+
+    switch (context->state) {
+        statecase(context->state, PCR_READ_READ_PCR);
+            SAFE_FREE(command->pcrValues);
+            r = Esys_PCR_Read_Finish(context->esys,
+                                     &command->update_count,
+                                     NULL,
+                                     &command->pcrValues);
+            return_try_again(r);
+            goto_if_error_reset_state(r, "PCR_ReadWithLog_Finish", cleanup);
+
+            if (pcrValueSize)
+                *pcrValueSize = command->pcrValues->digests[0].size;
+            if (pcrValue) {
+                *pcrValue = malloc(command->pcrValues->digests[0].size);
+                goto_if_null2(*pcrValue, "Out of memory.",
+                        r, TSS2_FAPI_RC_MEMORY, cleanup);
+
+                memcpy(*pcrValue, &command->pcrValues->digests[0].buffer[0],
+                       command->pcrValues->digests[0].size);
+            }
+            SAFE_FREE(command->pcrValues);
+            if (!pcrLog) {
+                context->state =  _FAPI_STATE_INIT;
+                break;
+            }
+
+            r = ifapi_eventlog_get_async(&context->eventlog, &context->io,
+                                         &command->pcrIndex, 1);
+            goto_if_error(r, "Error getting event log", cleanup);
+
+            context->state = PCR_READ_READ_EVENT_LIST;
+            fallthrough;
+
+        statecase(context->state, PCR_READ_READ_EVENT_LIST);
+            r = ifapi_eventlog_get_finish(&context->eventlog, &context->io, pcrLog);
+            return_try_again(r);
+            goto_if_error(r, "Error getting event log", cleanup);
+
+            context->state =  _FAPI_STATE_INIT;
+            break;
+
+        statecasedefault(context->state);
+    }
+
+cleanup:
+    SAFE_FREE(command->pcrValues);
+    LOG_TRACE("finsihed");
+    return r;
+}
diff --git a/src/tss2-fapi/api/Fapi_Provision.c b/src/tss2-fapi/api/Fapi_Provision.c
new file mode 100644
index 0000000..45936b3
--- /dev/null
+++ b/src/tss2-fapi/api/Fapi_Provision.c
@@ -0,0 +1,811 @@
+/* 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 <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#include "fapi_util.h"
+#include "tss2_tcti.h"
+#include "tss2_esys.h"
+#include "tss2_fapi.h"
+#include "fapi_int.h"
+#include "fapi_crypto.h"
+#include "fapi_policy.h"
+#include "ifapi_get_intl_cert.h"
+
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+#define EK_CERT_RANGE (0x01c07fff)
+
+/** One-Call function for the initial FAPI provisioning.
+ *
+ * Provisions a TSS with its TPM. This includes the setting of important passwords
+ * and policy settings as well as the readout of the EK and its certificate and
+ * the initialization of the system-wide keystore.
+ *
+ * @param [in,out] context The FAPI_CONTEXT.
+ * @param [in] authValueEh The authorization value for the endorsement
+ *             hierarchy. May be NULL
+ * @param [in] authValueSh The authorization value for the storage hierarchy.
+ *             Should be NULL
+ * @param [in] authValueLockout The authorization value for lockout.
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_PATH: if policyPathEh or policyPathSh do not map to
+ *         a FAPI policy.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_Provision(
+    FAPI_CONTEXT *context,
+    char   const *authValueEh,
+    char   const *authValueSh,
+    char   const *authValueLockout)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r, r2;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+
+    /* Check whether TCTI and ESYS are initialized */
+    return_if_null(context->esys, "Command can't be executed in none TPM mode.",
+                   TSS2_FAPI_RC_NO_TPM);
+
+    /* If the async state automata of FAPI shall be tested, then we must not set
+       the timeouts of ESYS to blocking mode.
+       During testing, the mssim tcti will ensure multiple re-invocations.
+       Usually however the synchronous invocations of FAPI shall instruct ESYS
+       to block until a result is available. */
+#ifndef TEST_FAPI_ASYNC
+    r = Esys_SetTimeout(context->esys, TSS2_TCTI_TIMEOUT_BLOCK);
+    return_if_error_reset_state(r, "Set Timeout to blocking");
+#endif /* TEST_FAPI_ASYNC */
+
+    r = Fapi_Provision_Async(context, authValueEh, authValueSh, authValueLockout);
+    return_if_error_reset_state(r, "Provision");
+
+    do {
+        /* We wait for file I/O to be ready if the FAPI state automata
+           are in a file I/O state. */
+        r = ifapi_io_poll(&context->io);
+        return_if_error(r, "Something went wrong with IO polling");
+
+        /* Repeatedly call the finish function, until FAPI has transitioned
+           through all execution stages / states of this invocation. */
+        r = Fapi_Provision_Finish(context);
+    } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
+
+    /* Reset the ESYS timeout to non-blocking, immediate response. */
+    r2 = Esys_SetTimeout(context->esys, 0);
+    return_if_error(r2, "Set Timeout to non-blocking");
+
+    return_if_error_reset_state(r, "Provision");
+
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous function for the initial FAPI provisioning.
+ *
+ * Provisions a TSS with its TPM. This includes the setting of important passwords
+ * and policy settings as well as the readout of the EK and its certificate and
+ * the initialization of the system-wide keystore.
+ *
+ * Call Fapi_Provision_Finish to finish the execution of this command.
+ *
+ * @param [in,out] context The FAPI_CONTEXT.
+ * @param [in] authValueEh The authorization value for the endorsement
+ *             hierarchy. May be NULL
+ * @param [in] authValueSh The authorization value for the storage hierarchy.
+ *             Should be NULL
+ * @param [in] authValueLockout The authorization value for lockout.
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_PATH: if policyPathEh or policyPathSh do not map to
+ *         a FAPI policy.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_Provision_Async(
+    FAPI_CONTEXT *context,
+    char const *authValueEh,
+    char const *authValueSh,
+    char const *authValueLockout)
+{
+    LOG_TRACE("called for context:%p", context);
+    LOG_TRACE("authValueEh: %s", authValueEh);
+    LOG_TRACE("authValueSh: %s", authValueSh);
+    LOG_TRACE("authValueLockout: %s", authValueLockout);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+
+    /* Helpful alias pointers */
+    IFAPI_Provision * command = &context->cmd.Provision;
+
+    r = ifapi_session_init(context);
+    goto_if_error(r, "Initialize Provision", end);
+
+    strdup_check(command->authValueLockout, authValueLockout, r, end);
+    strdup_check(command->authValueEh, authValueEh, r, end);
+    strdup_check(command->authValueSh, authValueSh, r, end);
+    context->ek_handle = ESYS_TR_NONE;
+    context->srk_handle = ESYS_TR_NONE;
+    command->cert_nv_idx = MIN_EK_CERT_HANDLE;
+    command->capabilityData = NULL;
+
+    context->state = PROVISION_READ_PROFILE;
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+end:
+    SAFE_FREE(command->authValueLockout);
+    SAFE_FREE(command->authValueEh);
+    SAFE_FREE(command->authValueSh);
+    return r;
+}
+
+/** Asynchronous finish function for Fapi_Provision
+ *
+ * This function should be called after a previous Fapi_Provision_Async.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
+ *         complete. Call this function again later.
+ */
+TSS2_RC
+Fapi_Provision_Finish(FAPI_CONTEXT *context)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    TPM2B_NV_PUBLIC *nvPublic = NULL;
+    uint8_t *certData = NULL;
+    size_t certSize;
+    TPMI_YES_NO moreData;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+
+    /* Helpful alias pointers */
+    IFAPI_Provision * command = &context->cmd.Provision;
+    IFAPI_OBJECT *hierarchy = &command->hierarchy;
+    TPMS_CAPABILITY_DATA **capabilityData = &command->capabilityData;
+    IFAPI_NV_Cmds * nvCmd = &context->nv_cmd;
+    IFAPI_OBJECT * pkeyObject = &context->createPrimary.pkey_object;
+    IFAPI_KEY * pkey = &pkeyObject->misc.key;
+    IFAPI_PROFILE * defaultProfile = &context->profiles.default_profile;
+
+    switch (context->state) {
+        statecase(context->state, PROVISION_READ_PROFILE);
+            command->root_crt = NULL;
+            r = ifapi_set_key_flags(defaultProfile->srk_template,
+                    context->profiles.default_profile.srk_policy ? true : false,
+                    &command->public_templ);
+            goto_if_error(r, "Set key flags for SRK", error_cleanup);
+
+            r = ifapi_merge_profile_into_template(&context->profiles.default_profile,
+                    &command->public_templ);
+            goto_if_error(r, "Merging profile and template", error_cleanup);
+
+            r = Esys_DictionaryAttackParameters_Async(context->esys, ESYS_TR_RH_LOCKOUT,
+                    ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
+                    defaultProfile->newMaxTries, defaultProfile->newRecoveryTime,
+                    defaultProfile->lockoutRecovery);
+            goto_if_error(r, "Error Esys_DictionaryAttackParameters",
+                          error_cleanup);
+            fallthrough;
+
+        statecase(context->state, PROVISION_WRITE_LOCKOUT_PARAM);
+            r = Esys_DictionaryAttackParameters_Finish(context->esys);
+            return_try_again(r);
+            goto_if_error_reset_state(r, "DictionaryAttackParameters_Finish",
+                    error_cleanup);
+
+            r = Esys_GetCapability_Async(context->esys,
+                    ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, TPM2_CAP_PCRS, 0, 1);
+            goto_if_error(r, "Esys_GetCapability_Async", error_cleanup);
+
+            fallthrough;
+
+        statecase(context->state, PROVISION_WAIT_FOR_GET_CAP1);
+            r = Esys_GetCapability_Finish(context->esys, &moreData, capabilityData);
+            return_try_again(r);
+            goto_if_error_reset_state(r, "GetCapablity_Finish", error_cleanup);
+
+            TPML_PCR_SELECTION pcr_capability = (*capabilityData)->data.assignedPCR;
+            r = ifapi_check_profile_pcr_selection(&defaultProfile->pcr_selection,
+                    &pcr_capability);
+            goto_if_error(r, "Invalid PCR selection in profile.", error_cleanup);
+
+            SAFE_FREE(*capabilityData);
+            fallthrough;
+
+        statecase(context->state, PROVISION_INIT_SRK);
+            /* Clear key object for the primary to be created */
+            memset(pkey, 0, sizeof(IFAPI_KEY));
+            r = ifapi_init_primary_async(context, TSS2_SRK);
+            goto_if_error(r, "Initialize primary", error_cleanup);
+
+            context->state =  PROVISION_AUTH_SRK_NO_AUTH_SENT;
+            fallthrough;
+
+        statecase(context->state, PROVISION_AUTH_SRK_AUTH_SENT);
+            fallthrough;
+
+        statecase(context->state, PROVISION_AUTH_SRK_NO_AUTH_SENT);
+            r = ifapi_init_primary_finish(context, TSS2_SRK);
+            return_try_again(r);
+            goto_if_error(r, "Init primary finish.", error_cleanup);
+
+            if (command->public_templ.persistent_handle) {
+                /* Assign found handle to object */
+                pkey->persistent_handle = command->public_templ.persistent_handle;
+                ifapi_init_hierarchy_object(hierarchy, ESYS_TR_RH_OWNER);
+                r = Esys_EvictControl_Async(context->esys, hierarchy->handle,
+                    pkeyObject->handle, ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
+                    pkey->persistent_handle);
+                goto_if_error(r, "Error Esys EvictControl", error_cleanup);
+                context->state = PROVISION_WAIT_FOR_SRK_PERSISTENT;
+                return TSS2_FAPI_RC_TRY_AGAIN;
+            } else {
+                context->state = PROVISION_SRK_WRITE_PREPARE;
+            }
+
+            context->state = PROVISION_SRK_WRITE_PREPARE;
+            fallthrough;
+
+        statecase(context->state, PROVISION_SRK_WRITE_PREPARE);
+            pkeyObject->objectType = IFAPI_KEY_OBJ;
+            pkeyObject->system = command->public_templ.system;
+
+            /* Perform esys serialization if necessary */
+            r = ifapi_esys_serialize_object(context->esys, pkeyObject);
+            goto_if_error(r, "Prepare serialization", error_cleanup);
+
+            /* Start writing the SRK to the key store */
+            r = ifapi_keystore_store_async(&context->keystore, &context->io, "HS/SRK",
+                    pkeyObject);
+            goto_if_error_reset_state(r, "Could not open: %sh", error_cleanup, "HS/SRK");
+            context->state = PROVISION_SRK_WRITE;
+            fallthrough;
+
+        statecase(context->state, PROVISION_SRK_WRITE);
+            /* Finish writing the SRK to the key store */
+            r = ifapi_keystore_store_finish(&context->keystore, &context->io);
+            return_try_again(r);
+            goto_if_error_reset_state(r, "write_finish failed", error_cleanup);
+
+            /* Clean objects used for SRK computation */
+            ifapi_cleanup_ifapi_object(pkeyObject);
+            memset(&command->public_templ, 0, sizeof(IFAPI_KEY_TEMPLATE));
+
+            r = ifapi_set_key_flags(defaultProfile->ek_template,
+                     context->profiles.default_profile.ek_policy ? true : false,
+                     &command->public_templ);
+            goto_if_error(r, "Set key flags for SRK", error_cleanup);
+
+            r = ifapi_merge_profile_into_template(&context->profiles.default_profile,
+                    &command->public_templ);
+            goto_if_error(r, "Merging profile", error_cleanup);
+
+            /* Clear key object for the primary to be created */
+            memset(pkey, 0, sizeof(IFAPI_KEY));
+            r = ifapi_init_primary_async(context, TSS2_EK);
+            goto_if_error(r, "Initialize primary", error_cleanup);
+
+            context->state = PROVISION_AUTH_EK_NO_AUTH_SENT;
+            fallthrough;
+
+        statecase(context->state, PROVISION_AUTH_EK_AUTH_SENT);
+            fallthrough;
+
+        statecase(context->state, PROVISION_AUTH_EK_NO_AUTH_SENT);
+            r = ifapi_init_primary_finish(context, TSS2_EK);
+            return_try_again(r);
+            goto_if_error(r, "Init primary finish", error_cleanup);
+
+            ifapi_init_hierarchy_object(hierarchy, ESYS_TR_RH_OWNER);
+            if (command->public_templ.persistent_handle) {
+                pkey->persistent_handle = command->public_templ.persistent_handle;
+                r = Esys_EvictControl_Async(context->esys, hierarchy->handle,
+                        pkeyObject->handle, ESYS_TR_PASSWORD, ESYS_TR_NONE,
+                        ESYS_TR_NONE, pkey->persistent_handle);
+                goto_if_error(r, "Error Esys EvictControl", error_cleanup);
+                context->state = PROVISION_WAIT_FOR_EK_PERSISTENT;
+                return TSS2_FAPI_RC_TRY_AGAIN;
+            }
+            fallthrough;
+
+        statecase(context->state, PROVISION_INIT_GET_CAP2);
+
+            r = Esys_GetCapability_Async(context->esys,
+                    ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, TPM2_CAP_HANDLES,
+                    MIN_EK_CERT_HANDLE, TPM2_MAX_CAP_HANDLES);
+            goto_if_error(r, "Esys_GetCapability_Async", error_cleanup);
+
+            fallthrough;
+
+        statecase(context->state, PROVISION_WAIT_FOR_GET_CAP2);
+            r = Esys_GetCapability_Finish(context->esys, &moreData, capabilityData);
+            return_try_again(r);
+            goto_if_error_reset_state(r, "GetCapablity_Finish", error_cleanup);
+
+            if ((*capabilityData)->data.handles.count == 0) {
+                Esys_Free(*capabilityData);
+                context->state = PROVISION_CHECK_FOR_VENDOR_CERT;
+                return TSS2_FAPI_RC_TRY_AGAIN;
+            }
+            command->capabilityData = *capabilityData;
+            command->cert_count = (*capabilityData)->data.handles.count;
+
+            /* Filter out NV handles beyond the EK cert range */
+            for (size_t i = 0; i < command->cert_count; i++) {
+                if (command->capabilityData->data.handles.handle[i] > EK_CERT_RANGE) {
+                    command->cert_count = i;
+                }
+            }
+
+            if (command->cert_count == 0) {
+                Esys_Free(command->capabilityData);
+                command->capabilityData = NULL;
+                context->state = PROVISION_CHECK_FOR_VENDOR_CERT;
+                return TSS2_FAPI_RC_TRY_AGAIN;
+            }
+            fallthrough;
+
+        statecase(context->state, PROVISION_GET_CERT_NV);
+            command->cert_nv_idx
+                = command->capabilityData->data.handles.handle[command->cert_count-1];
+
+            if ((command->cert_nv_idx % 2) || /**< Certificates will be stored at even address */
+                command->cert_nv_idx == 0x01c00004 || /**< RSA template */
+                command->cert_nv_idx == 0x01c0000c) { /**< ECC template */
+                if (command->cert_count > 1) {
+                    command->cert_count -= 1;
+                    /* Check next certificate */
+                    context->state = PROVISION_GET_CERT_NV;
+                    return TSS2_FAPI_RC_TRY_AGAIN;
+                } else {
+                    context->state = PROVISION_EK_WRITE_PREPARE;
+                    return TSS2_FAPI_RC_TRY_AGAIN;
+                }
+            }
+            ifapi_init_hierarchy_object(&nvCmd->auth_object, TPM2_RH_OWNER);
+
+            r = Esys_TR_FromTPMPublic_Async(context->esys, command->cert_nv_idx,
+                    ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE);
+            goto_if_error_reset_state(r, "Esys_TR_FromTPMPublic_Async", error_cleanup);
+
+            context->state = PROVISION_GET_CERT_NV_FINISH;
+            fallthrough;
+
+        statecase(context->state, PROVISION_GET_CERT_NV_FINISH);
+            r = Esys_TR_FromTPMPublic_Finish(context->esys,
+                    &command->esys_nv_cert_handle);
+            return_try_again(r);
+            goto_if_error_reset_state(r, "TR_FromTPMPublic_Finish", error_cleanup);
+
+            /* Read public to get size of certificate */
+            r = Esys_NV_ReadPublic_Async(context->esys, command->esys_nv_cert_handle,
+                     ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE);
+            goto_if_error_reset_state(r, "Esys_NV_ReadPublic_Async", error_cleanup);
+
+            context->state = PROVISION_GET_CERT_READ_PUBLIC;
+            fallthrough;
+
+        statecase(context->state, PROVISION_GET_CERT_READ_PUBLIC);
+            r = Esys_NV_ReadPublic_Finish(context->esys, &nvPublic, NULL);
+            return_try_again(r);
+
+            goto_if_error(r, "Error: nv read public", error_cleanup);
+
+            /* TPMA_NV_NO_DA is set for NV certificate */
+            nvCmd->nv_object.misc.nv.public.nvPublic.attributes = TPMA_NV_NO_DA;
+
+            /* Prepare context for nv read */
+            nvCmd->data_idx = 0;
+            nvCmd->auth_index = ESYS_TR_RH_OWNER;
+            nvCmd->numBytes = nvPublic->nvPublic.dataSize;
+            nvCmd->esys_handle = command->esys_nv_cert_handle;
+            nvCmd->offset = 0;
+            command->pem_cert = NULL;
+            context->session1 = ESYS_TR_PASSWORD;
+            context->session2 = ESYS_TR_NONE;
+            nvCmd->nv_read_state = NV_READ_INIT;
+            memset(&nvCmd->nv_object, 0, sizeof(IFAPI_OBJECT));
+            SAFE_FREE(nvPublic);
+
+            context->state = PROVISION_READ_CERT;
+            fallthrough;
+
+        statecase(context->state, PROVISION_READ_CERT);
+            TPM2B_PUBLIC public_key;
+            char * root_ca_file;
+            r = ifapi_nv_read(context, &certData, &certSize);
+            return_try_again(r);
+            goto_if_error_reset_state(r, " FAPI NV_Read", error_cleanup);
+
+            //TODO check even and not template
+            r = ifapi_cert_to_pem(certData, certSize, &command->pem_cert,
+                                  &command->cert_key_type, &public_key);
+            SAFE_FREE(certData);
+            goto_if_error(r, "Convert certificate to pem.", error_cleanup);
+
+            if (ifapi_cmp_public_key(&pkeyObject->misc.key.public, &public_key)) {
+                context->state = PROVISION_PREPARE_READ_ROOT_CERT;
+                return TSS2_FAPI_RC_TRY_AGAIN;
+            } else {
+                /* Certificate not appropriate for current EK key type */
+                command->cert_count -= 1;
+                SAFE_FREE(command->pem_cert);
+                if (command->cert_count > 0) {
+                    /* Check next certificate */
+                    context->state = PROVISION_GET_CERT_NV;
+                    return TSS2_FAPI_RC_TRY_AGAIN;
+                }
+            }
+            LOG_ERROR("No EK certificate found.");
+            context->state = PROVISION_EK_WRITE_PREPARE;
+            return TSS2_FAPI_RC_TRY_AGAIN;
+            fallthrough;
+
+        statecase(context->state, PROVISION_PREPARE_READ_ROOT_CERT);
+            /* Prepare reading of root certificate. */
+            root_ca_file = getenv("ROOTCA");
+            if (!root_ca_file) {
+                context->state = PROVISION_EK_CHECK_CERT;
+                return TSS2_FAPI_RC_TRY_AGAIN;
+            }
+            r = ifapi_io_read_async(&context->io, root_ca_file);
+            return_try_again(r);
+            goto_if_error2(r, "Reading certificate %s", error_cleanup, root_ca_file);
+
+	        fallthrough;
+
+        statecase(context->state, PROVISION_READ_ROOT_CERT);
+            char * intermed_ca_file;
+            r = ifapi_io_read_finish(&context->io, (uint8_t **) &command->root_crt, NULL);
+            return_try_again(r);
+            goto_if_error(r, "Reading root certificate failed", error_cleanup);
+
+            /* Prepare reading of intermed certificate. */
+            intermed_ca_file = getenv("INTERMEDCA");
+            if (!intermed_ca_file) {
+                context->state = PROVISION_EK_WRITE_PREPARE;
+                return TSS2_FAPI_RC_TRY_AGAIN;
+            }
+            r = ifapi_io_read_async(&context->io, intermed_ca_file);
+            goto_if_error2(r, "Reading certificate %s", error_cleanup, intermed_ca_file);
+
+            fallthrough;
+
+        statecase(context->state, PROVISION_READ_INTERMED_CERT);
+            r = ifapi_io_read_finish(&context->io, (uint8_t **) &command->intermed_crt, NULL);
+            return_try_again(r);
+            goto_if_error(r, "Reading intermediate certificate failed", error_cleanup);
+
+            fallthrough;
+
+        statecase(context->state, PROVISION_EK_CHECK_CERT);
+            r = ifapi_verify_ek_cert(command->root_crt, command->intermed_crt, command->pem_cert);
+            SAFE_FREE(command->root_crt);
+            SAFE_FREE(command->intermed_crt);
+            goto_if_error2(r, "Verify EK certificate", error_cleanup);
+
+            fallthrough;
+
+        statecase(context->state, PROVISION_EK_WRITE_PREPARE);
+            pkeyObject->objectType = IFAPI_KEY_OBJ;
+            pkeyObject->system = command->public_templ.system;
+            strdup_check(pkeyObject->misc.key.certificate, command->pem_cert, r, error_cleanup);
+            SAFE_FREE(command->pem_cert);
+
+            /* Perform esys serialization if necessary */
+            r = ifapi_esys_serialize_object(context->esys,
+                    pkeyObject);
+            goto_if_error(r, "Prepare serialization", error_cleanup);
+
+            /* Start writing the EK to the key store */
+            r = ifapi_keystore_store_async(&context->keystore, &context->io, "HE/EK",
+                    pkeyObject);
+            goto_if_error_reset_state(r, "Could not open: %sh", error_cleanup, "HE/EK");
+
+            fallthrough;
+
+        statecase(context->state, PROVISION_EK_WRITE);
+            /* Finish writing the EK to the key store */
+            r = ifapi_keystore_store_finish(&context->keystore, &context->io);
+            return_try_again(r);
+            goto_if_error_reset_state(r, "write_finish failed", error_cleanup);
+
+            /* Clean objects used for EK computation */
+            ifapi_cleanup_ifapi_object(pkeyObject);
+            memset(&command->public_templ, 0, sizeof(IFAPI_KEY_TEMPLATE));
+            SAFE_FREE(hierarchy->misc.hierarchy.description);
+            ifapi_init_hierarchy_object(hierarchy, ESYS_TR_RH_LOCKOUT);
+            strdup_check(hierarchy->misc.hierarchy.description, "Lockout Hierarchy",
+                    r, error_cleanup);
+
+            if (!command->authValueLockout ||
+                strcmp(command->authValueLockout, "") == 0) {
+                context->state = PROVISION_LOCKOUT_CHANGE_POLICY;
+                return TSS2_FAPI_RC_TRY_AGAIN;
+            }
+
+            if (strlen(command->authValueLockout) > sizeof(TPMU_HA)) {
+                goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
+                        "Password too long.", error_cleanup);
+            }
+            memcpy(&command->hierarchy_auth.buffer[0],
+                   command->authValueLockout, strlen(command->authValueLockout));
+            command->hierarchy_auth.size = strlen(command->authValueLockout);
+            context->state = PROVISION_CHANGE_LOCKOUT_AUTH;
+            return TSS2_FAPI_RC_TRY_AGAIN;
+
+        statecase(context->state, PROVISION_WAIT_FOR_SRK_PERSISTENT);
+            r = Esys_EvictControl_Finish(context->esys, &pkeyObject->handle);
+            return_try_again(r);
+            goto_if_error(r, "Evict control failed", error_cleanup);
+
+            context->state = PROVISION_SRK_WRITE_PREPARE;
+            return TSS2_FAPI_RC_TRY_AGAIN;
+
+        statecase(context->state, PROVISION_WAIT_FOR_EK_PERSISTENT);
+            r = Esys_EvictControl_Finish(context->esys, &pkeyObject->handle);
+            return_try_again(r);
+            goto_if_error(r, "Evict control failed", error_cleanup);
+
+            context->state = PROVISION_INIT_GET_CAP2;
+            return TSS2_FAPI_RC_TRY_AGAIN;
+
+        statecase(context->state, PROVISION_CHANGE_LOCKOUT_AUTH);
+            r = ifapi_change_auth_hierarchy(context, ESYS_TR_RH_LOCKOUT,
+                    &command->hierarchy, &command->hierarchy_auth);
+            return_try_again(r);
+            goto_if_error(r, "Change auth hierarchy.", error_cleanup);
+
+            context->state = PROVISION_LOCKOUT_CHANGE_POLICY;
+            fallthrough;
+
+        statecase(context->state, PROVISION_LOCKOUT_CHANGE_POLICY);
+            r = ifapi_change_policy_hierarchy(context, ESYS_TR_RH_OWNER,
+                    hierarchy, defaultProfile->sh_policy);
+            return_try_again(r);
+            goto_if_error(r, "Change policy LOCKOUT", error_cleanup);
+
+            /* Start writing the lockout hierarchy object to the key store */
+            r = ifapi_keystore_store_async(&context->keystore, &context->io, "/LOCKOUT",
+                    &command->hierarchy);
+            goto_if_error_reset_state(r, "Could not open: %sh",
+                    error_cleanup, "/LOCKOUT");
+
+            context->state = PROVISION_WRITE_LOCKOUT;
+            fallthrough;
+
+        statecase(context->state, PROVISION_WRITE_LOCKOUT);
+            /* Finish writing the lockout hierarchy to the key store */
+            r = ifapi_keystore_store_finish(&context->keystore, &context->io);
+            return_try_again(r);
+            goto_if_error_reset_state(r, "write_finish failed", error_cleanup);
+
+            SAFE_FREE(hierarchy->misc.hierarchy.description);
+            ifapi_init_hierarchy_object(hierarchy, ESYS_TR_RH_ENDORSEMENT);
+            strdup_check(hierarchy->misc.hierarchy.description,
+                    "Endorsement Hierarchy", r, error_cleanup);
+
+            context->state = PROVISION_CHANGE_EH_CHECK;
+            fallthrough;
+
+        statecase(context->state, PROVISION_CHANGE_EH_CHECK);
+            if (command->authValueEh) {
+                context->state = PROVISION_CHANGE_EH_AUTH;
+                memcpy(&command->hierarchy_auth.buffer[0], command->authValueEh,
+                       strlen(command->authValueEh));
+                command->hierarchy_auth.size = strlen(command->authValueEh);
+            } else {
+                context->state = PROVISION_EH_CHANGE_POLICY;
+                return TSS2_FAPI_RC_TRY_AGAIN;
+            }
+            context->state = PROVISION_CHANGE_EH_AUTH;
+            fallthrough;
+
+        statecase(context->state, PROVISION_CHANGE_EH_AUTH);
+            r = ifapi_change_auth_hierarchy(context, ESYS_TR_RH_ENDORSEMENT,
+                    &command->hierarchy, &command->hierarchy_auth);
+            return_try_again(r);
+            goto_if_error(r, "Change auth hierarchy.", error_cleanup);
+
+            context->state = PROVISION_EH_CHANGE_POLICY;
+            fallthrough;
+
+        statecase(context->state, PROVISION_EH_CHANGE_POLICY);
+            r = ifapi_change_policy_hierarchy(context, ESYS_TR_RH_ENDORSEMENT,
+                    hierarchy, defaultProfile->eh_policy);
+            return_try_again(r);
+            goto_if_error(r, "Change policy EH", error_cleanup);
+
+            /* Start writing the endorsement hierarchy object to the key store */
+            r = ifapi_keystore_store_async(&context->keystore, &context->io, "/HE",
+                    &command->hierarchy);
+            goto_if_error_reset_state(r, "Could not open: %sh", error_cleanup, "/HE");
+
+            context->state = PROVISION_WRITE_EH;
+            fallthrough;
+
+        statecase(context->state, PROVISION_WRITE_EH);
+            /* Finish writing the endorsement hierarchy to the key store */
+            r = ifapi_keystore_store_finish(&context->keystore, &context->io);
+            return_try_again(r);
+            return_if_error_reset_state(r, "write_finish failed");
+
+            SAFE_FREE(hierarchy->misc.hierarchy.description);
+            ifapi_init_hierarchy_object(hierarchy, ESYS_TR_RH_OWNER);
+            strdup_check(hierarchy->misc.hierarchy.description,
+                   "Owner Hierarchy", r, error_cleanup);
+
+            context->state = PROVISION_CHANGE_SH_CHECK;
+            fallthrough;
+
+        statecase(context->state, PROVISION_CHANGE_SH_CHECK);
+            if (command->authValueSh) {
+                context->state = PROVISION_CHANGE_SH_AUTH;
+                memcpy(&command->hierarchy_auth.buffer[0], command->authValueSh,
+                       strlen(command->authValueSh));
+                command->hierarchy_auth.size = strlen(command->authValueSh);
+                    context->state = PROVISION_CHANGE_SH_AUTH;
+            } else {
+                context->state = PROVISION_SH_CHANGE_POLICY;
+                return TSS2_FAPI_RC_TRY_AGAIN;
+            }
+            context->state = PROVISION_CHANGE_SH_AUTH;
+            fallthrough;
+
+        statecase(context->state, PROVISION_CHANGE_SH_AUTH);
+            r = ifapi_change_auth_hierarchy(context, ESYS_TR_RH_OWNER,
+                    &command->hierarchy, &command->hierarchy_auth);
+            return_try_again(r);
+            goto_if_error(r, "Change auth hierarchy.", error_cleanup);
+
+            context->state = PROVISION_SH_CHANGE_POLICY;
+            fallthrough;
+
+        statecase(context->state, PROVISION_SH_CHANGE_POLICY);
+            r = ifapi_change_policy_hierarchy(context, ESYS_TR_RH_OWNER,
+                    hierarchy, defaultProfile->sh_policy);
+            return_try_again(r);
+            goto_if_error(r, "Change policy SH", error_cleanup);
+
+            /* Start writing the owner hierarchy object to the key store */
+            r = ifapi_keystore_store_async(&context->keystore, &context->io, "/HS",
+                    &command->hierarchy);
+            goto_if_error_reset_state(r, "Could not open: %sh", error_cleanup, "/HS");
+            context->state = PROVISION_WRITE_SH;
+            fallthrough;
+
+        statecase(context->state, PROVISION_WRITE_SH);
+            r = ifapi_keystore_store_finish(&context->keystore, &context->io);
+            return_try_again(r);
+            goto_if_error_reset_state(r, "write_finish failed", error_cleanup);
+            fallthrough;
+
+        statecase(context->state, PROVISION_FINISHED);
+            if (!context->srk_persistent && context->srk_handle != ESYS_TR_NONE) {
+                r = Esys_FlushContext_Async(context->esys, context->srk_handle);
+                goto_if_error(r, "Flush SRK", error_cleanup);
+            }
+            fallthrough;
+
+        /* Flush the SRK if not persistent */
+        statecase(context->state, PROVISION_FLUSH_SRK);
+            if (!context->srk_persistent && context->srk_handle != ESYS_TR_NONE) {
+                r = Esys_FlushContext_Finish(context->esys);
+                try_again_or_error_goto(r, "Flush SRK", error_cleanup);
+
+                context->srk_handle = ESYS_TR_NONE;
+
+            }
+            if (!context->ek_persistent && context->ek_handle != ESYS_TR_NONE) {
+                r = Esys_FlushContext_Async(context->esys, context->ek_handle);
+                goto_if_error(r, "Flush EK", error_cleanup);
+            }
+            fallthrough;
+
+         /* Flush the SRK if not persistent */
+        statecase(context->state, PROVISION_FLUSH_EK);
+            if (!context->ek_persistent && context->ek_handle != ESYS_TR_NONE) {
+                r = Esys_FlushContext_Finish(context->esys);
+                try_again_or_error_goto(r, "Flush EK", error_cleanup);
+
+                context->ek_handle = ESYS_TR_NONE;
+            }
+
+            context->state = _FAPI_STATE_INIT;
+            break;
+
+        statecase(context->state, PROVISION_CHECK_FOR_VENDOR_CERT);
+            r = Esys_GetCapability_Async(context->esys,
+                                         ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
+                                         TPM2_CAP_TPM_PROPERTIES, TPM2_PT_MANUFACTURER, 1);
+            goto_if_error(r, "Esys_GetCapability_Async", error_cleanup);
+
+            fallthrough;
+
+        statecase(context->state, PROVISION_GET_VENDOR);
+            r = Esys_GetCapability_Finish(context->esys, &moreData, capabilityData);
+            return_try_again(r);
+            goto_if_error_reset_state(r, "GetCapablity_Finish", error_cleanup);
+
+            if ((*capabilityData)->data.tpmProperties.tpmProperty[0].value == VENDOR_INTC) {
+                /* Get INTEL certificate for EK public hash via web */
+                uint8_t *cert_buffer = NULL;
+                size_t cert_size;
+                TPM2B_PUBLIC public;
+                r = ifapi_get_intl_ek_certificate(&pkey->public, &cert_buffer,
+                                                  &cert_size);
+                goto_if_error_reset_state(r, "Get certificates", error_cleanup);
+
+                r = ifapi_cert_to_pem(cert_buffer, cert_size, &command->pem_cert,
+                                      NULL, &public);
+                SAFE_FREE(cert_buffer);
+                goto_if_error_reset_state(r, "Convert certificate buffer to PEM.",
+                                          error_cleanup);
+            }
+            SAFE_FREE(*capabilityData);
+            context->state = PROVISION_EK_WRITE_PREPARE;
+            return TSS2_FAPI_RC_TRY_AGAIN;
+
+        statecasedefault(context->state);
+    }
+
+error_cleanup:
+    /* Primaries might not have been flushed in error cases */
+    ifapi_primary_clean(context);
+    SAFE_FREE(command->root_crt);
+    SAFE_FREE(*capabilityData);
+    SAFE_FREE(hierarchy->misc.hierarchy.description);
+    SAFE_FREE(command->authValueLockout);
+    SAFE_FREE(command->authValueEh);
+    SAFE_FREE(command->authValueSh);
+    SAFE_FREE(command->pem_cert);
+    SAFE_FREE(certData);
+    SAFE_FREE(nvPublic);
+    LOG_TRACE("finished");
+    return r;
+}
diff --git a/src/tss2-fapi/api/Fapi_Quote.c b/src/tss2-fapi/api/Fapi_Quote.c
new file mode 100644
index 0000000..1b1650a
--- /dev/null
+++ b/src/tss2-fapi/api/Fapi_Quote.c
@@ -0,0 +1,414 @@
+/* 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 "tss2_fapi.h"
+#include "fapi_int.h"
+#include "fapi_util.h"
+#include "tss2_esys.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+/** One-Call function for Fapi_Quote
+ *
+ * Given a set of PCRs and a restricted signing key, it will sign those PCRs and
+ * return the quote.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] pcrList The list of PCRs that are to be quoted
+ * @param [in] pcrListSize The size of pcrList in bytes
+ * @param [in] keyPath The path to the signing key
+ * @param [in] quoteType The type of quote. May be NULL
+ * @param [in] qualifyingData A nonce provided by the caller. May be NULL
+ * @param [in] qualifyingDataSize The size of qualifyingData in bytes. Must be 0
+ *             if qualifyingData is NULL
+ * @param [out] quoteInfo A JSON-encoded structure holding the inputs to the
+ *              quote operation
+ * @param [out] signature The signature of the PCRs
+ * @param [out] signatureSize The size of the signature in bytes. May be NULL
+ * @param [out] pcrLog The log of the PCR. May be NULL
+ * @param [out] certificate The certificate associated with the signing key. May
+ *              be NULL
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context, pcrList, keyPath,
+ *         quoteInfo or signature is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_KEY_NOT_FOUND: if path does not map to a FAPI entity.
+ * @retval TSS2_FAPI_RC_BAD_KEY: if the entity at path is not a key, or is a key
+ *         that is unsuitable for the requested operation.
+ * @retval TSS2_FAPI_RC_BAD_VALUE: if qualifyingData is invalid or if
+ *         qualifyingDataSize is zero.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_Quote(
+    FAPI_CONTEXT   *context,
+    uint32_t       *pcrList,
+    size_t          pcrListSize,
+    char     const *keyPath,
+    char     const *quoteType,
+    uint8_t  const *qualifyingData,
+    size_t          qualifyingDataSize,
+    char          **quoteInfo,
+    uint8_t       **signature,
+    size_t         *signatureSize,
+    char          **pcrLog,
+    char          **certificate)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r, r2;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(pcrList);
+    check_not_null(keyPath);
+    check_not_null(quoteInfo);
+    check_not_null(signature);
+
+    /* Check whether TCTI and ESYS are initialized */
+    return_if_null(context->esys, "Command can't be executed in none TPM mode.",
+                   TSS2_FAPI_RC_NO_TPM);
+
+    /* If the async state automata of FAPI shall be tested, then we must not set
+       the timeouts of ESYS to blocking mode.
+       During testing, the mssim tcti will ensure multiple re-invocations.
+       Usually however the synchronous invocations of FAPI shall instruct ESYS
+       to block until a result is available. */
+#ifndef TEST_FAPI_ASYNC
+    r = Esys_SetTimeout(context->esys, TSS2_TCTI_TIMEOUT_BLOCK);
+    return_if_error_reset_state(r, "Set Timeout to blocking");
+#endif /* TEST_FAPI_ASYNC */
+
+    r = Fapi_Quote_Async(context, pcrList, pcrListSize, keyPath, quoteType,
+                         qualifyingData, qualifyingDataSize);
+    return_if_error_reset_state(r, "PCR_Quote");
+
+    do {
+        /* We wait for file I/O to be ready if the FAPI state automata
+           are in a file I/O state. */
+        r = ifapi_io_poll(&context->io);
+        return_if_error(r, "Something went wrong with IO polling");
+
+        /* Repeatedly call the finish function, until FAPI has transitioned
+           through all execution stages / states of this invocation. */
+        r = Fapi_Quote_Finish(context, quoteInfo, signature, signatureSize,
+                               pcrLog, certificate);
+    } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
+
+    /* Reset the ESYS timeout to non-blocking, immediate response. */
+    r2 = Esys_SetTimeout(context->esys, 0);
+    return_if_error(r2, "Set Timeout to non-blocking");
+
+    return_if_error_reset_state(r, "PCR_Quote");
+
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous function for Fapi_Quote
+ *
+ * Given a set of PCRs and a restricted signing key, it will sign those PCRs and
+ * return the quote.
+ *
+ * Call Fapi_Quote_Finish to finish the execution of this command.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] pcrList The list of PCRs that are to be quoted
+ * @param [in] pcrListSize The size of pcrList in bytes
+ * @param [in] keyPath The path to the signing key
+ * @param [in] quoteType The type of quote. May be NULL
+ * @param [in] qualifyingData A nonce provided by the caller. May be NULL
+ * @param [in] qualifyingDataSize The size of qualifyingData in bytes. Must be 0
+ *             if qualifyingData is NULL
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context, pcrList or keyPath
+ *         is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_KEY_NOT_FOUND: if path does not map to a FAPI entity.
+ * @retval TSS2_FAPI_RC_BAD_KEY: if the entity at path is not a key, or is a key
+ *         that is unsuitable for the requested operation.
+ * @retval TSS2_FAPI_RC_BAD_VALUE: if pcrListSize is 0, qualifyingData is
+ *         invalid or if qualifyingDataSize is zero.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_Quote_Async(
+    FAPI_CONTEXT   *context,
+    uint32_t       *pcrList,
+    size_t          pcrListSize,
+    char     const *keyPath,
+    char     const *quoteType,
+    uint8_t  const *qualifyingData,
+    size_t          qualifyingDataSize)
+{
+    LOG_TRACE("called for context:%p", context);
+    LOG_TRACE("pcrListSize: %zi", pcrListSize);
+    for (size_t i = 0; i < pcrListSize; i++) {
+        LOG_TRACE("PCR list entry %zu: %ul", i, pcrList[i]);
+    }
+    LOG_TRACE("keyPath: %s", keyPath);
+    LOG_TRACE("quoteType: %s", quoteType);
+    if (qualifyingData) {
+        LOGBLOB_TRACE(qualifyingData, qualifyingDataSize, "qualifyingData");
+    } else {
+        LOG_TRACE("qualifyingData: (null) qualifyingDataSize: %zi", qualifyingDataSize);
+    }
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(pcrList);
+    check_not_null(keyPath);
+
+    /* Check for invalid parameters */
+    if (pcrListSize == 0) {
+        LOG_ERROR("pcrListSize must not be NULL");
+        return TSS2_FAPI_RC_BAD_VALUE;
+    }
+    if (qualifyingData == NULL && qualifyingDataSize) {
+        LOG_ERROR("QualifyingData is NULL but qualifyingDataSize is not 0");
+        return TSS2_FAPI_RC_BAD_VALUE;
+    }
+
+    /* Helpful alias pointers */
+    IFAPI_PCR * command = &context->cmd.pcr;
+
+    r = ifapi_session_init(context);
+    return_if_error(r, "Initialize Quote");
+
+    if (quoteType && strcmp(quoteType, "TPM-Quote") != 0) {
+        return_error(TSS2_FAPI_RC_BAD_VALUE,
+                     "Only quote type TPM-Quote is allowed");
+    }
+
+    r = ifapi_session_init(context);
+    return_if_error(r, "Initialize PCR_Quote");
+
+    /* Store parameters in context */
+    strdup_check(command->keyPath, keyPath, r, error_cleanup);
+
+    command->pcrList = malloc(pcrListSize * sizeof(TPM2_HANDLE));
+    goto_if_null2(command->pcrList, "Out of memory", r, TSS2_FAPI_RC_MEMORY,
+            error_cleanup);
+    memcpy(command->pcrList, pcrList, pcrListSize);
+
+    command->pcrListSize = pcrListSize;
+    command->tpm_quoted = NULL;
+    if (qualifyingData != NULL) {
+        FAPI_COPY_DIGEST(&command->qualifyingData.buffer[0],
+                command->qualifyingData.size, qualifyingData, qualifyingDataSize);
+    } else {
+        command->qualifyingData.size = 0;
+    }
+    context->state = PCR_QUOTE_WAIT_FOR_GET_CAP;
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+error_cleanup:
+    SAFE_FREE(command->keyPath);
+    SAFE_FREE(command->pcrList);
+    return r;
+}
+
+/** Asynchronous finish function for Fapi_Quote
+ *
+ * This function should be called after a previous Fapi_Quote_Async.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [out] quoteInfo A JSON-encoded structure holding the inputs to the
+ *              quote operation
+ * @param [out] signature The signature of the PCRs
+ * @param [out] signatureSize The size of the signature in bytes. May be NULL
+ * @param [out] pcrLog The log of the PCR. May be NULL
+ * @param [out] certificate The certificate associated with the signing key. May
+ *              be NULL
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context, quoteInfor or signature
+ *         is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
+ *         complete. Call this function again later.
+ */
+TSS2_RC
+Fapi_Quote_Finish(
+    FAPI_CONTEXT  *context,
+    char         **quoteInfo,
+    uint8_t      **signature,
+    size_t        *signatureSize,
+    char          **pcrLog,
+    char          **certificate)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+    IFAPI_OBJECT *sig_key_object;
+    const IFAPI_PROFILE *profile;
+    ESYS_TR auth_session;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(quoteInfo);
+    check_not_null(signature);
+
+    /* Helpful alias pointers */
+    IFAPI_PCR * command = &context->cmd.pcr;
+
+    switch (context->state) {
+        statecase(context->state, PCR_QUOTE_WAIT_FOR_GET_CAP);
+            command->pcr_selection = context->profiles.default_profile.pcr_selection;
+
+            r = ifapi_filter_pcr_selection_by_index(&command->pcr_selection,
+                                                    command->pcrList,
+                                                    command->pcrListSize);
+            goto_if_error_reset_state(r, "Filtering banks for PCR list.", error_cleanup);
+
+            r = ifapi_get_sessions_async(context,
+                                         IFAPI_SESSION_GENEK | IFAPI_SESSION1,
+                                         TPMA_SESSION_DECRYPT, 0);
+            goto_if_error_reset_state(r, "Create sessions", error_cleanup);
+
+            context->state = PCR_QUOTE_WAIT_FOR_SESSION;
+            fallthrough;
+
+        statecase(context->state, PCR_QUOTE_WAIT_FOR_SESSION);
+            r = ifapi_profiles_get(&context->profiles, command->keyPath, &profile);
+            goto_if_error_reset_state(r, " FAPI create session", error_cleanup);
+
+            r = ifapi_get_sessions_finish(context, profile);
+            return_try_again(r);
+            goto_if_error_reset_state(r, " FAPI create session", error_cleanup);
+
+            r = ifapi_load_keys_async(context, command->keyPath);
+            goto_if_error(r, "Load keys.", error_cleanup);
+
+            context->state = PCR_QUOTE_WAIT_FOR_KEY;
+            fallthrough;
+
+        statecase(context->state, PCR_QUOTE_WAIT_FOR_KEY);
+            r = ifapi_load_keys_finish(context, IFAPI_FLUSH_PARENT,
+                                       &command->handle,
+                                       &command->key_object);
+            return_try_again(r);
+            goto_if_error_reset_state(r, " Load key.", error_cleanup);
+
+            context->state = PCR_QUOTE_AUTHORIZE;
+            fallthrough;
+
+        statecase(context->state, PCR_QUOTE_AUTHORIZE);
+        r = ifapi_authorize_object(context, command->key_object, &auth_session);
+            return_try_again(r);
+            goto_if_error(r, "Authorize key.", error_cleanup);
+
+            r = Esys_Quote_Async(context->esys, command->handle,
+                                 auth_session, ESYS_TR_NONE, ESYS_TR_NONE,
+                                 &command->qualifyingData,
+                                 &command->key_object->misc.key.signing_scheme,
+                                 &command->pcr_selection);
+            goto_if_error(r, "Error: PCR_Quote", error_cleanup);
+
+            context->state = PCR_QUOTE_AUTH_SENT;
+            fallthrough;
+
+        statecase(context->state, PCR_QUOTE_AUTH_SENT);
+            command->tpm_signature = NULL;
+            SAFE_FREE(command->tpm_signature);
+            r = Esys_Quote_Finish(context->esys, &command->tpm_quoted,
+                                  &command->tpm_signature);
+            return_try_again(r);
+            goto_if_error(r, "Error: PCR_Quote", error_cleanup);
+
+            r = Esys_FlushContext_Async(context->esys, command->handle);
+            goto_if_error(r, "Error: FlushContext", error_cleanup);
+
+            context->state = PCR_QUOTE_WAIT_FOR_FLUSH;
+            return TSS2_FAPI_RC_TRY_AGAIN;
+
+        statecase(context->state, PCR_QUOTE_WAIT_FOR_FLUSH);
+            r = Esys_FlushContext_Finish(context->esys);
+            return_try_again(r);
+            goto_if_error(r, "Error: Sign", error_cleanup);
+
+            sig_key_object = command->key_object;
+            r = ifapi_tpm_to_fapi_signature(sig_key_object,
+                                            command->tpm_signature,
+                                            signature, signatureSize);
+            SAFE_FREE(command->tpm_signature);
+            goto_if_error(r, "Create FAPI signature.", error_cleanup);
+
+            r = ifapi_compute_quote_info(sig_key_object,
+                                         command->tpm_quoted,
+                                         quoteInfo);
+            goto_if_error(r, "Create compute quote info.", error_cleanup);
+
+            if (certificate) {
+                strdup_check(*certificate, sig_key_object->misc.key.certificate, r, error_cleanup);
+            }
+            if (!pcrLog) {
+                context->state = PCR_QUOTE_CLEANUP;
+                return TSS2_FAPI_RC_TRY_AGAIN;
+            }
+
+            r = ifapi_eventlog_get_async(&context->eventlog, &context->io,
+                                         command->pcrList,
+                                         command->pcrListSize);
+            goto_if_error(r, "Error getting event log", error_cleanup);
+
+            context->state = PCR_QUOTE_READ_EVENT_LIST;
+            fallthrough;
+
+        statecase(context->state, PCR_QUOTE_READ_EVENT_LIST);
+            r = ifapi_eventlog_get_finish(&context->eventlog, &context->io, pcrLog);
+            return_try_again(r);
+            goto_if_error(r, "Error getting event log", error_cleanup);
+            fallthrough;
+
+        statecase(context->state, PCR_QUOTE_CLEANUP)
+            r = ifapi_cleanup_session(context);
+            try_again_or_error_goto(r, "Cleanup", error_cleanup);
+
+            context->state = _FAPI_STATE_INIT;
+            break;
+
+        statecasedefault(context->state);
+    }
+
+error_cleanup:
+    SAFE_FREE(command->tpm_signature);
+    SAFE_FREE(command->tpm_quoted);
+    SAFE_FREE(command->keyPath);
+    SAFE_FREE(command->pcrList);
+    ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
+    ifapi_cleanup_ifapi_object(context->loadKey.key_object);
+    ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
+    ifapi_cleanup_ifapi_object(command->key_object);
+    ifapi_session_clean(context);
+    LOG_TRACE("finsihed");
+    return r;
+}
diff --git a/src/tss2-fapi/api/Fapi_SetAppData.c b/src/tss2-fapi/api/Fapi_SetAppData.c
new file mode 100644
index 0000000..e36c05d
--- /dev/null
+++ b/src/tss2-fapi/api/Fapi_SetAppData.c
@@ -0,0 +1,271 @@
+/* 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 <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#include "tss2_fapi.h"
+#include "fapi_int.h"
+#include "fapi_util.h"
+#include "tss2_esys.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+/** One-Call function for Fapi_SetAppData
+ *
+ * Associates an arbitrary data blob with a given object.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] path The path to the object the blob is associated with
+ * @param [in] appData The blob to associate with the object. May be NULL
+ * @param [in] appDataSize The size of appData in bytes. Must be 0 if appData is
+ *             NULL
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or path is NULL or if appData
+ *         is NULL and appDataSize is not 0.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_PATH: if path does not map to a FAPI entity.
+ * @retval TSS2_FAPI_RC_STORAGE_ERROR: if the updated data cannot be saved.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_SetAppData(
+    FAPI_CONTEXT  *context,
+    char    const *path,
+    uint8_t const *appData,
+    size_t         appDataSize)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r, r2;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(path);
+
+    /* Check whether TCTI and ESYS are initialized */
+    return_if_null(context->esys, "Command can't be executed in none TPM mode.",
+                   TSS2_FAPI_RC_NO_TPM);
+
+    /* If the async state automata of FAPI shall be tested, then we must not set
+       the timeouts of ESYS to blocking mode.
+       During testing, the mssim tcti will ensure multiple re-invocations.
+       Usually however the synchronous invocations of FAPI shall instruct ESYS
+       to block until a result is available. */
+#ifndef TEST_FAPI_ASYNC
+    r = Esys_SetTimeout(context->esys, TSS2_TCTI_TIMEOUT_BLOCK);
+    return_if_error_reset_state(r, "Set Timeout to blocking");
+#endif /* TEST_FAPI_ASYNC */
+
+    r = Fapi_SetAppData_Async(context, path, appData, appDataSize);
+    return_if_error_reset_state(r, "SetAppData");
+
+    do {
+        /* We wait for file I/O to be ready if the FAPI state automata
+           are in a file I/O state. */
+        r = ifapi_io_poll(&context->io);
+        return_if_error(r, "Something went wrong with IO polling");
+
+        /* Repeatedly call the finish function, until FAPI has transitioned
+           through all execution stages / states of this invocation. */
+        r = Fapi_SetAppData_Finish(context);
+    } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
+
+    /* Reset the ESYS timeout to non-blocking, immediate response. */
+    r2 = Esys_SetTimeout(context->esys, 0);
+    return_if_error(r2, "Set Timeout to non-blocking");
+
+    return_if_error_reset_state(r, "SetAppData");
+
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+}
+
+/** One-Call function for Fapi_SetAppData
+ *
+ * Associates an arbitrary data blob with a given object.
+ *
+ * Call Fapi_SetAppData_Finish to finish the execution of this command.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] path The path to the object the blob is associated with
+ * @param [in] appData The blob to associate with the object. May be NULL
+ * @param [in] appDataSize The size of appData in bytes. Must be 0 if appData is
+ *             NULL
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or path is NULL or if appData
+ *         is NULL and appDataSize is not 0.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_PATH: if path does not map to a FAPI entity.
+ * @retval TSS2_FAPI_RC_STORAGE_ERROR: if the updated data cannot be saved.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_SetAppData_Async(
+    FAPI_CONTEXT  *context,
+    char    const *path,
+    uint8_t const *appData,
+    size_t         appDataSize)
+{
+    LOG_TRACE("called for context:%p", context);
+    LOG_TRACE("path: %s", path);
+    if (appData) {
+        LOGBLOB_TRACE(appData, appDataSize, "appData");
+    } else {
+        LOG_TRACE("appData: (null) appDataSize: %zi", appDataSize);
+    }
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(path);
+
+    /* Check for invalid parameters */
+    if (!appData && appDataSize != 0) {
+        return_error(TSS2_FAPI_RC_BAD_VALUE,
+                     "NULL-pointer passed for appData, though appDataSize != 0.");
+    }
+
+    /* Helpful alias pointers */
+    IFAPI_Path_SetDescription * command = &context->cmd.path_set_info;
+
+    r = ifapi_session_init(context);
+    return_if_error(r, "Initialize SetAppData");
+
+    strdup_check(command->object_path, path, r, error_cleanup);
+
+    if (appDataSize > 0) {
+        command->appData.buffer = malloc(appDataSize);
+        goto_if_null2(command->appData.buffer, "Out of memory.",
+                      r, TSS2_FAPI_RC_MEMORY, error_cleanup);
+
+        memcpy(&command->appData.buffer[0], appData, appDataSize);
+    } else {
+        command->appData.buffer = NULL;
+    }
+    command->appData.size = appDataSize;
+
+    r = ifapi_keystore_load_async(&context->keystore, &context->io, path);
+    return_if_error2(r, "Could not open: %s", path);
+
+    context->state = APP_DATA_SET_READ;
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+
+error_cleanup:
+    SAFE_FREE(command->object_path);
+    SAFE_FREE(command->appData.buffer);
+    return r;
+}
+
+/** Asynchronous finish function for Fapi_SetAppData
+ *
+ * This function should be called after a previous Fapi_SetAppData_Async.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
+ *         complete. Call this function again later.
+ */
+TSS2_RC
+Fapi_SetAppData_Finish(
+    FAPI_CONTEXT *context)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+
+    /* Helpful alias pointers */
+    IFAPI_Path_SetDescription * command = &context->cmd.path_set_info;
+    IFAPI_OBJECT *object = &command->object;
+    UINT8_ARY *objAppData;
+
+    switch (context->state) {
+        statecase(context->state, APP_DATA_SET_READ);
+            r = ifapi_keystore_load_finish(&context->keystore, &context->io, object);
+            return_try_again(r);
+            return_if_error_reset_state(r, "read_finish failed");
+
+            switch (object->objectType) {
+            case IFAPI_KEY_OBJ:
+                objAppData = &object->misc.key.appData;
+                break;
+            case IFAPI_NV_OBJ:
+                objAppData = &object->misc.nv.appData;
+                break;
+            default:
+                goto_error(r, TSS2_FAPI_RC_BAD_PATH, "Object has no app data.", error_cleanup);
+            }
+
+            /* If exists delete old appData */
+            SAFE_FREE(objAppData->buffer);
+
+            /* Set new appData for object */
+            objAppData->size = command->appData.size;
+            objAppData->buffer = command->appData.buffer;
+
+            /* Prepare writing of object */
+            r = ifapi_keystore_store_async(&context->keystore, &context->io,
+                                           command->object_path, object);
+            goto_if_error_reset_state(r, "Could not open: %sh", error_cleanup,
+                                      command->object_path);
+
+            context->state = APP_DATA_SET_WRITE;
+            fallthrough;
+
+        statecase(context->state, APP_DATA_SET_WRITE);
+            /* Finish writing of object */
+            r = ifapi_keystore_store_finish(&context->keystore, &context->io);
+            return_try_again(r);
+            return_if_error_reset_state(r, "write_finish failed");
+            ifapi_cleanup_ifapi_object(object);
+
+            context->state = _FAPI_STATE_INIT;
+            r = TSS2_RC_SUCCESS;
+            break;
+
+        statecasedefault(context->state);
+    }
+
+error_cleanup:
+    ifapi_cleanup_ifapi_object(object);
+    ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
+    ifapi_cleanup_ifapi_object(context->loadKey.key_object);
+    ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
+    SAFE_FREE(command->object_path);
+    LOG_TRACE("finsihed");
+    return r;
+}
diff --git a/src/tss2-fapi/api/Fapi_SetCertificate.c b/src/tss2-fapi/api/Fapi_SetCertificate.c
new file mode 100644
index 0000000..c230eaa
--- /dev/null
+++ b/src/tss2-fapi/api/Fapi_SetCertificate.c
@@ -0,0 +1,240 @@
+/* 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 <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+
+#include "tss2_fapi.h"
+#include "fapi_int.h"
+#include "fapi_util.h"
+#include "tss2_esys.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+#include "fapi_crypto.h"
+
+/** One-Call function for Fapi_SetCertificate
+ *
+ * Sets an x509 cert into the path of a key.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] path The path of the entity to be associated with the
+ *             certificate
+ * @param [in] x509certData The certificate that is associated with the entity.
+ *             If this is NULL an existing certificate will be removed from
+ *             the entity
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or path is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_KEY_NOT_FOUND: if path does not map to a FAPI entity.
+ * @retval TSS2_FAPI_RC_BAD_KEY: if x509certData is invalid.
+ * @retval TSS2_FAPI_RC_STORAGE_ERROR: if the FAPI storage cannot be updated.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_SetCertificate(
+    FAPI_CONTEXT  *context,
+    char    const *path,
+    char    const *x509certData)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(path);
+
+    r = Fapi_SetCertificate_Async(context, path, x509certData);
+    return_if_error_reset_state(r, "Key_SetCertificate");
+
+    do {
+        /* We wait for file I/O to be ready if the FAPI state automata
+           are in a file I/O state. */
+        r = ifapi_io_poll(&context->io);
+        return_if_error(r, "Something went wrong with IO polling");
+
+        /* Repeatedly call the finish function, until FAPI has transitioned
+           through all execution stages / states of this invocation. */
+        r = Fapi_SetCertificate_Finish(context);
+    } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
+
+    return_if_error_reset_state(r, "Key_SetCertificate");
+
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous function for Fapi_SetCertificate
+ *
+ * Sets an x509 cert into the path of a key.
+ *
+ * Call Fapi_SetCertificate_Finish to finish the execution of this command.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] path The path of the entity to be associated with the
+ *             certificate
+ * @param [in] x509certData The certificate that is associated with the entity.
+ *             If this is NULL an existing certificate will be removed from
+ *             the entity
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or path is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_KEY_NOT_FOUND: if path does not map to a FAPI entity.
+ * @retval TSS2_FAPI_RC_BAD_KEY: if x509certData is invalid.
+ * @retval TSS2_FAPI_RC_STORAGE_ERROR: if the FAPI storage cannot be updated.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_SetCertificate_Async(
+    FAPI_CONTEXT  *context,
+    char    const *path,
+    char    const *x509certData)
+{
+    LOG_TRACE("called for context:%p", context);
+    LOG_TRACE("path: %s", path);
+    LOG_TRACE("x509certData: %s", x509certData);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(path);
+
+    /* Helpful alias pointers */
+    IFAPI_Key_SetCertificate * command = &context->cmd.Key_SetCertificate;
+
+    r = ifapi_non_tpm_mode_init(context);
+    goto_if_error(r, "Initialize SetCertificate", error_cleanup);
+
+    command->pem_cert = x509certData;
+    strdup_check(command->key_path, path, r, error_cleanup);
+    context->state =  KEY_SET_CERTIFICATE_READ;
+    memset(&command->key_object, 0, sizeof(IFAPI_OBJECT));
+    r = ifapi_keystore_load_async(&context->keystore, &context->io, path);
+    goto_if_error2(r, "Could not open: %s", error_cleanup, path);
+
+    context->io_state = IO_INIT;
+
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+error_cleanup:
+    SAFE_FREE(command->key_path);
+    return r;
+}
+
+/** Asynchronous finish function for Fapi_SetCertificate
+ *
+ * This function should be called after a previous Fapi_SetCertificate_Async.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
+ *         complete. Call this function again later.
+ */
+TSS2_RC
+Fapi_SetCertificate_Finish(
+    FAPI_CONTEXT  *context)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+
+    /* Helpful alias pointers */
+    IFAPI_Key_SetCertificate * command = &context->cmd.Key_SetCertificate;
+    IFAPI_OBJECT *key_object = &command->key_object;
+    const char ** pem_cert =  &command->pem_cert;
+    char ** pem_cert_dup = &command->pem_cert_dup;
+
+    switch (context->state) {
+        statecase(context->state, KEY_SET_CERTIFICATE_READ)
+            r = ifapi_keystore_load_finish(&context->keystore, &context->io, key_object);
+            return_try_again(r);
+            return_if_error_reset_state(r, "read_finish failed");
+
+            r = ifapi_initialize_object(context->esys, key_object);
+            goto_if_error_reset_state(r, "Initialize NV object", error_cleanup);
+
+            if (!*pem_cert) {
+                strdup_check(*pem_cert_dup, "", r, error_cleanup);
+            } else {
+                strdup_check(*pem_cert_dup, *pem_cert, r, error_cleanup);
+            }
+
+            if (key_object->objectType == IFAPI_EXT_PUB_KEY_OBJ) {
+                SAFE_FREE(key_object->misc.ext_pub_key.certificate);
+                key_object->misc.ext_pub_key.certificate = *pem_cert_dup;
+            } else {
+                SAFE_FREE(key_object->misc.key.certificate);
+                key_object->misc.key.certificate = *pem_cert_dup;
+            }
+
+            /* Perform esys serialization if necessary */
+            r = ifapi_esys_serialize_object(context->esys, key_object);
+            goto_if_error(r, "Prepare serialization", error_cleanup);
+
+            /* Start writing the NV object to the key store */
+            r = ifapi_keystore_store_async(&context->keystore, &context->io,
+                    command->key_path, key_object);
+            goto_if_error_reset_state(r, "Could not open: %sh", error_cleanup,
+                    command->key_path);
+
+            context->state =  KEY_SET_CERTIFICATE_WRITE;
+            fallthrough;
+
+        statecase(context->state, KEY_SET_CERTIFICATE_WRITE)
+            /* Finish writing the object to the key store */
+            r = ifapi_keystore_store_finish(&context->keystore, &context->io);
+            return_try_again(r);
+            return_if_error_reset_state(r, "write_finish failed");
+
+            context->state = _FAPI_STATE_INIT;
+            r = TSS2_RC_SUCCESS;
+            break;
+
+        statecasedefault(context->state);
+    }
+
+error_cleanup:
+    SAFE_FREE(command->key_path);
+    if (key_object->objectType) {
+        ifapi_cleanup_ifapi_object(key_object);
+    }
+    ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
+    ifapi_cleanup_ifapi_object(context->loadKey.key_object);
+    ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
+    LOG_TRACE("finsihed");
+    return r;
+}
diff --git a/src/tss2-fapi/api/Fapi_SetDescription.c b/src/tss2-fapi/api/Fapi_SetDescription.c
new file mode 100644
index 0000000..4d553f3
--- /dev/null
+++ b/src/tss2-fapi/api/Fapi_SetDescription.c
@@ -0,0 +1,234 @@
+/* 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 <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#include "tss2_fapi.h"
+#include "fapi_int.h"
+#include "fapi_util.h"
+#include "tss2_esys.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+/** One-Call function for Fapi_SetDescription
+ *
+ * Associates a human readable description with an object in the metadata store.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] path The path of the object in the metadata store
+ * @param [in] description The description that is associated with the object.
+ *             May be NULL
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or path is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_PATH: if path does not map to a FAPI entity.
+ * @retval TSS2_FAPI_RC_STORAGE_ERROR: if the updated data cannot be saved.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_SetDescription(
+    FAPI_CONTEXT *context,
+    char   const *path,
+    char   const *description)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r, r2;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(path);
+
+    /* Check whether TCTI and ESYS are initialized */
+    return_if_null(context->esys, "Command can't be executed in none TPM mode.",
+                   TSS2_FAPI_RC_NO_TPM);
+
+    /* If the async state automata of FAPI shall be tested, then we must not set
+       the timeouts of ESYS to blocking mode.
+       During testing, the mssim tcti will ensure multiple re-invocations.
+       Usually however the synchronous invocations of FAPI shall instruct ESYS
+       to block until a result is available. */
+#ifndef TEST_FAPI_ASYNC
+    r = Esys_SetTimeout(context->esys, TSS2_TCTI_TIMEOUT_BLOCK);
+    return_if_error_reset_state(r, "Set Timeout to blocking");
+#endif /* TEST_FAPI_ASYNC */
+
+    r = Fapi_SetDescription_Async(context, path, description);
+    return_if_error_reset_state(r, "Path_SetDescription");
+
+    do {
+        /* We wait for file I/O to be ready if the FAPI state automata
+           are in a file I/O state. */
+        r = ifapi_io_poll(&context->io);
+        return_if_error(r, "Something went wrong with IO polling");
+
+        /* Repeatedly call the finish function, until FAPI has transitioned
+           through all execution stages / states of this invocation. */
+        r = Fapi_SetDescription_Finish(context);
+    } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
+
+    /* Reset the ESYS timeout to non-blocking, immediate response. */
+    r2 = Esys_SetTimeout(context->esys, 0);
+    return_if_error(r2, "Set Timeout to non-blocking");
+
+    return_if_error_reset_state(r, "Path_SetDescription");
+
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous function for Fapi_SetDescription
+ *
+ * Associates a human readable description with an object in the metadata store.
+ *
+ * Call Fapi_SetDescription_Finish to finish the execution of this command.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] path The path of the object in the metadata store
+ * @param [in] description The description that is associated with the object.
+ *             May be NULL
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or path is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_PATH: if path does not map to a FAPI entity.
+ * @retval TSS2_FAPI_RC_STORAGE_ERROR: if the updated data cannot be saved.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_SetDescription_Async(
+    FAPI_CONTEXT *context,
+    char   const *path,
+    char   const *description)
+{
+    LOG_TRACE("called for context:%p", context);
+    LOG_TRACE("path: %s", path);
+    LOG_TRACE("description: %s", description);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(path);
+
+    /* Check for invalid parameters */
+    if (description && strlen(description) + 1 > 1024) {
+        return_error(TSS2_FAPI_RC_BAD_VALUE,
+                     "Length of description > 1024");
+    }
+
+    /* Helpful alias pointers */
+    IFAPI_Path_SetDescription * command = &context->cmd.path_set_info;
+
+    strdup_check(command->object_path, path, r, error_cleanup);
+
+    r = ifapi_keystore_load_async(&context->keystore, &context->io, path);
+    goto_if_error2(r, "Could not open: %s", error_cleanup, path);
+
+    if (description == NULL) {
+        command->description = NULL;
+    } else {
+        strdup_check(command->description, description, r, error_cleanup);
+    }
+    context->state =  PATH_SET_DESCRIPTION_READ;
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+
+error_cleanup:
+    SAFE_FREE(command->object_path);
+    SAFE_FREE(command->description);
+    return r;
+}
+
+/** Asynchronous finish function for Fapi_SetDescription
+ *
+ * This function should be called after a previous Fapi_SetDescription_Async.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_PATH_NOT_FOUND If no file is found after pathname expansion.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
+ *         complete. Call this function again later.
+ */
+TSS2_RC
+Fapi_SetDescription_Finish(
+    FAPI_CONTEXT *context)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+
+    /* Helpful alias pointers */
+    IFAPI_Path_SetDescription * command = &context->cmd.path_set_info;
+    IFAPI_OBJECT *object = &command->object;
+
+    switch (context->state) {
+        statecase(context->state, PATH_SET_DESCRIPTION_READ);
+            r = ifapi_keystore_load_finish(&context->keystore, &context->io, object);
+            return_try_again(r);
+            goto_if_error_reset_state(r, "read_finish failed", error_cleanup);
+
+            /* Add new description to object and save object */
+            ifapi_set_description(object, command->description);
+
+            r = ifapi_keystore_store_async(&context->keystore, &context->io,
+                                           command->object_path, object);
+            goto_if_error_reset_state(r, "Could not open: %sh", error_cleanup,
+                                      command->object_path);
+
+            context->state = PATH_SET_DESCRIPTION_WRITE;
+            fallthrough;
+
+        statecase(context->state, PATH_SET_DESCRIPTION_WRITE);
+            r = ifapi_keystore_store_finish(&context->keystore, &context->io);
+            return_try_again(r);
+            return_if_error_reset_state(r, "write_finish failed");
+
+            context->state = _FAPI_STATE_INIT;
+            r = TSS2_RC_SUCCESS;
+            break;
+
+        statecasedefault(context->state);
+    }
+
+error_cleanup:
+    ifapi_cleanup_ifapi_object(object);
+    ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
+    ifapi_cleanup_ifapi_object(context->loadKey.key_object);
+    ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
+    SAFE_FREE(command->object_path);
+    LOG_TRACE("finsihed");
+    return r;
+}
diff --git a/src/tss2-fapi/api/Fapi_Sign.c b/src/tss2-fapi/api/Fapi_Sign.c
new file mode 100644
index 0000000..5ecb5fc
--- /dev/null
+++ b/src/tss2-fapi/api/Fapi_Sign.c
@@ -0,0 +1,293 @@
+/* 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 <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#include "tss2_fapi.h"
+#include "fapi_int.h"
+#include "fapi_util.h"
+#include "fapi_policy.h"
+#include "tss2_esys.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+#include "fapi_crypto.h"
+
+/** One-Call function for Fapi_Sign
+ *
+ * Uses a key, identified by its path, to sign a digest and puts the result in a
+ * TPM2B bytestream.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] keyPath The path of the signature key
+ * @param [in] padding A padding algorithm. Must be either "RSA_SSA" or
+ *             "RSA_PSS" or NULL
+ * @param [in] digest The digest to sign. Must be already hashed
+ * @param [in] digestSize The size of the digest in bytes
+ * @param [out] signature The signature
+ * @param [out] signatureSize The size of signature in bytes. May be NULL
+ * @param [out] publicKey The public key that can be used to verify signature
+ *             in PEM format. May be NULL
+ * @param [out] certificate The certificate associated with the signing key in PEM
+ *             format. May be NULL
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context, keyPath, digest or signature
+ *         is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_KEY_NOT_FOUND: if keyPath does not map to a FAPI key.
+ * @retval TSS2_FAPI_RC_BAD_KEY: if the object at keyPath is not a key, or is a
+ *         key that is unsuitable for the requested operation.
+ * @retval TSS2_FAPI_RC_BAD_VALUE: if the digestSize is zero.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_Sign(
+    FAPI_CONTEXT  *context,
+    char    const *keyPath,
+    char    const *padding,
+    uint8_t const *digest,
+    size_t         digestSize,
+    uint8_t      **signature,
+    size_t        *signatureSize,
+    char         **publicKey,
+    char         **certificate)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r, r2;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(keyPath);
+    check_not_null(digest);
+    check_not_null(signature);
+
+    /* Check whether TCTI and ESYS are initialized */
+    return_if_null(context->esys, "Command can't be executed in none TPM mode.",
+                   TSS2_FAPI_RC_NO_TPM);
+
+    /* If the async state automata of FAPI shall be tested, then we must not set
+       the timeouts of ESYS to blocking mode.
+       During testing, the mssim tcti will ensure multiple re-invocations.
+       Usually however the synchronous invocations of FAPI shall instruct ESYS
+       to block until a result is available. */
+#ifndef TEST_FAPI_ASYNC
+    r = Esys_SetTimeout(context->esys, TSS2_TCTI_TIMEOUT_BLOCK);
+    return_if_error_reset_state(r, "Set Timeout to blocking");
+#endif /* TEST_FAPI_ASYNC */
+
+    r = Fapi_Sign_Async(context, keyPath, padding, digest, digestSize);
+    return_if_error_reset_state(r, "Key_Sign");
+
+    do {
+        /* We wait for file I/O to be ready if the FAPI state automata
+           are in a file I/O state. */
+        r = ifapi_io_poll(&context->io);
+        return_if_error(r, "Something went wrong with IO polling");
+
+        /* Repeatedly call the finish function, until FAPI has transitioned
+           through all execution stages / states of this invocation. */
+        r = Fapi_Sign_Finish(context, signature, signatureSize, publicKey,
+                              certificate);
+    } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
+
+    /* Reset the ESYS timeout to non-blocking, immediate response. */
+    r2 = Esys_SetTimeout(context->esys, 0);
+    return_if_error(r2, "Set Timeout to non-blocking");
+
+    return_if_error_reset_state(r, "Key_Sign");
+
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous function for Fapi_Sign
+ *
+ * Uses a key, identified by its path, to sign a digest and puts the result in a
+ * TPM2B bytestream.
+ *
+ * Call Fapi_Sign_Finish to finish the execution of this command.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] keyPath The path of the signature key
+ * @param [in] padding A padding algorithm. Must be either "RSA_SSA" or
+ *             "RSA_PSS" or NULL
+ * @param [in] digest The digest to sign. Must be already hashed
+ * @param [in] digestSize The size of the digest in bytes
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context, keyPath or digest
+ *         is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_KEY_NOT_FOUND: if keyPath does not map to a FAPI key.
+ * @retval TSS2_FAPI_RC_BAD_KEY: if the object at keyPath is not a key, or is a
+ *         key that is unsuitable for the requested operation.
+ * @retval TSS2_FAPI_RC_BAD_VALUE: if the digestSize is zero.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_Sign_Async(
+    FAPI_CONTEXT  *context,
+    char    const *keyPath,
+    char    const *padding,
+    uint8_t const *digest,
+    size_t         digestSize)
+{
+    LOG_TRACE("called for context:%p", context);
+    LOG_TRACE("keyPath: %s", keyPath);
+    LOG_TRACE("padding: %s", padding);
+    if (digest) {
+        LOGBLOB_TRACE(digest, digestSize, "digest");
+    } else {
+        LOG_TRACE("digest: (null) digestSize: %zi", digestSize);
+    }
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(keyPath);
+    check_not_null(digest);
+
+    /* Check for invalid parameters */
+    if (padding) {
+        if (strcasecmp("RSA_SSA", padding) != 0 &&
+                strcasecmp("RSA_PSS", padding) != 0) {
+            return_error(TSS2_FAPI_RC_BAD_VALUE,
+                    "Only padding RSA_SSA or RSA_PSS allowed.");
+        }
+    }
+
+    /* Helpful alias pointers */
+    IFAPI_Key_Sign * command = &context->Key_Sign;
+
+    r = ifapi_session_init(context);
+    return_if_error(r, "Initialize Sign");
+
+    FAPI_COPY_DIGEST(&command->digest.buffer[0],
+                     command->digest.size, digest, digestSize);
+    r = ifapi_session_init(context);
+    return_if_error(r, "Initialize Key_Sign");
+
+    strdup_check(command->keyPath, keyPath, r, error_cleanup);
+    strdup_check(command->padding, padding, r, error_cleanup);
+    context->state = KEY_SIGN_WAIT_FOR_KEY;
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+error_cleanup:
+    SAFE_FREE(command->keyPath);
+    SAFE_FREE(command->padding);
+    return r;
+}
+
+/** Asynchronous finish function for Fapi_Sign
+ *
+ * This function should be called after a previous Fapi_Sign_Async.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [out] signature The signature
+ * @param [out] signatureSize The size of signature in bytes. May be NULL
+ * @param [out] publicKey The public key that can be used to verify signature
+ *             in PEM format. May be NULL
+ * @param [out] certificate The certificate associated with the signing key in PEM
+ *             format. May be NULL
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or signature is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
+ *         complete. Call this function again later.
+ */
+TSS2_RC
+Fapi_Sign_Finish(
+    FAPI_CONTEXT *context,
+    uint8_t     **signature,
+    size_t       *signatureSize,
+    char        **publicKey,
+    char        **certificate)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+    size_t resultSignatureSize;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(signature);
+
+    /* Helpful alias pointers */
+    IFAPI_Key_Sign * command = &context->Key_Sign;
+
+    switch (context->state) {
+        statecase(context->state, KEY_SIGN_WAIT_FOR_KEY);
+            r = ifapi_load_key(context,  command->keyPath,
+                               &command->key_object);
+            return_try_again(r);
+            goto_if_error(r, "Fapi load key.", error_cleanup);
+
+            context->state = KEY_SIGN_WAIT_FOR_SIGN;
+            fallthrough;
+
+        statecase(context->state, KEY_SIGN_WAIT_FOR_SIGN);
+            r = ifapi_key_sign(context, command->key_object,
+                    command->padding, &command->digest, &command->tpm_signature,
+                    publicKey, certificate);
+            return_try_again(r);
+            goto_if_error(r, "Fapi sign.", error_cleanup);
+
+
+            r = ifapi_tpm_to_fapi_signature(command->key_object,
+                     command->tpm_signature, signature, &resultSignatureSize);
+            goto_if_error(r, "Create FAPI signature.", error_cleanup);
+
+            if (signatureSize)
+                *signatureSize = resultSignatureSize;
+            fallthrough;
+
+        statecase(context->state, KEY_SIGN_CLEANUP)
+            r = ifapi_cleanup_session(context);
+            try_again_or_error_goto(r, "Cleanup", error_cleanup);
+
+            context->state = _FAPI_STATE_INIT;
+            break;
+
+        statecasedefault(context->state);
+    }
+
+error_cleanup:
+    SAFE_FREE(command->tpm_signature);
+    SAFE_FREE(command->keyPath);
+    SAFE_FREE(command->padding);
+    ifapi_session_clean(context);
+    ifapi_cleanup_ifapi_object(command->key_object);
+    ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
+    ifapi_cleanup_ifapi_object(context->loadKey.key_object);
+    ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
+    LOG_TRACE("finsihed");
+    return r;
+}
diff --git a/src/tss2-fapi/api/Fapi_Unseal.c b/src/tss2-fapi/api/Fapi_Unseal.c
new file mode 100644
index 0000000..8f14fb1
--- /dev/null
+++ b/src/tss2-fapi/api/Fapi_Unseal.c
@@ -0,0 +1,258 @@
+/* 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 <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#include "tss2_fapi.h"
+#include "fapi_int.h"
+#include "fapi_util.h"
+#include "fapi_policy.h"
+#include "tss2_esys.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+#include "fapi_crypto.h"
+
+/** One-Call function for Fapi_Unseal
+ *
+ * Unseals data from a seal in the FAPI metadata store.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] path The path to the sealed data
+ * @param [out] data The decrypted data after unsealing. May be NULL
+ * @param [out] size The size of data in bytes. May be NULL
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or path is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_PATH: if path does not point to a sealed data object.
+ * @retval TSS2_FAPI_RC_BAD_VALUE: if the digestSize is zero.
+ * @retval TSS2_FAPI_RC_STORAGE_ERROR: if the FAPI storage cannot be accessed.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_Unseal(
+    FAPI_CONTEXT  *context,
+    char    const *path,
+    uint8_t      **data,
+    size_t        *size)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r, r2;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(path);
+
+    /* Check whether TCTI and ESYS are initialized */
+    return_if_null(context->esys, "Command can't be executed in none TPM mode.",
+                   TSS2_FAPI_RC_NO_TPM);
+
+    /* If the async state automata of FAPI shall be tested, then we must not set
+       the timeouts of ESYS to blocking mode.
+       During testing, the mssim tcti will ensure multiple re-invocations.
+       Usually however the synchronous invocations of FAPI shall instruct ESYS
+       to block until a result is available. */
+#ifndef TEST_FAPI_ASYNC
+    r = Esys_SetTimeout(context->esys, TSS2_TCTI_TIMEOUT_BLOCK);
+    return_if_error_reset_state(r, "Set Timeout to blocking");
+#endif /* TEST_FAPI_ASYNC */
+
+    r = Fapi_Unseal_Async(context, path);
+    return_if_error_reset_state(r, "Unseal");
+
+    do {
+        /* We wait for file I/O to be ready if the FAPI state automata
+           are in a file I/O state. */
+        r = ifapi_io_poll(&context->io);
+        return_if_error(r, "Something went wrong with IO polling");
+
+        /* Repeatedly call the finish function, until FAPI has transitioned
+           through all execution stages / states of this invocation. */
+        r = Fapi_Unseal_Finish(context, data, size);
+    } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
+
+    /* Reset the ESYS timeout to non-blocking, immediate response. */
+    r2 = Esys_SetTimeout(context->esys, 0);
+    return_if_error(r2, "Set Timeout to non-blocking");
+
+    return_if_error_reset_state(r, "Unseal");
+
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous function for Fapi_Unseal
+ *
+ * Unseals data from a seal in the FAPI metadata store.
+ *
+ * Call Fapi_Unseal_Finish to finish the execution of this command.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] path The path to the sealed data
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or path is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_PATH: if path does not point to a sealed data object.
+ * @retval TSS2_FAPI_RC_BAD_VALUE: if the digestSize is zero.
+ * @retval TSS2_FAPI_RC_STORAGE_ERROR: if the FAPI storage cannot be accessed.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_Unseal_Async(
+    FAPI_CONTEXT  *context,
+    char    const *path)
+{
+    LOG_TRACE("called for context:%p", context);
+    LOG_TRACE("path: %s", path);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(path);
+
+    /* Helpful alias pointers */
+    IFAPI_Unseal * command = &context->cmd.Unseal;
+
+    r = ifapi_session_init(context);
+    return_if_error(r, "Initialize Unseal");
+
+    strdup_check(command->keyPath, path, r, error_cleanup);
+    context->state = UNSEAL_WAIT_FOR_KEY;
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+error_cleanup:
+    SAFE_FREE(command->keyPath);
+    return r;
+}
+
+/** Asynchronous finish function for Fapi_Unseal
+ *
+ * This function should be called after a previous Fapi_Unseal_Async.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [out] data The decrypted data after unsealing. May be NULL
+ * @param [out] size The size of data in bytes. May be NULL
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
+ *         complete. Call this function again later.
+ */
+TSS2_RC
+Fapi_Unseal_Finish(
+    FAPI_CONTEXT *context,
+    uint8_t     **data,
+    size_t       *size)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+    ESYS_TR auth_session;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+
+    /* Helpful alias pointers */
+    IFAPI_Unseal * command = &context->cmd.Unseal;
+
+    switch (context->state) {
+        statecase(context->state, UNSEAL_WAIT_FOR_KEY);
+            r = ifapi_load_key(context, command->keyPath,
+                               &command->object);
+            return_try_again(r);
+            goto_if_error(r, "Fapi load key.", error_cleanup);
+
+            context->state = UNSEAL_AUTHORIZE_OBJECT;
+            fallthrough;
+
+        statecase(context->state, UNSEAL_AUTHORIZE_OBJECT);
+            r = ifapi_authorize_object(context, command->object, &auth_session);
+            return_try_again(r);
+            goto_if_error(r, "Authorize sealed object.", error_cleanup);
+
+            r = Esys_Unseal_Async(context->esys, command->object->handle,
+                    auth_session,
+                    ESYS_TR_NONE, ESYS_TR_NONE);
+            goto_if_error(r, "Error esys Unseal ", error_cleanup);
+
+            context->state = UNSEAL_WAIT_FOR_UNSEAL;
+            fallthrough;
+
+        statecase(context->state, UNSEAL_WAIT_FOR_UNSEAL);
+            r = Esys_Unseal_Finish(context->esys, &command->unseal_data);
+            return_try_again(r);
+            goto_if_error(r, "Unseal_Finish", error_cleanup);
+
+            r = Esys_FlushContext_Async(context->esys, command->object->handle);
+            goto_if_error(r, "Error Esys Flush ", error_cleanup);
+
+            context->state = UNSEAL_WAIT_FOR_FLUSH;
+            fallthrough;
+
+        statecase(context->state, UNSEAL_WAIT_FOR_FLUSH);
+            r = Esys_FlushContext_Finish(context->esys);
+            return_try_again(r);
+            goto_if_error(r, "Unseal_Flush", error_cleanup);
+
+            if (size)
+                *size = command->unseal_data->size;
+            if (data) {
+                *data = malloc(command->unseal_data->size);
+                goto_if_null2(*data, "Out of memory", r, TSS2_FAPI_RC_MEMORY, error_cleanup);
+
+                memcpy(*data, &command->unseal_data->buffer[0],
+                       command->unseal_data->size);
+            }
+            SAFE_FREE(command->unseal_data);
+
+            fallthrough;
+
+        statecase(context->state, UNSEAL_CLEANUP)
+            r = ifapi_cleanup_session(context);
+            try_again_or_error_goto(r, "Cleanup", error_cleanup);
+
+            context->state = _FAPI_STATE_INIT;
+            break;
+
+        statecasedefault(context->state);
+    }
+
+error_cleanup:
+    ifapi_cleanup_ifapi_object(command->object);
+    ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
+    ifapi_cleanup_ifapi_object(context->loadKey.key_object);
+    ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
+    ifapi_session_clean(context);
+    SAFE_FREE(command->keyPath);
+    LOG_TRACE("finsihed");
+    return r;
+}
diff --git a/src/tss2-fapi/api/Fapi_VerifyQuote.c b/src/tss2-fapi/api/Fapi_VerifyQuote.c
new file mode 100644
index 0000000..c385def
--- /dev/null
+++ b/src/tss2-fapi/api/Fapi_VerifyQuote.c
@@ -0,0 +1,298 @@
+/* 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 <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#include "tss2_fapi.h"
+#include "fapi_int.h"
+#include "fapi_util.h"
+#include "tss2_esys.h"
+#include "fapi_crypto.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+/** One-Call function for Fapi_VerifyQuote
+ *
+ * Verifies that the data returned by a quote is valid.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] publicKeyPath The path to the signing key
+ * @param [in] qualifyingData The qualifying data nonce. May be NULL
+ * @param [in] qualifyingDataSize The size of qualifyingData in bytes. Must be 0
+ *             if qualifyingData is NULL
+ * @param [in] quoteInfo The quote information
+ * @param [in] signature The quote's signature
+ * @param [in] signatureSize The size of signature in bytes
+ * @param [in] pcrLog The PCR's log. May be NULL
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context, publicKeyPath, quoteInfo,
+ *         or signature is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_KEY_NOT_FOUND: if path does not map to a FAPI entity.
+ * @retval TSS2_FAPI_RC_BAD_KEY: if the entity at path is not a key, or is a key
+ *         that is unsuitable for the requested operation.
+ * @retval TSS2_FAPI_RC_BAD_VALUE: if quoteInfo, pcrEventLog, qualifyingData, or
+ *         signature is invalid.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_VerifyQuote(
+    FAPI_CONTEXT  *context,
+    char    const *publicKeyPath,
+    uint8_t const *qualifyingData,
+    size_t         qualifyingDataSize,
+    char    const *quoteInfo,
+    uint8_t const *signature,
+    size_t         signatureSize,
+    char           const *pcrLog)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(publicKeyPath);
+    check_not_null(quoteInfo);
+    check_not_null(signature);
+
+    r = Fapi_VerifyQuote_Async(context, publicKeyPath,
+                               qualifyingData, qualifyingDataSize,
+                               quoteInfo, signature,
+                               signatureSize, pcrLog);
+    return_if_error_reset_state(r, "Key_VerifyQuote");
+
+    do {
+        /* We wait for file I/O to be ready if the FAPI state automata
+           are in a file I/O state. */
+        r = ifapi_io_poll(&context->io);
+        return_if_error(r, "Something went wrong with IO polling");
+
+        /* Repeatedly call the finish function, until FAPI has transitioned
+           through all execution stages / states of this invocation. */
+        r = Fapi_VerifyQuote_Finish(context);
+    } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
+
+    return_if_error_reset_state(r, "Key_VerifyQuote");
+
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous function for Fapi_VerifyQuote
+ *
+ * Verifies that the data returned by a quote is valid.
+ * Call Fapi_VerifyQuote_Finish to finish the execution of this command.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] publicKeyPath The path to the signing key
+ * @param [in] qualifyingData The qualifying data nonce. May be NULL
+ * @param [in] qualifyingDataSize The size of qualifyingData in bytes. Must be 0
+ *             if qualifyingData is NULL
+ * @param [in] quoteInfo The quote information
+ * @param [in] signature The quote's signature
+ * @param [in] signatureSize The size of signature in bytes
+ * @param [in] pcrLog The PCR's log. May be NULL
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context, publicKeyPath, quoteInfo,
+ *         or signature is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_KEY_NOT_FOUND: if path does not map to a FAPI entity.
+ * @retval TSS2_FAPI_RC_BAD_KEY: if the entity at path is not a key, or is a key
+ *         that is unsuitable for the requested operation.
+ * @retval TSS2_FAPI_RC_BAD_VALUE: if quoteInfo, pcrEventLog, qualifyingData, or
+ *         signature is invalid.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_VerifyQuote_Async(
+    FAPI_CONTEXT  *context,
+    char    const *publicKeyPath,
+    uint8_t const *qualifyingData,
+    size_t         qualifyingDataSize,
+    char    const *quoteInfo,
+    uint8_t const *signature,
+    size_t         signatureSize,
+    char    const *pcrLog)
+{
+    LOG_TRACE("called for context:%p", context);
+    LOG_TRACE("publicKeyPath: %s", publicKeyPath);
+    if (qualifyingData) {
+        LOGBLOB_TRACE(qualifyingData, qualifyingDataSize, "qualifyingData");
+    } else {
+        LOG_TRACE("qualifyingData: (null) qualifyingDataSize: %zi", qualifyingDataSize);
+    }
+    LOG_TRACE("quoteInfo: %s", quoteInfo);
+    if (signature) {
+        LOGBLOB_TRACE(signature, signatureSize, "signature");
+    } else {
+        LOG_TRACE("signature: (null) signatureSize: %zi", signatureSize);
+    }
+    LOG_TRACE("pcrLog: %s", pcrLog);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(publicKeyPath);
+    check_not_null(quoteInfo);
+    check_not_null(signature);
+
+    /* Check for invalid parameters */
+    if (qualifyingData == NULL && qualifyingDataSize != 0) {
+        LOG_ERROR("qualifyingData is NULL but qualifyingDataSize is not 0");
+        return TSS2_FAPI_RC_BAD_VALUE;
+    }
+
+    /* Helpful alias pointers */
+    IFAPI_PCR * command = &context->cmd.pcr;
+
+    r = ifapi_non_tpm_mode_init(context);
+    return_if_error(r, "Initialize VerifyQuote");
+
+
+    uint8_t * signatureBuffer = malloc(signatureSize);
+    goto_if_null2(signatureBuffer, "Out of memory",
+            r, TSS2_FAPI_RC_MEMORY, error_cleanup);
+    memcpy(signatureBuffer, signature, signatureSize);
+    command->signature = signatureBuffer;
+    command->signatureSize = signatureSize;
+
+    strdup_check(command->keyPath, publicKeyPath, r, error_cleanup);
+    strdup_check(command->quoteInfo, quoteInfo, r, error_cleanup);
+    strdup_check(command->logData, pcrLog, r, error_cleanup);
+
+    if (qualifyingData != NULL) {
+        FAPI_COPY_DIGEST(&command->qualifyingData.buffer[0],
+                command->qualifyingData.size,
+                qualifyingData, qualifyingDataSize);
+    }
+
+    r = ifapi_keystore_load_async(&context->keystore, &context->io, publicKeyPath);
+    return_if_error2(r, "Could not open: %s", publicKeyPath);
+
+    context->state = VERIFY_QUOTE_READ;
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+error_cleanup:
+    SAFE_FREE(command->keyPath);
+    SAFE_FREE(signatureBuffer);
+    command->signature = NULL;
+    SAFE_FREE(command->quoteInfo);
+    SAFE_FREE(command->logData);
+    return r;
+}
+
+/** Asynchronous finish function for Fapi_VerifyQuote
+ *
+ * This function should be called after a previous Fapi_VerifyQuote_Async.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
+ *         complete. Call this function again later.
+ */
+TSS2_RC
+Fapi_VerifyQuote_Finish(
+    FAPI_CONTEXT  *context)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+    IFAPI_OBJECT key_object;
+    TPM2B_ATTEST attest2b;
+    TPM2B_DIGEST pcr_digest;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+
+    /* Helpful alias pointers */
+    IFAPI_PCR * command = &context->cmd.pcr;
+
+    memset(&key_object, 0, sizeof(IFAPI_OBJECT));
+
+    switch(context->state) {
+        statecase(context->state, VERIFY_QUOTE_READ);
+            r = ifapi_keystore_load_finish(&context->keystore, &context->io, &key_object);
+            return_try_again(r);
+            return_if_error_reset_state(r, "read_finish failed");
+
+            r = ifapi_initialize_object(context->esys, &key_object);
+            goto_if_error_reset_state(r, "Initialize public key  object", error_cleanup);
+
+            r = ifapi_get_quote_info(command->quoteInfo, &attest2b,
+                                     &command->fapi_quote_info);
+            goto_if_error(r, "Get quote info.", error_cleanup);
+
+            r = ifapi_verify_signature_quote(&key_object,
+                                             command->signature,
+                                             command->signatureSize,
+                                             &attest2b.attestationData[0],
+                                             attest2b.size,
+                                             &command->fapi_quote_info.sig_scheme);
+            goto_if_error(r, "Verify signature.", error_cleanup);
+
+            if (!command->logData) {
+                context->state =  _FAPI_STATE_INIT;
+                break;
+            }
+
+            command->event_list = json_tokener_parse(context->cmd.pcr.logData);
+            return_if_null(command->event_list, "Json error.", TSS2_FAPI_RC_BAD_VALUE);
+
+            r  = ifapi_calculate_pcr_digest(command->event_list,
+                                            &command->fapi_quote_info, &pcr_digest);
+
+            goto_if_error(r, "Verify event list.", error_cleanup);
+
+            context->state =  _FAPI_STATE_INIT;
+            break;
+
+        statecasedefault(context->state);
+    }
+
+error_cleanup:
+    if (key_object.objectType)
+        ifapi_cleanup_ifapi_object(&key_object);
+    if (command->event_list)
+        json_object_put(command->event_list);
+    ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
+    ifapi_cleanup_ifapi_object(context->loadKey.key_object);
+    ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
+    SAFE_FREE(command->keyPath);
+    SAFE_FREE(command->signature);
+    SAFE_FREE(command->quoteInfo);
+    SAFE_FREE(command->logData);
+    LOG_TRACE("finsihed");
+    return r;
+}
diff --git a/src/tss2-fapi/api/Fapi_VerifySignature.c b/src/tss2-fapi/api/Fapi_VerifySignature.c
new file mode 100644
index 0000000..0dd37c2
--- /dev/null
+++ b/src/tss2-fapi/api/Fapi_VerifySignature.c
@@ -0,0 +1,240 @@
+/* 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 <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#include "tss2_fapi.h"
+#include "fapi_crypto.h"
+#include "fapi_int.h"
+#include "fapi_util.h"
+#include "tss2_esys.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+/** One-Call function for Fapi_VerifySignature
+ *
+ * Verifies a signature using a public key found in a keyPath.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] keyPath The path to the verification public key
+ * @param [in] digest The that was signed. Must be already hashed
+ * @param [in] digestSize the size of digest in bytes
+ * @param [in] signature The signature to be verified
+ * @param [in] signatureSize The size of signature in bytes
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context, keyPath, signature, or
+ *         digest is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_KEY_NOT_FOUND: if keyPath does not map to a FAPI object.
+ * @retval TSS2_FAPI_RC_BAD_KEY: if the object at publicKeyPath is not a key, or
+ *         is a key that is unsuitable for the requested operation.
+ * @retval TSS2_FAPI_RC_BAD_VALUE: if signature is invalid (has the wrong format)
+ *         or if digestSize is zero.
+ * @retval TSS2_FAPI_RC_SIGNATURE_VERIFICATION_FAILED: if the signature fails to
+ *         verify.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_VerifySignature(
+    FAPI_CONTEXT  *context,
+    char    const *keyPath,
+    uint8_t const *digest,
+    size_t         digestSize,
+    uint8_t const *signature,
+    size_t         signatureSize)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(keyPath);
+    check_not_null(digest);
+    check_not_null(signature);
+
+    r = Fapi_VerifySignature_Async(context, keyPath, digest, digestSize,
+                                   signature, signatureSize);
+    return_if_error_reset_state(r, "Key_VerifySignature");
+
+    do {
+        /* We wait for file I/O to be ready if the FAPI state automata
+           are in a file I/O state. */
+        r = ifapi_io_poll(&context->io);
+        return_if_error(r, "Something went wrong with IO polling");
+
+        /* Repeatedly call the finish function, until FAPI has transitioned
+           through all execution stages / states of this invocation. */
+        r = Fapi_VerifySignature_Finish(context);
+    } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
+
+    return_if_error_reset_state(r, "Key_VerifySignature");
+
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous function for Fapi_VerifySignature
+ *
+ * Verifies a signature using a public key found in a keyPath.
+ *
+ * Call Fapi_VerifySignature_Finish to finish the execution of this command.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] keyPath The path to the verification public key
+ * @param [in] digest The that was signed. Must be already hashed
+ * @param [in] digestSize the size of digest in bytes
+ * @param [in] signature The signature to be verified
+ * @param [in] signatureSize The size of signature in bytes
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context, keyPath, signature, or
+ *         digest is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_KEY_NOT_FOUND: if keyPath does not map to a FAPI object.
+ * @retval TSS2_FAPI_RC_BAD_KEY: if the object at publicKeyPath is not a key, or
+ *         is a key that is unsuitable for the requested operation.
+ * @retval TSS2_FAPI_RC_BAD_VALUE: if signature is invalid (has the wrong format)
+ *         or if digestSize is zero.
+ * @retval TSS2_FAPI_RC_SIGNATURE_VERIFICATION_FAILED: if the signature fails to
+ *         verify.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_VerifySignature_Async(
+    FAPI_CONTEXT  *context,
+    char    const *keyPath,
+    uint8_t const *digest,
+    size_t         digestSize,
+    uint8_t const *signature,
+    size_t         signatureSize)
+{
+    LOG_TRACE("called for context:%p", context);
+    LOG_TRACE("keyPath: %s", keyPath);
+    if (digest) {
+        LOGBLOB_TRACE(digest, digestSize, "digest");
+    } else {
+        LOG_TRACE("digset: (null) digestSize: %zi", digestSize);
+    }
+    if (signature) {
+        LOGBLOB_TRACE(signature, signatureSize, "signature");
+    } else {
+        LOG_TRACE("signature: (null) sigantureSize: %zi", signatureSize);
+    }
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(keyPath);
+    check_not_null(digest);
+    check_not_null(signature);
+
+    /* Helpful alias pointers */
+    IFAPI_Key_VerifySignature * command = &context->cmd.Key_VerifySignature;
+
+    r = ifapi_non_tpm_mode_init(context);
+    return_if_error(r, "Initialize VerifySignature");
+
+    uint8_t * signatureBuffer = malloc(signatureSize);
+    uint8_t * digestBuffer = malloc(digestSize);
+    goto_if_null2(signatureBuffer, "Out of memory", r, TSS2_FAPI_RC_MEMORY,
+            error_cleanup);
+    goto_if_null2(digestBuffer, "Out of memory", r, TSS2_FAPI_RC_MEMORY,
+            error_cleanup);
+    memcpy(signatureBuffer, signature, signatureSize);
+    memcpy(digestBuffer, digest, digestSize);
+    command->signature = signatureBuffer;
+    command->digest = digestBuffer;
+    command->signatureSize = signatureSize;
+    command->digestSize = digestSize;
+    memset(&command->key_object, 0, sizeof(IFAPI_OBJECT));
+
+    r = ifapi_keystore_load_async(&context->keystore, &context->io, keyPath);
+    goto_if_error2(r, "Could not open: %s", error_cleanup, keyPath);
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+error_cleanup:
+    SAFE_FREE(signatureBuffer);
+    command->signature = NULL;
+    SAFE_FREE(digestBuffer);
+    command->digest = NULL;
+    return r;
+}
+
+/** Asynchronous finish function for Fapi_VerifySignature
+ *
+ * This function should be called after a previous Fapi_VerifySignature_Async.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
+ *         complete. Call this function again later.
+ */
+TSS2_RC
+Fapi_VerifySignature_Finish(
+    FAPI_CONTEXT  *context)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+
+    /* Helpful alias pointers */
+    IFAPI_Key_VerifySignature * command = &context->cmd.Key_VerifySignature;
+
+    r = ifapi_keystore_load_finish(&context->keystore, &context->io,
+                                   &command->key_object);
+    return_try_again(r);
+    return_if_error_reset_state(r, "read_finish failed");
+
+    r = ifapi_initialize_object(context->esys,
+                                &command->key_object);
+    goto_if_error_reset_state(r, "Initialize key object", cleanup);
+
+    goto_if_error(r, "Deserialize key.", cleanup);
+    r = ifapi_verify_signature(&command->key_object, command->signature,
+           command->signatureSize, command->digest, command->digestSize);
+
+cleanup:
+    if (command->key_object.objectType)
+        ifapi_cleanup_ifapi_object(&command->key_object);
+    ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
+    ifapi_cleanup_ifapi_object(context->loadKey.key_object);
+    ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
+    SAFE_FREE(command->signature);
+    SAFE_FREE(command->digest);
+    LOG_TRACE("finsihed");
+    return r;
+}
diff --git a/src/tss2-fapi/api/Fapi_WriteAuthorizeNV.c b/src/tss2-fapi/api/Fapi_WriteAuthorizeNV.c
new file mode 100644
index 0000000..fe8c54a
--- /dev/null
+++ b/src/tss2-fapi/api/Fapi_WriteAuthorizeNV.c
@@ -0,0 +1,323 @@
+/* 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 "tss2_mu.h"
+#include "tss2_fapi.h"
+#include "fapi_int.h"
+#include "fapi_util.h"
+#include "tss2_esys.h"
+#include "fapi_policy.h"
+#include "fapi_crypto.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+/** One-Call function for Fapi_WriteAuthorizeNv
+ *
+ * Write the policyDigest of a policy to an NV index so it can be used in policies
+ * containing PolicyAuthorizeNV elements.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] nvPath The path of the NV index
+ * @param [in] policyPath The path of the new policy
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or path is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_PATH: if nvPath or policyPath does not map to a
+ *         FAPI policy or NV index.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory
+           for internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_WriteAuthorizeNv(
+    FAPI_CONTEXT  *context,
+    char    const *nvPath,
+    char    const *policyPath)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r, r2;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(nvPath);
+    check_not_null(policyPath);
+
+    /* Check whether TCTI and ESYS are initialized */
+    return_if_null(context->esys, "Command can't be executed in none TPM mode.",
+                   TSS2_FAPI_RC_NO_TPM);
+
+    /* If the async state automata of FAPI shall be tested, then we must not set
+       the timeouts of ESYS to blocking mode.
+       During testing, the mssim tcti will ensure multiple re-invocations.
+       Usually however the synchronous invocations of FAPI shall instruct ESYS
+       to block until a result is available. */
+#ifndef TEST_FAPI_ASYNC
+    r = Esys_SetTimeout(context->esys, TSS2_TCTI_TIMEOUT_BLOCK);
+    return_if_error_reset_state(r, "Set Timeout to blocking");
+#endif /* TEST_FAPI_ASYNC */
+
+    r = Fapi_WriteAuthorizeNv_Async(context, nvPath, policyPath);
+    return_if_error_reset_state(r, "WriteAuthorizeNV");
+
+    do {
+        /* We wait for file I/O to be ready if the FAPI state automata
+           are in a file I/O state. */
+        r = ifapi_io_poll(&context->io);
+        return_if_error(r, "Something went wrong with IO polling");
+
+        /* Repeatedly call the finish function, until FAPI has transitioned
+           through all execution stages / states of this invocation. */
+        r = Fapi_WriteAuthorizeNv_Finish(context);
+    } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
+
+    /* Reset the ESYS timeout to non-blocking, immediate response. */
+    r2 = Esys_SetTimeout(context->esys, 0);
+    return_if_error(r2, "Set Timeout to non-blocking");
+
+    return_if_error_reset_state(r, "WriteAuthorizeNV");
+
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous function for Fapi_WriteAuthorizeNv
+ *
+ * Write the policyDigest of a policy to an NV index so it can be used in policies
+ * containing PolicyAuthorizeNV elements.
+ *
+ * Call Fapi_WriteAuthorizeNv_Finish to finish the execution of this command.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] nvPath The path of the NV index
+ * @param [in] policyPath The path of the new policy
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or path is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_PATH: if nvPath or policyPath does not map to a
+ *         FAPI policy or NV index.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory
+           for internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ */
+TSS2_RC
+Fapi_WriteAuthorizeNv_Async(
+    FAPI_CONTEXT  *context,
+    char    const *nvPath,
+    char    const *policyPath)
+{
+    LOG_TRACE("called for context:%p", context);
+    LOG_TRACE("nvPath: %s", nvPath);
+    LOG_TRACE("policyPath: %s", policyPath);
+
+    TSS2_RC r;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(nvPath);
+    check_not_null(policyPath);
+
+    /* Helpful alias pointers */
+    IFAPI_api_WriteAuthorizeNv * command = &context->cmd.WriteAuthorizeNV;
+    IFAPI_NV_Cmds * nvCmd = &context->nv_cmd;
+
+    r = ifapi_session_init(context);
+    return_if_error(r, "Initialize WriterAuthorizeNv");
+
+    strdup_check(command->policyPath, policyPath, r, error_cleanup);
+    strdup_check(nvCmd->nvPath, nvPath, r, error_cleanup);
+
+    r = ifapi_keystore_load_async(&context->keystore, &context->io, nvCmd->nvPath);
+    goto_if_error2(r, "Could not open: %s", error_cleanup, nvCmd->nvPath);
+
+    context->state = WRITE_AUTHORIZE_NV_READ_NV;
+    LOG_TRACE("finsihed");
+    return TSS2_RC_SUCCESS;
+error_cleanup:
+    SAFE_FREE(command->policyPath);
+    SAFE_FREE(nvCmd->nvPath);
+    return r;
+}
+
+/** Asynchronous finish function for Fapi_WriteAuthorizeNv
+ *
+ * This function should be called after a previous Fapi_WriteAuthorizeNv_Async.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
+ *         complete. Call this function again later.
+ */
+TSS2_RC
+Fapi_WriteAuthorizeNv_Finish(
+    FAPI_CONTEXT  *context)
+{
+    LOG_TRACE("called for context:%p", context);
+
+    TSS2_RC r;
+    const size_t maxNvSize = sizeof(TPMU_HA) + sizeof(TPMI_ALG_HASH);
+    BYTE nvBuffer[maxNvSize];
+    size_t offset = 0;
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+
+    /* Helpful alias pointers */
+    IFAPI_api_WriteAuthorizeNv * command = &context->cmd.WriteAuthorizeNV;
+    IFAPI_NV_Cmds * nvCmd = &context->nv_cmd;
+    IFAPI_OBJECT *object = &nvCmd->nv_object;
+    TPMI_ALG_HASH hashAlg;
+    TPMS_POLICY_HARNESS * policyHarness = &context->policy.harness;
+
+    switch (context->state) {
+        statecase(context->state, WRITE_AUTHORIZE_NV_READ_NV)
+            /* First check whether the file in object store can be updated. */
+            r = ifapi_keystore_check_writeable(&context->keystore, &context->io,
+                    nvCmd->nvPath);
+            goto_if_error_reset_state(r,
+                    "Check whether update object store is possible.", error_cleanup);
+
+            r = ifapi_keystore_load_finish(&context->keystore, &context->io, object);
+            return_try_again(r);
+            return_if_error_reset_state(r, "read_finish failed");
+
+            ifapi_cleanup_ifapi_object(object);
+            r = ifapi_initialize_object(context->esys, object);
+            goto_if_error_reset_state(r, "Initialize NV object", error_cleanup);
+
+            context->state = WRITE_AUTHORIZE_NV_CALCULATE_POLICY;
+            fallthrough;
+
+        statecase(context->state, WRITE_AUTHORIZE_NV_CALCULATE_POLICY)
+            hashAlg = object->misc.nv.public.nvPublic.nameAlg;
+            r = ifapi_calculate_tree(context, command->policyPath,
+                    policyHarness, hashAlg, &command->digest_idx,
+                    &command->hash_size);
+            if (r != TSS2_RC_SUCCESS) {
+                ifapi_cleanup_ifapi_object(object);
+            }
+            return_try_again(r);
+            goto_if_error(r, "Fapi calculate tree.", error_cleanup);
+
+            r = ifapi_get_sessions_async(context, IFAPI_SESSION_GENEK | IFAPI_SESSION1,
+                    TPMA_SESSION_DECRYPT, 0);
+            goto_if_error_reset_state(r, "Create sessions", error_cleanup);
+
+            context->state = WRITE_AUTHORIZE_NV_WAIT_FOR_SESSION;
+            fallthrough;
+
+        statecase(context->state, WRITE_AUTHORIZE_NV_WAIT_FOR_SESSION)
+    //TODO: Pass the namealg of the NV index into the session to be created
+            r = ifapi_get_sessions_finish(context, &context->profiles.default_profile);
+            return_try_again(r);
+            goto_if_error_reset_state(r, " FAPI create session", error_cleanup);
+
+            context->state = WRITE_AUTHORIZE_NV_WRITE_NV_RAM;
+            fallthrough;
+
+        statecase(context->state, WRITE_AUTHORIZE_NV_WRITE_NV_RAM_PREPARE)
+
+            /* Copy hash alg followed by digest into buffer to be written to NV ram */
+            r = Tss2_MU_TPMI_ALG_HASH_Marshal(
+                    object->misc.nv.public.nvPublic.nameAlg,
+                    &nvBuffer[0], maxNvSize, &offset);
+            goto_if_error_reset_state(r, "FAPI marshal hash alg", error_cleanup);
+
+            void * currentDigest =
+                &policyHarness->policyDigests.digests[command->digest_idx].digest;
+            memcpy(&nvBuffer[offset], currentDigest, command->hash_size);
+
+            nvCmd->data = &nvBuffer[0];
+            nvCmd->numBytes = command->hash_size + sizeof(TPMI_ALG_HASH);
+            fallthrough;
+
+        statecase(context->state, WRITE_AUTHORIZE_NV_WRITE_NV_RAM)
+            r = ifapi_nv_write(context, nvCmd->nvPath, 0,
+                    nvCmd->data, context->nv_cmd.numBytes);
+            return_try_again(r);
+            goto_if_error_reset_state(r, " FAPI NV Write", error_cleanup);
+
+            /* Perform esys serialization if necessary */
+            r = ifapi_esys_serialize_object(context->esys, object);
+            goto_if_error(r, "Prepare serialization", error_cleanup);
+
+             /* Save NV object to ensure that changed flags are updated. */
+            r = ifapi_keystore_store_async(&context->keystore, &context->io,
+                    nvCmd->nvPath, object);
+            goto_if_error_reset_state(r, "Could not open: %sh", error_cleanup,
+                    nvCmd->nvPath);
+
+            context->state = WRITE_AUTHORIZE_NV_WRITE_OBJCECT;
+            fallthrough;
+
+        statecase(context->state, WRITE_AUTHORIZE_NV_WRITE_OBJCECT)
+            /* Finish writing the NV object to the key store */
+            r = ifapi_keystore_store_finish(&context->keystore, &context->io);
+            return_try_again(r);
+            return_if_error_reset_state(r, "write_finish failed");
+
+            context->state = WRITE_AUTHORIZE_NV_WRITE_POLICY;
+            fallthrough;
+
+        statecase(context->state, WRITE_AUTHORIZE_NV_WRITE_POLICY_PREPARE)
+            r = ifapi_policy_store_store_async(&context->pstore, &context->io,
+                                               command->policyPath, policyHarness);
+            goto_if_error_reset_state(r, "Could not open: %s", error_cleanup,
+                    command->policyPath);
+            fallthrough;
+
+        statecase(context->state,  WRITE_AUTHORIZE_NV_WRITE_POLICY)
+            /* Save policy with computed digest */
+            r = ifapi_policy_store_store_finish(&context->pstore, &context->io);
+            return_try_again(r);
+            return_if_error_reset_state(r, "write_finish failed");
+
+            fallthrough;
+
+        statecase(context->state, WRITE_AUTHORIZE_NV_CLEANUP)
+            r = ifapi_cleanup_session(context);
+            try_again_or_error_goto(r, "Cleanup", error_cleanup);
+            context->state = _FAPI_STATE_INIT;
+            break;
+
+        statecasedefault(context->state);
+    }
+
+error_cleanup:
+    SAFE_FREE(command->policyPath);
+    SAFE_FREE(nvCmd->nvPath);
+    ifapi_session_clean(context);
+    ifapi_cleanup_policy_harness(policyHarness);
+    ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
+    ifapi_cleanup_ifapi_object(context->loadKey.key_object);
+    ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
+    ifapi_cleanup_ifapi_object(object);
+    LOG_TRACE("finsihed");
+    return r;
+}
diff --git a/src/tss2-fapi/api/fapi_callback.c b/src/tss2-fapi/api/fapi_callback.c
new file mode 100644
index 0000000..d402ac5
--- /dev/null
+++ b/src/tss2-fapi/api/fapi_callback.c
@@ -0,0 +1,180 @@
+/* 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
+
+#ifndef NO_DL
+#include <dlfcn.h>
+#endif /* NO_DL */
+#include <stdlib.h>
+
+#include "tss2_esys.h"
+#include "tss2_fapi.h"
+#include "fapi_int.h"
+
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+/**
+ * This function registers a callback that will be invoked whenever the FAPI has
+ * to decide which branch of a Policy-OR policy to use to authorize a particular
+ * FAPI operation.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] callback The callback function for branch selection
+ * @param [in] userData A pointer that is provided to all callback invocations
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or callback is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the synchronous or Async functions are
+ *         called while the context has another asynchronous operation
+ *         outstanding, or the Finish function is called while the context does
+ *         not have an appropriate asynchronous operation outstanding.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ */
+TSS2_RC
+Fapi_SetBranchCB(
+    FAPI_CONTEXT                      *context,
+    Fapi_CB_Branch                     callback,
+    void                              *userData)
+{
+    LOG_TRACE("called for context:%p", context);
+    LOG_TRACE("Callback %p Userdata %p", callback, userData);
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(callback);
+
+    context->callbacks.branch = callback;
+    context->callbacks.branchData = userData;
+
+    LOG_TRACE("finished");
+    return TSS2_RC_SUCCESS;
+}
+
+/**
+ * This function registers an application-defined function as a callback to
+ * allow the TSS to get authorization values from the application.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] callback The callback function for auth value retrieval
+ * @param [in] userData A pointer that is provided to all callback invocations
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or callback is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the synchronous or Async functions are
+ *         called while the context has another asynchronous operation
+ *         outstanding, or the Finish function is called while the context does
+ *         not have an appropriate asynchronous operation outstanding.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ */
+TSS2_RC
+Fapi_SetAuthCB(
+    FAPI_CONTEXT           *context,
+    Fapi_CB_Auth           callback,
+    void                   *userData)
+{
+    LOG_TRACE("called for context:%p", context);
+    LOG_TRACE("Callback %p Userdata %p", callback, userData);
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(callback);
+
+    context->callbacks.auth = callback;
+    context->callbacks.authData = userData;
+
+    LOG_TRACE("finished");
+    return TSS2_RC_SUCCESS;
+}
+
+/**
+ * Fapi_SetSignCB() registers an application-defined function as a callback to
+ * allow the FAPI to get signatures authorizing use of TPM objects.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] callback The callback function for signing selection
+ * @param [in] userData A pointer that is provided to all callback invocations
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or callback is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the synchronous or Async functions are
+ *         called while the context has another asynchronous operation
+ *         outstanding, or the Finish function is called while the context does
+ *         not have an appropriate asynchronous operation outstanding.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ */
+TSS2_RC
+Fapi_SetSignCB(
+    FAPI_CONTEXT                *context,
+    Fapi_CB_Sign                callback,
+    void                        *userData)
+{
+    LOG_TRACE("called for context:%p", context);
+    LOG_TRACE("Callback %p Userdata %p", callback, userData);
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(callback);
+
+    context->callbacks.sign = callback;
+    context->callbacks.signData = userData;
+
+    LOG_TRACE("finished");
+    return TSS2_RC_SUCCESS;
+}
+
+
+/**
+ * Fapi_SetActionCB() registers an application-defined function as a callback
+ * that shall be called back upon encountering a policy action element.
+ *
+ * @param [in, out] context The FAPI_CONTEXT
+ * @param [in] callback The callback function for branch selection
+ * @param [in] userData A pointer that is provided to all callback invocations
+ *
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or callback is NULL.
+ * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the synchronous or Async functions are
+ *         called while the context has another asynchronous operation
+ *         outstanding, or the Finish function is called while the context does
+ *         not have an appropriate asynchronous operation outstanding.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
+ */
+TSS2_RC
+Fapi_SetPolicyActionCB(
+    FAPI_CONTEXT                *context,
+    Fapi_CB_PolicyAction         callback,
+    void                        *userData)
+{
+    LOG_TRACE("called for context:%p", context);
+    LOG_TRACE("Callback %p Userdata %p", callback, userData);
+
+    /* Check for NULL parameters */
+    check_not_null(context);
+    check_not_null(callback);
+
+    context->callbacks.action = callback;
+    context->callbacks.actionData = userData;
+
+    LOG_TRACE("finished");
+    return TSS2_RC_SUCCESS;
+}
diff --git a/src/tss2-fapi/fapi_certificates.h b/src/tss2-fapi/fapi_certificates.h
new file mode 100644
index 0000000..2ac42d2
--- /dev/null
+++ b/src/tss2-fapi/fapi_certificates.h
@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ ******************************************************************************/
+#ifndef FAPI_CERTIFICATES_H
+#define FAPI_CERTIFICATES_H
+
+static char * root_cert_list[] = {
+    /* IFX RSA root certificate */
+    "-----BEGIN CERTIFICATE-----\n"
+    "MIIFqzCCA5OgAwIBAgIBAzANBgkqhkiG9w0BAQsFADB3MQswCQYDVQQGEwJERTEh\n"
+    "MB8GA1UECgwYSW5maW5lb24gVGVjaG5vbG9naWVzIEFHMRswGQYDVQQLDBJPUFRJ\n"
+    "R0EoVE0pIERldmljZXMxKDAmBgNVBAMMH0luZmluZW9uIE9QVElHQShUTSkgUlNB\n"
+    "IFJvb3QgQ0EwHhcNMTMwNzI2MDAwMDAwWhcNNDMwNzI1MjM1OTU5WjB3MQswCQYD\n"
+    "VQQGEwJERTEhMB8GA1UECgwYSW5maW5lb24gVGVjaG5vbG9naWVzIEFHMRswGQYD\n"
+    "VQQLDBJPUFRJR0EoVE0pIERldmljZXMxKDAmBgNVBAMMH0luZmluZW9uIE9QVElH\n"
+    "QShUTSkgUlNBIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC\n"
+    "AQC7E+gc0B5T7awzux66zMMZMTtCkPqGv6a3NVx73ICg2DSwnipFwBiUl9soEodn\n"
+    "25SVVN7pqmvKA2gMTR5QexuYS9PPerfRZrBY00xyFx84V+mIRPg4YqUMLtZBcAwr\n"
+    "R3GO6cffHp20SBH5ITpuqKciwb0v5ueLdtZHYRPq1+jgy58IFY/vACyF/ccWZxUS\n"
+    "JRNSe4ruwBgI7NMWicxiiWQmz1fE3e0mUGQ1tu4M6MpZPxTZxWzN0mMz9noj1oIT\n"
+    "ZUnq/drN54LHzX45l+2b14f5FkvtcXxJ7OCkI7lmWIt8s5fE4HhixEgsR2RX5hzl\n"
+    "8XiHiS7uD3pQhBYSBN5IBbVWREex1IUat5eAOb9AXjnZ7ivxJKiY/BkOmrNgN8k2\n"
+    "7vOS4P81ix1GnXsjyHJ6mOtWRC9UHfvJcvM3U9tuU+3dRfib03NGxSPnKteL4SP1\n"
+    "bdHfiGjV3LIxzFHOfdjM2cvFJ6jXg5hwXCFSdsQm5e2BfT3dWDBSfR4h3Prpkl6d\n"
+    "cAyb3nNtMK3HR5yl6QBuJybw8afHT3KRbwvOHOCR0ZVJTszclEPcM3NQdwFlhqLS\n"
+    "ghIflaKSPv9yHTKeg2AB5q9JSG2nwSTrjDKRab225+zJ0yylH5NwxIBLaVHDyAEu\n"
+    "81af+wnm99oqgvJuDKSQGyLf6sCeuy81wQYO46yNa+xJwQIDAQABo0IwQDAdBgNV\n"
+    "HQ4EFgQU3LtWq/EY/KaadREQZYQSntVBkrkwDgYDVR0PAQH/BAQDAgAGMA8GA1Ud\n"
+    "EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggIBAGHTBUx3ETIXYJsaAgb2pyyN\n"
+    "UltVL2bKzGMVSsnTCrXUU8hKrDQh3jNIMrS0d6dU/fGaGJvehxmmJfjaN/IFWA4M\n"
+    "BdZEnpAe2fJEP8vbLa/QHVfsAVuotLD6QWAqeaC2txpxkerveoV2JAwj1jrprT4y\n"
+    "rkS8SxZuKS05rYdlG30GjOKTq81amQtGf2NlNiM0lBB/SKTt0Uv5TK0jIWbz2WoZ\n"
+    "gGut7mF0md1rHRauWRcoHQdxWSQTCTtgoQzeBj4IS6N3QxQBKV9LL9UWm+CMIT7Y\n"
+    "np8bSJ8oW4UdpSuYWe1ZwSjZyzDiSzpuc4gTS6aHfMmEfoVwC8HN03/HD6B1Lwo2\n"
+    "DvEaqAxkya9IYWrDqkMrEErJO6cqx/vfIcfY/8JYmUJGTmvVlaODJTwYwov/2rjr\n"
+    "la5gR+xrTM7dq8bZimSQTO8h6cdL6u+3c8mGriCQkNZIZEac/Gdn+KwydaOZIcnf\n"
+    "Rdp3SalxsSp6cWwJGE4wpYKB2ClM2QF3yNQoTGNwMlpsxnU72ihDi/RxyaRTz9OR\n"
+    "pubNq8Wuq7jQUs5U00ryrMCZog1cxLzyfZwwCYh6O2CmbvMoydHNy5CU3ygxaLWv\n"
+    "JpgZVHN103npVMR3mLNa3QE+5MFlBlP3Mmystu8iVAKJas39VO5y5jad4dRLkwtM\n"
+    "6sJa8iBpdRjZrBp5sJBI\n"
+    "-----END CERTIFICATE-----\n",
+
+    /* IFX ECC root certificate */
+    "-----BEGIN CERTIFICATE-----\n"
+    "MIICWzCCAeKgAwIBAgIBBDAKBggqhkjOPQQDAzB3MQswCQYDVQQGEwJERTEhMB8G\n"
+    "A1UECgwYSW5maW5lb24gVGVjaG5vbG9naWVzIEFHMRswGQYDVQQLDBJPUFRJR0Eo\n"
+    "VE0pIERldmljZXMxKDAmBgNVBAMMH0luZmluZW9uIE9QVElHQShUTSkgRUNDIFJv\n"
+    "b3QgQ0EwHhcNMTMwNzI2MDAwMDAwWhcNNDMwNzI1MjM1OTU5WjB3MQswCQYDVQQG\n"
+    "EwJERTEhMB8GA1UECgwYSW5maW5lb24gVGVjaG5vbG9naWVzIEFHMRswGQYDVQQL\n"
+    "DBJPUFRJR0EoVE0pIERldmljZXMxKDAmBgNVBAMMH0luZmluZW9uIE9QVElHQShU\n"
+    "TSkgRUNDIFJvb3QgQ0EwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQm1HxLVgvAu1q2\n"
+    "GM+ymTz12zdTEu0JBVG9CdsVEJv/pE7pSWOlsG3YwU792YAvjSy7zL+WtDK40KGe\n"
+    "Om8bSWt46QJ00MQUkYxz6YqXbb14BBr06hWD6u6IMBupNkPd9pKjQjBAMB0GA1Ud\n"
+    "DgQWBBS0GIXISkrFEnryQDnexPWLHn5K0TAOBgNVHQ8BAf8EBAMCAAYwDwYDVR0T\n"
+    "AQH/BAUwAwEB/zAKBggqhkjOPQQDAwNnADBkAjA6QZcV8DjjbPuKjKDZQmTRywZk\n"
+    "MAn8wE6kuW3EouVvBt+/2O+szxMe4vxj8R6TDCYCMG7c9ov86ll/jDlJb/q0L4G+\n"
+    "+O3Bdel9P5+cOgzIGANkOPEzBQM3VfJegfnriT/kaA==\n"
+    "-----END CERTIFICATE-----\n"
+};
+
+#endif /* FAPI_CERTIFICATES_H */
diff --git a/src/tss2-fapi/fapi_crypto.c b/src/tss2-fapi/fapi_crypto.c
new file mode 100644
index 0000000..2331628
--- /dev/null
+++ b/src/tss2-fapi/fapi_crypto.c
@@ -0,0 +1,2218 @@
+/* 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 <string.h>
+
+#include <openssl/evp.h>
+#include <openssl/aes.h>
+#include <openssl/rsa.h>
+#include <openssl/engine.h>
+#include <openssl/pem.h>
+#include <openssl/x509v3.h>
+#include <curl/curl.h>
+#include <openssl/err.h>
+
+#include "fapi_certificates.h"
+#include "fapi_util.h"
+#include "util/aux_util.h"
+#include "fapi_crypto.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+
+/** Context to hold temporary values for ifapi_crypto */
+typedef struct _IFAPI_CRYPTO_CONTEXT {
+    /** The hash engine's context */
+    EVP_MD_CTX  *osslContext;
+    /** The currently used hash algorithm */
+    const EVP_MD *osslHashAlgorithm;
+    /** The size of the hash's digest */
+    size_t hashSize;
+} IFAPI_CRYPTO_CONTEXT;
+
+/** A singleton crypto engine for hash operations */
+static ENGINE *engine = NULL;
+
+/**
+ * Returns the signature scheme that is currently used in the FAPI context.
+ *
+ * @param [in] profile The FAPI profile from which the signing scheme is
+ *             retrieved
+ * @param [in] tpmPublic The public key for which the signing key is fetched
+ *             from the FAPI
+ * @param [out] signatureScheme The currently used signature scheme
+ *
+ * @retval TSS2_RC_SUCCESS if the signature scheme was successfully fetched
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE if one of the parameters is NULL
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the key type is not TPM2_ALG_RSA or
+ *         TPM2_ALG_ECC
+ */
+TPM2_RC
+ifapi_get_profile_sig_scheme(
+    const IFAPI_PROFILE *profile,
+    const TPMT_PUBLIC *tpmPublic,
+    TPMT_SIG_SCHEME *signatureScheme)
+{
+    /* Check for NULL parameters */
+    return_if_null(profile, "profile is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+    return_if_null(tpmPublic, "tpmPublic is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+    return_if_null(signatureScheme, "signatureScheme is NULL",
+            TSS2_FAPI_RC_BAD_REFERENCE);
+
+    /* Determine the appropriate signing scheme */
+    if (tpmPublic->type == TPM2_ALG_RSA) {
+        *signatureScheme = profile->rsa_signing_scheme;
+        return TSS2_RC_SUCCESS;
+    } else if (tpmPublic->type == TPM2_ALG_ECC) {
+        *signatureScheme = profile->ecc_signing_scheme;
+        return TSS2_RC_SUCCESS;
+    } else {
+        return_error(TSS2_FAPI_RC_BAD_VALUE, "Invalid key type.");
+    }
+}
+
+static const TPM2B_PUBLIC templateRsaSign = {
+    .size = 0,
+    .publicArea = {
+        .type = TPM2_ALG_RSA,
+        .nameAlg = TPM2_ALG_SHA1,
+        .objectAttributes = (TPMA_OBJECT_USERWITHAUTH |
+                             TPMA_OBJECT_SIGN_ENCRYPT |
+                             TPMA_OBJECT_RESTRICTED |
+                             TPMA_OBJECT_SENSITIVEDATAORIGIN
+                             ),
+        .authPolicy = {
+            .size = 0,
+            .buffer = 0,
+        },
+        .parameters.rsaDetail = {
+            .symmetric = {
+                .algorithm = TPM2_ALG_NULL,
+                .keyBits.aes = 128,
+                .mode.aes = TPM2_ALG_CFB,
+            },
+            .scheme = {
+                .scheme = TPM2_ALG_RSAPSS,
+                .details.rsapss.hashAlg = TPM2_ALG_SHA1,
+            },
+            .keyBits = 2048,
+            .exponent = 65537,
+        },
+        .unique.rsa = {
+            .size = 0,
+            .buffer = {},
+        }
+    }
+};
+
+/**
+ * A FAPI template for ECC signing keys
+ */
+static const TPM2B_PUBLIC templateEccSign = {
+    .size = 0,
+    .publicArea = {
+        .type = TPM2_ALG_ECC,
+        .nameAlg = TPM2_ALG_SHA1,
+        .objectAttributes = (
+                             TPMA_OBJECT_USERWITHAUTH |
+                             TPMA_OBJECT_RESTRICTED |
+                             TPMA_OBJECT_SIGN_ENCRYPT |
+                             TPMA_OBJECT_SENSITIVEDATAORIGIN
+                             ),
+        .authPolicy = {
+            .size = 0,
+        },
+
+        .parameters.eccDetail = {
+            .symmetric = {
+                .algorithm = TPM2_ALG_NULL,
+                .keyBits.aes = 128,
+                .mode.aes = TPM2_ALG_ECB,
+            },
+            .scheme = {
+                .scheme = TPM2_ALG_ECDSA,
+                .details = { .ecdsa = { .hashAlg = TPM2_ALG_SHA256 }},
+            },
+            .curveID = TPM2_ECC_BN_P256,
+            .kdf = { .scheme = TPM2_ALG_NULL, .details = {} }
+        },
+        .unique.ecc = {
+            .x = { .size = 0, .buffer = {} },
+            .y = { .size = 0, .buffer = {} },
+        },
+    },
+};
+
+/**
+ * Initializes a FAPI key template for a given signature algorithm.
+ *
+ * @param [in]  signatureAlgorithm The signature algorithm to use. Must be
+ *              TPM2_ALG_RSA or TPM2_ALG_ECC
+ * @param [out] template The template to initialize
+ *
+ * @retval TSS2_RC_SUCCESS on success
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE if template is NULL
+ * @retval TSS2_FAPI_RC_BAD_VALUE if signatureAlgorithm is not TPM2_ALG_RSA or
+ *         TPM2_ALG_ECC
+ */
+TSS2_RC
+ifapi_initialize_sign_public(TPM2_ALG_ID signatureAlgorithm,
+        TPM2B_PUBLIC *public) {
+
+    /* Check for NULL parameters */
+    return_if_null(public, "public is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    /* Initialize the template */
+    if (signatureAlgorithm == TPM2_ALG_RSA) {
+        /* RSA key template */
+        memcpy(public, &templateRsaSign, sizeof(TPM2B_PUBLIC));
+    } else if (signatureAlgorithm == TPM2_ALG_ECC) {
+        /* ECC key template */
+        memcpy(public, &templateEccSign, sizeof(TPM2B_PUBLIC));
+    } else {
+        /* Invalid key type */
+        LOG_ERROR("No suitable template found");
+        return TSS2_FAPI_RC_BAD_VALUE;
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/**
+ * Converts an openSSL BIGNUM into a binary byte buffer using.
+ *
+ * @param [in]  bn The BIGNUM to convert
+ * @param [out] bin The binary buffer to which the bignum is converted
+ * @param [in]  binSize The size of bin in bytes
+ *
+ * @retval 1 if the conversion was successful
+ * @retval 0 if one of the parameters is NULL
+ */
+static int
+ifapi_bn2binpad(const BIGNUM *bn, unsigned char *bin, int binSize)
+{
+    /* Check for NULL parameters */
+    return_if_null(bn, "bn is NULL", 0);
+    return_if_null(bin, "bin is NULL", 0);
+
+    /* Convert bn */
+    int bnSize = BN_num_bytes(bn);
+    int offset = binSize - bnSize;
+    memset(bin, 0, offset);
+    BN_bn2bin(bn, bin + offset);
+    return 1;
+}
+
+/**
+ * Returns the singleton hash engine for the use in ifapi_hash operations. If
+ * it does not yet exist, this function creates it.
+ *
+ * @retval A singleton hash engine
+ */
+ENGINE *
+get_engine()
+{
+    /* If an engine is present, it is returned */
+    if (engine)
+        return engine;
+    /* Otherwise, engine is created and returned */
+    engine = ENGINE_by_id(NULL);
+    return engine;
+}
+
+/**
+ * Returns a suitable openSSL hash algorithm identifier for a given TSS hash
+ * algorithm identifier.
+ *
+ * @param [in] hashAlgorithm The TSS hash algorithm identifier
+ *
+ * @retval An openSSL hash algorithm identifier if one that is suitable to
+ *         hashAlgorithm could be found
+ * @retval NULL if no suitable hash algorithm identifier could be found
+ */
+static const EVP_MD *
+get_hash_md(TPM2_ALG_ID hashAlgorithm)
+{
+    switch (hashAlgorithm) {
+    case TPM2_ALG_SHA1:
+        return EVP_sha1();
+    case TPM2_ALG_SHA256:
+        return EVP_sha256();
+    case TPM2_ALG_SHA384:
+        return EVP_sha384();
+    case TPM2_ALG_SHA512:
+        return EVP_sha512();
+    default:
+        return NULL;
+    }
+}
+
+/**
+ * Returns a suitable openSSL RSA signature scheme identifiver for a given TSS
+ * RSA signature scheme identifier.
+ *
+ * @param [in] signatureScheme The TSS RSA signature scheme identifier
+ *
+ * @retval RSA_PCKS1_PSS_PADDING if signatureScheme is TPM2_ALG_RSAPSS
+ * @retval RSA_PKCS1_PADDING if signatureScheme is TPM2_ALG_RSASSA
+ * @retval 0 otherwise
+ */
+static int
+get_sig_scheme(TPM2_ALG_ID signatureScheme)
+{
+    switch (signatureScheme) {
+    case TPM2_ALG_RSAPSS:
+        return RSA_PKCS1_PSS_PADDING;
+    case TPM2_ALG_RSASSA:
+        return RSA_PKCS1_PADDING;
+    default:
+        return 0;
+    }
+}
+
+/**
+ * Convert a TPM ECDSA signature into a DER formatted byte buffer. This can be
+ * used by TLS libraries.
+ *
+ * @param [in]  tpmSignature The signature created by the TPM
+ * @param [out] signature A byte buffer that will hold the DER representation of
+ *              the signature  (callee allocated)
+ * @param [out] signatureSize The size of signature in bytes. May be NULL
+ *
+ * @retval TSS2_RC_SUCCESS on success
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE if tpmSignature is NULL
+ * @retval TSS2_FAPI_RC_MEMORY if memory could not be allocated
+ * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an error occurs in the crypto library
+ */
+TSS2_RC
+ifapi_tpm_ecc_sig_to_der(
+    const TPMT_SIGNATURE *tpmSignature,
+    uint8_t **signature,
+    size_t *signatureSize)
+{
+    /* Check for NULL parameters */
+    return_if_null(tpmSignature, "tpmSignature is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    ECDSA_SIG *ecdsaSignature = NULL;
+    BIGNUM *bns = NULL, *bnr = NULL;
+    int osslRC;
+    TSS2_RC r;
+    uint8_t *signatureWalking;
+
+    /* Initialize an OpenSSL ECDSA signature which servers as an intermediate
+     * between the TSS ECDSA signature and the DER byte buffer */
+    ecdsaSignature = ECDSA_SIG_new();
+    if (ecdsaSignature == NULL) {
+        goto_if_null(ecdsaSignature, "Out of memory", TSS2_FAPI_RC_MEMORY,
+                      cleanup);
+    }
+
+    bns = BN_bin2bn(&tpmSignature->signature.ecdsa.signatureS.buffer[0],
+                    tpmSignature->signature.ecdsa.signatureS.size, NULL);
+    goto_if_null(bns, "Out of memory", TSS2_FAPI_RC_MEMORY, cleanup);
+
+    bnr = BN_bin2bn(&tpmSignature->signature.ecdsa.signatureR.buffer[0],
+                    tpmSignature->signature.ecdsa.signatureR.size, NULL);
+    goto_if_null(bnr, "Out of memory", TSS2_FAPI_RC_MEMORY, cleanup);
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000
+    ecdsaSignature->s = bns;
+    ecdsaSignature->r = bnr;
+#else /* OPENSSL_VERSION_NUMBER < 0x10100000 */
+    ECDSA_SIG_set0(ecdsaSignature, bnr, bns);
+#endif /* OPENSSL_VERSION_NUMBER < 0x10100000 */
+
+    osslRC = i2d_ECDSA_SIG(ecdsaSignature, NULL);
+    if (osslRC == -1) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "OSSL error", cleanup);
+    }
+
+    /* Initialize the byte buffer for the DER representation */
+    *signature = malloc(osslRC);
+    signatureWalking = *signature;
+    goto_if_null(*signature, "Out of memory", TSS2_FAPI_RC_MEMORY, cleanup);
+
+    if (signatureSize != NULL) {
+        *signatureSize = osslRC;
+    }
+
+    /* Convert the OpenSSL ECDSA signature to the DER buffer */
+    osslRC = i2d_ECDSA_SIG(ecdsaSignature, &signatureWalking);
+    if (!osslRC) {
+        free(*signature);
+        if (signatureSize != NULL) {
+            *signatureSize = 0;
+        }
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "OSSL error", cleanup);
+    }
+    r = TSS2_RC_SUCCESS;
+
+cleanup:
+    if (ecdsaSignature)
+        ECDSA_SIG_free(ecdsaSignature);
+    return r;
+}
+
+/**
+ * Converts a public RSA key created by the TPM into one that can be used by
+ * OpenSSL.
+ *
+ * @param [in]  tpmPublicKey The public RSA key created by the TPM
+ * @param [out] evpPublicKey The converted public RSA key that can be used by
+ *              OpenSSL
+ *
+ * @retval TSS2_RC_SUCCESS on success
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE if one of the parameters is NULL
+ * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an error occurs in the crypto library
+ */
+static TSS2_RC
+ossl_rsa_pub_from_tpm(const TPM2B_PUBLIC *tpmPublicKey, EVP_PKEY *evpPublicKey)
+{
+    /* Check for NULL parameters */
+    return_if_null(tpmPublicKey, "tpmPublicKey is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+    return_if_null(evpPublicKey, "evpPublicKey is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    /* Initialize the RSA parameters */
+    TSS2_RC r;
+    RSA *rsa = RSA_new();
+    BIGNUM *e = BN_new();
+    BIGNUM *d = BN_new();
+    BIGNUM *p = BN_new();
+    BIGNUM *q = BN_new();
+    BIGNUM *dmp1 = BN_new();
+    BIGNUM *dmq1 = BN_new();
+    BIGNUM *iqmp = BN_new();
+    BIGNUM *n = BN_bin2bn(tpmPublicKey->publicArea.unique.rsa.buffer,
+                          tpmPublicKey->publicArea.unique.rsa.size, NULL);
+
+    if (!n || !e || !d || !p || !q || !dmp1 || !dmq1 || !iqmp || !rsa) {
+        goto_error(r, TSS2_FAPI_RC_MEMORY, "Out of memory", error_cleanup);
+    }
+
+    BN_set_word(d, 0);
+    BN_set_word(p, 0);
+    BN_set_word(q, 0);
+    BN_set_word(dmp1, 0);
+    BN_set_word(dmq1, 0);
+    BN_set_word(iqmp, 0);
+    uint32_t exp;
+    if (tpmPublicKey->publicArea.parameters.rsaDetail.exponent == 0)
+        exp = 65537;
+    else
+        exp = tpmPublicKey->publicArea.parameters.rsaDetail.exponent;
+    if (1 != BN_set_word(e, exp)) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
+                   "Could not set exponent.", error_cleanup);
+    }
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000
+    rsa->e = e;
+    rsa->n = n;
+    rsa->d = d;
+    rsa->p = p;
+    rsa->q = q;
+    rsa->dmp1 = dmp1;
+    rsa->dmq1 = dmq1;
+    rsa->iqmp = iqmp;
+#else /* OPENSSL_VERSION_NUMBER < 0x10100000 */
+    RSA_set0_key(rsa, n, e, d);
+    RSA_set0_factors(rsa, p, q);
+    RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp);
+#endif /* OPENSSL_VERSION_NUMBER < 0x10100000 */
+
+    /* Assign the parameters to the key */
+    if (!EVP_PKEY_assign_RSA(evpPublicKey, rsa)) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Assign rsa key",
+                   error_cleanup);
+    }
+    return TSS2_RC_SUCCESS;
+
+error_cleanup:
+    OSSL_FREE(rsa, RSA);
+    OSSL_FREE(e, BN);
+    OSSL_FREE(n, BN);
+    OSSL_FREE(d, BN);
+    OSSL_FREE(p, BN);
+    OSSL_FREE(q, BN);
+    OSSL_FREE(dmp1, BN);
+    OSSL_FREE(dmq1, BN);
+    OSSL_FREE(iqmp, BN);
+    return r;
+}
+
+/**
+ * Converts a public ECC key created by the TPM into one that can be used by
+ * OpenSSL.
+ *
+ * @param [in]  tpmPublicKey The public ECC key created by the TPM
+ * @param [out] evpPublicKey The converted public ECC key that can be used by
+ *              OpenSSL
+ *
+ * @retval TSS2_RC_SUCCESS on success
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE if one of the parameters is NULL
+ * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an error occurs in the crypto library
+ */
+static TSS2_RC
+ossl_ecc_pub_from_tpm(const TPM2B_PUBLIC *tpmPublicKey, EVP_PKEY *evpPublicKey)
+{
+    /* Check for NULL parameters */
+    return_if_null(tpmPublicKey, "tpmPublicKey is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+    return_if_null(evpPublicKey, "evpPublicKey is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    EC_GROUP *ecgroup = NULL;
+    int curveId;
+    BIGNUM *x = NULL, *y = NULL;
+    EC_KEY *ecKey = EC_KEY_new();
+    return_if_null(ecKey, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+    /* Find the curve of the ECC key */
+    switch (tpmPublicKey->publicArea.parameters.eccDetail.curveID) {
+    case TPM2_ECC_NIST_P192:
+        curveId = NID_X9_62_prime192v1;
+        break;
+    case TPM2_ECC_NIST_P224:
+        curveId = NID_secp224r1;
+        break;
+    case TPM2_ECC_NIST_P256:
+        curveId = NID_X9_62_prime256v1;
+        break;
+    case TPM2_ECC_NIST_P384:
+        curveId = NID_secp384r1;
+        break;
+    case TPM2_ECC_NIST_P521:
+        curveId = NID_secp521r1;
+        break;
+    default:
+        return_error(TSS2_FAPI_RC_NOT_IMPLEMENTED,
+                     "ECC curve not implemented.");
+    }
+
+    /* Initialize the OpenSSL ECC key with its group */
+    ecgroup = EC_GROUP_new_by_curve_name(curveId);
+    goto_if_null(ecgroup, "new EC group.", TSS2_FAPI_RC_GENERAL_FAILURE,
+                  error_cleanup);
+
+    if (!EC_KEY_set_group(ecKey, ecgroup)) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "EC_KEY_set_group",
+                   error_cleanup);
+    }
+    EC_GROUP_free(ecgroup);
+
+    /* Set the ECC parameters in the OpenSSL key */
+    x = BN_bin2bn(tpmPublicKey->publicArea.unique.ecc.x.buffer,
+                  tpmPublicKey->publicArea.unique.ecc.x.size, NULL);
+
+    y = BN_bin2bn(tpmPublicKey->publicArea.unique.ecc.y.buffer,
+                  tpmPublicKey->publicArea.unique.ecc.y.size, NULL);
+
+    if (!x || !y) {
+        goto_error(r, TSS2_FAPI_RC_MEMORY, "Out of memory", error_cleanup);
+    }
+
+    if (!EC_KEY_set_public_key_affine_coordinates(ecKey, x, y)) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
+                   "EC_KEY_set_public_key_affine_coordinates", error_cleanup);
+    }
+
+    if (!EVP_PKEY_assign_EC_KEY(evpPublicKey, ecKey)) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Assign ecc key",
+                   error_cleanup);
+    }
+    OSSL_FREE(y, BN);
+    OSSL_FREE(x, BN);
+    return TSS2_RC_SUCCESS;
+
+error_cleanup:
+    OSSL_FREE(y, BN);
+    OSSL_FREE(x, BN);
+    OSSL_FREE(ecKey, EC_KEY);
+    return r;
+}
+
+/**
+ * Convert a TPM public key into a PEM formatted byte buffer. This can be
+ * used by TLS libraries.
+ *
+ * @param [in]  tpmPublicKey The public key created by the TPM
+ * @param [out] pemKey A byte buffer that will hold the PEM representation of
+ *              the public key  (callee allocated)
+ * @param [out] pemKeySize The size of pemKey in bytes
+ *
+ * @retval TSS2_RC_SUCCESS on success
+ * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an error occurs in the crypto library
+ * @retval TSS2_FAPI_RC_MEMORY if memory could not be allocated
+ * @retval TSS2_FAPI_BAD_REFERENCE if tpmPublicKey or pemKeySize are NULL
+ */
+TSS2_RC
+ifapi_pub_pem_key_from_tpm(
+    const TPM2B_PUBLIC *tpmPublicKey,
+    char **pemKey,
+    int *pemKeySize)
+{
+    /* Check for NULL parameters */
+    return_if_null(tpmPublicKey, "tpmPublicKey is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+    return_if_null(pemKeySize, "pemKeySize is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    EVP_PKEY *evpPublicKey = NULL;
+    BIO *bio = NULL;
+    TSS2_RC r = TPM2_RC_SUCCESS;
+
+    evpPublicKey = EVP_PKEY_new();
+    goto_if_null2(evpPublicKey, "Out of memory.", r, TSS2_FAPI_RC_MEMORY, cleanup);
+
+    /* Memory IO will be used for OSSL key conversion */
+    bio = BIO_new(BIO_s_mem());
+    goto_if_null2(evpPublicKey, "Out of memory.", r, TSS2_FAPI_RC_MEMORY, cleanup);
+
+    if (tpmPublicKey->publicArea.type == TPM2_ALG_RSA) {
+        r = ossl_rsa_pub_from_tpm(tpmPublicKey, evpPublicKey);
+    } else if (tpmPublicKey->publicArea.type == TPM2_ALG_ECC)
+        r = ossl_ecc_pub_from_tpm(tpmPublicKey, evpPublicKey);
+    else {
+        goto_error(r,TSS2_FAPI_RC_BAD_VALUE, "Invalid alg id.", cleanup);
+    }
+    goto_if_error(r, "Get ossl public key.", cleanup);
+
+    if (!PEM_write_bio_PUBKEY(bio, evpPublicKey)) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "PEM_write_bio_PUBKEY",
+                   cleanup);
+    }
+
+    /* Determine the size of the data written */
+    *pemKeySize = BIO_get_mem_data(bio, pemKey);
+    *pemKey = malloc(*pemKeySize+1);
+    goto_if_null(*pemKey, "Out of memory.", TSS2_FAPI_RC_MEMORY,
+            cleanup);
+    memset(*pemKey, 0, *pemKeySize + 1);
+
+    /* Get the byte buffer written to the BIO object */
+    int readSize = BIO_read(bio, *pemKey, *pemKeySize);
+    if (readSize != *pemKeySize) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Invalid BIO_read",
+                   cleanup);
+    }
+
+cleanup:
+    EVP_PKEY_free(evpPublicKey);
+    BIO_free(bio);
+    return r;
+}
+
+/** Converts an ECDSA signature from a DER encoded byte buffer into the
+ * TPM format. It can then be verified by the TPM.
+ *
+ * @param [in]  signature A DER encoded byte buffer holding the signature
+ * @param [in]  signatureSize The size of signature in bytes
+ * @param [in]  keySize The size of the verification key
+ * @param [in]  hashAlgorithm The TSS identifier of the hash algorithm to use
+ * @param [out] tpmSignature The signature in the TPM format
+ *
+ * @retval TSS2_RC_SUCCESS on success
+ * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an error occurs in the crypto library
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE if signature or tpmSignature is NULL
+ * @retval TSS2_FAPI_RC_MEMORY if memory could not be allocated
+ */
+static TSS2_RC
+ifapi_ecc_der_sig_to_tpm(
+    const unsigned char *signature,
+    size_t signatureSize,
+    int keySize,
+    TPMI_ALG_HASH hashAlgorithm,
+    TPMT_SIGNATURE *tpmSignature)
+{
+    /* Check for NULL parameters */
+    return_if_null(signature, "signature is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+    return_if_null(tpmSignature, "tpmSignature is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    /* Initialize the ECDSA signature components */
+    ECDSA_SIG *ecdsaSignature = NULL;
+#if OPENSSL_VERSION_NUMBER < 0x10100000
+    BIGNUM *bnr;
+    BIGNUM *bns;
+#else /* OPENSSL_VERSION_NUMBER < 0x10100000 */
+    const BIGNUM *bnr;
+    const BIGNUM *bns;
+#endif /* OPENSSL_VERSION_NUMBER < 0x10100000 */
+
+    d2i_ECDSA_SIG(&ecdsaSignature, &signature, signatureSize);
+    return_if_null(ecdsaSignature, "Invalid DER signature",
+                   TSS2_FAPI_RC_GENERAL_FAILURE);
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000
+    bns = ecdsaSignature->s;
+    bnr = ecdsaSignature->r;
+#else /* OPENSSL_VERSION_NUMBER < 0x10100000 */
+    ECDSA_SIG_get0(ecdsaSignature, &bnr, &bns);
+#endif /* OPENSSL_VERSION_NUMBER < 0x10100000 */
+
+    /* Writing them to the TPM format signature */
+    tpmSignature->signature.ecdsa.hash = hashAlgorithm;
+    tpmSignature->sigAlg = TPM2_ALG_ECDSA; /**< only ECDSA is used by FAPI */
+    ifapi_bn2binpad(bnr, &tpmSignature->signature.ecdsa.signatureR.buffer[0],
+                       keySize);
+    ifapi_bn2binpad(bns, &tpmSignature->signature.ecdsa.signatureS.buffer[0],
+                       keySize);
+    OSSL_FREE(ecdsaSignature, ECDSA_SIG);
+    OSSL_FREE(bnr, BN);
+    OSSL_FREE(bns, BN);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Convert signature from DER to TPM format.
+ *
+ * The signature in DER format is converted to TPM format to
+ * enable verification by the TPM.
+ *
+ * @param [in] tpmPublic The public information of the signature key
+ * @param [in] signature A byte buffer holding the DER encoded signature
+ * @param [in] signatureSize The size of signature in bytes
+ * @param [in] hashAlgorithm The TSS identifier for the hash algorithm used
+ *             to compute the digest
+ * @param [out] tpmSignature The signature in TPM format
+ *
+ * @retval TSS2_RC_SUCCESS on success
+ * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an error occurs in the crypto library
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE if tpmPublic, signature or tpmSignature is NULL
+ * @retval TSS2_FAPI_RC_MEMORY if memory could not be allocated
+ */
+TSS2_RC
+ifapi_der_sig_to_tpm(
+    const TPMT_PUBLIC *tpmPublic,
+    const unsigned char *signature,
+    size_t signatureSize,
+    TPMI_ALG_HASH hashAlgorithm,
+    TPMT_SIGNATURE *tpmSignature)
+{
+    /* Check for NULL parameters */
+    return_if_null(tpmPublic, "tpmPublic is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+    return_if_null(signature, "signature is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+    return_if_null(tpmSignature, "tpmSignature is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    /* Convert the signature */
+    if (tpmPublic->type == TPM2_ALG_RSA) {
+        if (tpmPublic->parameters.rsaDetail.scheme.scheme == TPM2_ALG_RSAPSS) {
+            tpmSignature->sigAlg = TPM2_ALG_RSAPSS;
+            tpmSignature->signature.rsapss.hash = hashAlgorithm;
+            tpmSignature->signature.rsapss.sig.size = signatureSize;
+            memcpy(&tpmSignature->signature.rsapss.sig.buffer[0], signature,
+                    signatureSize);
+        } else if (tpmPublic->parameters.rsaDetail.scheme.scheme == TPM2_ALG_RSASSA) {
+            tpmSignature->sigAlg = TPM2_ALG_RSASSA;
+            tpmSignature->signature.rsassa.hash = hashAlgorithm;
+            tpmSignature->signature.rsassa.sig.size = signatureSize;
+            memcpy(&tpmSignature->signature.rsassa.sig.buffer[0], signature,
+                    signatureSize);
+        } else {
+            return_error(TSS2_FAPI_RC_BAD_VALUE, "Invalid RSA scheme.");
+
+        }
+    } else if (tpmPublic->type == TPM2_ALG_ECC) {
+        return ifapi_ecc_der_sig_to_tpm(signature, signatureSize,
+                                        tpmPublic->unique.ecc.x.size, hashAlgorithm,
+                                        tpmSignature);
+    } else {
+        return_error(TSS2_FAPI_RC_BAD_VALUE, "Invalid key tpye.");
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/**
+ * Size of the table with the possible padding schemes
+ */
+#define N_PADDING 2
+
+/**
+ * Table with possible padding schemes to guess the one appropriate for
+ * for RSA signature verification
+ */
+static const int rsaPadding[N_PADDING] = { RSA_PKCS1_PADDING, RSA_PKCS1_PSS_PADDING };
+
+/**
+ * Verifies an RSA signature given as a binary byte buffer.
+ *
+ * @param [in] publicKey The public key with which the signature is to be
+ *             verified
+ * @param [in] signature A byte buffer holding the signature to verify
+ * @param [in] signatureSize The size of signature in bytes
+ * @param [in] digest The digest of the signature to verify
+ * @param [in] digestSize The size of digest in bytes. Required to determine the
+ *             hash algorithm
+ *
+ * @retval TSS2_RC_SUCCESS on success
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE if publicKey, signature or digest is NULL
+ * @retval TSS2_FAPI_RC_BAD_VALUE if no hash algorithm that matches digestSize
+ *         could be found
+ * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an error occurs in the crypto library
+ * @retval TSS2_FAPI_RC_SIGNATURE_VERIFICATION_FAILED if the signature could not
+ *         be verified
+ */
+static TSS2_RC
+rsa_verify_signature(
+    EVP_PKEY *publicKey,
+    const uint8_t *signature,
+    size_t signatureSize,
+    const uint8_t *digest,
+    size_t digestSize)
+{
+    /* Check for NULL parameters */
+    return_if_null(publicKey, "publicKey is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+    return_if_null(signature, "signature is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+    return_if_null(digest, "digest is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    const EVP_MD *mdType;
+    EVP_PKEY_CTX *ctx = NULL;
+
+    /* The hash algorithm of the signature is determined by the digest length */
+    switch (digestSize) {
+    case TPM2_SHA1_DIGEST_SIZE:
+        mdType = EVP_sha1();
+        break;
+    case TPM2_SHA256_DIGEST_SIZE:
+        mdType = EVP_sha256();
+        break;
+    case TPM2_SHA384_DIGEST_SIZE:
+        mdType = EVP_sha384();
+        break;
+    case TPM2_SHA512_DIGEST_SIZE:
+        mdType = EVP_sha512();
+        break;
+    default:
+        goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Invalid digest size", cleanup);
+    }
+
+    /* Try all possible padding schemes for verification */
+    for (int i = 0; i < N_PADDING; i++) {
+        ctx = EVP_PKEY_CTX_new(publicKey, NULL);
+        if (!ctx) {
+            goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Get pkey context.",
+                       cleanup);
+        }
+        if (EVP_PKEY_verify_init(ctx) <= 0) {
+            goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Verify init.",
+                       cleanup);
+        }
+        if (EVP_PKEY_CTX_set_rsa_padding(ctx, rsaPadding[i]) <= 0) {
+            goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
+                       "EVP_PKEY_CTX_set_rsa_padding", cleanup);
+        }
+        if (EVP_PKEY_CTX_set_signature_md(ctx, mdType) <= 0) {
+            goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
+                       "Verify set signature md.", cleanup);
+        }
+        if (1 !=  EVP_PKEY_verify(ctx, signature, signatureSize, digest, digestSize)) {
+            /* padding scheme was not appropriate, next should be tried */
+            EVP_PKEY_CTX_free(ctx);
+        } else {
+            /* Verification with selected padding scheme was successful */
+            r = TSS2_RC_SUCCESS;
+            goto cleanup;
+        }
+    }
+    /* Verification was not successful with one of the possible padding schemes */
+    r = TSS2_FAPI_RC_SIGNATURE_VERIFICATION_FAILED;
+
+cleanup:
+    EVP_PKEY_CTX_free(ctx);
+    return r;
+}
+
+/**
+ * Verifies an ECDSA signature given as a binary byte buffer.
+ *
+ * @param [in] publicKey The public key with which the signature is to be
+ *             verified
+ * @param [in] signature A byte buffer holding the signature to verify
+ * @param [in] signatureSize The size of signature in bytes
+ * @param [in] digest The digest of the signature to verify
+ * @param [in] digestSize The size of digest in bytes. Required to determine the
+ *             hash algorithm
+ *
+ * @retval TSS2_RC_SUCCESS on success
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE if publicKey, signature or digest is NULL
+ * @retval TSS2_FAPI_RC_BAD_VALUE if no hash algorithm that matches digestSize
+ *         could be found
+ * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an error occurs in the crypto library
+ * @retval TSS2_FAPI_RC_SIGNATURE_VERIFICATION_FAILED if the signature could not
+ *         be verified
+ */
+static TSS2_RC
+ecdsa_verify_signature(
+    EVP_PKEY *publicKey,
+    const uint8_t *signature,
+    size_t signatureSize,
+    const uint8_t *digest,
+    size_t digestSize)
+{
+    /* Check for NULL parameters */
+    return_if_null(publicKey, "publicKey is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+    return_if_null(signature, "signature is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+    return_if_null(digest, "digest is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    ECDSA_SIG *ecdsaSignature = NULL;
+    EC_KEY *eccKey = NULL;
+
+    /* Try to verify the signature using ECDSA */
+    if (!d2i_ECDSA_SIG(&ecdsaSignature, &signature, signatureSize)) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
+                     "Invalid ECDSA DER signature", error_cleanup);
+    }
+
+    eccKey = EVP_PKEY_get1_EC_KEY(publicKey);
+
+    if (!ECDSA_do_verify(digest, digestSize, ecdsaSignature, eccKey)) {
+        goto_error(r, TSS2_FAPI_RC_SIGNATURE_VERIFICATION_FAILED,
+                   "ECDSA signature verification failed.", error_cleanup);
+    }
+
+error_cleanup:
+    OSSL_FREE(eccKey, EC_KEY);
+    OSSL_FREE(ecdsaSignature, ECDSA_SIG);
+    return r;
+}
+
+/**
+ * Gets an object with the TPM-relevant public information of an OpenSSL
+ * RSA public key.
+ *
+ * @param [in, out] profile The crypto profile from which parameters are retrieved
+ * @param [in]  publicKey The public key for which the public information is
+ *              retrieved
+ * @param [out] tpmPublic The public information of publicKey
+ *
+ * @retval TSS2_RC_SUCCESS on success
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE if profile, publicKey or tpmPublic is NULL
+ * @retval TSS2_FAPI_RC_MEMORY if memory could not be allocated
+ * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an error occurs in the crypto library
+ */
+static TSS2_RC
+get_rsa_tpm2b_public_from_evp(
+    EVP_PKEY *publicKey,
+    TPM2B_PUBLIC *tpmPublic)
+{
+    /* Check for NULL parameters */
+    return_if_null(publicKey, "publicKey is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+    return_if_null(tpmPublic, "tpmPublic is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    /* Extract the public information */
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    RSA *rsaKey = EVP_PKEY_get1_RSA(publicKey);
+    return_if_null(rsaKey, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+    const BIGNUM *e = NULL, *n = NULL;
+    int rsaKeySize = RSA_size(rsaKey);
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000
+    e = rsaKey->e;
+    n = rsaKey->n;
+#else /* OPENSSL_VERSION_NUMBER < 0x10100000 */
+    RSA_get0_key(rsaKey, &n, &e, NULL);
+#endif /* OPENSSL_VERSION_NUMBER < 0x10100000 */
+    tpmPublic->publicArea.unique.rsa.size = rsaKeySize;
+    if (1 != ifapi_bn2binpad(n, &tpmPublic->publicArea.unique.rsa.buffer[0],
+                             rsaKeySize)) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
+                   "Write big num byte buffer", cleanup);
+    }
+    tpmPublic->publicArea.parameters.rsaDetail.keyBits = rsaKeySize * 8;
+    tpmPublic->publicArea.parameters.rsaDetail.exponent = BN_get_word(e);
+
+cleanup:
+    OSSL_FREE(rsaKey, RSA);
+    return r;
+}
+
+/**
+ * Gets an object with the TPM-relevant public information of an OpenSSL
+ * ECC public key.
+ *
+ * @param [in, out] profile The crypto profile to retrieve parameters from.
+ * @param [in]  publicKey The public key for which the public information is
+ *              retrieved
+ * @param [out] tpmPublic The public information of publicKey
+ *
+ * @retval TSS2_RC_SUCCESS on success
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE if profile, publicKey or tpmPublic is NULL
+ * @retval TSS2_FAPI_RC_MEMORY if memory could not be allocated
+ * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an error occurs in the crypto library
+ */
+static TSS2_RC
+get_ecc_tpm2b_public_from_evp(
+    EVP_PKEY *publicKey,
+    TPM2B_PUBLIC *tpmPublic)
+{
+    /* Check for NULL parameters */
+    return_if_null(publicKey, "publicKey is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+    return_if_null(tpmPublic, "tpmPublic is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    /* Initialize variables that will contain the relevant information */
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    EC_KEY *ecKey = EVP_PKEY_get1_EC_KEY(publicKey);
+    return_if_null(ecKey, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+    const EC_GROUP *ecGroup;
+    const EC_POINT *publicPoint;
+    int curveId;
+    size_t ecKeySize;
+    BIGNUM *bnX = NULL;
+    BIGNUM *bnY = NULL;
+    TPMI_ECC_CURVE tpmCurveId;
+
+    if (!ecKey) {
+        return_error(TSS2_FAPI_RC_GENERAL_FAILURE, "No ECC key!");
+    }
+
+    /* Retrieve the relevant information and write it to tpmPublic */
+    ecGroup = EC_KEY_get0_group(ecKey);
+    publicPoint = EC_KEY_get0_public_key(ecKey);
+    curveId = EC_GROUP_get_curve_name(ecGroup);
+    ecKeySize = EC_GROUP_get_degree(ecGroup) / 8;
+    tpmPublic->publicArea.unique.ecc.x.size = ecKeySize;
+    tpmPublic->publicArea.unique.ecc.y.size = ecKeySize;
+
+    if (!(bnX = BN_new())) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Create bignum", cleanup);
+    }
+
+    if (!(bnY = BN_new())) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Create bignum", cleanup);
+    }
+
+    if (1 != EC_POINT_get_affine_coordinates_GFp(ecGroup, publicPoint,
+                                                 bnX, bnY, NULL)) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
+                   "Get affine coordinates", cleanup);
+    }
+    if (1 != ifapi_bn2binpad(bnX, &tpmPublic->publicArea.unique.ecc.x.buffer[0],
+                             ecKeySize)) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
+                   "Write big num byte buffer", cleanup);
+    }
+    if (1 != ifapi_bn2binpad(bnY, &tpmPublic->publicArea.unique.ecc.y.buffer[0],
+                             ecKeySize)) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
+                   "Write big num byte buffer", cleanup);
+    }
+    switch (curveId) {
+    case NID_X9_62_prime192v1:
+        tpmCurveId = TPM2_ECC_NIST_P192;
+        break;
+    case NID_secp224r1:
+        tpmCurveId = TPM2_ECC_NIST_P224;
+        break;
+    case NID_X9_62_prime256v1:
+        tpmCurveId = TPM2_ECC_NIST_P256;
+        break;
+    case NID_secp384r1:
+        tpmCurveId = TPM2_ECC_NIST_P384;
+        break;
+    case NID_secp521r1:
+        tpmCurveId = TPM2_ECC_NIST_P521;
+        break;
+    default:
+        goto_error(r, TSS2_FAPI_RC_NOT_IMPLEMENTED,
+                   "Curve %x not implemented", cleanup, curveId);
+    }
+    tpmPublic->publicArea.parameters.eccDetail.curveID = tpmCurveId;
+
+cleanup:
+    OSSL_FREE(ecKey, EC_KEY);
+    OSSL_FREE(bnX, BN);
+    OSSL_FREE(bnY, BN);
+    return r;
+}
+
+/**
+ * Converts a given PEM key into an EVP public key object.
+ *
+ * @param [in] pemKey A byte buffer holding the PEM key to convert
+ * @param [out] publicKey An EVP public key
+ *
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE if any of the parameters is NULL
+ * @retval TSS2_FAPI_RC_MEMORY if memory could not be allocated
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the PEM key could not be decoded
+ */
+static TSS2_RC
+ifapi_get_evp_from_pem(const char *pemKey, EVP_PKEY **publicKey) {
+    /* Check for NULL parameters */
+    return_if_null(pemKey, "pemKey is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+    return_if_null(publicKey, "publicKey is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    BIO *bufio = NULL;
+
+    /* Use BIO for conversion */
+    bufio = BIO_new_mem_buf((void *)pemKey, strlen(pemKey));
+    goto_if_null(bufio, "BIO buffer could not be allocated.",
+                 TSS2_FAPI_RC_MEMORY, cleanup);
+
+    /* Convert the key */
+    *publicKey = PEM_read_bio_PUBKEY(bufio, NULL, NULL, NULL);
+    goto_if_null(*publicKey, "PEM format could not be decoded.",
+                 TSS2_FAPI_RC_BAD_VALUE, cleanup);
+cleanup:
+    BIO_free(bufio);
+    return r;
+}
+
+/**
+ * Returns the TPM algorithm identifier that matches to the signature algorithm
+ * of a given PEM key.
+ *
+ * @param [in] pemKey The public key from which the signature algorithm is retrieved
+ *
+ * @retval TPM2_ALG_RSA if pemKey holds an RSA key
+ * @retval TPM2_ALG_ECC if pemKey holds an ECC key
+ * @retval TPM2_ALG_ERROR if the signature algorithm could not be determined
+ */
+TPM2_ALG_ID
+ifapi_get_signature_algorithm_from_pem(const char *pemKey) {
+    /* Check for NULL parameters */
+    return_if_null(pemKey, "pemKey is NULL", TPM2_ALG_ERROR);
+
+    /* Get an EVP object for the key */
+    EVP_PKEY * publicKey = NULL;
+    TPM2_ALG_ID algorithmId = TPM2_ALG_ERROR;
+    TSS2_RC r = ifapi_get_evp_from_pem(pemKey, &publicKey);
+    if (r != TSS2_RC_SUCCESS || publicKey == NULL) {
+        LOG_ERROR("Could not get an EVP key from the PEM key");
+        algorithmId = TPM2_ALG_ERROR;
+        goto cleanup;
+    }
+
+    /* Determine the signature algorithm of the converted key */
+    if (EVP_PKEY_type(EVP_PKEY_id(publicKey)) == EVP_PKEY_RSA) {
+        algorithmId = TPM2_ALG_RSA;
+    } else if (EVP_PKEY_type(EVP_PKEY_id(publicKey)) == EVP_PKEY_EC) {
+        algorithmId = TPM2_ALG_ECC;
+    } else {
+        algorithmId = TPM2_ALG_ERROR;
+    }
+
+cleanup:
+    OSSL_FREE(publicKey, EVP_PKEY);
+    return algorithmId;
+}
+
+/**
+ * Gets an object with the TPM-relevant public information of a PEM encoded
+ * public key. The information is gathered from the key itself and the currently
+ * used FAPI profile.
+ *
+ * @param [in, out] profile The crypto profile to retrieve parameters from
+ * @param [in]  pemKey A byte buffer holding the PEM encoded public key for
+ *              which the public information is retrieved
+ * @param [out] tpmPublic The public information of pemKey
+ *
+ * @retval TSS2_RC_SUCCESS on success
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE if profile, pemKey or tpmPublic is NULL
+ * @retval TSS2_FAPI_RC_MEMORY if memory could not be allocated
+ * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an error occurs in the crypto library
+ */
+TSS2_RC
+ifapi_get_tpm2b_public_from_pem(
+    const char *pemKey,
+    TPM2B_PUBLIC *tpmPublic)
+{
+    /* Check for NULL parameters */
+    return_if_null(pemKey, "pemKey is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+    return_if_null(tpmPublic, "public is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    EVP_PKEY *publicKey = NULL;
+    r = ifapi_get_evp_from_pem(pemKey, &publicKey);
+    goto_if_error(r, "Get EVP key from PEM", cleanup);
+
+    if (EVP_PKEY_type(EVP_PKEY_id(publicKey)) == EVP_PKEY_RSA) {
+        tpmPublic->publicArea.type = TPM2_ALG_RSA;
+        r = get_rsa_tpm2b_public_from_evp(publicKey, tpmPublic);
+        goto_if_error(r, "Get public for RSA key.", cleanup);
+
+    } else if (EVP_PKEY_type(EVP_PKEY_id(publicKey)) == EVP_PKEY_EC) {
+        tpmPublic->publicArea.type = TPM2_ALG_ECC;
+        r = get_ecc_tpm2b_public_from_evp(publicKey, tpmPublic);
+        goto_if_error(r, "Get public for ECC key.", cleanup);
+    } else {
+        goto_error(r, TSS2_FAPI_RC_NOT_IMPLEMENTED, "Wrong key_type", cleanup);
+    }
+cleanup:
+    OSSL_FREE(publicKey, EVP_PKEY);
+    return r;
+}
+
+/**
+ * Verifies the signature created by a Quote command.
+ *
+ * @param [in] keyObject A FAPI key with which the signature is verified
+ * @param [in] signature A byte buffer holding the signature
+ * @param [in] signatureSize The size of signature in bytes
+ * @param [in] digest The digest of the signature
+ * @param [in] digestSize The size of digest in bytes
+ * @param [in] signatureScheme The signature scheme
+ *
+ * @retval TSS2_RC_SUCCESS on success
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE if keyObject, signature, digest
+ *         or signatureScheme is NULL
+ * @retval TSS2_FAPI_RC_MEMORY if memory could not be allocated
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the PEM encoded key could not be decoded
+ * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an error occurs in the crypto library
+ * @retval TSS2_FAPI_RC_SIGNATURE_VERIFICATION_FAILED if the verification of the
+ *         signature fails
+ */
+TSS2_RC
+ifapi_verify_signature_quote(
+    const IFAPI_OBJECT *keyObject,
+    const uint8_t *signature,
+    size_t signatureSize,
+    const uint8_t *digest,
+    size_t digestSize,
+    const TPMT_SIG_SCHEME *signatureScheme)
+{
+    /* Check for NULL parameters */
+    return_if_null(keyObject, "keyObject is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+    return_if_null(signature, "signature is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+    return_if_null(digest, "digest is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+    return_if_null(signatureScheme, "signatureScheme is NULL",
+            TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    char *public_pem_key = NULL;
+    int pem_size;
+    EVP_PKEY *publicKey = NULL;
+    BIO *bufio = NULL;
+    EVP_PKEY_CTX *pctx = NULL;
+    EVP_MD_CTX *mdctx = NULL;
+
+    /* Check whether or not the key is valid */
+    if (keyObject->objectType == IFAPI_KEY_OBJ) {
+        /* Compute public key */
+        r = ifapi_pub_pem_key_from_tpm(&keyObject->misc.key.public, &public_pem_key,
+                                       &pem_size);
+        goto_if_error(r, "Compute public PEM key.", error_cleanup);
+    } else if (keyObject->objectType == IFAPI_EXT_PUB_KEY_OBJ) {
+        public_pem_key = strdup(keyObject->misc.ext_pub_key.pem_ext_public);
+        check_oom(public_pem_key);
+    } else {
+        goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Wrong object type",
+                   error_cleanup);
+    }
+
+    /* Create an OpenSSL object for the key */
+    bufio = BIO_new_mem_buf((void *)public_pem_key,
+                            strlen(public_pem_key));
+    goto_if_null(bufio, "BIO buffer could not be allocated.",
+                 TSS2_FAPI_RC_MEMORY, error_cleanup);
+
+    publicKey = PEM_read_bio_PUBKEY(bufio, NULL, NULL, NULL);
+    goto_if_null(publicKey, "PEM format could not be decoded.",
+                 TSS2_FAPI_RC_BAD_VALUE, error_cleanup);
+
+    /* Create the hash engine */
+    if (!(mdctx = EVP_MD_CTX_create())) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "EVP_MD_CTX_create",
+                   error_cleanup);
+    }
+
+    const EVP_MD *hashAlgorithm = get_hash_md(signatureScheme->details.any.hashAlg);
+    if (!hashAlgorithm) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Invalid hash alg.",
+                   error_cleanup);
+    }
+
+    /* Verify the digest of the signature */
+    if (1 != EVP_DigestVerifyInit(mdctx, &pctx, hashAlgorithm, NULL, publicKey)) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "EVP_DigestVerifyInit",
+                   error_cleanup);
+    }
+    goto_if_null(pctx, "Out of memory", TSS2_FAPI_RC_MEMORY, error_cleanup);
+    if (EVP_PKEY_type(EVP_PKEY_id(publicKey)) == EVP_PKEY_RSA) {
+        int padding = get_sig_scheme(signatureScheme->scheme);
+        if (!padding) {
+            goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
+                       "Invalid padding scheme.", error_cleanup);
+        }
+        if (1 != EVP_PKEY_CTX_set_rsa_padding(pctx, padding)) {
+            goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
+                       "EVP_PKEY_CTX_set_rsa_padding", error_cleanup);
+        }
+    }
+
+    if (1 != EVP_DigestVerifyUpdate(mdctx, digest, digestSize)) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
+                   "EVP_DigestVerifyUpdate", error_cleanup);
+    }
+    if (1 != EVP_DigestVerifyFinal(mdctx, signature, signatureSize)) {
+        goto_error(r, TSS2_FAPI_RC_SIGNATURE_VERIFICATION_FAILED,
+                   "EVP_DigestSignFinal", error_cleanup);
+    }
+
+ error_cleanup:
+    if (mdctx != NULL) {
+        EVP_MD_CTX_destroy(mdctx);
+    }
+    SAFE_FREE(public_pem_key);
+    EVP_PKEY_free(publicKey);
+    BIO_free(bufio);
+    return r;
+}
+
+/**
+ * Verifies a signature using a given FAPI public key.
+ *
+ * @param [in] keyObject The FAPI public key used for verification
+ * @param [in] signature The signature to verify
+ * @param [in] signatureSize The size of signature in bytes
+ * @param [in] digest The digest of the signature
+ * @param [in] digestSize The size of digest in bytes
+ *
+ * @retval TSS2_RC_SUCCESS In case of success
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE if keyObject, signature or digest is NULL
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the type of the key is wrong
+ * @retval TSS2_FAPI_RC_MEMORY if memory could not be allocated
+ * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an error occurs in the crypto library
+ * @retval TSS2_FAPI_RC_SIGNATURE_VERIFICATION_FAILED if the verification of the
+ *         signature fails
+ *
+ */
+TSS2_RC
+ifapi_verify_signature(
+    const IFAPI_OBJECT *keyObject,
+    const uint8_t *signature,
+    size_t signatureSize,
+    const uint8_t *digest,
+    size_t digestSize)
+{
+    /* Check for NULL parameters */
+    return_if_null(keyObject, "keyObject is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+    return_if_null(signature, "signature is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+    return_if_null(digest, "digest is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    char *public_pem_key = NULL;
+    int pem_size;
+    EVP_PKEY *publicKey = NULL;
+    BIO *bufio = NULL;
+
+    /* Check whether or not the key is valid */
+    if (keyObject->objectType == IFAPI_KEY_OBJ) {
+        /* Compute public key */
+        r = ifapi_pub_pem_key_from_tpm(&keyObject->misc.key.public, &public_pem_key,
+                                       &pem_size);
+        goto_if_error(r, "Compute public PEM key.", error_cleanup);
+    } else if (keyObject->objectType == IFAPI_EXT_PUB_KEY_OBJ) {
+        public_pem_key = strdup(keyObject->misc.ext_pub_key.pem_ext_public);
+        check_oom(public_pem_key);
+    } else {
+        goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Wrong object type",
+                   error_cleanup);
+    }
+
+    /* Convert the key to an OpenSSL object */
+    bufio = BIO_new_mem_buf((void *)public_pem_key,
+                                strlen(public_pem_key));
+    goto_if_null(bufio, "Out of memory.", TSS2_FAPI_RC_MEMORY, error_cleanup);
+    publicKey = PEM_read_bio_PUBKEY(bufio, NULL, NULL, NULL);
+    goto_if_null(publicKey, "PEM format could not be decoded.",
+                 TSS2_FAPI_RC_MEMORY, error_cleanup);
+
+    /* Call a suitable local function for the verification */
+    if (EVP_PKEY_type(EVP_PKEY_id(publicKey)) == EVP_PKEY_RSA) {
+        r = rsa_verify_signature(publicKey, signature, signatureSize, digest,
+                                     digestSize);
+        goto_if_error(r, "Verify RSA signature.", error_cleanup);
+
+    } else if (EVP_PKEY_type(EVP_PKEY_id(publicKey)) == EVP_PKEY_EC) {
+        r = ecdsa_verify_signature(publicKey, signature, signatureSize,
+                                   digest, digestSize);
+        goto_if_error(r, "Verify ECC signature", error_cleanup);
+
+    } else {
+        goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Wrong key type",
+                       error_cleanup);
+    }
+
+error_cleanup:
+    SAFE_FREE(public_pem_key);
+    EVP_PKEY_free(publicKey);
+    if (bufio)
+        BIO_free(bufio);
+    return r;
+}
+
+/**
+ * Returns the digest size of a given hash algorithm.
+ *
+ * @param [in] hashAlgorithm The TSS identifier of the hash algorithm
+ *
+ * @return The size of the digest produced by the hash algorithm if
+ * hashAlgorithm is valid
+ * @retval 0 if hashAlgorithm is invalid
+ */
+size_t
+ifapi_hash_get_digest_size(TPM2_ALG_ID hashAlgorithm)
+{
+    switch (hashAlgorithm) {
+    case TPM2_ALG_SHA1:
+        return TPM2_SHA1_DIGEST_SIZE;
+        break;
+    case TPM2_ALG_SHA256:
+        return TPM2_SHA256_DIGEST_SIZE;
+        break;
+    case TPM2_ALG_SHA384:
+        return TPM2_SHA384_DIGEST_SIZE;
+        break;
+    case TPM2_ALG_SHA512:
+        return TPM2_SHA512_DIGEST_SIZE;
+        break;
+    case TPM2_ALG_SM3_256:
+        return TPM2_SM3_256_DIGEST_SIZE;
+        break;
+    default:
+        return 0;
+    }
+}
+
+/**
+ * Converts a TSS hash algorithm identifier into an OpenSSL hash algorithm
+ * identifier object.
+ *
+ * @param [in] hashAlgorithm The TSS hash algorithm identifier to convert
+ *
+ * @retval A suitable OpenSSL identifier object if one could be found
+ * @retval NULL if no suitable identifier object could be found
+ */
+static const EVP_MD *
+get_ossl_hash_md(TPM2_ALG_ID hashAlgorithm)
+{
+    switch (hashAlgorithm) {
+    case TPM2_ALG_SHA1:
+        return EVP_sha1();
+        break;
+    case TPM2_ALG_SHA256:
+        return EVP_sha256();
+        break;
+    case TPM2_ALG_SHA384:
+        return EVP_sha384();
+        break;
+    case TPM2_ALG_SHA512:
+        return EVP_sha512();
+        break;
+    default:
+        return NULL;
+    }
+}
+
+/**
+ * Starts the computation of a hash digest.
+ *
+ * @param[out] context The created hash context (callee-allocated).
+ * @param[in] hashAlgorithm The TSS hash identifier for the hash algorithm to use.
+ *
+ * @retval TSS2_RC_SUCCESS on success.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if hashAlgorithm is invalid
+ * @retval TSS2_ESYS_RC_BAD_REFERENCE if context is NULL
+ * @retval TSS2_FAPI_RC_MEMORY if memory cannot be allocated
+ * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an error occurs in the crypto library
+ */
+TSS2_RC
+ifapi_crypto_hash_start(IFAPI_CRYPTO_CONTEXT_BLOB **context,
+                        TPM2_ALG_ID hashAlgorithm)
+{
+    /* Check for NULL parameters */
+    return_if_null(context, "context is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    /* Initialize the hash context */
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    LOG_DEBUG("call: context=%p hashAlg=%" PRIu16, context, hashAlgorithm);
+    IFAPI_CRYPTO_CONTEXT *mycontext = NULL;
+    mycontext = calloc(1, sizeof(IFAPI_CRYPTO_CONTEXT));
+    return_if_null(mycontext, "Out of memory", TSS2_FAPI_RC_MEMORY);
+
+    if (!(mycontext->osslHashAlgorithm = get_ossl_hash_md(hashAlgorithm))) {
+        goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
+                   "Unsupported hash algorithm (%" PRIu16 ")", cleanup,
+                   hashAlgorithm);
+    }
+
+    if (!(mycontext->hashSize = ifapi_hash_get_digest_size(hashAlgorithm))) {
+        goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
+                   "Unsupported hash algorithm (%" PRIu16 ")", cleanup,
+                   hashAlgorithm);
+    }
+
+    if (!(mycontext->osslContext = EVP_MD_CTX_create())) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Error EVP_MD_CTX_create",
+                   cleanup);
+    }
+
+    if (1 != EVP_DigestInit_ex(mycontext->osslContext,
+                               mycontext->osslHashAlgorithm, get_engine())) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Error EVP_DigestInit_ex",
+                   cleanup);
+    }
+
+    *context = (IFAPI_CRYPTO_CONTEXT_BLOB *) mycontext;
+
+    return TSS2_RC_SUCCESS;
+
+cleanup:
+    if (mycontext->osslContext)
+        EVP_MD_CTX_destroy(mycontext->osslContext);
+    SAFE_FREE(mycontext);
+
+    return r;
+}
+
+/**
+ * Updates the digest value of a hash object with data from a byte buffer.
+ *
+ * @param[in,out] context The hash context that will be updated
+ * @param[in] buffer The data for the update
+ * @param[in] size The size of data in bytes
+ *
+ * @retval TSS2_RC_SUCCESS on success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE for invalid parameters.
+ * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an error occurs in the crypto library
+ */
+TSS2_RC
+ifapi_crypto_hash_update(IFAPI_CRYPTO_CONTEXT_BLOB *context,
+                         const uint8_t *buffer, size_t size)
+{
+    /* Check for NULL parameters */
+    return_if_null(context, "context is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+    return_if_null(buffer, "buffer is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    LOG_DEBUG("called for context %p, buffer %p and size %zd", context, buffer,
+              size);
+
+    /* Update the digest */
+    IFAPI_CRYPTO_CONTEXT *mycontext = (IFAPI_CRYPTO_CONTEXT *) context;
+    LOGBLOB_DEBUG(buffer, size, "Updating hash with");
+
+    if (1 != EVP_DigestUpdate(mycontext->osslContext, buffer, size)) {
+        return_error(TSS2_FAPI_RC_GENERAL_FAILURE, "OSSL hash update");
+    }
+
+    return TSS2_RC_SUCCESS;
+}
+
+/**
+ * Gets the digest value from a hash context and closes it.
+ *
+ * @param[in,out] context The hash context that is released
+ * @param[out] digest The buffer for the digest value
+ * @param[out] digestSize The size of digest in bytes. Can be NULL
+ *
+ * @retval TSS2_RC_SUCCESS on success
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE if context or digest is NULL
+ * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an error occurs in the crypto library
+ */
+TSS2_RC
+ifapi_crypto_hash_finish(IFAPI_CRYPTO_CONTEXT_BLOB **context,
+                         uint8_t *digest, size_t *digestSize)
+{
+    /* Check for NULL parameters */
+    return_if_null(context, "context is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+    return_if_null(digest, "digest is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    unsigned int computedDigestSize = 0;
+
+    LOG_TRACE("called for context-pointer %p, digest %p and size-pointer %p",
+              context, digest, digestSize);
+    /* Compute the digest */
+    IFAPI_CRYPTO_CONTEXT *mycontext = *context;
+    if (1 != EVP_DigestFinal_ex(mycontext->osslContext, digest,
+                                &computedDigestSize)) {
+        return_error(TSS2_FAPI_RC_GENERAL_FAILURE, "OSSL error.");
+    }
+
+    if (computedDigestSize != mycontext->hashSize) {
+        return_error(TSS2_FAPI_RC_GENERAL_FAILURE,
+                     "Invalid size computed by EVP_DigestFinal_ex");
+    }
+
+    LOGBLOB_DEBUG(digest, mycontext->hashSize, "finish hash");
+
+    if(digestSize != NULL) {
+        *digestSize = mycontext->hashSize;
+    }
+
+    /* Finalize the hash context */
+    EVP_MD_CTX_destroy(mycontext->osslContext);
+    free(mycontext);
+    *context = NULL;
+
+    return TSS2_RC_SUCCESS;
+}
+
+/**
+ * Aborts a hash operation and finalizes the hash context. It will be set to
+ * NULL.
+ *
+ * @param[in,out] context The context of the digest object.
+ */
+void
+ifapi_crypto_hash_abort(IFAPI_CRYPTO_CONTEXT_BLOB **context)
+{
+    LOG_TRACE("called for context-pointer %p", context);
+    if (context == NULL || *context == NULL) {
+        LOG_DEBUG("Null-Pointer passed");
+        return;
+    }
+    IFAPI_CRYPTO_CONTEXT *mycontext = (IFAPI_CRYPTO_CONTEXT *) * context;
+
+    EVP_MD_CTX_destroy(mycontext->osslContext);
+    free(mycontext);
+    *context = NULL;
+}
+
+struct CertificateStruct {
+  unsigned char *buffer;
+  size_t size;
+};
+
+static size_t
+write_certificate_cb(void *contents, size_t size, size_t nmemb, void *userp)
+{
+  size_t realsize = size * nmemb;
+  struct CertificateStruct *cert = (struct CertificateStruct *)userp;
+
+  unsigned char *tmp_ptr = realloc(cert->buffer, cert->size + realsize + 1);
+  if(tmp_ptr == NULL) {
+      LOG_ERROR("Can't allocate memory in CURL callback.");
+    return 0;
+  }
+  cert->buffer = tmp_ptr;
+  memcpy(&(cert->buffer[cert->size]), contents, realsize);
+  cert->size += realsize;
+  cert->buffer[cert->size] = 0;
+
+  return realsize;
+}
+
+/** Get DER encoded certificate via curl. */
+static TSS2_RC
+get_cert_buffer(unsigned char * url, unsigned char ** buffer, size_t *cert_size)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    CURL *curl_handle = NULL;
+
+    struct CertificateStruct cert_buffer = { .size = 0, .buffer = NULL };
+
+    /* Init dummy buffer, will be enlarged depending on the size of
+       the received data. */
+    cert_buffer.buffer = malloc(1);
+    goto_if_null2(cert_buffer.buffer, "Out of memory.", r,
+                  TSS2_FAPI_RC_GENERAL_FAILURE, cleanup);
+
+    /* Prepare curl with URL and callback for copying data */
+    if (CURLE_OK != curl_global_init(CURL_GLOBAL_ALL)) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Curl global init",
+                   cleanup);
+    }
+
+    curl_handle = curl_easy_init();
+    if (!curl_handle) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Curl easy init",
+                   cleanup);
+
+    }
+    if (CURLE_OK != curl_easy_setopt(curl_handle, CURLOPT_URL, url)) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Curl easy setopt",
+                   cleanup);
+    }
+    if (CURLE_OK != curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION,
+                                     write_certificate_cb)) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Curl easy setopt",
+                   cleanup);
+    }
+    if (CURLE_OK != curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA,
+                                     (void *)&cert_buffer)) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Curl easy setopt",
+                   cleanup);
+    }
+    if (CURLE_OK != curl_easy_setopt(curl_handle, CURLOPT_USERAGENT,
+                                     "libcurl-agent/1.0")) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Curl easy setopt",
+                   cleanup);
+    }
+    /* Receive the certificate */
+    if (CURLE_OK != curl_easy_perform(curl_handle)) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Curl easy setopt",
+                   cleanup);
+    }
+    LOG_TRACE("%zu bytes of certificate retrieved\n", cert_buffer.size);
+
+    *buffer = cert_buffer.buffer;
+    *cert_size = cert_buffer.size;
+    if (curl_handle)
+        curl_easy_cleanup(curl_handle);
+     curl_global_cleanup();
+     return r;
+
+ cleanup:
+     if (curl_handle)
+        curl_easy_cleanup(curl_handle);
+     curl_global_cleanup();
+     free(cert_buffer.buffer);
+     return r;
+}
+
+/**
+ * Get url to download crl from certificate.
+ */
+TSS2_RC
+get_crl_from_cert(X509 *cert, X509_CRL **crl)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    unsigned char* url = NULL;
+    unsigned char *crl_buffer = NULL;
+    size_t crl_buffer_size;
+    int nid = NID_crl_distribution_points;
+    STACK_OF(DIST_POINT) * dist_points = (STACK_OF(DIST_POINT) *)X509_get_ext_d2i(cert, nid, NULL, NULL);
+
+    *crl = NULL;
+    for (int i = 0; i < sk_DIST_POINT_num(dist_points); i++)
+    {
+        DIST_POINT *dp = sk_DIST_POINT_value(dist_points, i);
+        DIST_POINT_NAME    *distpoint = dp->distpoint;
+        if (distpoint->type==0)
+        {
+            for (int j = 0; j < sk_GENERAL_NAME_num(distpoint->name.fullname); j++)
+            {
+                GENERAL_NAME *gen_name = sk_GENERAL_NAME_value(distpoint->name.fullname, j);
+                ASN1_IA5STRING *asn1_str = gen_name->d.uniformResourceIdentifier;
+                SAFE_FREE(url);
+                url = (unsigned char *)strdup((char *)asn1_str->data);
+            }
+        }
+    }
+
+    r = get_cert_buffer(url, &crl_buffer, &crl_buffer_size);
+    goto_if_error(r, "Get crl.", cleanup);
+
+    OpenSSL_add_all_algorithms();
+
+    unsigned const char* tmp_ptr1 = crl_buffer;
+    unsigned const char** tmp_ptr2 = &tmp_ptr1;
+
+    if (!d2i_X509_CRL(crl, tmp_ptr2, crl_buffer_size)) {
+        goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Can't convert crl.", cleanup);
+    }
+
+ cleanup:
+    SAFE_FREE(crl_buffer);
+    CRL_DIST_POINTS_free(dist_points);
+    SAFE_FREE(url);
+    return r;
+}
+
+/**
+ * Converts a TPM certificate buffer to the PEM format.
+ *
+ * @param[in]  certBuffer A byte buffer holding the certificate
+ * @param[in]  certBufferSize The size of certBuffer in bytes
+ * @param[out] pemCert A byte buffer where the PEM-formatted certificate is
+ *             stored
+ * @param[out] certAlgorithmId The key type of the certified key
+ *
+ * @retval TSS2_RC_SUCCESS on success
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE if certBuffer or pemCert is NULL
+ * @retval TSS2_FAPI_RC_MEMORY if memory could not be allocated
+ * @retval TSS2_FAPI_RC_BAD_VALUE, if the certificate is invalid
+ * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an error occurs in the crypto library
+ */
+TSS2_RC
+ifapi_cert_to_pem(
+    const uint8_t *certBuffer,
+    size_t certBufferSize,
+    char **pemCert,
+    TPM2_ALG_ID *certAlgorithmId,
+    TPM2B_PUBLIC *tpmPublic)
+{
+    /* Check for NULL parameters */
+    return_if_null(certBuffer, "certBuffer is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+    return_if_null(pemCert, "pemCert is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    X509 *cert = NULL;
+    BIO *bio = NULL;
+    EVP_PKEY *publicKey = NULL;
+    int pemCertSize;
+
+    if (!d2i_X509(&cert, (const unsigned char **)&certBuffer, certBufferSize)) {
+        LOGBLOB_ERROR(certBuffer, certBufferSize, "Bad certificate data");
+        return_error(TSS2_FAPI_RC_GENERAL_FAILURE, "Invalid certificate.");
+    }
+    *pemCert = NULL;
+
+    /* Memory IO will be used for OSSL key conversion */
+    bio = BIO_new(BIO_s_mem());
+    return_if_null(bio, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+    if (!PEM_write_bio_X509(bio, cert)) {
+        goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "PEM_write_bio_X509", cleanup);
+    }
+    /* Determine the size of the data written */
+    pemCertSize = BIO_get_mem_data(bio, pemCert);
+    *pemCert = malloc(pemCertSize+1);
+    goto_if_null(pemCert, "Out of memory.", TSS2_FAPI_RC_MEMORY, cleanup);
+
+    /* Get the byte buffer written to the BIO object */
+    int readSize = BIO_read(bio, *pemCert, pemCertSize);
+    if (readSize != pemCertSize) {
+        SAFE_FREE(*pemCert);
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Invalid BIO_read",
+                   cleanup);
+    }
+    (*pemCert)[pemCertSize] = '\0';
+
+    publicKey = X509_get_pubkey(cert);
+    goto_if_null(publicKey, "No public key in certificate.",
+                  TSS2_FAPI_RC_GENERAL_FAILURE, cleanup);
+
+    if (EVP_PKEY_type(EVP_PKEY_id(publicKey)) == EVP_PKEY_RSA) {
+        tpmPublic->publicArea.type = TPM2_ALG_RSA;
+        r = get_rsa_tpm2b_public_from_evp(publicKey, tpmPublic);
+        goto_if_error(r, "Get public for RSA key.", cleanup);
+
+    } else if (EVP_PKEY_type(EVP_PKEY_id(publicKey)) == EVP_PKEY_EC) {
+        tpmPublic->publicArea.type = TPM2_ALG_ECC;
+        r = get_ecc_tpm2b_public_from_evp(publicKey, tpmPublic);
+        goto_if_error(r, "Get public for ECC key.", cleanup);
+    } else {
+        goto_error(r, TSS2_FAPI_RC_NOT_IMPLEMENTED, "Wrong key_type", cleanup);
+    }
+
+    if (certAlgorithmId != NULL) {
+        switch (EVP_PKEY_id(publicKey)) {
+        case EVP_PKEY_RSA:
+            *certAlgorithmId = TPM2_ALG_RSA;
+            break;
+        case EVP_PKEY_EC:
+            *certAlgorithmId = TPM2_ALG_ECC;
+            break;
+        default:
+            goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Wrong certificate (key type).",
+                       cleanup);
+        }
+    }
+cleanup:
+    BIO_free(bio);
+    OSSL_FREE(cert, X509);
+    OSSL_FREE(publicKey, EVP_PKEY);
+    return r;
+}
+
+/**
+ * Encrypts data using AES in GCM mode.
+ *
+ * @param[in] key The key used for AES
+ * @param[in] keySize The size of key in bytes
+ * @param[in] iv The initialization vector. The size is equal to the block
+ *            length of AES (16 bytes)
+ * @param[in,out] buffer Data to be encrypted. The encrypted data will be stored
+ *                in this buffer
+ * @param[in] bufferSize The size of buffer in bytes
+ *
+ * @retval TSS2_RC_SUCCESS on success, or TSS2_FAPI_RC_BAD_VALUE and
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE if key, iv or buffer is NULL
+ * @retval TSS2_FAPI_RC_BAD_VALUE if keySize is invalid
+ * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an error occurs in the crypto library
+ */
+TSS2_RC
+ifapi_crypto_aes_encrypt(
+    const uint8_t *key,
+    size_t keySize,
+    const uint8_t *iv,
+    uint8_t *buffer,
+    size_t bufferSize)
+{
+    /* Check for NULL parameters */
+    return_if_null(key, "key is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+    return_if_null(iv, "iv is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+    return_if_null(buffer, "buffer is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    /* Initialize variables */
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    EVP_CIPHER_CTX *ctx = NULL;
+    const EVP_CIPHER *cipherAlgorithm = NULL;
+    int cipherSize = 0;
+
+    LOGBLOB_TRACE(key, keySize, "AES key");
+    LOGBLOB_TRACE(iv, keySize, "AES iv");
+    LOGBLOB_TRACE(buffer, bufferSize, "IFAPI AES input");
+
+    /* Determine the key size */
+    if (keySize == 32) {
+        cipherAlgorithm = EVP_aes_256_cfb();
+    } else if (keySize == 24) {
+        cipherAlgorithm = EVP_aes_192_cfb();
+    } else if (keySize == 16) {
+        cipherAlgorithm = EVP_aes_128_cfb();
+    } else {
+        return_error2(TSS2_FAPI_RC_BAD_VALUE, "Invalid key size %zu", keySize);
+    }
+
+    /* Create and initialize the context */
+    if (!(ctx = EVP_CIPHER_CTX_new())) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
+                   "Initialize cipher context", cleanup);
+    }
+
+    if (1 != EVP_EncryptInit_ex(ctx, cipherAlgorithm, NULL, NULL, NULL)) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
+                   "Initialize cipher operation", cleanup);
+    }
+    if (1 != EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv)) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Set key and iv", cleanup);
+    }
+
+    /* Perform the encryption */
+    if (1 != EVP_EncryptUpdate(ctx, buffer, &cipherSize, buffer, bufferSize)) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Encrypt update", cleanup);
+    }
+
+    if (1 != EVP_EncryptFinal_ex(ctx, buffer, &cipherSize)) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Encrypt final", cleanup);
+    }
+    LOGBLOB_TRACE(buffer, bufferSize, "IFAPI AES output %i", cipherSize);
+
+cleanup:
+    OSSL_FREE(ctx, EVP_CIPHER_CTX);
+    return r;
+}
+
+/**
+ * Decrypts data using AES in GCM mode.
+ *
+ * @param[in] key The key used for AES
+ * @param[in] keySize The size of key in bytes
+ * @param[in] iv The initialization vector. The size is equal to the block
+ *            length of AES (16 bytes)
+ * @param[in,out] buffer Data to be encrypted. The encrypted data will be stored
+ *                in this buffer
+ * @param[in] bufferSize The size of buffer in bytes
+ *
+ * @retval TSS2_RC_SUCCESS on success, or TSS2_FAPI_RC_BAD_VALUE and
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE if key, iv or buffer is NULL
+ * @retval TSS2_FAPI_RC_BAD_VALUE if keySize is invalid
+ * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an error occurs in the crypto library
+ */
+TSS2_RC
+ifapi_crypto_aes_decrypt(
+    const uint8_t *key,
+    size_t keySize,
+    const uint8_t *iv,
+    uint8_t *buffer,
+    size_t bufferSize
+    )
+{
+    /* Check for NULL parameters */
+    return_if_null(key, "key is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+    return_if_null(iv, "iv is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+    return_if_null(buffer, "buffer is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    /* Initialize Variables */
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    const EVP_CIPHER *cipherAlgorithm = NULL;
+    EVP_CIPHER_CTX *ctx = NULL;
+    int cipherSize = 0;
+
+    /* Determine the key size */
+    if (keySize == 32) {
+        cipherAlgorithm = EVP_aes_256_cfb();
+    } else if (keySize == 24) {
+        cipherAlgorithm = EVP_aes_192_cfb();
+    } else if (keySize == 16) {
+        cipherAlgorithm = EVP_aes_128_cfb();
+    } else {
+        return_error2(TSS2_FAPI_RC_BAD_VALUE, "Invalid key size %zu", keySize);
+    }
+
+    /* Create and initialize the context */
+    if (!(ctx = EVP_CIPHER_CTX_new())) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
+                   "Initialize cipher context", cleanup);
+    }
+
+    LOGBLOB_TRACE(key, keySize, "AES key");
+    LOGBLOB_TRACE(iv, keySize, "AES iv");
+    LOGBLOB_TRACE(buffer, bufferSize, "IFAPI AES input");
+
+    /* Initialise the decryption operation. */
+    if (1 != EVP_DecryptInit_ex(ctx, cipherAlgorithm, NULL, NULL, NULL)) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
+                   "Initialize cipher operation", cleanup);
+    }
+
+    if (1 != EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv)) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Set key and iv", cleanup);
+    }
+
+    /* Perform the decryption */
+    if (1 != EVP_DecryptUpdate(ctx, buffer, &cipherSize, buffer, bufferSize)) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Encrypt update", cleanup);
+    }
+
+    if (1 != EVP_DecryptFinal_ex(ctx, buffer, &cipherSize)) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Encrypt final", cleanup);
+    }
+    LOGBLOB_TRACE(buffer, bufferSize, "IFAPI AES output");
+
+cleanup:
+    OSSL_FREE(ctx, EVP_CIPHER_CTX);
+    return r;
+}
+
+/**
+ * Returns a suitable hash algorithm for a given digest size.
+ *
+ * @param [in]  size The size of the digest
+ * @param [out] hashAlgorithm A suitable hash algorithm for the digest size
+ *
+ * @retval TSS2_RC_SUCCESS on success
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE if hashAlgorithm is NULL
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the digest size is invalid
+ */
+TSS2_RC
+ifapi_get_hash_alg_for_size(uint16_t size, TPMI_ALG_HASH *hashAlgorithm)
+{
+    /* Check for NULL parameters */
+    return_if_null(hashAlgorithm, "hashAlgorithm is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    /* Determine the hash algorithm */
+    switch (size) {
+    case TPM2_SHA1_DIGEST_SIZE:
+        *hashAlgorithm = TPM2_ALG_SHA1;
+        return TSS2_RC_SUCCESS;
+    case TPM2_SHA256_DIGEST_SIZE:
+        *hashAlgorithm = TPM2_ALG_SHA256;
+        return TSS2_RC_SUCCESS;
+    case TPM2_SHA384_DIGEST_SIZE:
+        *hashAlgorithm = TPM2_ALG_SHA384;
+        return TSS2_RC_SUCCESS;
+    case TPM2_SHA512_DIGEST_SIZE:
+        *hashAlgorithm = TPM2_ALG_SHA512;
+        return TSS2_RC_SUCCESS;
+    default:
+        return TSS2_FAPI_RC_BAD_VALUE;
+    }
+}
+
+static X509 *get_X509_from_pem(char *pem_cert)
+{
+    if (!pem_cert) {
+        return NULL;
+    }
+    BIO *bufio = NULL;
+    X509 *cert = NULL;
+
+    /* Use BIO for conversion */
+    size_t pem_length = strlen(pem_cert);
+    bufio = BIO_new_mem_buf((void *)pem_cert, pem_length);
+    if (!bufio)
+        return NULL;
+    /* Convert the certificate */
+    cert = PEM_read_bio_X509(bufio, NULL, NULL, NULL);
+    BIO_free(bufio);
+    return cert;
+}
+
+/** Convert buffer from web to X509 certificate.
+  */
+X509 * get_cert_from_buffer(unsigned char *cert_buffer, size_t cert_buffer_size)
+{
+    unsigned char *buffer = cert_buffer;
+    X509 *cert = NULL;
+
+    unsigned const char* tmp_ptr1 = buffer;
+    unsigned const char** tmp_ptr2 = &tmp_ptr1;
+
+    if (!d2i_X509(&cert, tmp_ptr2, cert_buffer_size))
+        return NULL;
+    return cert;
+}
+
+/**
+ * Verify EK certificate read from TPM.
+ *
+ * @param [in] root_cert_pem The vendor root certificate.
+ * @param [in] intermed_cert_pem The vendor intermediate certificate.
+ * @parma [in] ek_cert_pem The ek certificate from TPM.
+ *
+ * @retval TSS2_RC_SUCCESS on success
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the verification was no successful.
+ */
+TSS2_RC
+ifapi_verify_ek_cert(
+    char* root_cert_pem,
+    char* intermed_cert_pem,
+    char* ek_cert_pem)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    X509 *root_cert = NULL;
+    X509 *intermed_cert = NULL;
+    X509 *ek_cert = NULL;
+    X509_STORE *store = NULL;
+    X509_STORE_CTX *ctx = NULL;
+    X509_CRL *crl_intermed = NULL;
+    X509_CRL *crl_ek = NULL;
+    int i;
+    size_t ui;
+    AUTHORITY_INFO_ACCESS *info = NULL;
+    ASN1_IA5STRING *uri = NULL;
+    unsigned char * url;
+    unsigned char *cert_buffer = NULL;
+    size_t cert_buffer_size;
+
+    ek_cert = get_X509_from_pem(ek_cert_pem);
+    goto_if_null2(ek_cert, "Failed to convert PEM certificate to DER.",
+                  r, TSS2_FAPI_RC_BAD_VALUE, cleanup);
+
+    if (intermed_cert_pem) {
+        intermed_cert = get_X509_from_pem(intermed_cert_pem);
+        goto_if_null2(intermed_cert, "Failed to convert PEM certificate to DER.",
+                      r, TSS2_FAPI_RC_BAD_VALUE, cleanup);
+    } else {
+        /* Get uri for ek intermediate certificate. */
+        OpenSSL_add_all_algorithms();
+        info = X509_get_ext_d2i(ek_cert, NID_info_access, NULL, NULL);
+
+        for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) {
+            ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i);
+            if (ad->location->type != GEN_URI) {
+                continue;
+            }
+            uri = ad->location->d.uniformResourceIdentifier;
+            url = uri->data;
+            r = get_cert_buffer(url, &cert_buffer, &cert_buffer_size);
+            goto_if_error(r, "Failed to receive certificate", cleanup);
+            goto_if_null2(cert_buffer, "No certificate downloaded", r,
+                          TSS2_FAPI_RC_NO_CERT, cleanup);
+        }
+        goto_if_null2(cert_buffer, "No certificate downloaded", r,
+                      TSS2_FAPI_RC_NO_CERT, cleanup);
+
+        OpenSSL_add_all_algorithms();
+        intermed_cert = get_cert_from_buffer(cert_buffer, cert_buffer_size);
+
+        goto_if_null2(intermed_cert, "Failed to create intermediate certificate.",
+                      r, TSS2_FAPI_RC_GENERAL_FAILURE, cleanup);
+
+         /* Get Certificate revocation list for Intermediate certificate */
+        r = get_crl_from_cert(intermed_cert, &crl_intermed);
+        goto_if_error(r, "Get crl for intermediate certificate.", cleanup);
+
+        /* Get Certificate revocation list for EK certificate */
+        r = get_crl_from_cert(ek_cert, &crl_ek);
+        goto_if_error(r, "Get crl for ek certificate.", cleanup);
+    }
+
+    /* Prepare X509 certificate store */
+
+    store = X509_STORE_new();
+
+    goto_if_null2(store, "Failed to create X509 store.",
+                  r, TSS2_FAPI_RC_GENERAL_FAILURE, cleanup);
+
+    /* Add Certificate revocation list for EK certificate if one exists. */
+    if (crl_ek) {
+        /* Set the flags of the store to use CRLs. */
+        X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
+        if (1 != X509_STORE_add_crl(store, crl_ek)) {
+            goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
+                       "Failed to add intermediate crl.", cleanup);
+        }
+    }
+
+    /* Add Certificate revocation list for intermediate certificate if one exists. */
+    if (crl_intermed) {
+        /* Set the flags of the store to use CRLs. */
+        X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
+        if (1 != X509_STORE_add_crl(store, crl_intermed)) {
+            goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
+                       "Failed to add intermediate crl.", cleanup);
+        }
+    }
+
+    /* Add stored root certificates */
+    for (ui = 0; ui < sizeof(root_cert_list) / sizeof(char *); ui++) {
+         root_cert = get_X509_from_pem(root_cert_list[ui]);
+         goto_if_null2(root_cert, "Failed to convert PEM certificate to DER.",
+                       r, TSS2_FAPI_RC_BAD_VALUE, cleanup);
+         if (1 != X509_STORE_add_cert(store, root_cert)) {
+             goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
+                        "Failed to add root certificate", cleanup);
+        }
+        OSSL_FREE(root_cert, X509);
+    }
+
+    /* Create root cert if passed as parameter */
+    if (root_cert_pem) {
+        root_cert = get_X509_from_pem(root_cert_pem);
+        goto_if_null2(root_cert, "Failed to convert PEM certificate to DER.",
+                      r, TSS2_FAPI_RC_BAD_VALUE, cleanup);
+
+        if (1 != X509_STORE_add_cert(store, root_cert)) {
+            goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
+                       "Failed to add root certificate", cleanup);
+        }
+    }
+
+    /* Verify intermediate certificate */
+    ctx = X509_STORE_CTX_new();
+    goto_if_null2(ctx, "Failed to create X509 store context.",
+                  r, TSS2_FAPI_RC_GENERAL_FAILURE, cleanup);
+    if (1 != X509_STORE_CTX_init(ctx, store, intermed_cert, NULL)) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
+                   "Failed to initialize X509 context.", cleanup);
+    }
+    if (1 != X509_verify_cert(ctx)) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
+                   "Failed to verify EK certificate", cleanup);
+    }
+    if (1 != X509_STORE_add_cert(store, intermed_cert)) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
+                   "Failed to add intermediate certificate", cleanup);
+    }
+
+    X509_STORE_CTX_cleanup(ctx);
+    X509_STORE_CTX_free(ctx);
+    ctx = NULL;
+    ctx = X509_STORE_CTX_new();
+    goto_if_null2(ctx, "Failed to create X509 store context.",
+                  r, TSS2_FAPI_RC_GENERAL_FAILURE, cleanup);
+
+    if (1 != X509_STORE_CTX_init(ctx, store, ek_cert, NULL)) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
+                   "Failed to initialize X509 context.", cleanup);
+    }
+    /* Verify the EK certificate. */
+    if (1 != X509_verify_cert(ctx)) {
+        int rc = X509_STORE_CTX_get_error(ctx);
+        LOG_ERROR("%s", X509_verify_cert_error_string(rc));
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
+                   "Failed to verify EK certificate", cleanup);
+    }
+
+ cleanup:
+    if (ctx) {
+        X509_STORE_CTX_cleanup(ctx);
+        X509_STORE_CTX_free(ctx);
+    }
+    if (store)
+        X509_STORE_free(store);
+    OSSL_FREE(uri, ASN1_IA5STRING)
+    OSSL_FREE(root_cert, X509);
+    OSSL_FREE(intermed_cert, X509);
+    OSSL_FREE(ek_cert, X509);
+    OSSL_FREE(crl_intermed, X509_CRL);
+    OSSL_FREE(crl_ek, X509_CRL);
+    return r;
+}
diff --git a/src/tss2-fapi/fapi_crypto.h b/src/tss2-fapi/fapi_crypto.h
new file mode 100644
index 0000000..ec90b33
--- /dev/null
+++ b/src/tss2-fapi/fapi_crypto.h
@@ -0,0 +1,132 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ ******************************************************************************/
+#ifndef FAPI_CRYPTO_H
+#define FAPI_CRYPTO_H
+
+#include "fapi_int.h"
+
+TSS2_RC
+ifapi_get_profile_sig_scheme(
+    const IFAPI_PROFILE     *profile,
+    const TPMT_PUBLIC           *tpmPublic,
+    TPMT_SIG_SCHEME             *signatureScheme);
+
+TSS2_RC
+ifapi_der_sig_to_tpm(
+    const TPMT_PUBLIC           *tpmPublic,
+    const unsigned char         *signature,
+    size_t                      signatureSize,
+    TPMI_ALG_HASH               hashAlgorithm,
+    TPMT_SIGNATURE              *tpmSignature);
+
+TSS2_RC
+ifapi_tpm_ecc_sig_to_der(
+    const TPMT_SIGNATURE        *tpmSignature,
+    uint8_t                     **signature,
+    size_t                      *signatureSize);
+
+TSS2_RC
+ifapi_pub_pem_key_from_tpm(
+    const TPM2B_PUBLIC          *tpmPublicKey,
+    char                        **pemKey,
+    int                         *pemKeySize);
+
+TSS2_RC
+ifapi_verify_signature(
+    const IFAPI_OBJECT          *keyObject,
+    const uint8_t               *signature,
+    size_t                      signatureSize,
+    const uint8_t               *digest,
+    size_t                      digestSize);
+
+TSS2_RC
+ifapi_verify_signature_quote(
+    const IFAPI_OBJECT          *keyObject,
+    const uint8_t               *signature,
+    size_t                      signatureSize,
+    const uint8_t               *digest,
+    size_t                      digestSize,
+    const TPMT_SIG_SCHEME       *signatureScheme);
+
+
+typedef struct _IFAPI_CRYPTO_CONTEXT IFAPI_CRYPTO_CONTEXT_BLOB;
+
+TSS2_RC
+ifapi_crypto_hash_start(
+    IFAPI_CRYPTO_CONTEXT_BLOB   **context,
+    TPM2_ALG_ID                 hashAlgorithm);
+
+TSS2_RC
+ifapi_crypto_hash_update(
+    IFAPI_CRYPTO_CONTEXT_BLOB   *context,
+    const uint8_t               *buffer,
+    size_t                      size);
+
+TSS2_RC
+ifapi_crypto_hash_finish(
+    IFAPI_CRYPTO_CONTEXT_BLOB   **context,
+    uint8_t                     *digest,
+    size_t                      *digestSize);
+
+void
+ifapi_crypto_hash_abort(
+    IFAPI_CRYPTO_CONTEXT_BLOB   **context);
+
+TSS2_RC
+ifapi_cert_to_pem(
+    const uint8_t               *certBuffer,
+    size_t                      certBufferSize,
+    char                        **pemCert,
+    TPM2_ALG_ID                 *certAlgorithmId,
+    TPM2B_PUBLIC                *tpmPublic);
+
+size_t
+ifapi_hash_get_digest_size(
+    TPM2_ALG_ID                 hashAlgorithm);
+
+TSS2_RC
+ifapi_get_tpm2b_public_from_pem(
+    const char                  *pemKey,
+    TPM2B_PUBLIC                *tpmPublic);
+
+TSS2_RC
+ifapi_crypto_aes_encrypt(
+    const uint8_t               *key,
+    size_t                      keySize,
+    const uint8_t               *iv,
+    uint8_t                     *buffer,
+    size_t                      bufferSize);
+
+TSS2_RC
+ifapi_crypto_aes_decrypt(
+    const uint8_t               *key,
+    size_t                      keySize,
+    const uint8_t               *iv,
+    uint8_t                     *buffer,
+    size_t                      bufferSize
+    );
+
+TSS2_RC
+ifapi_get_hash_alg_for_size(
+    uint16_t                    size,
+    TPMI_ALG_HASH               *hashAlgorithm);
+
+TSS2_RC
+ifapi_initialize_sign_public(
+    TPM2_ALG_ID                 signatureAlgorithm,
+    TPM2B_PUBLIC                *template);
+
+TPM2_ALG_ID
+ifapi_get_signature_algorithm_from_pem(
+    const char                  *pemKey);
+
+TSS2_RC
+ifapi_verify_ek_cert(
+    char* root_cert_pem,
+    char* intermed_cert_pem,
+    char* ek_cert_pem);
+
+#endif /* FAPI_CRYPTO_H */
diff --git a/src/tss2-fapi/fapi_int.h b/src/tss2-fapi/fapi_int.h
new file mode 100644
index 0000000..a1affbb
--- /dev/null
+++ b/src/tss2-fapi/fapi_int.h
@@ -0,0 +1,1251 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ ******************************************************************************/
+#ifndef FAPI_INT_H
+#define FAPI_INT_H
+
+#include "fapi_types.h"
+#include "ifapi_policy_types.h"
+#include "ifapi_policy_instantiate.h"
+#include "ifapi_eventlog.h"
+#include "ifapi_io.h"
+#include "ifapi_profiles.h"
+#include "ifapi_macros.h"
+#include "ifapi_keystore.h"
+#include "ifapi_policy_store.h"
+#include "ifapi_object.h"
+#include "ifapi_config.h"
+//#include "ifapi_policy_execute.h"
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <inttypes.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <json-c/json.h>
+#include <poll.h>
+
+#include "tss2_esys.h"
+#include "tss2_fapi.h"
+
+#define TPM2_YES_NO TPMI_YES_NO
+
+#define DEFAULT_KEY_PROFILE "P_RSA"
+#define ENV_LOG_DIR "FAPI_TEST_LOGDIR"
+#define DEFAULT_LOG_DIR "/run/tpm2_tss"
+#define IFAPI_PCR_LOG_FILE "pcr.log"
+#define DEFAULT_HIERARCHY "HS"
+#define DEFAULT_KEY_NAME "key"
+
+#define IFAPI_OBJECT_TYPE ".json"
+#define IFAPI_OBJECT_FILE "object.json"
+#define IFAPI_EK_KEY_PATH "HE/EK"
+#define IFAPI_SRK_KEY_PATH "HS/SRK"
+
+typedef UINT32 TSS2_KEY_TYPE;
+#define TSS2_ASYM_STORAGE_KEY 1
+#define TSS2_SRK 2
+#define TSS2_EK 3
+#define TSS2_ASYM_RESTRICTED_SIGNING_KEY 4
+#define TSS2_HMAC_KEY 5
+#define MIN_EK_CERT_HANDLE 0x1c00000
+#define MAX_EK_CERT_HANDLE 0x1c07fff
+#define MIN_PLATFORM_CERT_HANDLE 0x01C08000
+#define MAX_PLATFORM_CERT_HANDLE 0x01C0FFFF
+
+typedef UINT8 IFAPI_SESSION_TYPE;
+#define IFAPI_SESSION_GENEK 0x01
+#define IFAPI_SESSION1      0x02
+#define IFAPI_SESSION2      0x04
+
+#define IFAPI_POLICY_PATH "policy"
+#define IFAPI_NV_PATH "nv"
+#define IFAPI_EXT_PATH "ext"
+#define IFAPI_FILE_DELIM "/"
+#define IFAPI_LIST_DELIM ":"
+#define IFAPI_FILE_DELIM_CHAR '/'
+#define IFAPI_PUB_KEY_DIR "ext"
+#define IFAPI_POLICY_DIR "policy"
+#define IFAPI_PEM_PUBLIC_STRING "-----BEGIN PUBLIC KEY-----"
+#define IFAPI_PEM_CERT_STRING "-----BEGIN CERTIFICATE-----"
+#define IFAPI_PEM_PRIVATE_KEY "-----PRIVATE KEY-----"
+#define IFAPI_JSON_TAG_FOR_KEY "persistent_handle"
+#define IFAPI_JSON_TAG_PUBLIC "public"
+#define IFAPI_JSON_TAG_FOR_NV_OBJECT "nv_object"
+#define IFAPI_JSON_TAG_CERTIFICATE "certificate"
+#define IFAPI_JSON_TAG_EXT_PUB_KEY "pem_ext_public"
+#define IFAPI_JSON_TAG_POLICY "policy"
+#define IFAPI_JSON_TAG_POLICY_HARNESS "policy_harness"
+
+
+#if TPM2_MAX_NV_BUFFER_SIZE > TPM2_MAX_DIGEST_BUFFER
+#define IFAPI_MAX_BUFFER_SIZE TPM2_MAX_NV_BUFFER_SIZE
+#else
+#define IFAPI_MAX_BUFFER_SIZE TPM2_MAX_DIGEST_BUFFER
+#endif
+
+#define IFAPI_FLUSH_PARENT true
+#define IFAPI_NOT_FLUSH_PARENT false
+
+/* Definition of FAPI buffer for TPM2B transmission */
+typedef struct {
+    UINT16 size;
+    BYTE buffer[IFAPI_MAX_BUFFER_SIZE];
+} IFAPI_MAX_BUFFER;
+
+#define OSSL_FREE(S,TYPE) if((S) != NULL) {TYPE##_free((void*) (S)); (S)=NULL;}
+
+
+#define FAPI_COPY_DIGEST(dest_buffer, dest_size, src, src_size) \
+    if (src_size > sizeof(TPMU_HA)) { \
+        return_error(TSS2_FAPI_RC_BAD_VALUE, "Digest size too large."); \
+    } \
+    memcpy(dest_buffer, (src), (src_size));  \
+    dest_size = src_size
+
+/** Macro testing parameters against null.
+ */
+#define _FAPI_ASSERT_NON_NULL(x) \
+    if (x == NULL) { \
+        LOG_ERROR(str(x) " == NULL."); \
+        return TSS2_ESYS_RC_BAD_REFERENCE; \
+    }
+
+#define HASH_UPDATE(CONTEXT, TYPE, OBJECT, R, LABEL)    \
+    { \
+        uint8_t buffer[sizeof(TYPE)]; \
+        size_t offset = 0; \
+        R = Tss2_MU_ ## TYPE ## _Marshal(OBJECT, \
+                                         &buffer[0], sizeof(TYPE), &offset); \
+        goto_if_error(R, "Marshal for hash update", LABEL); \
+        R = ifapi_crypto_hash_update(CONTEXT, \
+                                     (const uint8_t *) &buffer[0], \
+                                     offset);                     \
+        goto_if_error(R, "crypto hash update", LABEL); }
+
+#define HASH_UPDATE_BUFFER(CONTEXT, BUFFER, SIZE, R, LABEL) \
+    R = ifapi_crypto_hash_update(CONTEXT, \
+                                 (const uint8_t *) BUFFER, SIZE) ; \
+    goto_if_error(R, "crypto hash update", LABEL);
+
+#define MARSHAL_BUFFER(TYPE, OBJECT, BUFFER, SIZE, OFFSET, R, LABEL) \
+    R = Tss2_MU_ ## TYPE ## _Marshal(OBJECT, \
+                                     &BUFFER[OFFSET], SIZE, &OFFSET); \
+    goto_if_error(R, "Marshal buffer", LABEL);
+
+#define MARSHAL_OBJECT(TYPE, OBJECT, BUFFER, SIZE, OFFSET, R, LABEL) \
+    R = Tss2_MU_ ## TYPE ## _Marshal(OBJECT, \
+                                     &BUFFER[OFFSET], SIZE, &OFFSET); \
+    goto_if_error(R, "Marshal buffer", LABEL);
+
+
+#define HASH_UPDATE_2B(CONTEXT, OBJECT, R, LABEL) \
+    R = ifapi_crypto_hash_update(CONTEXT, \
+                                 (const uint8_t *) OBJECT.buffer, OBJECT->size) ; \
+    goto_if_error(R, "crypto hash update", LABEL); }
+
+#define FAPI_SYNC(r,msg,label, ...)             \
+    if ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN) \
+        return TSS2_FAPI_RC_TRY_AGAIN; \
+    if (r != TSS2_RC_SUCCESS) { \
+        LOG_ERROR(TPM2_ERROR_FORMAT " " msg, TPM2_ERROR_TEXT(r), ## __VA_ARGS__); \
+        goto label;  \
+    }
+
+/** Type of resource
+ */
+typedef UINT32 IFAPI_ENCRYPTION_TYPE;
+#define IFAPI_SYM_BULK_ENCRYPTION      1    /**< Tag for key resource */
+#define IFAPI_ASYM_BULK_ENCRYPTION      1    /**< Tag for key resource */
+#define IFAPI_ASYM_ENCRYPTION          2    /**< Tag for key resource */
+#define IFAPI_SYSM_ENCRYPTON_WRAPPED   2    /**< Tag for NV Ram resource */
+
+/** Type of resource
+ */
+
+
+/** The states for the FAPI's object authorization state*/
+enum IFAPI_GET_CERT_STATE {
+    GET_CERT_INIT = 0,
+    GET_CERT_WAIT_FOR_GET_CAP,
+    GET_CERT_GET_CERT_NV,
+    GET_CERT_GET_CERT_NV_FINISH,
+    GET_CERT_GET_CERT_READ_PUBLIC,
+    GET_CERT_READ_CERT
+};
+
+/** The states for the FAPI's cleanup after successful command execution*/
+enum IFAPI_CLEANUP_STATE {
+    CLEANUP_INIT = 0,
+    CLEANUP_SESSION1,
+    CLEANUP_SESSION2,
+    CLEANUP_SRK
+};
+
+#define IFAPI_MAX_CAP_INFO 17
+
+typedef struct {
+    char                                  *description;
+    TPMS_CAPABILITY_DATA                   *capability;
+} IFAPI_CAP_INFO;
+
+typedef struct {
+    char                                 *fapi_version;    /**< The version string of FAPI */
+    char                                  *fapi_config;    /**< The configuration information */
+    IFAPI_CAP_INFO             cap[IFAPI_MAX_CAP_INFO];
+} IFAPI_INFO;
+
+/** Type for representing FAPI profile for keys
+ */
+typedef struct {
+    TPMI_ALG_PUBLIC                                type;    /**< The algorithm used for key creation */
+    char                                  *srk_template;    /**< name of SRK template */
+    char                                   *ek_template;    /**< name of EK template */
+    TPMT_SIG_SCHEME                  ecc_signing_scheme;    /**< < Signing scheme for the ECC key. */
+    TPMT_SIG_SCHEME                  rsa_signing_scheme;    /**< < Signing scheme for the RSA key. */
+    TPMT_RSA_DECRYPT                 rsa_decrypt_scheme;    /**< < Decrypt scheme for the RSA key. */
+    TPMI_ALG_SYM_MODE                          sym_mode;    /**< < Mode for symmectric encryption. */
+    TPMT_SYM_DEF_OBJECT                  sym_parameters;    /**< < Parameters for symmectric encryption. */
+    UINT16                               sym_block_size;    /**< < Block size for symmectric encryption. */
+    TPML_PCR_SELECTION                    pcr_selection;    /**< < Parameters for symmectric encryption. */
+    TPMI_ALG_HASH                               nameAlg;
+    TPMI_RSA_KEY_BITS                           keyBits;
+    UINT32                                     exponent;
+    TPMI_ECC_CURVE                              curveID;
+    TPMT_SYM_DEF                      session_symmetric;
+    TPMS_POLICY_HARNESS                      *eh_policy;
+    TPMS_POLICY_HARNESS                      *sh_policy;
+    TPMS_POLICY_HARNESS                 *lockout_policy;
+    UINT32                                  newMaxTries;
+    UINT32                              newRecoveryTime;
+    UINT32                              lockoutRecovery;
+} IFAPI_KEY_PROFILE;
+
+/** Type for representing FAPI template for keys
+ */
+typedef struct {
+    TPMI_YES_NO                                  system;    /**< Store the object in the system wide
+                                                                 directory */
+    TPMI_YES_NO                              persistent;    /**< Store key persistent in NV ram. */
+    UINT32                            persistent_handle;    /**< < Persistent handle which should be used */
+    TPM2B_PUBLIC                                 public;    /**< Template for public data */
+} IFAPI_KEY_TEMPLATE;
+
+/** Type for representing template for NV objects
+ */
+typedef struct {
+    TPMI_YES_NO                                  system;    /**< Store the object in the system wide
+                                                                 directory */
+    TPMI_RH_HIERARCHY                         hierarchy;    /**< Hierarchy for NV object. */
+    char                                   *description;    /**< Description of template. */
+    TPMS_NV_PUBLIC                               public;    /**< Template for public data */
+} IFAPI_NV_TEMPLATE;
+
+/** Type for representing a external public key
+ */
+typedef struct {
+    TPMT_SIG_SCHEME                          sig_scheme;    /**< Signature scheme used for quote. */
+    TPMS_ATTEST                                  attest;    /**< Attestation data from Quote */
+} FAPI_QUOTE_INFO;
+
+
+/** The states for the FAPI's NV read state */
+enum _FAPI_STATE_NV_READ {
+    NV_READ_INIT = 0,
+    NV_READ_AUTHORIZE,
+    NV_READ_AUTH_SENT,
+    NV_READ_WRITE
+};
+
+/** The states for the FAPI's NV write state */
+enum _FAPI_STATE_NV_WRITE {
+    NV2_WRITE_INIT = 0,
+    NV2_WRITE_READ,
+    NV2_WRITE_EXEC_ESYS,
+    NV2_WRITE_NULL_AUTH_SENT,
+    NV2_WRITE_AUTH_SENT,
+     NV2_WRITE_WRITE_PREPARE,
+    NV2_WRITE_WRITE,
+    NV2_WRITE_AUTHORIZE
+};
+
+/** The data structure holding internal state of Fapi NV commands.
+ */
+typedef struct {
+    char *nvPath ;              /**< The name of the file for object serialization */
+    char *policyPath;           /**< The name of the policy file */
+    TPM2B_NV_PUBLIC public;     /**< The public info of the NV object. */
+    ESYS_TR esys_auth_handle;   /**< The ESAPI handle for the NV auth object */
+    ESYS_TR esys_handle;        /**< The ESAPI handle for the NV object */
+    size_t numBytes;            /**< The number of bytes of a ESYS request */
+    UINT16 bytesRequested;      /**< Bytes currently requested from TPM */
+    UINT16 offset;              /**< Offset in TPM memory TPM */
+    size_t data_idx;            /**< Offset in the read buffer */
+    const uint8_t *data;        /**< Buffer for data to be written */
+    uint8_t *rdata;             /**< Buffer for data to be read */
+    IFAPI_OBJECT auth_object;   /**< Object used for authentication */
+    IFAPI_OBJECT nv_object;     /**< Deserialized NV object */
+    TPM2B_AUTH auth;            /**< The Password */
+    IFAPI_NV nv_obj;            /**< The NV Object */
+    ESYS_TR auth_index;         /**< The ESAPI handle of the authorization object */
+    uint64_t bitmap;            /**< The bitmask for the SetBits command */
+    IFAPI_NV_TEMPLATE public_templ; /**< The template for nv creation, adjusted
+                                         appropriate by the passed flags */
+    enum _FAPI_STATE_NV_READ nv_read_state; /**< The current state of NV read */
+    enum _FAPI_STATE_NV_WRITE nv_write_state; /**< The current state of NV write*/
+    uint8_t *write_data;
+    char const *logData;         /**< The event log for NV objects of type pcr */
+    json_object *jso_event_log;  /**< logData in JSON format */
+    TPMI_RH_NV_INDEX maxNvIndex; /**< Max index for search for free index  */
+    IFAPI_EVENT pcr_event;       /**< Event to be added to log */
+    TPML_DIGEST_VALUES digests;  /**< Digest for teh event data of an extend */
+    bool skip_policy_computation; /**< switch whether policy needs to be computed */
+} IFAPI_NV_Cmds;
+
+
+/** Type for representing a FAPI encrypted data.
+ */
+typedef struct {
+    UINT32                                         type;    /**< Tag for encryption type. */
+    TPM2B_NAME                                 key_name;    /**<  Path to the encryption key. */
+    UINT8_ARY                                    cipher;    /**< None */
+    UINT8_ARY                               sym_private;    /**< Private data of encrypted sym key */
+    TPM2B_PUBLIC                             sym_public;    /**< The public information of the sym key object */
+    UINT32                                 sym_key_size;
+    TPM2B_DIGEST                                 sym_iv;
+    struct TPMS_POLICY_HARNESS       sym_policy_harness;
+} IFAPI_ENCRYPTED_DATA;
+
+/** The data structure storing a pem cerrificate with tpm_public_key.
+ */
+typedef struct {
+    TPMU_PUBLIC_ID unique;
+    TPM2_ALG_ID alg;
+    char *pem_cert;
+} IFAPI_CERT_BUFFER;
+
+/** The data structure holding internal state of Fapi_Initialize command.
+ */
+typedef struct {
+    TPMS_CAPABILITY_DATA *capability; /* TPM capability data to check available algs */
+} IFAPI_INITIALIZE;
+
+/** The data structure holding internal state of Fapi_PCR commands.
+ */
+typedef struct {
+    TPML_DIGEST_VALUES digest_list;    /**< The digest list computed for the event  */
+    TPML_DIGEST_VALUES *event_digests; /**< The digest list computed by TPM2_Event  */
+    ESYS_TR PCR;                       /**< The handle of the PCR register to be extended */
+    TPML_PCR_SELECTION pcr_selection;  /**< Selection used for Read and Quote */
+    TPML_PCR_SELECTION *pcr_selection_out; /**< Selection returned by PCR_Read  */
+    UINT32 update_count;
+    TPML_DIGEST *pcrValues;            /* The values returned by PCR_Read */
+    TPM2_HANDLE pcrIndex;
+    TPMI_ALG_HASH hashAlg;
+    const char *keyPath;              /**< The implicit key path for PCR_Quote */
+    ESYS_TR handle;                   /**< The ESYS handle of the signing key */
+    IFAPI_OBJECT *key_object;         /**< The IPAPI object of the signing key */
+    TPMS_CAPABILITY_DATA *capabilityData; /* TPM capability data to check available algs */
+    uint32_t *pcrList;                 /**< Array of PCR numbers */
+    size_t pcrListSize;                /**< Size of PCR array */
+    TPM2B_DATA qualifyingData;         /**< Nonce for quote command */
+    uint8_t  const *eventData;
+    TPM2B_EVENT event;
+    size_t eventDataSize;
+    uint32_t const *hashAlgs;
+    uint32_t *hashAlgs2;
+    size_t numHashAlgs;
+    char    const *quoteInfo;
+    TPM2B_ATTEST *tpm_quoted;
+    TPMT_SIGNATURE *tpm_signature;
+    uint8_t const *signature;
+    size_t signatureSize;
+    char const *logData;
+    char *pcrLog;
+    IFAPI_EVENT pcr_event;
+    json_object *event_list;
+    FAPI_QUOTE_INFO fapi_quote_info;
+} IFAPI_PCR;
+
+/** The data structure holding internal state of Fapi_SetDescription.
+ */
+typedef struct {
+    char *description;             /**< The description of the object */
+    UINT8_ARY appData;             /**< Application data to be stored in object store. */
+    IFAPI_OBJECT object;           /**< The IPAPI object to store the info*/
+    char *object_path;             /**< The realative path to the object */
+    json_object *jso;              /**< JSON object for storing the AppData */
+    char *jso_string;              /**< JSON deserialized buffer */
+} IFAPI_Path_SetDescription;
+
+/** The data structure holding internal state of Fapi_GetRandom.
+ */
+typedef struct {
+    size_t numBytes;              /**< The number of random bytes to be generated */
+    size_t idx;                   /**< Current position in output buffer.  */
+    UINT16 bytesRequested;        /**< Byted currently requested from TPM */
+    uint8_t *data;                /**< The buffer for the random data */
+} IFAPI_GetRandom;
+
+/** The data structure holding internal state of Fapi_Key_Setcertificate.
+ */
+typedef struct {
+    const char *pem_cert;        /**< The certifificate in pem or format */
+    char *pem_cert_dup;          /**< The allocate certifificate */
+    const char *key_path;        /**< The absolute key path */
+    NODE_STR_T *path_list;       /**< The computed explicit path */
+    IFAPI_OBJECT key_object;     /**< The IPAPI object for the certified key */
+} IFAPI_Key_SetCertificate;
+
+/** The states for the FAPI's key creation */
+enum IFAPI_KEY_CREATE_STATE {
+    KEY_CREATE_INIT = 0,
+    KEY_CREATE_READ_PROFILE,
+    KEY_CREATE_WAIT_FOR_SESSION,
+    KEY_CREATE_WAIT_FOR_PARENT,
+    KEY_CREATE_NULL_AUTH_SENT,
+    KEY_CREATE_AUTH_SENT,
+    KEY_CREATE_CREATED,
+    KEY_CREATE_WRITE_PREPARE,
+    KEY_CREATE_WRITE,
+    KEY_CREATE_FLUSH,
+    KEY_CREATE_LOAD_POLICY,
+    KEY_CREATE_CALCULATE_POLICY,
+    KEY_CREATE_WRITE_POLICY,
+    KEY_CREATE_WAIT_FOR_AUTHORIZATION,
+    KEY_CREATE_CLEANUP
+};
+
+/** The data structure holding internal state of Fapi_CreateKey.
+ */
+typedef struct {
+    enum IFAPI_KEY_CREATE_STATE state;
+    const char *keyPath;         /**< The pathname from the application */
+    NODE_STR_T *path_list;       /**< The computed explicit path */
+    IFAPI_OBJECT parent;         /**< The parent of the key for used for creation. */
+    IFAPI_OBJECT object;          /**< The current object. */
+    IFAPI_KEY_TEMPLATE public_templ;  /**< The template for the keys public data */
+    TPM2B_PUBLIC public;         /**< The public data of the key */
+    TPM2B_SENSITIVE_CREATE inSensitive;
+    TPM2B_DATA outsideInfo;
+    TPML_PCR_SELECTION creationPCR;
+    ESYS_TR handle;
+    const char *authValue;
+    const char *policyPath;
+    const IFAPI_PROFILE *profile;
+} IFAPI_Key_Create;
+
+/** The data structure holding internal state of Fapi_EncryptDecrypt.
+ */
+typedef struct {
+    char const *keyPath;            /**< The implicit key path */
+    char const *policyPath;
+    uint8_t const *in_data;
+    size_t in_dataSize;
+    IFAPI_OBJECT *key_object;       /**< The IPAPI object for the encryption key */
+    uint8_t *out_data;               /**< The output of symmetric encrypt/decryption */
+    ESYS_TR key_handle;                 /**< The ESYS handle of the encryption key */
+    TPM2B_IV iv;                    /**< The symmetric iv value */
+    size_t numBytes;                /**< The number of bytes of a ESYS request */
+    size_t decrypt;                 /**< Switch whether to encrypt or decrypt */
+    UINT16 bytesRequested;          /**< Bytes currently requested from TPM */
+    size_t data_idx;                /**< Offset in the read buffer */
+    char **pathlist;                /**< The array of all objects  in the search path */
+    size_t path_idx;                /**< Index of array of objects to be searched */
+    size_t numPaths;                /**< Number of all objects in data store */
+    TPMI_ALG_SYM_MODE sym_mode;
+    TPMT_RSA_DECRYPT rsa_scheme;
+    IFAPI_ENCRYPTED_DATA enc_data;
+    /* Fields uses for the sealed symmetric key */
+    uint8_t *sym_key;
+    IFAPI_KEY_TEMPLATE sym_template;
+    TPM2B_SENSITIVE_CREATE sym_sensitive;
+    TPM2B_DATA sym_outsideInfo;
+    TPML_PCR_SELECTION sym_creationPCR;
+    TPM2B_PRIVATE *outPrivate;
+    TPM2B_PUBLIC *outPublic;
+    ESYS_TR object_handle;
+    char *policy_path;
+    ESYS_TR auth_session;
+} IFAPI_Data_EncryptDecrypt;
+
+/** The states for signing  */
+enum FAPI_SIGN_STATE {
+    SIGN_INIT = 0,
+    SIGN_WAIT_FOR_PROFILE,
+    SIGN_WAIT_FOR_SESSION,
+    SIGN_WAIT_FOR_KEY,
+    SIGN_KEY_LOADED,
+    SIGN_AUTHORIZE,
+    SIGN_AUTH_SENT,
+    SIGN_NULL_AUTH_SENT,
+    SIGN_WAIT_FOR_FLUSH,
+    SIGN_CALL,
+    SIGN_EXEC_POLICY
+};
+
+/** The data structure holding internal state of Fapi_Sign.
+ */
+typedef struct {
+    enum FAPI_SIGN_STATE state;          /**< The state of the signing operation */
+    const char *keyPath;            /**< The implicit key path */
+    ESYS_TR handle;                 /**< The ESYS handle of the signing key */
+    TPM2B_DIGEST digest;            /**< The digest to be signed */
+    TPMT_SIG_SCHEME scheme;         /**< The signature scheme from profile */
+    IFAPI_OBJECT *key_object;       /**< The IPAPI object of the signing key */
+    TPMT_SIGNATURE *tpm_signature;  /**< The signature in TPM format */
+    TPMI_YES_NO decrypt;            /**< Switch for symmetric algs */
+    TPMT_SIGNATURE *signature;      /**< Produced TPM singature */
+    char const *padding;            /**< Optional padding parameter for key sign. */
+} IFAPI_Key_Sign;
+
+/** The data structure holding internal state of Fapi_Unseal.
+ */
+typedef struct {
+    const char *keyPath;            /**< The implicit key path */
+    IFAPI_OBJECT *object;           /**< The IPAPI object storing the data to be unsealed */
+    TPM2B_SENSITIVE_DATA *unseal_data; /** The result of the esys unseal operation */
+} IFAPI_Unseal;
+
+
+/** The data structure holding internal state of Fapi_GetInfo.
+ */
+typedef struct {
+    TPMS_CAPABILITY_DATA *capability_data;   /**< The TPM capability for one property */
+    TPMS_CAPABILITY_DATA *fetched_data;       /**< The data fetched in one TPM command */
+    size_t idx_info_cap;
+    IFAPI_INFO  info_obj;
+    UINT32 property_count;
+    UINT32 property;
+} IFAPI_GetInfo;
+
+/** The states for the FAPI's hierarchy authorization state*/
+enum IFAPI_HIERACHY_AUTHORIZATION_STATE {
+    HIERARCHY_CHANGE_AUTH_INIT = 0,
+    HIERARCHY_CHANGE_AUTH_NULL_AUTH_SENT,
+    HIERARCHY_CHANGE_AUTH_AUTH_SENT
+};
+
+/** The states for the FAPI's change policy authorization state*/
+enum IFAPI_HIERACHY_POLICY_AUTHORIZATION_STATE {
+    HIERARCHY_CHANGE_POLICY_INIT = 0,
+    HIERARCHY_CHANGE_POLICY_NULL_AUTH_SENT,
+    HIERARCHY_CHANGE_POLICY_AUTH_SENT
+};
+
+/** The data structure holding internal state of Fapi_ChangeAuth.
+ */
+typedef struct {
+    const char *entityPath;         /**< The implicit key path */
+    ESYS_TR handle;                 /**< The ESYS handle of the key */
+    IFAPI_OBJECT *key_object;       /**< The IPAPI object of the key */
+    const char  *authValue;         /**< The new auth value */
+    TPM2B_AUTH newAuthValue;        /**< The new auth value */
+    TPM2B_PRIVATE *newPrivate;      /**< New private data created by parend */
+    IFAPI_OBJECT object;            /**< Deserialized NV object or hierarchy */
+    ESYS_TR nv_index;               /**< NV handle of the object to be changed */
+    ESYS_TR hierarchy_handle;       /**< NV handle of the hierarchy to be changed */
+} IFAPI_Entity_ChangeAuth;
+
+/** The data structure holding internal state of Fapi_AuthorizePolicy.
+ */
+typedef struct {
+    const char *policyPath;           /**< Policy with Policy to be authorized */
+    const char *signingKeyPath;       /**< Key for policy signing */
+    TPM2B_DIGEST policyRef;
+    TPMS_POLICYAUTHORIZATION  authorization;
+} IFAPI_Fapi_AuthorizePolicy;
+
+/** The data structure holding internal state of Fapi_WriteAuthorizeNv.
+ */
+typedef struct {
+    const char *policyPath;            /**< Policy with Policy to be authorized */
+    TPMI_ALG_HASH *hash_alg;           /**< The hash alg used for digest computation */
+    size_t hash_size;                  /**< The digest size */
+    size_t digest_idx;                 /**< The index of the digest in the harness */
+} IFAPI_api_WriteAuthorizeNv;
+
+/** The data structure holding internal state of Provisioning.
+ */
+typedef struct {
+    IFAPI_OBJECT hierarchy;     /**< The current used hierarchy for CreatePrimary */
+    IFAPI_KEY_TEMPLATE public_templ;  /**< The basic template for the keys public data */
+    TPM2B_PUBLIC public;       /**< The public info of the created primary */
+    TPM2B_SENSITIVE_CREATE inSensitive;
+    TPM2B_DATA outsideInfo;
+    TPML_PCR_SELECTION creationPCR;
+    ESYS_TR handle;
+    const char *authValueLockout;
+    const char *authValueEh;
+    const char *policyPathEh;
+    const char *authValueSh;
+    const char *policyPathSh;
+    size_t digest_idx;
+    size_t hash_size;
+    TPM2_HANDLE cert_nv_idx;
+    ESYS_TR esys_nv_cert_handle;
+    char *pem_cert;
+    TPM2_ALG_ID cert_key_type;
+    size_t cert_count;
+    size_t cert_idx;
+    TPMS_CAPABILITY_DATA *capabilityData;
+    IFAPI_OBJECT hierarchy_object;
+    TPM2B_AUTH hierarchy_auth;
+    TPM2B_DIGEST policy_digest;
+    char *intermed_crt;
+    char *root_crt;
+} IFAPI_Provision;
+
+/** The data structure holding internal state of regenerate primary key.
+ */
+typedef struct {
+    char *path;                   /**< Path of the primary (starting with hierarchy)  */
+    IFAPI_OBJECT hierarchy;     /**< The current used hierarchy for CreatePrimary */
+    IFAPI_OBJECT pkey_object;
+    TPM2B_SENSITIVE_CREATE inSensitive;
+    TPM2B_DATA outsideInfo;
+    TPML_PCR_SELECTION creationPCR;
+    ESYS_TR handle;
+    TPMI_DH_PERSISTENT persistent_handle;
+} IFAPI_CreatePrimary;
+
+/** The data structure holding internal state of key verify signature.
+ */
+typedef struct {
+    const char    *keyPath;
+    uint8_t const *signature;
+    size_t         signatureSize;
+    uint8_t const *digest;
+    size_t         digestSize;
+    IFAPI_OBJECT   key_object;
+} IFAPI_Key_VerifySignature;
+
+/** The states for the FAPI's policy loading */
+enum IFAPI_STATE_POLICY {
+    POLICY_INIT = 0,
+    POLICY_READ,
+    POLICY_READ_FINISH,
+    POLICY_INSTANTIATE_PREPARE,
+    POLICY_INSTANTIATE,
+    POLICY_INIT_CACHE,
+    POLICY_INIT_CACHE_READ,
+    POLICY_READ_CACHE,
+    POLICY_READ_CACHE_GET_JSON,
+    POLICY_WRITE,
+    POLICY_CALCULATE,
+    POLICY_EXECUTE,
+    POLICY_SESSION,
+    POLICY_FLUSH,
+    POLICY_NEW
+};
+
+typedef struct IFAPI_POLICY_EXEC_CTX IFAPI_POLICY_EXEC_CTX;
+typedef struct IFAPI_POLICYUTIL_STACK IFAPI_POLICYUTIL_STACK;
+
+/** The states for session creation */
+enum FAPI_CREATE_SESSION_STATE {
+    CREATE_SESSION_INIT = 0,
+    CREATE_SESSION,
+    WAIT_FOR_CREATE_SESSION,
+    CREATE_SESSION_WAIT_FOR_FLUSH
+};
+
+/** The data structure holding internal policy state.
+ */
+typedef struct {
+    enum IFAPI_STATE_POLICY state;
+    struct TPMS_POLICY_HARNESS harness;
+    size_t digest_idx;
+    size_t hash_size;
+    char **pathlist;                  /**< The array of all objects  in the search path */
+    TPMI_ALG_HASH hash_alg;
+    IFAPI_POLICY_EXEC_CTX *policy_stack; /**< The stack used for storing current policy information.
+                                           e.g. for retry the current index of policy elements hash
+                                           to be stored. */
+    IFAPI_POLICYUTIL_STACK *util_current_policy;
+    IFAPI_POLICYUTIL_STACK *policyutil_stack;
+                                      /**< The stack used for storing current policy information.
+                                            e.g. for retry the current index of policy elements hash
+                                           to be stored. */
+    ESYS_TR session;                  /**< Auxiliary variable to store created policy session.
+                                           The value will also be stored in the policy stack */
+    enum FAPI_CREATE_SESSION_STATE create_session_state;
+    char *path;
+    IFAPI_POLICY_EVAL_INST_CTX eval_ctx;
+} IFAPI_POLICY_CTX;
+
+/** The states for the IFAPI's policy loading */
+enum IFAPI_STATE_FILE_SEARCH {
+    FSEARCH_INIT = 0,
+    FSEARCH_READ,
+    FSEARCH_OBJECT
+};
+
+/** The data structure holding internal policy state.
+ */
+typedef struct {
+    enum IFAPI_STATE_FILE_SEARCH state;
+    char **pathlist;                /**< The array of all objects  in the search path */
+    size_t path_idx;                /**< Index of array of objects to be searched */
+    size_t numPaths;                /**< Number of all objects in data store */
+    char *current_path;
+} IFAPI_FILE_SEARCH_CTX;
+
+/** The states for the FAPI's key loading */
+enum _FAPI_STATE_LOAD_KEY {
+    LOAD_KEY_INIT = 0,
+    LOAD_KEY_GET_PATH,
+    LOAD_KEY_READ_KEY,
+    LOAD_KEY_WAIT_FOR_PRIMARY,
+    LOAD_KEY_LOAD_KEY,
+    LOAD_KEY_AUTH,
+    LOAD_KEY_AUTHORIZE
+};
+
+/** The data structure holding internal state of export key.
+ */
+typedef struct {
+    char   const *pathOfKeyToDuplicate;          /**< The relative path of the key to be exported */
+    char   const *pathToPublicKeyOfNewParent;    /**<  The relative path of the new parent */
+    TPM2B_PUBLIC public_parent;                  /**< The public key of the new parent */
+    IFAPI_OBJECT *key_object;                    /**< The IPAPI object of the key to be duplicated */
+    IFAPI_OBJECT export_tree;                    /**< The complete tree to be exported */
+    IFAPI_OBJECT pub_key;                        /**< The public part of the new parent */
+    IFAPI_OBJECT dup_key;                        /**< The key to be duplicated or exported  */
+    struct TPMS_POLICY_HARNESS harness;
+    ESYS_TR handle_ext_key;
+} IFAPI_ExportKey;
+
+/** The data structure holding internal state of export policy.
+ */
+typedef struct {
+    char   const *path;                          /**<  Path of the object with the policy to be
+                                                       exported */
+    IFAPI_OBJECT object;                         /**<  Object corresponding to path */
+} IFAPI_ExportPolicy;
+
+/** The data structure holding internal state of import key.
+ */
+typedef struct {
+    IFAPI_OBJECT object;
+    TPM2B_NAME parent_name;
+    IFAPI_OBJECT *parent_object;
+    IFAPI_OBJECT new_object;
+    char *parent_path;
+    char *out_path;
+    TPM2B_PRIVATE *private;
+    char *jso_string;
+} IFAPI_ImportKey;
+
+
+/** The data structure holding internal state of loading keys.
+ */
+typedef struct {
+    enum _FAPI_STATE_LOAD_KEY state;   /**< The current state of key  loading */
+    NODE_STR_T *path_list;        /**< The current used hierarchy for CreatePrimary */
+    NODE_OBJECT_T *key_list;
+    IFAPI_OBJECT auth_object;
+    size_t position;
+    ESYS_TR handle;
+    ESYS_TR parent_handle;
+    bool parent_handle_persistent;
+    IFAPI_OBJECT *key_object;
+    char *key_path;
+} IFAPI_LoadKey;
+
+/** The data structure holding internal state of entity delete.
+ */
+typedef struct {
+    bool is_key;                    /**< Entity to be deleted is a key */
+    bool is_persistent_key;         /**< Entity to be deleted is a key */
+    ESYS_TR new_object_handle;
+    TPM2_HANDLE permanentHandle;    /**< The TPM permanent handle */
+    IFAPI_OBJECT auth_object;       /**< Object used for authentication */
+    ESYS_TR auth_index;             /**< The ESAPI handle of the nv authorization object */
+    char *path;                     /**< The name of the file to be deleted */
+    IFAPI_OBJECT object;            /**< Deserialized object */
+    char **pathlist;                /**< The array with the object files to be deleted */
+    size_t numPaths;                /**< Size of array with the object files to be deleted */
+    size_t path_idx;                /**< Index of array with the object files to be deleted */
+} IFAPI_Entity_Delete;
+
+/** The data structure holding internal state of list entities.
+ */
+typedef struct {
+    const char *searchPath;               /**< The path to searched for objectws */
+} IFAPI_Entities_List;
+
+/** Union for all input parameters.
+ *
+ * The input parameters of a command need to be stored in order to enable
+ * resubmission. This type provides the corresponding facilities.
+ */
+typedef union {
+    IFAPI_Provision Provision;
+    IFAPI_Key_Create Key_Create;
+    IFAPI_Key_SetCertificate Key_SetCertificate;
+    IFAPI_Entity_ChangeAuth Entity_ChangeAuth;
+    IFAPI_Entity_Delete Entity_Delete;
+    IFAPI_Entities_List Entities_List;
+    IFAPI_Key_VerifySignature Key_VerifySignature;
+    IFAPI_Data_EncryptDecrypt Data_EncryptDecrypt;
+    IFAPI_PCR pcr;
+    IFAPI_INITIALIZE Initialize;
+    IFAPI_Path_SetDescription path_set_info;
+    IFAPI_Fapi_AuthorizePolicy Policy_AuthorizeNewPolicy;
+    IFAPI_api_WriteAuthorizeNv WriteAuthorizeNV;
+    IFAPI_ExportKey ExportKey;
+    IFAPI_ImportKey ImportKey;
+    IFAPI_Unseal Unseal;
+    IFAPI_GetInfo GetInfo;
+    IFAPI_ExportPolicy ExportPolicy;
+} IFAPI_CMD_STATE;
+
+/** The states for the FAPI's primary key regeneration */
+enum _FAPI_STATE_PRIMARY {
+    PRIMARY_INIT = 0,
+    PRIMARY_READ_KEY,
+    PRIMARY_SEND_NULL_AUTH,
+    PRIMARY_READ_HIERARCHY,
+    PRIMARY_READ_HIERARCHY_FINISH,
+    PRIMARY_AUTHORIZE_HIERARCHY,
+    PRIMARY_HAUTH_SENT,
+    PRIMARY_CREATED,
+    PRIMARY_WAIT_FOR_SESSION
+};
+
+/** The states for the FAPI's primary key regeneration */
+enum _FAPI_STATE_SESSION {
+    SESSION_INIT = 0,
+    SESSION_WAIT_FOR_PRIMARY,
+    SESSION_CREATE_SESSION,
+    SESSION_WAIT_FOR_SESSION1,
+    SESSION_WAIT_FOR_SESSION2
+};
+
+/** The states for the FAPI's get random  state */
+enum _FAPI_STATE_GET_RANDOM {
+    GET_RANDOM_INIT = 0,
+    GET_RANDOM_SENT
+};
+
+/** The states for the FAPI's encrypt/decrypt state*/
+enum _FAPI_STATE_ENCRYPT_DECRYPT {
+    ENCRYPT_DECRYPT_INIT = 0,
+    ENCRYPT_DECRYPT_LOOP,
+    ENCRYPT_DECRYPT_AUTH_SENT,
+    ENCRYPT_DECRYPT_NULL_AUTH_SENT
+};
+
+/** The states for flushing objects */
+enum _FAPI_FLUSH_STATE {
+    FLUSH_INIT = 0,
+    WAIT_FOR_FLUSH
+};
+
+/** The states for writing objects */
+enum IFAPI_WRITE_STATE {
+    WRITE_INIT = 0,
+    WRITE_WAIT_FOR_FINISH
+};
+
+/** The states for the FAPI's internal state machine */
+enum _FAPI_STATE {
+    _FAPI_STATE_INIT = 0,         /**< The initial state after creation or after
+                                     finishing a command. A new command can only
+                                     be issued in this state. */
+    _FAPI_STATE_SENT,             /**< The state after sending a command to the TPM
+                                     withaout authorization before receiving a response. */
+    _FAPI_STATE_RESUBMISSION,     /**< The state after receiving a response from the
+                                     ESAPI that requires resending of the command or
+                                     a FAPI command which requires several ESAPI commands.*/
+    _FAPI_STATE_SENT_NO_AUTH,      /**< The state after sending a command to the TPM
+                                      withaout authorization before receiving a response. */
+    _FAPI_STATE_INTERNALERROR,     /**< A non-recoverable error occurred within the
+                                      ESAPI code. */
+    INITIALIZE_READ,
+    INITIALIZE_INIT_TCTI,
+    INITIALIZE_GET_CAP,
+    INITIALIZE_WAIT_FOR_CAP,
+    INITIALIZE_READ_PROFILE,
+    INITIALIZE_READ_PROFILE_INIT,
+
+    PROVISION_WAIT_FOR_GET_CAP1,
+    PROVISION_INIT_GET_CAP2,
+    PROVISION_WAIT_FOR_GET_CAP2,
+    PROVISION_GET_CERT_NV,
+    PROVISION_GET_CERT_NV_FINISH,
+    PROVISION_GET_CERT_READ_PUBLIC,
+    PROVISION_READ_CERT,
+    PROVISION_PREPARE_READ_ROOT_CERT,
+    PROVISION_READ_ROOT_CERT,
+    PROVISION_READ_INTERMED_CERT,
+    PROVISION_READ_PROFILE,
+    PROVISION_INIT_SRK,
+    PROVISION_READ_EK_TEMPLATE,
+    PROVISION_READ_SRK_TEMPLATE,
+    PROVISION_AUTH_EK_NO_AUTH_SENT,
+    PROVISION_AUTH_EK_AUTH_SENT,
+    PROVISION_AUTH_SRK_NO_AUTH_SENT,
+    PROVISION_AUTH_SRK_AUTH_SENT,
+    PROVISION_EK_CREATED,
+    PROVISION_SRK_CREATED,
+    PROVISION_EK_WRITE_PREPARE,
+    PROVISION_EK_WRITE,
+    PROVISION_EK_CHECK_CERT,
+    PROVISION_SRK_WRITE_PREPARE,
+    PROVISION_SRK_WRITE,
+    PROVISION_INIT_EK_WRITE,
+    PROVISION_INIT_SRK_WRITE,
+    PROVISION_WAIT_FOR_EK_PERSISTENT,
+    PROVISION_WAIT_FOR_SRK_PERSISTENT,
+    PROVISION_CHANGE_LOCKOUT_AUTH,
+    PROVISION_CHANGE_EH_CHECK,
+    PROVISION_CHANGE_EH_AUTH,
+    PROVISION_CHANGE_SH_CHECK,
+    PROVISION_CHANGE_SH_AUTH,
+    PROVISION_EH_CHANGE_POLICY,
+    PROVISION_SH_CHANGE_POLICY,
+    PROVISION_LOCKOUT_CHANGE_POLICY,
+    PROVISION_FINISHED,
+    PROVISION_WRITE_SH,
+    PROVISION_WRITE_EH,
+    PROVISION_WRITE_LOCKOUT,
+    PROVISION_WRITE_LOCKOUT_PARAM,
+    PROVISION_FLUSH_SRK,
+    PROVISION_FLUSH_EK,
+    PROVISION_CHECK_FOR_VENDOR_CERT,
+    PROVISION_GET_VENDOR,
+
+    KEY_CREATE_READ_TEMPLATE,
+    KEY_CREATE,
+
+    CREATE_SEAL,
+
+    KEY_SET_CERTIFICATE_READ_PROFILE,
+    KEY_SET_CERTIFICATE_READ,
+    KEY_SET_CERTIFICATE_WRITE,
+
+    KEY_GET_CERTIFICATE_READ,
+
+    GET_RANDOM_WAIT_FOR_SESSION,
+    GET_RANDOM_WAIT_FOR_RANDOM,
+    GET_RANDOM_CLEANUP,
+
+    NV_CREATE_READ_PROFILE,
+    NV_CREATE_READ_HIERARCHY,
+    NV_CREATE_AUTHORIZE_HIERARCHY,
+    NV_CREATE_GET_INDEX,
+    NV_CREATE_FIND_INDEX,
+    NV_CREATE_SESSION,
+    NV_CREATE_WAIT_FOR_SESSION,
+
+    NV_CREATE_AUTH_SENT,
+    NV_CREATE_WRITE,
+    NV_CREATE_CALCULATE_POLICY,
+    NV_WRITE_CALL,
+
+    NV_WRITE_READ,
+    NV_WRITE_SESSION,
+    NV_WRITE_WAIT_FOR_SESSION,
+    NV_WRITE_WAIT_FOR_PROFILE,
+    NV_WRITE_NULL_AUTH_SENT,
+    NV_WRITE_AUTH_SENT,
+    NV_WRITE_WRITE,
+    NV_WRITE_EXEC_POLICY,
+    NV_WRITE_CLEANUP,
+
+    NV_EXTEND_READ,
+    NV_EXTEND_SESSION,
+    NV_EXTEND_WAIT_FOR_SESSION,
+    NV_EXTEND_WAIT_FOR_PROFILE,
+    NV_EXTEND_AUTHORIZE,
+    NV_EXTEND_AUTH_SENT,
+    NV_EXTEND_WRITE,
+    NV_EXTEND_CLEANUP,
+
+    NV_INCREMENT_READ,
+    NV_INCREMENT_WAIT_FOR_SESSION,
+    NV_INCREMENT_AUTHORIZE,
+    NV_INCREMENT_AUTH_SENT,
+    NV_INCREMENT_WRITE,
+    NV_INCREMENT_CLEANUP,
+
+    NV_SET_BITS_READ,
+    NV_SET_BITS_WAIT_FOR_SESSION,
+    NV_SET_BITS_AUTHORIZE,
+    NV_SET_BITS_AUTH_SENT,
+    NV_SET_BITS_WRITE,
+    NV_SET_BITS_CLEANUP,
+
+    NV_READ_READ,
+    NV_READ_WAIT,
+    NV_READ_SESSION,
+    NV_READ_WAIT_FOR_SESSION,
+    NV_READ_WAIT_FOR_PROFILE,
+    NV_READ_CLEANUP,
+
+    ENTITY_DELETE_GET_FILE,
+    ENTITY_DELETE_READ,
+    ENTITY_DELETE_WAIT_FOR_SESSION,
+    ENTITY_DELETE_NULL_AUTH_SENT_FOR_KEY,
+    ENTITY_DELETE_AUTH_SENT_FOR_KEY,
+    ENTITY_DELETE_NULL_AUTH_SENT_FOR_NV,
+    ENTITY_DELETE_AUTH_SENT_FOR_NV,
+    ENTITY_DELETE_KEY,
+    ENTITY_DELETE_AUTHORIZE_NV,
+    ENTITY_DELETE_FILE,
+    ENTITY_DELETE_POLICY,
+    ENTITY_DELETE_REMOVE_DIRS,
+    ENTITY_DELETE_CLEANUP,
+
+    ENTITY_GET_TPM_BLOBS_READ,
+
+    KEY_SIGN_WAIT_FOR_PROFILE,
+    KEY_SIGN_WAIT_FOR_SESSION,
+    KEY_SIGN_WAIT_FOR_KEY,
+    KEY_SIGN_WAIT_FOR_SIGN,
+    KEY_SIGN_AUTH_SENT,
+    KEY_SIGN_NULL_AUTH_SENT,
+    KEY_SIGN_WAIT_FOR_FLUSH,
+    KEY_SIGN_CALL,
+    KEY_SIGN_EXEC_POLICY,
+    KEY_SIGN_CLEANUP,
+
+    ENTITY_CHANGE_AUTH_WAIT_FOR_SESSION,
+    ENTITY_CHANGE_AUTH_WAIT_FOR_KEY,
+    ENTITY_CHANGE_AUTH_AUTH_SENT,
+    ENTITY_CHANGE_AUTH_WAIT_FOR_FLUSH,
+    ENTITY_CHANGE_AUTH_WRITE_PREPARE,
+    ENTITY_CHANGE_AUTH_WRITE,
+    ENTITY_CHANGE_AUTH_WAIT_FOR_KEY_AUTH,
+    ENTITY_CHANGE_AUTH_WAIT_FOR_NV_READ,
+    ENTITY_CHANGE_AUTH_WAIT_FOR_NV_AUTH,
+    ENTITY_CHANGE_AUTH_WAIT_FOR_NV_CHANGE_AUTH,
+    ENTITY_CHANGE_AUTH_HIERARCHY_CHANGE_AUTH,
+    ENTITY_CHANGE_AUTH_HIERARCHY_READ,
+    ENTITY_CHANGE_AUTH_HIERARCHY_AUTHORIZE,
+    ENTITY_CHANGE_AUTH_CLEANUP,
+
+    DATA_ENCRYPT_WAIT_FOR_PROFILE,
+    DATA_ENCRYPT_WAIT_FOR_SESSION,
+    DATA_ENCRYPT_WAIT_FOR_KEY,
+    DATA_ENCRYPT_AUTH_SENT,
+    DATA_ENCRYPT_NULL_AUTH_SENT,
+    DATA_ENCRYPT_FLUSH_KEY,
+    DATA_ENCRYPT_WAIT_FOR_FLUSH,
+    DATA_ENCRYPT_WAIT_FOR_SYM_ENCRYPTION,
+    DATA_ENCRYPT_WAIT_FOR_RSA_ENCRYPTION,
+    DATA_ENCRYPT_WAIT_FOR_WRAPPED_ENCRYPTION,
+    DATA_ENCRYPT_GEN_SYM_KEY,
+    DATA_ENCRYPT_AUTHORIZE,
+    DATA_ENCRYPT_WAIT_FOR_SEAL,
+    DATA_ENCRYPT_CALCULATE_POLICY,
+    DATA_ENCRYPT_CLEAN,
+
+    DATA_DECRYPT_WAIT_FOR_PROFILE,
+    DATA_DECRYPT_WAIT_FOR_SESSION,
+    DATA_DECRYPT_SEARCH_KEY,
+    DATA_DECRYPT_READ,
+    DATA_DECRYPT_WAIT_FOR_KEY,
+    DATA_DECRYPT_WAIT_FOR_SEAL_KEY,
+    DATA_DECRYPT_AUTH_SENT,
+    DATA_DECRYPT_NULL_AUTH_SENT,
+    DATA_DECRYPT_FLUSH_KEY,
+    DATA_DECRYPT_FLUSH_SYM_OBJECT,
+    DATA_DECRYPT_WAIT_FOR_FLUSH,
+    DATA_DECRYPT_WAIT_FOR_SYM_ENCRYPTION,
+    DATA_DECRYPT_WAIT_FOR_RSA_DECRYPTION,
+    DATA_DECRYPT_WAIT_FOR_WRAPPED_DECRYPTION,
+    DATA_DECRYPT_AUTHORIZE_KEY,
+    DATA_DECRYPT_UNSEAL_OBJECT,
+    DATA_DECRYPT_EXEC_POLICY,
+    DATA_DECRYPT_WAIT_FOR_UNSEAL,
+    DATA_DECRYPT_FLUSH_POLICY,
+    DATA_DECRYPT_CLEANUP,
+
+    PCR_EXTEND_WAIT_FOR_SESSION,
+    PCR_EXTEND_WAIT_FOR_GET_CAP,
+    PCR_EXTEND_APPEND_EVENT_LOG,
+    PCR_EXTEND_FINISH,
+    PCR_EXTEND_CLEANUP,
+
+    PCR_RESET_WAIT_FOR_SESSION,
+    PCR_RESET_FINISH,
+
+    PCR_READ_READ_PCR,
+    PCR_READ_READ_EVENT_LIST,
+
+    PCR_QUOTE_WAIT_FOR_PROFILE,
+    PCR_QUOTE_WAIT_FOR_GET_CAP,
+    PCR_QUOTE_FINISH,
+    PCR_QUOTE_WAIT_FOR_SESSION,
+    PCR_QUOTE_WAIT_FOR_KEY,
+    PCR_QUOTE_AUTH_SENT,
+    PCR_QUOTE_AUTHORIZE,
+    PCR_QUOTE_WAIT_FOR_FLUSH,
+    PCR_QUOTE_READ_EVENT_LIST,
+    PCR_QUOTE_CLEANUP,
+
+    PATH_SET_DESCRIPTION_READ,
+    PATH_SET_DESCRIPTION_WRITE,
+
+    PATH_GET_DESCRIPTION_READ,
+    PATH_GET_DESCRIPTION_WRITE,
+
+    APP_DATA_SET_READ,
+    APP_DATA_SET_WRITE,
+
+    APP_DATA_GET_READ,
+    APP_DATA_GET_WRITE,
+
+    GET_TPM_INFO_GETCAP,
+
+    AUTHORIZE_NEW_READ_POLICY,
+    AUTHORIZE_NEW_CALCULATE_POLICY,
+    AUTHORIZE_NEW_LOAD_KEY,
+    AUTHORIZE_NEW_KEY_SIGN_POLICY,
+    AUTHORIZE_NEW_WRITE_POLICY_PREPARE,
+    AUTHORIZE_NEW_WRITE_POLICY,
+    AUTHORIZE_NEW_CLEANUP,
+
+    WRITE_AUTHORIZE_NV_READ_NV,
+    WRITE_AUTHORIZE_NV_CALCULATE_POLICY,
+     WRITE_AUTHORIZE_NV_WRITE_NV_RAM_PREPARE,
+    WRITE_AUTHORIZE_NV_WRITE_NV_RAM,
+    WRITE_AUTHORIZE_NV_WRITE_OBJCECT,
+    WRITE_AUTHORIZE_NV_WRITE_POLICY_PREPARE,
+    WRITE_AUTHORIZE_NV_WRITE_POLICY,
+    WRITE_AUTHORIZE_NV_WAIT_FOR_SESSION,
+    WRITE_AUTHORIZE_NV_CLEANUP,
+
+    EXPORT_KEY_READ_PUB_KEY,
+    EXPORT_KEY_READ_PUB_KEY_PARENT,
+    EXPORT_KEY_WAIT_FOR_SESSION,
+    EXPORT_KEY_WAIT_FOR_KEY,
+    EXPORT_KEY_WAIT_FOR_DUPLICATE,
+    EXPORT_KEY_WAIT_FOR_EXT_KEY,
+    EXPORT_KEY_WAIT_FOR_AUTHORIZATON,
+    EXPORT_KEY_WAIT_FOR_FLUSH1,
+    EXPORT_KEY_WAIT_FOR_FLUSH2,
+    EXPORT_KEY_CLEANUP,
+
+    IMPORT_KEY_WRITE_POLICY,
+    IMPORT_KEY_WRITE,
+    IMPORT_KEY_SEARCH,
+    IMPORT_KEY_LOAD_PARENT,
+    IMPORT_KEY_AUTHORIZE_PARENT,
+    IMPORT_KEY_IMPORT,
+    IMPORT_KEY_WAIT_FOR_FLUSH,
+    IMPORT_KEY_WRITE_OBJECT_PREPARE,
+    IMPORT_KEY_WRITE_OBJECT,
+    IMPORT_KEY_CLEANUP,
+
+    UNSEAL_WAIT_FOR_KEY,
+    UNSEAL_AUTHORIZE_OBJECT,
+    UNSEAL_WAIT_FOR_UNSEAL,
+    UNSEAL_WAIT_FOR_FLUSH,
+    UNSEAL_CLEANUP,
+
+    GET_PLATFORM_CERTIFICATE,
+
+    POLICY_EXPORT_READ_OBJECT,
+    POLICY_EXPORT_READ_OBJECT_FINISH,
+    POLICY_EXPORT_READ_POLICY,
+    POLICY_EXPORT_READ_POLICY_FINISH,
+
+    VERIFY_QUOTE_READ,
+
+    GET_INFO_GET_CAP,
+    GET_INFO_GET_CAP_MORE,
+    GET_INFO_WAIT_FOR_CAP
+};
+
+/** Structure holding FAPI callbacks and userData
+ *
+ * This structure holds the callback pointers and corresponding userData pointers for each of the
+ * three callback types of FAPI. They are set using Fapi_SetAuthCB, Fapi_SetBranchCB and
+ * Fapi_SetSignCB.
+ */
+struct IFAPI_CALLBACKS {
+    Fapi_CB_Auth auth;
+    void *authData;
+    Fapi_CB_Branch branch;
+    void *branchData;
+    Fapi_CB_Sign sign;
+    void *signData;
+    Fapi_CB_PolicyAction action;
+    void *actionData;
+};
+
+/** The data structure holding internal state information.
+ *
+ * Each FAPI_CONTEXT respresents a logically independent connection to the TPM.
+ * It stores meta data information about object in order to calculate session
+ * auths and similar things.
+ */
+struct FAPI_CONTEXT {
+    ESYS_CONTEXT *esys;              /**< The ESYS context used internally to talk to
+                                          the TPM. */
+    struct IFAPI_CALLBACKS callbacks;       /**< Callbacks for user interaction from FAPI */
+    struct IFAPI_IO io;
+    struct IFAPI_EVENTLOG eventlog;
+    struct IFAPI_KEYSTORE keystore;
+    struct IFAPI_POLICY_STORE pstore;
+    struct IFAPI_PROFILES profiles;
+
+    enum _FAPI_STATE state;          /**< The current state of the command execution */
+    enum _FAPI_STATE_PRIMARY primary_state; /**< The current state of the primary regeneration */
+    enum _FAPI_STATE_SESSION session_state; /**< The current state of the session creation */
+    enum _FAPI_STATE_GET_RANDOM get_random_state; /**< The current state of get random */
+    enum _FAPI_STATE_ENCRYPT_DECRYPT sym_encrypt_decrypt_state; /**< The current state of symmetric
+                                                                      encryption */
+    enum IFAPI_HIERACHY_AUTHORIZATION_STATE hierarchy_state;
+    enum IFAPI_HIERACHY_POLICY_AUTHORIZATION_STATE hierarchy_policy_state;
+    enum IFAPI_GET_CERT_STATE get_cert_state;
+    enum _FAPI_FLUSH_STATE flush_object_state;  /**< The current state of a flush operation */
+    enum IFAPI_CLEANUP_STATE cleanup_state;     /**< The state of cleanup after command execution */
+    IFAPI_CONFIG config;             /**< The profile independet configuration data */
+    UINT32 nv_buffer_max;            /**< The maximal size for transfer of nv buffer content */
+    TPM2_CC cmd_tag;                 /**< The TPM cmd currently executed by FAPI */
+    IFAPI_CMD_STATE cmd;             /**< The state information of the currently executed
+                                          command */
+    IFAPI_NV_Cmds nv_cmd;
+    IFAPI_NV_Cmds policy_nvCmdState;
+    IFAPI_NV_Cmds policy_nvCmdSav;
+    IFAPI_GetRandom get_random;
+    IFAPI_CreatePrimary createPrimary;
+    IFAPI_LoadKey loadKey;
+    ESYS_TR session1;                /**< The firest session used by FAPI  */
+    ESYS_TR session2;                /**< The second session used by FAPI  */
+    ESYS_TR policy_session;          /**< The policy session used by FAPI  */
+    ESYS_TR ek_handle;
+    ESYS_TR srk_handle;
+    bool ek_persistent;
+    bool srk_persistent;
+    IFAPI_SESSION_TYPE session_flags;
+    TPMA_SESSION session1_attribute_flags;
+    TPMA_SESSION session2_attribute_flags;
+    IFAPI_MAX_BUFFER aux_data; /**< tpm2b data to be transferred */
+    IFAPI_POLICY_CTX policy;  /**< The context of current policy. */
+    IFAPI_FILE_SEARCH_CTX fsearch;  /**< The context for object search in key/policy store */
+    IFAPI_Key_Sign Key_Sign; /**< State information for key signing */
+    enum IFAPI_WRITE_STATE write_state;
+    enum IFAPI_IO_STATE io_state;
+    NODE_OBJECT_T *object_list;
+    IFAPI_OBJECT *duplicate_key; /**< Will be needed for policy execution */
+};
+
+#define VENDOR_IFX  0x49465800
+#define VENDOR_INTC 0x494E5443
+#define VEDNOR_IBM  0x49424D20
+
+#endif /* FAPI_INT_H */
diff --git a/src/tss2-fapi/fapi_policy.c b/src/tss2-fapi/fapi_policy.c
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/src/tss2-fapi/fapi_policy.c
@@ -0,0 +1 @@
+
diff --git a/src/tss2-fapi/fapi_policy.h b/src/tss2-fapi/fapi_policy.h
new file mode 100644
index 0000000..b6312df
--- /dev/null
+++ b/src/tss2-fapi/fapi_policy.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ *******************************************************************************/
+#ifndef FAPI_POLICY_H
+#define FAPI_POLICY_H
+
+#include <stdint.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <sys/stat.h>
+#include <json-c/json.h>
+#include <json-c/json_util.h>
+
+#include "tss2_esys.h"
+#include "tss2_fapi.h"
+#include "fapi_int.h"
+
+#include "ifapi_policy_types.h"
+#include "ifapi_policy_json_serialize.h"
+#include "ifapi_policy_json_deserialize.h"
+#include "ifapi_policy.h"
+#include "ifapi_policy_calculate.h"
+#include "ifapi_policy_execute.h"
+#include "ifapi_json_serialize.h"
+#include "ifapi_json_deserialize.h"
+
+
+#endif /* FAPI_POLICY_H */
diff --git a/src/tss2-fapi/fapi_types.h b/src/tss2-fapi/fapi_types.h
new file mode 100644
index 0000000..88b4bbe
--- /dev/null
+++ b/src/tss2-fapi/fapi_types.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ ******************************************************************************/
+#ifndef FAPI_TYPES_H
+#define FAPI_TYPES_H
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+/** The data structure representing an unit8_t array.
+  */
+typedef struct {
+    size_t size;
+    uint8_t *buffer;
+} UINT8_ARY;
+
+/** The data structure storing a linked list of strings.
+ *
+ * The structure is used for the processing of file paths
+ */
+typedef struct str_node {
+    char *str;              /**< A string of the string list */
+    bool free_string;       /**< Indicates whether a free has to called on cleanup */
+    struct str_node *next;  /**< Pointer to next element */
+} NODE_STR_T;
+
+/** The data structure storing a linked list of objects.
+ *
+ * The structure is used for the processing of file paths
+ */
+typedef struct object_node {
+    void   *object;             /**< The pointer to the object  */
+    size_t size;                /**< Will be used only for BYTE arrays */
+    struct object_node *next;   /**< Pointer to next element */
+} NODE_OBJECT_T;
+
+#endif /* FAPI_TYPES_H */
diff --git a/src/tss2-fapi/fapi_util.c b/src/tss2-fapi/fapi_util.c
new file mode 100644
index 0000000..41db88a
--- /dev/null
+++ b/src/tss2-fapi/fapi_util.c
@@ -0,0 +1,3336 @@
+/* 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 <stdarg.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <dirent.h>
+
+#include "tss2_mu.h"
+#include "fapi_util.h"
+#include "fapi_crypto.h"
+#include "ifapi_helpers.h"
+#include "ifapi_json_serialize.h"
+#include "ifapi_json_deserialize.h"
+#include "tpm_json_deserialize.h"
+#include "fapi_policy.h"
+#include "ifapi_policyutil_execute.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+/** State machine for flushing objects.
+ *
+ * @param[in] context The FAPI_CONTEXT.
+ * @param[in] handle of the object to be flushed.
+ *
+ * @retval TSS2_RC_SUCCESS on success.
+ * @retval All possible error codes of ESAPI.
+ */
+TSS2_RC
+ifapi_flush_object(FAPI_CONTEXT *context, ESYS_TR handle)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+
+    if (handle == ESYS_TR_NONE)
+        return r;
+
+    switch (context->flush_object_state) {
+    statecase(context->flush_object_state, FLUSH_INIT);
+        r = Esys_FlushContext_Async(context->esys, handle);
+        return_if_error(r, "Flush Object");
+        fallthrough;
+
+    statecase(context->flush_object_state, WAIT_FOR_FLUSH);
+        r = Esys_FlushContext_Finish(context->esys);
+        if ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN)
+            return TSS2_FAPI_RC_TRY_AGAIN;
+
+        return_if_error(r, "FlushContext");
+
+        context->flush_object_state = FLUSH_INIT;
+        return TSS2_RC_SUCCESS;
+
+    statecasedefault(context->flush_object_state);
+    }
+}
+
+/** Preparation for getting a session handle.
+ *
+ * The corresponding async call be executed and a session secret for encryption
+ * TPM2B parameters will be created.
+ *
+ * @param[in] context The FAPI_CONTEXT.
+ * @param[in] tpmkey The key which will be used for the encryption of the sesssion
+ *            secret.
+ * @param[in] profile The FAPI profile will be used to adjust the sessions symmetric
+ *            parameters.
+ *
+ * @retval TSS2_RC_SUCCESS on success.
+ * @retval All possible error codes of ESAPI.
+ */
+TSS2_RC
+ifapi_get_session_async(ESYS_CONTEXT *esys, ESYS_TR saltkey, const IFAPI_PROFILE *profile)
+{
+    TSS2_RC r;
+
+    r = Esys_StartAuthSession_Async(esys, saltkey,
+                                    ESYS_TR_NONE,
+                                    ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
+                                    NULL,
+                                    TPM2_SE_HMAC, &profile->session_symmetric,
+                                    profile->nameAlg);
+//TODO: Get the key objects's nameAlg that the session will be applied to for sessionHash
+    return_if_error(r, "Creating session.");
+
+    return TSS2_RC_SUCCESS;
+}
+
+/**  Call for getting a session handle and adjust session parameters.
+ *
+ * @param[in] context The FAPI_CONTEXT.
+ * @param[out] session The session handle.
+ * @param[in] flags The flags to adjust the session attributes.
+ *
+ * @retval TSS2_RC_SUCCESS on success.
+ * @retval All possible error codes of ESAPI.
+ */
+TSS2_RC
+ifapi_get_session_finish(ESYS_CONTEXT *esys, ESYS_TR *session,
+                         TPMA_SESSION flags)
+{
+    TSS2_RC r;
+    TPMA_SESSION sessionAttributes = 0;
+
+    /* Check whether authorization callback is defined */
+
+    r = Esys_StartAuthSession_Finish(esys, session);
+    if (r != TSS2_RC_SUCCESS)
+        return r;
+
+    sessionAttributes |= flags;
+    sessionAttributes |= TPMA_SESSION_CONTINUESESSION;
+
+    r = Esys_TRSess_SetAttributes(esys, *session, sessionAttributes,
+                                  0xff);
+    return_if_error(r, "Set session attributes.");
+
+    return TSS2_RC_SUCCESS;
+}
+
+TSS2_RC
+pop_object_from_list(FAPI_CONTEXT *context, NODE_OBJECT_T **object_list)
+{
+    return_if_null(*object_list, "Pop from list.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    NODE_OBJECT_T *head = *object_list;
+    NODE_OBJECT_T *next = head->next;
+    *object_list = next;
+    ifapi_free_object(context, (void *)&head->object);
+    free(head);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Set authorization value for a FAPI object.
+ *
+ * @param[in,out] context The FAPI_CONTEXT.
+ *
+ * @retval TSS2_RC_SUCCESS on success.
+ * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN If the callback for getting
+ *         the auth value is not defined.
+ */
+TSS2_RC
+ifapi_set_auth(
+    FAPI_CONTEXT *context,
+    IFAPI_OBJECT *auth_object,
+    const char *description)
+{
+    TSS2_RC r;
+    char *auth = NULL;
+    TPM2B_AUTH authValue = { .size = 0, .buffer = {0} };
+    char *obj_description;
+
+    obj_description = get_description(auth_object);
+
+    if (obj_description)
+        description = obj_description;
+
+    /* Check whether callback is defined. */
+    if (context->callbacks.auth) {
+        r = context->callbacks.auth(context, description, &auth,
+                                        context->callbacks.authData);
+        return_if_error(r, "policyAuthCallback");
+        if (auth != NULL) {
+            authValue.size = strlen(auth);
+            memcpy(&authValue.buffer[0], auth, authValue.size);
+        }
+        /* Store auth value in the ESYS object. */
+        r = Esys_TR_SetAuth(context->esys, auth_object->handle, &authValue);
+        return_if_error(r, "Set auth value.");
+
+        SAFE_FREE(auth);
+        return TSS2_RC_SUCCESS;
+    }
+    SAFE_FREE(auth);
+    return  TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN;
+}
+
+/** Preparation for getting a free handle after a start handle number.
+ *
+ * @param[in] context The FAPI_CONTEXT.
+ * @param[in] handle The start value for handle search.
+ *
+ * @retval TSS2_RC_SUCCESS on success.
+ * @retval All possible error codes of ESAPI.
+ */
+TSS2_RC
+ifapi_get_free_handle_async(FAPI_CONTEXT *fctx, TPM2_HANDLE *handle)
+{
+    TSS2_RC r = Esys_GetCapability_Async(fctx->esys,
+                                         ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
+                                         TPM2_CAP_HANDLES, *handle, 1);
+    return_if_error(r, "GetCapability");
+    return r;
+}
+
+/** Execution of get capability until a free handle is found.
+ *
+ * The get capability method is called until a free handle is found
+ * or the max number of trials passe to the function is exeeded.
+ *
+ * @param[in] context The FAPI_CONTEXT.
+ * @param[out] handle The free handle.
+ * @param[in] max The maximal number of trials.
+ *
+ * @retval TSS2_RC_SUCCESS on success.
+ * @retval TSS2_FAPI_RC_NV_TOO_SMALL if too many NV handles are defined.
+ * @retval All possible error codes of ESAPI.
+ */
+TSS2_RC
+ifapi_get_free_handle_finish(FAPI_CONTEXT *fctx, TPM2_HANDLE *handle,
+                             TPM2_HANDLE max)
+{
+    TPMI_YES_NO moreData;
+    TPMS_CAPABILITY_DATA *capabilityData = NULL;
+    TSS2_RC r = Esys_GetCapability_Finish(fctx->esys,
+                                          &moreData, &capabilityData);
+
+    if ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN)
+        return TSS2_FAPI_RC_TRY_AGAIN;
+
+    return_if_error(r, "GetCapability");
+
+    if (capabilityData->data.handles.count == 0 ||
+            capabilityData->data.handles.handle[0] != *handle) {
+        SAFE_FREE(capabilityData);
+        return TSS2_RC_SUCCESS;
+    }
+    SAFE_FREE(capabilityData);
+    *handle += 1;
+    if (*handle > max) {
+        return_error(TSS2_FAPI_RC_NV_TOO_SMALL, "No NV index free.");
+    }
+
+    r = ifapi_get_free_handle_async(fctx, handle);
+    return_if_error(r, "GetCapability");
+
+    return TSS2_FAPI_RC_TRY_AGAIN;
+}
+
+static TSS2_RC
+get_explicit_key_path(
+    IFAPI_KEYSTORE *keystore,
+    const char *ipath,
+    NODE_STR_T **result)
+{
+    NODE_STR_T *list_node1 = NULL;
+    NODE_STR_T *list_node = NULL;
+    TSS2_RC r = init_explicit_key_path(keystore->defaultprofile, ipath,
+                                       &list_node1, &list_node, result);
+    goto_if_error(r, "init_explicit_key_path", error);
+
+    while (list_node != NULL) {
+        if (!add_string_to_list(*result, list_node->str)) {
+            LOG_ERROR("Out of memory");
+            r = TSS2_FAPI_RC_MEMORY;
+            goto error;
+        }
+        list_node = list_node->next;
+    }
+    free_string_list(list_node1);
+    return TSS2_RC_SUCCESS;
+
+error:
+    if (*result)
+        free_string_list(*result);
+    if (list_node1)
+        free_string_list(list_node1);
+    return r;
+}
+
+TSS2_RC
+ifapi_init_primary_async(FAPI_CONTEXT *context, TSS2_KEY_TYPE ktype)
+{
+    TSS2_RC r;
+    IFAPI_OBJECT *hierarchy;
+    hierarchy = &context->cmd.Provision.hierarchy;
+    TPMS_POLICY_HARNESS *policy;
+
+    if (ktype == TSS2_EK) {
+        /* Value set according to EK credential profile. */
+        if (context->cmd.Provision.public_templ.public.publicArea.type == TPM2_ALG_RSA) {
+            context->cmd.Provision.public_templ.public.publicArea.unique.rsa.size = 256;
+        } else if (context->cmd.Provision.public_templ.public.publicArea.type == TPM2_ALG_ECC) {
+            context->cmd.Provision.public_templ.public.publicArea.unique.ecc.x.size = 32;
+            context->cmd.Provision.public_templ.public.publicArea.unique.ecc.y.size = 32;
+        }
+        ifapi_init_hierarchy_object(hierarchy, ESYS_TR_RH_ENDORSEMENT);
+        policy = context->profiles.default_profile.ek_policy;
+    } else if (ktype == TSS2_SRK) {
+        policy = context->profiles.default_profile.srk_policy;
+        ifapi_init_hierarchy_object(hierarchy, ESYS_TR_RH_OWNER);
+    } else {
+        return_error(TSS2_FAPI_RC_BAD_VALUE,
+                     "Invalid key type. Only EK or SRK allowed");
+    }
+
+    if (policy) {
+        /* Duplicate policy to prevent profile policy from cleanup. */
+        policy = ifapi_copy_policy_harness(policy);
+        return_if_null(policy, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+        r = ifapi_calculate_tree(context, NULL, /**< no path needed */
+                                 policy,
+                                 context->profiles.default_profile.nameAlg,
+                                 &context->cmd.Provision.digest_idx,
+                                 &context->cmd.Provision.hash_size);
+        return_if_error(r, "Policy calculation");
+
+        context->cmd.Provision.public_templ.public.publicArea.authPolicy.size =
+            context->cmd.Provision.hash_size;
+        memcpy(&context->cmd.Provision.public_templ.public.publicArea.authPolicy.buffer[0],
+               &policy->policyDigests.digests[context->policy.digest_idx].digest,
+               context->cmd.Provision.hash_size);
+    }
+    context->createPrimary.pkey_object.policy_harness = policy;
+
+    memset(&context->cmd.Provision.inSensitive, 0, sizeof(TPM2B_SENSITIVE_CREATE));
+    memset(&context->cmd.Provision.outsideInfo, 0, sizeof(TPM2B_DATA));
+    memset(&context->cmd.Provision.creationPCR, 0, sizeof(TPML_PCR_SELECTION));
+
+    r = Esys_CreatePrimary_Async(context->esys, hierarchy->handle,
+                                 ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
+                                 &context->cmd.Provision.inSensitive,
+                                 &context->cmd.Provision.public_templ.public,
+                                 &context->cmd.Provision.outsideInfo,
+                                 &context->cmd.Provision.creationPCR);
+    return r;
+}
+
+TSS2_RC
+ifapi_init_primary_finish(FAPI_CONTEXT *context, TSS2_KEY_TYPE ktype)
+{
+    TSS2_RC r;
+    ESYS_TR primaryHandle;
+    IFAPI_OBJECT *hierarchy;
+    TPM2B_PUBLIC *outPublic = NULL;
+    TPM2B_CREATION_DATA *creationData = NULL;
+    TPM2B_DIGEST *creationHash = NULL;
+    TPMT_TK_CREATION *creationTicket = NULL;
+    IFAPI_KEY *pkey = &context->createPrimary.pkey_object.misc.key;
+    NODE_STR_T *k_sub_path = NULL;
+
+    hierarchy = &context->cmd.Provision.hierarchy;
+
+    r = Esys_CreatePrimary_Finish(context->esys,
+                                  &primaryHandle, &outPublic, &creationData, &creationHash,
+                                  &creationTicket);
+    if ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN)
+        return TSS2_FAPI_RC_TRY_AGAIN;
+
+    /* Retry with authorization callback after trial with null auth */
+    if ((((r & ~TPM2_RC_N_MASK) == TPM2_RC_BAD_AUTH))
+            && (context->state ==  PROVISION_AUTH_EK_NO_AUTH_SENT ||
+                context->state ==  PROVISION_AUTH_SRK_NO_AUTH_SENT)) {
+        r = ifapi_set_auth(context, hierarchy, "CreatePrimary");
+        goto_if_error_reset_state(r, "CreatePrimary", error_cleanup);
+
+        r = Esys_CreatePrimary_Async(context->esys, hierarchy->handle,
+                                     ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
+                                     &context->cmd.Provision.inSensitive,
+                                     &context->cmd.Provision.public,
+                                     &context->cmd.Provision.outsideInfo,
+                                     &context->cmd.Provision.creationPCR);
+        goto_if_error_reset_state(r, "CreatePrimary", error_cleanup);
+
+        if (ktype == TSS2_EK)
+            context->state = PROVISION_AUTH_EK_AUTH_SENT;
+        else
+            context->state = PROVISION_AUTH_SRK_AUTH_SENT;
+        return TSS2_FAPI_RC_TRY_AGAIN;
+
+    } else {
+        goto_if_error_reset_state(r, "FAPI Provision", error_cleanup);
+    }
+
+    if (ktype == TSS2_EK) {
+        context->ek_handle = primaryHandle;
+    } else if (ktype == TSS2_SRK) {
+        context->srk_handle = primaryHandle;
+    } else {
+        return_error(TSS2_FAPI_RC_BAD_VALUE,
+                     "Invalid key type. Only EK or SRK allowed");
+    }
+
+    SAFE_FREE(pkey->serialization.buffer);
+    r = Esys_TR_Serialize(context->esys, primaryHandle, &pkey->serialization.buffer,
+                          &pkey->serialization.size);
+    goto_if_error(r, "Error serialize esys object", error_cleanup);
+
+    r = ifapi_get_name(&outPublic->publicArea, &pkey->name);
+    goto_if_error(r, "Get primary name", error_cleanup);
+
+    pkey->public = *outPublic;
+    pkey->policyInstance = NULL;
+    pkey->creationData = *creationData;
+    pkey->creationTicket = *creationTicket;
+    pkey->description = NULL;
+    pkey->certificate = NULL;
+
+    SAFE_FREE(outPublic);
+    SAFE_FREE(creationData);
+    SAFE_FREE(creationHash);
+    SAFE_FREE(creationTicket);
+
+    if (pkey->public.publicArea.type == TPM2_ALG_RSA)
+        pkey->signing_scheme = context->profiles.default_profile.rsa_signing_scheme;
+    else
+        pkey->signing_scheme = context->profiles.default_profile.ecc_signing_scheme;
+    context->createPrimary.pkey_object.handle = primaryHandle;
+    SAFE_FREE(pkey->serialization.buffer);
+    ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
+    return TSS2_RC_SUCCESS;
+
+error_cleanup:
+    free_string_list(k_sub_path);
+    SAFE_FREE(pkey->serialization.buffer);
+    ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
+    return r;
+}
+
+TSS2_RC
+ifapi_load_primary_async(FAPI_CONTEXT *context, char *path)
+{
+
+    TSS2_RC r;
+
+    memset(&context->createPrimary.pkey_object, 0, sizeof(IFAPI_OBJECT));
+    context->createPrimary.path = path;
+    r = ifapi_keystore_load_async(&context->keystore, &context->io, path);
+    return_if_error2(r, "Could not open: %s", path);
+    context->primary_state = PRIMARY_READ_KEY;
+    return TSS2_RC_SUCCESS;
+
+}
+
+TSS2_RC
+ifapi_load_primary_finish(FAPI_CONTEXT *context, ESYS_TR *handle)
+{
+    TSS2_RC r;
+    IFAPI_OBJECT *hierarchy = &context->createPrimary.hierarchy;
+
+    TPM2B_PUBLIC *outPublic = NULL;
+    TPM2B_CREATION_DATA *creationData = NULL;
+    TPM2B_DIGEST *creationHash = NULL;
+    TPMT_TK_CREATION *creationTicket = NULL;
+    //TPM2B_NAME *name;
+    IFAPI_OBJECT *pkey_object =  &context->createPrimary.pkey_object;
+    IFAPI_KEY *pkey = &context->createPrimary.pkey_object.misc.key;
+    ESYS_TR auth_session;
+
+    LOG_TRACE("call");
+
+    switch (context->primary_state) {
+    statecase(context->primary_state, PRIMARY_READ_KEY);
+        r = ifapi_keystore_load_finish(&context->keystore, &context->io,
+                                       pkey_object);
+        return_try_again(r);
+        return_if_error(r, "read_finish failed");
+
+        r = ifapi_initialize_object(context->esys, pkey_object);
+        goto_if_error_reset_state(r, "Initialize key object", error_cleanup);
+
+        if (pkey_object->handle != ESYS_TR_NONE) {
+            if (pkey->creationTicket.hierarchy == TPM2_RH_EK) {
+                context->ek_persistent = true;
+            } else {
+                context->srk_persistent = true;
+            }
+            *handle = pkey_object->handle;
+            break;
+        } else {
+             if (pkey->creationTicket.hierarchy == TPM2_RH_EK) {
+                context->ek_persistent = false;
+            } else {
+                context->srk_persistent = false;
+            }
+        }
+        fallthrough;
+
+    statecase(context->primary_state, PRIMARY_READ_HIERARCHY);
+        if (pkey->creationTicket.hierarchy == TPM2_RH_EK) {
+            r = ifapi_keystore_load_async(&context->keystore, &context->io, "/HE");
+            return_if_error2(r, "Could not open hierarchy /HE");
+        } else {
+            r = ifapi_keystore_load_async(&context->keystore, &context->io, "/HS");
+            return_if_error2(r, "Could not open hierarchy /HS");
+        }
+        fallthrough;
+
+    statecase(context->primary_state, PRIMARY_READ_HIERARCHY_FINISH);
+        r = ifapi_keystore_load_finish(&context->keystore, &context->io, hierarchy);
+        return_try_again(r);
+        return_if_error(r, "read_finish failed");
+
+        r = ifapi_initialize_object(context->esys, hierarchy);
+        goto_if_error_reset_state(r, "Initialize hierarchy object", error_cleanup);
+
+        if (pkey->creationTicket.hierarchy == TPM2_RH_EK) {
+            hierarchy->handle = ESYS_TR_RH_ENDORSEMENT;
+        } else {
+            hierarchy->handle = ESYS_TR_RH_OWNER;
+        }
+        fallthrough;
+
+    statecase(context->primary_state, PRIMARY_AUTHORIZE_HIERARCHY);
+        r = ifapi_authorize_object(context, hierarchy, &auth_session);
+        FAPI_SYNC(r, "Authorize hierarchy.", error_cleanup);
+
+        memset(&context->createPrimary.inSensitive, 0, sizeof(TPM2B_SENSITIVE_CREATE));
+        memset(&context->createPrimary.outsideInfo, 0, sizeof(TPM2B_DATA));
+        memset(&context->createPrimary.creationPCR, 0, sizeof(TPML_PCR_SELECTION));
+
+        r = Esys_CreatePrimary_Async(context->esys, hierarchy->handle,
+                                     auth_session, ESYS_TR_NONE, ESYS_TR_NONE,
+                                     &context->createPrimary.inSensitive,
+                                     &pkey->public,
+                                     &context->createPrimary.outsideInfo,
+                                     &context->createPrimary.creationPCR);
+        return_if_error(r, "CreatePrimary");
+        fallthrough;
+
+    statecase(context->primary_state, PRIMARY_HAUTH_SENT);
+        if (context->createPrimary.handle) {
+            *handle = context->createPrimary.handle;
+            context->primary_state = PRIMARY_CREATED;
+            return TSS2_FAPI_RC_TRY_AGAIN;
+        } else {
+            r = Esys_CreatePrimary_Finish(context->esys,
+                                          &pkey_object->handle, &outPublic,
+                                          &creationData, &creationHash,
+                                          &creationTicket);
+            return_try_again(r);
+            goto_if_error_reset_state(r, "FAPI regenerate primary", error_cleanup);
+        }
+        *handle = pkey_object->handle;
+        context->primary_state = PRIMARY_INIT;
+        break;
+
+    statecasedefault(context->primary_state);
+    }
+    SAFE_FREE(outPublic);
+    SAFE_FREE(creationData);
+    SAFE_FREE(creationHash);
+    SAFE_FREE(creationTicket);
+    ifapi_cleanup_ifapi_object(&context->createPrimary.hierarchy);
+    return  TSS2_RC_SUCCESS;
+
+error_cleanup:
+    SAFE_FREE(outPublic);
+    SAFE_FREE(creationData);
+    SAFE_FREE(creationHash);
+    SAFE_FREE(creationTicket);
+    ifapi_cleanup_ifapi_object(&context->createPrimary.hierarchy);
+    ifapi_cleanup_ifapi_object(&context->createPrimary.pkey_object);
+    return r;
+}
+
+TSS2_RC
+ifapi_session_init(FAPI_CONTEXT *context)
+{
+    LOG_TRACE("call");
+    return_if_null(context, "No context", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    return_if_null(context->esys, "No context", TSS2_FAPI_RC_NO_TPM);
+
+    if (context->state != _FAPI_STATE_INIT) {
+        return_error(TSS2_FAPI_RC_BAD_SEQUENCE, "Invalid State");
+    }
+
+    context->session1 = ESYS_TR_NONE;
+    context->session2 = ESYS_TR_NONE;
+    context->policy.session = ESYS_TR_NONE;
+    context->srk_handle = ESYS_TR_NONE;
+    return TSS2_RC_SUCCESS;
+}
+
+TSS2_RC
+ifapi_non_tpm_mode_init(FAPI_CONTEXT *context)
+{
+    LOG_TRACE("call");
+    return_if_null(context, "No context", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    if (context->state != _FAPI_STATE_INIT) {
+        return_error(TSS2_FAPI_RC_BAD_SEQUENCE, "Invalid State");
+    }
+
+    context->session1 = ESYS_TR_NONE;
+    context->session2 = ESYS_TR_NONE;
+    context->policy.session = ESYS_TR_NONE;
+    context->srk_handle = ESYS_TR_NONE;
+    return TSS2_RC_SUCCESS;
+}
+
+void
+ifapi_session_clean(FAPI_CONTEXT *context)
+{
+    if (context->session1 != ESYS_TR_NONE) {
+        if (Esys_FlushContext(context->esys, context->session1) != TSS2_RC_SUCCESS) {
+            LOG_ERROR("Cleanup session failed.");
+        }
+        context->session1 = ESYS_TR_NONE;
+    }
+    if (context->session2 != ESYS_TR_NONE) {
+        if (Esys_FlushContext(context->esys, context->session2) != TSS2_RC_SUCCESS) {
+            LOG_ERROR("Cleanup session failed.");
+            context->session2 = ESYS_TR_NONE;
+        }
+    }
+    if (!context->srk_persistent && context->srk_handle != ESYS_TR_NONE) {
+        if (Esys_FlushContext(context->esys, context->srk_handle) != TSS2_RC_SUCCESS) {
+            LOG_ERROR("Cleanup Policy Session  failed.");
+        }
+        context->srk_handle = ESYS_TR_NONE;
+    }
+    context->srk_persistent = false;
+}
+
+/** State machine for cleanup of a FAPI session.
+ *
+ * Used sessions and the SRK will be flushed.
+ *
+ * @param[in] context The FAPI_CONTEXT storing the used handles.
+ *
+ * @retval TSS2_RC_SUCCESS on success.
+ * @retval All possible error codes of ESAPI.
+ */
+TSS2_RC
+ifapi_cleanup_session(FAPI_CONTEXT *context)
+{
+    TSS2_RC r;
+
+    switch (context->cleanup_state) {
+        statecase(context->cleanup_state, CLEANUP_INIT);
+            if (context->session1 != ESYS_TR_NONE) {
+                r = Esys_FlushContext_Async(context->esys, context->session1);
+                try_again_or_error(r, "Flush session.");
+            }
+            fallthrough;
+
+        statecase(context->cleanup_state, CLEANUP_SESSION1);
+            if (context->session1 != ESYS_TR_NONE) {
+                r = Esys_FlushContext_Finish(context->esys);
+                try_again_or_error(r, "Flush session.");
+            }
+            context->session1 = ESYS_TR_NONE;
+
+            if (context->session2 != ESYS_TR_NONE) {
+                r = Esys_FlushContext_Async(context->esys, context->session2);
+                try_again_or_error(r, "Flush session.");
+            }
+            fallthrough;
+
+        statecase(context->cleanup_state, CLEANUP_SESSION2);
+            if (context->session2 != ESYS_TR_NONE) {
+                r = Esys_FlushContext_Finish(context->esys);
+                try_again_or_error(r, "Flush session.");
+            }
+            context->session2 = ESYS_TR_NONE;
+
+            if (!context->srk_persistent && context->srk_handle != ESYS_TR_NONE) {
+                r = Esys_FlushContext_Async(context->esys, context->srk_handle);
+                try_again_or_error(r, "Flush SRK.");
+            }
+            fallthrough;
+
+        statecase(context->cleanup_state, CLEANUP_SRK);
+            if (!context->srk_persistent && context->srk_handle != ESYS_TR_NONE) {
+                r = Esys_FlushContext_Finish(context->esys);
+                try_again_or_error(r, "Flush SRK.");
+
+                context->srk_handle = ESYS_TR_NONE;
+                context->srk_persistent = false;
+            }
+            context->cleanup_state = CLEANUP_INIT;
+            return TSS2_RC_SUCCESS;
+
+        statecasedefault(context->state);
+    }
+}
+
+/** Cleanup primary keys in error cases (non asynchronous).
+  */
+void
+ifapi_primary_clean(FAPI_CONTEXT *context)
+{
+    if (!context->srk_persistent && context->srk_handle != ESYS_TR_NONE) {
+        if (Esys_FlushContext(context->esys, context->srk_handle) != TSS2_RC_SUCCESS) {
+            LOG_ERROR("Cleanup session failed.");
+        }
+        context->srk_handle = ESYS_TR_NONE;
+    }
+    if (!context->ek_persistent && context->ek_handle != ESYS_TR_NONE) {
+        if (Esys_FlushContext(context->esys, context->ek_handle) != TSS2_RC_SUCCESS) {
+            LOG_ERROR("Cleanup EK failed.");
+        }
+        context->ek_handle = ESYS_TR_NONE;
+    }
+    context->srk_persistent = false;
+}
+
+TSS2_RC
+ifapi_get_sessions_async(FAPI_CONTEXT *context,
+                         IFAPI_SESSION_TYPE session_flags,
+                         TPMA_SESSION attribute_flags1,
+                         TPMA_SESSION attribute_flags2)
+{
+    TSS2_RC r;
+
+    LOG_TRACE("call");
+    context->session_flags = session_flags;
+    context->session1_attribute_flags = attribute_flags1;
+    context->session2_attribute_flags = attribute_flags2;
+    char *file = NULL;
+
+    if (!(session_flags & IFAPI_SESSION_GENEK)) {
+        context->srk_handle = ESYS_TR_NONE;
+        context->session_state = SESSION_CREATE_SESSION;
+        return TSS2_RC_SUCCESS;
+    }
+
+    context->primary_state = PRIMARY_INIT;
+    r = ifapi_asprintf(&file, "%s/%s", context->config.profile_name,
+                       IFAPI_SRK_KEY_PATH);
+    goto_if_error(r, "Error ifapi_asprintf", error_cleanup);
+
+    r = ifapi_load_primary_async(context, file);
+    return_if_error_reset_state(r, "Load EK");
+    free(file);
+
+    context->session_state = SESSION_WAIT_FOR_PRIMARY;
+    return TSS2_RC_SUCCESS;
+
+error_cleanup:
+    SAFE_FREE(file);
+    return r;
+}
+
+TSS2_RC
+ifapi_get_sessions_finish(FAPI_CONTEXT *context, const IFAPI_PROFILE *profile)
+{
+    TSS2_RC r;
+
+    switch (context->session_state) {
+    statecase(context->session_state, SESSION_WAIT_FOR_PRIMARY);
+        LOG_TRACE("**STATE** SESSION_WAIT_FOR_PRIMARY");
+        r = ifapi_load_primary_finish(context, &context->srk_handle);
+        return_try_again(r);
+        return_if_error(r, "Load primary.");
+        fallthrough;
+
+    statecase(context->session_state, SESSION_CREATE_SESSION);
+        LOG_TRACE("**STATE** SESSION_CREATE_SESSION");
+        if (!(context->session_flags & IFAPI_SESSION1)) {
+            LOG_TRACE("finished");
+            return TSS2_RC_SUCCESS;
+        }
+
+        r = ifapi_get_session_async(context->esys, context->srk_handle, profile);
+        return_if_error_reset_state(r, "Create FAPI session async");
+        fallthrough;
+
+    statecase(context->session_state, SESSION_WAIT_FOR_SESSION1);
+        LOG_TRACE("**STATE** SESSION_WAIT_FOR_SESSION1");
+        r = ifapi_get_session_finish(context->esys, &context->session1,
+                                     context->session1_attribute_flags);
+        return_try_again(r);
+        return_if_error_reset_state(r, "Create FAPI session finish");
+
+        if (!(context->session_flags & IFAPI_SESSION2)) {
+            LOG_TRACE("finished");
+            return TSS2_RC_SUCCESS;
+        }
+
+        r = ifapi_get_session_async(context->esys, context->srk_handle, profile);
+        return_if_error_reset_state(r, "Create FAPI session async");
+        fallthrough;
+
+    statecase(context->session_state, SESSION_WAIT_FOR_SESSION2);
+        LOG_TRACE("**STATE** SESSION_WAIT_FOR_SESSION2");
+        r = ifapi_get_session_finish(context->esys, &context->session2,
+                                     context->session2_attribute_flags);
+        return_try_again(r);
+
+        return_if_error_reset_state(r, "Create FAPI session finish");
+        break;
+
+    statecasedefault(context->session_state);
+    }
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Merge profile already stored in FAPI context into a key template
+ */
+TSS2_RC
+ifapi_merge_profile_into_nv_template(
+    FAPI_CONTEXT *context,
+    IFAPI_NV_TEMPLATE *template)
+{
+    const TPMA_NV extend_mask = TPM2_NT_EXTEND << TPMA_NV_TPM2_NT_SHIFT;
+    const TPMA_NV counter_mask = TPM2_NT_COUNTER << TPMA_NV_TPM2_NT_SHIFT;
+    const TPMA_NV bitfield_mask = TPM2_NT_BITS << TPMA_NV_TPM2_NT_SHIFT;
+    const IFAPI_PROFILE *profile = &context->profiles.default_profile;
+    size_t hash_size;
+
+    template->public.nameAlg = profile->nameAlg;
+    if ((template->public.attributes & extend_mask) == extend_mask) {
+        /* The size of the NV ram to be extended must be read from the
+           profile */
+        hash_size = ifapi_hash_get_digest_size(profile->nameAlg);
+        template->public.dataSize = hash_size;
+    } else if ((template->public.attributes & counter_mask) == counter_mask ||
+               (template->public.attributes & bitfield_mask) == bitfield_mask) {
+        /* For bit fields and counters only size 8 is possible */
+        template->public.dataSize = 8;
+    } else {
+        /* For normal NV ram the passed size will be used. */
+        template->public.dataSize = context->nv_cmd.numBytes;
+    }
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Merge profile already stored in FAPI context into a key template
+ */
+TSS2_RC
+ifapi_merge_profile_into_template(
+    const IFAPI_PROFILE *profile,
+    IFAPI_KEY_TEMPLATE *template)
+{
+    /* Merge profile parameters */
+    template->public.publicArea.type = profile->type;
+    template->public.publicArea.nameAlg = profile->nameAlg;
+    if (profile->type == TPM2_ALG_RSA) {
+        template->public.publicArea.parameters.rsaDetail.keyBits = profile->keyBits;
+        template->public.publicArea.parameters.rsaDetail.exponent = profile->exponent;
+    } else if (profile->type == TPM2_ALG_ECC) {
+        template->public.publicArea.parameters.eccDetail.curveID = profile->curveID;
+        template->public.publicArea.parameters.eccDetail.kdf.scheme = TPM2_ALG_NULL;
+    }
+
+    /* Set remaining parameters depending on key type */
+    if (template->public.publicArea.objectAttributes & TPMA_OBJECT_RESTRICTED) {
+        if (template->public.publicArea.objectAttributes & TPMA_OBJECT_DECRYPT) {
+            template->public.publicArea.parameters.asymDetail.symmetric =
+            profile->sym_parameters;
+        } else {
+            template->public.publicArea.parameters.asymDetail.symmetric.algorithm =
+            TPM2_ALG_NULL;
+        }
+        if (profile->type == TPM2_ALG_RSA) {
+            if (template->public.publicArea.objectAttributes & TPMA_OBJECT_SIGN_ENCRYPT) {
+                template->public.publicArea.parameters.rsaDetail.scheme.scheme =
+                profile->rsa_signing_scheme.scheme;
+                memcpy(&template->public.publicArea.parameters.rsaDetail.scheme.details,
+                       &profile->rsa_signing_scheme.details, sizeof(TPMU_ASYM_SCHEME));
+            } else {
+                template->public.publicArea.parameters.rsaDetail.scheme.scheme = TPM2_ALG_NULL;
+            }
+        } else if (profile->type == TPM2_ALG_ECC) {
+            if (template->public.publicArea.objectAttributes & TPMA_OBJECT_SIGN_ENCRYPT) {
+                template->public.publicArea.parameters.eccDetail.scheme.scheme =
+                profile->ecc_signing_scheme.scheme;
+                memcpy(&template->public.publicArea.parameters.eccDetail.scheme.details,
+                       &profile->rsa_signing_scheme.details, sizeof(TPMU_ASYM_SCHEME));
+            } else {
+                template->public.publicArea.parameters.eccDetail.scheme.scheme = TPM2_ALG_NULL;
+            }
+        } else {
+            template->public.publicArea.parameters.asymDetail.scheme.scheme = TPM2_ALG_NULL;
+        }
+    } else {
+        /* Non restricted key */
+        template->public.publicArea.parameters.asymDetail.symmetric.algorithm =
+        TPM2_ALG_NULL;
+        template->public.publicArea.parameters.asymDetail.scheme.scheme = TPM2_ALG_NULL;
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+static void
+full_path_to_fapi_path(IFAPI_KEYSTORE *keystore, char *path)
+{
+    int start_pos, end_pos, i;
+    int path_length = strlen(path);
+    size_t keystore_length = strlen(keystore->userdir);
+    char fapi_path_delim;
+
+    start_pos = 0;
+
+    if (strncmp(&path[0], keystore->userdir, keystore_length) == 0) {
+        start_pos =  strlen(keystore->userdir);
+    } else {
+        keystore_length = strlen(keystore->systemdir);
+        if (strncmp(&path[0], keystore->systemdir, keystore_length) == 0)
+            start_pos = strlen(keystore->systemdir);
+    }
+    if (!start_pos)
+        return;
+
+    end_pos = path_length - start_pos;
+    memmove(&path[0], &path[start_pos], end_pos);
+    size_t ip = 0;
+    size_t lp = strlen(path);
+    while (ip < lp) {
+        if (strncmp(&path[ip], "//", 2) == 0) {
+            memmove(&path[ip], &path[ip+1], lp-ip);
+            lp -= 1;
+        } else {
+            ip += 1;
+        }
+    }
+
+    if (ifapi_path_type_p(path, IFAPI_POLICY_PATH))
+        fapi_path_delim = '.';
+    else
+        fapi_path_delim = IFAPI_FILE_DELIM_CHAR;
+
+    for (i = end_pos - 1; i > 0; i--) {
+        if (path[i] == fapi_path_delim) {
+            path[i] = '\0';
+            break;
+        }
+    }
+}
+
+/** Asynchronous function for loading a key.
+  *
+  * @param[in,out] context The FAPI_CONTEXT.
+  * @param[in]     keyPath the key path without the parent directories storing
+  *                of the key store. (e.g. HE/EK, HS/SRK/mykey)
+  * @retval All possible error codes of FAPI
+  * @retval TSS2_RC_SUCCESS if the function call was a success.
+  */
+TSS2_RC
+ifapi_load_keys_async(FAPI_CONTEXT *context, char const *keyPath)
+{
+    TSS2_RC r;
+    NODE_STR_T *path_list;
+    size_t path_length;
+    char *fapi_key_path = NULL;
+
+    LOG_TRACE("Load key: %s", keyPath);
+    fapi_key_path = strdup(keyPath);
+    check_oom(fapi_key_path);
+    full_path_to_fapi_path(&context->keystore, fapi_key_path);
+    r = get_explicit_key_path(&context->keystore, fapi_key_path, &path_list);
+    SAFE_FREE(fapi_key_path);
+    return_if_error(r, "Compute explicit path.");
+
+    context->loadKey.path_list = path_list;
+    path_length = ifapi_path_length(path_list);
+    r = ifapi_load_key_async(context, path_length);
+    return_if_error(r, "Load key async.");
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Asynchronous finish function for loading a key.
+  *
+  * @param[in,out] context The FAPI_CONTEXT.
+  * @param[in] flush_parent If false the parent of the key to be loaded
+  *            will not be flushed.
+  * @param[out]    handle The ESYS handle of the key.
+  * @retval All possible error codes of FAPI
+  * @retval TSS2_RC_SUCCESS if the function call was a success.
+ */
+TSS2_RC
+ifapi_load_keys_finish(
+    FAPI_CONTEXT *context,
+    bool flush_parent,
+    ESYS_TR *handle,
+    IFAPI_OBJECT **key_object)
+{
+    TSS2_RC r;
+
+    r = ifapi_load_key_finish(context, flush_parent);
+    if (r == TSS2_FAPI_RC_TRY_AGAIN)
+        return r;
+
+    return_if_error(r, "Load keys");
+
+    *handle = context->loadKey.auth_object.handle;
+    /* The current authorization object is the last key loaded and
+       will be used. */
+    *key_object = &context->loadKey.auth_object;
+    free_string_list(context->loadKey.path_list);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Initialize state machine for loading a key.
+ *
+ * @param[in,out] context for storing all state information.
+ * @param[in] position the position of the key in path list stored in
+ *            context->loadKey.path_list.
+ * @retval TSS2_RC_SUCCESS If data can be read.
+ */
+TSS2_RC
+ifapi_load_key_async(FAPI_CONTEXT *context, size_t position)
+{
+    context->loadKey.state = LOAD_KEY_GET_PATH;
+    context->loadKey.position = position;
+    context->loadKey.key_list = NULL;
+    context->loadKey.parent_handle = ESYS_TR_NONE;
+    // context->loadKey.auth_object = NULL;
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** State machine for loading a key.
+ *
+ * A stack with all sup keys will be created and decremented during
+ * the loading auf all keys.
+ * The object of the loaded key will be stored in:
+ * context->loadKey.auth_object
+ *
+ * @param[in,out] context for storing all state information.
+ * @retval TSS2_RC_SUCCESS If data can be read.
+ */
+TSS2_RC
+ifapi_load_key_finish(FAPI_CONTEXT *context, bool flush_parent)
+{
+    TSS2_RC r;
+    NODE_STR_T *path_list = context->loadKey.path_list;
+    size_t *position =  &context->loadKey.position;
+    IFAPI_OBJECT *key_object = NULL;
+    IFAPI_KEY *key = NULL;
+    ESYS_TR auth_session;
+
+    switch (context->loadKey.state) {
+    statecase(context->loadKey.state, LOAD_KEY_GET_PATH);
+        context->loadKey.key_path = NULL;
+        r = ifapi_path_string_n(&context->loadKey.key_path, NULL, path_list, NULL,
+                                *position);
+        return_if_error(r, "Compute key path.");
+
+        context->loadKey.key_object = ifapi_allocate_object(context);
+        goto_if_null2(context->loadKey.key_object, "Allocating key", r,
+                      TSS2_FAPI_RC_MEMORY, error_cleanup);
+
+        goto_if_null2(context->loadKey.key_path, "Invalid path", r,
+                      TSS2_FAPI_RC_GENERAL_FAILURE,
+                      error_cleanup); /**< to avoid scan-build errors. */
+
+        r = ifapi_keystore_load_async(&context->keystore, &context->io,
+                                      context->loadKey.key_path);
+        return_if_error2(r, "Could not open: %s", context->loadKey.key_path);
+        fallthrough;
+
+    statecase(context->loadKey.state, LOAD_KEY_READ_KEY);
+        goto_if_null2(context->loadKey.key_path, "Invalid path", r,
+                      TSS2_FAPI_RC_GENERAL_FAILURE,
+                      error_cleanup); /**< to avoid scan-build errors. */
+
+        key = &context->loadKey.key_object->misc.key;
+
+        r = ifapi_keystore_load_finish(&context->keystore, &context->io,
+                                       context->loadKey.key_object);
+        if (r != TSS2_RC_SUCCESS) {
+            ifapi_cleanup_ifapi_object(context->loadKey.key_object);
+        }
+        return_try_again(r);
+        return_if_error(r, "read_finish failed");
+
+        if (context->loadKey.key_object->objectType != IFAPI_KEY_OBJ)
+            goto_error(r, TSS2_FAPI_RC_BAD_KEY, "%s is no key", error_cleanup,
+                       context->loadKey.key_path);
+
+        r = ifapi_initialize_object(context->esys, context->loadKey.key_object);
+        goto_if_error_reset_state(r, "Initialize key object", error_cleanup);
+
+        SAFE_FREE(context->loadKey.key_path);
+        context->loadKey.handle = context->loadKey.key_object->handle;
+        if (context->loadKey.handle != ESYS_TR_NONE) {
+            /* Persistent key could be desearialized keys can be loaded */
+            r = ifapi_copy_ifapi_key_object(&context->loadKey.auth_object,
+                context->loadKey.key_object);
+            goto_if_error(r, "Could not copy key object", error_cleanup);
+            ifapi_cleanup_ifapi_object(context->loadKey.key_object);
+            context->loadKey.state = LOAD_KEY_LOAD_KEY;
+
+            return TSS2_FAPI_RC_TRY_AGAIN;
+        }
+
+        if (key->private.size == 0) {
+            /* Create a deep copy of the primary key */
+            ifapi_cleanup_ifapi_key(key);
+            r = ifapi_copy_ifapi_key(key, &context->createPrimary.pkey_object.misc.key);
+            goto_if_error(r, "Could not copy primary key", error_cleanup);
+            context->primary_state = PRIMARY_READ_HIERARCHY;
+            context->loadKey.state = LOAD_KEY_WAIT_FOR_PRIMARY;
+            return TSS2_FAPI_RC_TRY_AGAIN;
+        }
+        IFAPI_OBJECT * copyToPush = malloc(sizeof(IFAPI_OBJECT));
+        goto_if_null(copyToPush, "Out of memory", TSS2_FAPI_RC_MEMORY, error_cleanup);
+        r = ifapi_copy_ifapi_key_object(copyToPush, context->loadKey.key_object);
+        goto_if_error(r, "Could not create a copy to push", error_cleanup);
+        r = push_object_to_list(copyToPush, &context->loadKey.key_list);
+        goto_if_error(r, "Out of memory", error_cleanup);
+
+        ifapi_cleanup_ifapi_object(context->loadKey.key_object);
+
+        *position -= 1;
+        context->loadKey.state = LOAD_KEY_GET_PATH;
+        return TSS2_FAPI_RC_TRY_AGAIN;
+
+    statecase(context->loadKey.state, LOAD_KEY_LOAD_KEY);
+        if (!(context->loadKey.key_list)) {
+            LOG_TRACE("All keys loaded.");
+            return TSS2_RC_SUCCESS;
+        }
+
+        /* if flush_parent is false parent is only flushed if a new parent
+           is available */
+        if (!flush_parent && context->loadKey.parent_handle != ESYS_TR_NONE) {
+            r = Esys_FlushContext(context->esys, context->loadKey.parent_handle);
+            goto_if_error_reset_state(r, "Flush object", error_cleanup);
+        }
+        fallthrough;
+
+    statecase(context->loadKey.state, LOAD_KEY_AUTHORIZE);
+        key_object = context->loadKey.key_list->object;
+        key = &key_object->misc.key;
+        r = ifapi_authorize_object(context, &context->loadKey.auth_object, &auth_session);
+        FAPI_SYNC(r, "Authorize key.", error_cleanup);
+
+        /* Store parent handle in context for usage in ChangeAuth if not persistent */
+        context->loadKey.parent_handle =  context->loadKey.handle;
+        if (context->loadKey.auth_object.misc.key.persistent_handle)
+            context->loadKey.parent_handle_persistent = true;
+        else
+            context->loadKey.parent_handle_persistent = false;
+
+        TPM2B_PRIVATE private;
+
+        private.size = key->private.size;
+        memcpy(&private.buffer[0], key->private.buffer, key->private.size);
+
+        r = Esys_Load_Async(context->esys, context->loadKey.handle,
+                            auth_session,
+                            ESYS_TR_NONE, ESYS_TR_NONE,
+                            &private, &key->public);
+        goto_if_error(r, "Load async", error_cleanup);
+        fallthrough;
+
+    statecase(context->loadKey.state, LOAD_KEY_AUTH);
+        r = Esys_Load_Finish(context->esys, &context->loadKey.handle);
+        return_try_again(r);
+        goto_if_error_reset_state(r, "Load", error_cleanup);
+
+        /* The current parent is flushed if not prohibited by flush parent */
+        if (flush_parent && context->loadKey.auth_object.objectType == IFAPI_KEY_OBJ &&
+            ! context->loadKey.auth_object.misc.key.persistent_handle) {
+            r = Esys_FlushContext(context->esys, context->loadKey.auth_object.handle);
+            goto_if_error_reset_state(r, "Flush object", error_cleanup);
+
+        }
+        LOG_TRACE("New key used as auth object.");
+        ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
+        r = ifapi_copy_ifapi_key_object(&context->loadKey.auth_object,
+                context->loadKey.key_list->object);
+        goto_if_error(r, "Could not copy loaded key", error_cleanup);
+        context->loadKey.auth_object.handle =  context->loadKey.handle;
+        IFAPI_OBJECT *top_obj = context->loadKey.key_list->object;
+        ifapi_cleanup_ifapi_object(top_obj);
+        SAFE_FREE(context->loadKey.key_list->object);
+        r = pop_object_from_list(context, &context->loadKey.key_list);
+        goto_if_error_reset_state(r, "Pop key failed.", error_cleanup);
+
+        if (context->loadKey.key_list) {
+            /* Object can be cleaned if it's not the last */
+            ifapi_free_object(context, &top_obj);
+        }
+
+        context->loadKey.state = LOAD_KEY_LOAD_KEY;
+        return TSS2_FAPI_RC_TRY_AGAIN;
+
+    statecase(context->loadKey.state, LOAD_KEY_WAIT_FOR_PRIMARY);
+        r = ifapi_load_primary_finish(context, &context->loadKey.handle);
+        return_try_again(r);
+        goto_if_error(r, "CreatePrimary", error_cleanup);
+
+        /* Save the primary object for authorization */
+        r = ifapi_copy_ifapi_key_object(&context->loadKey.auth_object,
+                &context->createPrimary.pkey_object);
+        goto_if_error(r, "Could not copy primary key", error_cleanup);
+
+        if (context->loadKey.key_list) {
+            context->loadKey.state = LOAD_KEY_LOAD_KEY;
+            return TSS2_FAPI_RC_TRY_AGAIN;
+        } else {
+            LOG_TRACE("success");
+            ifapi_cleanup_ifapi_object(context->loadKey.key_object);
+            ifapi_cleanup_ifapi_object(&context->loadKey.auth_object);
+            return TSS2_RC_SUCCESS;
+        }
+        break;
+
+    statecasedefault(context->loadKey.state);
+    }
+
+error_cleanup:
+    ifapi_free_object_list(context->loadKey.key_list);
+    ifapi_cleanup_ifapi_object(context->loadKey.key_object);
+    SAFE_FREE(context->loadKey.key_path);
+    return r;
+}
+
+TSS2_RC
+get_entities(IFAPI_KEYSTORE *keystore, char *dir_name, NODE_OBJECT_T **list, size_t *n)
+{
+    DIR *dir;
+    struct dirent *entry;
+    TSS2_RC r;
+    char *path = NULL;
+    NODE_OBJECT_T *second;
+
+    if (!(dir = opendir(dir_name))) {
+        return TSS2_RC_SUCCESS;
+    }
+
+    while ((entry = readdir(dir)) != NULL) {
+        path = NULL;
+        if (entry->d_type == DT_DIR) {
+            if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
+                continue;
+            r = ifapi_asprintf(&path, "%s/%s", dir_name, entry->d_name);
+            return_if_error(r, "Out of memory");
+
+            LOG_TRACE("Directory: %s", path);
+            r = get_entities(keystore, path, list, n);
+            Fapi_Free(path);
+            return_if_error(r, "get_entities");
+
+        } else {
+            size_t l_dir = strlen(dir_name);
+            size_t l_user_dir = strlen(keystore->userdir);
+            size_t l_system_dir = strlen(keystore->systemdir);
+            if (dir_name[l_dir - 1] == IFAPI_FILE_DELIM_CHAR)
+                l_dir -= 1;
+            if (keystore->userdir[l_user_dir - 1] == IFAPI_FILE_DELIM_CHAR)
+                l_user_dir -= 1;
+            if (keystore->systemdir[l_system_dir - 1] == IFAPI_FILE_DELIM_CHAR)
+                l_user_dir -= 1;
+            if ((strncmp(dir_name, keystore->userdir, l_user_dir) == 0 && l_dir != l_user_dir) ||
+                (strncmp(dir_name, keystore->systemdir, l_system_dir) == 0 && l_dir != l_system_dir)) {
+                r = ifapi_asprintf(&path, "%s/%s", dir_name, entry->d_name);
+                return_if_error(r, "Out of memory");
+
+                NODE_OBJECT_T *file_obj = calloc(sizeof(NODE_OBJECT_T), 1);
+                return_if_null(file_obj, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+                *n += 1;
+                file_obj->object = strdup(path);
+                if (file_obj->object == NULL) {
+                    LOG_ERROR("%s", "Out of memory.");
+                    SAFE_FREE(file_obj);
+                    SAFE_FREE(path);
+                    closedir(dir);
+                    return TSS2_FAPI_RC_MEMORY;
+                }
+                if (*list != NULL) {
+                    second = *list;
+                    file_obj->next = second;
+                }
+                *list = file_obj;
+                LOG_TRACE("File: %s", path);
+                SAFE_FREE(path);
+            }
+        }
+    }
+    closedir(dir);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Get all object files from key store.
+ *
+ * @param[in] The search path in key store.
+ * @param[out] The array of absolute path names.
+ * @retval TSS2_RC_SUCCESS if computation of path array was successful.
+ */
+TSS2_RC
+ifapi_get_entities(
+    IFAPI_KEYSTORE *keystore,
+    const char *searchPath,
+    char ***pathlist,
+    size_t *numPaths)
+{
+    TSS2_RC r;
+    NODE_OBJECT_T *file_list = NULL;
+    char *dir = keystore->systemdir;
+    char *full_search_path = NULL;
+    size_t n;
+    NODE_OBJECT_T *head;
+    char **pathlist2;
+    char *expSearchPath = NULL;
+
+    /* Get objects from system directory */
+    if (searchPath && strcmp(searchPath,"") != 0 && strcmp(searchPath,"/") != 0) {
+        size_t start_pos = 0;
+        if (searchPath[0] == IFAPI_FILE_DELIM_CHAR)
+            start_pos = 1;
+        if ((strncmp(&searchPath[start_pos], "HS", 2) == 0 ||
+             strncmp(&searchPath[start_pos], "HE", 2) == 0) &&
+            strlen(&searchPath[start_pos]) <= 3) {
+            /* Root directory is hierarchy */
+            r = ifapi_asprintf(&expSearchPath, "%s/", keystore->defaultprofile,
+                               searchPath[start_pos]);
+            return_if_error(r, "Out of memory.");
+
+        } else {
+            /* Try to expand a key path */
+            r = ifapi_expand_path(keystore, searchPath, &expSearchPath);
+            return_if_error(r, "Out of memory.");
+        }
+    } else {
+        /* get entities for the complete data store */
+        expSearchPath = NULL;
+    }
+    r = ifapi_asprintf(&full_search_path, "%s%s%s", dir, IFAPI_FILE_DELIM,
+                       expSearchPath?expSearchPath:"");
+    return_if_error(r, "Out of memory.");
+
+
+    *numPaths = 0;
+    r = get_entities(keystore, full_search_path, &file_list, numPaths);
+    goto_if_error(r, "get_entities", error_cleanup);
+
+    /* Get objects from user directory if not equal system directory */
+    if (strcmp(keystore->systemdir, keystore->userdir) != 0) {
+        SAFE_FREE(full_search_path);
+        dir = keystore->userdir;
+        if (searchPath) {
+            r = ifapi_asprintf(&full_search_path, "%s%s%s", dir, IFAPI_FILE_DELIM,
+                               expSearchPath?expSearchPath:"");
+            return_if_error(r, "Out of memory.");
+        } else {
+            /* get entities for the complete data store */
+            strdup_check(full_search_path, dir, r, error_cleanup);
+        }
+        r = get_entities(keystore, full_search_path, &file_list, numPaths);
+        goto_if_error(r, "get_entities", error_cleanup);
+    }
+
+    if (*numPaths > 0) {
+        size_t size_path_list = *numPaths * sizeof(char *);
+        pathlist2 = calloc(1, size_path_list);
+        goto_if_null(pathlist2, "Out of memory.", TSS2_FAPI_RC_MEMORY,
+                error_cleanup);
+        n = *numPaths;
+
+        /* Move file names from list to array */
+        while (n > 0 && file_list) {
+            n -= 1;
+            pathlist2[n] = file_list->object;
+            head = file_list;
+            file_list = file_list->next;
+            SAFE_FREE(head);
+        }
+        *pathlist = pathlist2;
+        SAFE_FREE(full_search_path);
+        SAFE_FREE(expSearchPath);
+        return TSS2_RC_SUCCESS;
+    }
+
+error_cleanup:
+    while (file_list) {
+        head = file_list;
+        file_list = file_list->next;
+        SAFE_FREE(head->object);
+        SAFE_FREE(head);
+    }
+    SAFE_FREE(expSearchPath);
+    SAFE_FREE(full_search_path);
+    return r;
+}
+
+size_t
+get_name_alg(FAPI_CONTEXT *context, IFAPI_OBJECT *object)
+{
+    switch (object->objectType) {
+    case IFAPI_KEY_OBJ:
+        return object->misc.key.public.publicArea.nameAlg;
+    case IFAPI_NV_OBJ:
+        return object->misc.nv.public.nvPublic.nameAlg;
+    case IFAPI_HIERARCHY_OBJ:
+        return context->profiles.default_profile.nameAlg;
+    default:
+        return 0;
+    }
+}
+
+/** Check whether policy session has to be flushed.
+ *
+ * Policy sessions with cleared continue session flag are not flushed in error
+ * cases. Therefore the return code will be checked and if a policy session was
+ * used the session will be flushed if the command was not executed successfully.
+ *
+ * @param[in,out] context for storing all state information.
+ * @param[in] session the sessio to be checked wheter flush is needed.
+ * @param[in] r The return code of the command using the session.
+ */
+void
+ifapi_flush_policy_session(FAPI_CONTEXT *context, ESYS_TR session, TSS2_RC r)
+{
+    if (session != context->session1) {
+        /* A policy session was used instead auf the default session. */
+        if (r != TSS2_RC_SUCCESS) {
+            Esys_FlushContext(context->esys, session);
+        }
+    }
+}
+
+/** State machine to authorize a key, a NV object of a hierarchy.
+ *
+ * @param[in,out] context for storing all state information.
+ * @param[in] The FAPI object.
+ * @param[out] The session which can be used for object authorization.
+ * @retval TSS2_RC_SUCCESS If data can be read.
+ * @retval TSS2_FAPI_RC_MEMORY: if not enough memory can be allocated.
+ * @retval TSS2_FAPI_RC_BAD_VALUE If wrong values are detected during execution.
+ * @retval TSS2_FAPI_RC_IO_ERROR If an error occurs during access to the policy
+ *         store.
+ * @retval TSS2_FAPI_RC_PATH_NOT_FOUND If a policy for a certain path was not found.
+ * @retval TSS2_FAPI_RC_POLICY_UNKNOWN If policy search for a certain policy diges was
+           not successful.
+ * @retval TSS2_FAPI_RC_BAD_TEMPLATE In a invalid policy is loaded during execution.
+ * @retval TPM2_RC_BAD_AUTH If the authentication for an object needed for policy
+ *         execution fails.
+ */
+TSS2_RC
+ifapi_authorize_object(FAPI_CONTEXT *context, IFAPI_OBJECT *object, ESYS_TR *session)
+{
+    TSS2_RC r;
+    TPMI_YES_NO auth_required;
+
+    LOG_DEBUG("Authorize object: %x", object->handle);
+    switch (object->authorization_state) {
+        statecase(object->authorization_state, AUTH_INIT)
+            LOG_TRACE("**STATE** AUTH_INIT");
+
+            if (!policy_digest_size(object)) {
+                /* No policy used authorization callbacks have to be called if necessary. */
+                if (object_with_auth(object)) {
+                    r = ifapi_set_auth(context, object, "Authorize object");
+                    return_if_error(r, "Set auth value");
+                }
+                /* No policy session needed current fapi session can be used */
+                if (context->session1 && context->session1 != ESYS_TR_NONE)
+                    *session = context->session1;
+                else
+                    /* Use password session if session1 had not been created */
+                    *session = ESYS_TR_PASSWORD;
+                break;
+            }
+            r = ifapi_policyutil_execute_prepare(context, get_name_alg(context, object)
+                                                 ,object->policy_harness);
+            return_if_error(r, "Prepare policy execution.");
+
+            /* Next state will switch from prev context to next context. */
+            context->policy.util_current_policy =  context->policy.util_current_policy->prev;
+            object->authorization_state = AUTH_EXEC_POLICY;
+            fallthrough;
+
+        statecase(object->authorization_state, AUTH_EXEC_POLICY)
+            *session = ESYS_TR_NONE;
+            r = ifapi_policyutil_execute(context, session);
+            if (r == TSS2_FAPI_RC_TRY_AGAIN)
+                return r;
+
+            return_if_error(r, "Execute policy.");
+
+            r = Esys_TRSess_GetAuthRequired(context->esys, *session,
+                                            &auth_required);
+            return_if_error(r, "GetAuthRequired");
+
+            /* Check whether PolicyCommand requiring authorization was executed */
+            if (auth_required == TPM2_YES) {
+                r = ifapi_set_auth(context, object, "Authorize object");
+                goto_if_error(r, "Set auth value", error);
+            }
+            /* Clear continue session flag, so policy session will be flushed after authorization */
+            r = Esys_TRSess_SetAttributes(context->esys, *session, 0, TPMA_SESSION_CONTINUESESSION);
+            goto_if_error(r, "Esys_TRSess_SetAttributes", error);
+            break;
+
+        statecasedefault(object->authorization_state)
+    }
+
+    object->authorization_state = AUTH_INIT;
+    return TSS2_RC_SUCCESS;
+
+ error:
+    /* No policy call was executed session can be flushed */
+    Esys_FlushContext(context->esys, *session);
+    return r;
+}
+
+/** State machine to write data to the TPM.
+ *
+ * Context nv_cmd has to be prepared:
+ *
+ * @param[in,out] context for storing all state information.
+ * @param[in] nvPath The fapi path of the NV object.
+ * @param[in] param_offset The offset in the NV memory (will be stored in context).
+ * @param[in] data The pointer to the data to be written.
+ * @param[in] size The number of bytes to be written.
+ * @retval TSS2_RC_SUCCESS If data can be read.
+ */
+TSS2_RC
+ifapi_nv_write(
+    FAPI_CONTEXT *context,
+    char         *nvPath,
+    size_t         param_offset,
+    uint8_t const *data,
+    size_t         size)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    ESYS_TR auth_index;
+    size_t data_idx = context->nv_cmd.data_idx;
+    UINT16 bytesRequested = context->nv_cmd.bytesRequested;
+    ESYS_TR  offset =  context->nv_cmd.offset;
+    ESYS_TR nv_index =  context->nv_cmd.esys_handle;
+    IFAPI_OBJECT *object = &context->nv_cmd.nv_object;
+    IFAPI_OBJECT *auth_object = &context->nv_cmd.auth_object;
+    TPM2B_MAX_NV_BUFFER *aux_data = (TPM2B_MAX_NV_BUFFER *)&context->aux_data;
+    char *nv_file_name = NULL;
+    ESYS_TR auth_session;
+
+    switch (context->nv_cmd.nv_write_state) {
+    statecase(context->nv_cmd.nv_write_state, NV2_WRITE_INIT);
+        memset(&context->nv_cmd.nv_object, 0, sizeof(IFAPI_OBJECT));
+        context->nv_cmd.nvPath = nvPath;
+        context->nv_cmd.offset = param_offset;
+        context->nv_cmd.numBytes = size;
+        context->nv_cmd.data = data;
+        if (context->nv_cmd.numBytes > context->nv_buffer_max)
+            aux_data->size = context->nv_buffer_max;
+        else
+            aux_data->size = context->nv_cmd.numBytes;
+        context->nv_cmd.data_idx = aux_data->size;
+
+        /* Use calloc to ensure zero padding for write buffer. */
+        context->nv_cmd.write_data = calloc(object->misc.nv.public.nvPublic.dataSize,
+                                            1);
+        goto_if_null2(context->nv_cmd.write_data, "Out of memory.", r,
+                      TSS2_FAPI_RC_MEMORY,
+                      error_cleanup);
+        memcpy(context->nv_cmd.write_data, data,
+               object->misc.nv.public.nvPublic.dataSize);
+        memcpy(&aux_data->buffer[0], &context->nv_cmd.data[0], aux_data->size);
+
+        r = ifapi_keystore_load_async(&context->keystore, &context->io,
+                                      context->nv_cmd.nvPath);
+        return_if_error2(r, "Could not open: %s", context->nv_cmd.nvPath);
+        fallthrough;
+
+    statecase(context->nv_cmd.nv_write_state, NV2_WRITE_READ);
+        r = ifapi_keystore_load_finish(&context->keystore, &context->io, object);
+        return_try_again(r);
+        return_if_error(r, "read_finish failed");
+
+        if (object->objectType != IFAPI_NV_OBJ)
+            goto_error(r, TSS2_FAPI_RC_BAD_PATH, "%s is no NV object.", error_cleanup,
+                       context->nv_cmd.nvPath);
+
+        r = ifapi_initialize_object(context->esys, object);
+        goto_if_error_reset_state(r, "Initialize NV object", error_cleanup);
+
+        /* Store object info in context */
+        nv_index = context->nv_cmd.nv_object.handle;
+        context->nv_cmd.esys_handle = nv_index;
+        context->nv_cmd.nv_obj = object->misc.nv;
+
+        if (object->misc.nv.public.nvPublic.attributes & TPMA_NV_PPWRITE) {
+            ifapi_init_hierarchy_object(auth_object, ESYS_TR_RH_PLATFORM);
+            auth_index = ESYS_TR_RH_PLATFORM;
+        } else {
+            if (object->misc.nv.public.nvPublic.attributes & TPMA_NV_OWNERWRITE) {
+                ifapi_init_hierarchy_object(auth_object, ESYS_TR_RH_OWNER);
+                auth_index = ESYS_TR_RH_OWNER;
+            } else {
+                auth_index = nv_index;
+            }
+            *auth_object = *object;
+        }
+        context->nv_cmd.auth_index = auth_index;
+        fallthrough;
+
+    statecase(context->nv_cmd.nv_write_state, NV2_WRITE_AUTHORIZE);
+        r = ifapi_authorize_object(context, auth_object, &auth_session);
+        FAPI_SYNC(r, "Authorize NV object.", error_cleanup);
+
+        r = Esys_NV_Write_Async(context->esys,
+                                context->nv_cmd.auth_index,
+                                nv_index,
+                                auth_session,
+                                context->session2,
+                                ESYS_TR_NONE,
+                                aux_data,
+                                offset);
+        goto_if_error_reset_state(r, " Fapi_NvWrite_Async", error_cleanup);
+
+        if (!(object->misc.nv.public.nvPublic.attributes & TPMA_NV_NO_DA))
+            context->nv_cmd.nv_write_state = NV2_WRITE_AUTH_SENT;
+        else
+            context->nv_cmd.nv_write_state =  NV2_WRITE_NULL_AUTH_SENT;
+
+        context->nv_cmd.bytesRequested = aux_data->size;
+
+        context->nv_cmd.offset = offset;
+        fallthrough;
+
+    case NV2_WRITE_AUTH_SENT:
+    case NV2_WRITE_NULL_AUTH_SENT:
+        r = Esys_NV_Write_Finish(context->esys);
+        return_try_again(r);
+
+        if ((r & ~TPM2_RC_N_MASK) == TPM2_RC_BAD_AUTH) {
+            if (context->nv_cmd.nv_write_state ==  NV2_WRITE_NULL_AUTH_SENT) {
+                IFAPI_OBJECT *auth_object = &context->nv_cmd.auth_object;
+                r = ifapi_set_auth(context, auth_object, "NV Write");
+                goto_if_error_reset_state(r, " Fapi_NvWrite_Finish", error_cleanup);
+
+                r = Esys_NV_Write_Async(context->esys,
+                                        context->nv_cmd.auth_index,
+                                        nv_index,
+                                        (!context->policy.session
+                                         || context->policy.session == ESYS_TR_NONE) ? context->session1 :
+                                        context->policy.session,
+                                        context->session2,
+                                        ESYS_TR_NONE,
+                                        aux_data,
+                                        offset);
+                goto_if_error_reset_state(r, "FAPI NV_Write_Async", error_cleanup);
+
+                context->nv_cmd.nv_write_state = NV2_WRITE_AUTH_SENT;
+                return TSS2_FAPI_RC_TRY_AGAIN;
+            }
+        }
+        goto_if_error_reset_state(r, "FAPI NV_Write_Finish", error_cleanup);
+
+        context->nv_cmd.numBytes -= context->nv_cmd.bytesRequested;
+
+        if (context->nv_cmd.numBytes > 0) {
+            if (context->nv_cmd.numBytes > context->nv_buffer_max)
+                aux_data->size = context->nv_buffer_max;
+            else
+                aux_data->size = context->nv_cmd.numBytes;
+            memcpy(&aux_data->buffer[0], &context->nv_cmd.write_data[data_idx],
+                   aux_data->size);
+            offset += bytesRequested;
+            r = Esys_NV_Write_Async(context->esys,
+                                    context->nv_cmd.auth_index,
+                                    nv_index,
+                                    context->session1,
+                                    context->session2,
+                                    ESYS_TR_NONE,
+                                    aux_data,
+                                    offset);
+            goto_if_error_reset_state(r, "FAPI NV_Write", error_cleanup);
+
+            context->nv_cmd.bytesRequested = aux_data->size;
+            //context->state =  NV_READ_AUTH_SENT;
+            return TSS2_FAPI_RC_TRY_AGAIN;
+
+        }
+        fallthrough;
+
+    statecase(context->nv_cmd.nv_write_state, NV2_WRITE_WRITE_PREPARE);
+        /* Set written bit in keystore */
+        context->nv_cmd.nv_object.misc.nv.public.nvPublic.attributes |= TPMA_NV_WRITTEN;
+        /* Perform esys serialization if necessary */
+        r = ifapi_esys_serialize_object(context->esys, &context->nv_cmd.nv_object);
+        goto_if_error(r, "Prepare serialization", error_cleanup);
+
+        /* Start writing the NV object to the key store */
+        r = ifapi_keystore_store_async(&context->keystore, &context->io,
+                                       context->nv_cmd.nvPath,
+                                       &context->nv_cmd.nv_object);
+        goto_if_error_reset_state(r, "Could not open: %sh", error_cleanup,
+                                  context->nv_cmd.nvPath);
+        context->nv_cmd.nv_write_state = NV2_WRITE_WRITE;
+        fallthrough;
+
+    statecase(context->nv_cmd.nv_write_state, NV2_WRITE_WRITE);
+        /* Finish writing the NV object to the key store */
+        r = ifapi_keystore_store_finish(&context->keystore, &context->io);
+        return_try_again(r);
+        return_if_error_reset_state(r, "write_finish failed");
+
+        LOG_DEBUG("success");
+        r = TSS2_RC_SUCCESS;
+
+        context->nv_cmd.nv_write_state = NV2_WRITE_INIT;
+        break;
+
+    statecasedefault(context->nv_cmd.nv_write_state);
+    }
+
+error_cleanup:
+    SAFE_FREE(nv_file_name);
+    SAFE_FREE(context->nv_cmd.write_data);
+    return r;
+}
+
+/** State machine to read data from TPM.
+ *
+ * Context nv_cmd has to be prepared:
+ * - auth_index
+ * - numBytes
+ * - esys_handle
+ * @param[in,out] context for storing all state information.
+ * @param[out] data the data fetched from TPM.
+ * @param[in,out] The number of bytes requested and fetched.
+ * @retval TSS2_RC_SUCCESS If data can be read.
+ */
+TSS2_RC
+ifapi_nv_read(
+    FAPI_CONTEXT *context,
+    uint8_t     **data,
+    size_t       *size)
+{
+    TSS2_RC r;
+    UINT16 aux_size;
+    TPM2B_MAX_NV_BUFFER *aux_data;
+    UINT16 bytesRequested = context->nv_cmd.bytesRequested;
+    size_t numBytes = context->nv_cmd.numBytes;
+    ESYS_TR nv_index =  context->nv_cmd.esys_handle;
+    size_t data_idx = context->nv_cmd.data_idx;
+    UINT16 offset = context->nv_cmd.offset;
+    IFAPI_OBJECT *auth_object = &context->nv_cmd.auth_object;
+    ESYS_TR session;
+
+    switch (context->nv_cmd.nv_read_state) {
+    statecase(context->nv_cmd.nv_read_state, NV_READ_INIT);
+        LOG_TRACE("NV_READ_INIT");
+        context->nv_cmd.rdata = NULL;
+        fallthrough;
+
+    statecase(context->nv_cmd.nv_read_state, NV_READ_AUTHORIZE);
+        LOG_TRACE("NV_READ_AUTHORIZE");
+        r = ifapi_authorize_object(context, auth_object, &session);
+        FAPI_SYNC(r, "Authorize NV object.", error_cleanup);
+
+        if (context->nv_cmd.numBytes > context->nv_buffer_max)
+            aux_size = context->nv_buffer_max;
+        else
+            aux_size = context->nv_cmd.numBytes;
+        r = Esys_NV_Read_Async(context->esys,
+                               context->nv_cmd.auth_index,
+                               nv_index,
+                               session,
+                               ESYS_TR_NONE,
+                               ESYS_TR_NONE,
+                               aux_size,
+                               offset);
+        goto_if_error_reset_state(r, " Fapi_NvRead_Async", error_cleanup);
+
+        context->nv_cmd.nv_read_state = NV_READ_AUTH_SENT;
+        context->nv_cmd.bytesRequested = aux_size;
+
+        return TSS2_FAPI_RC_TRY_AGAIN;
+
+    statecase(context->nv_cmd.nv_read_state, NV_READ_AUTH_SENT);
+        LOG_TRACE("NV_READ_NULL_AUTH_SENT");
+        if (context->nv_cmd.rdata == NULL) {
+            LOG_TRACE("Allocate %zu bytes", context->nv_cmd.numBytes);
+            context->nv_cmd.rdata = malloc(context->nv_cmd.numBytes);
+        }
+        *data = context->nv_cmd.rdata;
+        goto_if_null(*data, "Malloc failed", TSS2_FAPI_RC_MEMORY, error_cleanup);
+
+        r = Esys_NV_Read_Finish(context->esys, &aux_data);
+
+        if ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN)
+            return TSS2_FAPI_RC_TRY_AGAIN;
+
+        goto_if_error_reset_state(r, "FAPI NV_Read_Finish", error_cleanup);
+
+        if (aux_data->size < bytesRequested)
+            numBytes = 0;
+        else
+            numBytes -= aux_data->size;
+        memcpy(*data + data_idx, &aux_data->buffer[0], aux_data->size);
+        data_idx += aux_data->size;
+        free(aux_data);
+        if (numBytes > 0) {
+            if (numBytes > context->nv_buffer_max)
+                aux_size = context->nv_buffer_max;
+            else
+                aux_size = numBytes;
+            offset += bytesRequested;
+
+            r = Esys_NV_Read_Async(context->esys,
+                                   context->nv_cmd.auth_index,
+                                   nv_index,
+                                   context->session1,
+                                   ESYS_TR_NONE,
+                                   ESYS_TR_NONE,
+                                   aux_size,
+                                   offset);
+            goto_if_error_reset_state(r, "FAPI NV_Read", error_cleanup);
+            context->nv_cmd.bytesRequested = aux_size;
+            context->nv_cmd.data_idx = data_idx;
+            context->nv_cmd.numBytes = numBytes;
+            context->nv_cmd.nv_read_state =  NV_READ_AUTH_SENT;
+            return TSS2_FAPI_RC_TRY_AGAIN;
+        } else {
+            *size = data_idx;
+            context->nv_cmd.nv_read_state = NV_READ_INIT;
+            LOG_DEBUG("success");
+            r = TSS2_RC_SUCCESS;
+            break;
+        }
+    statecasedefault(context->nv_cmd.nv_read_state);
+    }
+
+error_cleanup:
+    return r;
+}
+
+#define min(X,Y) (X>Y)?Y:X
+
+/** State machine to retrieve random data from TPM.
+ *
+ * @param[in,out] context for storing all state information.
+ * @param[in] numBytes Number of random bytes to be computed.
+ * @param[out] data The random data.
+ * @retval TSS2_RC_SUCCESS If random data can be computed.
+ */
+TSS2_RC
+ifapi_get_random(FAPI_CONTEXT *context, size_t numBytes, uint8_t **data)
+{
+    TSS2_RC r;
+    TPM2B_DIGEST *aux_data = NULL;
+
+    switch (context->get_random_state) {
+    statecase(context->get_random_state, GET_RANDOM_INIT);
+        context->get_random.numBytes = numBytes;
+        context->get_random.data = calloc(context->get_random.numBytes, 1);
+        context->get_random.idx = 0;
+        return_if_null(context->get_random.data, "FAPI out of memory.",
+                       TSS2_FAPI_RC_MEMORY);
+
+        r = Esys_GetRandom_Async(context->esys,
+                                 context->session1,
+                                 ESYS_TR_NONE, ESYS_TR_NONE,
+                                 min(context->get_random.numBytes, sizeof(TPMU_HA)));
+        goto_if_error_reset_state(r, "FAPI GetRandom", error_cleanup);
+        fallthrough;
+
+    statecase(context->get_random_state, GET_RANDOM_SENT);
+        r = Esys_GetRandom_Finish(context->esys, &aux_data);
+        return_try_again(r);
+        goto_if_error_reset_state(r, "FAPI GetRandom_Finish", error_cleanup);
+
+        if (aux_data -> size > context->get_random.numBytes) {
+            goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "TPM returned too many bytes",
+                       error_cleanup);
+        }
+
+        memcpy(context->get_random.data + context->get_random.idx, &aux_data->buffer[0],
+               aux_data->size);
+        context->get_random.numBytes -= aux_data->size;
+        context->get_random.idx += aux_data->size;
+        Esys_Free(aux_data);
+
+        if (context->get_random.numBytes > 0) {
+            r = Esys_GetRandom_Async(context->esys, context->session1, ESYS_TR_NONE,
+                                     ESYS_TR_NONE, min(context->get_random.numBytes, sizeof(TPMU_HA)));
+            goto_if_error_reset_state(r, "FAPI GetRandom", error_cleanup);
+
+            return TSS2_FAPI_RC_TRY_AGAIN;
+        }
+        break;
+
+    statecasedefault(context->get_random_state);
+    }
+
+    *data = context->get_random.data;
+
+    LOG_DEBUG("success");
+    context->get_random_state = GET_RANDOM_INIT;
+    return TSS2_RC_SUCCESS;
+
+error_cleanup:
+    context->get_random_state = GET_RANDOM_INIT;
+    if (context->get_random.data != NULL)
+        SAFE_FREE(context->get_random.data);
+    return r;
+}
+
+/** Initialize the context for symmetric encryption decryption.
+ *
+ * @param[in,out] context The FAPI_CONTEXT.
+ * @param[in] in_data The data to encrypt or decrypt, depending on
+ *            the decrypt switch.
+ * @param[in] size The size of the input data.
+ * @param[in] decrypt if 0 encrypt input else decrypt input.
+ * @retval TSS2_RC_SUCCESS on success.
+ */
+TSS2_RC
+ifapi_sym_encrypt_decrypt_async(
+    FAPI_CONTEXT *context,
+    const uint8_t *in_data,
+    size_t  size,
+    TPMI_YES_NO decrypt)
+{
+//TODO: Get mode and scheme from crypto data
+    context->cmd.Data_EncryptDecrypt.sym_mode = context->profiles.default_profile.sym_mode;
+    context->cmd.Data_EncryptDecrypt.rsa_scheme =
+        context->profiles.default_profile.rsa_decrypt_scheme;
+
+    context->cmd.Data_EncryptDecrypt.in_data = in_data;
+    context->cmd.Data_EncryptDecrypt.decrypt = decrypt;
+    context->cmd.Data_EncryptDecrypt.numBytes = size;
+
+
+    context->sym_encrypt_decrypt_state = ENCRYPT_DECRYPT_INIT;
+    context->get_random_state = GET_RANDOM_INIT;
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** State machine for symmetric encryption& / decryption.
+ *
+ * @param[in,out] context for storing all state information.
+ * @param[out] data the cipher text or plain text depending on decrypt switch.
+ * @param[out] size the size of the output buffer.
+ * @retval TSS2_RC_SUCCESS If encryption or decryption was successful.
+ */
+TSS2_RC
+ifapi_sym_encrypt_decrypt_finish(
+    FAPI_CONTEXT *context,
+    uint8_t     **data,
+    size_t       *size,
+    TPMI_YES_NO decrypt)
+{
+    TSS2_RC r;
+    TPM2B_MAX_BUFFER *aux_data = (TPM2B_MAX_BUFFER *)&context->aux_data;
+    UINT16 bytesRequested = context->cmd.Data_EncryptDecrypt.bytesRequested;
+    size_t numBytes = context->cmd.Data_EncryptDecrypt.numBytes;
+    size_t data_idx = context->cmd.Data_EncryptDecrypt.data_idx;
+    IFAPI_OBJECT *object = context->cmd.Data_EncryptDecrypt.key_object;
+    TPMI_ALG_SYM_MODE mode = context->cmd.Data_EncryptDecrypt.sym_mode;
+    TPM2B_IV *iv = &context->cmd.Data_EncryptDecrypt.iv;
+    TPM2B_IV *tpm_iv;
+    uint8_t *iv_rand = NULL;
+    const uint8_t *in_data = context->cmd.Data_EncryptDecrypt.in_data;
+    TPM2B_MAX_BUFFER *tpm_out_data;
+
+    switch (context->sym_encrypt_decrypt_state) {
+    statecase(context->sym_encrypt_decrypt_state, ENCRYPT_DECRYPT_INIT);
+//TODO: Get mode and scheme from crypto data
+        size_t iv_size = context->profiles.default_profile.sym_block_size;
+        /* Received random number will  be encrypted! */
+        r = Esys_TRSess_SetAttributes(context->esys, context->session1,
+                                      TPMA_SESSION_ENCRYPT,
+                                      TPMA_SESSION_ENCRYPT);
+        goto_if_error_reset_state(r, "Set session attributes.", error_cleanup);
+
+        r = ifapi_get_random(context, iv_size,  &iv_rand);
+
+        if (r == TSS2_FAPI_RC_TRY_AGAIN)
+            return r;
+
+        goto_if_error_reset_state(r, " FAPI GetRandom", error_cleanup);
+
+        iv->size = iv_size;
+        memcpy(&context->cmd.Data_EncryptDecrypt.iv.buffer[0], iv_rand, iv_size);
+        SAFE_FREE(iv_rand);
+
+        if (context->cmd.Data_EncryptDecrypt.numBytes > context->nv_buffer_max)
+            aux_data->size = context->nv_buffer_max;
+        else
+            aux_data->size = context->cmd.Data_EncryptDecrypt.numBytes;
+        memcpy(&aux_data->buffer[0], &in_data[0], aux_data->size);
+        context->cmd.Data_EncryptDecrypt.data_idx = 0;
+
+        /* Authorization needed if NO_DA is not set */
+        if (!(context->loadKey.auth_object.misc.key.public.publicArea.objectAttributes &
+                TPMA_OBJECT_NODA)) {
+            r = ifapi_set_auth(context, object, "Fapi_DataEncrypt/Decrypt");
+            goto_if_error_reset_state(r, "Fapi_Encrypt/Decrypt", error_cleanup);
+        }
+
+        /* Transmitted plain text will not be encrypted! */
+        r = Esys_TRSess_SetAttributes(context->esys, context->session1,
+                                      TPMA_SESSION_CONTINUESESSION,
+                                      0xff);
+        goto_if_error_reset_state(r, "Set session attributes.", error_cleanup);
+
+        for (int i = 0; i < 16; i++)
+            iv->buffer[i] = i;
+        r = Esys_EncryptDecrypt_Async(context->esys,
+                                      object->handle,
+                                      context->session1,
+                                      ESYS_TR_NONE,
+                                      ESYS_TR_NONE,
+                                      decrypt,
+                                      mode,
+                                      iv,
+                                      aux_data);
+        goto_if_error_reset_state(r, " Fapi_Encrypt/Decrypt", error_cleanup);
+        context->sym_encrypt_decrypt_state = ENCRYPT_DECRYPT_NULL_AUTH_SENT;
+
+        return TSS2_FAPI_RC_TRY_AGAIN;
+
+        /* This state is used below in an if statement. */
+    case ENCRYPT_DECRYPT_NULL_AUTH_SENT:
+    case ENCRYPT_DECRYPT_AUTH_SENT:
+        LOG_TRACE("**STATE** ENCRYPT_DECRYPT_NULL_AUTH_SENT");
+
+        /* Allocation of the output buffer */
+        if (context->cmd.Data_EncryptDecrypt.out_data == NULL)
+            context->cmd.Data_EncryptDecrypt.out_data =
+                malloc(context->cmd.Data_EncryptDecrypt.numBytes);
+        *data = context->cmd.Data_EncryptDecrypt.out_data;
+        goto_if_null(*data, "Malloc failed", TSS2_FAPI_RC_MEMORY, error_cleanup);
+
+        r = Esys_EncryptDecrypt_Finish(context->esys, &tpm_out_data, &tpm_iv);
+
+        if ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN)
+            return TSS2_FAPI_RC_TRY_AGAIN;
+        if ((r & ~TPM2_RC_N_MASK) == TPM2_RC_BAD_AUTH) {
+            if (context->sym_encrypt_decrypt_state == ENCRYPT_DECRYPT_NULL_AUTH_SENT) {
+                r = ifapi_set_auth(context, object, "Fapi_Encrypt/Decrypt");
+                goto_if_error_reset_state(r, " Fapi_NvRead", error_cleanup);
+
+                r = Esys_EncryptDecrypt_Async(context->esys,
+                                              object->handle,
+                                              context->session1,
+                                              ESYS_TR_NONE,
+                                              ESYS_TR_NONE,
+                                              decrypt,
+                                              mode,
+                                              iv,
+                                              aux_data);
+                goto_if_error_reset_state(r, "Fapi_Data/Encrypt/Decrypt", error_cleanup);
+
+                context->sym_encrypt_decrypt_state = ENCRYPT_DECRYPT_AUTH_SENT ;
+                return TSS2_FAPI_RC_TRY_AGAIN;
+            }
+        }
+        goto_if_error_reset_state(r, "FAPI Data_EncryptDecrypt", error_cleanup);
+
+        iv->size = tpm_iv->size;
+        memcpy(&iv->buffer[0], &tpm_iv->buffer[0], tpm_iv->size);
+        free(tpm_iv);
+
+        if (tpm_out_data->size < bytesRequested) {
+            goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Wrong encryption/decryption size",
+                       error_cleanup);
+
+        } else {
+            numBytes -= tpm_out_data->size;
+        }
+        memcpy(*data + data_idx, &tpm_out_data->buffer[0], tpm_out_data->size);
+        data_idx += aux_data->size;
+        free(tpm_out_data);
+        if (numBytes > 0) {
+            if (numBytes > context->nv_buffer_max)
+                aux_data->size = context->nv_buffer_max;
+            else
+                aux_data->size = numBytes;
+            memcpy(&aux_data->buffer[0], &in_data[data_idx], aux_data->size);
+            r = Esys_EncryptDecrypt_Async(context->esys,
+                                          object->handle,
+                                          context->session1,
+                                          ESYS_TR_NONE,
+                                          ESYS_TR_NONE,
+                                          decrypt,
+                                          mode,
+                                          iv,
+                                          aux_data);
+            goto_if_error_reset_state(r, "FAPI NV_Read", error_cleanup);
+            context->cmd.Data_EncryptDecrypt.bytesRequested = aux_data->size;
+            context->cmd.Data_EncryptDecrypt.data_idx = data_idx;
+            context->cmd.Data_EncryptDecrypt.numBytes = numBytes;
+            context->sym_encrypt_decrypt_state =  ENCRYPT_DECRYPT_AUTH_SENT;
+            return TSS2_FAPI_RC_TRY_AGAIN;
+
+        } else {
+            *size = data_idx;
+            IFAPI_ENCRYPTED_DATA *enc_data = &context->cmd.Data_EncryptDecrypt.enc_data;
+            enc_data->type = IFAPI_SYM_BULK_ENCRYPTION;
+            enc_data->cipher.size = context->cmd.Data_EncryptDecrypt.in_dataSize;
+            enc_data->cipher.buffer = context->cmd.Data_EncryptDecrypt.out_data;
+            r = ifapi_get_name(&context->loadKey.auth_object.misc.key.public.publicArea,
+                               &enc_data->key_name);
+            goto_if_error(r, "Compute key name.", error_cleanup);
+
+            LOG_DEBUG("success");
+            r = TSS2_RC_SUCCESS;
+            break;
+        }
+    statecasedefault(context->sym_encrypt_decrypt_state);
+    }
+    return r;
+
+error_cleanup:
+    return r;
+}
+
+/** Load a key and initialize profile and session for ESAPI commands
+ */
+TSS2_RC
+ifapi_load_key(
+    FAPI_CONTEXT  *context,
+    char    const *keyPath,
+    IFAPI_OBJECT **key_object)
+{
+    TSS2_RC r;
+    const IFAPI_PROFILE *profile;
+
+    return_if_null(keyPath, "Bad reference for key path.",
+                   TSS2_FAPI_RC_BAD_REFERENCE);
+
+    switch (context->Key_Sign.state) {
+    statecase(context->Key_Sign.state, SIGN_INIT);
+        context->Key_Sign.keyPath = keyPath;
+
+        r = ifapi_get_sessions_async(context,
+                                     IFAPI_SESSION_GENEK | IFAPI_SESSION1,
+                                     TPMA_SESSION_DECRYPT, 0);
+        goto_if_error_reset_state(r, "Create sessions", error_cleanup);
+        fallthrough;
+
+    statecase(context->Key_Sign.state, SIGN_WAIT_FOR_SESSION);
+        r = ifapi_profiles_get(&context->profiles, context->Key_Sign.keyPath, &profile);
+        goto_if_error_reset_state(r, "Reading profile data", error_cleanup);
+
+        r = ifapi_get_sessions_finish(context, profile);
+        return_try_again(r);
+        goto_if_error_reset_state(r, " FAPI create session", error_cleanup);
+
+        r = ifapi_load_keys_async(context, context->Key_Sign.keyPath);
+        goto_if_error(r, "Load keys.", error_cleanup);
+        fallthrough;
+
+    statecase(context->Key_Sign.state, SIGN_WAIT_FOR_KEY);
+        r = ifapi_load_keys_finish(context, IFAPI_FLUSH_PARENT,
+                                   &context->Key_Sign.handle,
+                                   key_object);
+        return_try_again(r);
+        goto_if_error_reset_state(r, " Load key.", error_cleanup);
+
+        context->Key_Sign.state = SIGN_INIT;
+        break;
+
+    statecasedefault(context->Key_Sign.state);
+        context->state = _FAPI_STATE_INTERNALERROR;
+        return_error(TSS2_FAPI_RC_BAD_VALUE, "Invalid state for FAPI load key");
+    }
+
+error_cleanup:
+    return r;
+}
+
+TSS2_RC
+ifapi_key_sign(
+    FAPI_CONTEXT     *context,
+    IFAPI_OBJECT     *sig_key_object,
+    char const       *padding,
+    TPM2B_DIGEST     *digest,
+    TPMT_SIGNATURE  **tpm_signature,
+    char            **publicKey,
+    char            **certificate)
+{
+    TSS2_RC r;
+    TPMT_SIG_SCHEME *sig_scheme;
+    ESYS_TR session;
+
+    TPMT_TK_HASHCHECK hash_validation = {
+        .tag = TPM2_ST_HASHCHECK,
+        .hierarchy = TPM2_RH_OWNER,
+    };
+    memset(&hash_validation.digest, 0, sizeof(TPM2B_DIGEST));
+
+    switch (context->Key_Sign.state) {
+    statecase(context->Key_Sign.state, SIGN_INIT);
+        sig_key_object = context->Key_Sign.key_object;
+
+        r = ifapi_authorize_object(context, sig_key_object, &session);
+        FAPI_SYNC(r, "Authorize signature key.", cleanup);
+
+        context->policy.session = session;
+
+        r = ifapi_get_sig_scheme(context, sig_key_object, padding, digest, &sig_scheme);
+        goto_if_error(r, "Get signature scheme", cleanup);
+
+        r = Esys_Sign_Async(context->esys,
+                            context->Key_Sign.handle,
+                            session,
+                            ESYS_TR_NONE, ESYS_TR_NONE,
+                            digest,
+                            sig_scheme,
+                            &hash_validation);
+        goto_if_error(r, "Error: Sign", cleanup);
+        fallthrough;
+
+    statecase(context->Key_Sign.state, SIGN_AUTH_SENT);
+        context->Key_Sign.signature = NULL;
+        r = Esys_Sign_Finish(context->esys,
+                             &context->Key_Sign.signature);
+        return_try_again(r);
+        ifapi_flush_policy_session(context, context->policy.session, r);
+        goto_if_error(r, "Error: Sign", cleanup);
+
+        r = Esys_FlushContext_Async(context->esys, context->Key_Sign.handle);
+        goto_if_error(r, "Error: FlushContext", cleanup);
+        fallthrough;
+
+    statecase(context->Key_Sign.state, SIGN_WAIT_FOR_FLUSH);
+        r = Esys_FlushContext_Finish(context->esys);
+        return_try_again(r);
+        goto_if_error(r, "Error: Sign", cleanup);
+
+        int pem_size;
+        if (publicKey) {
+            r = ifapi_pub_pem_key_from_tpm(&sig_key_object->misc.key.public,
+                                                publicKey,
+                                                &pem_size);
+            goto_if_error(r, "Conversion pub key to PEM failed", cleanup);
+        }
+        context->Key_Sign.handle = ESYS_TR_NONE;
+        *tpm_signature = context->Key_Sign.signature;
+        if (certificate) {
+            *certificate = strdup(context->Key_Sign.key_object->misc.key.certificate);
+            goto_if_null(*certificate, "Out of memory.",
+                    TSS2_FAPI_RC_MEMORY, cleanup);
+        }
+        context->Key_Sign.state = SIGN_INIT;
+        LOG_TRACE("success");
+        r = TSS2_RC_SUCCESS;
+        break;
+
+    statecasedefault(context->Key_Sign.state);
+    }
+
+cleanup:
+    if (context->Key_Sign.handle != ESYS_TR_NONE)
+        Esys_FlushContext(context->esys, context->Key_Sign.handle);
+    ifapi_cleanup_ifapi_object(context->Key_Sign.key_object);
+    return r;
+}
+
+/** Get json encoding for FAPI object
+ */
+TSS2_RC
+ifapi_get_json(FAPI_CONTEXT *context, IFAPI_OBJECT *object, char **json_string)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    json_object *jso = NULL;
+
+    /* Perform esys serialization if necessary */
+    r = ifapi_esys_serialize_object(context->esys, object);
+    goto_if_error(r, "Prepare serialization", cleanup);
+
+    r = ifapi_json_IFAPI_OBJECT_serialize(object, &jso);
+    return_if_error(r, "Serialize duplication object");
+
+    *json_string = strdup(json_object_to_json_string_ext(jso,
+                          JSON_C_TO_STRING_PRETTY));
+    goto_if_null2(*json_string, "Converting json to string", r, TSS2_FAPI_RC_MEMORY,
+                  cleanup);
+
+cleanup:
+    if (jso)
+        json_object_put(jso);
+    return r;
+}
+
+/** Serialize persistent objects into buffer of keystore object.
+ *
+ * NV objects and persistent keys will serialized via the ESYS API to
+ * enable reconstruction durinng loading from keystore.
+ *
+ * @param[object] object  The nv object or the key.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval ESYS error code if the serialization fails.
+ */
+TSS2_RC
+ifapi_esys_serialize_object(ESYS_CONTEXT *ectx, IFAPI_OBJECT *object)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    IFAPI_KEY *key_object = NULL;
+    IFAPI_NV *nv_object;
+
+    switch (object->objectType) {
+    case IFAPI_NV_OBJ:
+        nv_object = &object->misc.nv;
+        if (nv_object->serialization.buffer != NULL) {
+            Fapi_Free(nv_object->serialization.buffer);
+            nv_object->serialization.buffer = NULL;
+        }
+        r = Esys_TR_Serialize(ectx, object->handle,
+                              &nv_object->serialization.buffer,
+                              &nv_object->serialization.size);
+        return_if_error(r, "Error serialize esys object");
+        break;
+
+    case IFAPI_KEY_OBJ:
+        key_object = &object->misc.key;
+        key_object->serialization.size = 0;
+        if (key_object->serialization.buffer != NULL) {
+            Fapi_Free(key_object->serialization.buffer);
+            key_object->serialization.buffer = NULL;
+        }
+        if (object->handle != ESYS_TR_NONE && key_object->persistent_handle) {
+            key_object->serialization.buffer = NULL;
+            r = Esys_TR_Serialize(ectx, object->handle,
+                                  &key_object->serialization.buffer,
+                                  &key_object->serialization.size);
+            return_if_error(r, "Error serialize esys object");
+        }
+        break;
+
+    default:
+        /* Nothing to be done */
+        break;
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+ /** Initialize the part of an IFAPI_OBJECT  which is not serialized.
+ *
+ * For persistent objects the correspodning ESYS object will be created.
+ *
+ * @param[inout] ectx The ESYS context.
+ * @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_initialize_object(
+    ESYS_CONTEXT *ectx,
+    IFAPI_OBJECT *object)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    ESYS_TR handle;
+
+    switch (object->objectType) {
+    case IFAPI_NV_OBJ:
+        if (object->misc.nv.serialization.size > 0) {
+            r = Esys_TR_Deserialize(ectx, &object->misc.nv.serialization.buffer[0],
+                                    object->misc.nv.serialization.size, &handle);
+            goto_if_error(r, "Error dserialize esys object", cleanup);
+        } else {
+            handle = ESYS_TR_NONE;
+        }
+        object->authorization_state = AUTH_INIT;
+        object->handle = handle;
+        break;
+
+    case IFAPI_KEY_OBJ:
+        if (object->misc.key.serialization.size > 0) {
+            r = Esys_TR_Deserialize(ectx, &object->misc.key.serialization.buffer[0],
+                                    object->misc.key.serialization.size, &handle);
+            goto_if_error(r, "Error deserialize esys object", cleanup);
+        } else {
+            handle = ESYS_TR_NONE;
+        }
+        object->authorization_state = AUTH_INIT;
+        object->handle = handle;
+        break;
+
+    default:
+        /* Nothing to be done */
+        break;
+    }
+
+    return r;
+
+cleanup:
+    SAFE_FREE(object->policy_harness);
+    return r;
+}
+
+/** Load a key and initialize profile and session for ESAPI commands
+ */
+TSS2_RC
+ifapi_key_create_prepare_auth(
+    FAPI_CONTEXT  *context,
+    char   const *keyPath,
+    char   const *policyPath,
+    char   const *authValue)
+{
+    TSS2_RC r;
+
+    memset(&context->cmd.Key_Create.inSensitive, 0, sizeof(TPM2B_SENSITIVE_CREATE));
+    if (authValue) {
+        if (strlen(authValue) > sizeof(TPMU_HA)) {
+            return_error(TSS2_FAPI_RC_BAD_VALUE, "Password too long.");
+        }
+        memcpy(&context->cmd.Key_Create.inSensitive.sensitive.userAuth.buffer,
+               authValue, strlen(authValue));
+        context->cmd.Key_Create.inSensitive.sensitive.userAuth.size = strlen(authValue);
+    }
+    context->cmd.Key_Create.inSensitive.sensitive.data.size = 0;
+    r = ifapi_key_create_prepare(context, keyPath, policyPath);
+    return r;
+}
+
+TSS2_RC
+ifapi_key_create_prepare_sensitive(
+    FAPI_CONTEXT  *context,
+    char    const *keyPath,
+    char    const *policyPath,
+    size_t         dataSize,
+    char    const *authValue,
+    uint8_t const *data)
+{
+    TSS2_RC r;
+
+    memset(&context->cmd.Key_Create.inSensitive, 0, sizeof(TPM2B_SENSITIVE_CREATE));
+    if (dataSize > sizeof(TPMU_HA) || dataSize == 0) {
+        return_error(TSS2_FAPI_RC_BAD_VALUE, "Data to big or equal zero.");
+    }
+    if (data)
+        memcpy(&context->cmd.Key_Create.inSensitive.sensitive.data.buffer,
+               data, dataSize);
+    context->cmd.Key_Create.inSensitive.sensitive.data.size = dataSize;
+    if (authValue) {
+        if (strlen(authValue) > sizeof(TPMU_HA)) {
+            return_error(TSS2_FAPI_RC_BAD_VALUE, "Password too long.");
+        }
+        memcpy(&context->cmd.Key_Create.inSensitive.sensitive.userAuth.buffer,
+               authValue, strlen(authValue));
+        context->cmd.Key_Create.inSensitive.sensitive.userAuth.size = strlen(authValue);
+    }
+    r = ifapi_key_create_prepare(context, keyPath, policyPath);
+    return r;
+}
+
+/** Load a key and initialize profile and session for ESAPI commands
+ */
+TSS2_RC
+ifapi_key_create_prepare(
+    FAPI_CONTEXT  *context,
+    char   const *keyPath,
+    char   const *policyPath)
+{
+    TSS2_RC r;
+    IFAPI_OBJECT *object = &context->cmd.Key_Create.object;
+    NODE_STR_T *path_list = NULL;
+
+    LOG_TRACE("call");
+    r = ifapi_session_init(context);
+    return_if_error(r, "Initialize Key_Create");
+
+    /* First check whether an existing object would be overwritten */
+    r = ifapi_keystore_check_overwrite(&context->keystore, &context->io,
+                                       keyPath);
+    return_if_error2(r, "Check overwrite %s", keyPath);
+
+    context->srk_handle = 0;
+
+    /* Clear the memory used for the the new key object */
+    memset(&context->cmd.Key_Create.outsideInfo, 0, sizeof(TPM2B_DATA));
+    memset(&context->cmd.Key_Create.creationPCR, 0, sizeof(TPML_PCR_SELECTION));
+    memset(object, 0, sizeof(IFAPI_OBJECT));
+
+    strdup_check(context->cmd.Key_Create.policyPath, policyPath, r, error);
+    strdup_check(context->cmd.Key_Create.keyPath, keyPath, r, error);
+    r = get_explicit_key_path(&context->keystore, keyPath, &path_list);
+    return_if_error(r, "Compute explicit path.");
+
+    context->loadKey.path_list = path_list;
+    char *file;
+    r = ifapi_path_string(&file, NULL, path_list, NULL);
+    goto_if_error(r, "Compute explicit path.", error);
+
+    LOG_DEBUG("Explicit key path: %s", file);
+
+    free(file);
+
+    context->cmd.Key_Create.state = KEY_CREATE_INIT;
+
+    return TSS2_RC_SUCCESS;
+
+error:
+    free_string_list(path_list);
+    return r;
+}
+
+TSS2_RC
+ifapi_key_create(
+    FAPI_CONTEXT *context,
+    IFAPI_KEY_TEMPLATE *template)
+{
+    TSS2_RC r;
+    size_t path_length;
+    NODE_STR_T *path_list = context->loadKey.path_list;
+    TPM2B_PUBLIC *outPublic = NULL;
+    TPM2B_PRIVATE *outPrivate = NULL;
+    TPM2B_CREATION_DATA *creationData = NULL;
+    TPM2B_DIGEST *creationHash = NULL;
+    TPMT_TK_CREATION *creationTicket = NULL;
+    IFAPI_OBJECT *object = &context->cmd.Key_Create.object;
+    ESYS_TR auth_session;
+
+    LOG_TRACE("call");
+
+    switch (context->cmd.Key_Create.state) {
+    statecase(context->cmd.Key_Create.state, KEY_CREATE_INIT);
+        context->cmd.Key_Create.public_templ = *template;
+
+        /* Profile name is first element of the explicit path list */
+        char *profile_name = context->loadKey.path_list->str;
+        r = ifapi_profiles_get(&context->profiles, profile_name, &context->cmd.Key_Create.profile);
+        goto_if_error_reset_state(r, "Retrieving profile data", error_cleanup);
+
+        if (context->cmd.Key_Create.inSensitive.sensitive.data.size > 0) {
+            /* A keyed hash object sealing sensitive data will be created */
+            context->cmd.Key_Create.public_templ.public.publicArea.type = TPM2_ALG_KEYEDHASH;
+            context->cmd.Key_Create.public_templ.public.publicArea.nameAlg =
+                    context->cmd.Key_Create.profile->nameAlg;
+            context->cmd.Key_Create.public_templ.public.publicArea.parameters.keyedHashDetail.scheme.scheme =
+            TPM2_ALG_NULL;
+        } else {
+            r = ifapi_merge_profile_into_template(context->cmd.Key_Create.profile,
+                                                  &context->cmd.Key_Create.public_templ);
+            goto_if_error_reset_state(r, "Merge profile", error_cleanup);
+        }
+
+        if (context->cmd.Key_Create.policyPath
+                && strcmp(context->cmd.Key_Create.policyPath, "") != 0)
+            context->cmd.Key_Create.state = KEY_CREATE_CALCULATE_POLICY;
+        /* else jump over to KEY_CREATE_WAIT_FOR_SESSION below */
+    /* FALLTHRU */
+
+    case KEY_CREATE_CALCULATE_POLICY:
+        if (context->cmd.Key_Create.state == KEY_CREATE_CALCULATE_POLICY) {
+            r = ifapi_calculate_tree(context, context->cmd.Key_Create.policyPath,
+                                     &context->policy.harness,
+                                     context->cmd.Key_Create.public_templ.public.publicArea.nameAlg,
+                                     &context->policy.digest_idx,
+                                     &context->policy.hash_size);
+            return_try_again(r);
+            goto_if_error2(r, "Calculate policy tree %s", error_cleanup,
+                           context->cmd.Key_Create.policyPath);
+
+            /* Store the calculated policy in the key object */
+            object->policy_harness = calloc(1, sizeof(TPMS_POLICY_HARNESS));
+            return_if_null(object->policy_harness, "Out of memory",
+                    TSS2_FAPI_RC_MEMORY);
+            *(object->policy_harness) = context->policy.harness;
+
+            context->cmd.Key_Create.public_templ.public.publicArea.authPolicy.size =
+                context->policy.hash_size;
+            memcpy(&context->cmd.Key_Create.public_templ.public.publicArea.authPolicy.buffer[0],
+                   &context->policy.harness.policyDigests.digests[context->policy.digest_idx].digest,
+                   context->policy.hash_size);
+        }
+        r = ifapi_get_sessions_async(context,
+                                     IFAPI_SESSION_GENEK | IFAPI_SESSION1,
+                                     TPMA_SESSION_DECRYPT, 0);
+        goto_if_error_reset_state(r, "Create sessions", error_cleanup);
+        fallthrough;
+
+    statecase(context->cmd.Key_Create.state, KEY_CREATE_WAIT_FOR_SESSION);
+        LOG_TRACE("KEY_CREATE_WAIT_FOR_SESSION");
+        r = ifapi_get_sessions_finish(context, context->cmd.Key_Create.profile);
+        return_try_again(r);
+        goto_if_error_reset_state(r, " FAPI create session", error_cleanup);
+
+        path_length = ifapi_path_length(path_list);
+        r = ifapi_load_key_async(context, path_length - 1);
+        goto_if_error(r, "LoadKey async", error_cleanup);
+        fallthrough;
+
+    statecase(context->cmd.Key_Create.state, KEY_CREATE_WAIT_FOR_PARENT);
+        LOG_TRACE("KEY_CREATE_WAIT_FOR_PARENT");
+        r = ifapi_load_key_finish(context, IFAPI_FLUSH_PARENT);
+        return_try_again(r);
+        goto_if_error(r, "LoadKey finish", error_cleanup);
+        fallthrough;
+
+    statecase(context->cmd.Key_Create.state, KEY_CREATE_WAIT_FOR_AUTHORIZATION);
+        r = ifapi_authorize_object(context, &context->loadKey.auth_object, &auth_session);
+        FAPI_SYNC(r, "Authorize key.", error_cleanup);
+
+        r = Esys_Create_Async(context->esys, context->loadKey.auth_object.handle,
+                              auth_session,
+                              ESYS_TR_NONE, ESYS_TR_NONE,
+                              &context->cmd.Key_Create.inSensitive,
+                              &context->cmd.Key_Create.public_templ.public,
+                              &context->cmd.Key_Create.outsideInfo,
+                              &context->cmd.Key_Create.creationPCR);
+        goto_if_error(r, "Create_Async", error_cleanup);
+        fallthrough;
+
+    statecase(context->cmd.Key_Create.state, KEY_CREATE_AUTH_SENT);
+        r = Esys_Create_Finish(context->esys, &outPrivate, &outPublic, &creationData,
+                               &creationHash, &creationTicket);
+        try_again_or_error_goto(r, "Key create finish", error_cleanup);
+
+        /* Prepare object for serialization */
+        object->system = context->cmd.Key_Create.public_templ.system;
+        object->objectType = IFAPI_KEY_OBJ;
+        object->misc.key.public = *outPublic;
+        object->misc.key.private.size = outPrivate->size;
+        object->misc.key.private.buffer = calloc(1, outPrivate->size);
+        goto_if_null2( object->misc.key.private.buffer, "Out of memory.", r,
+                       TSS2_FAPI_RC_MEMORY, error_cleanup);
+
+        object->misc.key.private.buffer = memcpy(&object->misc.key.private.buffer[0],
+                                                 &outPrivate->buffer[0], outPrivate->size);
+        object->misc.key.policyInstance = NULL;
+        object->misc.key.creationData = *creationData;
+        object->misc.key.creationTicket = *creationTicket;
+        object->misc.key.description = NULL;
+        object->misc.key.certificate = NULL;
+        SAFE_FREE(outPrivate);
+        SAFE_FREE(creationData);
+        SAFE_FREE(creationTicket);
+        SAFE_FREE(creationHash);
+        if (context->cmd.Key_Create.inSensitive.sensitive.userAuth.size > 0)
+            object->misc.key.with_auth = TPM2_YES;
+        else
+            object->misc.key.with_auth = TPM2_NO;;
+        r = ifapi_get_name(&outPublic->publicArea, &object->misc.key.name);
+        goto_if_error(r, "Get key name", error_cleanup);
+
+        if (object->misc.key.public.publicArea.type == TPM2_ALG_RSA)
+            object->misc.key.signing_scheme = context->cmd.Key_Create.profile->rsa_signing_scheme;
+        else
+            object->misc.key.signing_scheme = context->cmd.Key_Create.profile->ecc_signing_scheme;
+        SAFE_FREE(outPublic);
+        fallthrough;
+
+    statecase(context->cmd.Key_Create.state, KEY_CREATE_WRITE_PREPARE);
+        /* Perform esys serialization if necessary */
+        r = ifapi_esys_serialize_object(context->esys, object);
+        goto_if_error(r, "Prepare serialization", error_cleanup);
+
+        /* Start writing the NV object to the key store */
+        r = ifapi_keystore_store_async(&context->keystore, &context->io,
+                                       context->cmd.Key_Create.keyPath, object);
+        goto_if_error_reset_state(r, "Could not open: %sh", error_cleanup,
+                                  context->cmd.Key_Create.keyPath);
+        ifapi_cleanup_ifapi_object(object);
+        fallthrough;
+
+    statecase(context->cmd.Key_Create.state, KEY_CREATE_WRITE);
+        /* Finish writing the key to the key store */
+        r = ifapi_keystore_store_finish(&context->keystore, &context->io);
+        return_try_again(r);
+        return_if_error_reset_state(r, "write_finish failed");
+
+        if (context->loadKey.auth_object.misc.key.persistent_handle) {
+            context->cmd.Key_Create.state = KEY_CREATE_INIT;
+            r = TSS2_RC_SUCCESS;
+            break;
+        }
+        r = Esys_FlushContext_Async(context->esys, context->loadKey.auth_object.handle);
+        goto_if_error(r, "Flush parent", error_cleanup);
+        fallthrough;
+
+    statecase(context->cmd.Key_Create.state, KEY_CREATE_FLUSH);
+        r = Esys_FlushContext_Finish(context->esys);
+        try_again_or_error_goto(r, "Flush context", error_cleanup);
+        fallthrough;
+
+    statecase(context->cmd.Key_Create.state, KEY_CREATE_CLEANUP);
+        r = ifapi_cleanup_session(context);
+        try_again_or_error_goto(r, "Cleanup", error_cleanup);
+
+        context->cmd.Key_Create.state = KEY_CREATE_INIT;
+        r = TSS2_RC_SUCCESS;
+        break;
+
+    statecasedefault(context->cmd.Key_Create.state);
+    }
+error_cleanup:
+    free_string_list(context->loadKey.path_list);
+    SAFE_FREE(outPublic);
+    SAFE_FREE(outPrivate);
+    SAFE_FREE(creationData);
+    SAFE_FREE(creationHash);
+    SAFE_FREE(creationTicket);
+    SAFE_FREE(context->cmd.Key_Create.policyPath);
+    SAFE_FREE(context->cmd.Key_Create.keyPath);
+    ifapi_cleanup_ifapi_object(object);
+    ifapi_session_clean(context);
+    return r;
+}
+
+/** Get signature scheme for object of if padding compute scheme from padding.
+ */
+TSS2_RC
+ifapi_get_sig_scheme(
+    FAPI_CONTEXT *context,
+    IFAPI_OBJECT *object,
+    char const *padding,
+    TPM2B_DIGEST *digest,
+    TPMT_SIG_SCHEME **sig_scheme)
+{
+    TPMI_ALG_HASH hash_alg;
+    TSS2_RC r;
+
+    if (padding) {
+        /* Get hash algorithm from digest size */
+        r = ifapi_get_hash_alg_for_size(digest->size, &hash_alg);
+        return_if_error2(r, "Invalid digest size.");
+
+        /* Use scheme object from context */
+        if (strcasecmp("RSA_SSA", padding) == 0) {
+            context->Key_Sign.scheme.scheme = TPM2_ALG_RSASSA;
+            context->Key_Sign.scheme.details.rsassa.hashAlg = hash_alg;
+        }
+        if (strcasecmp("RSA_PSS", padding) == 0) {
+            context->Key_Sign.scheme.scheme = TPM2_ALG_RSAPSS;
+            context->Key_Sign.scheme.details.rsapss.hashAlg = hash_alg;
+        }
+        *sig_scheme =  &context->Key_Sign.scheme;
+        return TSS2_RC_SUCCESS;
+    } else {
+        /* Use scheme defined for object */
+        *sig_scheme =  &object->misc.key.signing_scheme;
+        return TSS2_RC_SUCCESS;
+    }
+}
+
+/** State machine for changing the hierarchy authorization
+ */
+TSS2_RC
+ifapi_change_auth_hierarchy(
+    FAPI_CONTEXT *context,
+    ESYS_TR handle,
+    IFAPI_OBJECT *hierarchy_object,
+    TPM2B_AUTH *newAuthValue)
+{
+    TSS2_RC r;
+
+    switch (context->hierarchy_state) {
+    statecase(context->hierarchy_state, HIERARCHY_CHANGE_AUTH_INIT);
+        if (newAuthValue->size>0)
+            hierarchy_object->misc.hierarchy.with_auth = TPM2_YES;
+        else
+            hierarchy_object->misc.hierarchy.with_auth = TPM2_NO;
+        r = Esys_HierarchyChangeAuth_Async(context->esys,
+                                           handle,
+                                           (context->session1
+                                            && context->session1 != ESYS_TR_NONE) ?
+                                           context->session1 : ESYS_TR_PASSWORD,
+                                           ESYS_TR_NONE, ESYS_TR_NONE,
+                                           newAuthValue);
+        return_if_error(r, "HierarchyChangeAuth");
+        fallthrough;
+
+    statecase(context->hierarchy_state, HIERARCHY_CHANGE_AUTH_NULL_AUTH_SENT);
+        r = Esys_HierarchyChangeAuth_Finish(context->esys);
+        return_try_again(r);
+
+        if ((r & ~TPM2_RC_N_MASK) != TPM2_RC_BAD_AUTH) {
+            return_if_error(r, "Hierarchy change auth.");
+            context->hierarchy_state = HIERARCHY_CHANGE_AUTH_INIT;
+            LOG_TRACE("success");
+            return TSS2_RC_SUCCESS;
+        }
+
+        /* Retry after NULL authorization was not successful */
+        r = ifapi_set_auth(context, hierarchy_object, "Hierarchy object");
+        return_if_error(r, "HierarchyChangeAuth");
+
+        r = Esys_HierarchyChangeAuth_Async(context->esys,
+                                           handle,
+                                           (context->session1
+                                            && context->session1 != ESYS_TR_NONE) ?
+                                           context->session1 : ESYS_TR_PASSWORD,
+                                           ESYS_TR_NONE, ESYS_TR_NONE,
+                                           newAuthValue);
+        return_if_error(r, "HierarchyChangeAuth");
+        fallthrough;
+
+    statecase(context->hierarchy_state, HIERARCHY_CHANGE_AUTH_AUTH_SENT);
+        r = Esys_HierarchyChangeAuth_Finish(context->esys);
+        FAPI_SYNC(r, "Hierarchy change auth.", error);
+
+        context->hierarchy_state = HIERARCHY_CHANGE_AUTH_INIT;
+        return r;
+
+    statecasedefault(context->hierarchy_state);
+    }
+
+error:
+    return r;
+}
+
+TSS2_RC
+ifapi_change_policy_hierarchy(
+    FAPI_CONTEXT *context,
+    ESYS_TR handle,
+    IFAPI_OBJECT *hierarchy_object,
+    TPMS_POLICY_HARNESS *policy_harness)
+{
+    TSS2_RC r;
+
+    switch (context->hierarchy_policy_state) {
+    statecase(context->hierarchy_policy_state, HIERARCHY_CHANGE_POLICY_INIT);
+        if (! policy_harness || ! policy_harness->policy) {
+            /* No policy will be used for hierarchy */
+            return TSS2_RC_SUCCESS;
+        }
+
+        context->policy.state = POLICY_CALCULATE;
+
+        r = ifapi_calculate_tree(context, NULL, /**< no path needed */
+                                 policy_harness,
+                                 context->profiles.default_profile.nameAlg,
+                                 &context->cmd.Provision.digest_idx,
+                                 &context->cmd.Provision.hash_size);
+        goto_if_error(r, "Policy calculation", error);
+
+
+        context->cmd.Provision.policy_digest.size = context->cmd.Provision.hash_size;
+        memcpy(&context->cmd.Provision.policy_digest.buffer[0],
+               &policy_harness
+               ->policyDigests.digests[context->cmd.Provision.digest_idx].digest,
+               context->cmd.Provision.hash_size);
+
+        hierarchy_object->policy_harness = policy_harness;
+        hierarchy_object->misc.hierarchy.authPolicy = context->cmd.Provision.policy_digest;
+
+        r = Esys_SetPrimaryPolicy_Async(context->esys, handle,
+                                        ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
+                                        &context->cmd.Provision.policy_digest,
+                                        context->profiles.default_profile.nameAlg);
+        return_if_error(r, "Esys_SetPrimaryPolicy_Async");
+        fallthrough;
+
+    statecase(context->hierarchy_policy_state, HIERARCHY_CHANGE_POLICY_NULL_AUTH_SENT);
+        r = Esys_SetPrimaryPolicy_Finish(context->esys);
+        return_try_again(r);
+        if ((r & ~TPM2_RC_N_MASK) != TPM2_RC_BAD_AUTH) {
+            return_if_error(r, "SetPrimaryPolicy_Finish");
+            context->hierarchy_policy_state = HIERARCHY_CHANGE_POLICY_INIT;
+            return TSS2_RC_SUCCESS;
+        }
+
+        /* Retry after NULL authorization was not successful */
+        ifapi_init_hierarchy_object(hierarchy_object, handle);
+        r = ifapi_set_auth(context, hierarchy_object, "Hierarchy object");
+        return_if_error(r, "HierarchyChangePolicy");
+
+        r = Esys_SetPrimaryPolicy_Async(context->esys, handle,
+                                        context->session1, ESYS_TR_NONE, ESYS_TR_NONE,
+                                        &context->cmd.Provision.policy_digest,
+                                        context->profiles.default_profile.nameAlg);
+        return_if_error(r, "Esys_SetPrimaryPolicy_Async");
+
+        context->hierarchy_policy_state = HIERARCHY_CHANGE_POLICY_AUTH_SENT;
+        return TSS2_FAPI_RC_TRY_AGAIN;
+
+    statecasedefault(context->hierarchy_policy_state);
+    }
+
+error:
+    return r;
+}
+
+/** Allocated ifapi objects will be recorede in the context.
+ */
+IFAPI_OBJECT
+*ifapi_allocate_object(FAPI_CONTEXT *context)
+{
+    NODE_OBJECT_T *node = calloc(1, sizeof(NODE_OBJECT_T));
+    if (!node)
+        return NULL;
+
+    node->object = calloc(1, sizeof(IFAPI_OBJECT));
+    if (!node->object) {
+        free(node);
+        return NULL;
+    }
+    node->next = context->object_list;
+    context->object_list = node;
+    return (IFAPI_OBJECT *) node->object;
+}
+
+/** Free an object stored in the context.
+ */
+void
+ifapi_free_objects(FAPI_CONTEXT *context)
+{
+    NODE_OBJECT_T *free_node;
+    NODE_OBJECT_T *node = context->object_list;
+    while (node) {
+        free(node->object);
+        free_node = node;
+        node = node->next;
+        free(free_node);
+    }
+}
+
+/** Free all objects stored in the context.
+ */
+void
+ifapi_free_object(FAPI_CONTEXT *context, IFAPI_OBJECT **object)
+{
+    NODE_OBJECT_T *node;
+    NODE_OBJECT_T **update_ptr;
+
+    for (node = context->object_list,
+             update_ptr = &context->object_list;
+             node != NULL;
+         update_ptr = &node->next, node = node->next) {
+        if (node->object == object) {
+            *update_ptr = node->next;
+            SAFE_FREE(node->object);
+            SAFE_FREE(node);
+            *object = NULL;
+            return;
+        }
+    }
+}
+
+#define ADD_CAPABILITY_INFO(capability, field, subfield, max_count, property_count) \
+    if (context->cmd.GetInfo.fetched_data->data.capability.count > max_count - property_count) { \
+        context->cmd.GetInfo.fetched_data->data.capability.count = max_count - property_count; \
+    } \
+\
+    memmove(&context->cmd.GetInfo.capability_data->data.capability.field[property_count], \
+            context->cmd.GetInfo.fetched_data->data.capability.field, \
+            context->cmd.GetInfo.fetched_data->data.capability.count \
+            * sizeof(context->cmd.GetInfo.fetched_data->data.capability.field[0]));       \
+    property_count += context->cmd.GetInfo.fetched_data->data.capability.count; \
+\
+    context->cmd.GetInfo.capability_data->data.capability.count = property_count; \
+\
+    if (more_data && property_count < count \
+        && context->cmd.GetInfo.fetched_data->data.capability.count) {  \
+        context->cmd.GetInfo.property \
+            = context->cmd.GetInfo.capability_data->data. \
+            capability.field[property_count - 1]subfield + 1;   \
+    } else { \
+        more_data = false; \
+    }
+
+TPM2_RC
+ifapi_capability_init(FAPI_CONTEXT *context)
+{
+    context->cmd.GetInfo.capability_data = NULL;
+    context->cmd.GetInfo.fetched_data = NULL;
+
+    return TSS2_RC_SUCCESS;
+
+
+}
+
+TPM2_RC
+ifapi_capability_get(FAPI_CONTEXT *context, TPM2_CAP capability,
+                     UINT32 count, TPMS_CAPABILITY_DATA **capability_data) {
+
+    TPMI_YES_NO more_data;
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    ESYS_CONTEXT *ectx = context->esys;
+
+    switch (context->state) {
+    statecase(context->state, GET_INFO_GET_CAP);
+        /* fetch capability info */
+        context->cmd.GetInfo.fetched_data = NULL;
+        context->cmd.GetInfo.capability_data = NULL;
+        fallthrough;
+
+    statecase(context->state, GET_INFO_GET_CAP_MORE);
+        r = Esys_GetCapability_Async(ectx, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
+                                     capability, context->cmd.GetInfo.property,
+                                     count - context->cmd.GetInfo.property_count);
+        goto_if_error(r, "Error GetCapability", error_cleanup);
+        fallthrough;
+
+    statecase(context->state, GET_INFO_WAIT_FOR_CAP);
+        r = Esys_GetCapability_Finish(ectx, &more_data, &context->cmd.GetInfo.fetched_data);
+        return_try_again(r);
+        goto_if_error(r, "Error GetCapability", error_cleanup);
+
+        LOG_TRACE("GetCapability: capability: 0x%x, property: 0x%x", capability,
+                  context->cmd.GetInfo.property);
+
+        if (context->cmd.GetInfo.fetched_data->capability != capability) {
+            goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
+                       "TPM returned different capability than requested: 0x%x != 0x%x",
+                       error_cleanup,
+                       context->cmd.GetInfo.fetched_data->capability, capability);
+        }
+
+        if (context->cmd.GetInfo.capability_data == NULL) {
+            /* reuse the TPM's result structure */
+            context->cmd.GetInfo.capability_data = context->cmd.GetInfo.fetched_data;
+
+            if (!more_data) {
+                /* there won't be another iteration of the loop, just return the result unmodified */
+                *capability_data = context->cmd.GetInfo.capability_data;
+                return TPM2_RC_SUCCESS;
+            }
+        }
+
+        /* append the TPM's results to the initial structure, as long as there is still space left */
+        switch (capability) {
+        case TPM2_CAP_ALGS:
+            ADD_CAPABILITY_INFO(algorithms, algProperties, .alg,
+                                TPM2_MAX_CAP_ALGS,
+                                context->cmd.GetInfo.property_count);
+            break;
+        case TPM2_CAP_HANDLES:
+            ADD_CAPABILITY_INFO(handles, handle,,
+                                TPM2_MAX_CAP_HANDLES,
+                                context->cmd.GetInfo.property_count);
+            break;
+        case TPM2_CAP_COMMANDS:
+            ADD_CAPABILITY_INFO(command, commandAttributes,,
+                                TPM2_MAX_CAP_CC,
+                                context->cmd.GetInfo.property_count);
+            /* workaround because tpm2-tss does not implement attribute commandIndex for TPMA_CC */
+            context->cmd.GetInfo.property &= TPMA_CC_COMMANDINDEX_MASK;
+            break;
+        case TPM2_CAP_PP_COMMANDS:
+            ADD_CAPABILITY_INFO(ppCommands, commandCodes,,
+                                TPM2_MAX_CAP_CC,
+                                context->cmd.GetInfo.property_count);
+            break;
+        case TPM2_CAP_AUDIT_COMMANDS:
+            ADD_CAPABILITY_INFO(auditCommands, commandCodes,,
+                                TPM2_MAX_CAP_CC,
+                                context->cmd.GetInfo.property_count);
+            break;
+        case TPM2_CAP_PCRS:
+            ADD_CAPABILITY_INFO(assignedPCR, pcrSelections, .hash,
+                                TPM2_NUM_PCR_BANKS,
+                                context->cmd.GetInfo.property_count);
+            break;
+        case TPM2_CAP_TPM_PROPERTIES:
+            ADD_CAPABILITY_INFO(tpmProperties, tpmProperty, .property,
+                                TPM2_MAX_TPM_PROPERTIES,
+                                context->cmd.GetInfo.property_count);
+            break;
+        case TPM2_CAP_PCR_PROPERTIES:
+            ADD_CAPABILITY_INFO(pcrProperties, pcrProperty, .tag,
+                                TPM2_MAX_PCR_PROPERTIES,
+                                context->cmd.GetInfo.property_count);
+            break;
+        case TPM2_CAP_ECC_CURVES:
+            ADD_CAPABILITY_INFO(eccCurves, eccCurves,,
+                                TPM2_MAX_ECC_CURVES,
+                                context->cmd.GetInfo.property_count);
+            break;
+        case TPM2_CAP_VENDOR_PROPERTY:
+            ADD_CAPABILITY_INFO(intelPttProperty, property,,
+                                TPM2_MAX_PTT_PROPERTIES,
+                                context->cmd.GetInfo.property_count);
+            break;
+        default:
+            LOG_ERROR("Unsupported capability: 0x%x\n", capability);
+            if (context->cmd.GetInfo.fetched_data != context->cmd.GetInfo.capability_data) {
+                free(context->cmd.GetInfo.fetched_data);
+            }
+            free(context->cmd.GetInfo.capability_data);
+            *capability_data = NULL;
+            return TSS2_FAPI_RC_NOT_IMPLEMENTED;
+        }
+
+        if (context->cmd.GetInfo.fetched_data != context->cmd.GetInfo.capability_data) {
+            free(context->cmd.GetInfo.fetched_data);
+        }
+        *capability_data = context->cmd.GetInfo.capability_data;
+        break;
+
+    statecasedefault(context->state);
+    }
+    if (more_data) {
+        context->state = GET_INFO_GET_CAP_MORE;
+        return TSS2_FAPI_RC_TRY_AGAIN;
+    } else {
+        context->state = _FAPI_STATE_INIT;
+        return TSS2_RC_SUCCESS;
+    }
+
+ error_cleanup:
+    context->state = _FAPI_STATE_INIT;
+    SAFE_FREE(context->cmd.GetInfo.capability_data);
+    SAFE_FREE(context->cmd.GetInfo.fetched_data);
+    return r;
+}
+
+TSS2_RC
+ifapi_get_certificates(
+    FAPI_CONTEXT *context,
+    UINT32 min_handle,
+    UINT32 max_handle,
+    NODE_OBJECT_T **cert_list)
+{
+    TSS2_RC r;
+    TPMI_YES_NO moreData;
+    TPMS_CAPABILITY_DATA **capabilityData = &context->cmd.Provision.capabilityData;
+    TPM2B_NV_PUBLIC *nvPublic;
+    TPM2B_NAME *nvName;
+    uint8_t *cert_data;
+    size_t cert_size;
+
+    context->cmd.Provision.cert_nv_idx = MIN_EK_CERT_HANDLE;
+    context->cmd.Provision.capabilityData = NULL;
+
+    switch (context->get_cert_state) {
+    statecase(context->get_cert_state, GET_CERT_INIT);
+        *cert_list = NULL;
+        context->cmd.Provision.cert_idx = 0;
+        r = Esys_GetCapability_Async(context->esys,
+                                     ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
+                                     TPM2_CAP_HANDLES, min_handle,
+                                     TPM2_MAX_CAP_HANDLES);
+        goto_if_error(r, "Esys_GetCapability_Async", error);
+        fallthrough;
+
+    statecase(context->get_cert_state, GET_CERT_WAIT_FOR_GET_CAP);
+        r = Esys_GetCapability_Finish(context->esys, &moreData, capabilityData);
+        return_try_again(r);
+        goto_if_error_reset_state(r, "GetCapablity_Finish", error);
+
+        if (!*capabilityData || (*capabilityData)->data.handles.count == 0) {
+            *cert_list = NULL;
+            return TSS2_RC_SUCCESS;
+        }
+        context->cmd.Provision.capabilityData = *capabilityData;
+        context->cmd.Provision.cert_count = (*capabilityData)->data.handles.count;
+
+        /* Filter out NV handles beyond the EK cert range */
+        for (size_t i = 0; i < context->cmd.Provision.cert_count; i++) {
+            if (context->cmd.Provision.capabilityData->data.handles.handle[i] > max_handle) {
+                context->cmd.Provision.cert_count = i;
+                break;
+            }
+        }
+        fallthrough;
+
+    statecase(context->get_cert_state, GET_CERT_GET_CERT_NV);
+
+        context->cmd.Provision.cert_nv_idx
+            = context->cmd.Provision.capabilityData
+            ->data.handles.handle[context->cmd.Provision.cert_idx];
+
+        ifapi_init_hierarchy_object(&context->nv_cmd.auth_object,
+                                    TPM2_RH_OWNER);
+
+        r = Esys_TR_FromTPMPublic_Async(context->esys,
+                                        context->cmd.Provision.cert_nv_idx,
+                                        ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE);
+        goto_if_error_reset_state(r, "Esys_TR_FromTPMPublic_Async", error);
+        fallthrough;
+
+    statecase(context->get_cert_state, GET_CERT_GET_CERT_NV_FINISH);
+        r = Esys_TR_FromTPMPublic_Finish(context->esys,
+                                         &context->cmd.Provision.esys_nv_cert_handle);
+        return_try_again(r);
+        goto_if_error_reset_state(r, "TR_FromTPMPublic_Finish", error);
+
+        /* Read public to get size of certificate */
+        r = Esys_NV_ReadPublic_Async(context->esys,
+                                     context->cmd.Provision.esys_nv_cert_handle,
+                                     ESYS_TR_NONE,
+                                     ESYS_TR_NONE,
+                                     ESYS_TR_NONE);
+        goto_if_error_reset_state(r, "Esys_NV_ReadPublic_Async", error);
+        fallthrough;
+
+    statecase(context->get_cert_state, GET_CERT_GET_CERT_READ_PUBLIC);
+        r = Esys_NV_ReadPublic_Finish(context->esys,
+                                      &nvPublic,
+                                      &nvName);
+        return_try_again(r);
+        goto_if_error(r, "Error: nv read public", error);
+
+        /* TPMA_NV_NO_DA is set for NV certificate */
+        context->nv_cmd.nv_object.misc.nv.public.nvPublic.attributes = TPMA_NV_NO_DA;
+
+        /* Prepare context for nv read */
+        context->nv_cmd.data_idx = 0;
+        context->nv_cmd.auth_index = ESYS_TR_RH_OWNER;
+        context->nv_cmd.numBytes = nvPublic->nvPublic.dataSize;
+        context->nv_cmd.esys_handle = context->cmd.Provision.esys_nv_cert_handle;
+        context->nv_cmd.offset = 0;
+        context->cmd.Provision.pem_cert = NULL;
+        context->session1 = ESYS_TR_PASSWORD;
+        context->session2 = ESYS_TR_NONE;
+        context->nv_cmd.nv_read_state = NV_READ_INIT;
+        memset(&context->nv_cmd.nv_object, 0, sizeof(IFAPI_OBJECT));
+        fallthrough;
+
+    statecase(context->get_cert_state, GET_CERT_READ_CERT);
+        r = ifapi_nv_read(context, &cert_data, &cert_size);
+        return_try_again(r);
+        goto_if_error_reset_state(r, " FAPI NV_Read", error);
+
+        context->cmd.Provision.cert_idx += 1;
+
+        /* Add cert to list */
+        if (context->cmd.Provision.cert_idx == context->cmd.Provision.cert_count) {
+            context->get_cert_state = GET_CERT_GET_CERT_NV;
+
+            r = push_object_with_size_to_list(cert_data, cert_size, cert_list);
+            goto_if_error(r, "Store certificate in list.", error);
+
+            return TSS2_RC_SUCCESS;
+        } else {
+            context->get_cert_state = GET_CERT_GET_CERT_NV;
+        }
+        break;
+
+    statecasedefault(context->get_cert_state);
+    }
+
+ error:
+    ifapi_free_object_list(*cert_list);
+    return r;
+}
+
+
+/** Get description of an internal FAPI object.
+ *
+ * @parm[in] object The object with the descritpion.
+ * @retval The char string of the description.
+ * @retval NULL if no description exists.
+ */
+TSS2_RC
+ifapi_get_description(IFAPI_OBJECT *object, char **description)
+{
+    char *obj_description = NULL;
+
+    switch (object->objectType) {
+    case IFAPI_KEY_OBJ:
+        obj_description = object->misc.key.description;
+        break;
+    case IFAPI_NV_OBJ:
+        obj_description = object->misc.nv.description;
+        break;
+    case IFAPI_HIERARCHY_OBJ:
+        obj_description = object->misc.hierarchy.description;
+        break;
+    default:
+        *description = NULL;
+        return TSS2_RC_SUCCESS;
+    }
+    if (obj_description) {
+        *description = strdup(obj_description);
+        check_oom(*description);
+    } else {
+        *description = NULL;
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Set description of an internal FAPI object.
+ *
+ * @parm[in,out] object The object with the descritpion.
+ * @parm[in] descritpion The description char strint or NULL.
+ */
+void
+ifapi_set_description(IFAPI_OBJECT *object, char *description)
+{
+    switch (object->objectType) {
+    case IFAPI_KEY_OBJ:
+        SAFE_FREE(object->misc.key.description);
+        object->misc.key.description = description;
+        break;
+    case IFAPI_NV_OBJ:
+        SAFE_FREE(object->misc.nv.description);
+        object->misc.nv.description = description;
+        break;
+    case IFAPI_HIERARCHY_OBJ:
+        SAFE_FREE(object->misc.hierarchy.description);
+        object->misc.hierarchy.description = description;
+        break;
+    default:
+        LOG_WARNING("Description can't be set");
+        break;
+    }
+}
+
+TSS2_RC
+ifapi_expand_path(IFAPI_KEYSTORE *keystore, const char *path, char **file_name)
+{
+    TSS2_RC r;
+    NODE_STR_T *node_list = NULL;
+    size_t pos = 0;
+
+    if (ifapi_hierarchy_path_p(path)) {
+        if (strncmp(path, "P_", 2) == 0 || strncmp(path, "/P_", 3) == 0) {
+            *file_name = strdup(path);
+            return_if_null(*file_name, "Out of memory", TSS2_FAPI_RC_MEMORY);
+        } else {
+            if (strncmp("/", path, 1) == 0)
+                pos = 1;
+            r  = ifapi_asprintf(file_name, "%s%s%s",  keystore->defaultprofile,
+                                IFAPI_FILE_DELIM, &path[pos]);
+            return_if_error(r, "Out of memory.");
+        }
+    } else if (ifapi_path_type_p(path, IFAPI_NV_PATH)
+        || ifapi_path_type_p(path, IFAPI_POLICY_PATH)
+        || ifapi_path_type_p(path, IFAPI_EXT_PATH)
+        || strncmp(path, "/P_", 3) == 0
+        || strncmp(path, "P_", 2) == 0) {
+        *file_name = strdup(path);
+        return_if_null(*file_name, "Out of memory", TSS2_FAPI_RC_MEMORY);
+
+    } else {
+        r = get_explicit_key_path(keystore, path, &node_list);
+        return_if_error(r, "Out of memory");
+
+        r = ifapi_path_string(file_name, NULL, node_list, NULL);
+        goto_if_error(r, "Out of memory", error);
+
+        free_string_list(node_list);
+    }
+    return TSS2_RC_SUCCESS;
+
+error:
+    free_string_list(node_list);
+    return r;
+}
diff --git a/src/tss2-fapi/fapi_util.h b/src/tss2-fapi/fapi_util.h
new file mode 100644
index 0000000..6c7f676
--- /dev/null
+++ b/src/tss2-fapi/fapi_util.h
@@ -0,0 +1,309 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ *******************************************************************************/
+#ifndef FAPI_UTIL_H
+#define FAPI_UTIL_H
+
+#include <stdint.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <sys/stat.h>
+#include <json-c/json.h>
+#include <json-c/json_util.h>
+
+#include "tss2_esys.h"
+#include "tss2_fapi.h"
+#include "fapi_int.h"
+#include "ifapi_helpers.h"
+
+
+TSS2_RC
+ifapi_flush_object(FAPI_CONTEXT *context, ESYS_TR session);
+
+TSS2_RC
+ifapi_get_session_async(ESYS_CONTEXT *esys, ESYS_TR saltkey, const IFAPI_PROFILE *profile);
+
+TSS2_RC
+ifapi_get_session_finish(ESYS_CONTEXT *esys, ESYS_TR *session,
+                         TPMA_SESSION flags);
+
+TSS2_RC
+ifapi_set_auth(
+    FAPI_CONTEXT *context,
+    IFAPI_OBJECT *auth_object,
+    const char *description);
+
+TSS2_RC
+ifapi_key_deserialize_keep_json(
+    FAPI_CONTEXT *context,
+    json_object *jso,
+    ESYS_TR *kHandle,
+    IFAPI_OBJECT *object);
+
+
+TSS2_RC
+ifapi_key_deserialize(
+    FAPI_CONTEXT *context,
+    json_object *jso,
+    ESYS_TR *kHandle,
+    IFAPI_OBJECT *object);
+
+TSS2_RC
+ifapi_get_free_handle_async(FAPI_CONTEXT *fctx, TPM2_HANDLE *handle);
+
+TSS2_RC
+ifapi_get_free_handle_finish(FAPI_CONTEXT *fctx, TPM2_HANDLE *handle,
+                             TPM2_HANDLE max);
+
+TSS2_RC
+ifapi_init_primary_async(
+    FAPI_CONTEXT *context,
+    TSS2_KEY_TYPE ktype);
+
+TSS2_RC
+ifapi_init_primary_finish(
+    FAPI_CONTEXT *context,
+    TSS2_KEY_TYPE ktype);
+
+TSS2_RC
+ifapi_session_init(FAPI_CONTEXT *context);
+
+TSS2_RC
+ifapi_non_tpm_mode_init(FAPI_CONTEXT *context);
+
+void
+ifapi_session_clean(FAPI_CONTEXT *context);
+
+TSS2_RC
+ifapi_cleanup_session(FAPI_CONTEXT *context);
+
+void
+ifapi_primary_clean(FAPI_CONTEXT *context);
+
+TSS2_RC
+ifapi_get_sessions_async(
+    FAPI_CONTEXT *context,
+    IFAPI_SESSION_TYPE session_flags,
+    TPMA_SESSION attribute_flags1,
+    TPMA_SESSION attribute_flags2);
+
+TSS2_RC
+ifapi_get_sessions_finish(FAPI_CONTEXT *context, const IFAPI_PROFILE *profile);
+
+TSS2_RC
+ifapi_merge_profile_into_nv_template(
+    FAPI_CONTEXT *context,
+    IFAPI_NV_TEMPLATE *template);
+
+TSS2_RC
+ifapi_merge_profile_into_template(
+    const IFAPI_PROFILE *profile,
+    IFAPI_KEY_TEMPLATE *template);
+
+TSS2_RC
+ifapi_load_key_async(FAPI_CONTEXT *context, size_t position);
+
+TSS2_RC
+ifapi_load_key_finish(FAPI_CONTEXT *context, bool flush_parent);
+
+TSS2_RC
+ifapi_load_keys_async(
+    FAPI_CONTEXT *context,
+    char const *keyPath);
+
+TSS2_RC
+ifapi_load_keys_finish(
+    FAPI_CONTEXT *context,
+    bool flush_parent,
+    ESYS_TR *handle,
+    IFAPI_OBJECT **key_object);
+
+TSS2_RC
+ifapi_get_entities(
+    IFAPI_KEYSTORE *keystore,
+    const char *searchPath,
+    char ***pathlist,
+    size_t *numPaths);
+
+TSS2_RC
+ifapi_nv_read(
+    FAPI_CONTEXT *context,
+    uint8_t     **data,
+    size_t       *size);
+
+void
+ifapi_flush_policy_session(
+    FAPI_CONTEXT *context,
+    ESYS_TR session,
+    TSS2_RC r);
+
+TSS2_RC
+ifapi_nv_write(
+    FAPI_CONTEXT *context,
+    char         *nvPath,
+    size_t         param_offset,
+    uint8_t const *data,
+    size_t         size);
+
+TSS2_RC
+ifapi_get_random(
+    FAPI_CONTEXT *context,
+    size_t numBytes,
+    uint8_t **data);
+
+TSS2_RC
+ifapi_sym_encrypt_decrypt_async(
+    FAPI_CONTEXT *context,
+    const uint8_t *in_data,
+    size_t       size,
+    TPMI_YES_NO decrypt);
+
+TSS2_RC
+ifapi_sym_encrypt_decrypt_finish(
+    FAPI_CONTEXT *context,
+    uint8_t     **data,
+    size_t       *size,
+    TPMI_YES_NO decrypt);
+
+TSS2_RC
+ifapi_load_key(
+    FAPI_CONTEXT  *context,
+    char    const *keyPath,
+    IFAPI_OBJECT **key_object);
+
+TSS2_RC
+ifapi_key_sign(
+    FAPI_CONTEXT    *context,
+    IFAPI_OBJECT    *sig_key_object,
+    char const      *padding,
+    TPM2B_DIGEST    *digest,
+    TPMT_SIGNATURE **tpm_signature,
+    char           **publicKey,
+    char           **certificate);
+
+void
+ifapi_full_path_to_fapi_path(
+    IFAPI_KEYSTORE *keystore,
+    char *path);
+
+TSS2_RC
+ifapi_authorize_object(
+    FAPI_CONTEXT *context,
+    IFAPI_OBJECT *object,
+    ESYS_TR      *session);
+
+TSS2_RC
+ifapi_authorize_objectPV2(
+    FAPI_CONTEXT *context,
+    IFAPI_OBJECT *object,
+    ESYS_TR      *session);
+
+TSS2_RC
+ifapi_get_json(
+    FAPI_CONTEXT *context,
+    IFAPI_OBJECT *object,
+    char **json_string);
+
+TSS2_RC
+ifapi_read_object(
+    FAPI_CONTEXT *context,
+    IFAPI_OBJECT *object,
+    const char *path);
+
+TSS2_RC
+ifapi_key_create_prepare(
+    FAPI_CONTEXT  *context,
+    char   const *keyPath,
+    char   const *policyPath);
+
+TSS2_RC
+ifapi_key_create_prepare_auth(
+    FAPI_CONTEXT  *context,
+    char   const *keyPath,
+    char   const *policyPath,
+    char   const *authValue);
+
+TSS2_RC
+ifapi_key_create_prepare_sensitive(
+    FAPI_CONTEXT  *context,
+    char    const *keyPath,
+    char    const *policyPath,
+    size_t         dataSize,
+    char    const *authValue,
+    uint8_t const *data);
+
+TSS2_RC
+ifapi_key_create(
+    FAPI_CONTEXT *context,
+    IFAPI_KEY_TEMPLATE *template);
+
+TSS2_RC
+ifapi_get_sig_scheme(
+    FAPI_CONTEXT *context,
+    IFAPI_OBJECT *object,
+    char const *padding,
+    TPM2B_DIGEST *digest,
+    TPMT_SIG_SCHEME **sig_scheme);
+
+TSS2_RC
+ifapi_change_auth_hierarchy(
+    FAPI_CONTEXT *context,
+    ESYS_TR handle,
+    IFAPI_OBJECT *hierarchy_object,
+    TPM2B_AUTH *newAuthValue);
+
+TSS2_RC
+ifapi_change_policy_hierarchy(
+    FAPI_CONTEXT *context,
+    ESYS_TR handle,
+    IFAPI_OBJECT *hierarchy_object,
+    TPMS_POLICY_HARNESS *policy_harness);
+
+IFAPI_OBJECT
+*ifapi_allocate_object(FAPI_CONTEXT *context);
+
+void
+ifapi_free_objects(FAPI_CONTEXT *context);
+
+void
+ifapi_free_object(FAPI_CONTEXT *context, IFAPI_OBJECT **object);
+
+TPM2_RC
+ifapi_capability_init(FAPI_CONTEXT *context);
+
+TPM2_RC
+ifapi_capability_get(FAPI_CONTEXT *context, TPM2_CAP capability,
+                     UINT32 count, TPMS_CAPABILITY_DATA **capability_data);
+
+TSS2_RC
+ifapi_get_certificates(
+    FAPI_CONTEXT *context,
+    UINT32 min_handle,
+    UINT32 max_handle,
+    NODE_OBJECT_T **cert_list);
+
+TSS2_RC
+ifapi_initialize_object(
+    ESYS_CONTEXT *ectx,
+    IFAPI_OBJECT *object);
+
+TSS2_RC
+ifapi_esys_serialize_object(
+    ESYS_CONTEXT *ectx,
+    IFAPI_OBJECT *object);
+
+TSS2_RC
+ifapi_get_description(IFAPI_OBJECT *object, char **description);
+
+void
+ifapi_set_description(IFAPI_OBJECT *object, char *description);
+
+TSS2_RC
+ifapi_expand_path(
+    IFAPI_KEYSTORE *keystore,
+    const char *path,
+    char **file_name);
+
+#endif /* FAPI_UTIL_H */
diff --git a/src/tss2-fapi/ifapi_config.c b/src/tss2-fapi/ifapi_config.c
new file mode 100644
index 0000000..5d42286
--- /dev/null
+++ b/src/tss2-fapi/ifapi_config.c
@@ -0,0 +1,216 @@
+/* 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 <json-c/json.h>
+#include <json-c/json_util.h>
+
+#include "util/aux_util.h"
+#include "ifapi_config.h"
+#include "ifapi_json_deserialize.h"
+#include "tpm_json_deserialize.h"
+#include "ifapi_helpers.h"
+
+#define LOGMODULE fapi
+#include "util/log.h"
+
+/**
+ * The path of the default config file
+ */
+#define DEFAULT_CONFIG_FILE (SYSCONFDIR "/tpm2-tss/fapi-config.json")
+
+/** Deserializes a configuration JSON object.
+ *
+ * @param [in]  jso The JSON object to be deserialized
+ * @param [out] out The deserialized configuration object
+ *
+ * @retval TSS2_RC_SUCCESS on success
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE if jso or out is NULL
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the JSON object cannot be deserialized
+ */
+static TSS2_RC
+ifapi_json_IFAPI_CONFIG_deserialize(json_object *jso, IFAPI_CONFIG *out)
+{
+    /* Check for NULL parameters */
+    return_if_null(out, "out is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+    return_if_null(jso, "jso is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    /* Deserialize the JSON object) */
+    json_object *jso2;
+    TSS2_RC r;
+    LOG_TRACE("call");
+
+    if (!ifapi_get_sub_object(jso, "profile_dir", &jso2)) {
+        out->profile_dir = NULL;
+    } else {
+        r =  ifapi_json_char_deserialize(jso2, &out->profile_dir);
+        return_if_error(r, "BAD VALUE");
+    }
+
+    if (!ifapi_get_sub_object(jso, "user_dir", &jso2)) {
+        out->user_dir = NULL;
+    } else {
+        r =  ifapi_json_char_deserialize(jso2, &out->user_dir);
+        return_if_error(r, "BAD VALUE");
+    }
+
+    if (!ifapi_get_sub_object(jso, "system_dir", &jso2)) {
+        out->keystore_dir = NULL;
+    } else {
+        r =  ifapi_json_char_deserialize(jso2, &out->keystore_dir);
+        return_if_error(r, "BAD VALUE");
+    }
+
+    if (!ifapi_get_sub_object(jso, "log_dir", &jso2)) {
+        out->log_dir = DEFAULT_LOG_DIR;
+    } else {
+        r =  ifapi_json_char_deserialize (jso2, &out->log_dir);
+        return_if_error(r,"BAD VALUE");
+    }
+
+    if (!ifapi_get_sub_object(jso, "profile_name", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_char_deserialize(jso2, &out->profile_name);
+    return_if_error(r, "BAD VALUE");
+    if (!ifapi_get_sub_object(jso, "tcti", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_char_deserialize(jso2, &out->tcti);
+    return_if_error(r, "BAD VALUE");
+
+
+    if (!ifapi_get_sub_object(jso, "system_pcrs", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_TPML_PCR_SELECTION_deserialize(jso2, &out->system_pcrs);
+    return_if_error(r, "BAD VALUE");
+
+    LOG_TRACE("true");
+    return TSS2_RC_SUCCESS;
+}
+
+/**
+ * Starts the initialization of the FAPI configuration.
+ *
+ * @param [in] io An IO object for file system access
+ *
+ * @retval TSS2_RC_SUCCESS on success
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE if io is NULL
+ */
+TSS2_RC
+ifapi_config_initialize_async(IFAPI_IO *io)
+{
+    /* Check for NULL parameters */
+    return_if_null(io, "io is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    /* Determine the location of the configuration file */
+    char *configFile = getenv(ENV_FAPI_CONFIG);
+    if (!configFile) {
+        /* No config file given, falling back to the default */
+        configFile = DEFAULT_CONFIG_FILE;
+    }
+
+    /* Start reading the config file */
+    TSS2_RC r = ifapi_io_read_async(io, configFile);
+    return_if_error(r, "Could not read config file ");
+    return TSS2_RC_SUCCESS;
+}
+
+/**
+ * Finishes the initialization of the FAPI configuration.
+ * @param [in]  io An IO object for file system access
+ * @param [out] config The configuration that is initialized
+ *
+ * @retval TSS2_RC_SUCCESS on success
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE if config or io is NULL
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the read configuration file does not hold
+ *         a valid configuration
+ * @retval TSS2_FAPI_RC_GENERAL_FAILURE if JSON parsing fails
+ * @retval TSS2_FAPI_RC_BAD_PATH if the configuration path is invalid
+ */
+TSS2_RC
+ifapi_config_initialize_finish(IFAPI_IO *io, IFAPI_CONFIG *config)
+{
+    /* Check for NULL parameters */
+    return_if_null(config, "config is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+    return_if_null(io, "io is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    /* Definitions that must be listed here for the cleanup to work */
+    char* homeDir = NULL;
+    json_object *jso = NULL;
+
+    /* Finish reading operation */
+    uint8_t * configFileContent = NULL;
+    size_t configFileContentSize = 0;
+    TSS2_RC r = ifapi_io_read_finish(io, &configFileContent, &configFileContentSize);
+    return_try_again(r);
+    goto_if_error(r, "Could not finish read operation", cleanup);
+    if (configFileContent == NULL || configFileContentSize == 0) {
+        LOG_ERROR("Config file is empty");
+        r = TSS2_FAPI_RC_BAD_VALUE;
+        goto cleanup;
+    }
+
+    /* Parse and deserialize the configuration file */
+    jso = json_tokener_parse((char *)configFileContent);
+    goto_if_null(jso, "Could not parse JSON objects",
+            TSS2_FAPI_RC_GENERAL_FAILURE, cleanup);
+    r = ifapi_json_IFAPI_CONFIG_deserialize(jso, config);
+    goto_if_error(r, "Could not deserialize configuration", cleanup);
+
+    /* Check, if the values of the configuration are valid */
+    goto_if_null(config->profile_dir, "No profile directory defined in config file",
+            TSS2_FAPI_RC_BAD_VALUE, cleanup);
+    goto_if_null(config->user_dir, "No user directory defined in config file",
+            TSS2_FAPI_RC_BAD_VALUE, cleanup);
+    goto_if_null(config->profile_name, "No default profile defined in config file.",
+            TSS2_FAPI_RC_BAD_VALUE, cleanup);
+
+    /* Check whether usage of home directory is provided in config file */
+    size_t startPos = 0;
+    if (strncmp("~", config->user_dir, 1) == 0) {
+        startPos = 1;
+    } else if (strncmp("$HOME", config->user_dir, 5) == 0) {
+        startPos = 5;
+    }
+
+    /* Replace home abbreviation in user path. */
+    char* homePath = NULL;
+    if (startPos != 0) {
+        LOG_DEBUG("Expanding user directory %s to user's home", config->user_dir);
+        homeDir = getenv("HOME");
+        goto_if_null2(homeDir, "Home directory can't be determined.",
+                r, TSS2_FAPI_RC_BAD_PATH, cleanup);
+
+        r = ifapi_asprintf(&homePath, "%s%s%s", homeDir, IFAPI_FILE_DELIM,
+                &config->user_dir[startPos]);
+        goto_if_error(r, "Out of memory.", cleanup);
+
+        SAFE_FREE(config->user_dir);
+        config->user_dir = homePath;
+    }
+
+    /* Log the contents of the configuration */
+    LOG_DEBUG("Configuration profile directory: %s", config->profile_dir);
+    LOG_DEBUG("Configuration user directory: %s", config->user_dir);
+    LOG_DEBUG("Configuration key storage directory: %s", config->keystore_dir);
+    LOG_DEBUG("Configuration profile name: %s", config->profile_name);
+    LOG_DEBUG("Configuration TCTI: %s", config->tcti);
+    LOG_DEBUG("Configuration log directory: %s", config->log_dir);
+cleanup:
+    SAFE_FREE(configFileContent);
+    if (jso != NULL) {
+        json_object_put(jso);
+    }
+    return r;
+}
diff --git a/src/tss2-fapi/ifapi_config.h b/src/tss2-fapi/ifapi_config.h
new file mode 100644
index 0000000..91b89c8
--- /dev/null
+++ b/src/tss2-fapi/ifapi_config.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ *******************************************************************************/
+#ifndef IFAPI_CONFIG_H
+#define IFAPI_CONFIG_H
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include "tss2_tpm2_types.h"
+#include "ifapi_io.h"
+
+#define ENV_FAPI_CONFIG "TSS2_FAPICONF"
+
+/**
+ * Type for storing FAPI configuration
+ */
+typedef struct {
+    /** Path for profile directory */
+    char                *profile_dir;
+    /** Directory storing NV objects */
+    char                *user_dir;
+    /** Directory storing key and NV objects */
+    char                *keystore_dir;
+    /** Name the used profile */
+    char                *profile_name;
+    /** The used tcti interface */
+    char                *tcti;
+    /** The directory for event logs */
+    char                *log_dir;
+    /** The PCRs used by IMA etc. */
+    TPML_PCR_SELECTION  system_pcrs;
+} IFAPI_CONFIG;
+
+TSS2_RC
+ifapi_config_initialize_async(
+    IFAPI_IO            *io
+        );
+
+TSS2_RC
+ifapi_config_initialize_finish(
+    IFAPI_IO            *io,
+    IFAPI_CONFIG        *config
+    );
+
+#endif /* IFAPI_CONFIG_H */
diff --git a/src/tss2-fapi/ifapi_eventlog.c b/src/tss2-fapi/ifapi_eventlog.c
new file mode 100644
index 0000000..c6f02a7
--- /dev/null
+++ b/src/tss2-fapi/ifapi_eventlog.c
@@ -0,0 +1,338 @@
+/* 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 <string.h>
+
+#include "ifapi_helpers.h"
+#include "ifapi_eventlog.h"
+#include "ifapi_json_serialize.h"
+
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+#include "ifapi_macros.h"
+
+/** Initialize the eventlog module of FAPI.
+ *
+ * @param eventlog [in, out] The context area for the eventlog.
+ * @param log_dir [in] The directory where to put the eventlog data.
+ * @retval TSS2_RC_SUCCESS on success.
+ * @retval TSS2_FAPI_RC_IO_ERROR if creation of log_dir failed or log_dir is not writable.
+ * @retval TSS2_FAPI_RC_MEMORY if memory allocation failed.
+ */
+TSS2_RC
+ifapi_eventlog_initialize(
+    IFAPI_EVENTLOG *eventlog,
+    const char *log_dir)
+{
+    check_not_null(eventlog);
+    check_not_null(log_dir);
+
+    TSS2_RC r;
+
+    r = ifapi_io_check_create_dir(log_dir);
+    return_if_error2(r, "Directory check/creation failed for %s", log_dir);
+
+    eventlog->log_dir = strdup(log_dir);
+    return_if_null(eventlog->log_dir, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Retrieve the eventlog for a given list of pcrs using asynchronous io.
+ *
+ * Call ifapi_eventlog_get_finish to retrieve the results.
+ *
+ * @param eventlog [in, out] The context area for the eventlog.
+ * @param io [in, out] The context area for the asynchronous io module.
+ * @param pcrList [in] The list of PCR indices to retrieve the log for.
+ * @param pcrListSize The size of pcrList.
+ * @retval TSS2_RC_SUCCESS on success.
+ * @retval TSS2_FAPI_RC_IO_ERROR if creation of log_dir failed or log_dir is not writable.
+ * @retval TSS2_FAPI_RC_MEMORY if memory allocation failed.
+ */
+TSS2_RC
+ifapi_eventlog_get_async(
+    IFAPI_EVENTLOG *eventlog,
+    IFAPI_IO *io,
+    const TPM2_HANDLE *pcrList,
+    size_t pcrListSize)
+{
+    check_not_null(eventlog);
+    check_not_null(io);
+    check_not_null(pcrList);
+
+    if (pcrListSize > TPM2_MAX_PCRS) {
+        LOG_ERROR("pcrList too long %zi > %i", pcrListSize, TPM2_MAX_PCRS);
+        return TSS2_FAPI_RC_BAD_VALUE;
+    }
+
+    LOG_TRACE("called for pcrListSize=%zi", pcrListSize);
+
+    memcpy(&eventlog->pcrList, pcrList, pcrListSize * sizeof(TPM2_HANDLE));
+    eventlog->pcrListSize = pcrListSize;
+    eventlog->pcrListIdx = 0;
+
+    eventlog->log = json_object_new_array();
+    return_if_null(eventlog->log, "Out of memory", TSS2_FAPI_RC_MEMORY);
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Retrieve the eventlog for a given list of pcrs using asynchronous io.
+ *
+ * Call after ifapi_eventlog_get_async.
+ *
+ * @param eventlog [in, out] The context area for the eventlog.
+ * @param io [in, out] The context area for the asynchronous io module.
+ * @param log [out] The event log for the requested PCRs in JSON format
+ * @retval TSS2_RC_SUCCESS on success.
+ * @retval TSS2_FAPI_RC_IO_ERROR if creation of log_dir failed or log_dir is not writable.
+ * @retval TSS2_FAPI_RC_MEMORY if memory allocation failed.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN if the I/O operation is not finished yet and this function needs
+ *         to be called again.
+ */
+TSS2_RC
+ifapi_eventlog_get_finish(
+    IFAPI_EVENTLOG *eventlog,
+    IFAPI_IO *io,
+    char **log)
+{
+    /* eventlog parameter currently not used */
+    check_not_null(eventlog);
+    check_not_null(io);
+    check_not_null(log);
+
+    TSS2_RC r;
+    char *event_log_file, *logstr;
+    json_object *logpart, *event;
+
+    LOG_TRACE("called");
+
+loop:
+    /* If we're dune with adding all eventlogs to the json array, we can serialize it and return
+       it to the caller. */
+    if (eventlog->pcrListIdx >= eventlog->pcrListSize) {
+        LOG_TRACE("Done reading pcrLog");
+        *log = strdup(json_object_to_json_string_ext(eventlog->log, JSON_C_TO_STRING_PRETTY));
+        check_oom(*log);
+        json_object_put(eventlog->log);
+        eventlog->log = NULL;
+        eventlog->state = IFAPI_EVENTLOG_STATE_INIT;
+        return TSS2_RC_SUCCESS;
+    }
+
+    switch(eventlog->state) {
+    statecase(eventlog->state, IFAPI_EVENTLOG_STATE_INIT)
+        /* Construct the filename for the eventlog file */
+        r = ifapi_asprintf(&event_log_file, "%s/%s%i",
+                           eventlog->log_dir, IFAPI_PCR_LOG_FILE,
+                           eventlog->pcrList[eventlog->pcrListIdx]);
+        return_if_error(r, "Out of memory.");
+
+        //TODO: Add file-exists check with goto loop instead of failed read_async
+
+        /* Initiate the reading of the eventlog file */
+        r = ifapi_io_read_async(io, event_log_file);
+        free(event_log_file);
+        if (r) {
+            LOG_DEBUG("No event log for pcr %i", eventlog->pcrList[eventlog->pcrListIdx]);
+            eventlog->pcrListIdx += 1;
+            goto loop;
+        }
+        fallthrough;
+
+    statecase(eventlog->state, IFAPI_EVENTLOG_STATE_READING)
+        /* Finish the reading of the eventlog file and return it directly to the output parameter */
+        r = ifapi_io_read_finish(io, (uint8_t **)&logstr, NULL);
+        return_try_again(r);
+        return_if_error(r, "read_finish failed");
+
+        logpart = json_tokener_parse(logstr);
+        SAFE_FREE(logstr);
+        return_if_null(log, "JSON parsing error", TSS2_FAPI_RC_BAD_VALUE);
+
+        /* Append the log-entry from logpart to the eventlog */
+        json_type jso_type = json_object_get_type(logpart);
+        if (jso_type != json_type_array) {
+            /* libjson-c does not deliver an array if array has only one element */
+            json_object_array_add(eventlog->log, logpart);
+        } else {
+            /* Iterate through the array of logpart and add each item to the eventlog */
+            /* The return type of json_object_array_length() was changed, thus the case */
+            for (int i = 0; i < (int)json_object_array_length(logpart); i++) {
+                event = json_object_array_get_idx(logpart, i);
+                /* Increment the refcount of event so it does not get freed on put(logpart) below */
+                json_object_get(event);
+                json_object_array_add(eventlog->log, event);
+            }
+            json_object_put(logpart);
+        }
+
+        eventlog->pcrListIdx += 1;
+        goto loop;
+
+    statecasedefault(eventlog->state);
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Append an event to the existing event log.
+ *
+ * Call ifapi_eventlog_append_finish to finalize this operation.
+ *
+ * @param eventlog [in, out] The context area for the eventlog.
+ * @param io [in, out] The context area for the asynchronous io module.
+ * @param event The event to be appended to the eventlog.
+ * @retval TSS2_RC_SUCCESS on success.
+ * @retval TSS2_FAPI_RC_IO_ERROR if creation of log_dir failed or log_dir is not writable.
+ * @retval TSS2_FAPI_RC_MEMORY if memory allocation failed.
+ */
+TSS2_RC
+ifapi_eventlog_append_async(
+    IFAPI_EVENTLOG *eventlog,
+    IFAPI_IO *io,
+    const IFAPI_EVENT *event)
+{
+    check_not_null(eventlog);
+    check_not_null(io);
+    check_not_null(event);
+
+    TSS2_RC r;
+    char *event_log_file;
+
+    if (eventlog->state != IFAPI_EVENTLOG_STATE_INIT) {
+        LOG_ERROR("Wrong state: %i", eventlog->state);
+        return TSS2_FAPI_RC_BAD_SEQUENCE;
+    }
+
+    eventlog->event = *event;
+
+    /* Construct the filename for the eventlog file */
+    r = ifapi_asprintf(&event_log_file, "%s/%s%i",
+                       eventlog->log_dir, IFAPI_PCR_LOG_FILE, event->pcr);
+    return_if_error(r, "Out of memory.");
+
+    /* Initiate the reading of the eventlog file */
+    r = ifapi_io_read_async(io, event_log_file);
+    if (r) {
+        LOG_DEBUG("Eventlog file %s could not be opened, creating...", event_log_file);
+        free(event_log_file);
+        eventlog->state = IFAPI_EVENTLOG_STATE_APPENDING;
+        return TSS2_RC_SUCCESS;
+    }
+    free(event_log_file);
+
+    eventlog->state = IFAPI_EVENTLOG_STATE_READING;
+    return TSS2_RC_SUCCESS;
+}
+
+/** Append an event to the existing event log.
+ *
+ * Call after ifapi_eventlog_get_async.
+ *
+ * @param eventlog [in, out] The context area for the eventlog.
+ * @param io [in, out] The context area for the asynchronous io module.
+ * @retval TSS2_RC_SUCCESS on success.
+ * @retval TSS2_FAPI_RC_IO_ERROR if creation of log_dir failed or log_dir is not writable.
+ * @retval TSS2_FAPI_RC_MEMORY if memory allocation failed.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN if the I/O operation is not finished yet and this function needs
+ *         to be called again.
+ */
+TSS2_RC
+ifapi_eventlog_append_finish(
+    IFAPI_EVENTLOG *eventlog,
+    IFAPI_IO *io)
+{
+    check_not_null(eventlog);
+    check_not_null(io);
+
+    TSS2_RC r;
+    char *logstr = NULL, *event_log_file;
+    const char *logstr2 = NULL;
+    json_object *log, *event = NULL;
+
+    switch(eventlog->state) {
+    statecase(eventlog->state, IFAPI_EVENTLOG_STATE_READING)
+        /* Finish the reading of the eventlog file and return it directly to the output parameter */
+        r = ifapi_io_read_finish(io, (uint8_t **)&logstr, NULL);
+        return_try_again(r);
+        return_if_error(r, "read_finish failed");
+        fallthrough;
+
+    statecase(eventlog->state, IFAPI_EVENTLOG_STATE_APPENDING)
+        /* If a log was read, we deserialize it to JSON. Otherwise we start a new log. */
+        if (logstr) {
+            log = json_tokener_parse(logstr);
+            SAFE_FREE(logstr);
+            return_if_null(log, "JSON parsing error", TSS2_FAPI_RC_BAD_VALUE);
+
+             /* libjson-c does not deliver an array if array has only one element */
+            json_type jso_type = json_object_get_type(log);
+            if (jso_type != json_type_array) {
+                json_object *json_array = json_object_new_array();
+                json_object_array_add(json_array, log);
+                log = json_array;
+            }
+        } else {
+            log = json_object_new_array();
+            return_if_null(log, "Out of memory", TSS2_FAPI_RC_MEMORY);
+        }
+
+        /* Extend the eventlog with the data */
+        eventlog->event.recnum = json_object_array_length(log) + 1;
+
+        r = ifapi_json_IFAPI_EVENT_serialize(&eventlog->event, &event);
+        if (r) {
+            json_object_put(log);
+            LOG_ERROR("Error serializing event data");
+            return TSS2_FAPI_RC_GENERAL_FAILURE;
+        }
+
+        json_object_array_add(log, event);
+        logstr2 = json_object_to_json_string_ext(log, JSON_C_TO_STRING_PRETTY);
+
+        /* Construct the filename for the eventlog file */
+        r = ifapi_asprintf(&event_log_file, "%s/%s%i",
+                           eventlog->log_dir, IFAPI_PCR_LOG_FILE, eventlog->event.pcr);
+        return_if_error(r, "Out of memory.");
+
+        /* Start writing the eventlog back to disk */
+        r = ifapi_io_write_async(io, event_log_file, (uint8_t *) logstr2, strlen(logstr2));
+        free(event_log_file);
+        json_object_put(log); /* this also frees logstr2 */
+        return_if_error(r, "write_async failed");
+        fallthrough;
+
+    statecase(eventlog->state, IFAPI_EVENTLOG_STATE_WRITING)
+        /* Finish writing the eventlog */
+        r = ifapi_io_write_finish(io);
+        return_try_again(r);
+        return_if_error(r, "read_finish failed");
+
+        eventlog->state = IFAPI_EVENTLOG_STATE_INIT;
+        break;
+
+    statecasedefault(eventlog->state);
+    }
+
+    return TSS2_RC_SUCCESS;
+}
+
+void ifapi_cleanup_event(IFAPI_EVENT * event) {
+    if (event != NULL) {
+        if (event->type == IFAPI_IMA_EVENT_TAG) {
+            SAFE_FREE(event->sub_event.ima_event.eventName);
+        }
+        else if (event->type == IFAPI_TSS_EVENT_TAG) {
+            SAFE_FREE(event->sub_event.tss_event.event);
+        }
+    }
+}
diff --git a/src/tss2-fapi/ifapi_eventlog.h b/src/tss2-fapi/ifapi_eventlog.h
new file mode 100644
index 0000000..4909eb1
--- /dev/null
+++ b/src/tss2-fapi/ifapi_eventlog.h
@@ -0,0 +1,101 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ *******************************************************************************/
+#ifndef IFAPI_EVENTLOG_H
+#define IFAPI_EVENTLOG_H
+
+#include <json-c/json.h>
+
+#include "tss2_tpm2_types.h"
+#include "ifapi_io.h"
+
+/** Type of event
+ */
+typedef UINT32 IFAPI_EVENT_TYPE;
+#define IFAPI_IMA_EVENT_TAG            1    /**< Tag for key resource */
+#define IFAPI_TSS_EVENT_TAG            2    /**< Tag for key resource */
+
+/** TSS event information
+ */
+typedef struct {
+    TPM2B_EVENT                                    data;    /**< The event data */
+    char                                         *event;    /**< TSS event information */
+} IFAPI_TSS_EVENT;
+
+/** IMA event information
+ */
+typedef struct {
+    TPM2B_DIGEST                              eventData;    /**< The ima event digest */
+    char                                     *eventName;    /**< IMA event information */
+} IFAPI_IMA_EVENT;
+
+/** Type for representing sub types of FAPI events
+ */
+typedef union {
+    IFAPI_TSS_EVENT                           tss_event;    /**< TSS event information */
+    IFAPI_IMA_EVENT                           ima_event;    /**< IMA event information */
+} IFAPI_EVENT_UNION;
+
+/** Type for representing a FAPI event
+ */
+typedef struct IFAPI_EVENT {
+    UINT32                                       recnum;    /**< Number of event */
+    TPM2_HANDLE                                     pcr;    /**< PCR register */
+    TPML_DIGEST_VALUES                          digests;    /**< The digest list of the event */
+    IFAPI_EVENT_TYPE                               type;    /**< Selector for object type */
+    IFAPI_EVENT_UNION                         sub_event;    /**< Additional event information */
+} IFAPI_EVENT;
+
+enum IFAPI_EVENTLOG_STATE {
+    IFAPI_EVENTLOG_STATE_INIT = 0,
+    IFAPI_EVENTLOG_STATE_READING,
+    IFAPI_EVENTLOG_STATE_APPENDING,
+    IFAPI_EVENTLOG_STATE_WRITING
+};
+
+typedef struct IFAPI_EVENTLOG {
+    enum IFAPI_EVENTLOG_STATE state;
+    char *log_dir;
+    struct IFAPI_EVENT event;
+    TPM2_HANDLE pcrList[TPM2_MAX_PCRS];
+    size_t pcrListSize;
+    size_t pcrListIdx;
+    json_object *log;
+} IFAPI_EVENTLOG;
+
+TSS2_RC
+ifapi_eventlog_initialize(
+    IFAPI_EVENTLOG *eventlog,
+    const char *log_dir);
+
+TSS2_RC
+ifapi_eventlog_get_async(
+    IFAPI_EVENTLOG *eventlog,
+    IFAPI_IO *io,
+    const TPM2_HANDLE *pcrList,
+    size_t pcrListSize);
+
+TSS2_RC
+ifapi_eventlog_get_finish(
+    IFAPI_EVENTLOG *eventlog,
+    IFAPI_IO *io,
+    char **log);
+
+TSS2_RC
+ifapi_eventlog_append_async(
+    IFAPI_EVENTLOG *eventlog,
+    IFAPI_IO *io,
+    const IFAPI_EVENT *event);
+
+TSS2_RC
+ifapi_eventlog_append_finish(
+    IFAPI_EVENTLOG *eventlog,
+    IFAPI_IO *io);
+
+void
+ifapi_cleanup_event(
+    IFAPI_EVENT * event);
+
+#endif /* IFAPI_EVENTLOG_H */
diff --git a/src/tss2-fapi/ifapi_get_intl_cert.c b/src/tss2-fapi/ifapi_get_intl_cert.c
new file mode 100644
index 0000000..8654a01
--- /dev/null
+++ b/src/tss2-fapi/ifapi_get_intl_cert.c
@@ -0,0 +1,315 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <curl/curl.h>
+#include <openssl/buffer.h>
+#include <openssl/evp.h>
+#include <openssl/sha.h>
+
+
+#include "fapi_crypto.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+typedef struct tpm_getekcertificate_ctx tpm_getekcertificate_ctx;
+struct tpm_getekcertificate_ctx {
+    char *ec_cert_path;
+    FILE *ec_cert_file_handle;
+    char *ek_server_addr;
+    unsigned int SSL_NO_VERIFY;
+    char *ek_path;
+    bool verbose;
+    bool is_tpm2_device_active;
+    TPM2B_PUBLIC *out_public;
+};
+
+static tpm_getekcertificate_ctx ctx = {
+    .is_tpm2_device_active = true,
+};
+
+static unsigned char *hash_ek_public(TPM2B_PUBLIC *ek_public) {
+
+    unsigned char *hash = (unsigned char*) malloc(SHA256_DIGEST_LENGTH);
+    if (!hash) {
+        LOG_ERROR("OOM");
+        return NULL;
+    }
+
+    SHA256_CTX sha256;
+    int is_success = SHA256_Init(&sha256);
+    if (!is_success) {
+        LOG_ERROR("SHA256_Init failed");
+        goto err;
+    }
+
+    switch (ek_public->publicArea.type) {
+    case TPM2_ALG_RSA:
+        is_success = SHA256_Update(&sha256,
+                ek_public->publicArea.unique.rsa.buffer,
+                ek_public->publicArea.unique.rsa.size);
+        if (!is_success) {
+            LOG_ERROR("SHA256_Update failed");
+            goto err;
+        }
+
+        if (ek_public->publicArea.parameters.rsaDetail.exponent != 0) {
+            LOG_ERROR("non-default exponents unsupported");
+            goto err;
+        }
+        BYTE buf[3] = { 0x1, 0x00, 0x01 }; // Exponent
+        is_success = SHA256_Update(&sha256, buf, sizeof(buf));
+        if (!is_success) {
+            LOG_ERROR("SHA256_Update failed");
+            goto err;
+        }
+        break;
+
+    case TPM2_ALG_ECC:
+        is_success = SHA256_Update(&sha256,
+                ek_public->publicArea.unique.ecc.x.buffer,
+                ek_public->publicArea.unique.ecc.x.size);
+        if (!is_success) {
+            LOG_ERROR("SHA256_Update failed");
+            goto err;
+        }
+
+        is_success = SHA256_Update(&sha256,
+                ek_public->publicArea.unique.ecc.y.buffer,
+                ek_public->publicArea.unique.ecc.y.size);
+        if (!is_success) {
+            LOG_ERROR("SHA256_Update failed");
+            goto err;
+        }
+        break;
+
+    default:
+        LOG_ERROR("unsupported EK algorithm");
+        goto err;
+    }
+
+    is_success = SHA256_Final(hash, &sha256);
+    if (!is_success) {
+        LOG_ERROR("SHA256_Final failed");
+        goto err;
+    }
+
+    LOG_TRACE("public-key-hash:");
+    LOG_TRACE("  sha256: ");
+    LOGBLOB_TRACE(&hash[0], SHA256_DIGEST_LENGTH, "Hash");
+    return hash;
+err:
+    free(hash);
+    return NULL;
+}
+
+char *base64_encode(const unsigned char* buffer)
+{
+    BIO *bio, *b64;
+    BUF_MEM *buffer_pointer;
+
+    LOG_INFO("Calculating the base64_encode of the hash of the Endorsement"
+             "Public Key:");
+
+    if (buffer == NULL) {
+        LOG_ERROR("hash_ek_public returned null");
+        return NULL;
+    }
+
+    b64 = BIO_new(BIO_f_base64());
+    bio = BIO_new(BIO_s_mem());
+    bio = BIO_push(b64, bio);
+    BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
+    BIO_write(bio, buffer, SHA256_DIGEST_LENGTH);
+    (void)(BIO_flush(bio));
+    BIO_get_mem_ptr(bio, &buffer_pointer);
+
+    /* these are not NULL terminated */
+    char *b64text = buffer_pointer->data;
+    size_t len = buffer_pointer->length;
+
+    size_t i;
+    for (i = 0; i < len; i++) {
+        if (b64text[i] == '+') {
+            b64text[i] = '-';
+        }
+        if (b64text[i] == '/') {
+            b64text[i] = '_';
+        }
+    }
+
+    char *final_string = NULL;
+
+    CURL *curl = curl_easy_init();
+    if (curl) {
+        char *output = curl_easy_escape(curl, b64text, len);
+        if (output) {
+            final_string = strdup(output);
+            curl_free(output);
+        }
+    }
+    curl_easy_cleanup(curl);
+    curl_global_cleanup();
+    BIO_free_all(bio);
+
+    /* format to a proper NULL terminated string */
+    return final_string;
+}
+
+struct CertificateBuffer {
+  unsigned char *buffer;
+  size_t size;
+};
+
+static size_t
+get_certificate_buffer_cb(void *contents, size_t size, size_t nmemb, void *userp)
+{
+  size_t realsize = size * nmemb;
+  struct CertificateBuffer *cert = (struct CertificateBuffer *)userp;
+
+  unsigned char *tmp_ptr = realloc(cert->buffer, cert->size + realsize + 1);
+  if(tmp_ptr == NULL) {
+      LOG_ERROR("Can't allocate memory in CURL callback.");
+    return 0;
+  }
+  cert->buffer = tmp_ptr;
+  memcpy(&(cert->buffer[cert->size]), contents, realsize);
+  cert->size += realsize;
+  cert->buffer[cert->size] = 0;
+
+  return realsize;
+}
+
+int retrieve_endorsement_certificate(char *b64h, unsigned char ** buffer,
+                                     size_t *cert_size) {
+    int ret = -1;
+
+    size_t len = 1 + strlen(b64h) + strlen(ctx.ek_server_addr);
+    struct CertificateBuffer cert_buffer = { .size = 0, .buffer = NULL };
+    char *weblink = (char *) malloc(len);
+
+    if (!weblink) {
+        LOG_ERROR("oom");
+        return ret;
+    }
+
+    snprintf(weblink, len, "%s%s", ctx.ek_server_addr, b64h);
+
+    CURLcode rc = curl_global_init(CURL_GLOBAL_DEFAULT);
+    if (rc != CURLE_OK) {
+        LOG_ERROR("curl_global_init failed: %s", curl_easy_strerror(rc));
+        goto out_memory;
+    }
+
+    CURL *curl = curl_easy_init();
+    if (!curl) {
+        LOG_ERROR("curl_easy_init failed");
+        goto out_global_cleanup;
+    }
+
+    /*
+     * should not be used - Used only on platforms with older CA certificates.
+     */
+    if (ctx.SSL_NO_VERIFY) {
+        rc = curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
+        if (rc != CURLE_OK) {
+            LOG_ERROR("curl_easy_setopt for CURLOPT_SSL_VERIFYPEER failed: %s",
+                    curl_easy_strerror(rc));
+            goto out_easy_cleanup;
+        }
+    }
+
+    rc = curl_easy_setopt(curl, CURLOPT_URL, weblink);
+    if (rc != CURLE_OK) {
+        LOG_ERROR("curl_easy_setopt for CURLOPT_URL failed: %s",
+                curl_easy_strerror(rc));
+        goto out_easy_cleanup;
+    }
+
+    rc =  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,
+                           get_certificate_buffer_cb);
+    if (rc != CURLE_OK) {
+        LOG_ERROR("curl_easy_setopt for CURLOPT_URL failed: %s",
+                curl_easy_strerror(rc));
+        goto out_easy_cleanup;
+    }
+
+    rc =  curl_easy_setopt(curl, CURLOPT_WRITEDATA,
+                          (void *)&cert_buffer);
+    if (rc != CURLE_OK) {
+        LOG_ERROR("curl_easy_setopt for CURLOPT_URL failed: %s",
+                curl_easy_strerror(rc));
+        goto out_easy_cleanup;
+    }
+
+    rc = curl_easy_perform(curl);
+    if (rc != CURLE_OK) {
+        LOG_ERROR("curl_easy_perform() failed: %s", curl_easy_strerror(rc));
+        goto out_easy_cleanup;
+    }
+
+    *buffer = cert_buffer.buffer;
+    *cert_size = cert_buffer.size;
+
+    ret = 0;
+
+out_easy_cleanup:
+    if (ret != 0)
+        free(cert_buffer.buffer);
+    curl_easy_cleanup(curl);
+out_global_cleanup:
+    curl_global_cleanup();
+out_memory:
+    free(weblink);
+
+    return ret;
+}
+
+/**
+ * Get INTEL certificate for EK
+ *
+ * @param[in] ek_public The out public data of the EK.
+ * @param[out] cert_buffer the der encoded certificate.
+ * @param[out] cert_size The size of the certificate buffer.
+ *
+ * @retval TSS2_RC_SUCCESS on succes.
+ * @retval TSS2_FAPI_RC_NO_CERT If an error did occur during certificate downloading.
+ */
+TSS2_RC
+ifapi_get_intl_ek_certificate(TPM2B_PUBLIC *ek_public, unsigned char ** cert_buffer,
+                            size_t *cert_size)
+{
+    int rc = 1;
+    unsigned char *hash = hash_ek_public(ek_public);
+    char *b64 = base64_encode(hash);
+    if (!b64) {
+        LOG_ERROR("base64_encode returned null");
+        goto out;
+    }
+    // TODO check whether appropriate or store addess in profile and use value from profile
+    ctx.ek_server_addr = "https://ekop.intel.com/ekcertservice/";
+
+    LOG_INFO("%s", b64);
+
+    rc = retrieve_endorsement_certificate(b64, cert_buffer, cert_size);
+    free(b64);
+out:
+    /* In some case this call was necessary after curl usage */
+    OpenSSL_add_all_algorithms();
+
+    free(hash);
+    if (rc == 0) {
+        return TSS2_RC_SUCCESS;
+    } else {
+        LOG_ERROR("Get INTEL EK certificate.");
+        return TSS2_FAPI_RC_NO_CERT;
+    }
+}
diff --git a/src/tss2-fapi/ifapi_get_intl_cert.h b/src/tss2-fapi/ifapi_get_intl_cert.h
new file mode 100644
index 0000000..c0c5a90
--- /dev/null
+++ b/src/tss2-fapi/ifapi_get_intl_cert.h
@@ -0,0 +1,14 @@
+/*******************************************************************************
+ * Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ ******************************************************************************/
+#ifndef IFAPI_GET_INTL_CERT_H
+#define IFAPI_GET_INTL_CERT_H
+
+TSS2_RC
+ifapi_get_intl_ek_certificate(
+    TPM2B_PUBLIC *ek_public,
+    unsigned char ** buffer,
+    size_t *cert_size);
+
+#endif /* IFAPI_GET_INTL_CERT_H */
diff --git a/src/tss2-fapi/ifapi_helpers.c b/src/tss2-fapi/ifapi_helpers.c
new file mode 100644
index 0000000..2514369
--- /dev/null
+++ b/src/tss2-fapi/ifapi_helpers.c
@@ -0,0 +1,2090 @@
+/* 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 <stdarg.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <dirent.h>
+
+#include "tss2_mu.h"
+#include "fapi_util.h"
+#include "fapi_policy.h"
+#include "fapi_crypto.h"
+#include "ifapi_helpers.h"
+#include "ifapi_json_serialize.h"
+#include "ifapi_json_deserialize.h"
+#include "tpm_json_deserialize.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+/** Create template for key creation based on type flags.
+ *
+ * @param[in] type The flags describing the key type.
+ * @param[in] policy The flag whether a policy is used.
+ * @param[out] template The template including the TPM2B_PUBLIC which will
+ *             be used for key creation.
+ * @retval TSS2_RC_SUCCESS if the template can be generated.
+ * @retval TSS2_FAPI_RC_BAD_VALUE If an invalid combination of flags was used.
+ */
+TSS2_RC
+ifapi_set_key_flags(const char *type, bool policy, IFAPI_KEY_TEMPLATE *template)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    char *type_dup = NULL;
+    TPMA_OBJECT attributes = 0;
+    UINT32 handle;
+    int pos;
+    bool exportable = false;
+
+    memset(template, 0, sizeof(IFAPI_KEY_TEMPLATE));
+    type_dup = strdup(type);
+    return_if_null(type_dup, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+    char *flag = strtok(type_dup, ", ");
+
+    /* The default store will be the user directory */
+    template->system = TPM2_NO;
+
+    /* Loop over all comma or space separated flags */
+    while (flag != NULL) {
+        if (strcasecmp(flag, "system") == 0) {
+            template->system = TPM2_YES;
+        } else if (strcasecmp(flag, "sign") == 0) {
+            attributes |= TPMA_OBJECT_SIGN_ENCRYPT;
+        } else if (strcasecmp(flag, "decrypt") == 0) {
+            attributes |= TPMA_OBJECT_DECRYPT;
+        } else if (strcasecmp(flag, "restricted") == 0) {
+            attributes |= TPMA_OBJECT_RESTRICTED;
+        } else if (strcasecmp(flag, "exportable") == 0) {
+            /* TPMA_OBJECT_ENCRYPTEDDUPLICATION will not be set because no inner
+               symmetric encryption will be used */
+            exportable = true;
+        } else if (strcasecmp(flag, "noda") == 0) {
+            attributes |= TPMA_OBJECT_NODA;
+        } else if (strncmp(flag, "0x", 2) == 0) {
+            sscanf(&flag[2], "%"SCNx32 "%n", &handle, &pos);
+            if ((size_t)pos != strlen(flag) - 2) {
+                goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Invalid flag: %s",
+                           error, flag);
+            }
+            template->persistent_handle = handle;
+            template->persistent = TPM2_YES;
+        } else {
+            goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Invalid flag: %s",
+                       error, flag);
+        }
+        flag = strtok(NULL, " ,");
+    }
+    if (exportable) {
+        /* Clear flags preventing duplication */
+        attributes &= ~TPMA_OBJECT_FIXEDTPM;
+        attributes &= ~TPMA_OBJECT_FIXEDPARENT;
+    } else {
+        attributes |= TPMA_OBJECT_FIXEDTPM;
+        attributes |= TPMA_OBJECT_FIXEDPARENT;
+    }
+    /* Set default flags */
+    attributes |= TPMA_OBJECT_SENSITIVEDATAORIGIN;
+    if (!policy)
+        attributes |= TPMA_OBJECT_USERWITHAUTH;
+    else
+        attributes |= TPMA_OBJECT_ADMINWITHPOLICY;
+
+    /* Check whether flags are appropriate */
+    if (attributes & TPMA_OBJECT_RESTRICTED &&
+            attributes & TPMA_OBJECT_SIGN_ENCRYPT &&
+            attributes & TPMA_OBJECT_DECRYPT) {
+        goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
+                   "Exactly either sign or decrypt must be set.",
+                   error);
+    }
+
+    template->public.publicArea.objectAttributes = attributes;
+    SAFE_FREE(type_dup);
+    return TSS2_RC_SUCCESS;
+
+error:
+    SAFE_FREE(type_dup);
+    return r;
+}
+
+/** Create template for nv object  creation based on type flags.
+ */
+TSS2_RC
+ifapi_set_nv_flags(const char *type, IFAPI_NV_TEMPLATE *template,
+                   const char *policy)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    char *type_dup = NULL;
+    TPMA_NV attributes = 0;
+    UINT32 handle;
+    int pos;
+    UINT32 size = 0;
+    size_t type_count = 0;
+
+    memset(template, 0, sizeof(IFAPI_NV_TEMPLATE));
+    type_dup = strdup(type);
+    return_if_null(type_dup, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+    /* The default store will be the user directory */
+    template->system = TPM2_NO;
+
+    char *flag = strtok(type_dup, ", ");
+
+    /* Loop over all comma or space separated flags */
+    while (flag != NULL) {
+        if (strcasecmp(flag, "system") == 0) {
+            template->system = TPM2_YES;
+        } else if (strcasecmp(flag, "bitfield") == 0) {
+            attributes |=  TPM2_NT_BITS << TPMA_NV_TPM2_NT_SHIFT;
+            type_count += 1;
+        } else if (strcasecmp(flag, "counter") == 0) {
+            attributes |=  TPM2_NT_COUNTER << TPMA_NV_TPM2_NT_SHIFT;
+            type_count += 1;
+        } else if (strcasecmp(flag, "pcr") == 0) {
+            attributes |=  TPM2_NT_EXTEND << TPMA_NV_TPM2_NT_SHIFT;
+            type_count += 1;
+        } else if (strcasecmp(flag, "noda") == 0) {
+            attributes |= TPMA_NV_NO_DA;
+        } else if (strncmp(flag, "0x", 2) == 0) {
+            sscanf(&flag[2], "%"SCNx32 "%n", &handle, &pos);
+            if ((size_t)pos != strlen(flag) - 2) {
+                goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Invalid flag: %s",
+                           error, flag);
+            }
+            template->public.nvIndex = handle;
+        } else {
+            goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Invalid flag: %s",
+                       error, flag);
+        }
+        flag = strtok(NULL, " ,");
+    }
+    if (type_count > 1) {
+        goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
+                   "Only one type of NV object can be set.", error);
+    }
+    if (type_count == 0) {
+        /* Normal NV space will be defined */
+        attributes |=  TPM2_NT_ORDINARY << TPMA_NV_TPM2_NT_SHIFT;
+        if (size == 0)
+            size = 64;
+    }
+    /* If type extend is used the size will be set during the merging of the crypto
+       profile depending on the nameHashAlg stored in the profile.
+       The size of counter and bitfield will be determined by the TPM. */
+
+    if (policy && strlen(policy) > 0) {
+        attributes |= TPMA_NV_POLICYWRITE;
+        attributes |= TPMA_NV_POLICYREAD;
+    } else {
+        attributes |= TPMA_NV_AUTHREAD;
+        attributes |= TPMA_NV_AUTHWRITE;
+    }
+
+    attributes |= TPMA_NV_READ_STCLEAR;
+    attributes |= TPMA_NV_WRITE_STCLEAR;
+    template->public.attributes = attributes;
+    template->hierarchy = TPM2_RH_OWNER;
+    template->public.dataSize = size;
+
+    SAFE_FREE(type_dup);
+    return TSS2_RC_SUCCESS;
+
+error:
+    SAFE_FREE(type_dup);
+    return r;
+}
+
+/**
+ * Determine whether path describes a NV object
+ * @param[in] path:
+ */
+bool
+ifapi_path_type_p(const char *path, const char *type)
+{
+    size_t pos = 0;
+    char *end;
+    int end_pos;
+
+    if (strncmp("/", path, 1) == 0)
+        pos = 1;
+    if (strcmp(&path[pos], type) == 0)
+        return true;
+
+    end = strchr(&path[pos], IFAPI_FILE_DELIM_CHAR);
+    if (!end)
+        return false;
+    end_pos = (int)(end - path);
+    if (strlen(path) - pos > 3 &&
+            strncasecmp(type, &path[pos], strlen(type)) == 0 && end &&
+            strncmp(IFAPI_FILE_DELIM, &path[end_pos], 1) == 0)
+        return true;
+    return false;
+}
+
+/**
+ * Get ESYS handle for a hierarchy.
+ * @param[in] path:
+ */
+ESYS_TR
+ifapi_get_hierary_handle(const char *path)
+{
+    int pos = 0;
+
+    if (strncmp("/", path, 1) == 0)
+        pos = 1;
+    if (strcmp(&path[pos], "HE") == 0) {
+        return ESYS_TR_RH_ENDORSEMENT;
+    }
+    if (strcmp(&path[pos], "HS") == 0) {
+        return ESYS_TR_RH_OWNER;
+    }
+    if (strcmp(&path[pos], "LOCKOUT") == 0) {
+        return ESYS_TR_RH_LOCKOUT;
+    }
+    return 0;
+}
+
+/**
+ * Determine whether path describes a hierarchy object
+ * @param[in] path:
+ */
+bool
+ifapi_hierarchy_path_p(const char *path)
+{
+    size_t pos1 = 0;
+    size_t pos2 = 0;
+    char *start;
+
+    if (strncmp("/", path, 1) == 0)
+        pos1 = 1;
+    /* Skip profile if it does exist in path */
+    if (strncmp("P_", &path[pos1], 2) == 0) {
+        start = strchr(&path[pos1], IFAPI_FILE_DELIM_CHAR);
+        if (start) {
+            pos2 = (int)(start - &path[pos1]);
+            if (strncmp("/", &path[pos2], 1) == 0)
+                pos2 += 1;
+            if (strncmp("/", &path[pos2], 1) == 0)
+                pos2 += 1;
+        }
+    }
+    /* Check whether only hierarchy is specified in path */
+    if ((strncasecmp(&path[pos1 + pos2], "HS", 2) == 0 ||
+         strncasecmp(&path[pos1 + pos2], "HE", 2) == 0 ||
+         strncasecmp(&path[pos1 + pos2], "HE", 2) == 0 ||
+         strncasecmp(&path[pos1 + pos2], "HP", 2) == 0 ||
+         strncasecmp(&path[pos1 + pos2], "HN", 2) == 0 ||
+         strncasecmp(&path[pos1 + pos2], "HP", 2) == 0)
+        && (strlen(path) == pos1 + pos2 + 2 ||
+            (strlen(path) == pos1 + pos2 + 3 &&
+             path[pos1 + pos2 + 2] == IFAPI_FILE_DELIM_CHAR))){
+        return true;
+    } else if (strncasecmp(&path[pos1 + pos2], "LOCKOUT", 7) == 0
+               && (strlen(path) == pos1 + pos2 + 7 ||
+                   (strlen(path) == pos1 + pos2 + 8 &&
+                    path[pos1 + pos2 + 7] == IFAPI_FILE_DELIM_CHAR))) {
+        return true;
+    }
+    return false;
+}
+
+/**
+ * Compare two variables of type TPM2B_ECC_PARAMETER.
+ * @param[in] in1 variable to be compared with:
+ * @param[in] in2
+ */
+bool
+ifapi_TPM2B_ECC_PARAMETER_cmp(TPM2B_ECC_PARAMETER *in1,
+                              TPM2B_ECC_PARAMETER *in2)
+{
+
+    if (in1->size != in2->size)
+        return false;
+
+    return memcmp(&in1->buffer[0], &in2->buffer[0], in1->size) == 0;
+}
+
+/**
+ * Compare two variables of type TPMS_ECC_POINT.
+ * @param[in] in1 variable to be compared with:
+ * @param[in] in2
+ */
+bool
+ifapi_TPMS_ECC_POINT_cmp(TPMS_ECC_POINT *in1, TPMS_ECC_POINT *in2)
+{
+    LOG_TRACE("call");
+
+    if (!ifapi_TPM2B_ECC_PARAMETER_cmp(&in1->x, &in2->x))
+        return false;
+
+    if (!ifapi_TPM2B_ECC_PARAMETER_cmp(&in1->y, &in2->y))
+        return false;
+
+    return true;
+}
+
+/**  Compare two variables of type TPM2B_DIGEST.
+ *
+ * @param[in] in1 variable to be compared with:
+ * @param[in] in2
+ */
+bool
+ifapi_TPM2B_DIGEST_cmp(TPM2B_DIGEST *in1, TPM2B_DIGEST *in2)
+{
+
+    if (in1->size != in2->size)
+        return false;
+
+    return memcmp(&in1->buffer[0], &in2->buffer[0], in1->size) == 0;
+}
+
+/** Compare two variables of type TPM2B_PUBLIC_KEY_RSA.
+ *
+ * @param[in] in1 variable to be compared with:
+ * @param[in] in2
+ */
+bool
+ifapi_TPM2B_PUBLIC_KEY_RSA_cmp(TPM2B_PUBLIC_KEY_RSA *in1,
+                               TPM2B_PUBLIC_KEY_RSA *in2)
+{
+
+    if (in1->size != in2->size)
+        return false;
+
+    return memcmp(&in1->buffer[0], &in2->buffer[0], in1->size) == 0;
+}
+
+/**  Compare two variables of type TPMU_PUBLIC_ID.
+ *
+ * @param[in] in1 variable to be compared.
+ * @parma[in] selector1 key type of first key.
+ * @param[in] in2  variable to be compared.
+ * @param[in] selector2 key type of second key.
+ * @result true if variables are equal
+ */
+bool
+ifapi_TPMU_PUBLIC_ID_cmp(TPMU_PUBLIC_ID *in1, UINT32 selector1,
+                         TPMU_PUBLIC_ID *in2, UINT32 selector2)
+{
+
+    if (selector1 != selector2)
+        return false;
+
+    switch (selector1) {
+    case TPM2_ALG_KEYEDHASH:
+        if (!ifapi_TPM2B_DIGEST_cmp(&in1->keyedHash, &in2->keyedHash))
+            return false;
+        break;
+    case TPM2_ALG_SYMCIPHER:
+        if (!ifapi_TPM2B_DIGEST_cmp(&in1->sym, &in2->sym))
+            return false;
+        break;
+    case TPM2_ALG_RSA:
+        if (!ifapi_TPM2B_PUBLIC_KEY_RSA_cmp(&in1->rsa, &in2->rsa))
+            return false;
+        break;
+    case TPM2_ALG_ECC:
+        if (!ifapi_TPMS_ECC_POINT_cmp(&in1->ecc, &in2->ecc))
+            return false;
+        break;
+    default:
+        return false;
+    };
+    return true;
+}
+
+/**
+ * Compare the PUBLIC_ID stored in two  TPMT_PUBLIC structures.
+ * @param[in] in1 variable to be compared with:
+ * @param[in] in2
+ */
+bool
+ifapi_TPMT_PUBLIC_cmp(TPMT_PUBLIC *in1, TPMT_PUBLIC *in2)
+{
+
+    if (!ifapi_TPMU_PUBLIC_ID_cmp(&in1->unique, in1->type, &in2->unique, in2->type))
+        return false;
+
+    return true;
+}
+
+int
+vasprintf(char **str, const char *fmt, va_list args)
+{
+    int size = 0;
+    va_list tmpa;
+    char *dmy = NULL;
+    va_copy(tmpa, args);
+    size = vsnprintf(dmy, size, fmt, tmpa);
+    va_end(tmpa);
+    if (size < 0) {
+        return -1;
+    }
+    *str = (char *) malloc(size + 1);
+    if (NULL == *str) {
+        return -1;
+    }
+    size = vsprintf(*str, fmt, args);
+    return size;
+}
+
+TSS2_RC
+ifapi_asprintf(char **str, const char *fmt, ...)
+{
+    int size = 0;
+    va_list args;
+    va_start(args, fmt);
+    size = vasprintf(str, fmt, args);
+    va_end(args);
+    if (size == -1)
+        return TSS2_FAPI_RC_MEMORY;
+    return TSS2_RC_SUCCESS;
+}
+
+/** Divides str into substrings based on a delimiter.
+ *
+ * @param[in] string the string to split.
+ * @param[in] delimiter the delimiter.
+ * @retval The linked list of substrings.
+ */
+NODE_STR_T *
+split_string(const char *string, char *delimiter)
+{
+    NODE_STR_T *node = NULL;
+    NODE_STR_T *start_node = NULL;
+    char *strtok_save = NULL;
+    char *stringdup = NULL;
+    char *substr = NULL;
+    if (string == NULL)
+        return NULL;
+
+    stringdup = strdup(string);
+    if (stringdup == NULL) {
+        LOG_ERROR("%s", "Out of memory.");
+        goto error_cleanup;
+    }
+    char * stringdup_tokenized = strtok_r(stringdup, delimiter, &strtok_save);
+    if (stringdup_tokenized != NULL) {
+        substr = strdup(stringdup_tokenized);
+    } else {
+        substr = strdup(stringdup);
+    }
+    if (substr == NULL) {
+        LOG_ERROR("%s", "Out of memory.");
+        goto error_cleanup;
+    }
+    do {
+        if (node == NULL) {
+            node = malloc(sizeof(NODE_STR_T));
+            if(node == NULL) {
+                LOG_ERROR("%s", "Out of memory.");
+                goto error_cleanup;
+            }
+            node->next = NULL;
+            node->free_string = true;
+            start_node = node;
+        } else {
+            node->next = malloc(sizeof(NODE_STR_T));
+            if(node->next == NULL) {
+                LOG_ERROR("%s", "Out of memory.");
+                goto error_cleanup;
+            }
+            node = node->next;
+            node->next = NULL;
+            node->free_string = true;
+        }
+        node->str = substr;
+        substr = strtok_r(NULL, delimiter, &strtok_save);
+        if (substr) {
+            substr = strdup(substr);
+            if (substr == NULL) {
+                LOG_ERROR("%s", "Out of memory.");
+                goto error_cleanup;
+            }
+        }
+    } while (substr != NULL);
+
+    SAFE_FREE(stringdup);
+    return start_node;
+error_cleanup:
+    SAFE_FREE(start_node);
+    SAFE_FREE(substr);
+    SAFE_FREE(stringdup);
+    return NULL;
+}
+
+/** Free linked list of strings.
+ *
+ * @param[in] node the first node of the linked list.
+ */
+void
+free_string_list(NODE_STR_T *node)
+{
+    NODE_STR_T *next;
+    if (node == NULL)
+        return;
+    while (node != NULL) {
+        if (node->free_string)
+            free(node->str);
+        next = node->next;
+        free(node);
+        node = next;
+    }
+}
+
+/** Free linked list of IFAPI objects.
+ *
+ * @param[in] node the first node of the linked list.
+ */
+void
+ifapi_free_object_list(NODE_OBJECT_T *node)
+{
+    NODE_OBJECT_T *next;
+    if (node == NULL)
+        return;
+    while (node != NULL) {
+        ifapi_cleanup_ifapi_object((IFAPI_OBJECT *)node->object);
+        SAFE_FREE(node->object);
+        next = node->next;
+        free(node);
+        node = next;
+    }
+}
+
+/** Free linked list of IFAPI objects (link nodes only).
+ *
+ * @param[in] node the first node of the linked list.
+ */
+void
+ifapi_free_node_list(NODE_OBJECT_T *node)
+{
+    NODE_OBJECT_T *next;
+    if (node == NULL)
+        return;
+    while (node != NULL) {
+        next = node->next;
+        free(node);
+        node = next;
+    }
+}
+
+
+/** Compute the number on nodes in a linked list.
+ *
+ * @param[in] node the first node of the linked list.
+ * @retval the number on nodes.
+ */
+size_t
+ifapi_path_length(NODE_STR_T *node)
+{
+    size_t length = 0;
+    if (node == NULL)
+        return 0;
+    while (node != NULL) {
+        length += 1;
+        node = node->next;
+    }
+    return length;
+}
+
+/** Compute the size of a concatenated string.
+ *
+ * @param[in] node the first node of the linked string list.
+ * @param[in] delim_length the size of the delimiter used for the concatenation.
+ * @retval the size of the string.
+ */
+size_t
+path_str_length(NODE_STR_T *node, int delim_length)
+{
+    size_t size = 0;
+    if (node == NULL)
+        return 0;
+    while (node != NULL) {
+        size += strlen(node->str);
+        if (node->next != NULL)
+            size = size + delim_length;
+        node = node->next;
+    }
+    return size;
+}
+
+/** Compute a pathname based on a linked list of strings.
+ *
+ * @param[out] dest the pointer to the pathname (callee allocated).
+ * @param[in]  supdir a sup directory will be the prefix of the pathname.
+ * @param[in]  delim  the delimiter which will be used for concatenation.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY if the memory for the pathname can't be allocated.
+ */
+TSS2_RC
+ifapi_path_string(char **dest, const char *supdir, NODE_STR_T *node, char *name)
+{
+    size_t length = 1 + path_str_length(node,
+                                        1) + ((supdir == NULL) ? 0 : strlen(supdir) + 1)
+                    + ((name == NULL) ? 0 : strlen(name) + 1);
+    *dest = malloc(length);
+    if (*dest == NULL) {
+        LOG_ERROR("Out of memory");
+        return  TSS2_FAPI_RC_MEMORY;
+    }
+    *dest[0] = '\0';
+    if (supdir != NULL) {
+        strcat(*dest, supdir);
+        strcat(*dest, IFAPI_FILE_DELIM);
+    }
+    for (; node != NULL; node = node->next) {
+        strcat(*dest, node->str);
+        if (node->next != NULL) {
+            strcat(*dest, IFAPI_FILE_DELIM);
+        }
+    }
+    if (name != NULL) {
+        strcat(*dest, IFAPI_FILE_DELIM);
+        strcat(*dest, name);
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+
+/** Compute a pathname based on the first n elements of a linked list of strings.
+ *
+ * @param[out] dest the pointer to the pathname (callee allocated).
+ * @param[in]  supdir a sup directory will be the prefix of the pathname.
+ *                    (can be NULL).
+ * @param[in]  name  the filename (can be NULL).
+ * @param[in]  delim  the delimiter which will be used for concatenation.
+ * @param[in]  n the number of the first elements which will bes used for concatenation.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY if the memory for the pathname can't be allocated.
+ */
+TSS2_RC
+ifapi_path_string_n(char **dest, const char *supdir, NODE_STR_T *node, char *name,
+                    size_t n)
+{
+    size_t length = 1 + path_str_length(node,
+                                        1) + ((supdir == NULL) ? 0 : strlen(supdir) + 1)
+                    + ((name == NULL) ? 0 : strlen(name) + 1);
+    *dest = malloc(length);
+    size_t i;
+    if (*dest == NULL) {
+        LOG_ERROR("Out of memory");
+        return  TSS2_FAPI_RC_MEMORY;
+    }
+    *dest[0] = '\0';
+    if (supdir != NULL) {
+        strcat(*dest, supdir);
+        strcat(*dest, IFAPI_FILE_DELIM);
+    }
+    for (i = 1; node != NULL && i <= n; i++, node = node->next) {
+        strcat(*dest, node->str);
+        if (node->next != NULL) {
+            strcat(*dest, IFAPI_FILE_DELIM);
+        }
+    }
+    if (name != NULL) {
+        strcat(*dest, IFAPI_FILE_DELIM);
+        strcat(*dest, name);
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+NODE_STR_T *
+init_string_list(const char *string)
+{
+    NODE_STR_T *result = malloc(sizeof(NODE_STR_T));
+    if (result == NULL)
+        return NULL;
+    result->next = NULL;
+    result->str = strdup(string);
+    if (result->str == NULL) {
+        LOG_ERROR("Out of memory");
+        free(result);
+        return NULL;
+    }
+    result->free_string = true;
+    return result;
+}
+
+bool
+add_string_to_list(NODE_STR_T *str_list, char *string)
+{
+    if (str_list == NULL)
+        return NULL;
+    NODE_STR_T *last = malloc(sizeof(NODE_STR_T));
+    if (last == NULL)
+        return false;
+    while (str_list->next != NULL)
+        str_list = str_list->next;
+    str_list->next = last;
+    last->next = NULL;
+    last->str = strdup(string);
+    return_if_null(last->str, "Out of memory.", false);
+    last->free_string = true;
+    return true;
+}
+
+TSS2_RC
+push_object_to_list(void *object, NODE_OBJECT_T **object_list)
+{
+    NODE_OBJECT_T *first = calloc(1, sizeof(NODE_OBJECT_T));
+    return_if_null(first, "Out of space.", TSS2_FAPI_RC_MEMORY);
+    first->object = object;
+    if (*object_list)
+        first->next = *object_list;
+    *object_list = first;
+    return TSS2_RC_SUCCESS;
+}
+
+TSS2_RC
+append_object_to_list(void *object, NODE_OBJECT_T **object_list)
+{
+    NODE_OBJECT_T *list, *last = calloc(1, sizeof(NODE_OBJECT_T));
+    return_if_null(last, "Out of space.", TSS2_FAPI_RC_MEMORY);
+    last->object = object;
+    if (!*object_list) {
+        *object_list = last;
+        return TSS2_RC_SUCCESS;
+    }
+    list = *object_list;
+    while (list->next)
+        list = list->next;
+    list->next = last;
+    return TSS2_RC_SUCCESS;
+}
+
+TSS2_RC
+push_object_with_size_to_list(void *object, size_t size, NODE_OBJECT_T **object_list)
+{
+    TSS2_RC r;
+    r = push_object_to_list(object, object_list);
+    return_if_error(r, "Push object with size.");
+
+    (*object_list)->size = size;
+    return TSS2_RC_SUCCESS;
+}
+
+void
+ifapi_init_hierarchy_object(
+    IFAPI_OBJECT *hierarchy,
+    ESYS_TR esys_handle)
+{
+    memset(hierarchy, 0, sizeof(IFAPI_OBJECT));
+    hierarchy->system = TPM2_YES;
+    hierarchy->objectType = IFAPI_HIERARCHY_OBJ;
+    hierarchy->handle = esys_handle;
+}
+
+char *
+get_description(IFAPI_OBJECT *object)
+{
+    switch (object->objectType) {
+    case IFAPI_KEY_OBJ:
+        return object->misc.key.description;
+    case IFAPI_NV_OBJ:
+        return object->misc.nv.description;
+    default:
+        return NULL;
+    }
+}
+
+TSS2_RC
+create_dirs(const char *supdir, NODE_STR_T *dir_list, mode_t mode)
+{
+    char *new_dir;
+    for (size_t i = 1; i <= ifapi_path_length(dir_list); i++) {
+        TSS2_RC r =  ifapi_path_string_n(&new_dir, supdir, dir_list, NULL, i);
+        return_if_error(r, "Create path string");
+        struct stat buffer;
+        LOG_TRACE("Check file: %s", new_dir);
+        if (stat(new_dir, &buffer) != 0) {
+            int rc = mkdir(new_dir, mode);
+            if (rc != 0) {
+                LOG_ERROR("mkdir not possible: %i %s", rc, new_dir);
+                free(new_dir);
+                return TSS2_FAPI_RC_BAD_VALUE;
+            }
+        }
+        free(new_dir);
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+TSS2_RC
+ifapi_create_dirs(const char *supdir, const char *path)
+{
+    TSS2_RC r;
+    NODE_STR_T *path_list = split_string(path, IFAPI_FILE_DELIM);
+    return_if_null(path_list, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+    r = create_dirs(supdir, path_list, 0777);
+    goto_if_error2(r, "Create directories for %s", error_cleanup, path);
+    free_string_list(path_list);
+    return TSS2_RC_SUCCESS;
+
+error_cleanup:
+    free_string_list(path_list);
+    return r;
+}
+
+TSS2_RC
+init_explicit_key_path(
+    const char *context_profile,
+    const char *ipath,
+    NODE_STR_T **list_node1,
+    NODE_STR_T **current_list_node,
+    NODE_STR_T **result)
+{
+    *list_node1 = split_string(ipath, IFAPI_FILE_DELIM);
+    NODE_STR_T *list_node = *list_node1;
+    char const *profile;
+    char *hierarchy;
+    TSS2_RC r = TSS2_RC_SUCCESS;
+
+    *result = NULL;
+    if (list_node == NULL) {
+        LOG_ERROR("Invalid path");
+        free_string_list(*list_node1);
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    if (strncmp("P_", list_node->str, 2) == 0) {
+        profile = list_node->str;
+        list_node = list_node->next;
+    } else {
+        profile = context_profile;
+    }
+    *result = init_string_list(profile);
+    if (result == NULL) {
+        free_string_list(*list_node1);
+        LOG_ERROR("Out of memory");
+        return  TSS2_FAPI_RC_MEMORY;
+    }
+    if (list_node == NULL) {
+        hierarchy = "HS";
+    } else {
+        if (strcmp(list_node->str, "HS") == 0 ||
+                strcmp(list_node->str, "HE") == 0 ||
+                strcmp(list_node->str, "HP") == 0 ||
+                strcmp(list_node->str, "HN") == 0 ||
+                strcmp(list_node->str, "HP") == 0) {
+            hierarchy = list_node->str;
+            list_node = list_node->next;
+        } else if (strcmp(list_node->str, "EK") == 0) {
+            hierarchy = "HE";
+        } else if (list_node->next != NULL &&
+                   (strcmp(list_node->str, "SRK") == 0 ||
+                    strcmp(list_node->str, "SDK") == 0 ||
+                    strcmp(list_node->str, "UNK") == 0 ||
+                    strcmp(list_node->str, "UDK") == 0)) {
+            hierarchy = "HS";
+        } else {
+            hierarchy = "HS";
+        }
+    }
+    if (!add_string_to_list(*result, hierarchy)) {
+        LOG_ERROR("Out of memory");
+        r =  TSS2_FAPI_RC_MEMORY;
+        goto error;
+    }
+    if (list_node == NULL) {
+        goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Explicit path can't be determined.",
+                   error);
+    }
+    if (!add_string_to_list(*result, list_node->str)) {
+        LOG_ERROR("Out of memory");
+        r = TSS2_FAPI_RC_MEMORY;
+        goto error;
+    }
+    *current_list_node = list_node->next;
+    return TSS2_RC_SUCCESS;
+
+error:
+    free_string_list(*result);
+    *result = NULL;
+    free_string_list(*list_node1);
+    *list_node1 = NULL;
+    return r;
+}
+
+size_t
+policy_digest_size(IFAPI_OBJECT *object)
+{
+    switch (object->objectType) {
+    case IFAPI_KEY_OBJ:
+        return object->misc.key.public.publicArea.authPolicy.size;
+    case IFAPI_NV_OBJ:
+        return object->misc.nv.public.nvPublic.authPolicy.size;
+    case IFAPI_HIERARCHY_OBJ:
+        return object->misc.hierarchy.authPolicy.size;
+    default:
+        return 0;
+    }
+}
+
+bool
+object_with_auth(IFAPI_OBJECT *object)
+{
+    switch (object->objectType) {
+    case IFAPI_KEY_OBJ:
+        return (object->misc.key.with_auth == TPM2_YES);
+    case IFAPI_NV_OBJ:
+        return (object->misc.nv.with_auth == TPM2_YES);
+    case IFAPI_HIERARCHY_OBJ:
+        return (object->misc.hierarchy.with_auth == TPM2_YES);
+    default:
+        return false;
+    }
+}
+
+static void
+cleanup_policy_element(TPMT_POLICYELEMENT *policy)
+{
+        switch (policy->type) {
+        case POLICYSECRET:
+            SAFE_FREE(policy->element.PolicySecret.objectPath);
+            break;
+        case POLICYAUTHORIZE:
+            SAFE_FREE(policy->element.PolicyAuthorize.keyPath);
+            SAFE_FREE(policy->element.PolicyAuthorize.keyPEM);
+            break;
+        case POLICYAUTHORIZENV:
+            SAFE_FREE( policy->element.PolicyAuthorizeNv.nvPath);
+            SAFE_FREE( policy->element.PolicyAuthorizeNv.policy_buffer);
+            break;
+        case POLICYSIGNED:
+            SAFE_FREE(policy->element.PolicySigned.keyPath);
+            SAFE_FREE(policy->element.PolicySigned.keyPEM);
+            break;
+        case POLICYPCR:
+            SAFE_FREE(policy->element.PolicyPCR.pcrs);
+            break;
+        case POLICYNV:
+            SAFE_FREE(policy->element.PolicyNV.nvPath);
+            break;
+        case POLICYDUPLICATIONSELECT:
+            SAFE_FREE(policy->element.PolicyDuplicationSelect.newParentPath);
+            break;
+        case POLICYNAMEHASH:
+            for (size_t i = 0; i < 3; i++) {
+                SAFE_FREE(policy->element.PolicyNameHash.namePaths[i]);
+            }
+        }
+}
+
+static void cleanup_policy_elements(TPML_POLICYELEMENTS *policy)
+{
+    size_t i, j;
+    if (policy != NULL) {
+        for (i = 0; i < policy->count; i++) {
+            if (policy->elements[i].type ==  POLICYOR) {
+                /* Policy with sub policies */
+                TPML_POLICYBRANCHES *branches = policy->elements[i].element.PolicyOr.branches;
+                for (j = 0; j < branches->count; j++) {
+                    SAFE_FREE(branches->authorizations[j].name);
+                    SAFE_FREE(branches->authorizations[j].description);
+                    cleanup_policy_elements(branches->authorizations[j].policy);
+                }
+                SAFE_FREE(branches);
+            } else {
+                cleanup_policy_element(&policy->elements[i]);
+            }
+        }
+        SAFE_FREE(policy);
+    }
+}
+
+/** Free memory allocated during deserialization of policy.
+ *
+ * The object will not be freed (might be declared on the stack).
+ *
+ * @param[in]  object The policy to be cleaned up.
+ *
+ */
+void ifapi_cleanup_policy_harness(TPMS_POLICY_HARNESS *harness)
+{
+    if (harness) {
+       SAFE_FREE(harness->description);
+       if (harness->policyAuthorizations) {
+          for (size_t i = 0; i < harness->policyAuthorizations->count; i++) {
+              SAFE_FREE(harness->policyAuthorizations->
+                      authorizations[i].type);
+          }
+       }
+       SAFE_FREE(harness->policyAuthorizations);
+       cleanup_policy_elements(harness->policy);
+    }
+}
+
+static void cleanup_policy_object(POLICY_OBJECT * object) {
+    if (object != NULL) {
+        SAFE_FREE(object->path);
+        ifapi_cleanup_policy_harness(&object->policy);
+        cleanup_policy_object(object->next);
+    }
+}
+
+static TPML_POLICYELEMENTS *
+copy_policy_elements(const TPML_POLICYELEMENTS *from_policy);
+
+static TSS2_RC copy_policy_harness(TPMS_POLICY_HARNESS * dest,
+        const TPMS_POLICY_HARNESS * src) {
+    /* Check for NULL references */
+    if (dest == NULL || src == NULL) {
+        return TSS2_FAPI_RC_MEMORY;
+    }
+
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    dest->description = NULL;
+    strdup_check(dest->description,src->description,r, error_cleanup);
+    dest->policy = copy_policy_elements(src->policy);
+    goto_if_null2(dest->policy, "Out of memory", r, TSS2_FAPI_RC_MEMORY,
+            error_cleanup);
+
+    return r;
+error_cleanup:
+    ifapi_cleanup_policy_harness(dest);
+    return r;
+}
+
+static TSS2_RC
+copy_policy_object(POLICY_OBJECT * dest, const POLICY_OBJECT * src) {
+    /* Check for NULL references */
+    if (dest == NULL || src == NULL) {
+        return TSS2_FAPI_RC_MEMORY;
+    }
+
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    dest->policy.description = NULL;
+    dest->policy.policyAuthorizations = NULL;
+    dest->policy.policy = NULL;
+    strdup_check(dest->path, src->path, r, error_cleanup);
+    r = copy_policy_harness(&dest->policy, &src->policy);
+    goto_if_error(r, "Could not copy policy harness", error_cleanup);
+    if (src->next != NULL) {
+        dest->next = malloc(sizeof(POLICY_OBJECT));
+        goto_if_null(dest->next, "Out of memory", r, error_cleanup);
+        dest->next->next = NULL;
+        r = copy_policy_object(dest->next, src->next);
+        goto_if_error(r, "Could not copy next policy object", error_cleanup);
+    }
+
+    return r;
+error_cleanup:
+    cleanup_policy_object(dest);
+    return r;
+}
+
+static TSS2_RC
+copy_policyauthorization(TPMS_POLICYAUTHORIZATION * dest,
+        const TPMS_POLICYAUTHORIZATION * src) {
+    if (dest == NULL || src == NULL) {
+        return TSS2_FAPI_RC_BAD_REFERENCE;
+    }
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    strdup_check(dest->type, src->type, r, error_cleanup);
+
+    dest->key = src->key;
+    dest->policyRef = src->policyRef;
+    dest->signature = src->signature;
+
+    return r;
+error_cleanup:
+    SAFE_FREE(dest->type);
+    return r;
+}
+
+static TPML_POLICYBRANCHES *
+copy_policy_branches(const TPML_POLICYBRANCHES *from_branches)
+{
+    TPML_POLICYBRANCHES *to_branches;
+    size_t j;
+
+    to_branches = calloc(1, sizeof(TPML_POLICYBRANCHES) +
+                         from_branches->count * sizeof(TPMS_POLICYBRANCH));
+    to_branches->count = from_branches->count;
+    for (j = 0; j < from_branches->count; j++) {
+        to_branches->authorizations[j].name = strdup(from_branches->authorizations[j].name);
+        if (!to_branches->authorizations[j].name)
+            goto error;
+        to_branches->authorizations[j].description = strdup(from_branches->authorizations[j].description);
+        if (!to_branches->authorizations[j].description)
+            goto error;
+        to_branches->authorizations[j].policy = copy_policy_elements(from_branches->authorizations[j].policy);
+        if (to_branches->authorizations[j].policy == NULL &&
+                from_branches->authorizations[j].policy != NULL) {
+            LOG_ERROR("Out of memory.");
+            goto error;
+        }
+        to_branches->authorizations[j].policyDigests =
+            from_branches->authorizations[j].policyDigests;
+    }
+    return to_branches;
+
+ error:
+    if (to_branches) {
+        for (j = 0; j < to_branches->count; j++) {
+            SAFE_FREE(to_branches->authorizations[j].name);
+            SAFE_FREE(to_branches->authorizations[j].description);
+            cleanup_policy_elements(to_branches->authorizations[j].policy);
+        }
+        SAFE_FREE(to_branches);
+    }
+    return NULL;
+}
+
+TSS2_RC
+copy_policy_element(const TPMT_POLICYELEMENT *from_policy, TPMT_POLICYELEMENT *to_policy)
+{
+    if (from_policy == NULL || to_policy == NULL) {
+        return TSS2_FAPI_RC_BAD_REFERENCE;
+    }
+    TSS2_RC r = TSS2_RC_SUCCESS;
+
+    *to_policy = *from_policy;
+    size_t i;
+
+    switch (from_policy->type) {
+    case POLICYSECRET:
+        strdup_check(to_policy->element.PolicySecret.objectPath,
+                     from_policy->element.PolicySecret.objectPath, r, error);
+        break;
+    case POLICYAUTHORIZE:
+        strdup_check(to_policy->element.PolicyAuthorize.keyPath,
+                from_policy->element.PolicyAuthorize.keyPath, r, error);
+        strdup_check(to_policy->element.PolicyAuthorize.keyPEM,
+                from_policy->element.PolicyAuthorize.keyPEM, r, error);
+        if (from_policy->element.PolicyAuthorize.policy_list) {
+            to_policy->element.PolicyAuthorize.policy_list =
+                malloc(sizeof(POLICY_OBJECT));
+            goto_if_null2(to_policy->element.PolicyAuthorize.policy_list,
+                    "Out of memory", r, TSS2_FAPI_RC_MEMORY, error);
+            to_policy->element.PolicyAuthorize.policy_list->next = NULL;
+            r = copy_policy_object(to_policy->element.PolicyAuthorize.policy_list,
+                    from_policy->element.PolicyAuthorize.policy_list);
+            goto_if_error(r, "Could not copy policy list", error);
+
+        }
+        if (from_policy->element.PolicyAuthorize.authorization) {
+            to_policy->element.PolicyAuthorize.authorization =
+                malloc(sizeof(TPMS_POLICYAUTHORIZATION));
+            goto_if_null(to_policy->element.PolicyAuthorize.authorization,
+                    "Out of memory", r, error);
+            r = copy_policyauthorization(
+                    to_policy->element.PolicyAuthorize.authorization,
+                    from_policy->element.PolicyAuthorize.authorization);
+            goto_if_error(r, "Could not copy policy authorization", error);
+        }
+        break;
+    case POLICYAUTHORIZENV:
+        strdup_check(to_policy->element.PolicyAuthorizeNv.nvPath,
+                     from_policy->element.PolicyAuthorizeNv.nvPath, r, error);
+        break;
+    case POLICYSIGNED:
+        strdup_check(to_policy->element.PolicySigned.keyPath,
+                     from_policy->element.PolicySigned.keyPath, r, error);
+        strdup_check(to_policy->element.PolicySigned.keyPEM,
+                     from_policy->element.PolicySigned.keyPEM, r, error);
+        break;
+    case POLICYPCR:
+        to_policy->element.PolicyPCR.pcrs =
+            calloc(1, sizeof(TPML_PCRVALUES) +
+                   from_policy->element.PolicyPCR.pcrs->count + sizeof(TPMS_PCRVALUE));
+        goto_if_null2(to_policy->element.PolicyPCR.pcrs, "Out of memory.",
+                      r, TSS2_FAPI_RC_MEMORY, error);
+        to_policy->element.PolicyPCR.pcrs->count
+            = from_policy->element.PolicyPCR.pcrs->count;
+        for (i = 0; i < to_policy->element.PolicyPCR.pcrs->count; i++)
+            to_policy->element.PolicyPCR.pcrs->pcrs[i]
+                = from_policy->element.PolicyPCR.pcrs->pcrs[i];
+        break;
+    case POLICYNV:
+        strdup_check(to_policy->element.PolicyNV.nvPath,
+                     from_policy->element.PolicyNV.nvPath, r, error);
+        break;
+    case POLICYDUPLICATIONSELECT:
+        strdup_check(to_policy->element.PolicyDuplicationSelect.newParentPath,
+                     from_policy->element.PolicyDuplicationSelect.newParentPath,
+                     r, error);
+        break;
+    case POLICYNAMEHASH:
+        for (size_t i = 0; i < from_policy->element.PolicyNameHash.count; i++) {
+            strdup_check(to_policy->element.PolicyNameHash.namePaths[i],
+                    from_policy->element.PolicyNameHash.namePaths[i],
+                    r, error);
+        }
+        break;
+    case POLICYOR:
+        to_policy->element.PolicyOr.branches =
+            copy_policy_branches(from_policy->element.PolicyOr.branches);
+        goto_if_null2(to_policy->element.PolicyOr.branches, "Out of memory",
+                r, TSS2_FAPI_RC_MEMORY, error);
+        break;
+    }
+    return TSS2_RC_SUCCESS;
+
+ error:
+    return r;
+}
+
+static TPML_POLICYELEMENTS *
+copy_policy_elements(const TPML_POLICYELEMENTS *from_policy)
+{
+    if (from_policy == NULL) {
+        return NULL;
+    }
+    TSS2_RC r;
+    size_t i;
+    TPML_POLICYELEMENTS *to_policy = NULL;
+
+    to_policy = calloc(1, sizeof(TPML_POLICYELEMENTS) +
+                       from_policy->count * sizeof(TPMT_POLICYELEMENT));
+    to_policy->count = from_policy->count;
+    for (i = 0; i < from_policy->count; i++) {
+        if (from_policy->elements[i].type ==  POLICYOR) {
+            to_policy->elements[i].type = POLICYOR;
+            /* Policy with sub policies */
+            TPML_POLICYBRANCHES *branches = from_policy->elements[i].element.PolicyOr.branches;
+            to_policy->elements[i].element.PolicyOr.branches = copy_policy_branches(branches);
+            if(branches != NULL
+               && to_policy->elements[i].element.PolicyOr.branches == NULL) {
+                    LOG_ERROR("Out of memory");
+                    SAFE_FREE(to_policy);
+                    return NULL;
+            }
+        } else {
+            r = copy_policy_element(&from_policy->elements[i], &to_policy->elements[i]);
+            if (r != TSS2_RC_SUCCESS) {
+                cleanup_policy_elements(to_policy);
+                return NULL;
+            }
+        }
+    }
+    return to_policy;
+}
+
+
+
+/** Copy policy harness.
+ * The object will not be freed (might be declared on the stack).
+ *
+ * @param[in] from_harness the policy to be copied.
+ * @retval The new harness or NULL if not enough memory was available.
+ *
+ */
+TPMS_POLICY_HARNESS *
+ifapi_copy_policy_harness(
+    const TPMS_POLICY_HARNESS *from_harness)
+{
+    if (from_harness == NULL) {
+        return NULL;
+    }
+    TPMS_POLICY_HARNESS *to_harness = calloc(1, sizeof(TPMS_POLICY_HARNESS));
+    if (to_harness == NULL) {
+        return NULL;
+    }
+    to_harness->description = NULL;
+    TSS2_RC r = copy_policy_harness(to_harness, from_harness);
+    if (r != TSS2_RC_SUCCESS) {
+        SAFE_FREE(to_harness);
+        return NULL;
+    } else {
+        return to_harness;
+    }
+}
+
+/** Compute the name of a TPM transient or persistent object.
+ *
+ * @param[in] publicInfo The public information of the TPM object.
+ * @param[out] name The computed name.
+ * @retval TPM2_RC_SUCCESS  or one of the possible errors TSS2_ESYS_RC_BAD_VALUE,
+ * TSS2_ESYS_RC_MEMORY, TSS2_ESYS_RC_GENERAL_FAILURE, TSS2_ESYS_RC_NOT_IMPLEMENTED,
+ * or return codes of SAPI errors.
+ */
+TSS2_RC
+ifapi_get_name(TPMT_PUBLIC *publicInfo, TPM2B_NAME *name)
+{
+    BYTE buffer[sizeof(TPMT_PUBLIC)];
+    size_t offset = 0;
+    size_t len_alg_id = sizeof(TPMI_ALG_HASH);
+    size_t size = sizeof(TPMU_NAME) - sizeof(TPMI_ALG_HASH);
+    IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext;
+
+    if (publicInfo->nameAlg == TPM2_ALG_NULL) {
+        name->size = 0;
+        return TSS2_RC_SUCCESS;
+    }
+    TSS2_RC r;
+    r = ifapi_crypto_hash_start(&cryptoContext, publicInfo->nameAlg);
+    return_if_error(r, "crypto hash start");
+
+    r = Tss2_MU_TPMT_PUBLIC_Marshal(publicInfo,
+                                    &buffer[0], sizeof(TPMT_PUBLIC), &offset);
+    return_if_error(r, "Marshaling TPMT_PUBLIC");
+
+    r = ifapi_crypto_hash_update(cryptoContext, &buffer[0], offset);
+    return_if_error(r, "crypto hash update");
+
+    r = ifapi_crypto_hash_finish(&cryptoContext, &name->name[len_alg_id],
+                                 &size);
+    return_if_error(r, "crypto hash finish");
+
+    offset = 0;
+    r = Tss2_MU_TPMI_ALG_HASH_Marshal(publicInfo->nameAlg,
+                                      &name->name[0], sizeof(TPMI_ALG_HASH),
+                                      &offset);
+    return_if_error(r, "Marshaling TPMI_ALG_HASH");
+
+    name->size = size + len_alg_id;
+    return TSS2_RC_SUCCESS;
+}
+
+/** Compute the name from the public data of a NV index.
+ *
+ * The name of a NV index is computed as follows:
+ *   name =  nameAlg||Hash(nameAlg,marshal(publicArea))
+ * @param[in] publicInfo The public information of the NV index.
+ * @param[out] name The computed name.
+ * @retval TSS2_RC_SUCCESS on success.
+ * @retval TSS2_ESYS_RC_MEMORY Memory can not be allocated.
+ * @retval TSS2_ESYS_RC_BAD_VALUE for invalid parameters.
+ * @retval TSS2_ESYS_RC_BAD_REFERENCE for unexpected NULL pointer parameters.
+ * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
+ * @retval TSS2_ESYS_RC_NOT_IMPLEMENTED if hash algorithm is not implemented.
+ * @retval TSS2_SYS_RC_* for SAPI errors.
+ */
+TSS2_RC
+ifapi_nv_get_name(TPM2B_NV_PUBLIC *publicInfo, TPM2B_NAME *name)
+{
+    BYTE buffer[sizeof(TPMS_NV_PUBLIC)];
+    size_t offset = 0;
+    size_t size = sizeof(TPMU_NAME) - sizeof(TPMI_ALG_HASH);
+    size_t len_alg_id = sizeof(TPMI_ALG_HASH);
+    IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext;
+
+    if (publicInfo->nvPublic.nameAlg == TPM2_ALG_NULL) {
+        name->size = 0;
+        return TSS2_RC_SUCCESS;
+    }
+    TSS2_RC r;
+    r = ifapi_crypto_hash_start(&cryptoContext, publicInfo->nvPublic.nameAlg);
+    return_if_error(r, "Crypto hash start");
+
+    r = Tss2_MU_TPMS_NV_PUBLIC_Marshal(&publicInfo->nvPublic,
+                                       &buffer[0], sizeof(TPMS_NV_PUBLIC),
+                                       &offset);
+    return_if_error(r, "Marshaling TPMS_NV_PUBLIC");
+
+    r = ifapi_crypto_hash_update(cryptoContext, &buffer[0], offset);
+    return_if_error(r, "crypto hash update");
+
+    r = ifapi_crypto_hash_finish(&cryptoContext, &name->name[len_alg_id],
+                                 &size);
+    return_if_error(r, "crypto hash finish");
+
+    offset = 0;
+    r = Tss2_MU_TPMI_ALG_HASH_Marshal(publicInfo->nvPublic.nameAlg,
+                                      &name->name[0], sizeof(TPMI_ALG_HASH),
+                                      &offset);
+    return_if_error(r, "Marshaling TPMI_ALG_HASH");
+
+    name->size = size + len_alg_id;
+    return TSS2_RC_SUCCESS;
+}
+
+/** Check whether a nv or key object has a certain name.
+ *
+ * @param[in] object The object (has to be checked whether it's a key).
+ @ @param[in] name The name to be compared.
+ * @param[out] equal If the two names are equal.
+ * @retval TSS2_RC_SUCCESSS if name of object can be deserialized.
+ */
+TSS2_RC
+ifapi_object_cmp_name(IFAPI_OBJECT *object, void *name, bool *equal)
+{
+    TSS2_RC r;
+    *equal = false;
+    TPM2B_NAME *obj_name;
+    TPM2B_NAME nv_name;
+
+    switch (object->objectType) {
+    case IFAPI_KEY_OBJ:
+        obj_name = &object->misc.key.name;
+        break;
+    case IFAPI_NV_OBJ:
+        r = ifapi_nv_get_name(&object->misc.nv.public, &nv_name);
+        return_if_error(r, "Get NV name.");
+
+        obj_name = &nv_name;
+        break;
+    default:
+        return TSS2_RC_SUCCESS;
+    }
+    if (obj_name->size != ((TPM2B_NAME *)name)->size)
+        return TSS2_RC_SUCCESS;
+    if (memcmp(&obj_name->name[0], &((TPM2B_NAME *)name)->name[0], obj_name->size))
+        /* The names are not equal */
+        return TSS2_RC_SUCCESS;
+    /* The two names are equal */
+    *equal = true;
+    return TSS2_RC_SUCCESS;
+}
+
+/** Check whether a nv object has a certain public info.
+ *
+ * @param[in] object The object (has to be checked whether it's a key).
+ @ @param[in] nv_public The NV public data with the NV index.
+ * @param[out] equal If the two names are equal.
+ * @retval TSS2_RC_SUCCESSS if name of object can be deserialized.
+ */
+TSS2_RC
+ifapi_object_cmp_nv_public(IFAPI_OBJECT *object, void *nv_public, bool *equal)
+{
+    *equal = false;
+
+    switch (object->objectType) {
+        break;
+    case IFAPI_NV_OBJ:
+        if (object->misc.nv.public.nvPublic.nvIndex
+            == ((TPM2B_NV_PUBLIC *)nv_public)->nvPublic.nvIndex)
+            *equal = true;
+        break;
+    default:
+        return TSS2_RC_SUCCESS;
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Compute signature as byte array and signature size in DER format.
+ *
+ * For ECC signatures the conversion to DER is necessary, for RSA the
+ * buffer of the TPM2B has already DER format.
+ * parameters.
+ * @param[in] sig_key_object The signing key.
+ * @param[in] TPMT_SIGNATURE the signature in TPM format.
+ * @param[out] signature The byte array of the signature (callee allocated).
+ * @param[out] signatureSize The size of the byte array.
+ * @retval TSS2_RC_SUCCESSS if the conversion was successful.
+ */
+
+TSS2_RC
+ifapi_tpm_to_fapi_signature(
+    IFAPI_OBJECT *sig_key_object,
+    TPMT_SIGNATURE *tpm_signature,
+    uint8_t **signature,
+    size_t *signatureSize)
+{
+    TSS2_RC r;
+
+    *signature = NULL;
+    TPMT_SIG_SCHEME *sig_scheme = &sig_key_object->misc.key.signing_scheme;
+
+    if (sig_key_object->misc.key.public.publicArea.type == TPM2_ALG_RSA) {
+        if (sig_scheme->scheme == TPM2_ALG_RSAPSS) {
+            *signatureSize = tpm_signature->signature.rsapss.sig.size;
+            *signature = malloc(*signatureSize);
+            goto_if_null(*signature, "Out of memory.", TSS2_FAPI_RC_MEMORY, error_cleanup);
+
+            memcpy(*signature,
+                   &tpm_signature->signature.rsapss.sig.buffer[0],
+                   *signatureSize);
+        } else if (sig_scheme->scheme == TPM2_ALG_RSASSA) {
+            *signatureSize = tpm_signature->signature.rsassa.sig.size;
+            *signature = malloc(*signatureSize);
+            goto_if_null(*signature, "Out of memory.", TSS2_FAPI_RC_MEMORY, error_cleanup);
+
+            memcpy(*signature,
+                   &tpm_signature->signature.rsassa.sig.buffer[0],
+                   *signatureSize);
+        }
+    } else if (sig_key_object->misc.key.public.publicArea.type == TPM2_ALG_ECC &&
+            sig_scheme->scheme == TPM2_ALG_ECDSA) {
+        r = ifapi_tpm_ecc_sig_to_der(tpm_signature,
+                                     signature, signatureSize);
+        goto_if_error(r, "Conversion to DER failed", error_cleanup);
+    } else {
+        goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Unknown signature scheme", error_cleanup);
+    }
+    return TSS2_RC_SUCCESS;
+
+error_cleanup:
+    SAFE_FREE(*signature);
+    return r;
+}
+
+
+TSS2_RC
+ifapi_compute_quote_info(
+    IFAPI_OBJECT *sig_key_object,
+    TPM2B_ATTEST *tpm_quoted,
+    char **quoteInfo)
+{
+    json_object *jso = NULL;
+    TSS2_RC r;
+    size_t offset = 0;
+    TPMS_ATTEST attest_struct;
+    FAPI_QUOTE_INFO fapi_quote_info;
+
+    r = Tss2_MU_TPMS_ATTEST_Unmarshal((const uint8_t *)
+                                      &tpm_quoted->attestationData[0],
+                                      tpm_quoted->size, &offset, &attest_struct);
+    return_if_error(r, "Unmarshal TPMS_ATTEST.");
+
+    fapi_quote_info.attest = attest_struct;
+    fapi_quote_info.sig_scheme = sig_key_object->misc.key.signing_scheme;
+    r = ifapi_json_FAPI_QUOTE_INFO_serialize(&fapi_quote_info, &jso);
+    return_if_error(r, "Conversion to TPM2B_ATTEST to JSON.");
+
+    const char *quote_json = json_object_to_json_string_ext(jso,
+                             JSON_C_TO_STRING_PRETTY);
+    goto_if_null(quote_json, "Conversion attest to json.",
+                 TSS2_FAPI_RC_GENERAL_FAILURE, cleanup);
+
+    *quoteInfo = strdup(quote_json);
+    goto_if_null(*quoteInfo, "Out of memory.", TSS2_FAPI_RC_MEMORY, cleanup);
+
+cleanup:
+    json_object_put(jso);
+    return r;
+}
+
+TSS2_RC
+ifapi_get_quote_info(
+    char const *quoteInfo,
+    TPM2B_ATTEST *tpm_quoted,
+    FAPI_QUOTE_INFO *fapi_quote_info)
+{
+    json_object *jso = NULL;
+    TSS2_RC r;
+    size_t offset = 0;
+
+    jso = json_tokener_parse(quoteInfo);
+    return_if_null(jso, "Json error.", TSS2_FAPI_RC_BAD_VALUE);
+
+    memset(&fapi_quote_info->attest.attested.quote.pcrSelect, 0,
+           sizeof(TPML_PCR_SELECTION));
+
+    r = ifapi_json_FAPI_QUOTE_INFO_deserialize(jso, fapi_quote_info);
+    goto_if_error(r, "Conversion to JSON of TPM2S_ATTEST.", cleanup);
+
+    offset = 0;
+    r = Tss2_MU_TPMS_ATTEST_Marshal(&fapi_quote_info->attest,
+                                    (uint8_t *)&tpm_quoted->attestationData[0],
+                                    sizeof(TPMS_ATTEST), &offset);
+    LOGBLOB_TRACE(&tpm_quoted->attestationData[0],
+                  offset,
+                  "Attest");
+    tpm_quoted-> size = offset;
+    goto_if_error(r, "Marshal attest.", cleanup);
+
+cleanup:
+    if (jso)
+        json_object_put(jso);
+    return r;
+}
+
+
+TSS2_RC
+ifapi_load_sym_key_template(IFAPI_KEY_TEMPLATE *result_template)
+{
+    IFAPI_KEY_TEMPLATE template = {
+        .persistent = TPM2_NO,
+        .persistent_handle = 0,
+        .public = {
+            .size = 0,
+            .publicArea = {
+                .type = TPM2_ALG_KEYEDHASH,
+                .nameAlg = TPM2_ALG_SHA256,
+                .objectAttributes = (
+                    TPMA_OBJECT_NODA |
+                    TPMA_OBJECT_FIXEDTPM |
+                    TPMA_OBJECT_USERWITHAUTH |
+                    TPMA_OBJECT_FIXEDPARENT
+                ),
+                .authPolicy = {
+                    .size = 0,
+                },
+                .parameters.keyedHashDetail = {
+                    .scheme = {
+                        .scheme = TPM2_ALG_NULL,
+                        .details = {
+                            .hmac = {
+                                .hashAlg = TPM2_ALG_SHA256
+                            }
+                        }
+                    }
+                },
+                .unique.keyedHash = {
+                    .size = 0,
+                    .buffer = {},
+                },
+            }
+        }
+    };
+
+    *result_template = template;
+    return TSS2_RC_SUCCESS;
+}
+
+
+/* Determine start index for NV object depending on type.
+ *
+ * The value will be determined based on e TCG handle registry.
+ */
+TSS2_RC
+ifapi_get_nv_start_index(const char *path, TPM2_HANDLE *start_nv_index)
+{
+    NODE_STR_T *dir_list = split_string(path, IFAPI_FILE_DELIM);
+
+    *start_nv_index = 0;
+
+    return_if_null(dir_list, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+    if (dir_list->next && strcmp(dir_list->str, "nv") == 0) {
+        if (strcmp(dir_list->next->str, "TPM") == 0)
+            *start_nv_index = 0x01000000;
+        else if (strcmp(dir_list->next->str, "Platform") == 0)
+            *start_nv_index = 0x01400000;
+        else if (strcmp(dir_list->next->str, "Owner") == 0)
+            *start_nv_index = 0x01800000;
+        else if (strcmp(dir_list->next->str, "Endorsement_Certificate") == 0)
+            *start_nv_index = 0x01c00000;
+        else if (strcmp(dir_list->next->str, "Platform_Certificate") == 0)
+            *start_nv_index = 0x01c80000;
+        else if (strcmp(dir_list->next->str, "Component_OEM") == 0)
+            *start_nv_index = 0x01c10000;
+        else if (strcmp(dir_list->next->str, "TPM_OEM") == 0)
+            *start_nv_index = 0x01c20000;
+        else if (strcmp(dir_list->next->str, "Platform_OEM") == 0)
+            *start_nv_index = 0x01c30000;
+        else if (strcmp(dir_list->next->str, "PC-Client") == 0)
+            *start_nv_index = 0x01c40000;
+        else if (strcmp(dir_list->next->str, "Sever") == 0)
+            *start_nv_index = 0x01c50000;
+        else if (strcmp(dir_list->next->str, "Virtualized_Platform") == 0)
+            *start_nv_index = 0x01c60000;
+        else if (strcmp(dir_list->next->str, "MPWG") == 0)
+            *start_nv_index = 0x01c70000;
+        else if (strcmp(dir_list->next->str, "Embedded") == 0)
+            *start_nv_index = 0x01c80000;
+    }
+    free_string_list(dir_list);
+    if (*start_nv_index)
+        return TSS2_RC_SUCCESS;
+
+    return_error2(TSS2_FAPI_RC_BAD_PATH, "Invalid NV path: %s", path);
+}
+
+TSS2_RC
+ifapi_extend_vpcr(
+    TPM2B_DIGEST *vpcr,
+    TPMI_ALG_HASH bank,
+    const IFAPI_EVENT *event)
+{
+    TSS2_RC r;
+    size_t i;
+    size_t event_size, size;
+    IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext;
+
+    LOGBLOB_TRACE(&vpcr->buffer[0], vpcr->size, "Old vpcr value");
+
+    for (i = 0; i < event->digests.count; i++) {
+        if (event->digests.digests[i].hashAlg == bank) {
+            event_size = ifapi_hash_get_digest_size(event->digests.digests[i].hashAlg);
+
+            LOGBLOB_TRACE(&event->digests.digests[i].digest.sha512[0], event_size,
+                          "Extending with");
+
+            r = ifapi_crypto_hash_start(&cryptoContext, bank);
+            return_if_error(r, "crypto hash start");
+
+            HASH_UPDATE_BUFFER(cryptoContext, &vpcr->buffer[0], vpcr->size, r, error_cleanup);
+            HASH_UPDATE_BUFFER(cryptoContext, &event->digests.digests[i].digest.sha512[0],
+                               event_size, r, error_cleanup);
+            r = ifapi_crypto_hash_finish(&cryptoContext, &vpcr->buffer[0], &size);
+            return_if_error(r, "crypto hash finish");
+            vpcr->size = size;
+            break;
+        }
+    }
+    if (i == event->digests.count) {
+        LOG_ERROR("No digest for bank %"PRIu16" found in event", bank);
+        return TSS2_FAPI_RC_BAD_VALUE;
+    }
+    LOGBLOB_TRACE(&vpcr->buffer[0], vpcr->size, "New vpcr value");
+
+    return TSS2_RC_SUCCESS;
+
+error_cleanup:
+    ifapi_crypto_hash_abort(&cryptoContext);
+    return r;
+}
+
+TSS2_RC
+ifapi_calculate_pcr_digest(
+    json_object *jso_event_list,
+    const FAPI_QUOTE_INFO *quote_info,
+    TPM2B_DIGEST *pcr_digest)
+{
+    TSS2_RC r;
+    IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext;
+
+    struct {
+        TPMI_ALG_HASH bank;
+        TPM2_HANDLE pcr;
+        TPM2B_DIGEST value;
+    } pcrs[TPM2_MAX_PCRS];
+    size_t i, pcr, i_evt, hash_size, n_pcrs = 0, n_events = 0;
+
+    json_object *jso;
+    IFAPI_EVENT event;
+
+    const TPML_PCR_SELECTION *pcr_selection;
+    TPMI_ALG_HASH pcr_digest_hash_alg;
+
+    /* Get some data from the quote info for easier access */
+    pcr_selection = &quote_info->attest.attested.quote.pcrSelect;
+    pcr_digest->size = quote_info->attest.attested.quote.pcrDigest.size;
+
+    switch (quote_info->sig_scheme.scheme) {
+    case TPM2_ALG_RSAPSS:
+        pcr_digest_hash_alg = quote_info->sig_scheme.details.rsapss.hashAlg;
+        break;
+    case TPM2_ALG_RSASSA:
+        pcr_digest_hash_alg = quote_info->sig_scheme.details.rsassa.hashAlg;
+        break;
+    case TPM2_ALG_ECDSA:
+        pcr_digest_hash_alg = quote_info->sig_scheme.details.ecdsa.hashAlg;
+        break;
+    default:
+        LOG_ERROR("Unknown sig scheme");
+        return TSS2_FAPI_RC_BAD_VALUE;
+    }
+
+    /* Initialize used pcrs */
+    for (i = 0; i < pcr_selection->count; i++) {
+        for (pcr = 0; pcr < TPM2_MAX_PCRS; pcr++) {
+            uint8_t byte_idx = pcr / 8;
+            uint8_t flag = 1 << (pcr % 8);
+            if (flag & pcr_selection->pcrSelections[i].pcrSelect[byte_idx]) {
+                hash_size = ifapi_hash_get_digest_size(pcr_selection->pcrSelections[i].hash);
+                pcrs[n_pcrs].pcr = pcr;
+                pcrs[n_pcrs].bank = pcr_selection->pcrSelections[i].hash;
+                pcrs[n_pcrs].value.size = hash_size;
+                memset(&pcrs[n_pcrs].value.buffer[0], 0, hash_size);
+                n_pcrs +=1;
+            }
+        }
+    }
+
+    /* Compute pcr values based on event list */
+    if (jso_event_list) {
+        n_events = json_object_array_length(jso_event_list);
+        for (i_evt = 0; i_evt < n_events; i_evt++) {
+            jso = json_object_array_get_idx(jso_event_list, i_evt);
+            r = ifapi_json_IFAPI_EVENT_deserialize(jso, &event);
+            goto_if_error(r, "Error serialize policy", error_cleanup);
+
+            for (i = 0; i < n_pcrs; i++) {
+                 r = ifapi_extend_vpcr(&pcrs[i].value, pcrs[i].bank, &event);
+                 goto_if_error2(r, "Extending vpcr %"PRIu32, error_cleanup, pcrs[i].pcr);
+            }
+        }
+    }
+
+    /* Compute digest for the used pcrs */
+    r = ifapi_crypto_hash_start(&cryptoContext, pcr_digest_hash_alg);
+    return_if_error(r, "crypto hash start");
+
+    for (i = 0; i < n_pcrs; i++) {
+        HASH_UPDATE_BUFFER(cryptoContext, &pcrs[i].value.buffer, pcrs[i].value.size,
+                           r, error_cleanup);
+    }
+    r = ifapi_crypto_hash_finish(&cryptoContext,
+                                 (uint8_t *) &pcr_digest->buffer[0],
+                                 &hash_size);
+    return_if_error(r, "crypto hash finish");
+    pcr_digest->size = hash_size;
+
+    /* Compare the digest from the event list with the digest from the attest */
+    if (memcmp(&pcr_digest->buffer[0], &quote_info->attest.attested.quote.pcrDigest.buffer[0],
+               pcr_digest->size) != 0) {
+        goto_error(r, TSS2_FAPI_RC_SIGNATURE_VERIFICATION_FAILED,
+                   "The digest computed from event list does not match the attest.",
+                   error_cleanup);
+    }
+
+ error_cleanup:
+    ifapi_cleanup_event(&event);
+    return r;
+}
+
+/** Check whether profile PCR capabilities are a subset of TPM PCR capabilities.
+ *
+ * It has to be checked that every hash alg from the profile is available and
+ * whether the selected PCRs are available.
+ * @param[in] pcr_profile The pcr profile to use as basis for the selection.
+ * @param[in] pcr_capability The PCR capabilities  available for TPM.
+ * @retval TSS2_RC_SUCCESSS if the conversion was successful.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if profile is not subset of capabilities.
+ */
+TSS2_RC
+ifapi_check_profile_pcr_selection(
+    const TPML_PCR_SELECTION *pcr_profile,
+    const TPML_PCR_SELECTION *pcr_capablity)
+{
+    size_t i, j, k;
+
+    for (i = 0; i < pcr_profile->count; i++) {
+        bool hash_found = false;
+        for (j = 0; j < pcr_capablity->count; j++) {
+            if (pcr_capablity->pcrSelections[j].hash ==
+                    pcr_profile->pcrSelections[i].hash) {
+                /* Hash algorithm found, check PCRs */
+                hash_found = true;
+                if (pcr_profile->pcrSelections[i].sizeofSelect >
+                        pcr_capablity->pcrSelections[j].sizeofSelect) {
+                    return_error(TSS2_FAPI_RC_BAD_VALUE, "Invalid size of PCR select.");
+                }
+
+                for (k = 0;
+                        k < pcr_profile->pcrSelections[i].sizeofSelect;
+                        k++) {
+                    /* Check whether all selected PCRs are available */
+                    if ((pcr_profile->pcrSelections[i].pcrSelect[k] &
+                            pcr_capablity->pcrSelections[j].pcrSelect[k])
+                            != pcr_profile->pcrSelections[i].pcrSelect[k]) {
+                        return_error(TSS2_FAPI_RC_BAD_VALUE, "Invalid PCR selection.");
+
+                    }
+                }
+            }
+        }
+        if (!hash_found) {
+            return_error(TSS2_FAPI_RC_BAD_VALUE,
+                         "Hash alg for PCR selection not available.");
+        }
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Reduce a PCR selection to a single pcr.
+ *
+ * This includes two steps: clearing all bits but the selected and clearing empty hashalg lines.
+ *
+ * @param pcr_selection [in, out] The pcr selection to be filtered.
+ * @param pcr_index [in] The only PCR to remain selected.
+ * @retval TSS2_RC_SUCCESS if the filtering was successful.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if no pcr remain selected or the pcr selection is malformed.
+ */
+TSS2_RC
+ifapi_filter_pcr_selection_by_index(
+    TPML_PCR_SELECTION *pcr_selection,
+    const TPM2_HANDLE *pcr_index,
+    size_t pcr_count)
+{
+    UINT32 bank, j;
+    UINT16 select;
+    size_t i;
+    UINT8 selection[] = { 0, 0, 0, 0 };
+
+    for (i = 0; i < pcr_count; i++) {
+        selection[0] |= (1 << pcr_index[i]) % 256;
+        selection[1] |= (1 << (pcr_index[i] - 8)) % 256;
+        selection[2] |= (1 << (pcr_index[i] - 16)) % 256;
+        selection[3] |= (1 << (pcr_index[i] - 24)) % 256;
+    };
+
+    /* Remove unselected PCRs */
+    for (bank = 0; bank < pcr_selection->count; bank++) {
+        if (pcr_selection->pcrSelections[bank].sizeofSelect > 4) {
+            LOG_ERROR("pcrSelection's sizeofSelect exceeds allowed value of 4, is %"PRIu16,
+                      pcr_selection->pcrSelections[bank].sizeofSelect);
+            return TSS2_FAPI_RC_BAD_VALUE;
+        }
+        for (select = 0; select < pcr_selection->pcrSelections[bank].sizeofSelect; select++) {
+            pcr_selection->pcrSelections[bank].pcrSelect[select] &= selection[select];
+        }
+    }
+
+    /* Remove empty banks */
+    for (bank = 0; bank < pcr_selection->count; ) {
+        for (select = 0; select < pcr_selection->pcrSelections[bank].sizeofSelect; select++) {
+            if (pcr_selection->pcrSelections[bank].pcrSelect[select])
+                break;
+        }
+        if (select < pcr_selection->pcrSelections[bank].sizeofSelect) {
+            /* Bank contains selections */
+            bank ++;
+            continue;
+        }
+
+        /* Bank contains no selections, move all other banks one up */
+        pcr_selection->count -= 1;
+        for (j = bank; j < pcr_selection->count; j++) {
+            pcr_selection->pcrSelections[j] = pcr_selection->pcrSelections[j+1];
+        }
+    }
+
+    if (pcr_selection->count == 0) {
+        LOGBLOB_WARNING((void*)pcr_index, pcr_count * sizeof(*pcr_index),
+                        "pcr slection is empty after filtering for pcrlist");
+        return TSS2_FAPI_RC_BAD_VALUE;
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+TSS2_RC
+ifapi_compute_policy_digest(
+    TPML_PCRVALUES *pcrs,
+    TPML_PCR_SELECTION *pcr_selection,
+    TPMI_ALG_HASH hash_alg,
+    TPM2B_DIGEST *pcr_digest)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    size_t i, j;
+    IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext;
+    size_t hash_size;
+    UINT32 pcr;
+    UINT32 max_pcr = 0;
+
+    memset(pcr_selection, 0, sizeof(TPML_PCR_SELECTION));
+
+    /* Compute PCR selection */
+    pcr_selection->count = 0;
+    for (i = 0; i < pcrs->count; i++) {
+        for (j = 0; j < pcr_selection->count; j++) {
+            if (pcrs->pcrs[i].hashAlg ==
+                pcr_selection->pcrSelections[j].hash) {
+                break;
+            }
+        }
+        if (j == pcr_selection->count) {
+            /* New hash alg */
+            pcr_selection->count += 1;
+            if (pcr_selection->count > TPM2_NUM_PCR_BANKS) {
+                return_error(TSS2_FAPI_RC_BAD_VALUE,
+                             "More hash algs than banks.");
+            }
+            pcr_selection->pcrSelections[j].hash =
+                pcrs->pcrs[i].hashAlg;
+        }
+        UINT32 pcrIndex = pcrs->pcrs[i].pcr;
+        if (pcrIndex + 1 > max_pcr)
+            max_pcr = pcrIndex + 1;
+        pcr_selection->pcrSelections[j].pcrSelect[pcrIndex / 8] |=
+            1 << pcrIndex % 8;
+        if ((pcrIndex / 8) + 1 > pcr_selection->pcrSelections[j].sizeofSelect)
+            pcr_selection->pcrSelections[j].sizeofSelect = (pcrIndex / 8) + 1;
+    }
+    /* Compute digest for current pcr selection */
+    r = ifapi_crypto_hash_start(&cryptoContext, hash_alg);
+    return_if_error(r, "crypto hash start");
+
+    if (!(pcr_digest->size = ifapi_hash_get_digest_size(hash_alg))) {
+        goto_error(r, TSS2_ESYS_RC_NOT_IMPLEMENTED,
+                   "Unsupported hash algorithm (%" PRIu16 ")", cleanup,
+                   hash_alg);
+    }
+
+    for (i = 0; i < pcr_selection->count; i++) {
+        TPMS_PCR_SELECTION selection = pcr_selection->pcrSelections[i];
+        TPMI_ALG_HASH hashAlg = selection.hash;
+        if (!(hash_size = ifapi_hash_get_digest_size(hashAlg))) {
+            goto_error(r, TSS2_ESYS_RC_NOT_IMPLEMENTED,
+                       "Unsupported hash algorithm (%" PRIu16 ")", cleanup,
+                       hashAlg);
+        }
+        for (pcr = 0; pcr < max_pcr; pcr++) {
+            if ((selection.pcrSelect[pcr / 8]) & (1 << (pcr % 8))) {
+                /* pcr selected */
+                for (j = 0; j < pcrs->count; j++) {
+                    if (pcrs->pcrs[j].pcr == pcr) {
+                        r = ifapi_crypto_hash_update(cryptoContext,
+                                                     (const uint8_t *)&pcrs->
+                                                     pcrs[j].digest,
+                                                     hash_size);
+                        goto_if_error(r, "crypto hash update", cleanup);
+                    }
+                }
+            }
+        }
+    }
+    r = ifapi_crypto_hash_finish(&cryptoContext,
+                                 (uint8_t *) & pcr_digest->buffer[0],
+                                 &hash_size);
+cleanup:
+    return r;
+}
+
+/** Compare two public keys.
+ *
+ * @param[in] key1 The first key.
+ * @param[in] key2 The second key.
+ * @retval true if equal false if not.
+ */
+bool
+ifapi_cmp_public_key(
+    TPM2B_PUBLIC *key1,
+    TPM2B_PUBLIC *key2)
+{
+    if (key1->publicArea.type != key2->publicArea.type)
+        return false;
+    switch (key1->publicArea.type) {
+    case TPM2_ALG_RSA:
+        if (key1->publicArea.unique.rsa.size != key2->publicArea.unique.rsa.size) {
+            return false;
+        }
+        LOGBLOB_TRACE(&key1->publicArea.unique.rsa.buffer[0],
+                      key1->publicArea.unique.rsa.size, "Key 1");
+        LOGBLOB_TRACE(&key2->publicArea.unique.rsa.buffer[0],
+                      key2->publicArea.unique.rsa.size, "Key 2");
+        if (memcmp(&key1->publicArea.unique.rsa.buffer[0],
+                   &key2->publicArea.unique.rsa.buffer[0],
+                   key1->publicArea.unique.rsa.size) == 0)
+            return true;
+        else
+            return false;
+        break;
+    case TPM2_ALG_ECC:
+        if (key1->publicArea.unique.ecc.x.size != key2->publicArea.unique.ecc.x.size) {
+            return false;
+        }
+        LOGBLOB_TRACE(&key1->publicArea.unique.ecc.x.buffer[0],
+                      key1->publicArea.unique.ecc.x.size, "Key 1 x");
+        LOGBLOB_TRACE(&key2->publicArea.unique.ecc.x.buffer[0],
+                      key2->publicArea.unique.ecc.x.size, "Key 2 x");
+        if (memcmp(&key1->publicArea.unique.ecc.x.buffer[0],
+                   &key2->publicArea.unique.ecc.x.buffer[0],
+                   key1->publicArea.unique.ecc.x.size) != 0)
+            return false;
+        if (key1->publicArea.unique.ecc.y.size != key2->publicArea.unique.ecc.y.size) {
+            return false;
+        }
+        LOGBLOB_TRACE(&key1->publicArea.unique.ecc.y.buffer[0],
+                      key1->publicArea.unique.ecc.y.size, "Key 1 x");
+        LOGBLOB_TRACE(&key2->publicArea.unique.ecc.y.buffer[0],
+                      key2->publicArea.unique.ecc.y.size, "Key 2 x");
+        if (memcmp(&key1->publicArea.unique.ecc.y.buffer[0],
+                   &key2->publicArea.unique.ecc.y.buffer[0],
+                   key1->publicArea.unique.ecc.y.size) != 0)
+            return false;
+        else
+            return true;
+        break;
+
+    default:
+        return false;
+    }
+}
diff --git a/src/tss2-fapi/ifapi_helpers.h b/src/tss2-fapi/ifapi_helpers.h
new file mode 100644
index 0000000..e237066
--- /dev/null
+++ b/src/tss2-fapi/ifapi_helpers.h
@@ -0,0 +1,202 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ *******************************************************************************/
+#ifndef IFAPI_HELPERS_H
+#define IFAPI_HELPERS_H
+
+#include <stdint.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <sys/stat.h>
+#include <json-c/json.h>
+#include <json-c/json_util.h>
+
+#include "tss2_esys.h"
+#include "tss2_fapi.h"
+#include "fapi_int.h"
+
+TSS2_RC
+ifapi_create_dirs(const char *supdir, const char *path);
+
+TSS2_RC
+ifapi_set_key_flags(const char *type, bool policy, IFAPI_KEY_TEMPLATE *template);
+
+TSS2_RC
+ifapi_set_nv_flags(const char *type, IFAPI_NV_TEMPLATE *template,
+                   const char *policy);
+
+bool
+ifapi_path_type_p(const char *path, const char *type);
+
+ESYS_TR
+ifapi_get_hierary_handle(const char *path);
+
+bool
+ifapi_hierarchy_path_p(const char *path);
+
+bool
+ifapi_TPMT_PUBLIC_cmp(TPMT_PUBLIC *in1, TPMT_PUBLIC *in2);
+
+void
+ifapi_init_hierarchy_object(
+    IFAPI_OBJECT *hierarchy,
+    ESYS_TR esys_handle);
+
+char *
+get_description(IFAPI_OBJECT *object);
+
+TSS2_RC
+create_dirs(const char *supdir, NODE_STR_T *dir_list, mode_t mode);
+
+TSS2_RC
+init_explicit_key_path(
+    const char *context_profile,
+    const char *ipath,
+    NODE_STR_T **list_node1,
+    NODE_STR_T **current_list_node,
+    NODE_STR_T **result);
+
+size_t
+ifapi_path_length(NODE_STR_T *node);
+
+size_t
+path_str_length(NODE_STR_T *node, int delim_length);
+
+void
+ifapi_free_object_list(NODE_OBJECT_T *node);
+
+void
+ifapi_free_node_list(NODE_OBJECT_T *node);
+
+TSS2_RC
+ifapi_path_string(char **dest, const char *supdir, NODE_STR_T *node, char *name);
+
+TSS2_RC
+ifapi_path_string_n(
+    char **dest,
+    const char *supdir,
+    NODE_STR_T *node,
+    char *name,
+    size_t n);
+
+TSS2_RC
+ifapi_asprintf(char **str, const char *fmt, ...);
+
+NODE_STR_T *
+split_string(const char *string, char *delimiter);
+
+NODE_STR_T *
+init_string_list(const char *string);
+
+bool
+add_string_to_list(NODE_STR_T *str_list, char *string);
+
+void
+free_string_list(NODE_STR_T *node);
+
+void
+ifapi_cleanup_policy_harness(
+    TPMS_POLICY_HARNESS *harness);
+
+TPMS_POLICY_HARNESS *
+ifapi_copy_policy_harness(
+    const TPMS_POLICY_HARNESS *from_harness);
+
+TSS2_RC
+ifapi_get_name(
+    TPMT_PUBLIC *publicInfo,
+    TPM2B_NAME *name);
+
+TSS2_RC
+ifapi_nv_get_name(
+    TPM2B_NV_PUBLIC *publicInfo,
+    TPM2B_NAME *name);
+
+TSS2_RC
+ifapi_object_cmp_name(
+    IFAPI_OBJECT *object,
+    void *name,
+    bool *equal);
+
+TSS2_RC
+ifapi_object_cmp_nv_public(
+    IFAPI_OBJECT *object,
+    void *nv_public,
+    bool *equal);
+
+TSS2_RC
+ifapi_tpm_to_fapi_signature(
+    IFAPI_OBJECT *sig_key_object,
+    TPMT_SIGNATURE *tpm_signature,
+    uint8_t **signature,
+    size_t *signatureSize);
+
+TSS2_RC
+ifapi_compute_quote_info(
+    IFAPI_OBJECT *sig_key_object,
+    TPM2B_ATTEST *tpm_quoted,
+    char **quoteInfo);
+
+TSS2_RC
+ifapi_get_quote_info(
+    char const *quoteInfo,
+    TPM2B_ATTEST *tpm_quoted,
+    FAPI_QUOTE_INFO *fapi_quote_ingo);
+
+TSS2_RC
+push_object_to_list(void *object, NODE_OBJECT_T **object_list);
+
+TSS2_RC
+append_object_to_list(void *object, NODE_OBJECT_T **object_list);
+
+TSS2_RC
+push_object_with_size_to_list(void *object, size_t size, NODE_OBJECT_T **object_list);
+
+size_t
+policy_digest_size(
+    IFAPI_OBJECT *object);
+
+TPM2B_DIGEST *
+get_policy(IFAPI_OBJECT *object);
+
+bool
+object_with_auth(IFAPI_OBJECT *object);
+
+TSS2_RC
+ifapi_load_sym_key_template(
+    IFAPI_KEY_TEMPLATE *template);
+
+TSS2_RC
+ifapi_get_nv_start_index(const char *path, TPM2_HANDLE *start_nv_index);
+
+TSS2_RC
+ifapi_check_profile_pcr_selection(
+    const TPML_PCR_SELECTION *pcr_profile,
+    const TPML_PCR_SELECTION *pcr_capablity);
+
+TSS2_RC
+ifapi_filter_pcr_selection_by_index(
+    TPML_PCR_SELECTION *pcr_selection,
+    const TPM2_HANDLE *pcr_index,
+    size_t pcr_count);
+
+TSS2_RC ifapi_calculate_pcr_digest(
+    json_object *jso_event_list,
+    const FAPI_QUOTE_INFO *quote_info,
+    TPM2B_DIGEST *pcr_digest);
+
+TSS2_RC
+ifapi_compute_policy_digest(
+    TPML_PCRVALUES *pcrs,
+    TPML_PCR_SELECTION *pcr_selection,
+    TPMI_ALG_HASH hash_alg,
+    TPM2B_DIGEST *pcr_digest);
+
+bool
+ifapi_cmp_public_key(
+    TPM2B_PUBLIC *key1,
+    TPM2B_PUBLIC *key2);
+
+#endif /* IFAPI_HELPERS_H */
diff --git a/src/tss2-fapi/ifapi_io.c b/src/tss2-fapi/ifapi_io.c
new file mode 100644
index 0000000..886c464
--- /dev/null
+++ b/src/tss2-fapi/ifapi_io.c
@@ -0,0 +1,607 @@
+/* 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 <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <dirent.h>
+/* Need for some libc-versions */
+#include <malloc.h>
+
+#include "tss2_common.h"
+#include "ifapi_io.h"
+#include "ifapi_helpers.h"
+#include "ifapi_macros.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+/** Start reading a file's complete content into memory in an asynchronous way.
+ *
+ * @param [in, out] io The input/output context being used for file I/O.
+ * @param [in] filename The name of the file to be read into memory.
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if an I/O error was encountered; such as the file was not found.
+ * @retval TSS2_FAPI_RC_MEMORY: if memory could not be allocated to hold the read data.
+ */
+TSS2_RC
+ifapi_io_read_async(
+    struct IFAPI_IO *io,
+    const char *filename)
+{
+    if (io->char_rbuffer) {
+        LOG_ERROR("rbuffer still in use; maybe use of old API.");
+        return TSS2_FAPI_RC_IO_ERROR;
+    }
+
+    io->stream = fopen(filename, "rt");
+    if (io->stream == NULL) {
+        LOG_ERROR("File \"%s\" not found.", filename);
+        return TSS2_FAPI_RC_IO_ERROR;
+    }
+    /* Locking the file. Lock will be release upon close */
+    if (lockf(fileno(io->stream), F_TLOCK, 0) == -1 && errno == EAGAIN) {
+        LOG_ERROR("File %s currently locked.", filename);
+        fclose(io->stream);
+        return TSS2_FAPI_RC_IO_ERROR;
+    }
+
+    fseek(io->stream, 0L, SEEK_END);
+    long length = ftell(io->stream);
+    rewind(io->stream);
+
+    io->stream = fopen(filename, "rt");
+    io->char_rbuffer = malloc (length + 1);
+    if (io->char_rbuffer == NULL) {
+        fclose(io->stream);
+        io->stream = NULL;
+        LOG_ERROR("Memory could not be allocated. %li bytes requested", length + 1);
+        return TSS2_FAPI_RC_MEMORY;
+    }
+
+    int flags = fcntl(fileno(io->stream), F_GETFL, 0);
+    fcntl(fileno(io->stream), F_SETFL, flags | O_NONBLOCK);
+
+    io->buffer_length = length;
+    io->buffer_idx = 0;
+    io->char_rbuffer[length] = '\0';
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Finish reading a file's complete content into memory in an asynchronous way.
+ *
+ * This function needs to be called repeatedly until it does not return TSS2_FAPI_RC_TRY_AGAIN.
+ *
+ * @param [in, out] io The input/output context being used for file I/O.
+ * @param [out] buffer The data that was read from file. (callee-allocated; use free())
+ * @param [out] length The length of the data that was read from file.
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if an I/O error was encountered; such as the file was not found.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet complete.
+           Call this function again later.
+ */
+TSS2_RC
+ifapi_io_read_finish(
+    struct IFAPI_IO *io,
+    uint8_t **buffer,
+    size_t *length)
+{
+    io->pollevents = POLLIN;
+    if (_ifapi_io_retry-- > 0)
+        return TSS2_FAPI_RC_TRY_AGAIN;
+    else
+        _ifapi_io_retry = _IFAPI_IO_RETRIES;
+
+    ssize_t ret = read(fileno(io->stream),
+                       &io->char_rbuffer[io->buffer_idx],
+                       io->buffer_length - io->buffer_idx);
+    if (ret < 0 && (errno == EINTR || errno == EAGAIN))
+            return TSS2_FAPI_RC_TRY_AGAIN;
+
+    if (ret < 0) {
+        LOG_ERROR("Error reading from file: %i.", errno);
+        fclose(io->stream);
+        io->pollevents = 0;
+        SAFE_FREE(io->char_rbuffer);
+        return TSS2_FAPI_RC_IO_ERROR;
+    }
+
+    io->pollevents = 0;
+    io->buffer_idx += ret;
+    if (io->buffer_idx < io->buffer_length)
+        return TSS2_FAPI_RC_TRY_AGAIN;
+
+    fclose(io->stream);
+
+    if (!buffer) {
+        LOG_WARNING("The old file read API is still being used");
+        return TSS2_RC_SUCCESS;
+    }
+    *buffer = (uint8_t *)io->char_rbuffer;
+    io->char_rbuffer = NULL;
+
+    if (length)
+        *length = io->buffer_length;
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Start writing a buffer into a file in an asynchronous way.
+ *
+ * @param [in, out] io The input/output context being used for file I/O.
+ * @param [in] filename The name of the file to be read into memory.
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if an I/O error was encountered; such as the file was not found.
+ * @retval TSS2_FAPI_RC_MEMORY: if memory could not be allocated to hold the read data.
+ */
+TSS2_RC
+ifapi_io_write_async(
+    struct IFAPI_IO *io,
+    const char *filename,
+    const uint8_t *buffer,
+    size_t length)
+{
+    if (io->char_rbuffer) {
+        LOG_ERROR("rbuffer still in use; maybe use of old API.");
+        return TSS2_FAPI_RC_IO_ERROR;
+    }
+
+    io->buffer_length = length;
+    io->buffer_idx = 0;
+    io->char_rbuffer = malloc(length);
+    if (io->char_rbuffer == NULL) {
+        LOG_ERROR("Memory could not be allocated. %zi bytes requested", length);
+        return TSS2_FAPI_RC_MEMORY;
+    }
+    memcpy(io->char_rbuffer, buffer, length);
+
+    io->stream = fopen(filename, "wt");
+    if (io->stream == NULL) {
+        SAFE_FREE(io->char_rbuffer);
+        LOG_ERROR("Could not open file \"%s\" for writing.", filename);
+        return TSS2_FAPI_RC_IO_ERROR;
+    }
+    /* Locking the file. Lock will be release upon close */
+    if (lockf(fileno(io->stream), F_TLOCK, 0) == -1 && errno == EAGAIN) {
+        LOG_ERROR("File %s currently locked.", filename);
+        fclose(io->stream);
+        return TSS2_FAPI_RC_IO_ERROR;
+    }
+
+    /* Use non blocking IO, so asynchronous write will be needed */
+    int flags = fcntl(fileno(io->stream), F_GETFL, 0);
+    fcntl(fileno(io->stream), F_SETFL, flags | O_NONBLOCK);
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Finish writing a buffer into a file in an asynchronous way.
+ *
+ * This function needs to be called repeatedly until it does not return TSS2_FAPI_RC_TRY_AGAIN.
+ *
+ * @param [in, out] io The input/output context being used for file I/O.
+ * @param [out] buffer The data that was read from file. (callee-allocated; use free())
+ * @param [out] length The length of the data that was read from file.
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if an I/O error was encountered; such as the file was not found.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet complete.
+           Call this function again later.
+ */
+TSS2_RC
+ifapi_io_write_finish(
+    struct IFAPI_IO *io)
+{
+    io->pollevents = POLLOUT;
+    if (_ifapi_io_retry-- > 0)
+        return TSS2_FAPI_RC_TRY_AGAIN;
+    else
+        _ifapi_io_retry = _IFAPI_IO_RETRIES;
+
+    ssize_t ret = write(fileno(io->stream),
+                        &io->char_rbuffer[io->buffer_idx],
+                        io->buffer_length - io->buffer_idx);
+    if (ret < 0 && (errno == EINTR || errno == EAGAIN))
+            return TSS2_FAPI_RC_TRY_AGAIN;
+
+    if (ret < 0) {
+        LOG_ERROR("Error writing to file: %i.", errno);
+        fclose(io->stream);
+        io->pollevents = 0;
+        SAFE_FREE(io->char_rbuffer);
+        return TSS2_FAPI_RC_IO_ERROR;
+    }
+
+    io->pollevents = 0;
+    io->buffer_idx += ret;
+    if (io->buffer_idx < io->buffer_length)
+        return TSS2_FAPI_RC_TRY_AGAIN;
+
+    SAFE_FREE(io->char_rbuffer);
+    fclose(io->stream);
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Check whether a file is writeable.
+ *
+ * @param file  The name of the fileto be checked.
+ * @retval TSS2_RC_SUCCESS if the directories existed or were successfully created
+ * @retval TSS2_FAPI_RC_IO_ERROR if an I/O error occured
+ */
+TSS2_RC
+ifapi_io_check_file_writeable(
+    const char *file)
+{
+    /* Check access rights to file  */
+    if (access(file, W_OK)) {
+        return_error2(TSS2_FAPI_RC_IO_ERROR, "File %s is not writeable.", file);
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/* Check for the existence of a directory and create it if it does not yet exist.
+ *
+ * @param dirname The name of the directory to be checked / created
+ * @retval TSS2_RC_SUCCESS if the directories existed or were successfully created
+ * @retval TSS2_FAPI_RC_IO_ERROR if an I/O error occured
+ */
+TSS2_RC
+ifapi_io_check_create_dir(
+    const char *dirname)
+{
+    TSS2_RC r;
+    struct stat fbuffer;
+
+    /* Check existence of dirname and try to create it otherwise */
+    if (stat(dirname, &fbuffer)) {
+        LOG_WARNING("Directory %s does not exist, creating", dirname);
+
+        r = ifapi_create_dirs("", dirname);
+        return_if_error2(r, "Directory %s can't be created.", dirname);
+
+        LOG_DEBUG("Created directory: %s", dirname);
+    }
+
+    /* Check access rights to dirname */
+    if (access(dirname, W_OK)) {
+        return_error2(TSS2_FAPI_RC_IO_ERROR, "Directory %s is not writeable.", dirname);
+    }
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Remove a file.
+ *
+ * @param file The absolute path of the file to be removed.
+ * @retval TSS2_RC_SUCCESS If the file was successfully removed
+ * @retval TSS2_FAPI_RC_IO_ERROR If the file could not be removed.
+ */
+TSS2_RC
+ifapi_io_remove_file(const char *file)
+{
+    if (remove(file) != 0) {
+        LOG_ERROR("File: %s can't be deleted.", file);
+        return TSS2_FAPI_RC_IO_ERROR;
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Remove a directory recursively; i.e. including its subdirectories.
+ *
+ * @param dirname The directory to be removed
+ * @retval TSS2_RC_SUCCESS if the directories were successfully removed
+ * @retval TSS2_FAPI_RC_IO_ERROR if an I/O error occured
+ * @retval TSS2_FAPI_RC_MEMORY: if memory could not be allocated to hold the read data.
+ */
+TSS2_RC
+ifapi_io_remove_directories(
+    const char *dirname)
+{
+    DIR *dir;
+    struct dirent *entry;
+    TSS2_RC r;
+    char *path;
+
+    LOG_TRACE("Removing directory: %s", dirname);
+
+    if (!(dir = opendir(dirname))) {
+        return_error2(TSS2_FAPI_RC_IO_ERROR, "Could not open directory: %s",
+                      dirname);
+    }
+
+    /* Iterating through the list of entries inside the directory. */
+    while ((entry = readdir(dir)) != NULL) {
+        LOG_TRACE("Deleting directory entry %s", entry->d_name);
+
+        /* Entries . and .. are obviously ignored */
+        if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
+            continue;
+
+        /* If an entry is a directory then we call ourself recursively to remove those */
+        if (entry->d_type == DT_DIR) {
+            r = ifapi_asprintf(&path, "%s/%s", dirname, entry->d_name);
+            return_if_error(r, "Out of memory");
+
+            r = ifapi_io_remove_directories(path);
+            return_if_error(r, "remove directories.");
+
+            free(path);
+            continue;
+        }
+
+        /* If an entry is a file or symlink or anything else, we remove it */
+        r = ifapi_asprintf(&path, "%s/%s", dirname, entry->d_name);
+        return_if_error(r, "Out of memory");
+
+        LOG_WARNING("Found a file in directory; removing: %s", path);
+
+        if (remove(path) != 0)
+            return_error2(TSS2_FAPI_RC_IO_ERROR, "Removing file: %s", path);
+
+        free(path);
+    }
+    closedir(dir);
+    LOG_TRACE("Removing target directory %s", dirname);
+
+    if (rmdir(dirname) != 0)
+        return_error2(TSS2_FAPI_RC_IO_ERROR, "Removing directory: %s", dirname);
+
+    LOG_TRACE("SUCCESS");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Enumerate the list of files in a directory.
+ *
+ * Enumerage the regular files (no directories, symlinks etc) from a given directory.
+ *
+ * @param dirname [in] The directory to list files from.
+ * @param files [out] The list of file names.
+ * @param numfiles [out] The size of files.
+ * @retval TSS2_RC_SUCCESS if the directories were successfully removed
+ * @retval TSS2_FAPI_RC_IO_ERROR if an I/O error occured
+ * @retval TSS2_FAPI_RC_MEMORY: if memory could not be allocated to hold the read data.
+ */
+TSS2_RC
+ifapi_io_dirfiles(
+    const char *dirname,
+    char ***files,
+    size_t *numfiles)
+{
+    DIR *dir;
+    struct dirent *entry;
+    char **paths;
+    size_t numpaths = 0;
+    check_not_null(dirname);
+    check_not_null(files);
+    check_not_null(numfiles);
+
+    LOG_TRACE("Removing directory: %s", dirname);
+
+    if (!(dir = opendir(dirname))) {
+        return_error2(TSS2_FAPI_RC_IO_ERROR, "Could not open directory: %s",
+                      dirname);
+    }
+
+    paths = calloc(10, sizeof(*paths));
+    check_oom(paths);
+
+    /* Iterating through the list of entries inside the directory. */
+    while ((entry = readdir(dir)) != NULL) {
+        LOG_TRACE("Looking at %s", entry->d_name);
+        if (entry->d_type != DT_REG)
+            continue;
+
+        if (numpaths % 10 == 9) {
+#ifdef HAVE_REALLOCARRAY
+            paths = reallocarray(paths, numpaths + 10, sizeof(*paths));
+#else /* HAVE_REALLOCARRAY */
+            paths = realloc(paths, (numpaths + 10) * sizeof(*paths));
+#endif /* HAVE_REALLOCARRAY */
+            check_oom(paths);
+        }
+
+        paths[numpaths] = strdup(entry->d_name);
+        if (!paths[numpaths])
+            goto error_oom;
+
+        LOG_TRACE("Added %s to the list at index %zi", paths[numpaths], numpaths);
+        numpaths += 1;
+    }
+    closedir(dir);
+
+    *files = paths;
+    *numfiles = numpaths;
+
+    return TSS2_RC_SUCCESS;
+
+error_oom:
+    LOG_ERROR("Out of memory");
+    for (size_t i = 0; i < numpaths; i++)
+        free(paths[i]);
+    free(paths);
+    return TSS2_FAPI_RC_MEMORY;
+}
+
+static TSS2_RC
+dirfiles_all(const char *dir_name, NODE_OBJECT_T **list, size_t *n)
+{
+    DIR *dir;
+    struct dirent *entry;
+    TSS2_RC r;
+    char *path;
+    NODE_OBJECT_T *second;
+
+    if (!(dir = opendir(dir_name))) {
+        return TSS2_RC_SUCCESS;
+    }
+
+    /* Iterating through the list of entries inside the directory. */
+    while ((entry = readdir(dir)) != NULL) {
+        path = NULL;
+        if (entry->d_type == DT_DIR) {
+            /* Recursive call for sub directories */
+            if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
+                continue;
+            r = ifapi_asprintf(&path, "%s/%s", dir_name, entry->d_name);
+            return_if_error(r, "Out of memory");
+
+            LOG_TRACE("Directory: %s", path);
+            r = dirfiles_all(path, list, n);
+            return_if_error(r, "get_entities");
+            SAFE_FREE(path);
+
+        } else {
+            r = ifapi_asprintf(&path, "%s/%s", dir_name, entry->d_name);
+            return_if_error(r, "Out of memory");
+
+            NODE_OBJECT_T *file_obj = calloc(sizeof(NODE_OBJECT_T), 1);
+            return_if_null(file_obj, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+            *n += 1;
+            /* Add file name to linked list */
+            file_obj->object = strdup(path);
+            if (file_obj->object == NULL) {
+                LOG_ERROR("%s", "Out of memory.");
+                SAFE_FREE(file_obj);
+                SAFE_FREE(path);
+                closedir(dir);
+                return TSS2_FAPI_RC_MEMORY;
+            }
+            if (*list != NULL) {
+                second = *list;
+                file_obj->next = second;
+            }
+            *list = file_obj;
+            LOG_TRACE("File: %s", path);
+            SAFE_FREE(path);
+        }
+    }
+    closedir(dir);
+    return TSS2_RC_SUCCESS;
+}
+
+
+/** Recursive enumerate the list of files in a directory.
+ *
+ * Enumerage the regular files (no directories, symlinks etc) from a given directory.
+ *
+ * @param dirname [in] The directory to list files from.
+ * @param files [out] The list of file names.
+ * @param numfiles [out] The size of files.
+ * @retval TSS2_RC_SUCCESS if the directories were successfully removed
+ * @retval TSS2_FAPI_RC_IO_ERROR if an I/O error occured
+ * @retval TSS2_FAPI_RC_MEMORY: if memory could not be allocated to hold the read data.
+ */
+TSS2_RC
+ifapi_io_dirfiles_all(
+    const char *searchPath,
+    char ***pathlist,
+    size_t *numPaths)
+{
+    TSS2_RC r;
+    size_t n;
+    NODE_OBJECT_T *head;
+
+    *numPaths = 0;
+    char **pathlist2;
+
+    NODE_OBJECT_T *file_list = NULL;
+    r = dirfiles_all(searchPath, &file_list, numPaths);
+    goto_if_error(r, "get all sub files of directory", cleanup);
+
+    if (*numPaths > 0) {
+        size_t size_path_list = *numPaths * sizeof(char *);
+        pathlist2 = calloc(1, size_path_list);
+        goto_if_null2(pathlist2, "Out of memory.", r, TSS2_FAPI_RC_MEMORY,
+                      cleanup);
+        n = *numPaths;
+
+        /* Move file names from list to array */
+        while (n > 0 && file_list) {
+            n -= 1;
+            pathlist2[n] = file_list->object;
+            head = file_list;
+            file_list = file_list->next;
+            SAFE_FREE(head);
+        }
+        *pathlist = pathlist2;
+    }
+ cleanup:
+    /* Free linked list with file names */
+    while (file_list) {
+        head = file_list;
+        file_list = file_list->next;
+        SAFE_FREE(head);
+    }
+    return r;
+}
+
+/** Determine whether a path exists.
+ *
+ * @param path The absolute path of the file.
+ * @retval true The file exists.
+ * @retval fale The file does not exist.
+ */
+bool
+ifapi_io_path_exists(const char *path)
+{
+     struct stat fbuffer;
+
+     if (stat(path, &fbuffer) == 0)
+         return true;
+     else
+         return false;
+}
+
+TSS2_RC
+ifapi_io_poll(IFAPI_IO * io) {
+    /* Check for NULL parameters */
+    check_not_null(io);
+
+    if(io->pollevents) {
+        struct pollfd fds;
+        fds.events = io->pollevents;
+        fds.fd = fileno(io->stream);
+        LOG_TRACE("Waiting for fd %i with event %i", fds.fd, fds.events);
+        poll(&fds, 1, -1);
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+TSS2_RC
+ifapi_io_poll_handles(IFAPI_IO *io, FAPI_POLL_HANDLE **handles, size_t *num_handles) {
+    /* Check for NULL parameters */
+    check_not_null(io);
+    check_not_null(handles);
+    check_not_null(num_handles);
+
+    if (!io->pollevents) {
+        /* We're not spilling out error here, because this is called in the
+           functional path of Fapi_GetPollHandles(). */
+        LOG_DEBUG("No pollable operation in progress.");
+        return TSS2_FAPI_RC_NO_HANDLE;
+    }
+
+    *handles = calloc(1, sizeof(**handles));
+    check_oom(*handles);
+    (*handles)->events = io->pollevents;
+    (*handles)->fd = fileno(io->stream);
+    *num_handles = 1;
+
+    LOG_TRACE("Returning %zi poll handles for fd %i with event %i",
+              *num_handles, (*handles)->fd, (*handles)->events);
+
+    return TSS2_RC_SUCCESS;
+}
diff --git a/src/tss2-fapi/ifapi_io.h b/src/tss2-fapi/ifapi_io.h
new file mode 100644
index 0000000..792fd63
--- /dev/null
+++ b/src/tss2-fapi/ifapi_io.h
@@ -0,0 +1,97 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ ******************************************************************************/
+
+#ifndef IFAPI_IO_H
+#define IFAPI_IO_H
+
+#include <stdio.h>
+#include <stdbool.h>
+#include "tss2_common.h"
+#include "tss2_fapi.h"
+
+typedef struct IFAPI_IO {
+    FILE *stream;
+    short pollevents;
+    const char *char_buffer;
+    char *char_rbuffer;
+    size_t buffer_length;
+    size_t buffer_idx;
+} IFAPI_IO;
+
+#ifdef TEST_FAPI_ASYNC
+#define _IFAPI_IO_RETRIES 1
+#else /* TEST_FAPI_ASYNC */
+#define _IFAPI_IO_RETRIES 0
+#endif /* TEST_FAPI_ASYNC */
+
+static int _ifapi_io_retry __attribute__((unused)) = _IFAPI_IO_RETRIES;
+
+#define IFAPI_IO_STREAM context->io.stream
+#define IFAPI_IO_BUFF context->io.char_buffer
+#define IFAPI_IO_RBUFF context->io.char_rbuffer
+#define IFAPI_IO_BUFFLEN context->io.buffer_length
+#define IFAPI_IO_BUFFIDX context->io.buffer_idx
+
+TSS2_RC
+ifapi_io_read_async(
+    struct IFAPI_IO *io,
+    const char *filename);
+
+TSS2_RC
+ifapi_io_read_finish(
+    struct IFAPI_IO *io,
+    uint8_t **buffer,
+    size_t *length);
+
+TSS2_RC
+ifapi_io_write_async(
+    struct IFAPI_IO *io,
+    const char *filename,
+    const uint8_t *buffer,
+    size_t length);
+
+TSS2_RC
+ifapi_io_write_finish(
+    struct IFAPI_IO *io);
+
+TSS2_RC
+ifapi_io_check_file_writeable(
+    const char *file);
+
+TSS2_RC
+ifapi_io_check_create_dir(
+    const char *dirname);
+
+TSS2_RC
+ifapi_io_remove_file(
+    const char *file);
+
+TSS2_RC
+ifapi_io_remove_directories(
+    const char *dirname);
+
+TSS2_RC
+ifapi_io_dirfiles(
+    const char *dirname,
+    char ***files,
+    size_t *numfiles);
+
+TSS2_RC
+ifapi_io_dirfiles_all(
+    const char *searchPath,
+    char ***pathlist,
+    size_t *numPaths);
+
+bool
+ifapi_io_path_exists(const char *path);
+
+TSS2_RC
+ifapi_io_poll(IFAPI_IO * io);
+
+TSS2_RC
+ifapi_io_poll_handles(IFAPI_IO *io, FAPI_POLL_HANDLE **handles, size_t *num_handles);
+
+#endif /* IFAPI_IO_H */
diff --git a/src/tss2-fapi/ifapi_json_deserialize.c b/src/tss2-fapi/ifapi_json_deserialize.c
new file mode 100644
index 0000000..74f8502
--- /dev/null
+++ b/src/tss2-fapi/ifapi_json_deserialize.c
@@ -0,0 +1,856 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ ******************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#include "tpm_json_deserialize.h"
+#include "ifapi_json_deserialize.h"
+#include "fapi_policy.h"
+#include "ifapi_config.h"
+#define LOGMODULE fapijson
+#include "util/log.h"
+#include "util/aux_util.h"
+
+static char *tss_const_prefixes[] = { "TPM2_ALG_", "TPM2_", "TPM_", "TPMA_", "POLICY", NULL};
+
+/** Get the index of a sub string after a certain prefix.
+ *
+ * The prefixes from table tss_const_prefixes will be used for case
+ * insensitive comparison.
+ *
+ * param[in] token the token with a potential prefix.
+ * @retval the position of the sub string after the prefix.
+ * @retval 0 if no prefix is found.
+ */
+
+static int
+get_token_start_idx(const char *token)
+{
+    int itoken = 0;
+    char *entry;
+    int i;
+
+    for (i = 0, entry = tss_const_prefixes[0]; entry != NULL;
+            i++, entry = tss_const_prefixes[i]) {
+        if (strncasecmp(token, entry, strlen(entry)) == 0) {
+            itoken += strlen(entry);
+            break;
+        }
+    }
+    return itoken;
+}
+
+/** Get number from a string.
+ *
+ * A string which represents a number or hex number (prefix 0x) is converted
+ * to an int64 number.
+ *
+ * param[in] token the string representing the number.
+ * param[out] num the converted number.
+ * @retval true if token represents a number
+ * @retval false if token does not represent a number.
+ */
+static bool
+get_number(const char *token, int64_t *num)
+{
+    int itoken = 0;
+    int pos = 0;
+    if (strncmp(token, "0x", 2) == 0) {
+        itoken = 2;
+        sscanf(&token[itoken], "%"PRIx64"%n", num, &pos);
+    } else {
+        sscanf(&token[itoken], "%"PRId64"%n", num, &pos);
+    }
+    if ((size_t)pos == strlen(token) - itoken)
+        return true;
+    else
+        return false;
+}
+
+/** Deserialize a character string.
+ *
+ * @param[in]in json string object.
+ * @param[out] out the pointer to the created string.
+ */
+TSS2_RC
+ifapi_json_char_deserialize(
+    json_object *jso,
+    char **out)
+{
+    *out = strdup(json_object_get_string(jso));
+    return_if_null(*out, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Deserialize a IFAPI_ENCRYPTED_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.
+ */
+TSS2_RC
+ifapi_json_IFAPI_ENCRYPTED_DATA_deserialize(json_object *jso,
+        IFAPI_ENCRYPTED_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, "type", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_UINT32_deserialize(jso2, &out->type);
+    return_if_error(r, "BAD VALUE");
+
+    if (!ifapi_get_sub_object(jso, "key_name", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_TPM2B_NAME_deserialize(jso2, &out->key_name);
+    return_if_error(r, "BAD VALUE");
+
+    if (!ifapi_get_sub_object(jso, "cipher", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_UINT8_ARY_deserialize(jso2, &out->cipher);
+    return_if_error(r, "BAD VALUE");
+
+    if (ifapi_get_sub_object(jso, "sym_key_size", &jso2)) {
+        r =  ifapi_json_UINT32_deserialize(jso2, &out->sym_key_size);
+        return_if_error(r, "BAD VALUE");
+
+        if (!ifapi_get_sub_object(jso, "sym_private", &jso2)) {
+            LOG_ERROR("Bad value");
+            return  TSS2_FAPI_RC_BAD_VALUE;
+        }
+
+        r =  ifapi_json_UINT8_ARY_deserialize(jso2, &out->sym_private);
+        return_if_error(r, "BAD VALUE");
+
+        if (!ifapi_get_sub_object(jso, "sym_public", &jso2)) {
+            LOG_ERROR("Bad value");
+            return  TSS2_FAPI_RC_BAD_VALUE;
+        }
+
+        r =  ifapi_json_TPM2B_PUBLIC_deserialize(jso2, &out->sym_public);
+        return_if_error(r, "BAD VALUE");
+
+        if (!ifapi_get_sub_object(jso, "sym_iv", &jso2)) {
+            LOG_ERROR("Bad value");
+            return  TSS2_FAPI_RC_BAD_VALUE;
+        }
+
+        r =  ifapi_json_TPM2B_DIGEST_deserialize(jso2, &out->sym_iv);
+        return_if_error(r, "BAD VALUE");
+
+        if (!ifapi_get_sub_object(jso, "policy", &jso2)) {
+            memset(&out->sym_policy_harness.policy, 0, sizeof(TPMS_POLICY_HARNESS));
+        } else {
+            r =  ifapi_json_TPMS_POLICY_HARNESS_deserialize(jso2, &out->sym_policy_harness);
+
+            return_if_error(r, "BAD VALUE");
+        }
+
+    } else {
+        out->sym_key_size = 0;
+    }
+
+    LOG_TRACE("true");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Deserialize a IFAPI_KEY json object.
+ *
+ * @param[in]  jso the json object to be deserialized.
+ * @param[out] out the deserialzed binary object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the json object can't be deserialized.
+ */
+TSS2_RC
+ifapi_json_IFAPI_KEY_deserialize(json_object *jso,  IFAPI_KEY *out)
+{
+    json_object *jso2;
+    TSS2_RC r;
+    LOG_TRACE("call");
+    return_if_null(out, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+
+    if (!ifapi_get_sub_object(jso, "persistent_handle", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_UINT32_deserialize(jso2, &out->persistent_handle);
+    return_if_error(r, "BAD VALUE");
+
+    if (ifapi_get_sub_object(jso, "with_auth", &jso2)) {
+        r =  ifapi_json_TPMI_YES_NO_deserialize(jso2, &out->with_auth);
+        return_if_error(r, "BAD VALUE");
+
+    } else {
+        out->with_auth = TPM2_NO;
+    }
+
+    if (!ifapi_get_sub_object(jso, "public", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_TPM2B_PUBLIC_deserialize(jso2, &out->public);
+    return_if_error(r, "BAD VALUE");
+
+    if (!ifapi_get_sub_object(jso, "serialization", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_UINT8_ARY_deserialize(jso2, &out->serialization);
+    return_if_error(r, "BAD VALUE");
+
+    if (!ifapi_get_sub_object(jso, "private", &jso2)) {
+        memset(&out->private, 0, sizeof(UINT8_ARY));
+    } else {
+        r =  ifapi_json_UINT8_ARY_deserialize(jso2, &out->private);
+        return_if_error(r, "BAD VALUE");
+    }
+
+    if (!ifapi_get_sub_object(jso, "appData", &jso2)) {
+        memset(&out->appData, 0, sizeof(UINT8_ARY));
+    } else {
+        r =  ifapi_json_UINT8_ARY_deserialize(jso2, &out->appData);
+        return_if_error(r, "BAD VALUE");
+    }
+
+    if (!ifapi_get_sub_object(jso, "policyInstance", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_char_deserialize(jso2, &out->policyInstance);
+    return_if_error(r, "BAD VALUE");
+
+    if (ifapi_get_sub_object(jso, "creationData", &jso2)) {
+        r =  ifapi_json_TPM2B_CREATION_DATA_deserialize(jso2, &out->creationData);
+        return_if_error(r, "BAD VALUE");
+
+    } else {
+        memset(&out->creationData, 0, sizeof(TPM2B_CREATION_DATA));
+    }
+
+    if (ifapi_get_sub_object(jso, "creationTicket", &jso2)) {
+        r =  ifapi_json_TPMT_TK_CREATION_deserialize(jso2, &out->creationTicket);
+        return_if_error(r, "BAD VALUE");
+
+    } else {
+        memset(&out->creationData, 0, sizeof(TPMT_TK_CREATION));
+    }
+    if (!ifapi_get_sub_object(jso, "description", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_char_deserialize(jso2, &out->description);
+    return_if_error(r, "BAD VALUE");
+
+    if (!ifapi_get_sub_object(jso, "certificate", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_char_deserialize(jso2, &out->certificate);
+    return_if_error(r, "BAD VALUE");
+
+    if (!ifapi_get_sub_object(jso, "signing_scheme", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_TPMT_SIG_SCHEME_deserialize(jso2, &out->signing_scheme);
+    return_if_error(r, "BAD VALUE");
+
+    if (!ifapi_get_sub_object(jso, "name", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_TPM2B_NAME_deserialize(jso2, &out->name);
+    return_if_error(r, "BAD VALUE");
+    LOG_TRACE("true");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Deserialize a IFAPI_EXT_PUB_KEY json object.
+ *
+ * @param[in]  jso the json object to be deserialized.
+ * @param[out] out the deserialzed binary object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the json object can't be deserialized.
+ */
+TSS2_RC
+ifapi_json_IFAPI_EXT_PUB_KEY_deserialize(json_object *jso,
+        IFAPI_EXT_PUB_KEY *out)
+{
+    json_object *jso2;
+    TSS2_RC r;
+    LOG_TRACE("call");
+    return_if_null(out, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+
+    if (!ifapi_get_sub_object(jso, "pem_ext_public", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_char_deserialize(jso2, &out->pem_ext_public);
+    return_if_error(r, "BAD VALUE");
+
+    if (ifapi_get_sub_object(jso, "certificate", &jso2)) {
+        r =  ifapi_json_char_deserialize(jso2, &out->certificate);
+        return_if_error(r, "BAD VALUE");
+    } else {
+        out->certificate = NULL;
+    }
+
+    if (ifapi_get_sub_object(jso, "public", &jso2)) {
+        r =  ifapi_json_TPM2B_PUBLIC_deserialize(jso2, &out->public);
+        return_if_error(r, "BAD VALUE");
+
+    } else {
+        memset(&out->public, 0, sizeof(TPM2B_PUBLIC));
+    }
+    LOG_TRACE("true");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Deserialize a IFAPI_NV json object.
+ *
+ * @param[in]  jso the json object to be deserialized.
+ * @param[out] out the deserialzed binary object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the json object can't be deserialized.
+ */
+TSS2_RC
+ifapi_json_IFAPI_NV_deserialize(json_object *jso,  IFAPI_NV *out)
+{
+    json_object *jso2;
+    TSS2_RC r;
+    LOG_TRACE("call");
+    return_if_null(out, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    if (!ifapi_get_sub_object(jso, "appData", &jso2)) {
+        memset(&out->appData, 0, sizeof(UINT8_ARY));
+    } else {
+        r =  ifapi_json_UINT8_ARY_deserialize(jso2, &out->appData);
+        return_if_error(r, "BAD VALUE");
+    }
+
+    if (ifapi_get_sub_object(jso, "with_auth", &jso2)) {
+        r =  ifapi_json_TPMI_YES_NO_deserialize(jso2, &out->with_auth);
+        return_if_error(r, "BAD VALUE");
+
+    } else {
+        out->with_auth = TPM2_NO;
+    }
+
+    if (!ifapi_get_sub_object(jso, "public", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_TPM2B_NV_PUBLIC_deserialize(jso2, &out->public);
+    return_if_error(r, "BAD VALUE");
+
+    if (!ifapi_get_sub_object(jso, "serialization", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_UINT8_ARY_deserialize(jso2, &out->serialization);
+    return_if_error(r, "BAD VALUE");
+
+    if (!ifapi_get_sub_object(jso, "hierarchy", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_UINT32_deserialize(jso2, &out->hierarchy);
+    return_if_error(r, "BAD VALUE");
+
+    if (!ifapi_get_sub_object(jso, "policyInstance", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_char_deserialize(jso2, &out->policyInstance);
+    return_if_error(r, "BAD VALUE");
+
+    if (!ifapi_get_sub_object(jso, "description", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_char_deserialize(jso2, &out->description);
+    return_if_error(r, "BAD VALUE");
+
+    return_if_error(r, "BAD VALUE");
+    if (ifapi_get_sub_object(jso, "event_log", &jso2)) {
+        r =  ifapi_json_char_deserialize(jso2, &out->event_log);
+        return_if_error(r, "BAD VALUE");
+
+    } else {
+        out->event_log = NULL;
+    }
+    LOG_TRACE("true");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Deserialize a IFAPI_NV json object.
+ *
+ * @param[in]  jso the json object to be deserialized.
+ * @param[out] out the deserialzed binary object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the json object can't be deserialized.
+ */
+TSS2_RC
+ifapi_json_IFAPI_HIERARCHY_deserialize(json_object *jso,  IFAPI_HIERARCHY *out)
+{
+    json_object *jso2;
+    TSS2_RC r;
+    LOG_TRACE("call");
+    return_if_null(out, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    if (ifapi_get_sub_object(jso, "with_auth", &jso2)) {
+        r =  ifapi_json_TPMI_YES_NO_deserialize(jso2, &out->with_auth);
+        return_if_error(r, "BAD VALUE");
+
+    } else {
+        out->with_auth = TPM2_NO;
+    }
+
+    if (!ifapi_get_sub_object(jso, "authPolicy", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_TPM2B_DIGEST_deserialize(jso2, &out->authPolicy);
+    return_if_error(r, "BAD VALUE");
+
+    if (!ifapi_get_sub_object(jso, "description", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_char_deserialize(jso2, &out->description);
+    return_if_error(r, "BAD VALUE");
+
+    LOG_TRACE("true");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Deserialize a FAPI_QUOTE_INFO json object.
+ *
+ * @param[in]  jso the json object to be deserialized.
+ * @param[out] out the deserialzed binary object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the json object can't be deserialized.
+ */
+TSS2_RC
+ifapi_json_FAPI_QUOTE_INFO_deserialize(json_object *jso,  FAPI_QUOTE_INFO *out)
+{
+    json_object *jso2;
+    TSS2_RC r;
+    LOG_TRACE("call");
+    return_if_null(out, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+
+    if (!ifapi_get_sub_object(jso, "sig_scheme", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_TPMT_SIG_SCHEME_deserialize(jso2, &out->sig_scheme);
+    return_if_error(r, "BAD VALUE");
+
+    if (!ifapi_get_sub_object(jso, "attest", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_TPMS_ATTEST_deserialize(jso2, &out->attest);
+    return_if_error(r, "BAD VALUE");
+    LOG_TRACE("true");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Deserialize a IFAPI_DUPLICATE json object.
+ *
+ * @param[in]  jso the json object to be deserialized.
+ * @param[out] out the deserialzed binary object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the json object can't be deserialized.
+ */
+TSS2_RC
+ifapi_json_IFAPI_DUPLICATE_deserialize(json_object *jso, IFAPI_DUPLICATE *out)
+{
+    json_object *jso2;
+    TSS2_RC r;
+    LOG_TRACE("call");
+    return_if_null(out, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    if (!ifapi_get_sub_object(jso, "duplicate", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+
+    r =  ifapi_json_TPM2B_PRIVATE_deserialize(jso2, &out->duplicate);
+    return_if_error(r, "BAD VALUE");
+
+    if (!ifapi_get_sub_object(jso, "encrypted_seed", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_TPM2B_ENCRYPTED_SECRET_deserialize(jso2, &out->encrypted_seed);
+    return_if_error(r, "BAD VALUE");
+
+    if (ifapi_get_sub_object(jso, "certificate", &jso2)) {
+        r =  ifapi_json_char_deserialize(jso2, &out->certificate);
+        return_if_error(r, "BAD VALUE");
+
+    } else {
+        out->certificate = NULL;
+    }
+
+    if (!ifapi_get_sub_object(jso, "public", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+
+    r =  ifapi_json_TPM2B_PUBLIC_deserialize(jso2, &out->public);
+    return_if_error(r, "BAD VALUE");
+    if (!ifapi_get_sub_object(jso, "public_parent", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+
+    r =  ifapi_json_TPM2B_PUBLIC_deserialize(jso2, &out->public_parent);
+    return_if_error(r, "BAD VALUE");
+
+    return TSS2_RC_SUCCESS;
+}
+
+/**  Deserialize a IFAPI_OBJECT_TYPE_CONSTANT json object.
+ *
+ * @param[in]  jso the json object to be deserialized.
+ * @param[out] out the deserialzed binary object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the json object can't be deserialized.
+ */
+
+TSS2_RC
+ifapi_json_IFAPI_OBJECT_TYPE_CONSTANT_deserialize(json_object *jso,
+        IFAPI_OBJECT_TYPE_CONSTANT *out)
+{
+    LOG_TRACE("call");
+    const char *token = json_object_get_string(jso);
+    int64_t i64;
+    if (get_number(token, &i64)) {
+        *out = (IFAPI_OBJECT_TYPE_CONSTANT) i64;
+        if ((int64_t)*out != i64) {
+            LOG_ERROR("Bad value");
+            return  TSS2_FAPI_RC_BAD_VALUE;
+        }
+        return TSS2_RC_SUCCESS;
+    } else {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+}
+
+/** Deserialize a IFAPI_OBJECT json object.
+ *
+ * @param[in]  jso the json object to be deserialized.
+ * @param[out] out the deserialzed binary object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the json object can't be deserialized.
+ */
+TSS2_RC
+ifapi_json_IFAPI_OBJECT_deserialize(json_object *jso, IFAPI_OBJECT *out)
+{
+    json_object *jso2;
+    TSS2_RC r;
+    LOG_TRACE("call");
+    return_if_null(out, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    if (!ifapi_get_sub_object(jso, "objectType", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+
+    r =  ifapi_json_IFAPI_OBJECT_TYPE_CONSTANT_deserialize(jso2, &out->objectType);
+    return_if_error(r, "BAD VALUE");
+
+    switch (out->objectType) {
+    case IFAPI_NV_OBJ:
+        r = ifapi_json_IFAPI_NV_deserialize(jso, &out->misc.nv);
+        return_if_error(r, "BAD VALUE");
+        break;
+
+    case IFAPI_DUPLICATE_OBJ:
+        r = ifapi_json_IFAPI_DUPLICATE_deserialize(jso, &out->misc.key_tree);
+        return_if_error(r, "BAD VALUE");
+
+        break;
+
+    case IFAPI_EXT_PUB_KEY_OBJ:
+        r = ifapi_json_IFAPI_EXT_PUB_KEY_deserialize(jso, &out->misc.ext_pub_key);
+        return_if_error(r, "BAD VALUE");
+
+        break;
+
+    case IFAPI_HIERARCHY_OBJ:
+        r = ifapi_json_IFAPI_HIERARCHY_deserialize(jso, &out->misc.hierarchy);
+        return_if_error(r, "BAD VALUE");
+
+        break;
+    case IFAPI_KEY_OBJ:
+        r = ifapi_json_IFAPI_KEY_deserialize(jso, &out->misc.key);
+        return_if_error(r, "BAD VALUE");
+
+        break;
+    default:
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Invalid call deserialize",
+                   cleanup);
+    }
+
+    if (ifapi_get_sub_object(jso, "system", &jso2)) {
+        r =  ifapi_json_TPMI_YES_NO_deserialize(jso2, &out->system);
+        return_if_error(r, "BAD VALUE");
+
+    } else {
+        out->system = TPM2_NO;
+    }
+
+    if (ifapi_get_sub_object(jso, "policy_harness", &jso2)) {
+        out->policy_harness = calloc(1, sizeof(TPMS_POLICY_HARNESS));
+        goto_if_null2(out->policy_harness, "Out of memory.", r, TSS2_FAPI_RC_MEMORY,
+                      cleanup);
+
+        r =  ifapi_json_TPMS_POLICY_HARNESS_deserialize(jso2, out->policy_harness);
+        goto_if_error(r, "Deserialize policy harness.", cleanup);
+    } else {
+        out->policy_harness = NULL;
+    }
+
+    return TSS2_RC_SUCCESS;
+
+cleanup:
+    SAFE_FREE(out->policy_harness);
+    return r;
+}
+
+/** Deserialize a IFAPI_EVENT_TYPE json object.
+ *
+ * @param[in]  jso the json object to be deserialized.
+ * @param[out] out the deserialzed binary object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the json object can't be deserialized.
+ */
+TSS2_RC
+ifapi_json_IFAPI_EVENT_TYPE_deserialize(json_object *jso, IFAPI_EVENT_TYPE *out)
+{
+    LOG_TRACE("call");
+    return ifapi_json_IFAPI_EVENT_TYPE_deserialize_txt(jso, out);
+}
+
+typedef struct {
+    IFAPI_EVENT_TYPE in;
+    char *name;
+} IFAPI_IFAPI_EVENT_TYPE_ASSIGN;
+
+static IFAPI_IFAPI_EVENT_TYPE_ASSIGN deserialize_IFAPI_EVENT_TYPE_tab[] = {
+    { IFAPI_IMA_EVENT_TAG, "ima-legacy" },
+    { IFAPI_TSS_EVENT_TAG, "tss2" },
+};
+
+/**  Deserialize a json object of type IFAPI_EVENT_TYPE.
+ *
+ * @param[in]  jso the json object to be deserialized.
+ * @param[out] out the deserialzed binary object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the json object can't be deserialized.
+ */
+TSS2_RC
+ifapi_json_IFAPI_EVENT_TYPE_deserialize_txt(json_object *jso,
+        IFAPI_EVENT_TYPE *out)
+{
+    LOG_TRACE("call");
+    const char *token = json_object_get_string(jso);
+    int64_t i64;
+    if (get_number(token, &i64)) {
+        *out = (IFAPI_EVENT_TYPE) i64;
+        if ((int64_t)*out != i64) {
+            LOG_ERROR("Bad value");
+            return  TSS2_FAPI_RC_BAD_VALUE;
+        }
+        return TSS2_RC_SUCCESS;
+
+    } else {
+        int itoken = get_token_start_idx(token);
+        size_t i;
+        size_t n = sizeof(deserialize_IFAPI_EVENT_TYPE_tab) /
+                   sizeof(deserialize_IFAPI_EVENT_TYPE_tab[0]);
+        size_t size = strlen(token) - itoken;
+        for (i = 0; i < n; i++) {
+            if (strncasecmp(&token[itoken],
+                            &deserialize_IFAPI_EVENT_TYPE_tab[i].name[0],
+                            size) == 0) {
+                *out =  deserialize_IFAPI_EVENT_TYPE_tab[i].in;
+                return TSS2_RC_SUCCESS;
+            }
+        }
+        return_error(TSS2_FAPI_RC_BAD_VALUE, "Undefined constant.");
+    }
+
+}
+
+/** Deserialize a IFAPI_TSS_EVENT json object.
+ *
+ * @param[in]  jso the json object to be deserialized.
+ * @param[out] out the deserialzed binary object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the json object can't be deserialized.
+ */
+TSS2_RC
+ifapi_json_IFAPI_TSS_EVENT_deserialize(json_object *jso,  IFAPI_TSS_EVENT *out)
+{
+    json_object *jso2;
+    TSS2_RC r;
+    LOG_TRACE("call");
+    return_if_null(out, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+
+    if (!ifapi_get_sub_object(jso, "data", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_TPM2B_EVENT_deserialize(jso2, &out->data);
+    return_if_error(r, "BAD VALUE");
+
+    if (!ifapi_get_sub_object(jso, "event", &jso2)) {
+        out->event = NULL;
+    } else {
+        r =  ifapi_json_char_deserialize(jso2, &out->event);
+        return_if_error(r, "BAD VALUE");
+
+    }
+    LOG_TRACE("true");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Deserialize a IFAPI_IMA_EVENT json object.
+ *
+ * @param[in]  jso the json object to be deserialized.
+ * @param[out] out the deserialzed binary object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the json object can't be deserialized.
+ */
+TSS2_RC
+ifapi_json_IFAPI_IMA_EVENT_deserialize(json_object *jso,  IFAPI_IMA_EVENT *out)
+{
+    json_object *jso2;
+    TSS2_RC r;
+    LOG_TRACE("call");
+    return_if_null(out, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+
+    if (!ifapi_get_sub_object(jso, "eventData", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_TPM2B_DIGEST_deserialize(jso2, &out->eventData);
+    return_if_error(r, "BAD VALUE");
+
+    if (!ifapi_get_sub_object(jso, "eventName", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_char_deserialize(jso2, &out->eventName);
+    return_if_error(r, "BAD VALUE");
+    LOG_TRACE("true");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Deserialize a IFAPI_EVENT_UNION json object.
+ *
+ * This functions expects the Bitfield to be encoded as unsigned int in host-endianess.
+ * @param[in]  jso the json object to be deserialized.
+ * @param[out] out the deserialzed binary object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the json object can't be deserialized.
+ */
+TSS2_RC
+ifapi_json_IFAPI_EVENT_UNION_deserialize(
+    UINT32 selector,
+    json_object *jso,
+    IFAPI_EVENT_UNION *out)
+{
+    LOG_TRACE("call");
+    switch (selector) {
+    case IFAPI_TSS_EVENT_TAG:
+        return ifapi_json_IFAPI_TSS_EVENT_deserialize(jso, &out->tss_event);
+    case IFAPI_IMA_EVENT_TAG:
+        return ifapi_json_IFAPI_IMA_EVENT_deserialize(jso, &out->ima_event);
+    default:
+        LOG_TRACE("false");
+        return TSS2_FAPI_RC_BAD_VALUE;
+    };
+}
+
+/** Deserialize a IFAPI_EVENT json object.
+ *
+ * @param[in]  jso the json object to be deserialized.
+ * @param[out] out the deserialzed binary object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the json object can't be deserialized.
+ */
+TSS2_RC
+ifapi_json_IFAPI_EVENT_deserialize(json_object *jso,  IFAPI_EVENT *out)
+{
+    json_object *jso2;
+    TSS2_RC r;
+    LOG_TRACE("call");
+    return_if_null(out, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+
+    if (!ifapi_get_sub_object(jso, "recnum", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_UINT32_deserialize(jso2, &out->recnum);
+    return_if_error(r, "BAD VALUE");
+
+    if (!ifapi_get_sub_object(jso, "pcr", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_TPM2_HANDLE_deserialize(jso2, &out->pcr);
+    return_if_error(r, "BAD VALUE");
+
+    if (!ifapi_get_sub_object(jso, "digests", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_TPML_DIGEST_VALUES_deserialize(jso2, &out->digests);
+    return_if_error(r, "BAD VALUE");
+
+    if (!ifapi_get_sub_object(jso, "type", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_IFAPI_EVENT_TYPE_deserialize(jso2, &out->type);
+    return_if_error(r, "BAD VALUE");
+
+    if (!ifapi_get_sub_object(jso, "sub_event", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_IFAPI_EVENT_UNION_deserialize(out->type, jso2, &out->sub_event);
+    return_if_error(r, "BAD VALUE");
+    LOG_TRACE("true");
+    return TSS2_RC_SUCCESS;
+}
diff --git a/src/tss2-fapi/ifapi_json_deserialize.h b/src/tss2-fapi/ifapi_json_deserialize.h
new file mode 100644
index 0000000..c43cd01
--- /dev/null
+++ b/src/tss2-fapi/ifapi_json_deserialize.h
@@ -0,0 +1,82 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ ******************************************************************************/
+#ifndef IFAPI_JSON_DESERIALIZE_H
+#define IFAPI_JSON_DESERIALIZE_H
+
+#include <stdbool.h>
+#include <json-c/json.h>
+#include <json-c/json_util.h>
+
+#include "tss2_tpm2_types.h"
+#include "ifapi_keystore.h"
+#include "fapi_int.h"
+
+#define YES 1
+#define NO 0
+
+#define GET_OPTIONAL(name, json_name, type) \
+    if (!ifapi_get_sub_object(jso, json_name, &jso2)) { \
+        memset(&out->name, 0, sizeof(type)); \
+    } else { \
+        r =  ifapi_json_ ## type ## _deserialize (jso2, &out->name); \
+        return_if_error(r,"BAD VALUE"); \
+    }
+
+bool
+ifapi_get_sub_object(json_object *jso, char *name, json_object **sub_jso);
+
+TSS2_RC
+ifapi_json_char_deserialize(json_object *jso, char **out);
+
+TSS2_RC
+ifapi_json_IFAPI_ENCRYPTED_DATA_deserialize(json_object *jso,
+        IFAPI_ENCRYPTED_DATA *out);
+
+TSS2_RC
+ifapi_json_IFAPI_OBJECT_TYPE_CONSTANT_deserialize(json_object *jso,
+        IFAPI_OBJECT_TYPE_CONSTANT *out);
+
+TSS2_RC
+ifapi_json_IFAPI_KEY_deserialize(json_object *jso, IFAPI_KEY *out);
+
+TSS2_RC
+ifapi_json_IFAPI_EXT_PUB_KEY_deserialize(json_object *jso,
+        IFAPI_EXT_PUB_KEY *out);
+
+TSS2_RC
+ifapi_json_IFAPI_NV_deserialize(json_object *jso, IFAPI_NV *out);
+
+TSS2_RC
+ifapi_json_IFAPI_HIERARCHY_deserialize(json_object *jso,  IFAPI_HIERARCHY *out);
+
+TSS2_RC
+ifapi_json_IFAPI_OBJECT_deserialize(json_object *jso, IFAPI_OBJECT *out);
+
+TSS2_RC
+ifapi_json_FAPI_QUOTE_INFO_deserialize(json_object *jso, FAPI_QUOTE_INFO *out);
+
+TSS2_RC
+ifapi_json_IFAPI_EVENT_TYPE_deserialize(json_object *jso,
+                                        IFAPI_EVENT_TYPE *out);
+
+TSS2_RC
+ifapi_json_IFAPI_EVENT_TYPE_deserialize_txt(json_object *jso,
+        IFAPI_EVENT_TYPE *out);
+
+TSS2_RC
+ifapi_json_IFAPI_TSS_EVENT_deserialize(json_object *jso, IFAPI_TSS_EVENT *out);
+
+TSS2_RC
+ifapi_json_IFAPI_IMA_EVENT_deserialize(json_object *jso, IFAPI_IMA_EVENT *out);
+
+TSS2_RC
+ifapi_json_IFAPI_EVENT_UNION_deserialize(UINT32 selector, json_object *jso,
+        IFAPI_EVENT_UNION *out);
+
+TSS2_RC
+ifapi_json_IFAPI_EVENT_deserialize(json_object *jso, IFAPI_EVENT *out);
+
+#endif /* IFAPI_JSON_DESERIALIZE_H */
diff --git a/src/tss2-fapi/ifapi_json_serialize.c b/src/tss2-fapi/ifapi_json_serialize.c
new file mode 100644
index 0000000..354b353
--- /dev/null
+++ b/src/tss2-fapi/ifapi_json_serialize.c
@@ -0,0 +1,842 @@
+/* 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 "ifapi_json_serialize.h"
+#include "tpm_json_serialize.h"
+#include "fapi_policy.h"
+#include "ifapi_policy_json_serialize.h"
+
+#define LOGMODULE fapijson
+#include "util/log.h"
+#include "util/aux_util.h"
+
+TSS2_RC
+ifapi_json_char_serialize(
+    const char *in,
+    json_object **jso)
+{
+    if (in == NULL) {
+        *jso = json_object_new_string("");
+    } else {
+        *jso = json_object_new_string(in);
+    }
+    return_if_null(jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type UINT8_ARY to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPM2B_DIGEST.
+ */
+TSS2_RC
+ifapi_json_UINT8_ARY_serialize(const UINT8_ARY *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    char hex_string[(in->size) * 2 + 1];
+
+    if (in->size > 0) {
+        uint8_t *buffer = in->buffer;
+
+        for (size_t i = 0, off = 0; i < in->size; i++, off += 2)
+            sprintf(&hex_string[off], "%02x", buffer[i]);
+    }
+    hex_string[(in->size) * 2] = '\0';
+    *jso = json_object_new_string(hex_string);
+    return_if_null(*jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type IFAPI_ENCRYPTED_DATA to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type IFAPI_ENCRYPTED_DATA.
+ */
+TSS2_RC
+ifapi_json_IFAPI_ENCRYPTED_DATA_serialize(const IFAPI_ENCRYPTED_DATA *in,
+        json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+
+    if (*jso == NULL)
+        *jso = json_object_new_object();
+    jso2 = NULL;
+    r = ifapi_json_UINT32_serialize(in->type, &jso2);
+    return_if_error(r, "Serialize UINT32");
+
+    json_object_object_add(*jso, "type", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_NAME_serialize(&in->key_name, &jso2);
+    return_if_error(r, "Serialize TPM2B_NAME");
+
+    json_object_object_add(*jso, "key_name", jso2);
+    jso2 = NULL;
+    r = ifapi_json_UINT8_ARY_serialize(&in->cipher, &jso2);
+    return_if_error(r, "Serialize UINT8_ARY");
+
+    json_object_object_add(*jso, "cipher", jso2);
+
+    if (in->sym_key_size > 0) {
+        /* A sealed symmetric key is used for encryption */
+        jso2 = NULL;
+        r = ifapi_json_TPM2B_PUBLIC_serialize(&in->sym_public, &jso2);
+        return_if_error(r, "Serialize TPM2B_PUBLIC");
+
+        json_object_object_add(*jso, "sym_public", jso2);
+
+        jso2 = NULL;
+        r = ifapi_json_UINT8_ARY_serialize(&in->sym_private, &jso2);
+        return_if_error(r, "Serialize UINT8_ARY");
+
+        json_object_object_add(*jso, "sym_private", jso2);
+
+        jso2 = NULL;
+        r = ifapi_json_UINT32_serialize(in->sym_key_size, &jso2);
+        return_if_error(r, "Serialize UINT32");
+
+        json_object_object_add(*jso, "sym_key_size", jso2);
+
+        jso2 = NULL;
+        r = ifapi_json_TPM2B_DIGEST_serialize(&in->sym_iv, &jso2);
+        return_if_error(r, "Serialize iv");
+
+        json_object_object_add(*jso, "sym_iv", jso2);
+
+        if (in->sym_policy_harness.policy) {
+            jso2 = NULL;
+            r = ifapi_json_TPMS_POLICY_HARNESS_serialize(&in->sym_policy_harness, &jso2);
+            return_if_error(r, "Serialize policy");
+
+            json_object_object_add(*jso, "policy", jso2);
+        }
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type IFAPI_KEY to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type IFAPI_KEY.
+ */
+TSS2_RC
+ifapi_json_IFAPI_KEY_serialize(const IFAPI_KEY *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+
+    if (*jso == NULL)
+        *jso = json_object_new_object();
+    jso2 = NULL;
+    r = ifapi_json_TPMI_YES_NO_serialize(in->with_auth, &jso2);
+    return_if_error(r, "Serialize TPMI_YES_NO");
+
+    json_object_object_add(*jso, "with_auth", jso2);
+    jso2 = NULL;
+    r = ifapi_json_UINT32_serialize(in->persistent_handle, &jso2);
+    return_if_error(r, "Serialize UINT32");
+
+    json_object_object_add(*jso, "persistent_handle", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_PUBLIC_serialize(&in->public, &jso2);
+    return_if_error(r, "Serialize TPM2B_PUBLIC");
+
+    json_object_object_add(*jso, "public", jso2);
+    jso2 = NULL;
+    r = ifapi_json_UINT8_ARY_serialize(&in->serialization, &jso2);
+    return_if_error(r, "Serialize UINT8_ARY");
+
+    json_object_object_add(*jso, "serialization", jso2);
+    if (in->private.buffer != NULL) {
+        jso2 = NULL;
+        r = ifapi_json_UINT8_ARY_serialize(&in->private, &jso2);
+        return_if_error(r, "Serialize UINT8_ARY");
+
+        json_object_object_add(*jso, "private", jso2);
+    }
+    if (in->appData.buffer != NULL) {
+        jso2 = NULL;
+        r = ifapi_json_UINT8_ARY_serialize(&in->appData, &jso2);
+        return_if_error(r, "Serialize UINT8_ARY");
+
+        json_object_object_add(*jso, "appData", jso2);
+    }
+    jso2 = NULL;
+    r = ifapi_json_char_serialize(in->policyInstance, &jso2);
+    return_if_error(r, "Serialize char");
+
+    json_object_object_add(*jso, "policyInstance", jso2);
+
+    /* Creation Data is not available for imported keys */
+    if (in->creationData.size) {
+        jso2 = NULL;
+        r = ifapi_json_TPM2B_CREATION_DATA_serialize(&in->creationData, &jso2);
+        return_if_error(r, "Serialize TPM2B_CREATION_DATA");
+
+        json_object_object_add(*jso, "creationData", jso2);
+    }
+    /* Creation Ticket is not available for imported keys */
+    if (in->creationTicket.tag) {
+        jso2 = NULL;
+        r = ifapi_json_TPMT_TK_CREATION_serialize(&in->creationTicket, &jso2);
+        return_if_error(r, "Serialize TPMT_TK_CREATION");
+
+        json_object_object_add(*jso, "creationTicket", jso2);
+    }
+    jso2 = NULL;
+    r = ifapi_json_char_serialize(in->description, &jso2);
+    return_if_error(r, "Serialize char");
+
+    json_object_object_add(*jso, "description", jso2);
+    jso2 = NULL;
+    r = ifapi_json_char_serialize(in->certificate, &jso2);
+    return_if_error(r, "Serialize char");
+
+    json_object_object_add(*jso, "certificate", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPMT_SIG_SCHEME_serialize(&in->signing_scheme, &jso2);
+    return_if_error(r, "Serialize TPMT_SIG_SCHEME");
+
+    json_object_object_add(*jso, "signing_scheme", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_NAME_serialize(&in->name, &jso2);
+    return_if_error(r, "Serialize TPM2B_NAME");
+
+    json_object_object_add(*jso, "name", jso2);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type IFAPI_EXT_PUB_KEY to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type IFAPI_EXT_PUB_KEY.
+ */
+TSS2_RC
+ifapi_json_IFAPI_EXT_PUB_KEY_serialize(const IFAPI_EXT_PUB_KEY *in,
+                                       json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+
+    if (*jso == NULL)
+        *jso = json_object_new_object();
+    jso2 = NULL;
+    r = ifapi_json_char_serialize(in->pem_ext_public, &jso2);
+    return_if_error(r, "Serialize char");
+
+    json_object_object_add(*jso, "pem_ext_public", jso2);
+    jso2 = NULL;
+    if (in->certificate) {
+        r = ifapi_json_char_serialize(in->certificate, &jso2);
+        return_if_error(r, "Serialize char");
+
+        json_object_object_add(*jso, "certificate", jso2);
+    }
+    if (in->public.publicArea.type) {
+        /* Public area was initialized */
+        jso2 = NULL;
+        r = ifapi_json_TPM2B_PUBLIC_serialize(&in->public, &jso2);
+        return_if_error(r, "Serialize TPM2B_PUBLIC");
+
+        json_object_object_add(*jso, "public", jso2);
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type IFAPI_NV to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type IFAPI_NV.
+ */
+TSS2_RC
+ifapi_json_IFAPI_NV_serialize(const IFAPI_NV *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+
+    if (*jso == NULL)
+        *jso = json_object_new_object();
+    jso2 = NULL;
+    r = ifapi_json_TPMI_YES_NO_serialize(in->with_auth, &jso2);
+    return_if_error(r, "Serialize TPMI_YES_NO");
+
+    json_object_object_add(*jso, "with_auth", jso2);
+
+    /* Add tag to classify json NV objects without deserialization */
+    jso2 = json_object_new_boolean(true);
+    json_object_object_add(*jso, "nv_object", jso2);
+
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_NV_PUBLIC_serialize(&in->public, &jso2);
+    return_if_error(r, "Serialize TPM2B_NV_PUBLIC");
+
+    json_object_object_add(*jso, "public", jso2);
+    jso2 = NULL;
+    r = ifapi_json_UINT8_ARY_serialize(&in->serialization, &jso2);
+    return_if_error(r, "Serialize UINT8_ARY");
+
+    json_object_object_add(*jso, "serialization", jso2);
+    jso2 = NULL;
+    r = ifapi_json_UINT32_serialize(in->hierarchy, &jso2);
+    return_if_error(r, "Serialize UINT32");
+
+    json_object_object_add(*jso, "hierarchy", jso2);
+    jso2 = NULL;
+    r = ifapi_json_char_serialize(in->policyInstance, &jso2);
+    return_if_error(r, "Serialize char");
+
+    json_object_object_add(*jso, "policyInstance", jso2);
+    jso2 = NULL;
+    r = ifapi_json_char_serialize(in->description, &jso2);
+    return_if_error(r, "Serialize char");
+
+    json_object_object_add(*jso, "description", jso2);
+
+    if (in->appData.buffer != NULL) {
+        jso2 = NULL;
+        r = ifapi_json_UINT8_ARY_serialize(&in->appData, &jso2);
+        return_if_error(r, "Serialize UINT8_ARY");
+
+        json_object_object_add(*jso, "appData", jso2);
+    }
+    jso2 = NULL;
+    if (in->event_log) {
+        r = ifapi_json_char_serialize(in->event_log, &jso2);
+        return_if_error(r, "Serialize event log");
+
+        json_object_object_add(*jso, "event_log", jso2);
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type IFAPI_NV to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type IFAPI_NV.
+ */
+TSS2_RC
+ifapi_json_IFAPI_HIERARCHY_serialize(const IFAPI_HIERARCHY *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+
+    if (*jso == NULL)
+        *jso = json_object_new_object();
+    jso2 = NULL;
+    r = ifapi_json_TPMI_YES_NO_serialize(in->with_auth, &jso2);
+    return_if_error(r, "Serialize TPMI_YES_NO");
+
+    json_object_object_add(*jso, "with_auth", jso2);
+
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_DIGEST_serialize(&in->authPolicy, &jso2);
+    return_if_error(r, "Serialize TPM2B_DIGEST");
+
+    json_object_object_add(*jso, "authPolicy", jso2);
+
+    jso2 = NULL;
+    r = ifapi_json_char_serialize(in->description, &jso2);
+    return_if_error(r, "Serialize char");
+
+    json_object_object_add(*jso, "description", jso2);
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type FAPI_QUOTE_INFO to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type FAPI_QUOTE_INFO.
+ */
+TSS2_RC
+ifapi_json_FAPI_QUOTE_INFO_serialize(const FAPI_QUOTE_INFO *in,
+                                     json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+
+    if (*jso == NULL)
+        *jso = json_object_new_object();
+    jso2 = NULL;
+    r = ifapi_json_TPMT_SIG_SCHEME_serialize(&in->sig_scheme, &jso2);
+    return_if_error(r, "Serialize TPMT_SIG_SCHEME");
+
+    json_object_object_add(*jso, "sig_scheme", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPMS_ATTEST_serialize(&in->attest, &jso2);
+    return_if_error(r, "Serialize TPMS_ATTEST");
+
+    json_object_object_add(*jso, "attest", jso2);
+    return TSS2_RC_SUCCESS;
+}
+
+
+/** Serialize value of type IFAPI_DUPLICATE to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_POLICY_HARNESS.
+ */
+TSS2_RC
+ifapi_json_IFAPI_DUPLICATE_serialize(const IFAPI_DUPLICATE *in,
+                                     json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+
+    if (*jso == NULL)
+        *jso = json_object_new_object();
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_PRIVATE_serialize(&in->duplicate, &jso2);
+    return_if_error(r, "Serialize TPM2B_PRIVATE");
+
+    json_object_object_add(*jso, "duplicate", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_ENCRYPTED_SECRET_serialize(&in->encrypted_seed, &jso2);
+    return_if_error(r, "Serialize TPM2B_ENCRYPTED_SECRET");
+
+    json_object_object_add(*jso, "encrypted_seed", jso2);
+    jso2 = NULL;
+    if (in->certificate) {
+        r = ifapi_json_char_serialize(in->certificate, &jso2);
+        return_if_error(r, "Serialize certificate");
+
+        json_object_object_add(*jso, "certificate", jso2);
+    }
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_PUBLIC_serialize(&in->public, &jso2);
+    return_if_error(r, "Serialize TPM2B_PUBLIC");
+
+    json_object_object_add(*jso, "public", jso2);
+
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_PUBLIC_serialize(&in->public_parent, &jso2);
+    return_if_error(r, "Serialize TPM2B_PUBLIC");
+
+    json_object_object_add(*jso, "public_parent", jso2);
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type IFAPI_OBJECT_TYPE_CONSTANT to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPM2_HANDLE.
+ */
+
+TSS2_RC
+ifapi_json_IFAPI_OBJECT_TYPE_CONSTANT_serialize(const IFAPI_OBJECT_TYPE_CONSTANT
+        in, json_object **jso)
+{
+    *jso = json_object_new_int(in);
+    if (*jso == NULL) {
+        LOG_ERROR("Bad value %"PRIx32 "", in);
+        return TSS2_FAPI_RC_BAD_VALUE;
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize a IFAPI_OBJECT to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type IFAPI_OBJECT.
+ */
+TSS2_RC
+ifapi_json_IFAPI_OBJECT_serialize(const IFAPI_OBJECT *in,
+                                  json_object **jso)
+{
+    TSS2_RC r;
+
+    if (*jso == NULL)
+        *jso = json_object_new_object();
+    return_if_null(*jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+    json_object *jso2;
+
+    jso2 = NULL;
+    r = ifapi_json_IFAPI_OBJECT_TYPE_CONSTANT_serialize(in->objectType, &jso2);
+    return_if_error(r, "Serialize IFAPI_OBJECT");
+
+    json_object_object_add(*jso, "objectType", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPMI_YES_NO_serialize(in->system, &jso2);
+    return_if_error(r, "Serialize TPMI_YES_NO");
+
+    json_object_object_add(*jso, "system", jso2);
+
+    switch (in->objectType) {
+    case IFAPI_HIERARCHY_OBJ:
+        r = ifapi_json_IFAPI_HIERARCHY_serialize(&in->misc.hierarchy, jso);
+        return_if_error(r, "Error serialize FAPI hierarchy object");
+
+        break;
+    case IFAPI_NV_OBJ:
+        r = ifapi_json_IFAPI_NV_serialize(&in->misc.nv, jso);
+        return_if_error(r, "Error serialize FAPI NV object");
+
+        break;
+
+    case IFAPI_DUPLICATE_OBJ:
+        r = ifapi_json_IFAPI_DUPLICATE_serialize(&in->misc.key_tree, jso);
+        return_if_error(r, "Serialize IFAPI_OBJECT");
+
+        break;
+
+    case IFAPI_KEY_OBJ:
+        r = ifapi_json_IFAPI_KEY_serialize(&in->misc.key, jso);
+        return_if_error(r, "Error serialize FAPI KEY object");
+        break;
+
+    case IFAPI_EXT_PUB_KEY_OBJ:
+        r = ifapi_json_IFAPI_EXT_PUB_KEY_serialize(&in->misc.ext_pub_key, jso);
+        return_if_error(r, "Serialize IFAPI_OBJECT");
+
+        break;
+
+    default:
+        return_error(TSS2_FAPI_RC_GENERAL_FAILURE, "Invalid call get_json");
+    }
+
+    if (in->policy_harness) {
+        jso2 = NULL;
+        r = ifapi_json_TPMS_POLICY_HARNESS_serialize(in->policy_harness, &jso2);
+        return_if_error(r, "Serialize policy");
+
+        json_object_object_add(*jso, "policy_harness", jso2);
+    }
+
+    if (in->policy_harness) {
+        jso2 = NULL;
+        r = ifapi_json_TPMS_POLICY_HARNESS_serialize(in->policy_harness, &jso2);
+        return_if_error(r, "Serialize policy");
+
+        json_object_object_add(*jso, "policy_harness", jso2);
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type IFAPI_CAP_INFO to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type IFAPI_INFO.
+ */
+TSS2_RC
+ifapi_json_IFAPI_CAP_INFO_serialize(const IFAPI_CAP_INFO *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+
+    if (*jso == NULL)
+        *jso = json_object_new_object();
+    jso2 = NULL;
+    r = ifapi_json_char_serialize(in->description, &jso2);
+    return_if_error(r, "Serialize char");
+
+    json_object_object_add(*jso, "description", jso2);
+
+    jso2 = NULL;
+    r = ifapi_json_TPMS_CAPABILITY_DATA_serialize(in->capability, &jso2);
+    return_if_error(r, "Serialize TPMS_CAPABILITY_DATA");
+
+    json_object_object_add(*jso, "info", jso2);
+
+    return TSS2_RC_SUCCESS;
+}
+
+
+/** Serialize value of type IFAPI_INFO to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type IFAPI_INFO.
+ */
+TSS2_RC
+ifapi_json_IFAPI_INFO_serialize(const IFAPI_INFO *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    json_object *jso_cap_list;
+    size_t i;
+
+    if (*jso == NULL)
+        *jso = json_object_new_object();
+    jso2 = NULL;
+    r = ifapi_json_char_serialize(in->fapi_version, &jso2);
+    return_if_error(r, "Serialize char");
+
+    json_object_object_add(*jso, "version", jso2);
+    jso2 = NULL;
+    r = ifapi_json_char_serialize(in->fapi_config, &jso2);
+    return_if_error(r, "Serialize char");
+
+    json_object_object_add(*jso, "fapi_config", jso2);
+    jso_cap_list = json_object_new_array();
+
+    for (i = 0; i < IFAPI_MAX_CAP_INFO; i++) {
+        jso2 = NULL;
+        r = ifapi_json_IFAPI_CAP_INFO_serialize(&in->cap[i], &jso2);
+        return_if_error(r, "Serialize TPMS_CAPABILITY_DATA");
+
+        json_object_array_add(jso_cap_list, jso2);
+
+    }
+    json_object_object_add(*jso, "capabilities", jso_cap_list);
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize IFAPI_EVENT_TYPE to json.
+ *
+ * @param[in] in constant to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the constant is not of type IFAPI_EVENT_TYPE.
+ */
+TSS2_RC
+ifapi_json_IFAPI_EVENT_TYPE_serialize(const IFAPI_EVENT_TYPE in,
+                                      json_object **jso)
+{
+    return ifapi_json_IFAPI_EVENT_TYPE_serialize_txt(in, jso);
+}
+
+typedef struct {
+    IFAPI_EVENT_TYPE in;
+    char *name;
+} IFAPI_EVENT_TYPE_ASSIGN;
+
+static IFAPI_EVENT_TYPE_ASSIGN serialize_IFAPI_EVENT_TYPE_tab[] = {
+    { IFAPI_IMA_EVENT_TAG, "ima-legacy" },
+    { IFAPI_TSS_EVENT_TAG, "tss2" },
+};
+
+/** Get json object for a constant, if a variable is actually of type IFAPI_EVENT_TYPE.
+ *
+ * @param[in] in binary value of constant.
+ * @param[out] jso object with text representing the constant.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the constant is not of type IFAPI_EVENT_TYPE.
+ */
+TSS2_RC
+ifapi_json_IFAPI_EVENT_TYPE_serialize_txt(
+    const IFAPI_EVENT_TYPE in,
+    json_object **str_jso)
+{
+    size_t n = sizeof(serialize_IFAPI_EVENT_TYPE_tab) / sizeof(
+                   serialize_IFAPI_EVENT_TYPE_tab[0]);
+    size_t i;
+    for (i = 0; i < n; i++) {
+        if (serialize_IFAPI_EVENT_TYPE_tab[i].in == in) {
+            *str_jso = json_object_new_string(serialize_IFAPI_EVENT_TYPE_tab[i].name);
+            return_if_null(str_jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+            return TSS2_RC_SUCCESS;
+        }
+    }
+    return_error(TSS2_FAPI_RC_BAD_VALUE, "Undefined constant.");
+}
+
+/** Serialize value of type IFAPI_TSS_EVENT to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type IFAPI_TSS_EVENT.
+ */
+TSS2_RC
+ifapi_json_IFAPI_TSS_EVENT_serialize(const IFAPI_TSS_EVENT *in,
+                                     json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+
+    if (*jso == NULL)
+        *jso = json_object_new_object();
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_EVENT_serialize(&in->data, &jso2);
+    return_if_error(r, "Serialize TPM2B_EVENT");
+
+    json_object_object_add(*jso, "data", jso2);
+    if (in->event) {
+        jso2 = NULL;
+        r = ifapi_json_char_serialize(in->event, &jso2);
+        return_if_error(r, "Serialize char");
+
+        json_object_object_add(*jso, "event", jso2);
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type IFAPI_IMA_EVENT to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type IFAPI_IMA_EVENT.
+ */
+TSS2_RC
+ifapi_json_IFAPI_IMA_EVENT_serialize(const IFAPI_IMA_EVENT *in,
+                                     json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+
+    if (*jso == NULL)
+        *jso = json_object_new_object();
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_DIGEST_serialize(&in->eventData, &jso2);
+    return_if_error(r, "Serialize TPM2B_DIGEST");
+
+    json_object_object_add(*jso, "eventData", jso2);
+    jso2 = NULL;
+    r = ifapi_json_char_serialize(in->eventName, &jso2);
+    return_if_error(r, "Serialize char");
+
+    json_object_object_add(*jso, "eventName", jso2);
+    return TSS2_RC_SUCCESS;
+}
+
+/**  Serialize a IFAPI_EVENT_UNION to json.
+ *
+ * This function expects the Bitfield to be encoded as unsigned int in host-endianess.
+ * @param[in] in the value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type IFAPI_EVENT_UNION.
+ */
+TSS2_RC
+ifapi_json_IFAPI_EVENT_UNION_serialize(const IFAPI_EVENT_UNION *in,
+                                       UINT32 selector, json_object **jso)
+{
+    if (*jso == NULL)
+        *jso = json_object_new_object();
+    return_if_null(*jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+    switch (selector) {
+    case IFAPI_TSS_EVENT_TAG:
+        return ifapi_json_IFAPI_TSS_EVENT_serialize(&in->tss_event, jso);
+    case IFAPI_IMA_EVENT_TAG:
+        return ifapi_json_IFAPI_IMA_EVENT_serialize(&in->ima_event, jso);
+    default:
+        LOG_ERROR("\nSelector %"PRIx32 " did not match", selector);
+        return TSS2_SYS_RC_BAD_VALUE;
+    };
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type IFAPI_EVENT to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type IFAPI_EVENT.
+ */
+TSS2_RC
+ifapi_json_IFAPI_EVENT_serialize(const IFAPI_EVENT *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+
+    if (*jso == NULL)
+        *jso = json_object_new_object();
+    jso2 = NULL;
+    r = ifapi_json_UINT32_serialize(in->recnum, &jso2);
+    return_if_error(r, "Serialize UINT32");
+
+    json_object_object_add(*jso, "recnum", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPM2_HANDLE_serialize(in->pcr, &jso2);
+    return_if_error(r, "Serialize TPM2_HANDLE");
+
+    json_object_object_add(*jso, "pcr", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPML_DIGEST_VALUES_serialize(&in->digests, &jso2);
+    return_if_error(r, "Serialize TPML_DIGEST");
+
+    json_object_object_add(*jso, "digests", jso2);
+    jso2 = NULL;
+    r = ifapi_json_IFAPI_EVENT_TYPE_serialize(in->type, &jso2);
+    return_if_error(r, "Serialize IFAPI_EVENT_TYPE");
+
+    json_object_object_add(*jso, "type", jso2);
+    jso2 = NULL;
+    r = ifapi_json_IFAPI_EVENT_UNION_serialize(&in->sub_event, in->type, &jso2);
+    return_if_error(r, "Serialize IFAPI_EVENT_UNION");
+
+    json_object_object_add(*jso, "sub_event", jso2);
+    return TSS2_RC_SUCCESS;
+}
diff --git a/src/tss2-fapi/ifapi_json_serialize.h b/src/tss2-fapi/ifapi_json_serialize.h
new file mode 100644
index 0000000..6b1ae56
--- /dev/null
+++ b/src/tss2-fapi/ifapi_json_serialize.h
@@ -0,0 +1,84 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ ******************************************************************************/
+#ifndef IFAPI_JSON_SERIALIZE_H
+#define IFAPI_JSON_SERIALIZE_H
+
+#include <stdbool.h>
+#include <json-c/json.h>
+#include <json-c/json_util.h>
+
+#include "tss2_tpm2_types.h"
+#include "fapi_int.h"
+#include "ifapi_keystore.h"
+
+#define YES 1
+#define NO 0
+
+TSS2_RC
+ifapi_json_UINT8_ARY_serialize(const UINT8_ARY *in, json_object **jso);
+
+TSS2_RC
+ifapi_json_IFAPI_ENCRYPTED_DATA_serialize(const IFAPI_ENCRYPTED_DATA *in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_IFAPI_OBJECT_TYPE_CONSTANT_serialize(const IFAPI_OBJECT_TYPE_CONSTANT
+        in, json_object **jso);
+
+TSS2_RC
+ifapi_json_IFAPI_KEY_serialize(const IFAPI_KEY *in, json_object **jso);
+
+TSS2_RC
+ifapi_json_IFAPI_EXT_PUB_KEY_serialize(const IFAPI_EXT_PUB_KEY *in,
+                                       json_object **jso);
+
+TSS2_RC
+ifapi_json_IFAPI_NV_serialize(const IFAPI_NV *in, json_object **jso);
+
+TSS2_RC
+ifapi_json_IFAPI_HIERARCHY_serialize(const IFAPI_HIERARCHY *in, json_object **jso);
+
+TSS2_RC
+ifapi_json_IFAPI_OBJECT_serialize(const IFAPI_OBJECT *in,
+                                  json_object **jso);
+
+TSS2_RC
+ifapi_json_FAPI_QUOTE_INFO_serialize(const FAPI_QUOTE_INFO *in,
+                                     json_object **jso);
+
+TSS2_RC
+ifapi_json_IFAPI_DUPLICATE_serialize(const IFAPI_DUPLICATE *in,
+                                     json_object **jso);
+TSS2_RC
+ifapi_json_IFAPI_CAP_INFO_serialize(const IFAPI_CAP_INFO *in, json_object **jso);
+
+TSS2_RC
+ifapi_json_IFAPI_INFO_serialize(const IFAPI_INFO *in, json_object **jso);
+
+TSS2_RC
+ifapi_json_IFAPI_EVENT_TYPE_serialize(const IFAPI_EVENT_TYPE in,
+                                      json_object **jso);
+
+TSS2_RC
+ifapi_json_IFAPI_EVENT_TYPE_serialize_txt(const IFAPI_EVENT_TYPE in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_IFAPI_TSS_EVENT_serialize(const IFAPI_TSS_EVENT *in,
+                                     json_object **jso);
+
+TSS2_RC
+ifapi_json_IFAPI_IMA_EVENT_serialize(const IFAPI_IMA_EVENT *in,
+                                     json_object **jso);
+
+TSS2_RC
+ifapi_json_IFAPI_EVENT_UNION_serialize(const IFAPI_EVENT_UNION *in,
+                                       UINT32 selector, json_object **jso);
+
+TSS2_RC
+ifapi_json_IFAPI_EVENT_serialize(const IFAPI_EVENT *in, json_object **jso);
+
+#endif /* IFAPI_JSON_SERIALIZE_H */
diff --git a/src/tss2-fapi/ifapi_keystore.c b/src/tss2-fapi/ifapi_keystore.c
new file mode 100644
index 0000000..c1846b9
--- /dev/null
+++ b/src/tss2-fapi/ifapi_keystore.c
@@ -0,0 +1,1244 @@
+/* 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>
+#include <dirent.h>
+#endif
+
+#include "ifapi_io.h"
+#include "ifapi_helpers.h"
+#include "ifapi_keystore.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+#include "ifapi_json_deserialize.h"
+#include "ifapi_json_serialize.h"
+
+static TSS2_RC
+initialize_explicit_key_path(
+    const char *context_profile,
+    const char *ipath,
+    NODE_STR_T **list_node1,
+    NODE_STR_T **current_list_node,
+    NODE_STR_T **result)
+{
+    *list_node1 = split_string(ipath, IFAPI_FILE_DELIM);
+    NODE_STR_T *list_node = *list_node1;
+    char const *profile;
+    char *hierarchy;
+    TSS2_RC r = TSS2_RC_SUCCESS;
+
+    *result = NULL;
+    if (list_node == NULL) {
+        LOG_ERROR("Invalid path");
+        free_string_list(*list_node1);
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    if (strncmp("P_", list_node->str, 2) == 0) {
+        profile = list_node->str;
+        list_node = list_node->next;
+    } else {
+        profile = context_profile;
+    }
+    *result = init_string_list(profile);
+    if (result == NULL) {
+        free_string_list(*list_node1);
+        LOG_ERROR("Out of memory");
+        return  TSS2_FAPI_RC_MEMORY;
+    }
+    if (list_node == NULL) {
+        hierarchy = "HS";
+    } else {
+        if (strcmp(list_node->str, "HS") == 0 ||
+                strcmp(list_node->str, "HE") == 0 ||
+                strcmp(list_node->str, "HP") == 0 ||
+                strcmp(list_node->str, "HN") == 0 ||
+                strcmp(list_node->str, "HP") == 0) {
+            hierarchy = list_node->str;
+            list_node = list_node->next;
+        } else if (strcmp(list_node->str, "EK") == 0) {
+            hierarchy = "HE";
+        } else if (list_node->next != NULL &&
+                   (strcmp(list_node->str, "SRK") == 0 ||
+                    strcmp(list_node->str, "SDK") == 0 ||
+                    strcmp(list_node->str, "UNK") == 0 ||
+                    strcmp(list_node->str, "UDK") == 0)) {
+            hierarchy = "HS";
+        } else {
+            hierarchy = "HS";
+        }
+    }
+    if (!add_string_to_list(*result, hierarchy)) {
+        LOG_ERROR("Out of memory");
+        r = TSS2_FAPI_RC_MEMORY;
+        goto error;
+    }
+    if (list_node == NULL) {
+        goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Explicit path can't be determined.",
+                   error);
+    }
+    if (!add_string_to_list(*result, list_node->str)) {
+        LOG_ERROR("Out of memory");
+        r = TSS2_FAPI_RC_MEMORY;
+        goto error;
+    }
+    *current_list_node = list_node->next;
+    return TSS2_RC_SUCCESS;
+
+error:
+    free_string_list(*result);
+    *result = NULL;
+    free_string_list(*list_node1);
+    *list_node1 = NULL;
+    return r;
+}
+
+static TSS2_RC
+get_explicit_key_path(
+    IFAPI_KEYSTORE *keystore,
+    const char *ipath,
+    NODE_STR_T **result)
+{
+    NODE_STR_T *list_node1 = NULL;
+    NODE_STR_T *list_node = NULL;
+    TSS2_RC r = initialize_explicit_key_path(keystore->defaultprofile, ipath,
+                                             &list_node1, &list_node, result);
+    goto_if_error(r, "init_explicit_key_path", error);
+
+    while (list_node != NULL) {
+        if (!add_string_to_list(*result, list_node->str)) {
+            LOG_ERROR("Out of memory");
+            r = TSS2_FAPI_RC_MEMORY;
+            goto error;
+        }
+        list_node = list_node->next;
+    }
+    free_string_list(list_node1);
+    return TSS2_RC_SUCCESS;
+
+error:
+    if (*result)
+        free_string_list(*result);
+    if (list_node1)
+        free_string_list(list_node1);
+    return r;
+}
+
+/** Convert full FAPI path to relative path.
+ *
+ * The relative path will be copied directly into the passed object.
+ *
+ * @parm[in] keystore The key directories and default profile.
+ * @parm[in,out] path The absolute path.
+ */
+void
+full_path_to_fapi_path(IFAPI_KEYSTORE *keystore, char *path)
+{
+    int start_pos, end_pos, i;
+    int path_length = strlen(path);
+    size_t keystore_length = strlen(keystore->userdir);
+    char fapi_path_delim;
+
+    start_pos = 0;
+
+    /* Check type of path, user or system */
+    if (strncmp(&path[0], keystore->userdir, keystore_length) == 0) {
+        start_pos = strlen(keystore->userdir);
+    } else {
+        keystore_length = strlen(keystore->systemdir);
+        if (strncmp(&path[0], keystore->systemdir, keystore_length) == 0)
+            start_pos = strlen(keystore->systemdir);
+    }
+
+    if (!start_pos)
+        /* relative path was passed */
+        return;
+
+    /* Move relative path */
+    end_pos = path_length - start_pos;
+    memmove(&path[0], &path[start_pos], end_pos);
+    size_t ip = 0;
+    size_t lp = strlen(path);
+
+    /* Remove double / */
+    while (ip < lp) {
+        if (strncmp(&path[ip], "//", 2) == 0) {
+            memmove(&path[ip], &path[ip+1], lp-ip);
+            lp -= 1;
+        } else {
+            ip += 1;
+        }
+    }
+
+    /* A relative policy path will end before the file extension.
+       For other objects only the directory name will be uses as
+       relative name. */
+    if (ifapi_path_type_p(path, IFAPI_POLICY_PATH))
+        fapi_path_delim = '.';
+    else
+        fapi_path_delim = IFAPI_FILE_DELIM_CHAR;
+
+    for (i = end_pos - 2; i > 0; i--) {
+        if (path[i] == fapi_path_delim) {
+            path[i] = '\0';
+            break;
+        }
+    }
+}
+
+static TSS2_RC
+expand_path(IFAPI_KEYSTORE *keystore, const char *path, char **file_name)
+{
+    TSS2_RC r;
+    NODE_STR_T *node_list = NULL;
+    size_t pos = 0;
+
+    if (ifapi_hierarchy_path_p(path)) {
+        if (strncmp(path, "P_", 2) == 0 || strncmp(path, "/P_", 3) == 0) {
+            *file_name = strdup(path);
+            return_if_null(*file_name, "Out of memory", TSS2_FAPI_RC_MEMORY);
+        } else {
+            if (strncmp("/", path, 1) == 0)
+                pos = 1;
+            r  = ifapi_asprintf(file_name, "%s%s%s",  keystore->defaultprofile,
+                                IFAPI_FILE_DELIM, &path[pos]);
+            return_if_error(r, "Out of memory.");
+        }
+    } else if (ifapi_path_type_p(path, IFAPI_NV_PATH)
+        || ifapi_path_type_p(path, IFAPI_POLICY_PATH)
+        || ifapi_path_type_p(path, IFAPI_EXT_PATH)
+        || strncmp(path, "/P_", 3) == 0
+        || strncmp(path, "P_", 2) == 0) {
+        *file_name = strdup(path);
+        return_if_null(*file_name, "Out of memory", TSS2_FAPI_RC_MEMORY);
+
+    } else {
+        r = get_explicit_key_path(keystore, path, &node_list);
+        return_if_error(r, "Out of memory");
+
+        r = ifapi_path_string(file_name, NULL, node_list, NULL);
+        goto_if_error(r, "Out of memory", error);
+
+        free_string_list(node_list);
+    }
+    return TSS2_RC_SUCCESS;
+
+error:
+    free_string_list(node_list);
+    return r;
+}
+
+static TSS2_RC
+expand_path_to_object(
+    IFAPI_KEYSTORE *keystore,
+    const char *path,
+    const char *dir,
+    char **file_name)
+{
+
+    TSS2_RC r;
+    char *expanded_path = NULL;
+
+    r = expand_path(keystore, path, &expanded_path);
+    return_if_error(r, "Expand path");
+
+    r = ifapi_asprintf(file_name, "%s/%s/%s", dir, expanded_path, IFAPI_OBJECT_FILE);
+    SAFE_FREE(expanded_path);
+    return r;
+}
+
+/** Store keystore parameters in the keystore context.
+ *
+ * Also the user directory will be created if it does not exist.
+ *
+ * @parm[out] keystore The keystore to be initialized.
+ * @parm[in] config_systemdir The configured system directory.
+ * @parm[in] config_userdir The configured user directory.
+ * @parm[in] config_defaultprofile The configured profile.
+ * @retval TSS2_RC_SUCCESS If the keystore can be initialized.
+ * @retval TSS2_FAPI_RC_IO_ERROR If the user part of the keystore can't be
+ *         initialized.
+ * @retval TSS2_FAPI_RC_MEMORY: if memory could not be allocated.
+ */
+TSS2_RC
+ifapi_keystore_initialize(
+    IFAPI_KEYSTORE *keystore,
+    const char *config_systemdir,
+    const char *config_userdir,
+    const char *config_defaultprofile)
+{
+    TSS2_RC r;
+    char *home_dir;
+    char *home_path = NULL;
+    size_t start_pos;
+
+    memset(keystore, 0, sizeof(IFAPI_KEYSTORE));
+
+    /* Check whether usage of home directory is provided in config file */
+    if (strncmp("~", config_userdir, 1) == 0) {
+        start_pos = 1;
+    } else if (strncmp("$HOME", config_userdir, 5) == 0) {
+        start_pos = 5;
+    } else {
+        start_pos = 0;
+    }
+
+    /* Replace home abbreviation in user path. */
+    if (start_pos) {
+        LOG_DEBUG("Expanding user directory %s to user's home", config_userdir);
+        home_dir = getenv("HOME");
+        goto_if_null2(home_dir, "Home directory can't be determined.",
+                      r, TSS2_FAPI_RC_BAD_PATH, error);
+
+        r = ifapi_asprintf(&home_path, "%s%s%s", home_dir, IFAPI_FILE_DELIM,
+                           &config_userdir[start_pos]);
+        goto_if_error(r, "Out of memory.", error);
+        keystore->userdir = home_path;
+
+    } else {
+        keystore->userdir = strdup(config_userdir);
+        goto_if_null2(keystore->userdir, "Out of memory.", r, TSS2_FAPI_RC_MEMORY,
+                      error);
+    }
+
+    /* Create user directory if necessary */
+    r = ifapi_io_check_create_dir(keystore->userdir);
+    goto_if_error2(r, "User directory %s can't be created.", error, keystore->userdir);
+
+    keystore->systemdir = strdup(config_systemdir);
+    goto_if_null2(keystore->systemdir, "Out of memory.", r, TSS2_FAPI_RC_MEMORY,
+                  error);
+
+    keystore->defaultprofile = strdup(config_defaultprofile);
+    goto_if_null2(keystore->defaultprofile, "Out of memory.", r, TSS2_FAPI_RC_MEMORY,
+                  error);
+
+    SAFE_FREE(home_path);
+    return TSS2_RC_SUCCESS;
+
+ error:
+    SAFE_FREE(keystore->defaultprofile);
+    SAFE_FREE(keystore->userdir);
+    SAFE_FREE(keystore->systemdir);
+    return r;
+}
+
+/** Get absolute object path for FAPI relative path and check whether file exists.
+ *
+ *  It will be checked whether object exists in user directory, if no
+ *  the path in system directory will be returnde
+ *
+ * @parm[in] keystore The key directories and default profile.
+ * @parm[in] rel_path The relative path of the object. For keys the path will
+ *           expanded if possible.
+ * @parm[out] abs_path The absolute path of the object.
+ * @retval TSS2_RC_SUCCESS If the object can be read.
+ * @retval TSS2_FAPI_RC_KEY_NOT_FOUND if the file does not exist (for key objects).
+ * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if the file does not exist (for NV and hierarchy objects).
+ * @retval TSS2_FAPI_RC_IO_ERROR: If the file could not be read by the IO module.
+ * @retval TSS2_FAPI_RC_MEMORY: if memory could not be allocated to hold the read data.
+ */
+    static TSS2_RC
+rel_path_to_abs_path(
+        IFAPI_KEYSTORE *keystore,
+        const char *rel_path,
+        char **abs_path)
+{
+    TSS2_RC r;
+    char *directory = NULL;
+
+    /* First expand path in user directory  */
+    r = expand_path(keystore, rel_path, &directory);
+    goto_if_error(r, "Expand path", cleanup);
+
+    r = expand_path_to_object(keystore, directory,
+            keystore->userdir, abs_path);
+    goto_if_error2(r, "Object path %s could not be created.", cleanup, directory);
+
+
+    if (!ifapi_io_path_exists(*abs_path)) {
+        /* Second try system directory if object not found in user directory */
+        SAFE_FREE(*abs_path);
+        r = expand_path_to_object(keystore, directory,
+                keystore->systemdir, abs_path);
+        goto_if_error2(r, "Object path %s could not be created.", cleanup, directory);
+
+        if (ifapi_io_path_exists(*abs_path)) {
+            r = TSS2_RC_SUCCESS;
+            goto cleanup;
+        }
+
+        /* Check type of object which does not exist. */
+        if (ifapi_path_type_p(rel_path, IFAPI_NV_PATH) ||
+                (ifapi_hierarchy_path_p(rel_path))) {
+            /* Hierachy which should be created during provisioning could not be loaded. */
+            goto_error(r, TSS2_FAPI_RC_PATH_NOT_FOUND,
+                    "Keystore not initialized. Hierachy file %s does not exist.",
+                    cleanup, rel_path);
+        } else {
+            /* Object file for key does not exist in keystore */
+            goto_error(r, TSS2_FAPI_RC_KEY_NOT_FOUND,
+                    "Key %s not found.", cleanup, rel_path);
+        }
+    }
+
+cleanup:
+    SAFE_FREE(directory);
+    return r;
+}
+
+/** Start loading FAPI object from key store.
+ *
+ * Keys objects, NV objects, and hierarchies can be loaded.
+ *
+ * @parm[in] keystore The key directories and default profile.
+ * @parm[in] io  The input/output context being used for file I/O.
+ * @parm[in] path The relative path of the object. For keys the path will
+ *           expanded if possible.
+ * @retval TSS2_RC_SUCCESS If the object can be read.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if an I/O error was encountered.
+ * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if the file does not exist.
+ * @retval TSS2_FAPI_RC_MEMORY: if memory could not be allocated to hold the read data.
+ */
+TSS2_RC
+ifapi_keystore_load_async(
+    IFAPI_KEYSTORE *keystore,
+    IFAPI_IO *io,
+    const char *path)
+{
+    TSS2_RC r;
+     char *abs_path = NULL;
+
+     LOG_TRACE("Load object: %s", path);
+
+     /* Free old input buffer if buffer exists */
+     SAFE_FREE(io->char_rbuffer);
+
+     /* Convert relative path to abolute path in keystore */
+     r = rel_path_to_abs_path(keystore, path, &abs_path);
+     goto_if_error2(r, "Object %s not found.", cleanup, path);
+
+     /* Prepare read operation */
+     r = ifapi_io_read_async(io, abs_path);
+
+ cleanup:
+     SAFE_FREE(abs_path);
+     return r;
+}
+
+/** Finish loading FAPI object from key store.
+ *
+ * This function needs to be called repeatedly until it does not return TSS2_FAPI_RC_TRY_AGAIN.
+ *
+ * @parm[in] keystore The key directories and default profile.
+ * @param [in, out] io The input/output context being used for file I/O.
+ * @parm[in] object The caller allocated object which will loaded from keystore.
+ * @retval TSS2_RC_SUCCESS After successfully loading the object.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if an I/O error was encountered; such as the file was not found.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet complete.
+ */
+TSS2_RC
+ifapi_keystore_load_finish(
+    IFAPI_KEYSTORE *keystore,
+    IFAPI_IO *io,
+    IFAPI_OBJECT *object)
+{
+    TSS2_RC r;
+    json_object *jso = NULL;
+    uint8_t  *buffer = NULL;
+    /* Keystore parameter is used to be prepared if transmission of state information
+       between async and finish will be necessary in future extensions. */
+    (void)keystore;
+
+    r = ifapi_io_read_finish(io, &buffer, NULL);
+    return_try_again(r);
+    return_if_error(r, "keystore read_finish failed");
+
+    /* If json objects can't be parse the object store is corrupted */
+    jso = json_tokener_parse((char *)buffer);
+    SAFE_FREE(buffer);
+    return_if_null(jso, "Keystore is corrupted (Json error).", TSS2_FAPI_RC_GENERAL_FAILURE);
+
+    r = ifapi_json_IFAPI_OBJECT_deserialize(jso, object);
+    goto_if_error(r, "Deserialize object.", cleanup);
+
+cleanup:
+    SAFE_FREE(buffer);
+    if (jso)
+        json_object_put(jso);
+    LOG_TRACE("Return %x", r);
+    return r;
+
+}
+
+/**  Start writing FAPI object to the key store.
+ *
+ *  Keys objects, NV objects, and hierarchies can be written.
+ *
+ * @parm[in] keystore The key directories and default profile.
+ * @parm[in] io  The input/output context being used for file I/O.
+ * @parm[in] path The relative path of the object. For keys the path will
+ *           expanded if possible.
+ * @parm[in] object The object to be written to the keystore.
+ * @retval TSS2_RC_SUCCESS if the object is written successfully.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if an I/O error was encountered;
+ * @retval TSS2_FAPI_RC_MEMORY: if memory could not be allocated to hold the output data.
+ */
+TSS2_RC
+ifapi_keystore_store_async(
+    IFAPI_KEYSTORE *keystore,
+    IFAPI_IO *io,
+    const char *path,
+    const IFAPI_OBJECT *object)
+{
+    TSS2_RC r;
+    char *directory = NULL;
+    char *file = NULL;
+    char *jso_string = NULL;
+    json_object *jso = NULL;
+
+    LOG_TRACE("Store object: %s", path);
+
+    /* Prepare write operation: Create directories and valid object path */
+    r = expand_path(keystore, path, &directory);
+    goto_if_error(r, "Expand path", cleanup);
+
+    if (object->system) {
+        r = ifapi_create_dirs(keystore->systemdir, directory);
+        goto_if_error2(r, "Directory %s could not be created.", cleanup, directory);
+
+        r = expand_path_to_object(keystore, directory,
+                                  keystore->systemdir, &file);
+    } else {
+        r = ifapi_create_dirs(keystore->userdir, directory);
+        goto_if_error2(r, "Directory %s could not be created.", cleanup, directory);
+
+        r = expand_path_to_object(keystore, directory,
+                                  keystore->userdir, &file);
+    }
+    goto_if_error2(r, "Object path %s could not be created.", cleanup, directory);
+
+    /* Generate JSON string to be written to store */
+    r = ifapi_json_IFAPI_OBJECT_serialize(object, &jso);
+    goto_if_error2(r, "Object for %s could not be serialized.", cleanup, file);
+
+    jso_string = strdup(json_object_to_json_string_ext(jso,
+                                                       JSON_C_TO_STRING_PRETTY));
+    goto_if_null2(jso_string, "Converting json to string", r, TSS2_FAPI_RC_MEMORY,
+                  cleanup);
+
+    /* Start writing the json string to disk */
+    r = ifapi_io_write_async(io, file, (uint8_t *) jso_string, strlen(jso_string));
+    free(jso_string);
+    goto_if_error(r, "write_async failed", cleanup);
+
+ cleanup:
+    if (jso)
+        json_object_put(jso);
+    SAFE_FREE(directory);
+    SAFE_FREE(file);
+    return r;
+}
+
+/** Finish writing a FAPI object to the keystore.
+ *
+ * This function needs to be called repeatedly until it does not return TSS2_FAPI_RC_TRY_AGAIN.
+ *
+ * @param [in, out] io The input/output context being used for file I/O.
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if an I/O error was encountered; such as the file was not found.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet complete.
+           Call this function again later.
+ */
+TSS2_RC
+ifapi_keystore_store_finish(
+    IFAPI_KEYSTORE *keystore,
+    IFAPI_IO *io)
+{
+    TSS2_RC r;
+
+    /* Keystore parameter is used to be prepared if transmission of state infomation
+       between async and finish will be necessary in future extensions. */
+    (void)keystore;
+    /* Finish writing the object */
+    r = ifapi_io_write_finish(io);
+    return_try_again(r);
+
+    LOG_TRACE("Return %x", r);
+    return_if_error(r, "read_finish failed");
+
+    return TSS2_RC_SUCCESS;
+}
+
+static TSS2_RC
+keystore_list_all_abs
+(
+    IFAPI_KEYSTORE *keystore,
+    const char *searchpath,
+    char ***results,
+    size_t *numresults)
+{
+    TSS2_RC r;
+    char *expanded_search_path = NULL, *full_search_path = NULL;
+    size_t num_paths_system, num_paths_user, i, j;
+    char **file_ary, **file_ary_system, **file_ary_user;
+
+    *numresults = 0;
+    file_ary_user = NULL;
+    file_ary_system = NULL;
+
+    if (!searchpath || strcmp(searchpath,"") == 0 || strcmp(searchpath,"/") == 0) {
+        /* The complete keystore will be listed, no path expansion */
+        expanded_search_path = NULL;
+    }
+    else {
+        r = expand_path(keystore, searchpath, &expanded_search_path);
+        return_if_error(r, "Out of memory.");
+    }
+
+    /* Get the objects from system store */
+    r = ifapi_asprintf(&full_search_path, "%s%s%s", keystore->systemdir, IFAPI_FILE_DELIM,
+                       expanded_search_path?expanded_search_path:"");
+    return_if_error(r, "Out of memory.");
+
+    r = ifapi_io_dirfiles_all(full_search_path, &file_ary_system, &num_paths_system);
+    goto_if_error(r, "Get all files in directory.", cleanup);
+    SAFE_FREE(full_search_path);
+
+    /* Get the objects from user store */
+    r = ifapi_asprintf(&full_search_path, "%s%s%s", keystore->userdir, IFAPI_FILE_DELIM,
+                       expanded_search_path?expanded_search_path:"");
+    return_if_error(r, "Out of memory.");
+
+    r = ifapi_io_dirfiles_all(full_search_path, &file_ary_user, &num_paths_user);
+
+    *numresults = num_paths_system + num_paths_user;
+     SAFE_FREE(full_search_path);
+
+    if (*numresults > 0) {
+
+        /* Move file names from list to combined array */
+        file_ary = calloc(*numresults, sizeof(char *));
+        goto_if_null(file_ary, "Out of memory.", TSS2_FAPI_RC_MEMORY,
+                    cleanup);
+        i = 0;
+        for (j = 0; j < num_paths_system; j++)
+            file_ary[i++] = file_ary_system[j];
+        for (j = 0; j < num_paths_user; j++)
+            file_ary[i++] = file_ary_user[j];
+
+        SAFE_FREE(file_ary_system);
+        SAFE_FREE(file_ary_user);
+        SAFE_FREE(expanded_search_path);
+        *results = file_ary;
+    }
+
+ cleanup:
+    SAFE_FREE(file_ary_system);
+    SAFE_FREE(file_ary_user);
+    SAFE_FREE(expanded_search_path);
+    SAFE_FREE(full_search_path);
+    return r;
+}
+
+/** Create a list of of objects in a certain search path.
+ *
+ * A vector of relative paths will be computed.
+ *
+ * @parm[in] keystore The key directories, the default profile.
+ * @parm[in] searchpath The relative search path in key store.
+ * @parm[out] results The array with pointers to the relative object paths.
+ * @parm[out] numresults The number of found objects.
+ * @retval TSS2_RC_SUCCESS on success.
+ * @retval TSS2_FAPI_RC_MEMORY: if memory could not be allocated.
+ */
+TSS2_RC
+ifapi_keystore_list_all(
+    IFAPI_KEYSTORE *keystore,
+    const char *searchpath,
+    char ***results,
+    size_t *numresults)
+{
+    TSS2_RC r;
+    size_t i;
+
+    r = keystore_list_all_abs(keystore, searchpath, results, numresults);
+    return_if_error(r, "Get all keystore objects.");
+
+    if (*numresults > 0) {
+        /* Convert absolute path to relative path */
+        for (i = 0; i < *numresults; i++) {
+            full_path_to_fapi_path(keystore, (*results)[i]);
+        }
+    }
+    return r;
+}
+
+/** Remove file storing a keystore object.
+ *
+ * @parm[in] keystore The key directories, the default profile.
+ * @parm[in] path The relative name of the object be removed.
+ * @retval TSS2_RC_SUCCESS On success.
+ * @retval TSS2_FAPI_RC_MEMORY: If memory could not be allocated.
+ * @retval TSS2_FAPI_RC_IO_ERROR If the file can't be removed.
+ */
+TSS2_RC
+ifapi_keystore_delete(
+     IFAPI_KEYSTORE *keystore,
+     char *path)
+{
+    TSS2_RC r;
+    char *abs_path = NULL;
+
+    /* Convert relative path to abolute path in keystore */
+    r = rel_path_to_abs_path(keystore, path, &abs_path);
+    goto_if_error2(r, "Object %s not found.", cleanup, path);
+
+    r = ifapi_io_remove_file(abs_path);
+
+ cleanup:
+     SAFE_FREE(abs_path);
+     return r;
+}
+
+static TSS2_RC
+expand_directory(IFAPI_KEYSTORE *keystore, const char *path, char **directory_name)
+{
+    TSS2_RC r;
+
+    if (path && strcmp(path,"") != 0 && strcmp(path,"/") != 0) {
+        size_t start_pos = 0;
+        if (path[0] == IFAPI_FILE_DELIM_CHAR)
+            start_pos = 1;
+        if ((strncmp(&path[start_pos], "HS", 2) == 0 ||
+             strncmp(&path[start_pos], "HE", 2) == 0) &&
+            strlen(&path[start_pos]) <= 3) {
+            /* Root directory is hierarchy */
+            r = ifapi_asprintf(directory_name, "%s/", keystore->defaultprofile,
+                               path[start_pos]);
+            return_if_error(r, "Out of memory.");
+
+        } else {
+            /* Try to expand a key path */
+            r = expand_path(keystore, path, directory_name);
+            return_if_error(r, "Out of memory.");
+        }
+    } else {
+        *directory_name = NULL;
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Remove directories in keystore.
+ *
+ * If the expanded directory exists in userdir and systemdir both will be deleted.
+ *
+ * @parm[in] keystore The key directories, the default profile.
+ * @parm[in] dir_name The relative name of the directory to be removed.
+ * @retval TSS2_RC_SUCCESS on success.
+ * @retval TSS2_FAPI_RC_MEMORY: If memory could not be allocated.
+ * @retval TSS2_FAPI_RC_IO_ERROR If directory can't be deleted.
+ */
+TSS2_RC
+ifapi_keystore_remove_directories(IFAPI_KEYSTORE *keystore, const char *dir_name)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    char *absolute_dir_path = NULL;
+    char *exp_dir_name = NULL;
+    struct stat fbuffer;
+
+    r = expand_directory(keystore, dir_name, &exp_dir_name);
+    return_if_error(r, "Expand path string.");
+
+    /* Cleanup user part of the store */
+    r = ifapi_asprintf(&absolute_dir_path, "%s%s%s", keystore->userdir, IFAPI_FILE_DELIM,
+                       exp_dir_name? exp_dir_name : "");
+    return_if_error(r, "Out of memory.");
+
+    if (stat(absolute_dir_path, &fbuffer) == 0) {
+        r = ifapi_io_remove_directories(absolute_dir_path);
+        goto_if_error2(r, "Could not remove: %s", cleanup, absolute_dir_path);
+    }
+    SAFE_FREE(absolute_dir_path);
+
+    /* Cleanup system part of the store */
+    r = ifapi_asprintf(&absolute_dir_path, "%s%s%s",  keystore->systemdir,
+                       IFAPI_FILE_DELIM, exp_dir_name? exp_dir_name : "");
+    return_if_error(r, "Out of memory.");
+
+    if (stat(absolute_dir_path, &fbuffer) == 0) {
+        r = ifapi_io_remove_directories(absolute_dir_path);
+        goto_if_error2(r, "Could not remove: %s", cleanup, absolute_dir_path);
+    }
+
+cleanup:
+    SAFE_FREE(absolute_dir_path);
+    SAFE_FREE(exp_dir_name);
+    return r;
+}
+
+/* Predicate used as function parameter for object searching in keystore */
+typedef TSS2_RC (*ifapi_keystore_object_cmp) (
+    IFAPI_OBJECT *object,
+    void *cmp_object,
+    bool *equal);
+
+/** Search object with a certain propoerty in keystore.
+ *
+ * @parm[in,out] keystore The key directories, the default profile, and the
+ *               state information for the asynchronous search.
+ * @parm[in] io The input/output context being used for file I/O.
+ * @parm[in] name The name of the searched key.
+ * @param[out] found_path The relative path of the found key.
+ * @retval TSS2_RC_SUCCESS on success.
+ * @retval TSS2_FAPI_RC_MEMORY: if memory could not be allocated.
+ * @retval TSS2_FAPI_RC_KEY_NOT_FOUND If the key was not found in keystore.
+ */
+static TSS2_RC
+keystore_search_obj(
+    IFAPI_KEYSTORE *keystore,
+    IFAPI_IO *io,
+    void *cmp_object,
+    ifapi_keystore_object_cmp cmp_function,
+    char **found_path)
+{
+    TSS2_RC r;
+    UINT32 path_idx;
+    char *path;
+    IFAPI_OBJECT object;
+    size_t i;
+
+    switch (keystore->key_search.state) {
+    statecase(keystore->key_search.state, KSEARCH_INIT)
+        r = ifapi_keystore_list_all(keystore,
+                                    "/", /**< search keys and NV objects in store */
+                                    &keystore->key_search.pathlist,
+                                    &keystore->key_search.numPaths);
+        goto_if_error2(r, "Get entities.", cleanup);
+
+        keystore->key_search.path_idx = keystore->key_search.numPaths;
+        fallthrough;
+
+    statecase(keystore->key_search.state, KSEARCH_SEARCH_OBJECT)
+        /* Use the next object in the path list */
+        if (keystore->key_search.path_idx == 0) {
+            goto_error(r, TSS2_FAPI_RC_PATH_NOT_FOUND, "Key not found.", cleanup);
+        }
+        keystore->key_search.path_idx -= 1;
+        path_idx = keystore->key_search.path_idx;
+        path = keystore->key_search.pathlist[path_idx];
+        LOG_TRACE("Check file: %s %zu", path, keystore->key_search.path_idx);
+
+        r = ifapi_keystore_load_async(keystore, io, path);
+        return_if_error2(r, "Could not open: %s", path);
+
+        fallthrough;
+
+    statecase(keystore->key_search.state, KSEARCH_READ)
+        r = ifapi_keystore_load_finish(keystore, io, &object);
+        return_try_again(r);
+        goto_if_error(r, "read_finish failed", cleanup);
+
+        /* Check whether the key has the passed name */
+        bool keys_equal;
+        r = cmp_function(&object, cmp_object, &keys_equal);
+        ifapi_cleanup_ifapi_object(&object);
+        goto_if_error(r, "Invalid object.", cleanup);
+
+        if (!keys_equal) {
+            /* Try next key */
+            keystore->key_search.state = KSEARCH_SEARCH_OBJECT;
+            return TSS2_FAPI_RC_TRY_AGAIN;
+        }
+        /* Key found, the absolute path will be converted to relative path. */
+        path_idx = keystore->key_search.path_idx;
+        *found_path = strdup(keystore->key_search.pathlist[path_idx]);
+        goto_if_null(*found_path, "Out of memory.",
+                     TSS2_FAPI_RC_MEMORY, cleanup);
+        full_path_to_fapi_path(keystore, *found_path);
+        break;
+
+    statecasedefault(keystore->key_search.state);
+    }
+cleanup:
+    for (i = 0; i < keystore->key_search.numPaths; i++)
+        free(keystore->key_search.pathlist[i]);
+    free(keystore->key_search.pathlist);
+    if (!*found_path) {
+        LOG_ERROR("Object not found");
+        r = TSS2_FAPI_RC_KEY_NOT_FOUND;
+    }
+    keystore->key_search.state = KSEARCH_INIT;
+    return r;
+}
+
+/** Search object with a certain name in keystore.
+ *
+ * @parm[in,out] keystore The key directories, the default profile, and the
+ *               state information for the asynchronous search.
+ * @parm[in] io The input/output context being used for file I/O.
+ * @parm[in] name The name of the searched object.
+ * @param[out] found_path The relative path of the found key.
+ * @retval TSS2_RC_SUCCESS on success.
+ * @retval TSS2_FAPI_RC_MEMORY: if memory could not be allocated.
+ * @retval TSS2_FAPI_RC_KEY_NOT_FOUND If the key was not found in keystore.
+ */
+TSS2_RC
+ifapi_keystore_search_obj(
+    IFAPI_KEYSTORE *keystore,
+    IFAPI_IO *io,
+    TPM2B_NAME *name,
+    char **found_path)
+{
+    return keystore_search_obj(keystore, io, name,
+                               ifapi_object_cmp_name, found_path);
+}
+
+/** Search nv object with a certain nv_index (from nv_public) in keystore.
+ *
+ * @parm[in,out] keystore The key directories, the default profile, and the
+ *               state information for the asynchronous search.
+ * @parm[in] io The input/output context being used for file I/O.
+ * @parm[in] nv_public The public data of the searched nv object.
+ * @param[out] found_path The relative path of the found key.
+ * @retval TSS2_RC_SUCCESS on success.
+ * @retval TSS2_FAPI_RC_MEMORY: if memory could not be allocated.
+ * @retval TSS2_FAPI_RC_KEY_NOT_FOUND If the key was not found in keystore.
+ */
+TSS2_RC
+ifapi_keystore_search_nv_obj(
+    IFAPI_KEYSTORE *keystore,
+    IFAPI_IO *io,
+    TPM2B_NV_PUBLIC *nv_public,
+    char **found_path)
+{
+    return keystore_search_obj(keystore, io, nv_public,
+                               ifapi_object_cmp_nv_public, found_path);
+}
+
+ /** Check whether keystore object already exists.
+  *
+  * The passed relative path will be expanded for user store and system store.
+ *
+ *  Keys objects, NV objects, and hierarchies can be written.
+ *
+ * @parm[in] keystore The key directories and default profile.
+ * @parm[in] io  The input/output context being used for file I/O.
+ * @parm[in] path The relative path of the object. For keys the path will
+ *           expanded if possible.
+ * @parm[in] system Switch whether system directory will be checked. Otherwise
+             the user directory will be checked.
+ * @retval TSS2_RC_SUCCESS if the object does not exist.
+ * @retval TSS2_FAPI_RC_PATH_ALREADY_EXISTS if the file in objects exists.
+ * @retval TSS2_FAPI_RC_MEMORY: if memory could not be allocated to hold the output data.
+ */
+TSS2_RC
+ifapi_keystore_check_overwrite(
+    IFAPI_KEYSTORE *keystore,
+    IFAPI_IO *io,
+    const char *path)
+{
+    TSS2_RC r;
+    char *directory = NULL;
+    char *file = NULL;
+    (void)io; /* Used to simplifiy future extensions */
+
+    /* Expand relative path */
+    r = expand_path(keystore, path, &directory);
+    goto_if_error(r, "Expand path", cleanup);
+
+    /* Expand absolute path for user and system directory */
+    r = expand_path_to_object(keystore, directory,
+                              keystore->systemdir, &file);
+    goto_if_error(r, "Expand path to object", cleanup);
+
+    if (ifapi_io_path_exists(file)) {
+        goto_error(r, TSS2_FAPI_RC_PATH_ALREADY_EXISTS,
+                   "Object %s already exists.", cleanup, path);
+    }
+    SAFE_FREE(file);
+    r = expand_path_to_object(keystore, directory,
+                              keystore->userdir, &file);
+    goto_if_error(r, "Expand path to object", cleanup);
+
+    if (ifapi_io_path_exists(file)) {
+        goto_error(r, TSS2_FAPI_RC_PATH_ALREADY_EXISTS,
+                   "Object %s already exists.", cleanup, path);
+    }
+    r = TSS2_RC_SUCCESS;
+
+ cleanup:
+    SAFE_FREE(directory);
+    SAFE_FREE(file);
+    return r;
+}
+
+/** Check whether keystore object is writeable.
+ *
+ * The passed relative path will be expanded first for  user store, second for
+ * system store if the file does not exist in system store.
+ *
+ *  Keys objects, NV objects, and hierarchies can be written.
+ *
+ * @parm[in] keystore The key directories and default profile.
+ * @parm[in] io  The input/output context being used for file I/O.
+ * @parm[in] path The relative path of the object. For keys the path will
+ *           expanded if possible.
+ * @parm[in] system Switch whether system directory will be checked. Otherwise
+             the user directory will be checked.
+ * @retval TSS2_RC_SUCCESS if the object does not exist.
+ * @retval TSS2_FAPI_RC_PATH_ALREADY_EXISTS if the file in objects exists.
+ * @retval TSS2_FAPI_RC_MEMORY: if memory could not be allocated to hold the output data.
+ */
+TSS2_RC
+ifapi_keystore_check_writeable(
+    IFAPI_KEYSTORE *keystore,
+    IFAPI_IO *io,
+    const char *path)
+{
+    TSS2_RC r;
+    char *directory = NULL;
+    char *file = NULL;
+    (void)io; /* Used to simplifiy future extensions */
+
+    /* Expand relative path */
+    r = expand_path(keystore, path, &directory);
+    goto_if_error(r, "Expand path", cleanup);
+
+    /* Expand absolute path for user and system directory */
+    r = expand_path_to_object(keystore, directory,
+                              keystore->userdir, &file);
+    goto_if_error(r, "Expand path to object", cleanup);
+
+    if (ifapi_io_path_exists(file)) {
+        r = ifapi_io_check_file_writeable(file);
+        goto_if_error2(r, "Object %s is not writable.", cleanup, path);
+
+        /* File can be written */
+        goto cleanup;
+    } else {
+        SAFE_FREE(file);
+        r = expand_path_to_object(keystore, directory,
+                                  keystore->systemdir, &file);
+        goto_if_error(r, "Expand path to object", cleanup);
+
+        if (ifapi_io_path_exists(file)) {
+             r = ifapi_io_check_file_writeable(file);
+             goto_if_error2(r, "Object %s is not writable.", cleanup, path);
+
+             /* File can be written */
+             goto cleanup;
+        }
+    }
+
+ cleanup:
+    SAFE_FREE(directory);
+    SAFE_FREE(file);
+    return r;
+}
+
+static TSS2_RC
+copy_uint8_ary(UINT8_ARY *dest, const UINT8_ARY * src) {
+    TSS2_RC r = TSS2_RC_SUCCESS;
+
+    /* Check the parameters if they are valid */
+    if (src ==  NULL || dest == NULL) {
+        return TSS2_FAPI_RC_BAD_REFERENCE;
+    }
+
+    /* Initialize the object variables for a possible error cleanup */
+    dest->buffer = NULL;
+
+    /* Create the copy */
+    dest->size = src->size;
+    dest->buffer = malloc(dest->size);
+    goto_if_null(dest->buffer, "Out of memory.", r, error_cleanup);
+    memcpy(dest->buffer, src->buffer, dest->size);
+
+    return r;
+
+error_cleanup:
+    SAFE_FREE(dest->buffer);
+    return r;
+}
+
+TSS2_RC
+ifapi_copy_ifapi_key(IFAPI_KEY * dest, const IFAPI_KEY * src) {
+    TSS2_RC r = TSS2_RC_SUCCESS;
+
+    /* Check the parameters if they are valid */
+    if (src == NULL || dest == NULL) {
+        return TSS2_FAPI_RC_BAD_REFERENCE;
+    }
+
+    /* Initialize the object variables for a possible error cleanup */
+    dest->private.buffer = NULL;
+    dest->serialization.buffer = NULL;
+    dest->appData.buffer = NULL;
+    dest->policyInstance = NULL;
+    dest->description = NULL;
+
+    /* Create the copy */
+
+    r = copy_uint8_ary(&dest->private, &src->private);
+    goto_if_error(r, "Could not copy private", error_cleanup);
+    r =copy_uint8_ary(&dest->serialization, &src->serialization);
+    goto_if_error(r, "Could not copy serialization", error_cleanup);
+    r =copy_uint8_ary(&dest->appData, &src->appData);
+    goto_if_error(r, "Could not copy appData", error_cleanup);
+
+    strdup_check(dest->policyInstance, src->policyInstance, r, error_cleanup);
+    strdup_check(dest->description, src->description, r, error_cleanup);
+    strdup_check(dest->certificate, src->certificate, r, error_cleanup);
+
+    dest->persistent_handle = src->persistent_handle;
+    dest->public = src->public;
+    dest->creationData = src->creationData;
+    dest->creationTicket = src->creationTicket;
+    dest->signing_scheme = src->signing_scheme;
+    dest->name = src->name;
+    dest->with_auth = src->with_auth;
+
+    return r;
+
+error_cleanup:
+    ifapi_cleanup_ifapi_key(dest);
+    return r;
+}
+
+/** Free memory allocated during deserialization of a key object.
+ *
+ * The key will not be freed (might be declared on the stack).
+ *
+ * @param[in] key The key object to be cleaned up.
+ *
+ */
+void ifapi_cleanup_ifapi_key(IFAPI_KEY * key) {
+    if (key != NULL) {
+        SAFE_FREE(key->policyInstance);
+        SAFE_FREE(key->serialization.buffer);
+        SAFE_FREE(key->private.buffer);
+        SAFE_FREE(key->description);
+        SAFE_FREE(key->certificate);
+        SAFE_FREE(key->appData.buffer);
+    }
+}
+
+void ifapi_cleanup_ifapi_ext_pub_key(IFAPI_EXT_PUB_KEY * key) {
+    if (key != NULL) {
+        SAFE_FREE(key->pem_ext_public);
+        SAFE_FREE(key->certificate);
+    }
+}
+
+void ifapi_cleanup_ifapi_hierarchy(IFAPI_HIERARCHY * hierarchy) {
+    if (hierarchy != NULL) {
+        SAFE_FREE(hierarchy->description);
+    }
+}
+
+void ifapi_cleanup_ifapi_nv(IFAPI_NV * nv) {
+    if (nv != NULL) {
+        SAFE_FREE(nv->serialization.buffer);
+        SAFE_FREE(nv->appData.buffer);
+        SAFE_FREE(nv->policyInstance);
+        SAFE_FREE(nv->description);
+        SAFE_FREE(nv->event_log);
+    }
+}
+
+void ifapi_cleanup_ifapi_duplicate(IFAPI_DUPLICATE * duplicate) {
+    if(duplicate != NULL) {
+        SAFE_FREE(duplicate->certificate);
+    }
+}
+
+void ifapi_cleanup_ifapi_key_search(IFAPI_KEY_SEARCH * key_search) {
+    if (key_search != NULL) {
+        if (key_search->pathlist) {
+            for (size_t i = 0; i < key_search->numPaths; i++) {
+                SAFE_FREE(key_search->pathlist[i]);
+            }
+            Fapi_Free(key_search->pathlist);
+        }
+    }
+}
+
+void ifapi_cleanup_ifapi_keystore(IFAPI_KEYSTORE * keystore) {
+    if (keystore != NULL) {
+        ifapi_cleanup_ifapi_key_search(&keystore->key_search);
+        SAFE_FREE(keystore->systemdir);
+        SAFE_FREE(keystore->userdir);
+        SAFE_FREE(keystore->defaultprofile);
+    }
+}
+
+TSS2_RC
+ifapi_copy_ifapi_key_object(IFAPI_OBJECT * dest, const IFAPI_OBJECT * src) {
+    TSS2_RC r = TSS2_RC_SUCCESS;
+
+    /* Check the parameters if they are valid */
+    if (src == NULL || dest == NULL) {
+        return TSS2_FAPI_RC_BAD_REFERENCE;
+    }
+
+    if (src->objectType != IFAPI_KEY_OBJ) {
+        LOG_ERROR("Bad object type");
+        return TSS2_FAPI_RC_GENERAL_FAILURE;
+    }
+
+    /* Initialize the object variables for a possible error cleanup */
+
+    /* Create the copy */
+    dest->policy_harness = ifapi_copy_policy_harness(src->policy_harness);
+
+    ifapi_copy_ifapi_key(&dest->misc.key, &src->misc.key);
+    goto_if_error(r, "Could not copy key", error_cleanup);
+
+    dest->objectType = src->objectType;
+    dest->system = src->system;
+    dest->handle = src->handle;
+    dest->authorization_state = src->authorization_state;
+
+    return r;
+
+error_cleanup:
+    ifapi_cleanup_ifapi_object(dest);
+    return r;
+}
+
+/** Free memory allocated during deserialization of object.
+ *
+ * The object will not be freed (might be declared on the stack).
+ *
+ * @param[in]  object The object to be cleaned up.
+ *
+ */
+    void
+ifapi_cleanup_ifapi_object(
+        IFAPI_OBJECT *object)
+{
+    if (object != NULL) {
+        if (object->objectType != IFAPI_OBJ_NONE) {
+            if (object->objectType == IFAPI_KEY_OBJ) {
+                ifapi_cleanup_ifapi_key(&object->misc.key);
+            } else if (object->objectType == IFAPI_NV_OBJ) {
+                ifapi_cleanup_ifapi_nv(&object->misc.nv);
+            } else if (object->objectType == IFAPI_DUPLICATE_OBJ) {
+                ifapi_cleanup_ifapi_duplicate(&object->misc.key_tree);
+            } else if (object->objectType == IFAPI_EXT_PUB_KEY_OBJ) {
+                ifapi_cleanup_ifapi_ext_pub_key(&object->misc.ext_pub_key);
+            } else if (object->objectType == IFAPI_HIERARCHY_OBJ) {
+                ifapi_cleanup_ifapi_hierarchy(&object->misc.hierarchy);
+            }
+
+            ifapi_cleanup_policy_harness(object->policy_harness);
+            SAFE_FREE(object->policy_harness);
+            object->objectType = IFAPI_OBJ_NONE;
+        }
+    }
+}
diff --git a/src/tss2-fapi/ifapi_keystore.h b/src/tss2-fapi/ifapi_keystore.h
new file mode 100644
index 0000000..3d43494
--- /dev/null
+++ b/src/tss2-fapi/ifapi_keystore.h
@@ -0,0 +1,259 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ ******************************************************************************/
+
+#ifndef IFAPI_KEYSTORE_H
+#define IFAPI_KEYSTORE_H
+
+#include <stdlib.h>
+
+#include "tss2_common.h"
+#include "tss2_tpm2_types.h"
+#include "fapi_types.h"
+#include "ifapi_policy_types.h"
+#include "ifapi_object.h"
+#include "tss2_esys.h"
+
+typedef UINT32 IFAPI_OBJECT_TYPE_CONSTANT;
+#define IFAPI_OBJ_NONE                 0    /**< Tag for key resource */
+#define IFAPI_KEY_OBJ                  1    /**< Tag for key resource */
+#define IFAPI_NV_OBJ                   2    /**< Tag for NV Ram resource */
+#define IFAPI_EXT_PUB_KEY_OBJ          3    /**< Tag for key resource */
+#define IFAPI_HIERARCHY_OBJ            4    /**< Tag for other resources, e.g. PCR register, hierarchies */
+#define IFAPI_DUPLICATE_OBJ            5    /**< Tag for key duplication object */
+
+/** Type for representing a FAPI key
+ */
+typedef struct {
+    UINT32                            persistent_handle;    /**< Persistent TPM Handle */
+    TPM2B_PUBLIC                                 public;    /**< The wrapped public portion of the object */
+    UINT8_ARY                             serialization;    /**< None */
+    UINT8_ARY                                   private;    /**< None */
+    char                                *policyInstance;    /**<  Keys policy */
+    TPM2B_CREATION_DATA                    creationData;    /**< None */
+    TPMT_TK_CREATION                     creationTicket;    /**< None */
+    char                                   *description;    /**< Human readable description of key */
+    UINT8_ARY                                   appData;    /**< Application data */
+    char                                   *certificate;    /**< Keys certificate (if any) */
+    TPMT_SIG_SCHEME                      signing_scheme;    /**< Signing scheme for the key */
+    TPM2B_NAME                                     name;    /**< Name of the key */
+    TPMI_YES_NO                               with_auth;    /**< Authorization provided during creation */
+} IFAPI_KEY;
+
+/** Type for representing a external public key
+ */
+typedef struct {
+    char                                *pem_ext_public;    /**< Public key in PEM format */
+    char                                   *certificate;    /**< Keys certificate (if any) */
+    TPM2B_PUBLIC                                 public;    /**< The pulic information in TPM format */
+} IFAPI_EXT_PUB_KEY;
+
+/** Type for representing hierarchy
+ */
+typedef struct {
+    TPMI_YES_NO                               with_auth;    /**< Authorization provided */
+    char                                   *description;    /**< Human readable description of hierarchy */
+    TPM2B_DIGEST                             authPolicy;
+} IFAPI_HIERARCHY;
+
+/** Type for representing a FAPI NV object
+ */
+typedef struct {
+    TPM2B_NV_PUBLIC                              public;    /**< The wrapped public portion of the object */
+    UINT8_ARY                             serialization;    /**< None */
+    UINT32                                    hierarchy;    /**< The hierarchy used for NV object creation */
+    char                                *policyInstance;    /**<  Keys policy */
+    char                                   *description;    /**< Human readable description of key */
+    UINT8_ARY                                   appData;    /**< Application data */
+    TPMI_YES_NO                               with_auth;    /**< Authorization provided during creation */
+    char*                                     event_log;    /**< The event log if NV type is pcr */
+} IFAPI_NV;
+
+/** Type for representing a FAPI object for key duplication.
+ */
+typedef struct {
+
+    TPM2B_PRIVATE                             duplicate; /**< The duplicate of the key to export*/
+    TPM2B_ENCRYPTED_SECRET               encrypted_seed; /**< Encrypted seed needed for key import */
+    TPM2B_PUBLIC                                 public; /**< The public information of the key to be duplicated */
+    TPM2B_PUBLIC                          public_parent; /**< The public information of the new parent key */
+    char                                   *certificate; /**< The certificate of the key to be duplicated */
+} IFAPI_DUPLICATE;
+
+/** type for representing public info of a TPM-Resource
+ */
+typedef union {
+    IFAPI_EXT_PUB_KEY                       ext_pub_key;    /**< Public info for external key. */
+    IFAPI_KEY                                       key;    /**< Public info for key objects */
+    IFAPI_NV                                         nv;    /**< Public info for NV ram objects */
+    IFAPI_DUPLICATE                            key_tree;    /**< Information for key duplication */
+    IFAPI_HIERARCHY                           hierarchy;    /**< Information related ot hierarchies */
+} IFAPI_OBJECT_UNION;
+
+/** The states for key searching */
+enum FAPI_SEARCH_STATE {
+    KSEARCH_INIT = 0,
+    KSEARCH_SEARCH_OBJECT,
+    KSEARCH_READ
+};
+
+/** The data structure holding internal state for key searching.
+ */
+typedef struct {
+    size_t path_idx;                /**< Index of array of objects to be searched */
+    size_t numPaths;                /**< Number of all objects in data store */
+    char **pathlist;                /**< The array of all objects  in the search path */
+    enum FAPI_SEARCH_STATE state;
+} IFAPI_KEY_SEARCH;
+
+typedef struct IFAPI_KEYSTORE {
+    char *systemdir;
+    char *userdir;
+    char *defaultprofile;
+    IFAPI_KEY_SEARCH key_search;
+} IFAPI_KEYSTORE;
+
+
+/** The states for the FAPI's object authorization state*/
+enum IFAPI_AUTHORIZATION_STATE {
+    AUTH_INIT = 0,
+    AUTH_CHECK_POLICY,
+    AUTH_CREATE_SESSION,
+    AUTH_EXEC_POLICY,
+    AUTH_FLUSH_OLD_POLICY,
+    AUTH_DONE
+};
+
+/** The states for the FAPI's object write/read state*/
+enum IFAPI_IO_STATE {
+    IO_INIT = 0,
+    IO_ACTIVE,
+};
+
+/** Type for representing TPM-Resource
+ */
+typedef struct _IFAPI_OBJECT {
+    TPMS_POLICY_HARNESS                 *policy_harness;
+    IFAPI_OBJECT_TYPE_CONSTANT               objectType;    /**< Selector for object type */
+    IFAPI_OBJECT_UNION                             misc;    /**< Resource specific information */
+    TPMI_YES_NO                                  system;    /**< Store the object in the system wide
+                                                             directory */
+    ESYS_TR                                      handle;    /**< Handle used by ESAPI */
+    enum IFAPI_AUTHORIZATION_STATE  authorization_state;    /**< State of object authorization state machine */
+    enum IFAPI_IO_STATE                           state;
+
+} IFAPI_OBJECT;
+
+
+TSS2_RC
+ifapi_keystore_initialize(
+    IFAPI_KEYSTORE *keystore,
+    const char *config_systemdir,
+    const char *config_userdir,
+    const char *config_defaultprofile);
+
+TSS2_RC
+ifapi_keystore_load_async(
+    IFAPI_KEYSTORE *keystore,
+    IFAPI_IO *io,
+    const char *path);
+
+TSS2_RC
+ifapi_keystore_load_finish(
+    IFAPI_KEYSTORE *keystore,
+    IFAPI_IO *io,
+    IFAPI_OBJECT *object);
+
+TSS2_RC
+ifapi_keystore_store_async(
+    IFAPI_KEYSTORE *keystore,
+    IFAPI_IO *io,
+    const char *path,
+    const IFAPI_OBJECT *object);
+
+TSS2_RC
+ifapi_keystore_store_finish(
+    IFAPI_KEYSTORE *keystore,
+    IFAPI_IO *io);
+
+TSS2_RC
+ifapi_keystore_list_all(
+    IFAPI_KEYSTORE *keystore,
+    const char *searchpath,
+    char ***results,
+    size_t *numresults);
+
+TSS2_RC
+ifapi_keystore_delete(
+     IFAPI_KEYSTORE *keystore,
+     char *path);
+
+TSS2_RC
+ifapi_keystore_remove_directories(
+    IFAPI_KEYSTORE *keystore,
+    const char *dir_name);
+
+TSS2_RC
+ifapi_keystore_search_obj(
+    IFAPI_KEYSTORE *keystore,
+    IFAPI_IO *io,
+    TPM2B_NAME *name,
+    char **found_path);
+
+TSS2_RC
+ifapi_keystore_search_nv_obj(
+    IFAPI_KEYSTORE *keystore,
+    IFAPI_IO *io,
+    TPM2B_NV_PUBLIC *nv_public,
+    char **found_path);
+
+TSS2_RC
+ifapi_keystore_check_overwrite(
+    IFAPI_KEYSTORE *keystore,
+    IFAPI_IO *io,
+    const char *path);
+
+TSS2_RC
+ifapi_keystore_check_writeable(
+    IFAPI_KEYSTORE *keystore,
+    IFAPI_IO *io,
+    const char *path);
+
+TSS2_RC
+ifapi_copy_ifapi_key(
+    IFAPI_KEY * dest,
+    const IFAPI_KEY * src);
+
+TSS2_RC
+ifapi_copy_ifapi_key_object(
+    IFAPI_OBJECT * dest,
+    const IFAPI_OBJECT * src);
+
+void ifapi_cleanup_ifapi_key(
+    IFAPI_KEY * key);
+
+void ifapi_cleanup_ifapi_ext_pub_key(
+    IFAPI_EXT_PUB_KEY * key);
+
+void ifapi_cleanup_ifapi_hierarchy(
+    IFAPI_HIERARCHY * hierarchy);
+
+void ifapi_cleanup_ifapi_nv(
+    IFAPI_NV * nv);
+
+void ifapi_cleanup_ifapi_duplicate(
+    IFAPI_DUPLICATE * duplicate);
+
+void ifapi_cleanup_ifapi_key_search(
+    IFAPI_KEY_SEARCH * key_search);
+
+void ifapi_cleanup_ifapi_keystore(
+    IFAPI_KEYSTORE * keystore);
+
+void
+ifapi_cleanup_ifapi_object(
+    IFAPI_OBJECT *object);
+
+#endif /* IFAPI_KEYSTORE_H */
diff --git a/src/tss2-fapi/ifapi_macros.h b/src/tss2-fapi/ifapi_macros.h
new file mode 100644
index 0000000..b9a47cc
--- /dev/null
+++ b/src/tss2-fapi/ifapi_macros.h
@@ -0,0 +1,139 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ *******************************************************************************/
+#ifndef IFAPI_MACROS_H
+#define IFAPI_MACROS_H
+
+#define strdup_check(dest, str, r, label) \
+    if (str) {                             \
+       dest = strdup(str); \
+       if (!dest) { \
+          r = TSS2_FAPI_RC_MEMORY; \
+          LOG_ERROR("Out of memory.");          \
+          goto label; \
+       } \
+    } else { \
+        dest = NULL; \
+    }
+
+#define calloc_check(dest, size, r, label) \
+    {                             \
+       dest = callock(size,1);     \
+       if (!dest) { \
+          r = TSS2_FAPI_RC_MEMORY; \
+          LOG_ERROR("Out of memory.");          \
+          goto label; \
+       } \
+    }
+
+#define goto_if_null2(p,msg, r, ec, label, ...) \
+    if ((p) == NULL) { \
+        LOG_ERROR(TPM2_ERROR_FORMAT " " msg, TPM2_ERROR_TEXT(ec), ## __VA_ARGS__); \
+        r = (ec); \
+        goto label;  \
+    }
+
+#define goto_if_error2(r,msg,label, ...)             \
+    if (r != TSS2_RC_SUCCESS) { \
+        LOG_ERROR(TPM2_ERROR_FORMAT " " msg, TPM2_ERROR_TEXT(r), ## __VA_ARGS__); \
+        goto label;  \
+    }
+
+#define return_if_error2(r,msg, ...)                \
+    if (r != TSS2_RC_SUCCESS) { \
+        LOG_ERROR(TPM2_ERROR_FORMAT " " msg, TPM2_ERROR_TEXT(r), ## __VA_ARGS__); \
+        return r;  \
+    }
+
+#define try_again_or_error(r,msg, ...)                \
+    if ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN) \
+        return TSS2_FAPI_RC_TRY_AGAIN; \
+    if (r != TSS2_RC_SUCCESS) { \
+        LOG_ERROR(TPM2_ERROR_FORMAT " " msg, TPM2_ERROR_TEXT(r), ## __VA_ARGS__); \
+        return r;  \
+    }
+
+#define try_again_or_error_goto(r,msg, label, ...)            \
+    if ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN) \
+        return TSS2_FAPI_RC_TRY_AGAIN; \
+    if (r != TSS2_RC_SUCCESS) { \
+        LOG_ERROR(TPM2_ERROR_FORMAT " " msg, TPM2_ERROR_TEXT(r), ## __VA_ARGS__); \
+        goto label;  \
+    }
+
+#define return_error2(r,msg, ...) {               \
+    LOG_ERROR(TPM2_ERROR_FORMAT " " msg, TPM2_ERROR_TEXT(r), ## __VA_ARGS__); \
+    return (r); }
+
+
+#define return_if_error_reset_state(r,msg, ...)     \
+    if (r != TSS2_RC_SUCCESS) { \
+        LOG_ERROR(TPM2_ERROR_FORMAT " " msg, TPM2_ERROR_TEXT(r), ## __VA_ARGS__); \
+        context->state = _FAPI_STATE_INIT; \
+        return r;  \
+    }
+
+#define goto_if_error_reset_state(r,msg,label, ...) \
+    if (r != TSS2_RC_SUCCESS) { \
+        LOG_ERROR(TPM2_ERROR_FORMAT " " msg, TPM2_ERROR_TEXT(r), ## __VA_ARGS__); \
+        context->state = _FAPI_STATE_INIT; \
+        goto label;  \
+    }
+
+#define goto_error_reset_state(r,v,msg,label) {  \
+    r = v; \
+    LOG_ERROR("%s " TPM2_ERROR_FORMAT, msg, TPM2_ERROR_TEXT(r));    \
+    context->state = _FAPI_STATE_INIT;                              \
+    goto label; }
+
+#define goto_if_null_reset_state(p,msg,r,ec,label)  \
+    if ((p) == NULL) { \
+        LOG_ERROR("%s ", (msg)); \
+        context->state = _FAPI_STATE_INIT;      \
+        (r) = (ec);                             \
+        goto label;  \
+    }
+
+#define return_try_again(r) \
+    if ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN) { \
+        LOG_TRACE("Received TRY_AGAIN; returning TRY_AGAIN"); \
+        return TSS2_FAPI_RC_TRY_AGAIN; \
+    }
+
+#define check_not_null(X) \
+    if (X == NULL) { \
+        LOG_ERROR(str(X) " is NULL: BAD_REFERENCE"); \
+        return TSS2_FAPI_RC_BAD_REFERENCE; \
+    }
+
+#define check_oom(X) \
+    if (X == NULL) { \
+        LOG_ERROR("Out of memory"); \
+        return TSS2_FAPI_RC_MEMORY; \
+    }
+
+#if defined __GNUC__ && __GNUC__ < 7
+#define fallthrough { }
+#else
+#define fallthrough __attribute__((fallthrough))
+#endif
+
+#define statecase(VAR, STATE) \
+    case STATE: \
+        LOG_TRACE("State " str(VAR) " reached " str(STATE)); \
+        VAR=STATE;
+
+#define statecasedefault(VAR) \
+    default: \
+        LOG_ERROR("Bad state for " str(VAR)); \
+        return TSS2_FAPI_RC_BAD_SEQUENCE;
+
+#define statecasedefault_error(VAR, r, label)         \
+    default: \
+        LOG_ERROR("Bad state for " str(VAR)); \
+        r = TSS2_FAPI_RC_BAD_SEQUENCE; \
+        goto label;
+
+#endif /* IFAPI_MACROS_H */
diff --git a/src/tss2-fapi/ifapi_object.h b/src/tss2-fapi/ifapi_object.h
new file mode 100644
index 0000000..a1b4690
--- /dev/null
+++ b/src/tss2-fapi/ifapi_object.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ ******************************************************************************/
+
+#ifndef IFAPI_OBJECT_H
+#define IFAPI_OBJECT_H
+
+
+
+#endif /* IFAPI_OBJECT_H */
diff --git a/src/tss2-fapi/ifapi_policy.c b/src/tss2-fapi/ifapi_policy.c
new file mode 100644
index 0000000..9b48ef0
--- /dev/null
+++ b/src/tss2-fapi/ifapi_policy.c
@@ -0,0 +1,164 @@
+/* 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 <string.h>
+#include <stdlib.h>
+
+#include "tss2_mu.h"
+#include "fapi_util.h"
+#include "fapi_int.h"
+#include "fapi_crypto.h"
+#include "fapi_policy.h"
+#include "ifapi_policy_instantiate.h"
+#include "ifapi_policy_callbacks.h"
+#include "ifapi_helpers.h"
+#include "ifapi_json_deserialize.h"
+#include "tpm_json_deserialize.h"
+#include "ifapi_policy_store.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+/** Compute policy digest for a json policy tree.
+ */
+TSS2_RC
+ifapi_calculate_tree(
+    FAPI_CONTEXT *context,
+    const char *policyPath,
+    TPMS_POLICY_HARNESS *harness,
+    TPMI_ALG_HASH hash_alg,
+    size_t *digest_idx,
+    size_t *hash_size)
+{
+    size_t i;
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    bool already_computed = false;
+    IFAPI_POLICY_EVAL_INST_CTX *eval_ctx = NULL;
+    ifapi_policyeval_INST_CB *callbacks;
+
+    if (context->policy.state == POLICY_INIT && !policyPath)
+        /* Skip policy reading */
+        context->policy.state = POLICY_INSTANTIATE_PREPARE;
+
+    switch (context->policy.state) {
+    statecase(context->policy.state, POLICY_INIT);
+        fallthrough;
+
+    statecase(context->policy.state, POLICY_READ);
+        r = ifapi_policy_store_load_async(&context->pstore, &context->io, policyPath);
+        goto_if_error2(r, "Can't open: %s", cleanup, policyPath);
+        fallthrough;
+
+    statecase(context->policy.state, POLICY_READ_FINISH);
+        r = ifapi_policy_store_load_finish(&context->pstore, &context->io, harness);
+        return_try_again(r);
+        return_if_error_reset_state(r, "read_finish failed");
+        fallthrough;
+
+    statecase(context->policy.state, POLICY_INSTANTIATE_PREPARE);
+        eval_ctx = &context->policy.eval_ctx;
+        callbacks = &eval_ctx->callbacks;
+        callbacks->cbname = ifapi_get_object_name;
+        callbacks->cbname_userdata = context;
+        callbacks->cbpublic = ifapi_get_key_public;
+        callbacks->cbpublic_userdata = context;
+        callbacks->cbnvpublic = ifapi_get_nv_public;
+        callbacks->cbnvpublic_userdata = context;
+        callbacks->cbpcr = ifapi_read_pcr;
+        callbacks->cbpcr_userdata = context;
+
+        r = ifapi_policyeval_instantiate_async(eval_ctx, harness, callbacks);
+        goto_if_error(r, "Instantiate policy.", cleanup);
+        fallthrough;
+
+    statecase(context->policy.state, POLICY_INSTANTIATE);
+        r = ifapi_policyeval_instantiate_finish(&context->policy.eval_ctx);
+        FAPI_SYNC(r, "Instantiate policy.", cleanup);
+        ifapi_free_node_list(context->policy.eval_ctx.policy_elements);
+        if (!(*hash_size = ifapi_hash_get_digest_size(hash_alg))) {
+            goto_error(r, TSS2_ESYS_RC_NOT_IMPLEMENTED,
+                       "Unsupported hash algorithm (%" PRIu16 ")", cleanup,
+                       hash_alg);
+        }
+
+        for (i = 0; i < harness->policyDigests.count; i++) {
+            if (harness->policyDigests.digests[i].hashAlg == hash_alg) {
+                /* Digest already computed */
+                *digest_idx = i;
+                already_computed = true;
+            }
+        }
+        if (already_computed)
+            break;
+
+        if (i > TPM2_NUM_PCR_BANKS) {
+            return_error(TSS2_FAPI_RC_BAD_VALUE, "Table overflow");
+        }
+        *digest_idx = i;
+        harness->policyDigests.count += 1;
+        harness->policyDigests.digests[i].hashAlg = hash_alg;
+
+        memset(&harness->policyDigests.digests[*digest_idx].digest, 0,
+               sizeof(TPMU_HA));
+
+        r = ifapi_calculate_policy(harness->policy,
+                                   &harness->policyDigests, hash_alg,
+                                   *hash_size, *digest_idx);
+        goto_if_error(r, "Compute policy.", cleanup);
+
+        break;
+    statecasedefault(context->policy.state);
+    }
+cleanup:
+    context->policy.state = POLICY_INIT;
+    return r;
+}
+
+/** Calculate policy for a key object:.
+ *
+ * The intermediate information is stored in the policy field of the context.
+ */
+TSS2_RC
+ifapi_calculate_policy_for_key(
+    FAPI_CONTEXT *context,
+    const char *policyPath,
+    IFAPI_KEY_TEMPLATE *template,
+    TPMS_POLICY_HARNESS **policy_harness)
+{
+    TSS2_RC r;
+
+    if (policyPath && strcmp(policyPath, "") != 0) {
+        r = ifapi_calculate_tree(context, policyPath,
+                                 &context->policy.harness,
+                                 context->cmd.Key_Create.public_templ.public.publicArea.nameAlg,
+                                 &context->policy.digest_idx,
+                                 &context->policy.hash_size);
+        FAPI_SYNC(r, "Calculate policy tree %s", error_cleanup, policyPath)
+
+        template->public.publicArea.authPolicy.size = context->policy.hash_size;
+        memcpy(&template->public.publicArea.authPolicy.buffer[0],
+               &context->policy.harness.policyDigests.digests[context->policy.digest_idx].digest,
+               context->policy.hash_size);
+        /* Store the calculated policy in the key object */
+        *policy_harness = calloc(1, sizeof(TPMS_POLICY_HARNESS));
+        return_if_null(*policy_harness, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+        **policy_harness = context->policy.harness;
+        template->public.publicArea.authPolicy.size = context->policy.hash_size;
+        memcpy(&template->public.publicArea.authPolicy.buffer[0],
+               &context->policy.harness.policyDigests.digests[context->policy.digest_idx].digest,
+               context->policy.hash_size);
+    } else {
+        *policy_harness = NULL;
+        return TSS2_RC_SUCCESS;
+    }
+
+error_cleanup:
+    return r;
+}
diff --git a/src/tss2-fapi/ifapi_policy.h b/src/tss2-fapi/ifapi_policy.h
new file mode 100644
index 0000000..978f477
--- /dev/null
+++ b/src/tss2-fapi/ifapi_policy.h
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ *******************************************************************************/
+#ifndef IFAPI_POLICY_H
+#define IFAPI_POLICY_H
+
+#include <stdint.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <sys/stat.h>
+#include <json-c/json.h>
+#include <json-c/json_util.h>
+
+#include "tss2_esys.h"
+#include "tss2_fapi.h"
+#include "fapi_int.h"
+#include "fapi_policy.h"
+
+TSS2_RC
+get_policy_digest_idx(
+    TPML_DIGEST_VALUES *digest_values,
+    TPMI_ALG_HASH hashAlg,
+    size_t *idx);
+
+TSS2_RC
+ifapi_compute_policy_digest(
+    TPML_PCRVALUES *pcrs,
+    TPML_PCR_SELECTION *pcr_selection,
+    TPMI_ALG_HASH hash_alg,
+    TPM2B_DIGEST *pcr_digest);
+
+TSS2_RC
+ifapi_calculate_tree(
+    FAPI_CONTEXT *context,
+    const char *policyPath,
+    TPMS_POLICY_HARNESS *harness,
+    TPMI_ALG_HASH hash_alg,
+    size_t *digest_idx,
+    size_t *hash_size);
+
+TSS2_RC
+ifapi_calculate_policy_for_key(
+    FAPI_CONTEXT *context,
+    const char *policyPath,
+    IFAPI_KEY_TEMPLATE *template,
+    TPMS_POLICY_HARNESS **policy_harness);
+
+#endif /* IFAPI_POLICY_H */
diff --git a/src/tss2-fapi/ifapi_policy_calculate.c b/src/tss2-fapi/ifapi_policy_calculate.c
new file mode 100644
index 0000000..0497edd
--- /dev/null
+++ b/src/tss2-fapi/ifapi_policy_calculate.c
@@ -0,0 +1,945 @@
+/* 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 <string.h>
+#include <stdlib.h>
+
+#include "tss2_mu.h"
+#include "fapi_util.h"
+#include "fapi_crypto.h"
+#include "fapi_policy.h"
+#include "ifapi_helpers.h"
+#include "ifapi_json_deserialize.h"
+#include "tpm_json_deserialize.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+void
+copy_policy_digest(TPML_DIGEST_VALUES *dest, TPML_DIGEST_VALUES *src,
+                   size_t digest_idx, size_t hash_size, char *txt)
+{
+    memcpy(&dest->digests[digest_idx].digest, &src->digests[digest_idx].digest,
+           hash_size);
+    dest->digests[digest_idx].hashAlg = src->digests[digest_idx].hashAlg;
+    LOGBLOB_DEBUG((uint8_t *)&dest->digests[digest_idx].digest, hash_size,
+                  "%s : Copy digest size: %zu", txt, hash_size);
+    dest->count = src->count;
+}
+
+void
+log_policy_digest(TPML_DIGEST_VALUES *dest, size_t digest_idx, size_t hash_size,
+                  char *txt)
+{
+    LOGBLOB_DEBUG((uint8_t *)&dest->digests[digest_idx].digest, hash_size,
+                  "Digest %s", txt);
+}
+
+TSS2_RC
+ifapi_compute_policy_pcr(
+    TPMS_POLICYPCR *policy,
+    TPML_DIGEST_VALUES *current_digest,
+    TPMI_ALG_HASH current_hash_alg)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext;
+    TPML_PCR_SELECTION pcr_selection;
+    size_t digest_idx;
+    TPM2B_DIGEST pcr_digest;
+    size_t hash_size;
+
+    LOG_TRACE("call");
+
+    if (!(hash_size = ifapi_hash_get_digest_size(current_hash_alg))) {
+        goto_error(r, TSS2_ESYS_RC_NOT_IMPLEMENTED,
+                   "Unsupported hash algorithm (%" PRIu16 ")", cleanup,
+                   current_hash_alg);
+    }
+
+    r = get_policy_digest_idx(current_digest, current_hash_alg, &digest_idx);
+    return_if_error(r, "Get hash alg for digest.");
+
+    /* Compute PCR selection and pcr digest */
+    r = ifapi_compute_policy_digest(policy->pcrs, &pcr_selection,
+                                    current_hash_alg, &pcr_digest);
+    return_if_error(r, "Compute policy digest and selection.");
+
+    LOG_TRACE("Compute policy");
+    r = ifapi_crypto_hash_start(&cryptoContext, current_hash_alg);
+    return_if_error(r, "crypto hash start");
+
+    HASH_UPDATE_BUFFER(cryptoContext,
+                       &current_digest->digests[digest_idx].digest, hash_size,
+                       r, cleanup);
+    HASH_UPDATE(cryptoContext, TPM2_CC, TPM2_CC_PolicyPCR, r, cleanup);
+    HASH_UPDATE(cryptoContext, TPML_PCR_SELECTION, &pcr_selection, r, cleanup);
+    HASH_UPDATE_BUFFER(cryptoContext, &pcr_digest.buffer[0], hash_size, r,
+                       cleanup);
+
+    r = ifapi_crypto_hash_finish(&cryptoContext,
+                                 (uint8_t *) & current_digest->
+                                 digests[digest_idx].digest, &hash_size);
+    return_if_error(r, "crypto hash finish");
+
+cleanup:
+    return r;
+}
+
+TSS2_RC
+calculate_policy_key_param(
+    TPM2_CC command_code,
+    TPM2B_NAME *name,
+    TPM2B_NONCE *policyRef,
+    size_t hash_size,
+    TPMI_ALG_HASH current_hash_alg,
+    TPMU_HA *digest)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext;
+
+    r = ifapi_crypto_hash_start(&cryptoContext, current_hash_alg);
+    return_if_error(r, "crypto hash start");
+
+    LOGBLOB_DEBUG((uint8_t *) digest, hash_size, "Digest Start");
+    HASH_UPDATE_BUFFER(cryptoContext, digest, hash_size, r, cleanup);
+    HASH_UPDATE(cryptoContext, TPM2_CC, command_code, r, cleanup);
+    if (name && name->size > 0) {
+        LOGBLOB_DEBUG(&name->name[0], name->size, "Key name");
+        HASH_UPDATE_BUFFER(cryptoContext, &name->name[0],
+                           name->size, r, cleanup);
+    }
+    r = ifapi_crypto_hash_finish(&cryptoContext,
+                                 (uint8_t *) digest, &hash_size);
+    LOGBLOB_DEBUG((uint8_t *) digest, hash_size, "Digest Finish");
+    return_if_error(r, "crypto hash finish");
+
+    /* Use policyRef for second hash computation */
+    if (policyRef) {
+        r = ifapi_crypto_hash_start(&cryptoContext, current_hash_alg);
+        return_if_error(r, "crypto hash start");
+
+        HASH_UPDATE_BUFFER(cryptoContext, digest, hash_size, r, cleanup);
+        HASH_UPDATE_BUFFER(cryptoContext, &policyRef->buffer[0],
+                           policyRef->size, r, cleanup);
+        r = ifapi_crypto_hash_finish(&cryptoContext,
+                                     (uint8_t *) digest, &hash_size);
+        return_if_error(r, "crypto hash finish");
+    }
+
+cleanup:
+    return r;
+}
+
+TSS2_RC
+ifapi_calculate_policy_signed(
+    TPMS_POLICYSIGNED *policy,
+    TPML_DIGEST_VALUES *current_digest,
+    TPMI_ALG_HASH current_hash_alg)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    size_t digest_idx;
+    size_t hash_size;
+
+    LOG_DEBUG("call");
+
+    if (!(hash_size = ifapi_hash_get_digest_size(current_hash_alg))) {
+        goto_error(r, TSS2_ESYS_RC_NOT_IMPLEMENTED,
+                   "Unsupported hash algorithm (%" PRIu16 ")", cleanup,
+                   current_hash_alg);
+    }
+
+    r = get_policy_digest_idx(current_digest, current_hash_alg, &digest_idx);
+    return_if_error(r, "Get hash alg for digest.");
+
+    r = calculate_policy_key_param(TPM2_CC_PolicySigned,
+                                   &policy->publicKey,
+                                   &policy->policyRef, hash_size,
+                                   current_hash_alg,
+                                   &current_digest->digests[digest_idx].digest);
+    goto_if_error(r, "crypto hash start", cleanup);
+
+cleanup:
+    return r;
+}
+
+TSS2_RC
+ifapi_calculate_policy_authorize_nv(
+    TPMS_POLICYAUTHORIZENV *policy,
+    TPML_DIGEST_VALUES *current_digest,
+    TPMI_ALG_HASH current_hash_alg)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    size_t digest_idx;
+    size_t hash_size;
+    TPM2B_NAME nv_name;
+
+    LOG_DEBUG("call");
+
+    r = ifapi_nv_get_name(&policy->nvPublic, &nv_name);
+    return_if_error(r, "Compute NV name");
+
+    if (!(hash_size = ifapi_hash_get_digest_size(current_hash_alg))) {
+        goto_error(r, TSS2_ESYS_RC_NOT_IMPLEMENTED,
+                   "Unsupported hash algorithm (%" PRIu16 ")", cleanup,
+                   current_hash_alg);
+    }
+
+    r = get_policy_digest_idx(current_digest, current_hash_alg, &digest_idx);
+    return_if_error(r, "Get hash alg for digest.");
+
+    r = calculate_policy_key_param(TPM2_CC_PolicyAuthorizeNV,
+                                   &nv_name,
+                                   NULL, hash_size, current_hash_alg,
+                                   &current_digest->digests[digest_idx].digest);
+    goto_if_error(r, "crypto hash start", cleanup);
+
+cleanup:
+    return r;
+}
+
+TSS2_RC
+ifapi_calculate_policy_duplicate(
+    TPMS_POLICYDUPLICATIONSELECT *policy,
+    TPML_DIGEST_VALUES *current_digest,
+    TPMI_ALG_HASH current_hash_alg)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext;
+    size_t digest_idx;
+    size_t hash_size;
+
+    LOG_DEBUG("call");
+
+    if (!(hash_size = ifapi_hash_get_digest_size(current_hash_alg))) {
+        goto_error(r, TSS2_ESYS_RC_NOT_IMPLEMENTED,
+                   "Unsupported hash algorithm (%" PRIu16 ")", cleanup,
+                   current_hash_alg);
+    }
+
+    r = get_policy_digest_idx(current_digest, current_hash_alg, &digest_idx);
+    return_if_error(r, "Get hash alg for digest.");
+
+    LOG_TRACE("Compute policy");
+    r = ifapi_crypto_hash_start(&cryptoContext, current_hash_alg);
+    return_if_error(r, "crypto hash start");
+
+    HASH_UPDATE_BUFFER(cryptoContext,
+                       &current_digest->digests[digest_idx].digest, hash_size,
+                       r, cleanup);
+    HASH_UPDATE(cryptoContext, TPM2_CC, TPM2_CC_PolicyDuplicationSelect, r,
+                cleanup);
+    LOGBLOB_DEBUG(&policy->newParentName.name[0], policy->newParentName.size,
+                  "Policy Duplicate Parent Name");
+    HASH_UPDATE_BUFFER(cryptoContext, &policy->newParentName.name[0],
+                       policy->newParentName.size, r, cleanup);
+    HASH_UPDATE(cryptoContext, BYTE, policy->includeObject, r, cleanup);
+
+    r = ifapi_crypto_hash_finish(&cryptoContext,
+                                 (uint8_t *) & current_digest->
+                                 digests[digest_idx].digest, &hash_size);
+    return_if_error(r, "crypto hash finish");
+
+    LOGBLOB_DEBUG((uint8_t *) & current_digest->digests[digest_idx].digest,
+                  hash_size, "Policy Duplicate digest");
+
+cleanup:
+    return r;
+}
+
+TSS2_RC
+ifapi_calculate_policy_authorize(
+    TPMS_POLICYAUTHORIZE *policy,
+    TPML_DIGEST_VALUES *current_digest,
+    TPMI_ALG_HASH current_hash_alg)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    size_t digest_idx;
+    size_t hash_size;
+
+    LOG_DEBUG("call");
+
+    if (!(hash_size = ifapi_hash_get_digest_size(current_hash_alg))) {
+        goto_error(r, TSS2_ESYS_RC_NOT_IMPLEMENTED,
+                   "Unsupported hash algorithm (%" PRIu16 ")", cleanup,
+                   current_hash_alg);
+    }
+
+    r = get_policy_digest_idx(current_digest, current_hash_alg, &digest_idx);
+    return_if_error(r, "Get hash alg for digest.");
+
+    r = calculate_policy_key_param(TPM2_CC_PolicyAuthorize,
+                                   &policy->keyName,
+                                   &policy->policyRef, hash_size,
+                                   current_hash_alg,
+                                   &current_digest->digests[digest_idx].digest);
+    goto_if_error(r, "crypto hash start", cleanup);
+
+cleanup:
+    return r;
+}
+
+TSS2_RC
+ifapi_calculate_policy_secret(
+    TPMS_POLICYSECRET *policy,
+    TPML_DIGEST_VALUES *current_digest,
+    TPMI_ALG_HASH current_hash_alg)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    size_t digest_idx;
+    size_t hash_size;
+
+    LOG_DEBUG("call");
+
+    if (!(hash_size = ifapi_hash_get_digest_size(current_hash_alg))) {
+        goto_error(r, TSS2_ESYS_RC_NOT_IMPLEMENTED,
+                   "Unsupported hash algorithm (%" PRIu16 ")", cleanup,
+                   current_hash_alg);
+    }
+
+    r = get_policy_digest_idx(current_digest, current_hash_alg, &digest_idx);
+    return_if_error(r, "Get hash alg for digest.");
+
+    r = calculate_policy_key_param(TPM2_CC_PolicySecret,
+                                   (TPM2B_NAME *)&policy->objectName,
+                                   &policy->policyRef, hash_size,
+                                   current_hash_alg,
+                                   &current_digest->digests[digest_idx].digest);
+    goto_if_error(r, "crypto hash start", cleanup);
+
+cleanup:
+    return r;
+}
+
+TSS2_RC
+ifapi_calculate_policy_counter_timer(
+    TPMS_POLICYCOUNTERTIMER *policy,
+    TPML_DIGEST_VALUES *current_digest,
+    TPMI_ALG_HASH current_hash_alg)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext;
+    size_t digest_idx;
+    size_t hash_size;
+    TPM2B_DIGEST counter_timer_hash;
+
+    LOG_DEBUG("call");
+
+    if (!(hash_size = ifapi_hash_get_digest_size(current_hash_alg))) {
+        goto_error(r, TSS2_ESYS_RC_NOT_IMPLEMENTED,
+                   "Unsupported hash algorithm (%" PRIu16 ")", cleanup,
+                   current_hash_alg);
+    }
+
+    r = get_policy_digest_idx(current_digest, current_hash_alg, &digest_idx);
+    return_if_error(r, "Get hash alg for digest.");
+
+    r = ifapi_crypto_hash_start(&cryptoContext, current_hash_alg);
+    return_if_error(r, "crypto hash start");
+
+    HASH_UPDATE_BUFFER(cryptoContext, &policy->operandB.buffer[0],
+                       policy->operandB.size, r, cleanup);
+    HASH_UPDATE(cryptoContext, UINT16, policy->offset, r, cleanup);
+    HASH_UPDATE(cryptoContext, UINT16, policy->operation, r, cleanup);
+
+    r = ifapi_crypto_hash_finish(&cryptoContext,
+                                 (uint8_t *) &counter_timer_hash.buffer[0], &hash_size);
+    return_if_error(r, "crypto hash finish");
+
+    r = ifapi_crypto_hash_start(&cryptoContext, current_hash_alg);
+    return_if_error(r, "crypto hash start");
+
+    HASH_UPDATE_BUFFER(cryptoContext,
+                       &current_digest->digests[digest_idx].digest, hash_size,
+                       r, cleanup);
+    HASH_UPDATE(cryptoContext, TPM2_CC, TPM2_CC_PolicyCounterTimer, r, cleanup);
+    HASH_UPDATE_BUFFER(cryptoContext, &counter_timer_hash.buffer[0],
+                       hash_size, r, cleanup);
+    r = ifapi_crypto_hash_finish(&cryptoContext,
+                                 (uint8_t *) &current_digest->digests[digest_idx].digest,
+                                 &hash_size);
+cleanup:
+    return r;
+}
+
+/** Update plolicy if only the command codes is used
+ */
+TSS2_RC
+ifapi_calculate_simple_policy(
+    TPM2_CC command_code1,
+    TPM2_CC command_code2,
+    TPML_DIGEST_VALUES *current_digest,
+    TPMI_ALG_HASH current_hash_alg)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext;
+    size_t digest_idx;
+    size_t hash_size;
+
+    LOG_DEBUG("call");
+
+    if (!(hash_size = ifapi_hash_get_digest_size(current_hash_alg))) {
+        goto_error(r, TSS2_ESYS_RC_NOT_IMPLEMENTED,
+                   "Unsupported hash algorithm (%" PRIu16 ")", cleanup,
+                   current_hash_alg);
+    }
+
+    r = get_policy_digest_idx(current_digest, current_hash_alg, &digest_idx);
+    return_if_error(r, "Get hash alg for digest.");
+
+    r = ifapi_crypto_hash_start(&cryptoContext, current_hash_alg);
+    return_if_error(r, "crypto hash start");
+
+    HASH_UPDATE_BUFFER(cryptoContext,
+                       &current_digest->digests[digest_idx].digest, hash_size,
+                       r, cleanup);
+    if (command_code1) {
+        HASH_UPDATE(cryptoContext, TPM2_CC, command_code1, r, cleanup);
+    }
+    if (command_code2) {
+        HASH_UPDATE(cryptoContext, TPM2_CC, command_code2, r, cleanup);
+    }
+    r = ifapi_crypto_hash_finish(&cryptoContext,
+                                 (uint8_t *) &current_digest->digests[digest_idx].digest,
+                                 &hash_size);
+
+cleanup:
+    return r;
+}
+
+TSS2_RC
+ifapi_calculate_policy_physical_presence(
+    TPMS_POLICYPHYSICALPRESENCE *policy,
+    TPML_DIGEST_VALUES *current_digest,
+    TPMI_ALG_HASH current_hash_alg)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    (void)policy;
+
+    LOG_DEBUG("call");
+
+    r = ifapi_calculate_simple_policy(TPM2_CC_PolicyPhysicalPresence, 0,
+            current_digest, current_hash_alg);
+    return_if_error(r, "Calculate policy for command code.");
+
+    return r;
+}
+
+TSS2_RC
+ifapi_calculate_policy_auth_value(
+    TPMS_POLICYAUTHVALUE *policy,
+    TPML_DIGEST_VALUES *current_digest,
+    TPMI_ALG_HASH current_hash_alg)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    (void)policy;
+
+    LOG_DEBUG("call");
+
+    r = ifapi_calculate_simple_policy(TPM2_CC_PolicyAuthValue, 0,
+            current_digest, current_hash_alg);
+    return_if_error(r, "Calculate policy auth value.");
+
+    return r;
+}
+
+TSS2_RC
+ifapi_calculate_policy_password(
+    TPMS_POLICYPASSWORD *policy,
+    TPML_DIGEST_VALUES *current_digest,
+    TPMI_ALG_HASH current_hash_alg)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    (void)policy;
+
+    LOG_DEBUG("call");
+
+    r = ifapi_calculate_simple_policy(TPM2_CC_PolicyAuthValue, 0,
+            current_digest, current_hash_alg);
+    return_if_error(r, "Calculate policy password.");
+
+    return r;
+}
+
+TSS2_RC
+ifapi_calculate_policy_command_code(
+    TPMS_POLICYCOMMANDCODE *policy,
+    TPML_DIGEST_VALUES *current_digest,
+    TPMI_ALG_HASH current_hash_alg)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+
+    LOG_DEBUG("call");
+
+    r = ifapi_calculate_simple_policy(TPM2_CC_PolicyCommandCode, policy->code,
+            current_digest, current_hash_alg);
+    return_if_error(r, "Calculate policy for command code.");
+
+    return r;
+}
+
+/** Compute policy if only a special digest will bed added.
+ */
+TSS2_RC
+ifapi_calculate_policy_digest_hash(
+    TPM2B_DIGEST *digest,
+    TPML_DIGEST_VALUES *current_digest,
+    TPMI_ALG_HASH current_hash_alg,
+    TPM2_CC command_code)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext;
+    size_t digest_idx;
+    size_t hash_size;
+
+    LOG_DEBUG("call");
+
+    if (!(hash_size = ifapi_hash_get_digest_size(current_hash_alg))) {
+        goto_error(r, TSS2_ESYS_RC_NOT_IMPLEMENTED,
+                   "Unsupported hash algorithm (%" PRIu16 ")", cleanup,
+                   current_hash_alg);
+    }
+
+    r = get_policy_digest_idx(current_digest, current_hash_alg, &digest_idx);
+    return_if_error(r, "Get hash alg for digest.");
+
+    r = ifapi_crypto_hash_start(&cryptoContext, current_hash_alg);
+    return_if_error(r, "crypto hash start");
+
+    HASH_UPDATE_BUFFER(cryptoContext,
+                       &current_digest->digests[digest_idx].digest, hash_size,
+                       r, cleanup);
+    HASH_UPDATE(cryptoContext, TPM2_CC, command_code, r, cleanup);
+    HASH_UPDATE_BUFFER(cryptoContext, &digest->buffer[0],
+                       digest->size, r, cleanup);
+    r = ifapi_crypto_hash_finish(&cryptoContext,
+                                 (uint8_t *) &current_digest->digests[digest_idx].digest,
+                                 &hash_size);
+cleanup:
+    return r;
+}
+
+TSS2_RC
+ifapi_calculate_policy_name_hash(
+    TPMS_POLICYNAMEHASH *policy,
+    TPML_DIGEST_VALUES *current_digest,
+    TPMI_ALG_HASH current_hash_alg)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext;
+    size_t hash_size;
+    size_t i;
+
+    LOG_DEBUG("call");
+
+    if (!(hash_size = ifapi_hash_get_digest_size(current_hash_alg))) {
+        goto_error(r, TSS2_ESYS_RC_NOT_IMPLEMENTED,
+                   "Unsupported hash algorithm (%" PRIu16 ")", cleanup,
+                   current_hash_alg);
+    }
+
+    r = ifapi_crypto_hash_start(&cryptoContext, current_hash_alg);
+    return_if_error(r, "crypto hash start");
+
+    /* Compute name hash from the list of object names */
+    for (i = 0; i <= policy->count; i++) {
+        HASH_UPDATE_BUFFER(cryptoContext, &policy->objectNames[i].name[0],
+                           policy->objectNames[i].size, r,
+                           cleanup);
+    }
+    r = ifapi_crypto_hash_finish(&cryptoContext,
+                                 (uint8_t *) &policy->nameHash.buffer[0],
+                                 &hash_size);
+    return_if_error(r, "crypto hash finish");
+
+    policy->nameHash.size = hash_size;
+    r = ifapi_calculate_policy_digest_hash(&policy->nameHash,
+                                           current_digest,
+                                           current_hash_alg, TPM2_CC_PolicyNameHash);
+    return_if_error(r, "Calculate digest hash for policy");
+
+ cleanup:
+    return r;
+}
+
+TSS2_RC
+ifapi_calculate_policy_cp_hash(
+    TPMS_POLICYCPHASH *policy,
+    TPML_DIGEST_VALUES *current_digest,
+    TPMI_ALG_HASH current_hash_alg)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+
+    LOG_DEBUG("call");
+
+    r = ifapi_calculate_policy_digest_hash(&policy->cpHash,
+                                           current_digest, current_hash_alg,
+                                           TPM2_CC_PolicyCpHash);
+    return_if_error(r, "Calculate digest hash for policy");
+
+    return r;
+}
+
+TSS2_RC
+ifapi_calculate_policy_locality(
+    TPMS_POLICYLOCALITY *policy,
+    TPML_DIGEST_VALUES *current_digest,
+    TPMI_ALG_HASH current_hash_alg)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext;
+    size_t digest_idx;
+    size_t hash_size;
+
+    LOG_DEBUG("call");
+
+    if (!(hash_size = ifapi_hash_get_digest_size(current_hash_alg))) {
+        goto_error(r, TSS2_ESYS_RC_NOT_IMPLEMENTED,
+                   "Unsupported hash algorithm (%" PRIu16 ")", cleanup,
+                   current_hash_alg);
+    }
+
+    r = get_policy_digest_idx(current_digest, current_hash_alg, &digest_idx);
+    return_if_error(r, "Get hash alg for digest.");
+
+    r = ifapi_crypto_hash_start(&cryptoContext, current_hash_alg);
+    return_if_error(r, "crypto hash start");
+
+    HASH_UPDATE_BUFFER(cryptoContext,
+                       &current_digest->digests[digest_idx].digest, hash_size,
+                       r, cleanup);
+    HASH_UPDATE(cryptoContext, TPM2_CC, TPM2_CC_PolicyLocality, r, cleanup);
+    HASH_UPDATE(cryptoContext, BYTE, policy->locality, r, cleanup);
+    r = ifapi_crypto_hash_finish(&cryptoContext,
+                                 (uint8_t *) & current_digest->
+                                 digests[digest_idx].digest, &hash_size);
+
+cleanup:
+    return r;
+}
+
+TSS2_RC
+ifapi_calculate_policy_nv_written(
+    TPMS_POLICYNVWRITTEN *policy,
+    TPML_DIGEST_VALUES *current_digest,
+    TPMI_ALG_HASH current_hash_alg)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext;
+    size_t digest_idx;
+    size_t hash_size;
+
+    LOG_DEBUG("call");
+
+    if (!(hash_size = ifapi_hash_get_digest_size(current_hash_alg))) {
+        goto_error(r, TSS2_ESYS_RC_NOT_IMPLEMENTED,
+                   "Unsupported hash algorithm (%" PRIu16 ")", cleanup,
+                   current_hash_alg);
+    }
+
+    r = get_policy_digest_idx(current_digest, current_hash_alg, &digest_idx);
+    return_if_error(r, "Get hash alg for digest.");
+
+    r = ifapi_crypto_hash_start(&cryptoContext, current_hash_alg);
+    return_if_error(r, "crypto hash start");
+
+    HASH_UPDATE_BUFFER(cryptoContext,
+                       &current_digest->digests[digest_idx].digest, hash_size,
+                       r, cleanup);
+    HASH_UPDATE(cryptoContext, TPM2_CC, TPM2_CC_PolicyNvWritten, r, cleanup);
+    HASH_UPDATE(cryptoContext, BYTE, policy->writtenSet, r, cleanup);
+    r = ifapi_crypto_hash_finish(&cryptoContext,
+                                 (uint8_t *) & current_digest->
+                                 digests[digest_idx].digest, &hash_size);
+
+cleanup:
+    return r;
+}
+
+TSS2_RC
+ifapi_calculate_policy_nv(
+    TPMS_POLICYNV *policy,
+    TPML_DIGEST_VALUES *current_digest,
+    TPMI_ALG_HASH current_hash_alg)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext;
+    TPM2B_NAME nv_name;
+    size_t hash_size;
+    TPM2B_DIGEST nv_hash;
+    size_t digest_idx;
+
+    LOG_DEBUG("call");
+
+    memset(&nv_name, 0, sizeof(TPM2B_NAME));
+
+    /* Compute NV name from public info */
+
+    r = ifapi_nv_get_name(&policy->nvPublic, &nv_name);
+    return_if_error(r, "Compute NV name");
+
+    r = get_policy_digest_idx(current_digest, current_hash_alg, &digest_idx);
+    return_if_error(r, "Get hash alg for digest.");
+
+    r = ifapi_crypto_hash_start(&cryptoContext, current_hash_alg);
+    return_if_error(r, "crypto hash start");
+
+    HASH_UPDATE_BUFFER(cryptoContext, &policy->operandB.buffer[0],
+                       policy->operandB.size, r, cleanup);
+    HASH_UPDATE(cryptoContext, UINT16, policy->offset, r, cleanup);
+    HASH_UPDATE(cryptoContext, UINT16, policy->operation, r, cleanup);
+    r = ifapi_crypto_hash_finish(&cryptoContext,
+                                 (uint8_t *) &nv_hash.buffer[0], &hash_size);
+    return_if_error(r, "crypto hash finish");
+
+    nv_hash.size = hash_size;
+
+    r = ifapi_crypto_hash_start(&cryptoContext, current_hash_alg);
+    return_if_error(r, "crypto hash start");
+
+    HASH_UPDATE_BUFFER(cryptoContext,
+                       &current_digest->digests[digest_idx].digest, hash_size,
+                       r, cleanup);
+    HASH_UPDATE(cryptoContext, TPM2_CC, TPM2_CC_PolicyNV, r, cleanup);
+    HASH_UPDATE_BUFFER(cryptoContext, &nv_hash.buffer[0], nv_hash.size, r, cleanup)
+    HASH_UPDATE_BUFFER(cryptoContext, &nv_name.name[0], nv_name.size, r, cleanup);
+    r = ifapi_crypto_hash_finish(&cryptoContext,
+                                 (uint8_t *) &current_digest->digests[digest_idx].digest,
+                                 &hash_size);
+    return_if_error(r, "crypto hash finish");
+
+cleanup:
+    return r;
+}
+
+TSS2_RC
+ifapi_calculate_policy_or(
+    TPMS_POLICYOR *policyOr,
+    TPML_DIGEST_VALUES *current_digest,
+    TPMI_ALG_HASH hash_alg,
+    size_t hash_size,
+    size_t digest_idx)
+{
+    size_t i;
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext;
+
+    for (i = 0; i < policyOr->branches->count; i++) {
+        copy_policy_digest(&policyOr->branches->authorizations[i].policyDigests,
+                           current_digest, digest_idx, hash_size,
+                           "Copy or digest");
+
+        r = ifapi_calculate_policy(policyOr->branches->authorizations[i].policy,
+                                   &policyOr->branches->authorizations[i].
+                                   policyDigests, hash_alg, hash_size,
+                                   digest_idx);
+        log_policy_digest(&policyOr->branches->authorizations[i].policyDigests,
+                          digest_idx, hash_size, "Branch digest");
+
+        return_if_error(r, "Compute policy.");
+    }
+    /* Reset the or policy digest because the digest is included in all sub policies */
+    memset(&current_digest->digests[digest_idx], 0, hash_size);
+    r = ifapi_crypto_hash_start(&cryptoContext, hash_alg);
+    return_if_error(r, "crypto hash start");
+    r = ifapi_crypto_hash_update(cryptoContext, (const uint8_t *)
+                                 &current_digest->digests[digest_idx].digest,
+                                 hash_size);
+    return_if_error(r, "crypto hash update");
+
+    uint8_t buffer[sizeof(TPM2_CC)];
+    size_t offset = 0;
+    r = Tss2_MU_TPM2_CC_Marshal(TPM2_CC_PolicyOR,
+                                &buffer[0], sizeof(TPM2_CC), &offset);
+    return_if_error(r, "Marshal cc");
+
+    r = ifapi_crypto_hash_update(cryptoContext,
+                                 (const uint8_t *)&buffer[0], sizeof(TPM2_CC));
+    return_if_error(r, "crypto hash update");
+
+    for (i = 0; i < policyOr->branches->count; i++) {
+        r = ifapi_crypto_hash_update(cryptoContext, (const uint8_t *)
+                                     &policyOr->branches->authorizations[i]
+                                     .policyDigests.digests[digest_idx].digest,
+                                     hash_size);
+        log_policy_digest(&policyOr->branches->authorizations[i].policyDigests,
+                          digest_idx, hash_size, "Or branch");
+        current_digest->count =
+            policyOr->branches->authorizations[i].policyDigests.count;
+        return_if_error(r, "crypto hash update");
+    }
+    current_digest->digests[digest_idx].hashAlg = hash_alg;
+    r = ifapi_crypto_hash_finish(&cryptoContext,
+                                 (uint8_t *) & current_digest->
+                                 digests[digest_idx].digest, &hash_size);
+    log_policy_digest(current_digest, digest_idx, hash_size, "Final or digest");
+    return_if_error(r, "crypto hash finish");
+
+    return r;
+}
+
+TSS2_RC
+ifapi_calculate_policy(
+    TPML_POLICYELEMENTS *policy,
+    TPML_DIGEST_VALUES *policyDigests,
+    TPMI_ALG_HASH hash_alg,
+    size_t hash_size,
+    size_t digest_idx)
+{
+    size_t i;
+    TSS2_RC r = TSS2_RC_SUCCESS;
+
+    for (i = 0; i < policy->count; i++) {
+
+        copy_policy_digest(&policy->elements[i].policyDigests,
+                           policyDigests, digest_idx, hash_size,
+                           "Copy policy digest (to)");
+
+        switch (policy->elements[i].type) {
+
+        case POLICYPCR:
+            r = ifapi_compute_policy_pcr(&policy->elements[i].element.PolicyPCR,
+                                         &policy->elements[i].policyDigests,
+                                         hash_alg);
+            return_if_error(r, "Compute policy pcr");
+            break;
+
+        case POLICYSIGNED:
+            r = ifapi_calculate_policy_signed(&policy->elements[i].element.
+                                              PolicySigned,
+                                              &policy->elements[i].
+                                              policyDigests, hash_alg);
+            return_if_error(r, "Compute policy nv");
+
+            break;
+
+        case POLICYDUPLICATIONSELECT:
+            r = ifapi_calculate_policy_duplicate(&policy->elements[i].element.
+                                                 PolicyDuplicationSelect,
+                                                 &policy->elements[i].
+                                                 policyDigests, hash_alg);
+            return_if_error(r, "Compute policy duplication select");
+
+            break;
+
+        case POLICYAUTHORIZENV:
+            r = ifapi_calculate_policy_authorize_nv(&policy->elements[i].
+                                                    element.PolicyAuthorizeNv,
+                                                    &policy->elements[i].
+                                                    policyDigests, hash_alg);
+            return_if_error(r, "Compute policy authorizeg");
+
+            break;
+
+        case POLICYAUTHORIZE:
+            r = ifapi_calculate_policy_authorize(&policy->elements[i].element.
+                                                 PolicyAuthorize,
+                                                 &policy->elements[i].
+                                                 policyDigests, hash_alg);
+            return_if_error(r, "Compute policy authorizeg");
+
+            break;
+
+        case POLICYSECRET:
+            r = ifapi_calculate_policy_secret(&policy->elements[i].element.
+                                              PolicySecret,
+                                              &policy->elements[i].
+                                              policyDigests, hash_alg);
+            return_if_error(r, "Compute policy nv");
+
+            break;
+
+        case POLICYOR:
+            r = ifapi_calculate_policy_or(&policy->elements[i].element.PolicyOr,
+                                          &policy->elements[i].policyDigests,
+                                          hash_alg, hash_size, digest_idx);
+            return_if_error(r, "Compute policy or");
+
+            break;
+
+        case POLICYNV:
+            r = ifapi_calculate_policy_nv(&policy->elements[i].element.PolicyNV,
+                                          &policy->elements[i].policyDigests,
+                                          hash_alg);
+            return_if_error(r, "Compute policy nv");
+
+            break;
+
+        case POLICYNVWRITTEN:
+            r = ifapi_calculate_policy_nv_written(&policy->elements[i].element.
+                                                  PolicyNvWritten,
+                                                  &policy->elements[i].
+                                                  policyDigests, hash_alg);
+            return_if_error(r, "Compute policy nv written");
+            break;
+
+        case POLICYCOUNTERTIMER:
+            r = ifapi_calculate_policy_counter_timer(
+                    &policy->elements[i].element.PolicyCounterTimer,
+                    &policy->elements[i].policyDigests, hash_alg);
+            return_if_error(r, "Compute policy counter timer");
+            break;
+
+        case POLICYPHYSICALPRESENCE:
+            r = ifapi_calculate_policy_physical_presence(
+                    &policy->elements[i].element.PolicyPhysicalPresence,
+                    &policy->elements[i].policyDigests, hash_alg);
+            return_if_error(r, "Compute policy physical presence");
+            break;
+
+        case POLICYAUTHVALUE:
+            r = ifapi_calculate_policy_auth_value(&policy->elements[i].element.PolicyAuthValue,
+                                                  &policy->elements[i].policyDigests, hash_alg);
+            return_if_error(r, "Compute policy auth value");
+            break;
+
+        case POLICYPASSWORD:
+            r = ifapi_calculate_policy_password(&policy->elements[i].element.PolicyPassword,
+                                                &policy->elements[i].policyDigests, hash_alg);
+            return_if_error(r, "Compute policy password");
+            break;
+
+        case POLICYCOMMANDCODE:
+            r = ifapi_calculate_policy_command_code(&policy->elements[i].element.PolicyCommandCode,
+                                                    &policy->elements[i].policyDigests, hash_alg);
+            return_if_error(r, "Compute policy physical presence");
+            break;
+
+        case POLICYNAMEHASH:
+            r = ifapi_calculate_policy_name_hash(&policy->elements[i].element.PolicyNameHash,
+                                                 &policy->elements[i].policyDigests, hash_alg);
+            return_if_error(r, "Compute policy  name hash");
+            break;
+
+        case POLICYCPHASH:
+            r = ifapi_calculate_policy_cp_hash(&policy->elements[i].element.PolicyCpHash,
+                                               &policy->elements[i].policyDigests, hash_alg);
+            return_if_error(r, "Compute policy cp hash");
+            break;
+
+        case POLICYLOCALITY:
+            r = ifapi_calculate_policy_locality(&policy->elements[i].element.PolicyLocality,
+                                                &policy->elements[i].policyDigests, hash_alg);
+            return_if_error(r, "Compute policy locality");
+            break;
+
+        case POLICYACTION:
+            /* This does not alter the policyDigest */
+            break;
+
+        default:
+            return_error(TSS2_ESYS_RC_NOT_IMPLEMENTED,
+                         "Policy not implemented");
+        }
+
+        copy_policy_digest(policyDigests, &policy->elements[i].policyDigests,
+                           digest_idx, hash_size, "Copy policy digest (from)");
+    }
+    return r;
+}
diff --git a/src/tss2-fapi/ifapi_policy_calculate.h b/src/tss2-fapi/ifapi_policy_calculate.h
new file mode 100644
index 0000000..ae2d7cf
--- /dev/null
+++ b/src/tss2-fapi/ifapi_policy_calculate.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ *******************************************************************************/
+#ifndef FAPI_POLICY_CALCULATE_H
+#define FAPI_POLICY_CALCULATE_H
+
+#include <stdint.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <sys/stat.h>
+#include <json-c/json.h>
+#include <json-c/json_util.h>
+
+#include "tss2_esys.h"
+#include "tss2_fapi.h"
+#include "fapi_int.h"
+//#include "fapi_policy.h"
+//#include "ifapi_keystore.h"
+
+TSS2_RC
+ifapi_calculate_policy(
+    TPML_POLICYELEMENTS *policy,
+    TPML_DIGEST_VALUES *policyDigests,
+    TPMI_ALG_HASH hash_alg,
+    size_t hash_size,
+    size_t digest_idx);
+
+#endif /* FAPI_POLICY_CALCULATE_H */
diff --git a/src/tss2-fapi/ifapi_policy_callbacks.c b/src/tss2-fapi/ifapi_policy_callbacks.c
new file mode 100644
index 0000000..9108d3d
--- /dev/null
+++ b/src/tss2-fapi/ifapi_policy_callbacks.c
@@ -0,0 +1,1203 @@
+/* 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 <string.h>
+#include <stdlib.h>
+
+#include "fapi_util.h"
+#include "fapi_policy.h"
+#include "ifapi_helpers.h"
+#include "fapi_crypto.h"
+#include "ifapi_policy_instantiate.h"
+#include "ifapi_policyutil_execute.h"
+#include "ifapi_policy_execute.h"
+#include "ifapi_policy_callbacks.h"
+#include "tss2_mu.h"
+
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+static void
+get_nv_auth_object(
+    IFAPI_OBJECT *nv_object,
+    ESYS_TR nv_index,
+    IFAPI_OBJECT *auth_object,
+    ESYS_TR *auth_index)
+{
+    if (nv_object->misc.nv.public.nvPublic.attributes & TPMA_NV_PPREAD) {
+        ifapi_init_hierarchy_object(auth_object, ESYS_TR_RH_PLATFORM);
+        *auth_index = ESYS_TR_RH_PLATFORM;
+    } else {
+        if (nv_object->misc.nv.public.nvPublic.attributes & TPMA_NV_OWNERREAD) {
+            ifapi_init_hierarchy_object(auth_object, ESYS_TR_RH_OWNER);
+            *auth_index = ESYS_TR_RH_OWNER;
+        } else {
+            *auth_index = nv_index;
+            *auth_object = *nv_object;
+        }
+    }
+}
+
+/** Get public data of a key from keystore.
+ *
+ * @parm[in] path The relative path of the key.
+ * @parm[out] public The caller allocated public structure.
+ * @parm[in,out] ctx The context to access io and keystore module and to store
+*                    the io state.
+ * @retval TSS2_RC_SUCCESS on success.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be loaded.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_BAD_TEMPLATE If the loaded template is not
+ *         appropriate for this operation.
+ */
+TSS2_RC
+ifapi_get_key_public(
+    const char *path,
+    TPMT_PUBLIC *public,
+    void *ctx)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    IFAPI_OBJECT object;
+    FAPI_CONTEXT *context = ctx;
+
+    switch (context->io_state) {
+    statecase(context->io_state, IO_INIT)
+        /* Prepare the loading of the object. */
+        r = ifapi_keystore_load_async(&context->keystore, &context->io, path);
+        return_if_error2(r, "Could not open: %s", path);
+        fallthrough;
+
+    statecase(context->io_state, IO_ACTIVE)
+        /* Finalize or retry the reading and check the object type */
+        r = ifapi_keystore_load_finish(&context->keystore, &context->io,
+                                       &object);
+        return_try_again(r);
+        return_if_error(r, "read_finish failed");
+
+        switch(object.objectType) {
+        case IFAPI_KEY_OBJ:
+            *public = object.misc.key.public.publicArea;
+            break;
+        case IFAPI_EXT_PUB_KEY_OBJ:
+            *public = object.misc.ext_pub_key.public.publicArea;
+            break;
+        default:
+            goto_error(r, TSS2_FAPI_RC_BAD_TEMPLATE, "Object %s is not a key.",
+                       cleanup, path);
+        }
+        break;
+
+    statecasedefault_error(context->state, r, cleanup);
+    }
+
+ cleanup:
+    context->io_state = IO_INIT;
+    ifapi_cleanup_ifapi_object(&object);
+    return r;
+}
+
+/** Get TPM name of an object from  key keystore.
+ *
+ * @parm[in] path The relative path of the object.
+ * @parm[out] name The caller allocate public structure.
+ * @parm[in,out] ctx The context to access io and keystore module and to store
+ *               the io state.
+ * @retval TSS2_RC_SUCCESS on success.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be loaded.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_BAD_TEMPLATE If the loaded template is not
+ *         appropriate for this operation.
+ */
+TSS2_RC
+ifapi_get_object_name(
+    const char *path,
+    TPM2B_NAME *name,
+    void *ctx)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    IFAPI_OBJECT object;
+    FAPI_CONTEXT *context = ctx;
+
+    switch (context->io_state) {
+    statecase(context->io_state, IO_INIT)
+        /* Prepare the loading of the object. */
+        r = ifapi_keystore_load_async(&context->keystore, &context->io, path);
+        return_if_error2(r, "Could not open: %s", path);
+        fallthrough;
+
+    statecase(context->io_state, IO_ACTIVE)
+        /* Finalize or retry the reading and check the object type */
+        r = ifapi_keystore_load_finish(&context->keystore, &context->io,
+                                       &object);
+        return_try_again(r);
+        return_if_error(r, "read_finish failed");
+
+        switch(object.objectType) {
+        case IFAPI_KEY_OBJ:
+            r = ifapi_get_name(&object.misc.key.public.publicArea,
+                               (TPM2B_NAME *)name);
+            break;
+        case IFAPI_EXT_PUB_KEY_OBJ:
+            r = ifapi_get_name(&object.misc.ext_pub_key.public.publicArea,
+                               (TPM2B_NAME *)name);
+            break;
+        case IFAPI_NV_OBJ:
+            r = ifapi_nv_get_name(&object.misc.nv.public, name);
+            break;
+        default:
+            goto_error(r, TSS2_FAPI_RC_BAD_TEMPLATE, "Invalid object %s.",
+                       cleanup, path);
+        }
+        goto_if_error(r, "Get object name.", cleanup);
+        break;
+
+    statecasedefault(context->state);
+    }
+
+ cleanup:
+    ifapi_cleanup_ifapi_object(&object);
+    return r;
+}
+
+/** Get public data of a NV object from keystore.
+ *
+ * @parm[in] path The relative path of the NV object.
+ * @parm[out] public The caller allocated public structure.
+ * @parm[in,out] ctx The context to access io and keystore module and to store
+     *           the io state.
+ * @retval TSS2_RC_SUCCESS on success.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be loaded.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_FAPI_RC_BAD_TEMPLATE If the loaded template is not
+ *         appropriate for this operation.
+ */
+TSS2_RC
+ifapi_get_nv_public(
+    const char *path,
+    TPM2B_NV_PUBLIC *nv_public,
+    void *ctx)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    IFAPI_OBJECT object;
+    FAPI_CONTEXT *context = ctx;
+
+    switch (context->io_state) {
+    statecase(context->io_state, IO_INIT)
+        /* Prepare the loading of the object. */
+        r = ifapi_keystore_load_async(&context->keystore, &context->io, path);
+        return_if_error2(r, "Could not open: %s", path);
+        fallthrough;
+
+    statecase(context->io_state, IO_ACTIVE)
+        /* Finalize or retry the reading and check the object type */
+        r = ifapi_keystore_load_finish(&context->keystore, &context->io,
+                                       &object);
+        return_try_again(r);
+        return_if_error(r, "read_finish failed");
+
+        if (object.objectType != IFAPI_NV_OBJ) {
+            goto_error(r, TSS2_FAPI_RC_BAD_TEMPLATE, "Object %s is not a key.",
+                       cleanup, path);
+        }
+
+        *nv_public = object.misc.nv.public;
+        context->io_state = IO_INIT;
+        break;
+
+    statecasedefault(context->state);
+    }
+
+ cleanup:
+    ifapi_cleanup_ifapi_object(&object);
+    return r;
+}
+
+/** Read values of PCR registers and clear selection.
+ *
+ * @parm[in,out] pcr_select The registers to be read (bank selection from profile).
+ * @parm[in,out] pcr_selection The registers to be read (with bank selection).
+ * @parm[out] pcr_values The callee-allocated public structure.
+ * @parm[in,out] ctx The context to access io and keystore module and to store
+ *               the io state.
+ * @retval TSS2_RC_SUCCESS on success.
+ * @retval TSS2_ESYS_RC_BAD_CONTEXT: if esysContext corruption is detected.
+ * @retval TSS2_ESYS_RC_MEMORY: if the ESAPI cannot allocate enough memory for
+ *         internal operations or return parameters.
+ * @retval TSS2_ESYS_RC_BAD_SEQUENCE: if the context has an asynchronous
+ *         operation already pending.
+ * @retval TSS2_ESYS_RC_TRY_AGAIN: if the timeout counter expires before the
+ *         TPM response is received.
+ * @retval TSS2_ESYS_RC_INSUFFICIENT_RESPONSE: if the TPM's response does not
+ *         at least contain the tag, response length, and response code.
+ * @retval TSS2_ESYS_RC_RSP_AUTH_FAILED: if the response HMAC from the TPM did
+ *         not verify.
+ * @retval TSS2_ESYS_RC_MALFORMED_RESPONSE: if the TPM's response is corrupted.
+ *         internal operations or return parameters.
+ *         appropriate for this operation.
+ */
+TSS2_RC
+ifapi_read_pcr(
+    TPMS_PCR_SELECT *pcr_select,
+    TPML_PCR_SELECTION *pcr_selection,
+    TPML_PCRVALUES **pcr_values,
+    void *ctx)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    FAPI_CONTEXT *context = ctx;
+    UINT32 update_counter;
+    TPML_PCR_SELECTION *out_selection = NULL;
+    TPML_PCR_SELECTION *profile_selection;
+    TPML_DIGEST *pcr_digests = NULL;
+    size_t i, pcr, n_pcrs = 0, i_pcr;
+
+    switch (context->io_state) {
+    statecase(context->io_state, IO_INIT)
+        if (pcr_select->sizeofSelect) {
+            if (pcr_selection->count) {
+                /* If pcr_select is used pcr_selection can't be initialized */
+                return_error(TSS2_FAPI_RC_BAD_TEMPLATE,
+                             "Policy PCR: pcr_selection can't be used if pcr_selection is used.");
+            }
+            /* Determine hash alg */
+            profile_selection = &context->profiles.default_profile.pcr_selection;
+            for (i = 0; i < profile_selection->count; i++) {
+                for (pcr = 0; pcr < TPM2_MAX_PCRS; pcr++) {
+                    uint8_t byte_idx = pcr / 8;
+                    uint8_t flag = 1 << (pcr % 8);
+                    /* Check whether PCR is used. */
+                    if (flag & profile_selection->pcrSelections[i].pcrSelect[byte_idx] &&
+                        flag & pcr_select->pcrSelect[byte_idx]) {
+                        pcr_selection->pcrSelections[0].hash = profile_selection->pcrSelections[i].hash;
+                    }
+                }
+            }
+            if (!pcr_selection->pcrSelections[0].hash) {
+                /* hash for current pcr_select can't be determined */
+                return_error(TSS2_FAPI_RC_BAD_TEMPLATE,
+                             "Policy PCR: pcr_select does not match profile.");
+            }
+            /* Only one bank will be used. The hash alg from profile will be used */
+            pcr_selection->count = 1;
+            pcr_selection->pcrSelections[0].sizeofSelect = pcr_select->sizeofSelect;
+            for (i = 0; i <= TPM2_PCR_SELECT_MAX; i++)
+                pcr_selection->pcrSelections[0].pcrSelect[i] = pcr_select->pcrSelect[i];
+        }
+
+        /* Prepare the PCR Reading. */
+        r = Esys_PCR_Read_Async(context->esys,
+                                ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
+                                pcr_selection);
+        return_if_error(r, "PCR Read");
+        fallthrough;
+
+    statecase(context->io_state, IO_ACTIVE)
+        /* Finalize or retry the reading and check the object type */
+        r = Esys_PCR_Read_Finish(context->esys,
+                                 &update_counter,
+                                 &out_selection,
+                                 &pcr_digests);
+
+        if ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN)
+            return TSS2_FAPI_RC_TRY_AGAIN;
+
+        return_if_error(r, "PCR_Read_Finish");
+
+        /* Count pcrs */
+        for (i = 0; i < out_selection->count; i++) {
+            for (pcr = 0; pcr < TPM2_MAX_PCRS; pcr++) {
+                uint8_t byte_idx = pcr / 8;
+                uint8_t flag = 1 << (pcr % 8);
+                /* Check whether PCR is used. */
+                if (flag & out_selection->pcrSelections[i].pcrSelect[byte_idx])
+                    n_pcrs += 1;
+            }
+        }
+
+        *pcr_values = calloc(1, sizeof(TPML_PCRVALUES) + n_pcrs* sizeof(TPMS_PCRVALUE));
+        goto_if_null2(*pcr_values, "Out of memory.", r, TSS2_FAPI_RC_MEMORY, cleanup);
+
+        /* Initialize digest list with pcr values from TPM */
+        i_pcr = 0;
+        for (i = 0; i < out_selection->count; i++) {
+            for (pcr = 0; pcr < TPM2_MAX_PCRS; pcr++) {
+                uint8_t byte_idx = pcr / 8;
+                uint8_t flag = 1 << (pcr % 8);
+                /* Check whether PCR is used. */
+                if (flag & out_selection->pcrSelections[i].pcrSelect[byte_idx]) {
+                    (*pcr_values)->pcrs[i_pcr].pcr = pcr;
+                    (*pcr_values)->pcrs[i_pcr].hashAlg = out_selection->pcrSelections[i].hash;
+                    memcpy(&(*pcr_values)->pcrs[i_pcr].digest,
+                           &pcr_digests->digests[i_pcr].buffer[0],
+                           pcr_digests->digests[i_pcr].size);
+                    i_pcr +=1;
+                }
+            }
+        }
+
+        context->io_state = IO_INIT;
+        break;
+
+    statecasedefault(context->state);
+    }
+
+ cleanup:
+    SAFE_FREE(out_selection);
+    SAFE_FREE(pcr_digests);
+    return r;
+}
+
+/** Callback for authorization of objects used by policy.
+ *
+ * @parm[in] name The name of the object to be authorized.
+ * @parm[in] object_handle The ESYS handle of the used object.
+ * @parm[in] auth_handle will be used for object authorization. For
+             keys it will we equal to the object handle.
+ * @parm[out] authSession The session used for object authorization.
+ * @parm[in,out] userdata The Fapi context which will be used for keystore
+ *               access, and storing the policy execution state.
+ *               the io state.
+ * @retval TSS2_RC_SUCCESS on success.
+ * @retval TSS2_ESYS_RC_MEMORY: if it's not possible to allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE If no user data is passed.
+ */
+TSS2_RC
+ifapi_policyeval_cbauth(
+    TPM2B_NAME *name,
+    ESYS_TR *object_handle,
+    ESYS_TR *auth_handle,
+    ESYS_TR *authSession,
+    void *userdata)
+{
+    TSS2_RC r;
+    FAPI_CONTEXT *fapi_ctx = userdata;
+    IFAPI_POLICY_EXEC_CTX *current_policy;
+    IFAPI_POLICY_EXEC_CB_CTX *cb_ctx;
+    bool next_case;
+
+    return_if_null(fapi_ctx, "Bad user data.", TSS2_FAPI_RC_BAD_REFERENCE);
+    return_if_null(fapi_ctx->policy.policyutil_stack, "Policy not initialized.",
+                   TSS2_FAPI_RC_BAD_REFERENCE);
+
+    if (fapi_ctx->policy.util_current_policy) {
+        /* Use the current policy in the policy stack. */
+        current_policy = fapi_ctx->policy.util_current_policy->pol_exec_ctx;
+    } else {
+        /* Start with the bottom of the policy stack */
+        current_policy = fapi_ctx->policy.policyutil_stack->pol_exec_ctx;
+    }
+    cb_ctx = current_policy->app_data;
+
+    do {
+        next_case = false;
+        switch(cb_ctx->cb_state) {
+        statecase(cb_ctx->cb_state, POL_CB_EXECUTE_INIT);
+            cb_ctx->auth_index = ESYS_TR_NONE;
+            r = ifapi_keystore_search_obj(&fapi_ctx->keystore, &fapi_ctx->io,
+                                          name,
+                                          &cb_ctx->object_path);
+            FAPI_SYNC(r, "Search Object", cleanup);
+
+            r = ifapi_keystore_load_async(&fapi_ctx->keystore, &fapi_ctx->io,
+                                          cb_ctx->object_path);
+            return_if_error2(r, "Could not open: %s", cb_ctx->object_path);
+            SAFE_FREE(cb_ctx->object_path);
+            fallthrough;
+
+        statecase(cb_ctx->cb_state, POL_CB_READ_OBJECT);
+            /* Get object from file */
+            r = ifapi_keystore_load_finish(&fapi_ctx->keystore, &fapi_ctx->io,
+                                           &cb_ctx->object);
+            return_try_again(r);
+            return_if_error(r, "read_finish failed");
+
+            r = ifapi_initialize_object(fapi_ctx->esys, &cb_ctx->object);
+            goto_if_error(r, "Initialize NV object", cleanup);
+
+            if (cb_ctx->object.objectType == IFAPI_NV_OBJ) {
+                /* NV Authorization */
+
+                cb_ctx->nv_index = cb_ctx->object.handle;
+
+                get_nv_auth_object(&cb_ctx->object,
+                                   cb_ctx->object.handle,
+                                   &cb_ctx->auth_object,
+                                   &cb_ctx->auth_index);
+
+                goto_if_error(r, "PolicySecret set authorization", cleanup);
+                cb_ctx->cb_state = POL_CB_AUTHORIZE_OBJECT;
+
+                cb_ctx->auth_object_ptr = &cb_ctx->auth_object;
+                next_case = true;
+                break;
+            } else if (cb_ctx->object.objectType == IFAPI_HIERARCHY_OBJ) {
+                cb_ctx->cb_state = POL_CB_AUTHORIZE_OBJECT;
+                next_case = true;
+                break;
+            } else {
+                cb_ctx->key_handle = cb_ctx->object.handle;
+                cb_ctx->cb_state = POL_CB_LOAD_KEY;
+            }
+            fallthrough;
+
+        statecase(cb_ctx->cb_state, POL_CB_LOAD_KEY);
+            /* Key loading and authorization */
+            r = ifapi_load_key(fapi_ctx, cb_ctx->object_path,
+                               &cb_ctx->auth_object_ptr);
+            FAPI_SYNC(r, "Fapi load key.", cleanup);
+
+            cb_ctx->object = *cb_ctx->key_object_ptr;
+            SAFE_FREE(cb_ctx->key_object_ptr);
+            cb_ctx->auth_object_ptr = &cb_ctx->object;
+            fallthrough;
+
+        statecase(cb_ctx->cb_state, POL_CB_AUTHORIZE_OBJECT);
+            r = ifapi_authorize_object(fapi_ctx, cb_ctx->auth_object_ptr, authSession);
+            return_try_again(r);
+            goto_if_error(r, "Authorize  object.", cleanup);
+
+            cb_ctx->cb_state = POL_CB_EXECUTE_INIT;
+            break;
+            /* FALLTHRU */
+
+        statecasedefault(cb_ctx->cb_state);
+        }
+    } while (next_case);
+    *object_handle = cb_ctx->object.handle;
+    if (cb_ctx->object.objectType == IFAPI_NV_OBJ)
+        *auth_handle = cb_ctx->auth_index;
+    else
+        *auth_handle = cb_ctx->object.handle;
+
+    if (current_policy->policySessionSav != ESYS_TR_NONE)
+        fapi_ctx->policy.session = current_policy->policySessionSav;
+
+ cleanup:
+    ifapi_cleanup_ifapi_object(&cb_ctx->object);
+    if (current_policy->policySessionSav
+        && current_policy->policySessionSav != ESYS_TR_NONE)
+        fapi_ctx->policy.session = current_policy->policySessionSav;
+    return r;
+}
+
+/** Callback for branch selection of policy or.
+ *
+ * @parm[in] name The name of the object to be authorized.
+ * @parm[in] object_handle The ESYS handle of the used object.
+ * @parm[in] auth_handle will be used for object authorization. For
+             keys it will we equal to the object handle.
+ * @parm[out] authSession The session used for object authorization.
+ * @parm[in,out] userdata The Fapi context which will be used for keystore
+ *               access, and storing the policy execution state.
+ *               the io state.
+ * @retval TSS2_RC_SUCCESS on success.
+ * @retval TSS2_ESYS_RC_MEMORY: if it's not possible to allocate enough memory.
+ * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN If the callback for branch selection is
+ *         not defined. This callback will be needed of or policies have to be
+ *         executed.
+ * @retval TSS2_FAPI_RC_BAD_VALUE If the computed branch index deliverd by the
+ *         callback does not identify a branch.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE If no user data is passed.
+ */
+TSS2_RC
+ifapi_branch_selection(
+    TPML_POLICYBRANCHES *branches,
+    size_t *branch_idx,
+    void *userdata)
+{
+    TSS2_RC r;
+    FAPI_CONTEXT *fapi_ctx = userdata;
+    size_t i;
+    const char *names[8];
+
+    return_if_null(fapi_ctx, "Bad user data.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    if (!fapi_ctx->callbacks.branch) {
+        return_error(TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN,
+                     "No branch selection callback");
+    }
+    for (i = 0; i < branches->count; i++)
+        names[i] = branches->authorizations[i].name;
+
+    r = fapi_ctx->callbacks.branch(fapi_ctx, "PolicyOR",
+                                   &names[0],
+                                   branches->count,
+                                   branch_idx,
+                                   fapi_ctx->callbacks.branchData);
+    return_if_error(r, "policyBranchSelectionCallback");
+
+    if (*branch_idx > branches->count) {
+        return_error2(TSS2_FAPI_RC_BAD_VALUE, "Invalid branch number.");
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Callback for policyaction.
+ *
+ * @parm[in] name The name of the object to be authorized.
+ * @parm[in] object_handle The ESYS handle of the used object.
+ * @parm[in] auth_handle will be used for object authorization. For
+             keys it will we equal to the object handle.
+ * @parm[out] authSession The session used for object authorization.
+ * @parm[in,out] userdata The Fapi context which will be used for keystore
+ *               access, and storing the policy execution state.
+ *               the io state.
+ * @retval TSS2_RC_SUCCESS on success.
+ * @retval TSS2_ESYS_RC_MEMORY: if it's not possible to allocate enough memory.
+ * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN If the callback for branch selection is
+ *         not defined. This callback will be needed of or policies have to be
+ *         executed.
+ * @retval TSS2_FAPI_RC_BAD_VALUE If the computed branch index deliverd by the
+ *         callback does not identify a branch.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE If no user data is passed.
+ */
+TSS2_RC
+ifapi_policy_action(
+    const char *action,
+    void *userdata)
+{
+    TSS2_RC r;
+    FAPI_CONTEXT *fapi_ctx = userdata;
+    return_if_null(fapi_ctx, "Bad user data.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    if (!fapi_ctx->callbacks.action) {
+        return_error(TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN,
+                     "No action callback");
+    }
+    r = fapi_ctx->callbacks.action(fapi_ctx, action,
+                                   fapi_ctx->callbacks.actionData);
+    return_if_error(r, "ifapi_policy_action callback");
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Callback for signing a byte buffer.
+ *
+ * @parm[in] key_pem The pem key used for signing operation.
+ * @parm[in] key_pem_hash_alg The hash alg used for digest computation.
+ * @parm[in] buffer the byte array to be signed.
+ * @parm[in] buffer_size The size of the buffer to be signed.
+ * @parm[out] signature The signature in DER format.
+ * @parm[out] signature_size The size of the signature.
+ * @parm[in] userdata The user context to retrieve the signing function.
+ * @retval TSS2_RC_SUCCESS on success.
+ * @retval TSS2_ESYS_RC_MEMORY: if it's not possible to allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE If no user data is passed.
+ */
+TSS2_RC
+ifapi_sign_buffer(
+    char *key_pem,
+    TPMI_ALG_HASH key_pem_hash_alg,
+    uint8_t *buffer,
+    size_t buffer_size,
+    uint8_t **signature,
+    size_t *signature_size,
+    void *userdata)
+{
+    TSS2_RC r;
+    FAPI_CONTEXT *fapi_ctx = userdata;
+
+    return_if_null(fapi_ctx, "Bad user data.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    if (!fapi_ctx->callbacks.sign) {
+        return_error2(TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN,
+                      "No signature callback.");
+    }
+    r = fapi_ctx->callbacks.sign(fapi_ctx, "PolicySigned", key_pem, "",       // TODO check publicKeyHint
+                                 key_pem_hash_alg,
+                                 buffer, buffer_size,
+                                 signature, signature_size,
+                                 fapi_ctx->callbacks.signData);
+    try_again_or_error(r, "Execute policy signature callback.");
+
+    return TSS2_RC_SUCCESS;
+}
+
+/**  Check whether public data of key is assigned to policy.
+ *
+ * It will be checked whether policy was authorized with key with public
+ * data of type TPMT_PUBLIC.
+ */
+static TSS2_RC
+equal_policy_authorization(
+    TPMS_POLICY_HARNESS *policy,
+    void *publicVoid,
+    void *nameAlgVoid,
+    bool *equal)
+{
+    TPMT_PUBLIC *public = publicVoid;
+    (void)nameAlgVoid;
+    size_t i;
+    TPML_POLICYAUTHORIZATIONS *authorizations = policy->policyAuthorizations;
+
+    *equal = false;
+    if (authorizations) {
+        for (i = 0; i < authorizations->count; i++) {
+            if (ifapi_TPMT_PUBLIC_cmp
+                (public, &authorizations->authorizations[i].key)) {
+                *equal = true;
+                return TSS2_RC_SUCCESS;
+            }
+        }
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Check whether policy digest can be found in policy.
+ *
+ * It will be testes whether the policy has been instatiated with the
+ * passed digest.
+ */
+static TSS2_RC
+compare_policy_digest(
+    TPMS_POLICY_HARNESS *policy,
+    void *authPolicyVoid,
+    void *nameAlgVoid,
+    bool *equal)
+{
+    TPM2B_DIGEST *authPolicy = authPolicyVoid;
+    TPMI_ALG_HASH *hash_alg_ptr = nameAlgVoid;
+    TPMI_ALG_HASH hash_alg = *hash_alg_ptr;
+    size_t i;
+    TPML_DIGEST_VALUES *digest_values;
+
+    *equal = false;
+
+    digest_values = &policy->policyDigests;
+
+    if (digest_values) {
+        for (i = 0; i < digest_values->count; i++) {
+            if (digest_values->digests[i].hashAlg == hash_alg) {
+                if (memcmp(&digest_values->digests[i].digest,
+                           &authPolicy->buffer[0],
+                           authPolicy->size))
+                    continue;
+                *equal = true;
+                return TSS2_RC_SUCCESS;
+            }
+        }
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Search a policy file which fulfills a certain predicate.
+ */
+static TSS2_RC
+search_policy(
+    FAPI_CONTEXT *context,
+    Policy_Compare_Object compare,
+    bool all_objects,
+    void *object1,
+    void *object2,
+    struct POLICY_LIST **policy_found)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    char *path;
+    TPMS_POLICY_HARNESS policy = {0};
+    bool found;
+    struct POLICY_LIST *policy_object;
+    struct POLICY_LIST *second;
+
+    switch (context->fsearch.state) {
+    case FSEARCH_INIT:
+        LOG_DEBUG("** STATE ** FSEARCH_INIT");
+        memset(&context->fsearch, 0, sizeof(IFAPI_FILE_SEARCH_CTX));
+        r = ifapi_keystore_list_all(&context->keystore, IFAPI_POLICY_DIR, &context->fsearch.pathlist,
+                                    &context->fsearch.numPaths);
+        return_if_error(r, "get entities.");
+        context->fsearch.path_idx = context->fsearch.numPaths;
+
+        context->fsearch.state = FSEARCH_OBJECT;
+    /* FALLTHRU */
+
+    case FSEARCH_OBJECT:
+        LOG_DEBUG("** STATE ** FSEARCH_OBJECT");
+        if (context->fsearch.path_idx == 0) {
+            if (*policy_found) {
+                context->fsearch.state = FSEARCH_INIT;
+                for (size_t i = 0; i < context->fsearch.numPaths; i++) {
+                    SAFE_FREE(context->fsearch.pathlist[i]);
+                }
+                SAFE_FREE(context->fsearch.pathlist);
+                return TSS2_RC_SUCCESS;
+            }
+            goto_error(r, TSS2_FAPI_RC_POLICY_UNKNOWN, "Policy not found.", cleanup);
+        }
+        context->fsearch.path_idx -= 1;
+        context->fsearch.path_idx = context->fsearch.path_idx;
+        path =  context->fsearch.pathlist[context->fsearch.path_idx];
+        context->fsearch.current_path = path;
+        LOG_DEBUG("Check file: %s %zu", path, context->fsearch.path_idx);
+
+        r = ifapi_policy_store_load_async(&context->pstore, &context->io, path);
+        goto_if_error2(r, "Can't open: %s", cleanup, path);
+
+        context->fsearch.state = FSEARCH_READ;
+    /* FALLTHRU */
+
+    case FSEARCH_READ:
+        LOG_DEBUG("** STATE ** FSEARCH_READ");
+        r = ifapi_policy_store_load_finish(&context->pstore, &context->io, &policy);
+        return_try_again(r);
+        goto_if_error(r, "read_finish failed", cleanup);
+
+        r = compare(&policy, object1, object2, &found);
+        if (found) {
+            LOG_DEBUG("compare true  %s",
+                      context->fsearch.pathlist[context->fsearch.path_idx]);
+        } else {
+            LOG_DEBUG("compare false  %s",
+                      context->fsearch.pathlist[context->fsearch.path_idx]);
+        }
+        goto_if_error(r, "Invalid cipher object.", cleanup);
+
+        if (!found) {
+            if (!all_objects && context->fsearch.path_idx == 0) {
+                context->fsearch.state = FSEARCH_INIT;
+                ifapi_cleanup_policy_harness(&policy);
+                return TSS2_BASE_RC_POLICY_UNKNOWN;
+            } else {
+                context->fsearch.state = FSEARCH_OBJECT;
+                ifapi_cleanup_policy_harness(&policy);
+                return TSS2_FAPI_RC_TRY_AGAIN;
+            }
+        }
+        policy_object = calloc(sizeof(struct POLICY_LIST), 1);
+        return_if_null(policy_object, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+        policy_object->path = context->fsearch.current_path;
+        policy_object->policy = policy;
+        if (*policy_found != NULL) {
+            second = *policy_found;
+            policy_object->next = second;
+        }
+        *policy_found = policy_object;
+
+        if (context->fsearch.path_idx == 0) {
+            context->fsearch.state = FSEARCH_INIT;
+            for (size_t i = 0; i < context->fsearch.numPaths; i++) {
+                SAFE_FREE(context->fsearch.pathlist[i]);
+            }
+            SAFE_FREE(context->fsearch.pathlist);
+            return TSS2_RC_SUCCESS;
+        }
+
+        if (all_objects) {
+            context->fsearch.state = FSEARCH_OBJECT;
+            return TSS2_FAPI_RC_TRY_AGAIN;
+        }
+
+        break;
+
+    default:
+        context->state = _FAPI_STATE_INTERNALERROR;
+        goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Invalid state for load key.", cleanup);
+    }
+    context->fsearch.state = FSEARCH_INIT;
+    for (size_t i = 0; i < context->fsearch.numPaths; i++) {
+        SAFE_FREE(context->fsearch.pathlist[i]);
+    }
+    SAFE_FREE(context->fsearch.pathlist);
+    return TSS2_RC_SUCCESS;
+cleanup:
+    ifapi_cleanup_policy_harness(&policy);
+    for (size_t i = 0; i < context->fsearch.numPaths; i++) {
+        SAFE_FREE(context->fsearch.pathlist[i]);
+    }
+    SAFE_FREE(context->fsearch.pathlist);
+    context->fsearch.state = FSEARCH_INIT;
+    return r;
+}
+
+/** Get policy digeset  for a certain hash alg.
+ */
+static TSS2_RC
+get_policy_digest(TPMS_POLICY_HARNESS *harness,
+                  TPMI_ALG_HASH hashAlg,
+                  TPM2B_DIGEST *digest)
+{
+    size_t i;
+
+    if (!(digest->size = ifapi_hash_get_digest_size(hashAlg))) {
+        return_error2(TSS2_ESYS_RC_NOT_IMPLEMENTED,
+                      "Unsupported hash algorithm (%" PRIu16 ")", hashAlg);
+    }
+
+    for (i = 0; i < harness->policyDigests.count; i++) {
+        if (harness->policyDigests.digests[i].hashAlg == hashAlg) {
+            memcpy(&digest->buffer[0],
+                   &harness->policyDigests.digests[i].digest, digest->size);
+            return TSS2_RC_SUCCESS;
+        }
+    }
+    return TSS2_FAPI_RC_GENERAL_FAILURE;
+}
+
+/** Get policy authorization for a certain public key
+ */
+static TSS2_RC
+get_policy_signature(
+    TPMS_POLICY_HARNESS *harness,
+    TPMT_PUBLIC *public,
+    TPMT_SIGNATURE *signature)
+{
+    size_t i;
+
+    for (i = 0; i < harness->policyAuthorizations->count; i++) {
+        if (ifapi_TPMT_PUBLIC_cmp(public,
+                                  &harness->policyAuthorizations->authorizations[i].key)) {
+            *signature = harness->policyAuthorizations->authorizations[i].signature;
+            return TSS2_RC_SUCCESS;
+        }
+    }
+    /* Appropriate authorization should always exist */
+    return TSS2_FAPI_RC_GENERAL_FAILURE;
+}
+
+static void cleanup_policy_list(struct POLICY_LIST * list) {
+    if (list) {
+        struct POLICY_LIST * branch = list;
+        while (branch) {
+            struct POLICY_LIST *next = branch->next;
+            ifapi_cleanup_policy_harness(&branch->policy);
+            SAFE_FREE(branch);
+            branch = next;
+        }
+    }
+}
+
+/** Callback for retrieving, selecting and execute a authorized policy.
+ *
+ * All policies authorized by a certain key will be retrieved and one policy
+ * will be selected via a branch selection callback.
+ *
+ * @parm[in] key_public the public data of the key which was used for policy
+ *           authorization.
+ * @parm[in] hash_alg The hash algorithm used for policy computation.
+ * @parm[out] digest The policy digest of the authorized policy.
+ * @parm[out] signature The signature produced during policy authorization.
+ * @parm[in] userdata The user context to retrieve the policy.
+ * @retval TSS2_RC_SUCCESS on success.
+ * @retval TSS2_ESYS_RC_MEMORY: if it's not possible to allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE If no user data id passed or context stack
+ *         is not initialized.
+ * @retval TSS2_FAPI_RC_IO_ERROR If an error occurs during access to the policy
+ *         store.
+ * @retval TSS2_FAPI_RC_PATH_NOT_FOUND If a policy for a certain path was not found.
+ * @retval TSS2_FAPI_RC_POLICY_UNKNOWN If policy search for a certain policy diges was
+           not successful.
+ * @retval TPM2_RC_BAD_AUTH If the authentication for an object needed for policy
+ *         execution fails.
+ */
+TSS2_RC
+ifapi_exec_auth_policy(
+    TPMT_PUBLIC *key_public,
+    TPMI_ALG_HASH hash_alg,
+    TPM2B_DIGEST *digest,
+    TPMT_SIGNATURE *signature,
+    void *userdata)
+{
+    TSS2_RC r;
+    FAPI_CONTEXT *fapi_ctx = userdata;
+    IFAPI_POLICY_EXEC_CTX *current_policy;
+    IFAPI_POLICY_EXEC_CB_CTX *cb_ctx;
+    size_t n, i;
+    struct POLICY_LIST *branch;
+    const char **names = NULL;
+    size_t branch_idx;
+    bool harness_set = false;
+
+    return_if_null(fapi_ctx, "Bad user data.", TSS2_FAPI_RC_BAD_REFERENCE);
+    return_if_null(fapi_ctx->policy.policyutil_stack, "Policy not initialized.",
+                   TSS2_FAPI_RC_BAD_REFERENCE);
+
+    if (fapi_ctx->policy.util_current_policy) {
+        /* Use the current policy in the policy stack. */
+        current_policy = fapi_ctx->policy.util_current_policy->pol_exec_ctx;
+    } else {
+        /* Start with the bottom of the policy stack */
+        current_policy = fapi_ctx->policy.policyutil_stack->pol_exec_ctx;
+    }
+    cb_ctx = current_policy->app_data;
+
+    switch(cb_ctx->cb_state) {
+        statecase(cb_ctx->cb_state, POL_CB_EXECUTE_INIT)
+            current_policy->object_handle = ESYS_TR_NONE;
+            current_policy->policy_list = NULL;
+            fallthrough;
+
+        statecase(cb_ctx->cb_state, POL_CB_SEARCH_POLICY)
+            r = search_policy(fapi_ctx,
+                              equal_policy_authorization, true,
+                              key_public, NULL,
+                              &current_policy->policy_list);
+            FAPI_SYNC(r, "Search policy", cleanup);
+
+            if (current_policy->policy_list->next) {
+                /* More than one policy policy has to be selected via
+                   callback */
+                if (!fapi_ctx->callbacks.branch) {
+                    return_error(TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN,
+                                 "No branch selection callback");
+                }
+                n = 1;
+
+                /* Count policies */
+                for (branch = current_policy->policy_list; branch->next;
+                     branch = branch->next)
+                    n += 1;
+                names = malloc(sizeof(char *) * n);
+                return_if_null(names, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+                i = 0;
+                branch = current_policy->policy_list;
+                /* Compute name list for slectiion callback. */
+                do {
+                    names[i] = branch->policy.description;
+                    i += 1;
+                    branch = branch->next;
+                } while (branch);
+
+                /* Policy selection */
+                r = fapi_ctx->callbacks.branch(fapi_ctx, "PolicyAuthorize",
+                                               &names[0], n, &branch_idx,
+                                               fapi_ctx->callbacks.branchData);
+                return_if_error(r, "policyBranchSelectionCallback");
+
+                if (branch_idx > n) {
+                    goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Invalid branch number.",
+                               cleanup);
+                }
+                /* Get harness from policy list */
+                n = 1;
+                branch = current_policy->policy_list;
+                do {
+                    if (n == branch_idx) {
+                        cb_ctx->harness = &branch->policy;
+                        harness_set = true;
+                        break;
+                    }
+                    n += 1;
+                    branch = branch->next;
+                }  while (branch);
+
+            } else {
+                /* Only one policy found. */
+                cb_ctx->harness = &current_policy->policy_list->policy;
+                harness_set = true;
+            }
+            if (!harness_set) {
+                goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Policy could not be set.",
+                           cleanup);
+            }
+            /* Prepare policy execution */
+            r = ifapi_policyutil_execute_prepare(fapi_ctx, current_policy->hash_alg,
+                                                 cb_ctx->harness);
+            /* Next state will switch from prev context to next context. */
+            return_if_error(r, "Prepare policy execution.");
+            fallthrough;
+
+        statecase(cb_ctx->cb_state, POL_CB_EXECUTE_SUB_POLICY)
+            ESYS_TR session = current_policy->session;
+            r = ifapi_policyutil_execute(fapi_ctx, &session);
+            if (r == TSS2_FAPI_RC_TRY_AGAIN){
+                return r;
+            }
+
+            goto_if_error(r, "Execute policy.", cleanup);
+
+            r = get_policy_signature(cb_ctx->harness, key_public,
+                                     signature);
+            goto_if_error(r, "Get authorization", cleanup);
+
+            r = get_policy_digest(cb_ctx->harness, hash_alg, digest);
+            goto_if_error(r, "Get authorization", cleanup);
+            cb_ctx->cb_state = POL_CB_EXECUTE_INIT;
+            break;
+
+        statecasedefault_error(cb_ctx->state, r, cleanup);
+    }
+ cleanup:
+    SAFE_FREE(names);
+    cleanup_policy_list(current_policy->policy_list);
+    return r;
+}
+
+/** Callback for executing a policy identified by a digest stored in a nv object.
+ *
+ * @parm[in] nv_public the public data of the nv object which stores the diges
+ *           of the authorized policy.
+ * @parm[in] hash_alg The hash algorithm used for policy computation.
+ * @parm[out] The policy digest read from nv ram.
+ * @parm[in] userdata The user context to retrieve the policy.
+ * @retval TSS2_RC_SUCCESS on success.
+ * @retval TSS2_ESYS_RC_MEMORY: if it's not possible to allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE If no user data id passed or context stack
+ *         is not initialized.
+ * @retval TSS2_FAPI_RC_IO_ERROR If an error occurs during access to the policy
+ *         store.
+ * @retval TSS2_FAPI_RC_PATH_NOT_FOUND If a policy for a certain path was not found.
+ * @retval TSS2_FAPI_RC_POLICY_UNKNOWN If policy search for a certain policy diges was
+           not successful.
+ * @retval TPM2_RC_BAD_AUTH If the authentication for an object needed for policy
+ *         execution fails.
+ */
+TSS2_RC
+ifapi_exec_auth_nv_policy(
+    TPM2B_NV_PUBLIC *nv_public,
+    TPMI_ALG_HASH hash_alg,
+    void *userdata)
+{
+    TSS2_RC r;
+    TPM2B_MAX_NV_BUFFER *aux_data;
+    FAPI_CONTEXT *fapi_ctx = userdata;
+    IFAPI_POLICY_EXEC_CTX *current_policy;
+    IFAPI_POLICY_EXEC_CB_CTX *cb_ctx;
+    char *nv_path = NULL;
+    ESYS_CONTEXT *esys_ctx;
+    size_t digest_size, offset;
+    TPMT_HA nv_policy;
+
+    return_if_null(fapi_ctx, "Bad user data.", TSS2_FAPI_RC_BAD_REFERENCE);
+    return_if_null(fapi_ctx->policy.policyutil_stack, "Policy not initialized.",
+                   TSS2_FAPI_RC_BAD_REFERENCE);
+
+    if (fapi_ctx->policy.util_current_policy) {
+        /* Use the current policy in the policy stack. */
+        current_policy = fapi_ctx->policy.util_current_policy->pol_exec_ctx;
+    } else {
+        /* Start with the bottom of the policy stack */
+        current_policy = fapi_ctx->policy.policyutil_stack->pol_exec_ctx;
+    }
+    cb_ctx = current_policy->app_data;
+    esys_ctx = fapi_ctx->esys;
+
+    if (!(digest_size = ifapi_hash_get_digest_size(hash_alg))) {
+        return_error2(TSS2_ESYS_RC_NOT_IMPLEMENTED,
+                      "Unsupported hash algorithm (%" PRIu16 ")", hash_alg);
+    }
+
+    switch(cb_ctx->cb_state) {
+        statecase(cb_ctx->cb_state, POL_CB_EXECUTE_INIT)
+            r = ifapi_keystore_search_nv_obj(&fapi_ctx->keystore, &fapi_ctx->io,
+                                             nv_public, &nv_path);
+            FAPI_SYNC(r, "Search Object", cleanup);
+
+            r = ifapi_keystore_load_async(&fapi_ctx->keystore, &fapi_ctx->io, nv_path);
+            SAFE_FREE(nv_path);
+            return_if_error2(r, "Could not open: %s", nv_path);
+
+            fallthrough;
+
+        statecase(cb_ctx->cb_state, POL_CB_NV_READ)
+            /* Get object from file */
+            r = ifapi_keystore_load_finish(&fapi_ctx->keystore, &fapi_ctx->io,
+                                           &cb_ctx->object);
+            return_try_again(r);
+            return_if_error(r, "read_finish failed");
+
+            r = ifapi_initialize_object(esys_ctx, &cb_ctx->object);
+            goto_if_error(r, "Initialize NV object", cleanup);
+
+            current_policy->nv_index = cb_ctx->object.handle;
+            ifapi_cleanup_ifapi_object(&cb_ctx->object);
+            get_nv_auth_object(&cb_ctx->object,
+                               current_policy->nv_index,
+                               &current_policy->auth_object,
+                               &current_policy->auth_handle);
+            fallthrough;
+
+        statecase(cb_ctx->cb_state, POL_CB_AUTHORIZE_OBJECT)
+            r = ifapi_authorize_object(fapi_ctx, &cb_ctx->auth_object, &cb_ctx->session);
+            return_try_again(r);
+            goto_if_error(r, "Authorize  object.", cleanup);
+
+            r = Esys_NV_Read_Async(esys_ctx,
+                            current_policy->auth_handle, current_policy->nv_index,
+                            cb_ctx->session, ESYS_TR_NONE, ESYS_TR_NONE,
+                            sizeof(TPMI_ALG_HASH) + digest_size, 0);
+            goto_if_error(r, "Unmarshal policy", cleanup);
+            fallthrough;
+
+        statecase(cb_ctx->cb_state, POL_CB_READ_NV_POLICY)
+            r = Esys_NV_Read_Finish(esys_ctx, &aux_data);
+            try_again_or_error_goto(r, "NV read", cleanup);
+
+            offset = 0;
+            r = Tss2_MU_TPMT_HA_Unmarshal(&aux_data->buffer[0], aux_data->size,
+                                          &offset, &nv_policy);
+            Esys_Free(aux_data);
+            goto_if_error(r, "Unmarshal policy", cleanup);
+
+            cb_ctx->policy_digest.size = digest_size;
+            memcpy(&cb_ctx->policy_digest.buffer[0], &nv_policy.digest, digest_size);
+            fallthrough;
+
+        statecase(cb_ctx->cb_state, POL_CB_SEARCH_POLICY)
+            /* Search policy appropriate in object store */
+            r = search_policy(fapi_ctx, compare_policy_digest, false,
+                              &cb_ctx->policy_digest, &hash_alg,
+                              &current_policy->policy_list);
+            FAPI_SYNC(r, "Search policy", cleanup);
+
+            if (!current_policy->policy_list) {
+                goto_error(r, TSS2_FAPI_RC_POLICY_UNKNOWN, "Policy not found", cleanup);
+            }
+            /* Prepare policy execution */
+            r = ifapi_policyutil_execute_prepare(fapi_ctx, current_policy->hash_alg,
+                                                 &current_policy->policy_list->policy);
+            return_if_error(r, "Prepare policy execution.");
+            fallthrough;
+
+        statecase(cb_ctx->cb_state, POL_CB_EXECUTE_SUB_POLICY)
+            ESYS_TR session = current_policy->session;
+            r = ifapi_policyutil_execute(fapi_ctx, &session);
+            if (r == TSS2_FAPI_RC_TRY_AGAIN)
+                return r;
+
+            goto_if_error(r, "Execute policy.", cleanup);
+            cb_ctx->cb_state = POL_CB_EXECUTE_INIT;
+            break;
+
+        statecasedefault_error(cb_ctx->state, r, cleanup);
+    }
+ cleanup:
+    if (current_policy->policy_list) {
+        ifapi_cleanup_policy_harness(&current_policy->policy_list->policy);
+        SAFE_FREE(current_policy->policy_list);
+    }
+    SAFE_FREE(nv_path);
+    return r;
+
+}
+
+/** Callback for getting the name of a key to be duplicated.
+ *
+ * @parm[out] name the name of the object to be duplicated.
+ * @parm[in] userdata The user context to retrieve the key.
+ * @retval TSS2_RC_SUCCESS on success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE: if the context is not passed or the
+ *         object to be duplicated is not set.
+ */
+TSS2_RC
+ifapi_get_duplicate_name(
+    TPM2B_NAME *name,
+    void *userdata)
+{
+    FAPI_CONTEXT *fapi_ctx = userdata;
+
+    return_if_null(fapi_ctx, "Bad user data.", TSS2_FAPI_RC_BAD_REFERENCE);
+    return_if_null(fapi_ctx->duplicate_key, "Object for duplication no set.",
+                   TSS2_FAPI_RC_BAD_REFERENCE);
+    *name = fapi_ctx->duplicate_key->misc.key.name;
+    return TSS2_RC_SUCCESS;
+}
diff --git a/src/tss2-fapi/ifapi_policy_callbacks.h b/src/tss2-fapi/ifapi_policy_callbacks.h
new file mode 100644
index 0000000..671cae3
--- /dev/null
+++ b/src/tss2-fapi/ifapi_policy_callbacks.h
@@ -0,0 +1,114 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ *******************************************************************************/
+#ifndef FAPI_POLICY_CALLBACKS_H
+#define FAPI_POLICY_CALLBACKS_H
+
+
+/** The states for policy execution callbacks */
+enum IFAPI_STATE_POL_CB_EXCECUTE {
+    POL_CB_EXECUTE_INIT = 0,
+    POL_CB_LOAD_KEY,
+    POL_CB_SEARCH_POLICY,
+    POL_CB_EXECUTE_SUB_POLICY,
+    POL_CB_NV_READ,
+    POL_CB_READ_NV_POLICY,
+    POL_CB_READ_OBJECT,
+    POL_CB_AUTHORIZE_OBJECT
+};
+
+/** The context of the policy execution */
+typedef struct {
+    enum  IFAPI_STATE_POL_CB_EXCECUTE cb_state;
+                                    /**< The execution state of the current policy callback */
+    char*object_path;               /**< The pathname determined by object search */
+    IFAPI_OBJECT object;            /**< Object to be authorized */
+    ESYS_TR key_handle;             /**< Handle of a used key */
+    ESYS_TR nv_index;               /**< Index of nv object storing a policy */
+    ESYS_TR auth_index;             /**< Index of authorization object */
+    IFAPI_OBJECT auth_object;       /**< FAPI auth object needed for authorization */
+    IFAPI_OBJECT *key_object_ptr;
+    IFAPI_OBJECT *auth_object_ptr;
+    IFAPI_NV_Cmds nv_cmd_state;
+    IFAPI_NV_Cmds nv_cmd_state_sav; /**< backup for state of fapi nv commands */
+    TPM2B_DIGEST policy_digest;
+    ESYS_TR session;
+    TPMS_POLICY_HARNESS *harness;
+} IFAPI_POLICY_EXEC_CB_CTX;
+
+TSS2_RC
+ifapi_get_key_public(
+    const char *path,
+    TPMT_PUBLIC *public,
+    void *context);
+
+TSS2_RC
+ifapi_get_object_name(
+    const char *path,
+    TPM2B_NAME *name,
+    void *context);
+
+TSS2_RC
+ifapi_get_nv_public(
+    const char *path,
+    TPM2B_NV_PUBLIC *nv_public,
+    void *context);
+
+TSS2_RC
+ifapi_read_pcr(
+    TPMS_PCR_SELECT *pcr_select,
+    TPML_PCR_SELECTION *pcr_selection,
+    TPML_PCRVALUES **pcr_values,
+    void *ctx);
+
+TSS2_RC
+ifapi_policyeval_cbauth(
+    TPM2B_NAME *name,
+    ESYS_TR *object_handle,
+    ESYS_TR *auth_handle,
+    ESYS_TR *authSession,
+    void *userdata);
+
+TSS2_RC
+ifapi_branch_selection(
+    TPML_POLICYBRANCHES *branches,
+    size_t *branch_idx,
+    void *userdata);
+
+TSS2_RC
+ifapi_sign_buffer(
+    char *key_pem,
+    TPMI_ALG_HASH key_pem_hash_alg,
+    uint8_t *buffer,
+    size_t buffer_size,
+    uint8_t **signature,
+    size_t *signature_size,
+    void *userdata);
+
+TSS2_RC
+ifapi_exec_auth_policy(
+    TPMT_PUBLIC *key_public,
+    TPMI_ALG_HASH hash_alg,
+    TPM2B_DIGEST *digest,
+    TPMT_SIGNATURE *signature,
+    void *userdata);
+
+TSS2_RC
+ifapi_exec_auth_nv_policy(
+    TPM2B_NV_PUBLIC *nv_public,
+    TPMI_ALG_HASH hash_alg,
+    void *userdata);
+
+TSS2_RC
+ifapi_get_duplicate_name(
+    TPM2B_NAME *name,
+    void *userdata);
+
+TSS2_RC
+ifapi_policy_action(
+    const char *action,
+    void *userdata);
+
+#endif /* FAPI_POLICY_CALLBACKS_H */
diff --git a/src/tss2-fapi/ifapi_policy_execute.c b/src/tss2-fapi/ifapi_policy_execute.c
new file mode 100644
index 0000000..6ff54be
--- /dev/null
+++ b/src/tss2-fapi/ifapi_policy_execute.c
@@ -0,0 +1,1195 @@
+/* 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 <string.h>
+#include <stdlib.h>
+
+#include "tss2_mu.h"
+#include "fapi_util.h"
+#include "fapi_crypto.h"
+//#include "fapi_policy.h"
+#include "ifapi_policy_execute.h"
+#include "ifapi_helpers.h"
+#include "ifapi_json_deserialize.h"
+#include "tpm_json_deserialize.h"
+#include "ifapi_policy_callbacks.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+TSS2_RC
+compute_or_digest_list(
+    TPML_POLICYBRANCHES *branches,
+    TPMI_ALG_HASH current_hash_alg,
+    TPML_DIGEST *digest_list,
+    const char *names[8])
+{
+    size_t i;
+    size_t digest_idx, hash_size;
+    bool digest_found = false;
+
+    if (!(hash_size = ifapi_hash_get_digest_size(current_hash_alg))) {
+        return_error2(TSS2_ESYS_RC_NOT_IMPLEMENTED,
+                      "Unsupported hash algorithm (%" PRIu16 ")",
+                              current_hash_alg);
+    }
+    /* Determine digest values with appropriate hash alg */
+    TPML_DIGEST_VALUES *branch_digests = &branches->authorizations[0].policyDigests;
+    for (i = 0; i < branch_digests->count; i++) {
+        if (branch_digests->digests[i].hashAlg == current_hash_alg) {
+            digest_idx = i;
+            digest_found = true;
+            break;
+        }
+    }
+    if (!digest_found) {
+         return_error(TSS2_FAPI_RC_BAD_VALUE, "No digest found for hash alg");
+    }
+
+    digest_list->count = branches->count;
+    for (i = 0; i < branches->count; i++) {
+        if (i > 7) {
+            return_error(TSS2_FAPI_RC_BAD_VALUE, "Too much or branches.");
+        }
+        names[i] = branches->authorizations[i].name;
+        digest_list->digests[i].size = hash_size;
+        memcpy(&digest_list->digests[i].buffer[0],
+               &branches->authorizations[i].policyDigests.
+               digests[digest_idx].digest, hash_size);
+        LOGBLOB_DEBUG(&digest_list->digests[i].buffer[0],
+                      digest_list->digests[i].size, "Compute digest list");
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+TSS2_RC
+ifapi_extend_authorization(
+    TPMS_POLICY_HARNESS *harness,
+    TPMS_POLICYAUTHORIZATION *authorization)
+{
+    TPML_POLICYAUTHORIZATIONS *save = NULL;
+    size_t n = 0;
+    size_t i;
+
+    if (harness->policyAuthorizations) {
+        /* Extend old authorizations */
+        n = harness->policyAuthorizations->count;
+        save = harness->policyAuthorizations;
+        harness->policyAuthorizations =
+            malloc((n + 1) * sizeof(TPMS_POLICYAUTHORIZATION)
+                   + sizeof(TPML_POLICYAUTHORIZATIONS));
+        return_if_null(harness->policyAuthorizations->authorizations,
+                       "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+        for (i = 0; i < n; i++)
+            harness->policyAuthorizations->authorizations[i] =
+                save->authorizations[i];
+        harness->policyAuthorizations->authorizations[n] = *authorization;
+        harness->policyAuthorizations->count = n + 1;
+        SAFE_FREE(save);
+    } else {
+        /* No old authorizations exits */
+        harness->policyAuthorizations = malloc(sizeof(TPMS_POLICYAUTHORIZATION)
+                                               + sizeof(TPML_POLICYAUTHORIZATIONS));
+        return_if_null(harness->policyAuthorizations->authorizations,
+                       "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+        harness->policyAuthorizations->count = 1;
+        harness->policyAuthorizations->authorizations[0] = *authorization;
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+TSS2_RC
+get_policy_digest_idx(TPML_DIGEST_VALUES *digest_values, TPMI_ALG_HASH hashAlg,
+                      size_t *idx)
+{
+    size_t i;
+    for (i = 0; i < digest_values->count; i++) {
+        if (digest_values->digests[i].hashAlg == hashAlg) {
+            *idx = i;
+            return TSS2_RC_SUCCESS;
+        }
+    }
+
+    if (i >= TPM2_NUM_PCR_BANKS) {
+        return_error(TSS2_FAPI_RC_BAD_VALUE, "Table overflow");
+    }
+    digest_values->digests[i].hashAlg = hashAlg;
+    memset(&digest_values->digests[i].digest, 0, sizeof(TPMU_HA));
+    *idx = i;
+    digest_values->count += 1;
+    return TSS2_RC_SUCCESS;
+}
+
+static TSS2_RC
+execute_policy_pcr(
+    ESYS_CONTEXT *esys_ctx,
+    TPMS_POLICYPCR *policy,
+    TPMI_ALG_HASH current_hash_alg,
+    IFAPI_POLICY_EXEC_CTX *current_policy)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    TPML_PCR_SELECTION pcr_selection;
+    TPM2B_DIGEST pcr_digest;
+
+    LOG_TRACE("call");
+
+    switch (current_policy->state) {
+    statecase(current_policy->state, POLICY_EXECUTE_INIT)
+        /* Compute PCR selection and pcr digest */
+        r = ifapi_compute_policy_digest(policy->pcrs, &pcr_selection,
+                                        current_hash_alg, &pcr_digest);
+        return_if_error(r, "Compute policy digest and selection.");
+
+        LOGBLOB_DEBUG(&pcr_digest.buffer[0], pcr_digest.size, "PCR Digest");
+        r = Esys_PolicyPCR_Async(esys_ctx,
+                                 current_policy->session,
+                                 ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
+                                 &pcr_digest, &pcr_selection);
+        return_if_error(r, "Execute PolicyPCR.");
+        fallthrough;
+
+    statecase(current_policy->state, POLICY_EXECUTE_FINISH)
+        r = Esys_PolicyPCR_Finish(esys_ctx);
+        try_again_or_error(r, "Execute PolicyPCR_Finish.");
+
+        current_policy->state = POLICY_EXECUTE_INIT;
+        return r;
+
+    statecasedefault(current_policy->state);
+    }
+    return r;
+}
+
+static TSS2_RC
+execute_policy_duplicate(
+    ESYS_CONTEXT *esys_ctx,
+    TPMS_POLICYDUPLICATIONSELECT *policy,
+    IFAPI_POLICY_EXEC_CTX *current_policy)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+
+    LOG_TRACE("call");
+
+    switch (current_policy->state) {
+    statecase(current_policy->state, POLICY_EXECUTE_INIT)
+        ifapi_policyeval_EXEC_CB *cb = &current_policy->callbacks;
+        r = cb->cbdup(&policy->objectName, cb->cbdup_userdata);
+        return_if_error(r, "Get name for policy duplicate select.");
+
+        r = Esys_PolicyDuplicationSelect_Async(esys_ctx,
+                                               current_policy->session,
+                                               ESYS_TR_NONE, ESYS_TR_NONE,
+                                               ESYS_TR_NONE,
+                                               &policy->objectName,
+                                               &policy->newParentName,
+                                               policy->includeObject);
+        return_if_error(r, "Execute PolicyDuplicatonSelect_Async.");
+        fallthrough;
+
+    statecase(current_policy->state, POLICY_EXECUTE_FINISH)
+        r = Esys_PolicyDuplicationSelect_Finish(esys_ctx);
+        try_again_or_error(r, "Execute PolicyDuplicationselect_Finish.");
+
+        current_policy->state = POLICY_EXECUTE_INIT;
+        return r;
+
+    statecasedefault(current_policy->state);
+    }
+    return r;
+}
+
+static TSS2_RC
+execute_policy_nv(
+    ESYS_CONTEXT *esys_ctx,
+    TPMS_POLICYNV *policy,
+    IFAPI_POLICY_EXEC_CTX *current_policy)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+
+    LOG_TRACE("call");
+
+    switch (current_policy->state) {
+    statecase(current_policy->state, POLICY_EXECUTE_INIT)
+        r = ifapi_nv_get_name(&policy->nvPublic, &current_policy->name);
+        return_if_error(r, "Compute NV name");
+        fallthrough;
+
+    statecase(current_policy->state, POLICY_AUTH_CALLBACK)
+        ifapi_policyeval_EXEC_CB *cb = &current_policy->callbacks;
+        r = cb->cbauth(&current_policy->name,
+                       &current_policy->object_handle,
+                       &current_policy->auth_handle,
+                       &current_policy->auth_session, cb->cbauth_userdata);
+        return_try_again(r);
+        return_if_error(r, "Execute authorized policy.");
+
+        r = Esys_PolicyNV_Async(esys_ctx,
+                                current_policy->object_handle,
+                                current_policy->auth_handle,
+                                current_policy->session,
+                                current_policy->auth_session, ESYS_TR_NONE, ESYS_TR_NONE,
+                                &policy->operandB, policy->offset,
+                                policy->operation);
+        return_if_error(r, "Execute PolicyNV_Async.");
+        fallthrough;
+
+    statecase(current_policy->state, POLICY_EXECUTE_FINISH)
+        r = Esys_PolicyNV_Finish(esys_ctx);
+        try_again_or_error(r, "Execute PolicyNV_Finish.");
+
+        current_policy->state = POLICY_EXECUTE_INIT;
+        return r;
+
+    statecasedefault(current_policy->state);
+    }
+    return r;
+}
+
+TSS2_RC
+execute_policy_signed(
+    ESYS_CONTEXT *esys_ctx,
+    TPMS_POLICYSIGNED *policy,
+    IFAPI_POLICY_EXEC_CTX *current_policy)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    size_t offset = 0;
+    //TPMT_SIGNATURE signature_tpm;
+    size_t signature_size;
+    uint8_t *signature_ossl = NULL;
+
+    LOG_TRACE("call");
+
+    switch (current_policy->state) {
+    statecase(current_policy->state, POLICY_EXECUTE_INIT);
+        current_policy->pem_key = NULL;
+        current_policy->object_handle = ESYS_TR_NONE;
+        current_policy->buffer_size = sizeof(INT32) + sizeof(TPM2B_NONCE)
+            + policy->cpHashA.size + policy->policyRef.size;
+        current_policy->buffer = malloc(current_policy->buffer_size);
+        return_if_null(current_policy->buffer, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+        r = Esys_TRSess_GetNonceTPM(esys_ctx, current_policy->session,
+                                    &current_policy->nonceTPM);
+        return_if_error(r, "Get TPM nonce.");
+
+        /* Concatenate objects needed for the authorization hash */
+        memcpy(&current_policy->buffer[offset], &current_policy->nonceTPM->buffer[0],
+               current_policy->nonceTPM->size);
+        offset += current_policy->nonceTPM->size;
+        memset(&current_policy->buffer[offset], 0, sizeof(INT32));
+        offset += sizeof(INT32);
+        memcpy(&current_policy->buffer[offset], &policy->cpHashA.buffer[0],
+               policy->cpHashA.size);
+        offset += policy->cpHashA.size;
+        memcpy(&current_policy->buffer[offset], &policy->policyRef.buffer[0],
+               policy->policyRef.size);
+        offset += policy->policyRef.size;
+        current_policy->buffer_size = offset;
+        fallthrough;
+
+    statecase(current_policy->state, POLICY_EXECUTE_CALLBACK);
+        ifapi_policyeval_EXEC_CB *cb = &current_policy->callbacks;
+        int pem_key_size;
+        TPM2B_PUBLIC tpm_public;
+
+        /* RECREATE pem key from tpm public key */
+        if (!current_policy->pem_key) {
+            tpm_public.publicArea = policy->keyPublic;
+            tpm_public.size = 0;
+            r = ifapi_pub_pem_key_from_tpm(&tpm_public, &current_policy->pem_key,
+                                       &pem_key_size);
+            return_if_error(r, "Convert TPM public key into PEM key.");
+        }
+
+        r = cb->cbsign(current_policy->pem_key, policy->keyPEMhashAlg, current_policy->buffer,
+                       current_policy->buffer_size,
+                       &signature_ossl, &signature_size,
+                       cb->cbsign_userdata);
+        SAFE_FREE(current_policy->pem_key);
+        SAFE_FREE(current_policy->buffer);
+        try_again_or_error_goto(r, "Execute policy signature callback.", cleanup);
+
+        /* Convert signature into TPM format */
+        r = ifapi_der_sig_to_tpm(&policy->keyPublic, signature_ossl,
+                                 signature_size, policy->keyPEMhashAlg,
+                                 &policy->signature_tpm);
+        goto_if_error2(r, "Convert der signature into TPM format", cleanup);
+
+        SAFE_FREE(signature_ossl);
+
+        TPM2B_PUBLIC inPublic;
+        inPublic.size = 0;
+        inPublic.publicArea = policy->keyPublic;
+
+        r = Esys_LoadExternal_Async(esys_ctx,
+                                    ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
+                                    NULL, &inPublic, TPM2_RH_OWNER);
+        goto_if_error(r, "LoadExternal_Async", cleanup);
+        fallthrough;
+
+    statecase(current_policy->state, POLICY_LOAD_KEY);
+        r = Esys_LoadExternal_Finish(esys_ctx, &current_policy->object_handle);
+        try_again_or_error(r, "Load external key.");
+
+        r = Esys_PolicySigned_Async(esys_ctx,
+                                    current_policy->object_handle,
+                                    current_policy->session,
+                                    ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
+                                    current_policy->nonceTPM,
+                                    &policy->cpHashA,
+                                    &policy->policyRef, 0, &policy->signature_tpm);
+        SAFE_FREE(current_policy->nonceTPM);
+        goto_if_error(r, "Execute PolicySigned.", cleanup);
+        fallthrough;
+
+    statecase(current_policy->state, POLICY_EXECUTE_FINISH);
+        r = Esys_PolicySigned_Finish(esys_ctx, NULL, NULL);
+        try_again_or_error(r, "Execute PolicySigned_Finish.");
+
+        r = Esys_FlushContext_Async(esys_ctx, current_policy->object_handle);
+        goto_if_error(r, "FlushContext_Async", cleanup);
+        fallthrough;
+
+    statecase(current_policy->state, POLICY_FLUSH_KEY);
+        r = Esys_FlushContext_Finish(esys_ctx);
+        try_again_or_error(r, "Flush key finish.");
+
+        current_policy->object_handle = ESYS_TR_NONE;
+        current_policy->state = POLICY_EXECUTE_INIT;
+        return r;
+
+    statecasedefault(current_policy->state);
+    }
+cleanup:
+    SAFE_FREE(current_policy->pem_key);
+    SAFE_FREE(signature_ossl);
+    SAFE_FREE(current_policy->buffer);
+    SAFE_FREE(current_policy->pem_key);
+    /* In error cases object might not have been flushed. */
+    if (current_policy->object_handle != ESYS_TR_NONE)
+        Esys_FlushContext(esys_ctx, current_policy->object_handle);
+    return r;
+}
+
+static TSS2_RC
+execute_policy_authorize(
+    ESYS_CONTEXT *esys_ctx,
+    TPMS_POLICYAUTHORIZE *policy,
+    TPMI_ALG_HASH hash_alg,
+    IFAPI_POLICY_EXEC_CTX *current_policy)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    TPM2B_PUBLIC public2b;
+    TPM2B_DIGEST aHash;
+    IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext;
+    size_t hash_size;
+    size_t size;
+    TPMT_TK_VERIFIED *ticket;
+    TPM2B_NAME *tmp_name = NULL;
+
+    LOG_TRACE("call");
+    public2b.size = 0;
+    if (!(hash_size = ifapi_hash_get_digest_size(hash_alg))) {
+        goto_error(r, TSS2_ESYS_RC_NOT_IMPLEMENTED,
+                   "Unsupported hash algorithm (%" PRIu16 ")", cleanup,
+                   hash_alg);
+    }
+    switch (current_policy->state) {
+    statecase(current_policy->state, POLICY_EXECUTE_INIT);
+        current_policy->object_handle = ESYS_TR_NONE;
+        /* Execute authorized policy. */
+        ifapi_policyeval_EXEC_CB *cb = &current_policy->callbacks;
+        r = cb->cbauthpol(&policy->keyPublic, hash_alg, &policy->approvedPolicy,
+                          &policy->signature, cb->cbauthpol_userdata);
+        return_try_again(r);
+        goto_if_error(r, "Execute authorized policy.", cleanup);
+
+        public2b.size = 0;
+        public2b.publicArea = policy->keyPublic;
+        r = Esys_LoadExternal_Async(esys_ctx,
+                                    ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
+                                    NULL,  &public2b, TPM2_RH_OWNER);
+        goto_if_error(r, "LoadExternal_Async", cleanup);
+        fallthrough;
+
+    statecase(current_policy->state, POLICY_LOAD_KEY);
+        r = Esys_LoadExternal_Finish(esys_ctx, &current_policy->object_handle);
+        try_again_or_error(r, "Load external key.");
+
+        /* Save key name for policy execution */
+        r = Esys_TR_GetName(esys_ctx, current_policy->object_handle, &tmp_name);
+        return_if_error(r, "Get key name.");
+        policy->keyName = *tmp_name;
+        SAFE_FREE(tmp_name);
+
+        /* Use policyRef and policy to compute authorization hash */
+        r = ifapi_crypto_hash_start(&cryptoContext, hash_alg);
+        return_if_error(r, "crypto hash start");
+
+        HASH_UPDATE_BUFFER(cryptoContext, &policy->approvedPolicy.buffer[0],
+                           hash_size, r, cleanup);
+        HASH_UPDATE_BUFFER(cryptoContext, &policy->policyRef.buffer[0],
+                           policy->policyRef.size, r, cleanup);
+        r = ifapi_crypto_hash_finish(&cryptoContext,
+                                     (uint8_t *) &aHash.buffer[0],
+                                     &size);
+        return_if_error(r, "crypto hash finish");
+        aHash.size = size;
+
+        /* Verify the signature retrieved from the authorized policy against
+           the computed ahash. */
+        r = Esys_VerifySignature_Async(esys_ctx, current_policy->object_handle,
+                                       ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
+                                       &aHash,
+                                       &policy->signature);
+        goto_if_error(r, "Verify signature", cleanup);
+        fallthrough;
+
+    statecase(current_policy->state, POLICY_VERIFY);
+        r = Esys_VerifySignature_Finish(esys_ctx, &ticket);
+        try_again_or_error(r, "Load external key.");
+
+        /* Execute policy authorize */
+        policy->checkTicket = *ticket;
+        SAFE_FREE(ticket);
+        r = Esys_PolicyAuthorize_Async(esys_ctx,
+                                       current_policy->session,
+                                       ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
+                                       &policy->approvedPolicy,
+                                       &policy->policyRef,
+                                       &policy->keyName,
+                                       &policy->checkTicket);
+        goto_if_error(r, "Policy Authorize", cleanup);
+        fallthrough;
+
+    statecase(current_policy->state, POLICY_EXECUTE_FINISH);
+        r = Esys_PolicyAuthorize_Finish(esys_ctx);
+        try_again_or_error(r, "Load external key.");
+
+        r = Esys_FlushContext_Async(esys_ctx, current_policy->object_handle);
+        goto_if_error(r, "FlushContext_Async", cleanup);
+        fallthrough;
+
+    statecase(current_policy->state, POLICY_FLUSH_KEY);
+        /* Flush key used for verification. */
+        r = Esys_FlushContext_Finish(esys_ctx);
+        try_again_or_error(r, "Flush key finish.");
+
+        current_policy->object_handle = ESYS_TR_NONE;
+        current_policy->state = POLICY_EXECUTE_INIT;
+        break;
+
+    statecasedefault(current_policy->state);
+    }
+cleanup:
+    /* In error cases object might not have been flushed. */
+    if (current_policy->object_handle != ESYS_TR_NONE)
+        Esys_FlushContext(esys_ctx, current_policy->object_handle);
+
+    return r;
+}
+
+static TSS2_RC
+execute_policy_authorize_nv(
+    ESYS_CONTEXT *esys_ctx,
+    TPMS_POLICYAUTHORIZENV *policy,
+    TPMI_ALG_HASH hash_alg,
+    IFAPI_POLICY_EXEC_CTX *current_policy)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    ifapi_policyeval_EXEC_CB *cb;
+
+    LOG_DEBUG("call");
+    cb = &current_policy->callbacks;
+
+    switch (current_policy->state) {
+    statecase(current_policy->state, POLICY_EXECUTE_INIT)
+        r = cb->cbauthnv(&policy->nvPublic, hash_alg, cb->cbauthpol_userdata);
+        try_again_or_error(r, "Execute policy authorize nv callback.");
+
+        r = ifapi_nv_get_name(&policy->nvPublic, &current_policy->name);
+        return_if_error(r, "Compute NV name");
+        fallthrough;
+
+    statecase(current_policy->state, POLICY_AUTH_CALLBACK)
+        r = cb->cbauth(&current_policy->name,
+                       &current_policy->object_handle,
+                       &current_policy->auth_handle,
+                       &current_policy->auth_session, cb->cbauth_userdata);
+        return_try_again(r);
+        goto_if_error(r, "Execute authorized policy.", cleanup);
+        fallthrough;
+
+    statecase(current_policy->state, POLICY_EXEC_ESYS)
+        LOG_DEBUG("**STATE** POLICY_EXEC_ESYS");
+        r = Esys_PolicyAuthorizeNV_Async(esys_ctx,
+                                         current_policy->auth_handle,
+                                         current_policy->object_handle,
+                                         current_policy->session,
+                                         current_policy->auth_session, ESYS_TR_NONE,
+                                         ESYS_TR_NONE);
+        goto_if_error(r, "PolicyAuthorizeNV_Async", cleanup);
+        fallthrough;
+
+    statecase(current_policy->state, POLICY_AUTH_SENT)
+        r = Esys_PolicyAuthorizeNV_Finish(esys_ctx);
+        return_try_again(r);
+        goto_if_error(r, "FAPI PolicyAuthorizeNV_Finish", cleanup);
+        break;
+
+    statecasedefault(current_policy->state);
+    }
+cleanup:
+    return r;
+}
+
+static TSS2_RC
+execute_policy_secret(
+    ESYS_CONTEXT *esys_ctx,
+    TPMS_POLICYSECRET *policy,
+    TPMI_ALG_HASH hash_alg,
+    IFAPI_POLICY_EXEC_CTX *current_policy)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    (void)hash_alg;
+
+    LOG_DEBUG("call");
+
+    switch (current_policy->state) {
+    statecase(current_policy->state, POLICY_EXECUTE_INIT)
+        ifapi_policyeval_EXEC_CB *cb = &current_policy->callbacks;
+        r = cb->cbauth(&policy->objectName,
+                       &current_policy->object_handle,
+                       &current_policy->auth_handle,
+                   &current_policy->auth_session, cb->cbauth_userdata);
+        return_try_again(r);
+        goto_if_error(r, "Authorize object callback.", cleanup);
+        fallthrough;
+
+    statecase(current_policy->state, POLICY_EXEC_ESYS)
+        r = Esys_TRSess_GetNonceTPM(esys_ctx, current_policy->session,
+                                    &current_policy->nonceTPM);
+        goto_if_error(r, "Get TPM nonce.", cleanup);
+
+        policy->nonceTPM = *(current_policy->nonceTPM);
+        SAFE_FREE(current_policy->nonceTPM);
+
+        r = Esys_PolicySecret_Async(esys_ctx,
+                                    current_policy->auth_handle,
+                                    current_policy->session,
+                                    current_policy->auth_session, ESYS_TR_NONE,
+                                    ESYS_TR_NONE, &policy->nonceTPM,
+                                    &policy->cpHashA, &policy->policyRef,
+                                    0);
+        goto_if_error(r, "PolicySecret_Async", cleanup);
+        fallthrough;
+
+    statecase(current_policy->state, POLICY_AUTH_SENT)
+        r = Esys_PolicySecret_Finish(esys_ctx, NULL,
+                                     NULL);
+        return_try_again(r);
+        goto_if_error(r, "FAPI PolicyAuthorizeNV_Finish", cleanup);
+        break;
+
+    statecasedefault(current_policy->state);
+    }
+
+ cleanup:
+    return r;
+}
+
+static TSS2_RC
+execute_policy_counter_timer(
+    ESYS_CONTEXT *esys_ctx,
+    TPMS_POLICYCOUNTERTIMER *policy,
+    IFAPI_POLICY_EXEC_CTX *current_policy)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+
+    LOG_TRACE("call");
+
+    switch (current_policy->state) {
+    statecase(current_policy->state, POLICY_EXECUTE_INIT)
+        r = Esys_PolicyCounterTimer_Async(esys_ctx,
+                                          current_policy->session,
+                                          ESYS_TR_NONE, ESYS_TR_NONE,
+                                          ESYS_TR_NONE,
+                                          &policy->operandB,
+                                          policy->offset,
+                                          policy->operation);
+        return_if_error(r, "Execute PolicyCounter.");
+        fallthrough;
+
+    statecase(current_policy->state, POLICY_EXECUTE_FINISH)
+        r = Esys_PolicyCounterTimer_Finish(esys_ctx);
+        try_again_or_error(r, "Execute PolicyCounterTImer_Finish.");
+
+        current_policy->state = POLICY_EXECUTE_INIT;
+        return r;
+
+    statecasedefault(current_policy->state);
+    }
+    return r;
+}
+
+static TSS2_RC
+execute_policy_physical_presence(
+    ESYS_CONTEXT *esys_ctx,
+    TPMS_POLICYPHYSICALPRESENCE *policy,
+    IFAPI_POLICY_EXEC_CTX *current_policy)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    (void)policy;
+
+    LOG_TRACE("call");
+
+    switch (current_policy->state) {
+    statecase(current_policy->state, POLICY_EXECUTE_INIT)
+        r = Esys_PolicyPhysicalPresence_Async(esys_ctx,
+                                              current_policy->session,
+                                              ESYS_TR_NONE, ESYS_TR_NONE,
+                                              ESYS_TR_NONE);
+        return_if_error(r, "Execute PolicyPhysicalpresence.");
+        fallthrough;
+
+    statecase(current_policy->state, POLICY_EXECUTE_FINISH)
+        r = Esys_PolicyPhysicalPresence_Finish(esys_ctx);
+        try_again_or_error(r, "Execute PolicyPhysicalPresence_Finish.");
+
+        current_policy->state = POLICY_EXECUTE_INIT;
+        return r;
+
+    statecasedefault(current_policy->state);
+    }
+    return r;
+}
+
+static TSS2_RC
+execute_policy_auth_value(
+    ESYS_CONTEXT *esys_ctx,
+    TPMS_POLICYAUTHVALUE *policy,
+    IFAPI_POLICY_EXEC_CTX *current_policy)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    (void)policy;
+
+    LOG_TRACE("call");
+
+    switch (current_policy->state) {
+    statecase(current_policy->state, POLICY_EXECUTE_INIT)
+        r = Esys_PolicyAuthValue_Async(esys_ctx,
+                                       current_policy->session,
+                                       ESYS_TR_NONE, ESYS_TR_NONE,
+                                       ESYS_TR_NONE);
+        return_if_error(r, "Execute PolicyAuthValue.");
+        fallthrough;
+
+    statecase(current_policy->state, POLICY_EXECUTE_FINISH)
+        r = Esys_PolicyAuthValue_Finish(esys_ctx);
+        try_again_or_error(r, "Execute PolicyAuthValue_Finish.");
+
+        current_policy->state = POLICY_EXECUTE_INIT;
+        return r;
+
+    statecasedefault(current_policy->state);
+    }
+    return r;
+}
+
+static TSS2_RC
+execute_policy_password(
+    ESYS_CONTEXT *esys_ctx,
+    TPMS_POLICYPASSWORD *policy,
+    IFAPI_POLICY_EXEC_CTX *current_policy)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    (void)policy;
+
+    LOG_TRACE("call");
+
+    switch (current_policy->state) {
+    statecase(current_policy->state, POLICY_EXECUTE_INIT)
+        r = Esys_PolicyPassword_Async(esys_ctx,
+                                      current_policy->session,
+                                      ESYS_TR_NONE, ESYS_TR_NONE,
+                                      ESYS_TR_NONE);
+        return_if_error(r, "Execute PolicyPassword.");
+        fallthrough;
+
+    statecase(current_policy->state, POLICY_EXECUTE_FINISH)
+        r = Esys_PolicyPassword_Finish(esys_ctx);
+        try_again_or_error(r, "Execute PolicyPassword_Finish.");
+
+        current_policy->state = POLICY_EXECUTE_INIT;
+        return r;
+
+    statecasedefault(current_policy->state);
+    }
+    return r;
+}
+
+static TSS2_RC
+execute_policy_command_code(
+    ESYS_CONTEXT *esys_ctx,
+    TPMS_POLICYCOMMANDCODE *policy,
+    IFAPI_POLICY_EXEC_CTX *current_policy)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+
+    LOG_TRACE("call");
+
+    switch (current_policy->state) {
+    statecase(current_policy->state, POLICY_EXECUTE_INIT)
+        r = Esys_PolicyCommandCode_Async(esys_ctx,
+                                         current_policy->session,
+                                         ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
+                                         policy->code);
+        return_if_error(r, "Execute PolicyCommandCode.");
+        fallthrough;
+
+    statecase(current_policy->state, POLICY_EXECUTE_FINISH)
+        r = Esys_PolicyCommandCode_Finish(esys_ctx);
+        try_again_or_error(r, "Execute PolicyCommandCode_Finish.");
+
+        current_policy->state = POLICY_EXECUTE_INIT;
+        return r;
+
+    statecasedefault(current_policy->state)
+    }
+    return r;
+}
+
+static TSS2_RC
+execute_policy_name_hash(
+    ESYS_CONTEXT *esys_ctx,
+    TPMS_POLICYNAMEHASH *policy,
+    IFAPI_POLICY_EXEC_CTX *current_policy)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+
+    LOG_TRACE("call");
+
+    switch (current_policy->state) {
+    statecase(current_policy->state, POLICY_EXECUTE_INIT)
+        r = Esys_PolicyNameHash_Async(esys_ctx,
+                                      current_policy->session,
+                                      ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
+                                      &policy->nameHash);
+        return_if_error(r, "Execute PolicyNameH.");
+        fallthrough;
+
+    statecase(current_policy->state, POLICY_EXECUTE_FINISH)
+        r = Esys_PolicyNameHash_Finish(esys_ctx);
+        try_again_or_error(r, "Execute PolicyNameHash_Finish.");
+
+        current_policy->state = POLICY_EXECUTE_INIT;
+        return r;
+
+    statecasedefault(current_policy->state)
+    }
+    return r;
+}
+
+static TSS2_RC
+execute_policy_cp_hash(
+    ESYS_CONTEXT *esys_ctx,
+    TPMS_POLICYCPHASH *policy,
+    IFAPI_POLICY_EXEC_CTX *current_policy)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+
+    LOG_TRACE("call");
+
+    switch (current_policy->state) {
+    statecase(current_policy->state, POLICY_EXECUTE_INIT)
+        r = Esys_PolicyCpHash_Async(esys_ctx,
+                                    current_policy->session,
+                                    ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
+                                    &policy->cpHash);
+        return_if_error(r, "Execute PolicyNameH.");
+
+        fallthrough;
+
+    statecase(current_policy->state, POLICY_EXECUTE_FINISH)
+        r = Esys_PolicyCpHash_Finish(esys_ctx);
+        try_again_or_error(r, "Execute PolicyCpHash_Finish.");
+
+        current_policy->state = POLICY_EXECUTE_INIT;
+        return r;
+
+    statecasedefault(current_policy->state);
+    }
+    return r;
+}
+
+static TSS2_RC
+execute_policy_locality(
+    ESYS_CONTEXT *esys_ctx,
+    TPMS_POLICYLOCALITY *policy,
+    IFAPI_POLICY_EXEC_CTX *current_policy)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+
+    LOG_TRACE("call");
+
+    switch (current_policy->state) {
+    statecase(current_policy->state, POLICY_EXECUTE_INIT)
+        r = Esys_PolicyLocality_Async(esys_ctx,
+                                      current_policy->session,
+                                      ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
+                                      policy->locality);
+        return_if_error(r, "Execute PolicyLocality.");
+        fallthrough;
+
+    statecase(current_policy->state, POLICY_EXECUTE_FINISH)
+        r = Esys_PolicyLocality_Finish(esys_ctx);
+        try_again_or_error(r, "Execute PolicyNV_Finish.");
+
+        current_policy->state = POLICY_EXECUTE_INIT;
+        return r;
+
+    statecasedefault(current_policy->state);
+    }
+    return r;
+}
+
+TSS2_RC
+execute_policy_nv_written(
+    ESYS_CONTEXT *esys_ctx,
+    TPMS_POLICYNVWRITTEN *policy,
+    IFAPI_POLICY_EXEC_CTX *current_policy)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+
+    LOG_TRACE("call");
+
+    switch (current_policy->state) {
+    statecase(current_policy->state, POLICY_EXECUTE_INIT)
+        r = Esys_PolicyNvWritten_Async(esys_ctx,
+                                       current_policy->session,
+                                       ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
+                                       policy->writtenSet);
+        return_if_error(r, "Execute PolicyNvWritten.");
+        fallthrough;
+
+    statecase(current_policy->state, POLICY_EXECUTE_FINISH)
+        r = Esys_PolicyNvWritten_Finish(esys_ctx);
+        try_again_or_error(r, "Execute PolicyNV_Finish.");
+
+        current_policy->state = POLICY_EXECUTE_INIT;
+        return r;
+
+    statecasedefault(current_policy->state);
+    }
+    return r;
+}
+
+static TSS2_RC
+execute_policy_or(
+    ESYS_CONTEXT *esys_ctx,
+    TPMS_POLICYOR *policy,
+    TPMI_ALG_HASH current_hash_alg,
+    IFAPI_POLICY_EXEC_CTX *current_policy)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    const char *names[8];
+
+    LOG_TRACE("call");
+
+    switch(current_policy->state) {
+    statecase(current_policy->state, POLICY_EXECUTE_INIT)
+        r = compute_or_digest_list(policy->branches, current_hash_alg,
+                                      &current_policy->digest_list, names);
+        return_if_error(r, "Compute policy or digest list.");
+
+        r = Esys_PolicyOR_Async(esys_ctx,
+                                current_policy->session,
+                                ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
+                                &current_policy->digest_list);
+        return_if_error(r, "Execute PolicyPCR.");
+        fallthrough;
+    statecase(current_policy->state, POLICY_EXECUTE_FINISH)
+        r = Esys_PolicyOR_Finish(esys_ctx);
+        try_again_or_error(r, "Execute PolicyPCR_Finish.");
+
+        return r;
+
+    statecasedefault(current_policy->state);
+    }
+}
+
+
+TSS2_RC
+execute_policy_action(
+    ESYS_CONTEXT *esys_ctx,
+    TPMS_POLICYACTION *policy,
+    IFAPI_POLICY_EXEC_CTX *current_policy)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    (void)(esys_ctx);
+    LOG_TRACE("call");
+
+    switch (current_policy->state) {
+    statecase(current_policy->state, POLICY_EXECUTE_INIT);
+        ifapi_policyeval_EXEC_CB *cb = &current_policy->callbacks;
+
+        r = cb->cbaction(policy->action, cb->cbaction_userdata);
+        try_again_or_error(r, "Execute policy action callback.");
+        return r;
+
+    statecasedefault(current_policy->state);
+    }
+}
+
+static TSS2_RC
+execute_policy_element(
+    ESYS_CONTEXT *esys_ctx,
+    TPMT_POLICYELEMENT *policy,
+    TPMI_ALG_HASH hash_alg,
+    IFAPI_POLICY_EXEC_CTX *current_policy)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+
+    LOG_TRACE("call");
+
+    switch (policy->type) {
+    case POLICYSECRET:
+        r = execute_policy_secret(esys_ctx,
+                                  &policy->element.PolicySecret,
+                                  hash_alg,
+                                  current_policy);
+        try_again_or_error_goto(r, "Execute policy authorize", error);
+        break;
+    case POLICYPCR:
+        r = execute_policy_pcr(esys_ctx,
+                               &policy->element.PolicyPCR,
+                               hash_alg, current_policy);
+        try_again_or_error_goto(r, "Execute policy pcr", error);
+        break;
+    case POLICYAUTHVALUE:
+        r = execute_policy_auth_value(esys_ctx,
+                                      &policy->element.PolicyAuthValue,
+                                      current_policy);
+        try_again_or_error_goto(r, "Execute policy auth value", error);
+        break;
+    case POLICYOR:
+        r = execute_policy_or(esys_ctx,
+                              &policy->element.PolicyOr,
+                              hash_alg, current_policy);
+        try_again_or_error_goto(r, "Execute policy or", error);
+        break;
+    case POLICYSIGNED:
+        r = execute_policy_signed(esys_ctx,
+                                  &policy->element.PolicySigned,
+                                  current_policy);
+        try_again_or_error_goto(r, "Execute policy signed", error);
+        break;
+    case POLICYAUTHORIZE:
+        r = execute_policy_authorize(esys_ctx,
+                                     &policy->element.PolicyAuthorize,
+                                     hash_alg,
+                                     current_policy);
+        try_again_or_error_goto(r, "Execute policy authorize", error);
+        break;
+    case POLICYAUTHORIZENV:
+        r = execute_policy_authorize_nv(esys_ctx,
+                                        &policy->element.PolicyAuthorizeNv,
+                                        hash_alg,
+                                        current_policy);
+        try_again_or_error_goto(r, "Execute policy authorize", error);
+        break;
+    case POLICYNV:
+        r = execute_policy_nv(esys_ctx,
+                              &policy->element.PolicyNV,
+                              current_policy);
+        try_again_or_error_goto(r, "Execute policy nv", error);
+        break;
+    case POLICYDUPLICATIONSELECT:
+        r = execute_policy_duplicate(esys_ctx,
+                                     &policy->element.PolicyDuplicationSelect,
+                                     current_policy);
+        try_again_or_error_goto(r, "Execute policy duplicate", error);
+        break;
+    case POLICYNVWRITTEN:
+        r = execute_policy_nv_written(esys_ctx,
+                                      &policy->element.PolicyNvWritten,
+                                      current_policy);
+        try_again_or_error_goto(r, "Execute policy nv written", error);
+        break;
+    case POLICYLOCALITY:
+        r = execute_policy_locality(esys_ctx,
+                                    &policy->element.PolicyLocality,
+                                    current_policy);
+        try_again_or_error_goto(r, "Execute policy locality", error);
+        break;
+    case POLICYCOMMANDCODE:
+        r = execute_policy_command_code(esys_ctx,
+                                        &policy->element.PolicyCommandCode,
+                                        current_policy);
+        try_again_or_error_goto(r, "Execute policy command code", error);
+        break;
+    case POLICYNAMEHASH:
+        r = execute_policy_name_hash(esys_ctx,
+                                     &policy->element.PolicyNameHash,
+                                     current_policy);
+            try_again_or_error_goto(r, "Execute policy name hash", error);
+            break;
+    case POLICYCPHASH:
+        r = execute_policy_cp_hash(esys_ctx,
+                                   &policy->element.PolicyCpHash,
+                                   current_policy);
+        try_again_or_error_goto(r, "Execute policy cp hash", error);
+        break;
+    case POLICYPHYSICALPRESENCE:
+        r = execute_policy_physical_presence(esys_ctx,
+                                             &policy->element.PolicyPhysicalPresence,
+                                             current_policy);
+        try_again_or_error_goto(r, "Execute policy physical presence", error);
+            break;
+    case POLICYPASSWORD:
+        r = execute_policy_password(esys_ctx,
+                                    &policy->element.PolicyPassword,
+                                    current_policy);
+        try_again_or_error_goto(r, "Execute policy password", error);
+        break;
+    case POLICYCOUNTERTIMER:
+        r = execute_policy_counter_timer(esys_ctx,
+                                         &policy->element.PolicyCounterTimer,
+                                         current_policy);
+        try_again_or_error_goto(r, "Execute policy counter timer", error);
+        break;
+    case POLICYACTION:
+        r = execute_policy_action(esys_ctx,
+                                  &policy->element.PolicyAction,
+                                  current_policy);
+        try_again_or_error_goto(r, "Execute policy action", error);
+        break;
+
+    default:
+        return_error(TSS2_ESYS_RC_NOT_IMPLEMENTED,
+                     "Policy not implemented");
+        }
+    return r;
+error:
+    return r;
+
+    /* All policies executed successfully */
+    return r;
+}
+
+/** Compute execution order for policies based on branch selection.
+ *
+ * To simplifiy asynncronous policy executiion a linked list of the policy structures
+ * needed for execution based on the result of the  branch selection callbacks
+ * is computed.
+ */
+static TSS2_RC
+compute_policy_list(
+    IFAPI_POLICY_EXEC_CTX *pol_ctx,
+    TPML_POLICYELEMENTS *elements)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    TPML_POLICYBRANCHES *branches;
+    TPML_POLICYELEMENTS *or_elements;
+    size_t branch_idx, i;
+
+    for (i = 0; i < elements->count; i++) {
+        if (elements->elements[i].type == POLICYOR) {
+            branches = elements->elements[i].element.PolicyOr.branches;
+            r = pol_ctx->callbacks.cbpolsel(branches, &branch_idx,
+                                            pol_ctx->callbacks.cbpolsel_userdata);
+            return_if_error(r, "Select policy branch.");
+            or_elements = branches->authorizations[branch_idx].policy;
+            r = compute_policy_list(pol_ctx, or_elements);
+            return_if_error(r, "Compute policy digest list for policy or.");
+        }
+        r = append_object_to_list(&elements->elements[i], &pol_ctx->policy_elements);
+        return_if_error(r, "Extend policy list.");
+    }
+    return r;
+}
+
+/** Initialize policy element list to be executed and store harness in context.
+ *
+ * @param[in] pol_ctx Context for execution of a list of policy elements.
+ * @param[in] hash_alg The hash algorithm used for the policy computation.
+ * @param[in,out] harness The policy to be executed. Some policy elements will
+ *                be used to store computed parameters needed for policy
+ *                execution.
+ * @retval TSS2_RC_SUCCESS on success.
+ * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN If the callback for branch selection is
+ *         not defined. This callback will be needed of or policies have to be
+ *         executed.
+ * @retval TSS2_FAPI_RC_BAD_VALUE If the computed branch index deliverd by the
+ *         callback does not identify a branch.
+ */
+TSS2_RC
+ifapi_policyeval_execute_prepare(
+    IFAPI_POLICY_EXEC_CTX *pol_ctx,
+    TPMI_ALG_HASH hash_alg,
+    TPMS_POLICY_HARNESS *harness)
+{
+    TSS2_RC r;
+
+    pol_ctx->harness = harness;
+    pol_ctx->hash_alg = hash_alg;
+    r = compute_policy_list(pol_ctx, harness->policy);
+    return_if_error(r, "Compute list of policy elements to be executed.");
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Execute all policy commands defined by a list of policy elements.
+ *
+ * @retval TSS2_RC_SUCCESS on success.
+ * @retval TSS2_FAPI_RC_MEMORY: if not enough memory can be allocated.
+ * @retval TSS2_FAPI_RC_BAD_VALUE If wrong values are detected during execution.
+ * @retval TSS2_FAPI_RC_IO_ERROR If an error occurs during access to the policy
+ *         store.
+ * @retval TSS2_FAPI_RC_POLICY_UNKNOWN If policy search for a certain policy diges was
+           not successful.
+ * @retval TSS2_FAPI_RC_BAD_TEMPLATE In a invalid policy is loaded during execution.
+ */
+TSS2_RC
+ifapi_policyeval_execute(
+    ESYS_CONTEXT *esys_ctx,
+    IFAPI_POLICY_EXEC_CTX *current_policy)
+
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    NODE_OBJECT_T *current_policy_element;
+
+    LOG_DEBUG("call");
+
+    while (current_policy->policy_elements) {
+        r = execute_policy_element(esys_ctx,
+                                   (TPMT_POLICYELEMENT *)
+                                   current_policy->policy_elements->object,
+                                   current_policy->hash_alg,
+                                   current_policy);
+        return_try_again(r);
+
+        if (r != TSS2_RC_SUCCESS) {
+            Esys_FlushContext(esys_ctx, current_policy->session);
+            current_policy->session = ESYS_TR_NONE;
+            ifapi_free_node_list(current_policy->policy_elements);
+
+        }
+        return_if_error(r, "Execute policy.");
+
+        current_policy_element =  current_policy->policy_elements;
+        current_policy->policy_elements = current_policy->policy_elements->next;
+        SAFE_FREE(current_policy_element);
+    }
+    return r;
+
+}
diff --git a/src/tss2-fapi/ifapi_policy_execute.h b/src/tss2-fapi/ifapi_policy_execute.h
new file mode 100644
index 0000000..103ceff
--- /dev/null
+++ b/src/tss2-fapi/ifapi_policy_execute.h
@@ -0,0 +1,184 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ *******************************************************************************/
+#ifndef FAPI_POLICY_EXECUTE_H
+#define FAPI_POLICY_EXECUTE_H
+
+#include <stdint.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <sys/stat.h>
+#include <json-c/json.h>
+#include <json-c/json_util.h>
+
+#include "tss2_esys.h"
+#include "tss2_fapi.h"
+
+TSS2_RC
+ifapi_extend_authorization(
+    TPMS_POLICY_HARNESS *harness,
+    TPMS_POLICYAUTHORIZATION *authorization);
+
+TSS2_RC
+ifapi_execute_policy_or(
+    FAPI_CONTEXT *context,
+    TPMS_POLICYOR *policy,
+    TPMI_ALG_HASH current_hash_alg,
+    size_t digest_idx,
+    IFAPI_POLICY_EXEC_CTX *current_policy);
+
+TSS2_RC
+ifapi_execute_policy_element(
+    FAPI_CONTEXT *context,
+    TPML_POLICYELEMENTS *policy,
+    TPMI_ALG_HASH hash_alg,
+    IFAPI_POLICY_EXEC_CTX *current_policy);
+
+typedef TSS2_RC(*Policy_Compare_Object)(
+    TPMS_POLICY_HARNESS *policy,
+    void *object1,
+    void *object2,
+    bool *found);
+
+/** List of policies which fulfill a certain predicate.
+ *
+ * The elements are stored in a linked list.
+ */
+struct POLICY_LIST {
+    const char *path;            /**< The path of the policy object */
+    TPMS_POLICY_HARNESS policy;  /**< The policy object */
+    struct POLICY_LIST *next;    /**< Pointer to next element */
+};
+
+/** List of policies which fulfill a certain predicate.
+ *
+ * The elements are stored in a linked list.
+ */
+struct policy_object_node {
+    const char *path;                  /**< The path of the policy object */
+    TPMS_POLICY_HARNESS policy;        /**< The policy object */
+    struct policy_object_node *next;   /**< Pointer to next element */
+};
+
+typedef TSS2_RC (*ifapi_policyexec_cbauth) (
+    TPM2B_NAME *name,
+    ESYS_TR *object_handle,
+    ESYS_TR *auth_handle,
+    ESYS_TR *authSession,
+    void *userdata);
+
+typedef TSS2_RC (*ifapi_policyexec_cbdup) (
+    TPM2B_NAME *name,
+    void *userdata);
+
+typedef TSS2_RC (*ifapi_policyexec_cbpolsel) (
+    TPML_POLICYBRANCHES *branches,
+    size_t *branch_idx,
+    void *userdata);
+
+typedef TSS2_RC (*ifapi_policyexec_cbsign) (
+    char *key_pem,
+    TPMI_ALG_HASH key_pem_hash_alg,
+    uint8_t *buffer,
+    size_t buffer_size,
+    uint8_t **signature,
+    size_t *signature_size,
+    void *userdata);
+
+typedef TSS2_RC (*ifapi_policyexec_cbauthpol) (
+    TPMT_PUBLIC *key_public,
+    TPMI_ALG_HASH hash_alg,
+    TPM2B_DIGEST *digest,
+    TPMT_SIGNATURE *signature,
+    void *userdata);
+
+typedef TSS2_RC (*ifapi_policyexec_cbauthnv) (
+    TPM2B_NV_PUBLIC *nv_public,
+    TPMI_ALG_HASH hash_alg,
+    void *userdata);
+
+typedef TSS2_RC (*ifapi_policyexec_cbaction) (
+    const char *action,
+    void *userdata);
+
+typedef struct {
+    ifapi_policyexec_cbauth               cbauth; /**< Callback to authorize an object
+                                                       retrieved by name in keystore */
+    void                        *cbauth_userdata;
+    ifapi_policyexec_cbpolsel           cbpolsel; /**< Callback for selection of policy
+                                                       branch */
+    void                      *cbpolsel_userdata;
+    ifapi_policyexec_cbsign               cbsign; /**< Callback for policy sign */
+    void                        *cbsign_userdata;
+    ifapi_policyexec_cbauthpol         cbauthpol; /**< Callback for policy authorize */
+    void                     *cbauthpol_userdata;
+    ifapi_policyexec_cbauthnv           cbauthnv; /**< Callback for policy authorize nv */
+    void                      *cbauthnv_userdata;
+    ifapi_policyexec_cbdup                 cbdup; /**< Callback for policy duplication
+                                                       select */
+    void                         *cbdup_userdata;
+    ifapi_policyexec_cbaction           cbaction; /**< Callback for policy action */
+    void                      *cbaction_userdata;
+} ifapi_policyeval_EXEC_CB;
+
+/** The states for policy execution */
+enum IFAPI_STATE_POLICY_EXCECUTE {
+    POLICY_EXECUTE_INIT = 0,
+    POLICY_EXECUTE_FINISH,
+    POLICY_EXECUTE_CALLBACK,
+    POLICY_LOAD_KEY,
+    POLICY_FLUSH_KEY,
+    POLICY_VERIFY,
+    POLICY_AUTH_CALLBACK,
+    POLICY_AUTH_SENT,
+    POLICY_EXEC_ESYS
+};
+
+typedef struct IFAPI_POLICY_CALLBACK_CTX IFAPI_POLICY_CALLBACK_CTX;
+
+/** The context of the policy execution */
+struct IFAPI_POLICY_EXEC_CTX {
+    enum IFAPI_STATE_POLICY_EXCECUTE state;
+                                    /**< The execution state of the current
+                                         policy command */
+    TPML_DIGEST digest_list;        /** The digest list of policy or */
+    IFAPI_POLICY_EXEC_CTX *next;    /**< Pointer to next policy */
+    IFAPI_POLICY_EXEC_CTX *prev;    /**< Pointer to previous policy */
+    ESYS_TR session;                /**< The current policy session */
+    TPMS_POLICY_HARNESS *harness;
+    ESYS_TR policySessionSav;       /**< Backup policy session */
+    ESYS_TR object_handle;
+    ESYS_TR nv_index;
+    ESYS_TR auth_handle;
+    IFAPI_OBJECT auth_object;       /**< Object used for authentication */
+    ESYS_TR auth_session;
+    TPMI_ALG_HASH hash_alg;
+    void  *app_data;                /**< Application data  for policy execution callbacks */
+    NODE_OBJECT_T *policy_elements; /**< The policy elements to be executed */
+    TPM2B_DIGEST *nonceTPM;
+    uint8_t *buffer;
+    size_t buffer_size;
+    TPM2B_NAME name;
+    char *pem_key;                   /**< Pem key recreated during policy execution */
+    struct POLICY_LIST *policy_list;
+                                    /**< List of policies for authorization selection */
+    ifapi_policyeval_EXEC_CB callbacks;
+                                    /**< callbacks used for execution of sub
+                                         policies and actions wich require access
+                                         to the FAPI context. */
+};
+
+TSS2_RC
+ifapi_policyeval_execute_prepare(
+    IFAPI_POLICY_EXEC_CTX *pol_ctx,
+    TPMI_ALG_HASH hash_alg,
+    TPMS_POLICY_HARNESS *harness);
+
+TSS2_RC
+ifapi_policyeval_execute(
+    ESYS_CONTEXT *esys_ctx,
+    IFAPI_POLICY_EXEC_CTX *current_policy);
+
+#endif /* FAPI_POLICY_EXECUTE_H */
diff --git a/src/tss2-fapi/ifapi_policy_instantiate.c b/src/tss2-fapi/ifapi_policy_instantiate.c
new file mode 100644
index 0000000..e899f1c
--- /dev/null
+++ b/src/tss2-fapi/ifapi_policy_instantiate.c
@@ -0,0 +1,354 @@
+/* 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 <string.h>
+#include <stdlib.h>
+
+#include "tss2_mu.h"
+#include "fapi_util.h"
+#include "fapi_crypto.h"
+//#include "fapi_policy.h"
+#include "ifapi_helpers.h"
+#include "ifapi_policy_instantiate.h"
+#include "ifapi_json_deserialize.h"
+#include "tpm_json_deserialize.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+static TSS2_RC
+get_policy_elements(TPML_POLICYELEMENTS *policy, NODE_OBJECT_T **policy_element_list);
+
+/** Compute linked list with a list of policy elements which could be instantiated.
+ */
+static TSS2_RC
+get_policy_elements(TPML_POLICYELEMENTS *policy, NODE_OBJECT_T **policy_element_list)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    size_t i, j;
+
+    for (i = 0; i < policy->count; i++) {
+        if (policy->elements[i].type ==  POLICYOR) {
+            /* Policy with sub policies */
+            TPML_POLICYBRANCHES *branches = policy->elements[i].element.PolicyOr.branches;
+            for (j = 0; j < branches->count; j++) {
+                r = get_policy_elements(branches->authorizations[j].policy,
+                                        policy_element_list);
+                goto_if_error(r, "Get policy elements.", error_cleanup);
+            }
+        } else {
+            r = push_object_to_list(&policy->elements[i], policy_element_list);
+            goto_if_error(r, "Get policy elements.", error_cleanup);
+        }
+    }
+    return r;
+
+ error_cleanup:
+    ifapi_free_node_list(*policy_element_list);
+    return r;
+}
+
+/** Prepare instantiation a policy template.
+ *
+ * Parts of policies which are referenced by object paths will be replaced with
+ * the appropriate values of the referenced objects.
+ *
+ * @parm[in] context The context storing information for re-entry after try again.
+ * @parm[in] policy The policy to be instantiated.
+ * @parm[in] callbacks The needed callback functions with the corresponding user data
+ *           which will be passed to the callback.
+ * @retval TSS2_RC_SUCCESS on success.
+ * @retval FAPI error codes on failure
+ */
+TSS2_RC
+ifapi_policyeval_instantiate_async(
+    IFAPI_POLICY_EVAL_INST_CTX *context, /* For re-entry after try_again for offsets and such */
+    TPMS_POLICY_HARNESS *policy, /* in */
+    ifapi_policyeval_INST_CB *callbacks)
+{
+    TSS2_RC r;
+
+    /* Store callbacks and their parameters in context */
+    context->callbacks = *callbacks;
+
+    /* Compute list of all policy elements which have to be instantiated */
+    if (context->policy_elements) {
+        ifapi_free_object_list(context->policy_elements);
+        context->policy_elements = NULL;
+    }
+    r = get_policy_elements(policy->policy, &context->policy_elements);
+    return r;
+}
+
+static TSS2_RC
+set_pem_key_param(
+    const char *keyPEM,
+    TPMT_PUBLIC *keyPublic,
+    TPM2B_NAME *name,
+    TPMI_ALG_HASH hash_alg)
+{
+    TSS2_RC r;
+    TPM2B_PUBLIC public;
+
+    if (!keyPEM ||  strlen(keyPEM) == 0) {
+        /* No PEM key used. Parmeters are already set in policy. */
+        return TSS2_RC_SUCCESS;
+    }
+
+    /* Use PEM key to compute public information and name */
+    name->size = 0;
+
+    TPM2_ALG_ID rsaOrEcc = ifapi_get_signature_algorithm_from_pem(keyPEM);
+    r = ifapi_initialize_sign_public(rsaOrEcc, &public);
+    return_if_error(r, "Could not initialize public info of key");
+
+    r = ifapi_get_tpm2b_public_from_pem(keyPEM, &public);
+    return_if_error(r, "Invalid PEM key.");
+
+    *keyPublic = public.publicArea;
+    keyPublic->nameAlg = hash_alg;
+    r = ifapi_get_name(&public.publicArea, name);
+    return_if_error(r, "Compute key name.");
+
+    return TSS2_RC_SUCCESS;
+}
+
+
+#define CHECK_TEMPLATE_PATH(path, template) \
+     if (!path) { \
+         return_error2(TSS2_FAPI_RC_BAD_TEMPLATE, "No path for policy %s", template); \
+     }
+
+/** Finalize  instantiation a policy template.
+ *
+ * All needed asyncroous callbacks will be executed for all policy elements offset
+ * The policy.
+ *
+ * @parm[in] context The context storing information for re-entry after try again.
+ * @retval TSS2_RC_SUCCESS on success.
+ * @retval TSS2_FAPI_RC_BAD_TEMPLATE If the templayte is not complete for instantiation.
+ * @retval FAPI error codes on failure
+ */
+TSS2_RC
+ifapi_policyeval_instantiate_finish(
+    IFAPI_POLICY_EVAL_INST_CTX *context)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    NODE_OBJECT_T *first_in_pol_list = context->policy_elements;
+    size_t i_last;
+
+    /* While not all policy elements are instantiated */
+    while (first_in_pol_list) {
+        TPMT_POLICYELEMENT *pol_element = first_in_pol_list->object;
+        switch (pol_element->type) {
+        case POLICYSIGNED:
+            if (pol_element->element.PolicySigned.keyPublic.type) {
+                /* Public info found in template, key path will not be needed. */
+                SAFE_FREE(pol_element->element.PolicySigned.keyPath);
+                break;
+            }
+
+            if (pol_element->element.PolicySigned.keyPEM &&
+                strlen(pol_element->element.PolicySigned.keyPEM) > 0) {
+                /* Determine name and public info for PEM key. */
+                r = set_pem_key_param(pol_element->element.PolicySigned.keyPEM,
+                                      &pol_element->element.PolicySigned.keyPublic,
+                                      &pol_element->element.PolicySigned.publicKey,
+                                      pol_element->element.PolicySigned.keyPEMhashAlg);
+                return_if_error(r, "Set parameter of pem key.");
+
+                /* Clear pem key, will be recreated during execution. */
+                SAFE_FREE(pol_element->element.PolicySigned.keyPEM);
+
+                break;
+            }
+            CHECK_TEMPLATE_PATH(pol_element->element.PolicySigned.keyPath, "PolicySigned");
+
+            /* Public info will be added to policy. */
+            r = context->callbacks.cbpublic(pol_element->element.PolicySigned.keyPath,
+                                            &pol_element->element.PolicySigned.keyPublic,
+                                            context->callbacks.cbpublic_userdata);
+            return_try_again(r);
+            return_if_error(r, "read_finish failed");
+            /* Clear keypath, only public data will be needed */
+            SAFE_FREE(pol_element->element.PolicySigned.keyPath);
+
+
+            break;
+
+        case POLICYNAMEHASH:
+            /* Set index of last name to be computed. */
+            i_last = pol_element->element.PolicyNameHash.count - 1;
+            while (!pol_element->element.PolicyNameHash.objectNames[i_last].size) {
+                /* Not all object names have been computed or were initialized */
+                size_t i = pol_element->element.PolicyNameHash.i;
+                r = context->callbacks.cbname(pol_element->element.PolicyNameHash.namePaths[i],
+                                              &pol_element->element.PolicyNameHash.objectNames[i],
+                                              context->callbacks.cbname_userdata);
+                return_try_again(r);
+                return_if_error(r, "get object name.");
+                pol_element->element.PolicyNameHash.i++;
+                SAFE_FREE(pol_element->element.PolicyNameHash.namePaths[i]);
+            }
+            break;
+
+        case POLICYSECRET:
+            if (pol_element->element.PolicySecret.objectName.size) {
+                /* Name found in template, object path will not be needed. */
+                SAFE_FREE(pol_element->element.PolicySecret.objectPath);
+                break;
+            }
+            CHECK_TEMPLATE_PATH(pol_element->element.PolicySecret.objectPath, "PolicySecret");
+            /* Object name will be added to policy. */
+            r = context->callbacks.cbname(pol_element->element.PolicySecret.objectPath,
+                                          &pol_element->element.PolicySecret.objectName,
+                                          context->callbacks.cbname_userdata);
+            return_try_again(r);
+            return_if_error(r, "read_finish failed");
+            SAFE_FREE(pol_element->element.PolicySecret.objectPath);
+            break;
+
+        case POLICYPCR:
+            if (pol_element->element.PolicyPCR.pcrs &&
+                pol_element->element.PolicyPCR.pcrs->count) {
+                /* PCR values already defined */
+                break;
+            }
+            /* Current values of PCRs will be used for policy */
+            r = context->callbacks.cbpcr(&pol_element->element.PolicyPCR.currentPCRs,
+                                         &pol_element->element.PolicyPCR.currentPCRandBanks,
+                                         &pol_element->element.PolicyPCR.pcrs,
+                                         context->callbacks.cbpcr_userdata);
+            return_try_again(r);
+            return_if_error(r, "read_finish failed");
+
+            pol_element->element.PolicyPCR.currentPCRs.sizeofSelect = 0;
+            pol_element->element.PolicyPCR.currentPCRandBanks.count = 0;
+            break;
+
+        case POLICYNV:
+            if (pol_element->element.PolicyNV.nvPublic.nvPublic.nvIndex) {
+                /* nvIndex is already set in policy. Path will not be needed */
+                pol_element->element.PolicyNV.nvIndex
+                    = pol_element->element.PolicyNV.nvPublic.nvPublic.nvIndex;
+                SAFE_FREE(pol_element->element.PolicyNV.nvPath);
+                break;
+            }
+
+            CHECK_TEMPLATE_PATH(pol_element->element.PolicyNV.nvPath, "PolicyNv");
+            /* Object name will be added to policy. */
+            r = context->callbacks.cbnvpublic(pol_element->element.PolicyNV.nvPath,
+                                              &pol_element->element.PolicyNV.nvPublic,
+                                              context->callbacks.cbnvpublic_userdata);
+            return_try_again(r);
+            return_if_error(r, "read_finish failed");
+
+            pol_element->element.PolicyNV.nvIndex
+                = pol_element->element.PolicyNV.nvPublic.nvPublic.nvIndex;
+
+            /* Clear NV path, only public data will be needed */
+            SAFE_FREE(pol_element->element.PolicyNV.nvPath);
+            break;
+
+        case POLICYDUPLICATIONSELECT:
+            if (pol_element->element.PolicyDuplicationSelect.newParentPublic.publicArea.type) {
+                 /* public data is already set in policy. Path will not be needed. */
+                SAFE_FREE(pol_element->element.PolicyDuplicationSelect.newParentPath);
+                break;
+            }
+
+            CHECK_TEMPLATE_PATH(pol_element->element.PolicyDuplicationSelect.newParentPath,
+                                "PolicyDuplicationselect");
+
+            /* Public info will be added to policy. */
+            r = context->callbacks.cbpublic(
+                     pol_element->element.PolicyDuplicationSelect.newParentPath,
+                     &pol_element->element.PolicyDuplicationSelect.newParentPublic.publicArea,
+                     context->callbacks.cbpublic_userdata);
+            return_try_again(r);
+            return_if_error(r, "read_finish failed");
+
+            r = ifapi_get_name(
+                     &pol_element->element.PolicyDuplicationSelect.newParentPublic.publicArea,
+                     &pol_element->element.PolicyDuplicationSelect.newParentName);
+            return_if_error(r, "Compute key name");
+
+            /* Clear keypath, only public data will be needed */
+            SAFE_FREE(pol_element->element.PolicyDuplicationSelect.newParentPath);
+            break;
+
+        case POLICYAUTHORIZENV:
+            if (pol_element->element.PolicyAuthorizeNv.nvPublic.nvPublic.nvIndex) {
+                /* nvIndex is already set in policy. Path will not be needed */
+                SAFE_FREE(pol_element->element.PolicyAuthorizeNv.nvPath);
+                break;
+            }
+
+            CHECK_TEMPLATE_PATH(pol_element->element.PolicyAuthorizeNv.nvPath,
+                                "PolicyAuthorizeNv");
+            /* Object name will be added to policy. */
+            r = context->callbacks.cbnvpublic(pol_element->element.PolicyAuthorizeNv.nvPath,
+                                               &pol_element->element.PolicyAuthorizeNv.nvPublic,
+                                               context->callbacks.cbnvpublic_userdata);
+            return_try_again(r);
+            return_if_error(r, "read_finish failed");
+            /* Clear NV path, only public data will be needed */
+            SAFE_FREE(pol_element->element.PolicyAuthorizeNv.nvPath);
+            break;
+
+        case POLICYAUTHORIZE:
+            if (pol_element->element.PolicyAuthorize.keyPublic.type) {
+                /* Public info found in template, key path will not be needed. */
+                SAFE_FREE(pol_element->element.PolicyAuthorize.keyPath);
+                r = ifapi_get_name(&pol_element->element.PolicyAuthorize.keyPublic,
+                                   &pol_element->element.PolicyAuthorize.keyName);
+                return_if_error(r, "Compute key name");
+
+                break;
+            }
+
+            if (pol_element->element.PolicyAuthorize.keyPEM &&
+                strlen(pol_element->element.PolicyAuthorize.keyPEM) > 0) {
+                /* Determine name and public info for PEM key. */
+                r =  set_pem_key_param(pol_element->element.PolicyAuthorize.keyPEM,
+                                       &pol_element->element.PolicyAuthorize.keyPublic,
+                                       &pol_element->element.PolicyAuthorize.keyName,
+                                       pol_element->element.PolicyAuthorize.keyPEMhashAlg);
+                return_if_error(r, "Set parameter of pem key.");
+
+                pol_element->element.PolicyAuthorize.keyPEM = NULL;
+
+                break;
+            }
+
+            CHECK_TEMPLATE_PATH(pol_element->element.PolicyAuthorize.keyPath, "PolicyAuthorize");
+
+            /* Object public data will be added to policy. */
+            r = context->callbacks.cbpublic(pol_element->element.PolicyAuthorize.keyPath,
+                                            &pol_element->element.PolicyAuthorize.keyPublic,
+                                            context->callbacks.cbpublic_userdata);
+            return_try_again(r);
+            return_if_error(r, "read_finish failed");
+
+            /* Compute key name from public info */
+            r = ifapi_get_name(&pol_element->element.PolicyAuthorize.keyPublic,
+                               &pol_element->element.PolicyAuthorize.keyName);
+            return_if_error(r, "Compute key name");
+
+            /* Clear key path, only public data will be needed */
+            SAFE_FREE(pol_element->element.PolicyAuthorize.keyPath);
+            break;
+        }
+        /* Cleanup head of list and use next policy element */
+        context->policy_elements = first_in_pol_list->next;
+        SAFE_FREE(first_in_pol_list);
+    }
+    return r;
+}
diff --git a/src/tss2-fapi/ifapi_policy_instantiate.h b/src/tss2-fapi/ifapi_policy_instantiate.h
new file mode 100644
index 0000000..bb60572
--- /dev/null
+++ b/src/tss2-fapi/ifapi_policy_instantiate.h
@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ *******************************************************************************/
+#ifndef FAPI_POLICY_INSTANTIATE_H
+#define FAPI_POLICY_INSTANTIATE_H
+
+#include <stdint.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <sys/stat.h>
+#include <json-c/json.h>
+#include <json-c/json_util.h>
+
+#include "tss2_esys.h"
+#include "tss2_fapi.h"
+//#include "fapi_int.h"
+//#include "fapi_policy.h"
+//#include "ifapi_keystore.h"
+
+typedef TSS2_RC (*ifapi_policyeval_cbpublic) (
+    const char *path,
+    TPMT_PUBLIC *public,
+    void *userdata);   /* e.g. for FAPI_CONTEXT */
+
+typedef TSS2_RC (*ifapi_policyeval_cbname) (
+    const char *path,
+    TPM2B_NAME *name,
+    void *userdata);   /* e.g. for FAPI_CONTEXT */
+
+typedef TSS2_RC (*ifapi_policyeval_cbnvindex) (
+    const char *path,
+    TPMI_RH_NV_INDEX  *nv_index,
+    void *userdata);   /* e.g. for FAPI_CONTEXT */
+
+typedef TSS2_RC (*ifapi_policyeval_cbnvpublic) (
+    const char *path,
+    TPM2B_NV_PUBLIC *nv_public,
+    void *userdata);   /* e.g. for FAPI_CONTEXT */
+
+typedef TSS2_RC (*ifapi_policyeval_cbpemparam) (
+    const char *keyPEM,
+    TPMT_PUBLIC *keyPublic,
+    TPM2B_NAME *name,
+    void *userdata);   /* e.g. for FAPI_CONTEXT */
+
+typedef TSS2_RC (*ifapi_policyeval_cbpcr) (
+    TPMS_PCR_SELECT *pcrSelect,
+    TPML_PCR_SELECTION *pcrBankSelect,
+    TPML_PCRVALUES **pcrs,
+    void *userdata);   /* e.g. for FAPI_CONTEXT */
+
+typedef struct {
+    ifapi_policyeval_cbpcr                cbpcr; /**< Callback to compute current PCR value */
+    void                        *cbpcr_userdata;
+    ifapi_policyeval_cbname              cbname; /**< Callback to compute name of an object from path */
+    void                       *cbname_userdata;
+    ifapi_policyeval_cbpublic          cbpublic; /**< Callback to compute public info of a key */
+    void                     *cbpublic_userdata;
+    ifapi_policyeval_cbnvpublic      cbnvpublic; /**< Callback to compute the NV public from path */
+    void                   *cbnvpublic_userdata;
+} ifapi_policyeval_INST_CB;
+
+/** Type for representing the context for policy instantiation.
+ */
+typedef struct {
+    TPMS_POLICY_HARNESS                 *policy; /**< The policy to be instantiated */
+    NODE_OBJECT_T              *policy_elements; /** The policy elements to be instantiated */
+    ifapi_policyeval_INST_CB          callbacks;
+} IFAPI_POLICY_EVAL_INST_CTX;
+
+TSS2_RC
+ifapi_policyeval_instantiate_async(
+    IFAPI_POLICY_EVAL_INST_CTX *context, /* For re-entry after try_again for offsets and such */
+    TPMS_POLICY_HARNESS *policy, /* in */
+    ifapi_policyeval_INST_CB *callbacks);
+TSS2_RC
+
+ifapi_policyeval_instantiate_finish(
+    IFAPI_POLICY_EVAL_INST_CTX *context);
+
+#endif /* FAPI_POLICY_INSTANTIATE_H */
diff --git a/src/tss2-fapi/ifapi_policy_json_deserialize.c b/src/tss2-fapi/ifapi_policy_json_deserialize.c
new file mode 100644
index 0000000..5668c2d
--- /dev/null
+++ b/src/tss2-fapi/ifapi_policy_json_deserialize.c
@@ -0,0 +1,1407 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ ******************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#include "tpm_json_deserialize.h"
+#include "ifapi_json_deserialize.h"
+#include "fapi_policy.h"
+#define LOGMODULE fapijson
+#include "util/log.h"
+#include "util/aux_util.h"
+
+static char *tss_const_prefixes[] = { "TPM2_ALG_", "TPM2_", "TPM_", "TPMA_", "POLICY", NULL};
+
+/** Get the index of a sub string after a certain prefix.
+ *
+ * The prefixes from table tss_const_prefixes will be used for case
+ * insensitive comparison.
+ *
+ * param[in] token the token with a potential prefix.
+ * @retval the position of the sub string after the prefix.
+ * @retval 0 if no prefix is found.
+ */
+
+static int
+get_token_start_idx(const char *token)
+{
+    int itoken = 0;
+    char *entry;
+    int i;
+
+    for (i = 0, entry = tss_const_prefixes[0]; entry != NULL;
+            i++, entry = tss_const_prefixes[i]) {
+        if (strncasecmp(token, entry, strlen(entry)) == 0) {
+            itoken += strlen(entry);
+            break;
+        }
+    }
+    return itoken;
+}
+
+/** Get number from a string.
+ *
+ * A string which represents a number or hex number (prefix 0x) is converted
+ * to an int64 number.
+ *
+ * param[in] token the string representing the number.
+ * param[out] num the converted number.
+ * @retval true if token represents a number
+ * @retval false if token does not represent a number.
+ */
+static bool
+get_number(const char *token, int64_t *num)
+{
+    int itoken = 0;
+    int pos = 0;
+    if (strncmp(token, "0x", 2) == 0) {
+        itoken = 2;
+        sscanf(&token[itoken], "%"PRIx64"%n", num, &pos);
+    } else {
+        sscanf(&token[itoken], "%"PRId64"%n", num, &pos);
+    }
+    if ((size_t)pos == strlen(token) - itoken)
+        return true;
+    else
+        return false;
+}
+
+/** Deserialize a TPMI_POLICYTYPE 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_POLICYTYPE_deserialize(json_object *jso, TPMI_POLICYTYPE *out)
+{
+    LOG_TRACE("call");
+    return ifapi_json_TPMI_POLICYTYPE_deserialize_txt(jso, out);
+}
+
+typedef struct {
+    TPMI_POLICYTYPE in;
+    char *name;
+} IFAPI_TPMI_POLICYTYPE_ASSIGN;
+
+static IFAPI_TPMI_POLICYTYPE_ASSIGN deserialize_TPMI_POLICYTYPE_tab[] = {
+    { POLICYOR, "Or" },
+    { POLICYSIGNED, "Signed" },
+    { POLICYSECRET, "Secret" },
+    { POLICYPCR, "PCR" },
+    { POLICYLOCALITY, "Locality" },
+    { POLICYNV, "NV" },
+    { POLICYCOUNTERTIMER, "CounterTimer" },
+    { POLICYCOMMANDCODE, "CommandCode" },
+    { POLICYPHYSICALPRESENCE, "PhysicalPresence" },
+    { POLICYCPHASH, "CpHash" },
+    { POLICYNAMEHASH, "NameHash" },
+    { POLICYDUPLICATIONSELECT, "DuplicationSelect" },
+    { POLICYAUTHORIZE, "Authorize" },
+    { POLICYAUTHVALUE, "AuthValue" },
+    { POLICYPASSWORD, "Password" },
+    { POLICYNVWRITTEN, "NvWritten" },
+    { POLICYTEMPLATE, "Template" },
+    { POLICYAUTHORIZENV, "AuthorizeNv" },
+    { POLICYACTION, "Action" },
+};
+
+/**  Deserialize a json object of type TPMI_POLICYTYPE.
+ *
+ * @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_POLICYTYPE_deserialize_txt(json_object *jso,
+        TPMI_POLICYTYPE *out)
+{
+    LOG_TRACE("call");
+    const char *token = json_object_get_string(jso);
+    int64_t i64;
+    if (get_number(token, &i64)) {
+        *out = (TPMI_POLICYTYPE) i64;
+        if ((int64_t)*out != i64) {
+            LOG_ERROR("Bad value");
+            return  TSS2_FAPI_RC_BAD_VALUE;
+        }
+        return TSS2_RC_SUCCESS;
+
+    } else {
+        int itoken = get_token_start_idx(token);
+        size_t i;
+        size_t n = sizeof(deserialize_TPMI_POLICYTYPE_tab) /
+                   sizeof(deserialize_TPMI_POLICYTYPE_tab[0]);
+        size_t size = strlen(token) - itoken;
+        for (i = 0; i < n; i++) {
+            if (strncasecmp(&token[itoken],
+                            &deserialize_TPMI_POLICYTYPE_tab[i].name[0],
+                            size) == 0) {
+                *out =  deserialize_TPMI_POLICYTYPE_tab[i].in;
+                return TSS2_RC_SUCCESS;
+            }
+        }
+        return_error(TSS2_FAPI_RC_BAD_VALUE, "Undefined constant.");
+    }
+
+}
+
+/** Deserialize a TPMS_POLICYSIGNED 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_POLICYSIGNED_deserialize(json_object *jso,
+        TPMS_POLICYSIGNED *out)
+{
+    json_object *jso2;
+    TSS2_RC r;
+    LOG_TRACE("call");
+    return_if_null(out, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+    size_t cond_cnt = 0; /**< counter for conditional fields */
+
+    if (!ifapi_get_sub_object(jso, "cpHashA", &jso2)) {
+        memset(&out->cpHashA, 0, sizeof(TPM2B_DIGEST));
+    } else {
+        r =  ifapi_json_TPM2B_DIGEST_deserialize(jso2, &out->cpHashA);
+        return_if_error(r, "BAD VALUE");
+    }
+
+    if (!ifapi_get_sub_object(jso, "policyRef", &jso2)) {
+        memset(&out->policyRef, 0, sizeof(TPM2B_NONCE));
+    } else {
+        r =  ifapi_json_TPM2B_NONCE_deserialize(jso2, &out->policyRef);
+        return_if_error(r, "BAD VALUE");
+    }
+
+    out->expiration = 0;
+
+    if (!ifapi_get_sub_object(jso, "keyPath", &jso2)) {
+        out->keyPath = NULL;
+    } else {
+        cond_cnt++;
+        r =  ifapi_json_char_deserialize(jso2, &out->keyPath);
+        return_if_error(r, "BAD VALUE");
+    }
+
+    if (!ifapi_get_sub_object(jso, "keyPublic", &jso2)) {
+        memset(&out->keyPublic, 0, sizeof(TPMT_PUBLIC));
+    } else {
+        cond_cnt++;
+        r =  ifapi_json_TPMT_PUBLIC_deserialize(jso2, &out->keyPublic);
+        return_if_error(r, "BAD VALUE");
+    }
+
+    if (!ifapi_get_sub_object(jso, "keyPEM", &jso2)) {
+        out->keyPEM = NULL;
+    } else {
+        cond_cnt++;
+        r =  ifapi_json_char_deserialize(jso2, &out->keyPEM);
+        return_if_error(r, "BAD VALUE");
+    }
+
+    if (!ifapi_get_sub_object(jso, "keyPEMhashAlg", &jso2)) {
+        out->keyPEMhashAlg = TPM2_ALG_SHA256;
+    } else {
+        r =  ifapi_json_TPMI_ALG_HASH_deserialize(jso2, &out->keyPEMhashAlg);
+        return_if_error(r, "BAD VALUE");
+    }
+
+    /* Check whether only one condition field found in policy. */
+    if (cond_cnt != 1) {
+        return_error(TSS2_FAPI_RC_BAD_TEMPLATE,
+                     "Exactly one conditional is allowed for policy signed.");
+    }
+
+    LOG_TRACE("true");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Deserialize a TPMS_POLICYSECRET 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_POLICYSECRET_deserialize(json_object *jso,
+        TPMS_POLICYSECRET *out)
+{
+    json_object *jso2;
+    TSS2_RC r;
+    size_t cond_cnt = 0; /**< counter for conditional fields */
+
+    LOG_TRACE("call");
+    return_if_null(out, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    if (!ifapi_get_sub_object(jso, "cpHashA", &jso2)) {
+        memset(&out->cpHashA, 0, sizeof(TPM2B_DIGEST));
+    } else {
+        r =  ifapi_json_TPM2B_DIGEST_deserialize(jso2, &out->cpHashA);
+        return_if_error(r, "BAD VALUE");
+    }
+
+    if (!ifapi_get_sub_object(jso, "policyRef", &jso2)) {
+        memset(&out->policyRef, 0, sizeof(TPM2B_NONCE));
+    } else {
+        r =  ifapi_json_TPM2B_NONCE_deserialize(jso2, &out->policyRef);
+        return_if_error(r, "BAD VALUE");
+    }
+    out->expiration = 0;
+
+    if (!ifapi_get_sub_object(jso, "objectPath", &jso2)) {
+        out->objectPath = NULL;
+    } else {
+        cond_cnt++;
+        r =  ifapi_json_char_deserialize(jso2, &out->objectPath);
+        return_if_error(r, "BAD VALUE");
+    }
+
+    if (!ifapi_get_sub_object(jso, "objectName", &jso2)) {
+        memset(&out->objectName, 0, sizeof(TPM2B_DIGEST));
+    } else {
+        cond_cnt++;
+        r =  ifapi_json_TPM2B_NAME_deserialize(jso2, &out->objectName);
+        return_if_error(r, "BAD VALUE");
+    }
+    if (cond_cnt != 1) {
+        return_error(TSS2_FAPI_RC_BAD_TEMPLATE,
+                     "Exactly one conditional needed for policy secret .");
+    }
+    LOG_TRACE("true");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Deserialize a TPMS_POLICYLOCALITY 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_POLICYLOCALITY_deserialize(json_object *jso,
+        TPMS_POLICYLOCALITY *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, "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");
+    LOG_TRACE("true");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Deserialize a TPMS_POLICYNV 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_POLICYNV_deserialize(json_object *jso,  TPMS_POLICYNV *out)
+{
+    json_object *jso2;
+    TSS2_RC r;
+    size_t cond_cnt = 0; /**< counter for conditional fields */
+
+    LOG_TRACE("call");
+    return_if_null(out, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    if (!ifapi_get_sub_object(jso, "nvPath", &jso2)) {
+        out->nvPath = NULL;
+    } else {
+        cond_cnt++;
+        r =  ifapi_json_char_deserialize(jso2, &out->nvPath);
+        return_if_error(r, "BAD VALUE");
+    }
+
+    if (!ifapi_get_sub_object(jso, "nvIndex", &jso2)) {
+        out->nvIndex = 0;
+    } else {
+        cond_cnt++;
+        r =  ifapi_json_TPMI_RH_NV_INDEX_deserialize(jso2, &out->nvIndex);
+        return_if_error(r, "BAD VALUE");
+    }
+
+    if (!ifapi_get_sub_object(jso, "nvPublic", &jso2)) {
+        memset(&out->nvPublic, 0, sizeof(TPM2B_NV_PUBLIC));
+    } else {
+        r =  ifapi_json_TPM2B_NV_PUBLIC_deserialize(jso2, &out->nvPublic);
+        return_if_error(r, "BAD VALUE");
+    }
+
+    if (!ifapi_get_sub_object(jso, "operandB", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_TPM2B_OPERAND_deserialize(jso2, &out->operandB);
+    return_if_error(r, "BAD VALUE");
+
+    if (!ifapi_get_sub_object(jso, "offset", &jso2)) {
+        out->offset = 0;
+    } else {
+        r =  ifapi_json_UINT16_deserialize(jso2, &out->offset);
+        return_if_error(r, "BAD VALUE");
+    }
+
+    if (!ifapi_get_sub_object(jso, "operation", &jso2)) {
+        out->operation = 0;
+    } else {
+        r =  ifapi_json_TPM2_EO_deserialize(jso2, &out->operation);
+        return_if_error(r, "BAD VALUE");
+    }
+    /* Check whether only one conditional is used. */
+    if (cond_cnt != 1) {
+        return_error(TSS2_FAPI_RC_BAD_TEMPLATE,
+                     "Exactly one conditional is allowed for policy NV.");
+    }
+
+    LOG_TRACE("true");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Deserialize a TPMS_POLICYCOUNTERTIMER 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_POLICYCOUNTERTIMER_deserialize(json_object *jso,
+        TPMS_POLICYCOUNTERTIMER *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, "operandB", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_TPM2B_OPERAND_deserialize(jso2, &out->operandB);
+    return_if_error(r, "BAD VALUE");
+
+    if (!ifapi_get_sub_object(jso, "offset", &jso2)) {
+        out->offset = 0;
+    } else {
+        r =  ifapi_json_UINT16_deserialize(jso2, &out->offset);
+        return_if_error(r, "BAD VALUE");
+    }
+
+    if (!ifapi_get_sub_object(jso, "operation", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_TPM2_EO_deserialize(jso2, &out->operation);
+    return_if_error(r, "BAD VALUE");
+    LOG_TRACE("true");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Deserialize a TPMS_POLICYCOMMANDCODE 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_POLICYCOMMANDCODE_deserialize(json_object *jso,
+        TPMS_POLICYCOMMANDCODE *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, "code", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_TPM2_CC_deserialize(jso2, &out->code);
+    return_if_error(r, "BAD VALUE");
+    LOG_TRACE("true");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Deserialize a TPMS_POLICYPHYSICALPRESENCE 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_POLICYPHYSICALPRESENCE_deserialize(json_object *jso,
+        TPMS_POLICYPHYSICALPRESENCE *out)
+{
+    LOG_TRACE("call");
+    (void)jso;
+    (void)out;
+
+    LOG_TRACE("true");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Deserialize a TPMS_POLICYCPHASH 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_POLICYCPHASH_deserialize(json_object *jso,
+        TPMS_POLICYCPHASH *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, "cpHash", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_TPM2B_DIGEST_deserialize(jso2, &out->cpHash);
+    return_if_error(r, "BAD VALUE");
+    LOG_TRACE("true");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Deserialize a TPMS_POLICYNAMEHASH 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_POLICYNAMEHASH_deserialize(json_object *jso,
+        TPMS_POLICYNAMEHASH *out)
+{
+    json_object *jso2, *jso3;
+    TSS2_RC r;
+    size_t i, n_paths = 0, n_names = 0;
+    size_t cond_cnt = 0; /**< counter for conditional fields */
+
+    LOG_TRACE("call");
+    memset(out, 0, sizeof(TPMS_POLICYNAMEHASH));
+    return_if_null(out, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    if (ifapi_get_sub_object(jso, "nameHash", &jso2)) {
+        cond_cnt++;
+        r =  ifapi_json_TPM2B_DIGEST_deserialize(jso2, &out->nameHash);
+        return_if_error(r, "BAD VALUE");
+
+        /* No need to deserialize namePaths or objectNames from which nameHash would
+           be derived. */
+        return TSS2_RC_SUCCESS;
+    }
+
+    if (ifapi_get_sub_object(jso, "namePaths", &jso2)) {
+        json_type jso_type = json_object_get_type(jso2);
+        cond_cnt++;
+        if (jso_type == json_type_array) {
+            n_paths = json_object_array_length(jso2);
+            if (n_paths > 3) {
+                return_error(TSS2_FAPI_RC_BAD_TEMPLATE,
+                             "More than 3 path names in policy name hash.");
+            }
+            for (i = 0; i < n_paths; i++) {
+                jso3 = json_object_array_get_idx(jso2, i);
+                r =  ifapi_json_char_deserialize(jso3, &out->namePaths[i]);
+                return_if_error(r, "BAD VALUE");
+            }
+            out->count = n_paths;
+        } else {
+            LOG_ERROR("No list of name paths");
+            return  TSS2_FAPI_RC_BAD_TEMPLATE;
+        }
+
+    }
+    if (ifapi_get_sub_object(jso, "objectNames", &jso2)) {
+        json_type jso_type = json_object_get_type(jso);
+        if (jso_type == json_type_array) {
+            n_names = json_object_array_length(jso2);
+            if (n_paths> 0 && n_names > 0) {
+                return_error(TSS2_FAPI_RC_BAD_TEMPLATE,
+                             "Only pathname or only TPM names are allowed "
+                             "for policy name hash.");
+            }
+            if (n_names > 3) {
+                return_error(TSS2_FAPI_RC_BAD_TEMPLATE,
+                             "More than 3 names in policy name hash.");
+            }
+            for (i = 0; i < n_names; i++) {
+                jso3 = json_object_array_get_idx(jso, i);
+                r = ifapi_json_TPM2B_NAME_deserialize(jso3, &out->objectNames[i]);
+                return_if_error(r, "BAD TEMPLATE");
+            }
+            out->count = n_names;
+        } else {
+            LOG_ERROR("No list of object names");
+            return  TSS2_FAPI_RC_BAD_TEMPLATE;
+        }
+    }
+    if (out->count == 0) {
+        LOG_ERROR("No list of object names or path names");
+        return  TSS2_FAPI_RC_BAD_TEMPLATE;
+    }
+    /* Check whether only one condition field found in policy. */
+    if (cond_cnt != 1) {
+        return_error(TSS2_FAPI_RC_BAD_TEMPLATE,
+                     "Exactly one conditional is allowed for policy name hash.");
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Deserialize a TPMS_POLICYDUPLICATIONSELECT 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_POLICYDUPLICATIONSELECT_deserialize(json_object *jso,
+        TPMS_POLICYDUPLICATIONSELECT *out)
+{
+    json_object *jso2;
+    TSS2_RC r;
+    size_t cond_cnt = 0; /**< counter for conditional fields */
+
+    LOG_TRACE("call");
+    return_if_null(out, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    GET_OPTIONAL(objectName, "objectName", TPM2B_NAME);
+    GET_OPTIONAL(newParentName, "newParentName", TPM2B_NAME);
+    if (out->newParentName.size)
+        cond_cnt++;
+    if (ifapi_get_sub_object(jso, "includeObject", &jso2)) {
+        r =  ifapi_json_TPMI_YES_NO_deserialize(jso2, &out->includeObject);
+        return_if_error(r, "Yes or No expected.");
+    } else {
+        out->includeObject = TPM2_NO;
+    }
+    GET_OPTIONAL(newParentPublic, "newParentPublic", TPM2B_PUBLIC);
+    if (out->newParentPublic.size)
+        cond_cnt++;
+
+    if (!ifapi_get_sub_object(jso, "newParentPath", &jso2)) {
+        if (!out->newParentPublic.publicArea.type) {
+            return_error(TSS2_FAPI_RC_BAD_VALUE, "No path and TPM2B_PUBLIC");
+        }
+        out->newParentPath = NULL;
+    } else {
+        cond_cnt++;
+        r =  ifapi_json_char_deserialize(jso2, &out->newParentPath);
+        return_if_error(r, "BAD VALUE");
+    }
+    /* Check whether only one condition field found in policy. */
+    if (cond_cnt != 1) {
+        return_error(TSS2_FAPI_RC_BAD_TEMPLATE,
+                     "Exactly one conditional is allowed for "
+                     "policy duplication select.");
+    }
+    LOG_TRACE("true");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Deserialize a TPMS_POLICYAUTHORIZE 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_POLICYAUTHORIZE_deserialize(json_object *jso,
+        TPMS_POLICYAUTHORIZE *out)
+{
+    json_object *jso2;
+    TSS2_RC r;
+    size_t cond_cnt = 0; /**< counter for conditional fields */
+
+    LOG_TRACE("call");
+    return_if_null(out, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    if (!ifapi_get_sub_object(jso, "approvedPolicy", &jso2)) {
+        memset(&out->approvedPolicy, 0, sizeof(TPM2B_DIGEST));
+    } else {
+        r =  ifapi_json_TPM2B_DIGEST_deserialize(jso2, &out->approvedPolicy);
+        return_if_error(r, "BAD VALUE");
+    }
+
+    if (!ifapi_get_sub_object(jso, "policyRef", &jso2)) {
+        memset(&out->policyRef, 0, sizeof(TPM2B_NONCE));
+    } else {
+        r =  ifapi_json_TPM2B_NONCE_deserialize(jso2, &out->policyRef);
+        return_if_error(r, "BAD VALUE");
+    }
+
+    if (!ifapi_get_sub_object(jso, "keyName", &jso2)) {
+        memset(&out->keyName, 0, sizeof(TPM2B_NAME));
+    } else {
+        r =  ifapi_json_TPM2B_NAME_deserialize(jso2, &out->keyName);
+        return_if_error(r, "BAD VALUE");
+    }
+
+    if (!ifapi_get_sub_object(jso, "checkTicket", &jso2)) {
+        memset(&out->checkTicket, 0, sizeof(TPMT_TK_VERIFIED));
+    } else {
+        r =  ifapi_json_TPMT_TK_VERIFIED_deserialize(jso2, &out->checkTicket);
+        return_if_error(r, "BAD VALUE");
+    }
+
+    if (ifapi_get_sub_object(jso, "keyPath", &jso2)) {
+        cond_cnt++;
+        r =  ifapi_json_char_deserialize(jso2, &out->keyPath);
+        return_if_error(r, "BAD VALUE");
+    } else {
+        out->keyPath = NULL;
+    }
+
+    if (!ifapi_get_sub_object(jso, "keyPublic", &jso2)) {
+        memset(&out->keyPublic, 0, sizeof(TPMT_PUBLIC));
+    } else {
+        cond_cnt++;
+        r =  ifapi_json_TPMT_PUBLIC_deserialize(jso2, &out->keyPublic);
+        return_if_error(r, "BAD VALUE");
+    }
+
+    if (!ifapi_get_sub_object(jso, "keyPEM", &jso2)) {
+        out->keyPEM = NULL;
+    } else {
+        cond_cnt++;
+        r =  ifapi_json_char_deserialize(jso2, &out->keyPEM);
+        return_if_error(r, "BAD VALUE");
+    }
+
+    if (!ifapi_get_sub_object(jso, "keyPEMhashAlg", &jso2)) {
+        out->keyPEMhashAlg = 0;
+    } else {
+        r =  ifapi_json_TPMI_ALG_HASH_deserialize(jso2, &out->keyPEMhashAlg);
+        return_if_error(r, "BAD VALUE");
+    }
+    /* Check whether only one condition field found in policy. */
+    if (cond_cnt != 1) {
+        return_error(TSS2_FAPI_RC_BAD_TEMPLATE,
+                     "Exactly one conditional is allowed for policy authorize.");
+    }
+    LOG_TRACE("true");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Deserialize a TPMS_POLICYAUTHVALUE 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_POLICYAUTHVALUE_deserialize(json_object *jso,
+        TPMS_POLICYAUTHVALUE *out)
+{
+    LOG_TRACE("call");
+    (void)out;
+    (void)jso;
+
+    LOG_TRACE("true");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Deserialize a TPMS_POLICYPASSWORD 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_POLICYPASSWORD_deserialize(json_object *jso,
+        TPMS_POLICYPASSWORD *out)
+{
+    LOG_TRACE("call");
+    (void)jso;
+    (void)out;
+
+    LOG_TRACE("true");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Deserialize a TPMS_POLICYNVWRITTEN 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_POLICYNVWRITTEN_deserialize(json_object *jso,
+        TPMS_POLICYNVWRITTEN *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, "writtenSet", &jso2)) {
+        out->writtenSet = TPM2_YES;
+        return  TSS2_RC_SUCCESS;
+    }
+    r =  ifapi_json_TPMI_YES_NO_deserialize(jso2, &out->writtenSet);
+    return_if_error(r, "BAD VALUE");
+    LOG_TRACE("true");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Deserialize a TPMS_POLICYTEMPLATE 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_POLICYTEMPLATE_deserialize(json_object *jso,
+        TPMS_POLICYTEMPLATE *out)
+{
+    json_object *jso2;
+    TSS2_RC r;
+    size_t cond_cnt = 0; /**< counter for conditional fields */
+
+    LOG_TRACE("call");
+    return_if_null(out, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    if (!ifapi_get_sub_object(jso, "templateHash", &jso2)) {
+        memset(&out->templateHash, 0, sizeof(TPM2B_DIGEST));
+    } else {
+        cond_cnt++;
+        r =  ifapi_json_TPM2B_DIGEST_deserialize(jso2, &out->templateHash);
+        return_if_error(r, "BAD VALUE");
+    }
+
+    if (!ifapi_get_sub_object(jso, "templatePublic", &jso2)) {
+        memset(&out->templatePublic, 0, sizeof(TPM2B_PUBLIC));
+    } else {
+        cond_cnt++;
+        r =  ifapi_json_TPM2B_PUBLIC_deserialize(jso2, &out->templatePublic);
+        return_if_error(r, "BAD VALUE");
+    }
+
+    if (ifapi_get_sub_object(jso, "templateName", &jso2)) {
+        r =  ifapi_json_char_deserialize(jso2, &out->templateName);
+        return_if_error(r, "BAD VALUE");
+    } else {
+        out->templateName = NULL;
+    }
+
+    /* Check whether only one condition field found in policy. */
+    if (cond_cnt != 1) {
+        return_error(TSS2_FAPI_RC_BAD_TEMPLATE,
+                     "Exactly one conditional is allowed for policy template.");
+    }
+
+    LOG_TRACE("true");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Deserialize a TPMS_POLICYAUTHORIZENV 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_POLICYAUTHORIZENV_deserialize(json_object *jso,
+        TPMS_POLICYAUTHORIZENV *out)
+{
+    json_object *jso2;
+    TSS2_RC r;
+    size_t cond_cnt = 0; /**< counter for conditional fields */
+
+    LOG_TRACE("call");
+    return_if_null(out, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    memset(out, 0, sizeof(TPMS_POLICYAUTHORIZENV));
+
+    if (ifapi_get_sub_object(jso, "nvPath", &jso2)) {
+        cond_cnt++;
+        r =  ifapi_json_char_deserialize(jso2, &out->nvPath);
+        return_if_error(r, "BAD VALUE");
+    } else {
+        out->nvPath = NULL;
+    }
+
+    if (!ifapi_get_sub_object(jso, "nvPublic", &jso2)) {
+        memset(&out->nvPublic, 0, sizeof(TPM2B_NV_PUBLIC));
+    } else {
+        cond_cnt++;
+        r =  ifapi_json_TPM2B_NV_PUBLIC_deserialize(jso2, &out->nvPublic);
+        return_if_error(r, "BAD VALUE");
+    }
+    /* Check whether only one condition field found in policy. */
+    if (cond_cnt != 1) {
+        return_error(TSS2_FAPI_RC_BAD_TEMPLATE,
+                     "Exactly one conditional is allowed for policy signed.");
+    }
+
+    LOG_TRACE("true");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Deserialize a TPMS_POLICYACTION 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_POLICYACTION_deserialize(json_object *jso,
+        TPMS_POLICYACTION *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, "action", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_char_deserialize(jso2, &out->action);
+    return_if_error(r, "BAD VALUE");
+    LOG_TRACE("true");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Deserialize a TPMS_PCRVALUE 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_PCRVALUE_deserialize(json_object *jso,  TPMS_PCRVALUE *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, "pcr", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_UINT32_deserialize(jso2, &out->pcr);
+    return_if_error(r, "BAD VALUE");
+
+    if (!ifapi_get_sub_object(jso, "hashAlg", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_TPM2_ALG_ID_deserialize(jso2, &out->hashAlg);
+    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_TPMU_HA_deserialize(out->hashAlg, jso2, &out-> digest);
+    return_if_error(r, "BAD VALUE");
+
+    LOG_TRACE("true");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Deserialize a TPML_PCRVALUES 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_TPML_PCRVALUES_deserialize(json_object *jso,  TPML_PCRVALUES **out)
+{
+    json_object *jso2;
+    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) {
+        *out = calloc(1, sizeof(TPML_PCRVALUES) +
+                      json_object_array_length(jso) * sizeof(TPMS_PCRVALUE));
+        return_if_null(*out, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+        (*out)->count = json_object_array_length(jso);
+        for (size_t i = 0; i < (*out)->count; i++) {
+            jso2 = json_object_array_get_idx(jso, i);
+            r =  ifapi_json_TPMS_PCRVALUE_deserialize(jso2, &(*out)->pcrs[i]);
+            return_if_error(r, "TPMS_PCRVALUE_deserialize");
+        }
+    } else {
+        return_error(TSS2_FAPI_RC_BAD_VALUE, "BAD VALUE");
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Deserialize a TPMS_POLICYPCR 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_POLICYPCR_deserialize(json_object *jso,  TPMS_POLICYPCR *out)
+{
+    json_object *jso2;
+    TSS2_RC r;
+    size_t cond_cnt = 0; /**< counter for conditional fields */
+
+    LOG_TRACE("call");
+    return_if_null(out, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    if (ifapi_get_sub_object(jso, "pcrs", &jso2)) {
+        cond_cnt++;
+        r =  ifapi_json_TPML_PCRVALUES_deserialize(jso2, &out->pcrs);
+        return_if_error(r, "BAD VALUE");
+    } else {
+        memset(&out->pcrs, 0, sizeof(TPML_PCRVALUES));
+    }
+
+    if (ifapi_get_sub_object(jso, "currentPCRs", &jso2)) {
+        cond_cnt++;
+        r =  ifapi_json_TPMS_PCR_SELECT_deserialize(jso2, &out->currentPCRs);
+        return_if_error(r, "BAD VALUE");
+    } else {
+        memset(&out->currentPCRs, 0, sizeof(TPMS_PCR_SELECT));
+    }
+
+    if (ifapi_get_sub_object(jso, "currentPCRandBanks", &jso2)) {
+        cond_cnt++;
+        r =  ifapi_json_TPML_PCR_SELECTION_deserialize(jso2, &out->currentPCRandBanks);
+        return_if_error(r, "BAD VALUE");
+    } else {
+        memset(&out->currentPCRandBanks, 0, sizeof(TPML_PCR_SELECTION));
+    }
+
+    /* Check whether only one conditional is used. */
+    if (cond_cnt != 1) {
+        return_error(TSS2_FAPI_RC_BAD_TEMPLATE,
+                     "Exactly one conditional is allowed for policy PCR.");
+    }
+
+    LOG_TRACE("true");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Deserialize a TPMS_POLICYAUTHORIZATION 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_POLICYAUTHORIZATION_deserialize(json_object *jso,
+        TPMS_POLICYAUTHORIZATION *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_char_deserialize(jso2, &out->type);
+    return_if_error(r, "BAD VALUE");
+
+    if (!ifapi_get_sub_object(jso, "key", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_TPMT_PUBLIC_deserialize(jso2, &out->key);
+    return_if_error(r, "BAD VALUE");
+
+    if (!ifapi_get_sub_object(jso, "policyRef", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_TPM2B_NONCE_deserialize(jso2, &out->policyRef);
+    return_if_error(r, "BAD VALUE");
+
+    if (!ifapi_get_sub_object(jso, "signature", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_TPMT_SIGNATURE_deserialize(jso2, &out->signature);
+    return_if_error(r, "BAD VALUE");
+    LOG_TRACE("true");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Deserialize a TPML_POLICYAUTHORIZATIONS 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_TPML_POLICYAUTHORIZATIONS_deserialize(json_object *jso,
+        TPML_POLICYAUTHORIZATIONS **out)
+{
+    json_object *jso2;
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    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) {
+        *out = calloc(1, sizeof(TPML_POLICYAUTHORIZATIONS) +
+                      json_object_array_length(jso) * sizeof(TPMS_POLICYAUTHORIZATION));
+        return_if_null(*out, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+        (*out)->count = json_object_array_length(jso);
+        for (size_t i = 0; i < (*out)->count; i++) {
+            jso2 = json_object_array_get_idx(jso, i);
+            r =  ifapi_json_TPMS_POLICYAUTHORIZATION_deserialize(jso2,
+                    &(*out)->authorizations[i]);
+            return_if_error(r, "TPMS_POLICYAUTHORIZATION_deserialize");
+        }
+    } else {
+        return_error(TSS2_FAPI_RC_BAD_VALUE, "BAD VALUE");
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Deserialize a TPMS_POLICYBRANCH 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_POLICYBRANCH_deserialize(json_object *jso,
+        TPMS_POLICYBRANCH *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_char_deserialize(jso2, &out->name);
+    return_if_error(r, "BAD VALUE");
+
+    if (!ifapi_get_sub_object(jso, "description", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_char_deserialize(jso2, &out->description);
+    return_if_error(r, "BAD VALUE");
+
+    if (!ifapi_get_sub_object(jso, "policy", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_TPML_POLICYELEMENTS_deserialize(jso2, &out->policy);
+    return_if_error(r, "BAD VALUE");
+
+    if (!ifapi_get_sub_object(jso, "policyDigests", &jso2)) {
+        memset(&out->policyDigests, 0, sizeof(TPML_DIGEST_VALUES));
+    } else {
+        r =  ifapi_json_TPML_DIGEST_VALUES_deserialize(jso2, &out->policyDigests);
+        return_if_error(r, "BAD VALUE");
+
+    }
+
+    LOG_TRACE("true");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Deserialize a TPML_POLICYBRANCHES 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_TPML_POLICYBRANCHES_deserialize(json_object *jso,
+        TPML_POLICYBRANCHES **out)
+{
+    json_object *jso2;
+    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) {
+        *out = calloc(1, sizeof(TPML_POLICYBRANCHES) +
+                      json_object_array_length(jso) * sizeof(TPMS_POLICYBRANCH));
+        return_if_null(*out, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+        (*out)->count = json_object_array_length(jso);
+        for (size_t i = 0; i < (*out)->count; i++) {
+            jso2 = json_object_array_get_idx(jso, i);
+            r =  ifapi_json_TPMS_POLICYBRANCH_deserialize(jso2, &(*out)->authorizations[i]);
+            return_if_error(r, "TPMS_POLICYBRANCH_deserialize");
+        }
+    } else {
+        return_error(TSS2_FAPI_RC_BAD_VALUE, "BAD VALUE");
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Deserialize a TPMS_POLICYOR 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_POLICYOR_deserialize(json_object *jso,  TPMS_POLICYOR *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, "branches", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_TPML_POLICYBRANCHES_deserialize(jso2, &out->branches);
+    return_if_error(r, "BAD VALUE");
+    LOG_TRACE("true");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Deserialize a TPMU_POLICYELEMENT 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[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_POLICYELEMENT_deserialize(
+    UINT32 selector,
+    json_object *jso,
+    TPMU_POLICYELEMENT *out)
+{
+    LOG_TRACE("call");
+    switch (selector) {
+    case POLICYOR:
+        return ifapi_json_TPMS_POLICYOR_deserialize(jso, &out->PolicyOr);
+    case POLICYSIGNED:
+        return ifapi_json_TPMS_POLICYSIGNED_deserialize(jso, &out->PolicySigned);
+    case POLICYSECRET:
+        return ifapi_json_TPMS_POLICYSECRET_deserialize(jso, &out->PolicySecret);
+    case POLICYPCR:
+        return ifapi_json_TPMS_POLICYPCR_deserialize(jso, &out->PolicyPCR);
+    case POLICYLOCALITY:
+        return ifapi_json_TPMS_POLICYLOCALITY_deserialize(jso, &out->PolicyLocality);
+    case POLICYNV:
+        return ifapi_json_TPMS_POLICYNV_deserialize(jso, &out->PolicyNV);
+    case POLICYCOUNTERTIMER:
+        return ifapi_json_TPMS_POLICYCOUNTERTIMER_deserialize(jso,
+                &out->PolicyCounterTimer);
+    case POLICYCOMMANDCODE:
+        return ifapi_json_TPMS_POLICYCOMMANDCODE_deserialize(jso,
+                &out->PolicyCommandCode);
+    case POLICYPHYSICALPRESENCE:
+        return ifapi_json_TPMS_POLICYPHYSICALPRESENCE_deserialize(jso,
+                &out->PolicyPhysicalPresence);
+    case POLICYCPHASH:
+        return ifapi_json_TPMS_POLICYCPHASH_deserialize(jso, &out->PolicyCpHash);
+    case POLICYNAMEHASH:
+        return ifapi_json_TPMS_POLICYNAMEHASH_deserialize(jso, &out->PolicyNameHash);
+    case POLICYDUPLICATIONSELECT:
+        return ifapi_json_TPMS_POLICYDUPLICATIONSELECT_deserialize(jso,
+                &out->PolicyDuplicationSelect);
+    case POLICYAUTHORIZE:
+        return ifapi_json_TPMS_POLICYAUTHORIZE_deserialize(jso, &out->PolicyAuthorize);
+    case POLICYAUTHVALUE:
+        return ifapi_json_TPMS_POLICYAUTHVALUE_deserialize(jso, &out->PolicyAuthValue);
+    case POLICYPASSWORD:
+        return ifapi_json_TPMS_POLICYPASSWORD_deserialize(jso, &out->PolicyPassword);
+    case POLICYNVWRITTEN:
+        return ifapi_json_TPMS_POLICYNVWRITTEN_deserialize(jso, &out->PolicyNvWritten);
+    case POLICYTEMPLATE:
+        return ifapi_json_TPMS_POLICYTEMPLATE_deserialize(jso, &out->PolicyTemplate);
+    case POLICYAUTHORIZENV:
+        return ifapi_json_TPMS_POLICYAUTHORIZENV_deserialize(jso,
+                &out->PolicyAuthorizeNv);
+    case POLICYACTION:
+        return ifapi_json_TPMS_POLICYACTION_deserialize(jso, &out->PolicyAction);
+    default:
+        LOG_TRACE("false");
+        return TSS2_FAPI_RC_BAD_VALUE;
+    };
+}
+
+/** Deserialize a TPMT_POLICYELEMENT 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_TPMT_POLICYELEMENT_deserialize(json_object *jso,
+        TPMT_POLICYELEMENT *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_POLICYTYPE_deserialize(jso2, &out->type);
+    return_if_error(r, "BAD VALUE");
+
+    if (!ifapi_get_sub_object(jso, "policyDigests", &jso2)) {
+        memset(&out->policyDigests, 0, sizeof(TPML_DIGEST_VALUES));
+    } else {
+        r =  ifapi_json_TPML_DIGEST_VALUES_deserialize(jso2, &out->policyDigests);
+        return_if_error(r, "BAD VALUE");
+
+    }
+    r = ifapi_json_TPMU_POLICYELEMENT_deserialize(out->type, jso, &out->element);
+    return_if_error(r, "BAD VALUE");
+
+    LOG_TRACE("true");
+    return TSS2_RC_SUCCESS;
+}
+
+/** Deserialize a TPML_POLICYELEMENTS 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_TPML_POLICYELEMENTS_deserialize(json_object *jso,
+        TPML_POLICYELEMENTS **out)
+{
+    json_object *jso2;
+    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) {
+        *out = calloc(1, sizeof(TPML_POLICYELEMENTS) +
+                      json_object_array_length(jso) * sizeof(TPMT_POLICYELEMENT));
+        return_if_null(*out, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+        (*out)->count = json_object_array_length(jso);
+        for (size_t i = 0; i < (*out)->count; i++) {
+            jso2 = json_object_array_get_idx(jso, i);
+            r =  ifapi_json_TPMT_POLICYELEMENT_deserialize(jso2, &(*out)->elements[i]);
+            return_if_error(r, "TPMT_POLICYELEMENT_deserialize");
+        }
+    } else {
+        return_error(TSS2_FAPI_RC_BAD_VALUE, "BAD VALUE");
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Deserialize a TPMS_POLICY_HARNESS 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_POLICY_HARNESS_deserialize(json_object *jso,
+        TPMS_POLICY_HARNESS *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, "description", &jso2)) {
+        LOG_ERROR("No description for policy.");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_char_deserialize(jso2, &out->description);
+    return_if_error(r, "BAD VALUE");
+
+    if (!ifapi_get_sub_object(jso, "policyDigests", &jso2)) {
+        memset(&out->policyDigests, 0, sizeof(TPML_DIGEST_VALUES));
+    } else {
+        r =  ifapi_json_TPML_DIGEST_VALUES_deserialize(jso2, &out->policyDigests);
+        return_if_error(r, "BAD VALUE");
+
+    }
+    if (!ifapi_get_sub_object(jso, "policyAuthorizations", &jso2)) {
+        memset(&out->policyAuthorizations, 0, sizeof(TPML_POLICYAUTHORIZATIONS));
+    } else {
+        r =  ifapi_json_TPML_POLICYAUTHORIZATIONS_deserialize(jso2,
+                &out->policyAuthorizations);
+        return_if_error(r, "BAD VALUE");
+
+    }
+    if (!ifapi_get_sub_object(jso, "policy", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_TPML_POLICYELEMENTS_deserialize(jso2, &out->policy);
+    return_if_error(r, "BAD VALUE");
+    LOG_TRACE("true");
+    return TSS2_RC_SUCCESS;
+}
diff --git a/src/tss2-fapi/ifapi_policy_json_deserialize.h b/src/tss2-fapi/ifapi_policy_json_deserialize.h
new file mode 100644
index 0000000..e0d15fb
--- /dev/null
+++ b/src/tss2-fapi/ifapi_policy_json_deserialize.h
@@ -0,0 +1,134 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ ******************************************************************************/
+#ifndef IFAPI_POLICY_JSON_DESERIALIZE_H
+#define IFAPI_POLICY_JSON_DESERIALIZE_H
+
+#include <stdbool.h>
+#include <json-c/json.h>
+#include <json-c/json_util.h>
+
+#include "tss2_tpm2_types.h"
+#include "fapi_int.h"
+
+TSS2_RC
+ifapi_json_TPMI_POLICYTYPE_deserialize(json_object *jso, TPMI_POLICYTYPE *out);
+
+TSS2_RC
+ifapi_json_TPMI_POLICYTYPE_deserialize_txt(json_object *jso,
+        TPMI_POLICYTYPE *out);
+
+TSS2_RC
+ifapi_json_TPMS_POLICYSIGNED_deserialize(json_object *jso,
+        TPMS_POLICYSIGNED *out);
+
+TSS2_RC
+ifapi_json_TPMS_POLICYSECRET_deserialize(json_object *jso,
+        TPMS_POLICYSECRET *out);
+
+TSS2_RC
+ifapi_json_TPMS_POLICYLOCALITY_deserialize(json_object *jso,
+        TPMS_POLICYLOCALITY *out);
+
+TSS2_RC
+ifapi_json_TPMS_POLICYNV_deserialize(json_object *jso, TPMS_POLICYNV *out);
+
+TSS2_RC
+ifapi_json_TPMS_POLICYCOUNTERTIMER_deserialize(json_object *jso,
+        TPMS_POLICYCOUNTERTIMER *out);
+
+TSS2_RC
+ifapi_json_TPMS_POLICYCOMMANDCODE_deserialize(json_object *jso,
+        TPMS_POLICYCOMMANDCODE *out);
+
+TSS2_RC
+ifapi_json_TPMS_POLICYPHYSICALPRESENCE_deserialize(json_object *jso,
+        TPMS_POLICYPHYSICALPRESENCE *out);
+
+TSS2_RC
+ifapi_json_TPMS_POLICYCPHASH_deserialize(json_object *jso,
+        TPMS_POLICYCPHASH *out);
+
+TSS2_RC
+ifapi_json_TPMS_POLICYNAMEHASH_deserialize(json_object *jso,
+        TPMS_POLICYNAMEHASH *out);
+
+TSS2_RC
+ifapi_json_TPMS_POLICYDUPLICATIONSELECT_deserialize(json_object *jso,
+        TPMS_POLICYDUPLICATIONSELECT *out);
+
+TSS2_RC
+ifapi_json_TPMS_POLICYAUTHORIZE_deserialize(json_object *jso,
+        TPMS_POLICYAUTHORIZE *out);
+
+TSS2_RC
+ifapi_json_TPMS_POLICYAUTHVALUE_deserialize(json_object *jso,
+        TPMS_POLICYAUTHVALUE *out);
+
+TSS2_RC
+ifapi_json_TPMS_POLICYPASSWORD_deserialize(json_object *jso,
+        TPMS_POLICYPASSWORD *out);
+
+TSS2_RC
+ifapi_json_TPMS_POLICYNVWRITTEN_deserialize(json_object *jso,
+        TPMS_POLICYNVWRITTEN *out);
+
+TSS2_RC
+ifapi_json_TPMS_POLICYTEMPLATE_deserialize(json_object *jso,
+        TPMS_POLICYTEMPLATE *out);
+
+TSS2_RC
+ifapi_json_TPMS_POLICYAUTHORIZENV_deserialize(json_object *jso,
+        TPMS_POLICYAUTHORIZENV *out);
+
+TSS2_RC
+ifapi_json_TPMS_POLICYACTION_deserialize(json_object *jso,
+        TPMS_POLICYACTION *out);
+
+TSS2_RC
+ifapi_json_TPMS_PCRVALUE_deserialize(json_object *jso, TPMS_PCRVALUE *out);
+
+TSS2_RC
+ifapi_json_TPML_PCRVALUES_deserialize(json_object *jso, TPML_PCRVALUES **out);
+
+TSS2_RC
+ifapi_json_TPMS_POLICYPCR_deserialize(json_object *jso, TPMS_POLICYPCR *out);
+
+TSS2_RC
+ifapi_json_TPMS_POLICYAUTHORIZATION_deserialize(json_object *jso,
+        TPMS_POLICYAUTHORIZATION *out);
+
+TSS2_RC
+ifapi_json_TPML_POLICYAUTHORIZATIONS_deserialize(json_object *jso,
+        TPML_POLICYAUTHORIZATIONS **out);
+
+TSS2_RC
+ifapi_json_TPMS_POLICYBRANCH_deserialize(json_object *jso,
+        TPMS_POLICYBRANCH *out);
+
+TSS2_RC
+ifapi_json_TPML_POLICYBRANCHES_deserialize(json_object *jso,
+        TPML_POLICYBRANCHES **out);
+
+TSS2_RC
+ifapi_json_TPMS_POLICYOR_deserialize(json_object *jso, TPMS_POLICYOR *out);
+
+TSS2_RC
+ifapi_json_TPMU_POLICYELEMENT_deserialize(UINT32 selector, json_object *jso,
+        TPMU_POLICYELEMENT *out);
+
+TSS2_RC
+ifapi_json_TPMT_POLICYELEMENT_deserialize(json_object *jso,
+        TPMT_POLICYELEMENT *out);
+
+TSS2_RC
+ifapi_json_TPML_POLICYELEMENTS_deserialize(json_object *jso,
+        TPML_POLICYELEMENTS **out);
+
+TSS2_RC
+ifapi_json_TPMS_POLICY_HARNESS_deserialize(json_object *jso,
+        TPMS_POLICY_HARNESS *out);
+
+#endif /* IFAPI_POLICY_JSON_DESERIALIZE_H */
diff --git a/src/tss2-fapi/ifapi_policy_json_serialize.c b/src/tss2-fapi/ifapi_policy_json_serialize.c
new file mode 100644
index 0000000..53c97a2
--- /dev/null
+++ b/src/tss2-fapi/ifapi_policy_json_serialize.c
@@ -0,0 +1,1330 @@
+/* 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 "tpm_json_serialize.h"
+#include "fapi_policy.h"
+#include "ifapi_policy_json_serialize.h"
+
+#define LOGMODULE fapijson
+#include "util/log.h"
+#include "util/aux_util.h"
+
+static TSS2_RC
+ifapi_json_char_serialize(
+    const char *in,
+    json_object **jso)
+{
+    if (in == NULL) {
+        *jso = json_object_new_string("");
+    } else {
+        *jso = json_object_new_string(in);
+    }
+    return_if_null(jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+    return TSS2_RC_SUCCESS;
+}
+
+typedef struct {
+    TPMI_POLICYTYPE in;
+    char *name;
+} TPMI_POLICYTYPE_ASSIGN;
+
+static TPMI_POLICYTYPE_ASSIGN serialize_TPMI_POLICYTYPE_tab[] = {
+    { POLICYOR, "POLICYOR" },
+    { POLICYSIGNED, "POLICYSIGNED" },
+    { POLICYSECRET, "POLICYSECRET" },
+    { POLICYPCR, "POLICYPCR" },
+    { POLICYLOCALITY, "POLICYLOCALITY" },
+    { POLICYNV, "POLICYNV" },
+    { POLICYCOUNTERTIMER, "POLICYCOUNTERTIMER" },
+    { POLICYCOMMANDCODE, "POLICYCOMMANDCODE" },
+    { POLICYPHYSICALPRESENCE, "POLICYPHYSICALPRESENCE" },
+    { POLICYCPHASH, "POLICYCPHASH" },
+    { POLICYNAMEHASH, "POLICYNAMEHASH" },
+    { POLICYDUPLICATIONSELECT, "POLICYDUPLICATIONSELECT" },
+    { POLICYAUTHORIZE, "POLICYAUTHORIZE" },
+    { POLICYAUTHVALUE, "POLICYAUTHVALUE" },
+    { POLICYPASSWORD, "POLICYPASSWORD" },
+    { POLICYNVWRITTEN, "POLICYNVWRITTEN" },
+    { POLICYTEMPLATE, "POLICYTEMPLATE" },
+    { POLICYAUTHORIZENV, "POLICYAUTHORIZENV" },
+    { POLICYACTION, "POLICYACTION" },
+};
+
+/** Get json object for a constant, if a variable is actually of type TPMI_POLICYTYPE.
+ *
+ * @param[in] in binary value of constant.
+ * @param[out] jso object with text representing the constant.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the constant is not of type TPMI_POLICYTYPE.
+ */
+TSS2_RC
+ifapi_json_TPMI_POLICYTYPE_serialize_txt(
+    const TPMI_POLICYTYPE in,
+    json_object **str_jso)
+{
+    size_t n = sizeof(serialize_TPMI_POLICYTYPE_tab) / sizeof(
+                   serialize_TPMI_POLICYTYPE_tab[0]);
+    size_t i;
+    for (i = 0; i < n; i++) {
+        if (serialize_TPMI_POLICYTYPE_tab[i].in == in) {
+            *str_jso = json_object_new_string(serialize_TPMI_POLICYTYPE_tab[i].name);
+            return_if_null(str_jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+            return TSS2_RC_SUCCESS;
+        }
+    }
+    return_error(TSS2_FAPI_RC_BAD_VALUE, "Undefined constant.");
+}
+
+/** Serialize TPMI_POLICYTYPE to json.
+ *
+ * @param[in] in constant to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the constant is not of type TPMI_POLICYTYPE.
+ */
+TSS2_RC
+ifapi_json_TPMI_POLICYTYPE_serialize(const TPMI_POLICYTYPE in,
+                                     json_object **jso)
+{
+    return ifapi_json_TPMI_POLICYTYPE_serialize_txt(in, jso);
+}
+
+/** Serialize value of type TPMS_POLICYSIGNED to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_POLICYSIGNED.
+ */
+TSS2_RC
+ifapi_json_TPMS_POLICYSIGNED_serialize(const TPMS_POLICYSIGNED *in,
+                                       json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    size_t cond_cnt = 0; /**< counter for conditional fields */
+
+    if (*jso == NULL)
+        *jso = json_object_new_object();
+
+    if (in->cpHashA.size != 0) {
+        jso2 = NULL;
+        r = ifapi_json_TPM2B_DIGEST_serialize(&in->cpHashA, &jso2);
+        return_if_error(r, "Serialize TPM2B_DIGEST");
+
+        json_object_object_add(*jso, "cpHashA", jso2);
+    }
+    if (in->policyRef.size != 0) {
+        jso2 = NULL;
+        r = ifapi_json_TPM2B_NONCE_serialize(&in->policyRef, &jso2);
+        return_if_error(r, "Serialize TPM2B_NONCE");
+
+        json_object_object_add(*jso, "policyRef", jso2);
+    }
+    if (in->keyPath && strlen(in->keyPath) > 0) {
+        jso2 = NULL;
+        cond_cnt++;
+        r = ifapi_json_char_serialize(in->keyPath, &jso2);
+        return_if_error(r, "Serialize char");
+
+        json_object_object_add(*jso, "keyPath", jso2);
+    }
+    if (in->keyPublic.type != 0) {
+        jso2 = NULL;
+        cond_cnt++;
+        r = ifapi_json_TPMT_PUBLIC_serialize(&in->keyPublic, &jso2);
+        return_if_error(r, "Serialize TPMT_PUBLIC");
+
+        json_object_object_add(*jso, "keyPublic", jso2);
+    }
+    if ((in->keyPEM) && strcmp(in->keyPEM, "") != 0) {
+        jso2 = NULL;
+        cond_cnt++;
+        r = ifapi_json_char_serialize(in->keyPEM, &jso2);
+        return_if_error(r, "Serialize char");
+
+        json_object_object_add(*jso, "keyPEM", jso2);
+    }
+    if (in->keyPEMhashAlg != 0) {
+        jso2 = NULL;
+        r = ifapi_json_TPMI_ALG_HASH_serialize(in->keyPEMhashAlg, &jso2);
+        return_if_error(r, "Serialize TPMI_ALG_HASH");
+
+        json_object_object_add(*jso, "keyPEMhashAlg", jso2);
+    }
+    /* Check whether only one conditional is used. */
+    if (cond_cnt != 1) {
+        return_error(TSS2_FAPI_RC_BAD_TEMPLATE,
+                     "Exactly one conditional is allowed for policy signed.");
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_POLICYSECRET to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_POLICYSECRET.
+ */
+TSS2_RC
+ifapi_json_TPMS_POLICYSECRET_serialize(const TPMS_POLICYSECRET *in,
+                                       json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    size_t cond_cnt = 0; /**< counter for conditional fields */
+
+    if (*jso == NULL)
+        *jso = json_object_new_object();
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_NONCE_serialize(&in->nonceTPM, &jso2);
+    return_if_error(r, "Serialize TPM2B_NONCE");
+
+    json_object_object_add(*jso, "nonceTPM", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_DIGEST_serialize(&in->cpHashA, &jso2);
+    return_if_error(r, "Serialize TPM2B_DIGEST");
+
+    json_object_object_add(*jso, "cpHashA", jso2);
+    if (in->policyRef.size != 0) {
+        jso2 = NULL;
+        r = ifapi_json_TPM2B_NONCE_serialize(&in->policyRef, &jso2);
+        return_if_error(r, "Serialize TPM2B_NONCE");
+
+        json_object_object_add(*jso, "policyRef", jso2);
+    }
+    jso2 = NULL;
+    r = ifapi_json_INT32_serialize(in->expiration, &jso2);
+    return_if_error(r, "Serialize INT32");
+
+    json_object_object_add(*jso, "expiration", jso2);
+    if ((in->objectPath) && strcmp(in->objectPath, "") != 0) {
+        jso2 = NULL;
+        cond_cnt++;
+        r = ifapi_json_char_serialize(in->objectPath, &jso2);
+        return_if_error(r, "Serialize char");
+
+        json_object_object_add(*jso, "objectPath", jso2);
+    }
+    if (in->objectName.size != 0) {
+        jso2 = NULL;
+        cond_cnt++;
+        r = ifapi_json_TPM2B_NAME_serialize(&in->objectName, &jso2);
+        return_if_error(r, "Serialize TPM2B_DIGEST");
+
+        json_object_object_add(*jso, "objectName", jso2);
+    }
+    if (cond_cnt != 1) {
+        return_error(TSS2_FAPI_RC_BAD_TEMPLATE,
+                     "Exactly one conditional needed for policy secret .");
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_POLICYLOCALITY to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_POLICYLOCALITY.
+ */
+TSS2_RC
+ifapi_json_TPMS_POLICYLOCALITY_serialize(const TPMS_POLICYLOCALITY *in,
+        json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+
+    if (*jso == NULL)
+        *jso = json_object_new_object();
+    jso2 = NULL;
+    r = ifapi_json_TPMA_LOCALITY_serialize(in->locality, &jso2);
+    return_if_error(r, "Serialize TPMA_LOCALITY");
+
+    json_object_object_add(*jso, "locality", jso2);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_POLICYNV to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_POLICYNV.
+ */
+TSS2_RC
+ifapi_json_TPMS_POLICYNV_serialize(const TPMS_POLICYNV *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    size_t cond_cnt = 0; /**< counter for conditional fields */
+
+    if (*jso == NULL)
+        *jso = json_object_new_object();
+    if ((in->nvPath) && strcmp(in->nvPath, "") != 0) {
+        jso2 = NULL;
+        cond_cnt++;
+        r = ifapi_json_char_serialize(in->nvPath, &jso2);
+        return_if_error(r, "Serialize char");
+
+        json_object_object_add(*jso, "nvPath", jso2);
+    }
+    if (in->nvIndex != 0) {
+        jso2 = NULL;
+        cond_cnt++;
+        r = ifapi_json_TPMI_RH_NV_INDEX_serialize(in->nvIndex, &jso2);
+        return_if_error(r, "Serialize TPMI_RH_NV_INDEX");
+
+        json_object_object_add(*jso, "nvIndex", jso2);
+    }
+
+    if (in->nvPublic.nvPublic.nvIndex) {
+        jso2 = NULL;
+        r = ifapi_json_TPM2B_NV_PUBLIC_serialize(&in->nvPublic, &jso2);
+        return_if_error(r, "Serialize TPM2B_NV_PUBLIC");
+
+        json_object_object_add(*jso, "nvPublic", jso2);
+    }
+
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_OPERAND_serialize(&in->operandB, &jso2);
+    return_if_error(r, "Serialize TPM2B_OPERAND");
+
+    json_object_object_add(*jso, "operandB", jso2);
+    if (in->offset != 0) {
+        jso2 = NULL;
+        r = ifapi_json_UINT16_serialize(in->offset, &jso2);
+        return_if_error(r, "Serialize UINT16");
+
+        json_object_object_add(*jso, "offset", jso2);
+    }
+    if (in->operation != 0) {
+        jso2 = NULL;
+        r = ifapi_json_TPM2_EO_serialize(in->operation, &jso2);
+        return_if_error(r, "Serialize TPM2_EO");
+
+        json_object_object_add(*jso, "operation", jso2);
+    }
+    /* Check whether only one conditional is used. */
+    if (cond_cnt != 1) {
+        return_error(TSS2_FAPI_RC_BAD_TEMPLATE,
+                     "Exactly one conditional is allowed for policy NV.");
+    }
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_POLICYCOUNTERTIMER to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_POLICYCOUNTERTIMER.
+ */
+TSS2_RC
+ifapi_json_TPMS_POLICYCOUNTERTIMER_serialize(const TPMS_POLICYCOUNTERTIMER *in,
+        json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+
+    if (*jso == NULL)
+        *jso = json_object_new_object();
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_OPERAND_serialize(&in->operandB, &jso2);
+    return_if_error(r, "Serialize TPM2B_OPERAND");
+
+    json_object_object_add(*jso, "operandB", jso2);
+    if (in->offset != 0) {
+        jso2 = NULL;
+        r = ifapi_json_UINT16_serialize(in->offset, &jso2);
+        return_if_error(r, "Serialize UINT16");
+
+        json_object_object_add(*jso, "offset", jso2);
+    }
+    jso2 = NULL;
+    r = ifapi_json_TPM2_EO_serialize(in->operation, &jso2);
+    return_if_error(r, "Serialize TPM2_EO");
+
+    json_object_object_add(*jso, "operation", jso2);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_POLICYCOMMANDCODE to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_POLICYCOMMANDCODE.
+ */
+TSS2_RC
+ifapi_json_TPMS_POLICYCOMMANDCODE_serialize(const TPMS_POLICYCOMMANDCODE *in,
+        json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+
+    if (*jso == NULL)
+        *jso = json_object_new_object();
+    jso2 = NULL;
+    r = ifapi_json_TPM2_CC_serialize(in->code, &jso2);
+    return_if_error(r, "Serialize TPM2_CC");
+
+    json_object_object_add(*jso, "code", jso2);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_POLICYPHYSICALPRESENCE to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_POLICYPHYSICALPRESENCE.
+ */
+TSS2_RC
+ifapi_json_TPMS_POLICYPHYSICALPRESENCE_serialize(const
+        TPMS_POLICYPHYSICALPRESENCE *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    if (*jso == NULL)
+        *jso = json_object_new_object();
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_POLICYCPHASH to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_POLICYCPHASH.
+ */
+TSS2_RC
+ifapi_json_TPMS_POLICYCPHASH_serialize(const TPMS_POLICYCPHASH *in,
+                                       json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+
+    if (*jso == NULL)
+        *jso = json_object_new_object();
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_DIGEST_serialize(&in->cpHash, &jso2);
+    return_if_error(r, "Serialize TPM2B_DIGEST");
+
+    json_object_object_add(*jso, "cpHash", jso2);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_POLICYNAMEHASH to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_POLICYNAMEHASH.
+ */
+TSS2_RC
+ifapi_json_TPMS_POLICYNAMEHASH_serialize(const TPMS_POLICYNAMEHASH *in,
+        json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2, *jso_ary;
+    size_t i;
+    size_t cond_cnt = 0; /**< counter for conditional fields */
+
+    if (*jso == NULL) {
+        *jso = json_object_new_object();
+        return_if_null(jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+    }
+
+    if (in->nameHash.size) {
+        jso2 = NULL;
+        cond_cnt++;
+        r = ifapi_json_TPM2B_DIGEST_serialize(&in->nameHash, &jso2);
+        return_if_error(r, "Serialize TPM2B_DIGEST");
+
+        json_object_object_add(*jso, "nameHash", jso2);
+
+        /* No need to serialize namePaths or objectNames from which would be
+           needed to compute nameHash. */
+        return TSS2_RC_SUCCESS;
+    }
+
+    jso_ary = json_object_new_array();
+    return_if_null(jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+    if (in->namePaths[0]) {
+        /* Pathnamees for objects are used */
+        cond_cnt++;
+        for (i = 0; i < in->count; i++) {
+            jso2 = NULL;
+            r = ifapi_json_char_serialize(in->namePaths[i], &jso2);
+            return_if_error(r, "Serialize char");
+
+            json_object_array_add(jso_ary, jso2);
+        }
+        json_object_object_add(*jso, "namePaths", jso_ary);
+    } else {
+        /* TPM object names are used */
+        for (i = 0; i < in->count; i++) {
+            jso2 = NULL;
+            r = ifapi_json_TPM2B_NAME_serialize(&in->objectNames[i], &jso2);
+            return_if_error(r, "Serialize TPM2B_NAME");
+            json_object_array_add(jso_ary, jso2);
+        }
+        json_object_object_add(*jso, "objectNames", jso_ary);
+    }
+    /* Check whether only one condition field found in policy. */
+    if (cond_cnt != 1) {
+        return_error(TSS2_FAPI_RC_BAD_TEMPLATE,
+                     "Exactly one conditional is allowed for policy name hash.");
+    }
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_POLICYDUPLICATIONSELECT to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_POLICYDUPLICATIONSELECT.
+ */
+TSS2_RC
+ifapi_json_TPMS_POLICYDUPLICATIONSELECT_serialize(const
+        TPMS_POLICYDUPLICATIONSELECT *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    size_t cond_cnt = 0; /**< counter for conditional fields */
+
+    if (*jso == NULL)
+        *jso = json_object_new_object();
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_NAME_serialize(&in->objectName, &jso2);
+    return_if_error(r, "Serialize TPM2B_NAME");
+
+    json_object_object_add(*jso, "objectName", jso2);
+
+    if (in->newParentName.size) {
+        cond_cnt++;
+        jso2 = NULL;
+        r = ifapi_json_TPM2B_NAME_serialize(&in->newParentName, &jso2);
+        return_if_error(r, "Serialize TPM2B_NAME");
+
+        json_object_object_add(*jso, "newParentName", jso2);
+    }
+    jso2 = NULL;
+    r = ifapi_json_TPMI_YES_NO_serialize(in->includeObject, &jso2);
+    return_if_error(r, "Serialize TPMI_YES_NO");
+
+    json_object_object_add(*jso, "includeObject", jso2);
+
+    if (in->newParentPath) {
+        jso2 = NULL;
+        cond_cnt++;
+        r = ifapi_json_char_serialize(in->newParentPath, &jso2);
+        return_if_error(r, "Serialize char");
+
+        json_object_object_add(*jso, "newParentPath", jso2);
+    }
+
+    if (in->newParentPublic.publicArea.type) {
+        jso2 = NULL;
+        r = ifapi_json_TPM2B_PUBLIC_serialize(&in->newParentPublic, &jso2);
+        return_if_error(r, "Serialize TPM2B_PUBLIC");
+
+        json_object_object_add(*jso, "newParentPublic", jso2);
+    }
+
+    /* Check whether only one condition field found in policy. */
+    if (cond_cnt != 1) {
+        return_error(TSS2_FAPI_RC_BAD_TEMPLATE,
+                     "Exactly one conditional is allowed for policy "
+                     "duplication select.");
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_POLICYAUTHORIZE to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_POLICYAUTHORIZE.
+ */
+TSS2_RC
+ifapi_json_TPMS_POLICYAUTHORIZE_serialize(const TPMS_POLICYAUTHORIZE *in,
+        json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    size_t cond_cnt = 0; /**< counter for conditional fields */
+
+    if (*jso == NULL)
+        *jso = json_object_new_object();
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_DIGEST_serialize(&in->approvedPolicy, &jso2);
+    return_if_error(r, "Serialize TPM2B_DIGEST");
+
+    json_object_object_add(*jso, "approvedPolicy", jso2);
+    if (in->policyRef.size != 0) {
+        jso2 = NULL;
+        r = ifapi_json_TPM2B_NONCE_serialize(&in->policyRef, &jso2);
+        return_if_error(r, "Serialize TPM2B_NONCE");
+
+        json_object_object_add(*jso, "policyRef", jso2);
+    }
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_NAME_serialize(&in->keyName, &jso2);
+    return_if_error(r, "Serialize TPM2B_NAME");
+
+    json_object_object_add(*jso, "keyName", jso2);
+    jso2 = NULL;
+    /*
+    r = ifapi_json_TPMT_TK_VERIFIED_serialize(&in->checkTicket, &jso2);
+    return_if_error(r, "Serialize TPMT_TK_VERIFIED");
+
+    json_object_object_add(*jso, "checkTicket", jso2);
+    jso2 = NULL;
+    */
+    if (in->keyPath) {
+        cond_cnt++;
+        r = ifapi_json_char_serialize(in->keyPath, &jso2);
+        return_if_error(r, "Serialize char");
+
+        json_object_object_add(*jso, "keyPath", jso2);
+    }
+    if (in->keyPublic.type != 0) {
+        jso2 = NULL;
+        cond_cnt++;
+        r = ifapi_json_TPMT_PUBLIC_serialize(&in->keyPublic, &jso2);
+        return_if_error(r, "Serialize TPMT_PUBLIC");
+
+        json_object_object_add(*jso, "keyPublic", jso2);
+    }
+    if ((in->keyPEM) && strcmp(in->keyPEM, "") != 0) {
+        jso2 = NULL;
+        r = ifapi_json_char_serialize(in->keyPEM, &jso2);
+        return_if_error(r, "Serialize char");
+
+        json_object_object_add(*jso, "keyPEM", jso2);
+    }
+    if (in->keyPEMhashAlg != 0) {
+        jso2 = NULL;
+        r = ifapi_json_TPMI_ALG_HASH_serialize(in->keyPEMhashAlg, &jso2);
+        return_if_error(r, "Serialize TPMI_ALG_HASH");
+
+        json_object_object_add(*jso, "keyPEMhashAlg", jso2);
+    }
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_POLICYAUTHVALUE to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_POLICYAUTHVALUE.
+ */
+TSS2_RC
+ifapi_json_TPMS_POLICYAUTHVALUE_serialize(const TPMS_POLICYAUTHVALUE *in,
+        json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    if (*jso == NULL)
+        *jso = json_object_new_object();
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_POLICYPASSWORD to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_POLICYPASSWORD.
+ */
+TSS2_RC
+ifapi_json_TPMS_POLICYPASSWORD_serialize(const TPMS_POLICYPASSWORD *in,
+        json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    if (*jso == NULL)
+        *jso = json_object_new_object();
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_POLICYNVWRITTEN to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_POLICYNVWRITTEN.
+ */
+TSS2_RC
+ifapi_json_TPMS_POLICYNVWRITTEN_serialize(const TPMS_POLICYNVWRITTEN *in,
+        json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+
+    if (*jso == NULL)
+        *jso = json_object_new_object();
+    jso2 = NULL;
+    r = ifapi_json_TPMI_YES_NO_serialize(in->writtenSet, &jso2);
+    return_if_error(r, "Serialize TPMI_YES_NO");
+
+    json_object_object_add(*jso, "writtenSet", jso2);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_POLICYTEMPLATE to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_POLICYTEMPLATE.
+ */
+TSS2_RC
+ifapi_json_TPMS_POLICYTEMPLATE_serialize(const TPMS_POLICYTEMPLATE *in,
+        json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    size_t cond_cnt = 0; /**< counter for conditional fields */
+
+    if (*jso == NULL)
+        *jso = json_object_new_object();
+    if (in->templateHash.size != 0) {
+        jso2 = NULL;
+        cond_cnt++;
+        r = ifapi_json_TPM2B_DIGEST_serialize(&in->templateHash, &jso2);
+        return_if_error(r, "Serialize TPM2B_DIGEST");
+
+        json_object_object_add(*jso, "templateHash", jso2);
+    }
+    if (in->templatePublic.size != 0) {
+        jso2 = NULL;
+        cond_cnt++;
+        r = ifapi_json_TPM2B_PUBLIC_serialize(&in->templatePublic, &jso2);
+        return_if_error(r, "Serialize TPM2B_PUBLIC");
+
+        json_object_object_add(*jso, "templatePublic", jso2);
+    }
+    if (in->templateName) {
+        jso2 = NULL;
+        cond_cnt++;
+        r = ifapi_json_char_serialize(in->templateName, &jso2);
+        return_if_error(r, "Serialize char");
+
+        json_object_object_add(*jso, "templateName", jso2);
+    }
+
+    /* Check whether only one condition field found in policy. */
+    if (cond_cnt != 1) {
+        return_error(TSS2_FAPI_RC_BAD_TEMPLATE,
+                     "Exactly one conditional is allowed for policy template.");
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_POLICYAUTHORIZENV to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_POLICYAUTHORIZENV.
+ */
+TSS2_RC
+ifapi_json_TPMS_POLICYAUTHORIZENV_serialize(const TPMS_POLICYAUTHORIZENV *in,
+        json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    size_t cond_cnt = 0; /**< counter for conditional fields */
+
+    if (*jso == NULL)
+        *jso = json_object_new_object();
+    jso2 = NULL;
+    if (in->nvPath) {
+        cond_cnt++;
+        r = ifapi_json_char_serialize(in->nvPath, &jso2);
+        return_if_error(r, "Serialize char");
+
+        json_object_object_add(*jso, "nvPath", jso2);
+    }
+    jso2 = NULL;
+    if (in->nvPublic.nvPublic.nvIndex > 0) {
+        cond_cnt++;
+        /* Template already instantiated */
+        r = ifapi_json_TPM2B_NV_PUBLIC_serialize(&in->nvPublic, &jso2);
+        return_if_error(r, "Serialize TPM2B_NV_PUBLIC");
+
+        json_object_object_add(*jso, "nvPublic", jso2);
+    }
+    if (cond_cnt != 1) {
+        return_error(TSS2_FAPI_RC_BAD_TEMPLATE,
+                     "Exactly one conditional needed for policy authorize nv .");
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_POLICYACTION to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_POLICYACTION.
+ */
+TSS2_RC
+ifapi_json_TPMS_POLICYACTION_serialize(const TPMS_POLICYACTION *in,
+                                       json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+
+    if (*jso == NULL)
+        *jso = json_object_new_object();
+    jso2 = NULL;
+    r = ifapi_json_char_serialize(in->action, &jso2);
+    return_if_error(r, "Serialize char");
+
+    json_object_object_add(*jso, "action", jso2);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_PCRVALUE to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_PCRVALUE.
+ */
+TSS2_RC
+ifapi_json_TPMS_PCRVALUE_serialize(const TPMS_PCRVALUE *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+
+    if (*jso == NULL)
+        *jso = json_object_new_object();
+    jso2 = NULL;
+    r = ifapi_json_UINT32_serialize(in->pcr, &jso2);
+    return_if_error(r, "Serialize UINT32");
+
+    json_object_object_add(*jso, "pcr", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPM2_ALG_ID_serialize(in->hashAlg, &jso2);
+    return_if_error(r, "Serialize TPM2_ALG_ID");
+
+    json_object_object_add(*jso, "hashAlg", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPMU_HA_serialize(&in->digest, in->hashAlg, &jso2);
+    return_if_error(r, "Serialize TPMU_HA");
+
+    json_object_object_add(*jso, "digest", jso2);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPML_PCRVALUES to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPML_PCRVALUES.
+ */
+TSS2_RC
+ifapi_json_TPML_PCRVALUES_serialize(const TPML_PCRVALUES *in, json_object **jso)
+{
+    TSS2_RC r;
+    json_object *jso2;
+
+    if (*jso == NULL)
+        *jso = json_object_new_array();
+    jso2 = NULL;
+    return_if_null(jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+    for (size_t i = 0; i < in->count; i++) {
+        jso2 = NULL;
+        r = ifapi_json_TPMS_PCRVALUE_serialize(&in->pcrs[i], &jso2);
+        return_if_error(r, "Serialize TPMS_PCRVALUE");
+
+        json_object_array_add(*jso, jso2);
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_POLICYPCR to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_POLICYPCR.
+ */
+TSS2_RC
+ifapi_json_TPMS_POLICYPCR_serialize(const TPMS_POLICYPCR *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    size_t cond_cnt = 0; /**< counter for conditional fields */
+
+    if (in->pcrs) {
+        if (*jso == NULL)
+            *jso = json_object_new_object();
+        jso2 = NULL;
+        cond_cnt++;
+        r = ifapi_json_TPML_PCRVALUES_serialize(in->pcrs, &jso2);
+        return_if_error(r, "Serialize TPML_PCRVALUES");
+
+        json_object_object_add(*jso, "pcrs", jso2);
+    }
+
+    if (in->currentPCRandBanks.count) {
+        jso2 = NULL;
+        cond_cnt++;
+        r = ifapi_json_TPML_PCR_SELECTION_serialize(&in->currentPCRandBanks, &jso2);
+        return_if_error(r, "Serialize TPML_PCR_SELECTION");
+
+        json_object_object_add(*jso, "currentPCRandBanks", jso2);
+    }
+
+    if (in->currentPCRs.sizeofSelect) {
+        jso2 = NULL;
+        cond_cnt++;
+        r = ifapi_json_TPMS_PCR_SELECT_serialize(&in->currentPCRs, &jso2);
+        return_if_error(r, "Serialize TPMS_PCR_SELECT");
+
+        json_object_object_add(*jso, "currentPCRs", jso2);
+    }
+    /* Check whether only one conditional is used. */
+    if (cond_cnt != 1) {
+        return_error(TSS2_FAPI_RC_BAD_TEMPLATE,
+                     "Exactly one conditional is allowed for policy pcr.");
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_POLICYAUTHORIZATION to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_POLICYAUTHORIZATION.
+ */
+TSS2_RC
+ifapi_json_TPMS_POLICYAUTHORIZATION_serialize(const TPMS_POLICYAUTHORIZATION
+        *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+
+    if (*jso == NULL)
+        *jso = json_object_new_object();
+    jso2 = NULL;
+    r = ifapi_json_char_serialize(in->type, &jso2);
+    return_if_error(r, "Serialize char");
+
+    json_object_object_add(*jso, "type", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPMT_PUBLIC_serialize(&in->key, &jso2);
+    return_if_error(r, "Serialize TPMT_PUBLIC");
+
+    json_object_object_add(*jso, "key", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_NONCE_serialize(&in->policyRef, &jso2);
+    return_if_error(r, "Serialize TPM2B_NONCE");
+
+    json_object_object_add(*jso, "policyRef", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPMT_SIGNATURE_serialize(&in->signature, &jso2);
+    return_if_error(r, "Serialize TPMT_SIGNATURE");
+
+    json_object_object_add(*jso, "signature", jso2);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPML_POLICYAUTHORIZATIONS to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPML_POLICYAUTHORIZATIONS.
+ */
+TSS2_RC
+ifapi_json_TPML_POLICYAUTHORIZATIONS_serialize(const TPML_POLICYAUTHORIZATIONS
+        *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+
+    if (*jso == NULL)
+        *jso = json_object_new_array();
+    jso2 = NULL;
+    return_if_null(jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+    jso2 = NULL;
+    for (size_t i = 0; i < in->count; i++) {
+        jso2 = NULL;
+        r = ifapi_json_TPMS_POLICYAUTHORIZATION_serialize(&in->authorizations[i],
+                &jso2);
+        return_if_error(r, "Serialize TPMS_POLICYAUTHORIZATION");
+
+        json_object_array_add(*jso, jso2);
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_POLICYBRANCH to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_POLICYBRANCH.
+ */
+TSS2_RC
+ifapi_json_TPMS_POLICYBRANCH_serialize(const TPMS_POLICYBRANCH *in,
+                                       json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+
+    if (*jso == NULL)
+        *jso = json_object_new_object();
+    jso2 = NULL;
+    r = ifapi_json_char_serialize(in->name, &jso2);
+    return_if_error(r, "Serialize char");
+
+    json_object_object_add(*jso, "name", jso2);
+    jso2 = NULL;
+    r = ifapi_json_char_serialize(in->description, &jso2);
+    return_if_error(r, "Serialize char");
+
+    json_object_object_add(*jso, "description", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPML_POLICYELEMENTS_serialize(in->policy, &jso2);
+    return_if_error(r, "Serialize TPML_POLICYELEMENTS");
+
+    json_object_object_add(*jso, "policy", jso2);
+    if (in->policyDigests.count > 0) {
+        jso2 = NULL;
+        r = ifapi_json_TPML_DIGEST_VALUES_serialize(&in->policyDigests, &jso2);
+        return_if_error(r, "Serialize TPML_DIGEST_VALUES");
+
+        json_object_object_add(*jso, "policyDigests", jso2);
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPML_POLICYBRANCHES to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPML_POLICYBRANCHES.
+ */
+TSS2_RC
+ifapi_json_TPML_POLICYBRANCHES_serialize(const TPML_POLICYBRANCHES *in,
+        json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+
+    if (*jso == NULL)
+        *jso = json_object_new_array();
+    jso2 = NULL;
+    return_if_null(jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+    jso2 = NULL;
+    for (size_t i = 0; i < in->count; i++) {
+        jso2 = NULL;
+        r = ifapi_json_TPMS_POLICYBRANCH_serialize(&in->authorizations[i], &jso2);
+        return_if_error(r, "Serialize TPMS_POLICYBRANCH");
+
+        json_object_array_add(*jso, jso2);
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_POLICYOR to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_POLICYOR.
+ */
+TSS2_RC
+ifapi_json_TPMS_POLICYOR_serialize(const TPMS_POLICYOR *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+
+    if (*jso == NULL)
+        *jso = json_object_new_object();
+    jso2 = NULL;
+    r = ifapi_json_TPML_POLICYBRANCHES_serialize(in->branches, &jso2);
+    return_if_error(r, "Serialize TPML_POLICYBRANCHES");
+
+    json_object_object_add(*jso, "branches", jso2);
+    return TSS2_RC_SUCCESS;
+}
+
+/**  Serialize a TPMU_POLICYELEMENT to json.
+ *
+ * This function expects the Bitfield to be encoded as unsigned int in host-endianess.
+ * @param[in] in the value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMU_POLICYELEMENT.
+ */
+TSS2_RC
+ifapi_json_TPMU_POLICYELEMENT_serialize(const TPMU_POLICYELEMENT *in,
+                                        UINT32 selector, json_object **jso)
+{
+    if (*jso == NULL)
+        *jso = json_object_new_object();
+    return_if_null(*jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+    switch (selector) {
+    case POLICYOR:
+        return ifapi_json_TPMS_POLICYOR_serialize(&in->PolicyOr, jso);
+    case POLICYSIGNED:
+        return ifapi_json_TPMS_POLICYSIGNED_serialize(&in->PolicySigned, jso);
+    case POLICYSECRET:
+        return ifapi_json_TPMS_POLICYSECRET_serialize(&in->PolicySecret, jso);
+    case POLICYPCR:
+        return ifapi_json_TPMS_POLICYPCR_serialize(&in->PolicyPCR, jso);
+    case POLICYLOCALITY:
+        return ifapi_json_TPMS_POLICYLOCALITY_serialize(&in->PolicyLocality, jso);
+    case POLICYNV:
+        return ifapi_json_TPMS_POLICYNV_serialize(&in->PolicyNV, jso);
+    case POLICYCOUNTERTIMER:
+        return ifapi_json_TPMS_POLICYCOUNTERTIMER_serialize(&in->PolicyCounterTimer,
+                jso);
+    case POLICYCOMMANDCODE:
+        return ifapi_json_TPMS_POLICYCOMMANDCODE_serialize(&in->PolicyCommandCode, jso);
+    case POLICYPHYSICALPRESENCE:
+        return ifapi_json_TPMS_POLICYPHYSICALPRESENCE_serialize(
+                   &in->PolicyPhysicalPresence, jso);
+    case POLICYCPHASH:
+        return ifapi_json_TPMS_POLICYCPHASH_serialize(&in->PolicyCpHash, jso);
+    case POLICYNAMEHASH:
+        return ifapi_json_TPMS_POLICYNAMEHASH_serialize(&in->PolicyNameHash, jso);
+    case POLICYDUPLICATIONSELECT:
+        return ifapi_json_TPMS_POLICYDUPLICATIONSELECT_serialize(
+                   &in->PolicyDuplicationSelect, jso);
+    case POLICYAUTHORIZE:
+        return ifapi_json_TPMS_POLICYAUTHORIZE_serialize(&in->PolicyAuthorize, jso);
+    case POLICYAUTHVALUE:
+        return ifapi_json_TPMS_POLICYAUTHVALUE_serialize(&in->PolicyAuthValue, jso);
+    case POLICYPASSWORD:
+        return ifapi_json_TPMS_POLICYPASSWORD_serialize(&in->PolicyPassword, jso);
+    case POLICYNVWRITTEN:
+        return ifapi_json_TPMS_POLICYNVWRITTEN_serialize(&in->PolicyNvWritten, jso);
+    case POLICYTEMPLATE:
+        return ifapi_json_TPMS_POLICYTEMPLATE_serialize(&in->PolicyTemplate, jso);
+    case POLICYAUTHORIZENV:
+        return ifapi_json_TPMS_POLICYAUTHORIZENV_serialize(&in->PolicyAuthorizeNv, jso);
+    case POLICYACTION:
+        return ifapi_json_TPMS_POLICYACTION_serialize(&in->PolicyAction, jso);
+    default:
+        LOG_ERROR("\nSelector %"PRIx32 " did not match", selector);
+        return TSS2_SYS_RC_BAD_VALUE;
+    };
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMT_POLICYELEMENT to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMT_POLICYELEMENT.
+ */
+TSS2_RC
+ifapi_json_TPMT_POLICYELEMENT_serialize(const TPMT_POLICYELEMENT *in,
+                                        json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+
+    if (*jso == NULL)
+        *jso = json_object_new_object();
+    jso2 = NULL;
+    r = ifapi_json_TPMI_POLICYTYPE_serialize(in->type, &jso2);
+    return_if_error(r, "Serialize TPMI_POLICYTYPE");
+
+    json_object_object_add(*jso, "type", jso2);
+
+    if (in->policyDigests.count > 0) {
+        jso2 = NULL;
+        r = ifapi_json_TPML_DIGEST_VALUES_serialize(&in->policyDigests, &jso2);
+        return_if_error(r, "Serialize TPML_DIGEST_VALUES");
+
+        json_object_object_add(*jso, "policyDigests", jso2);
+    }
+    r = ifapi_json_TPMU_POLICYELEMENT_serialize(&in->element, in->type, jso);
+    return_if_error(r, "Serialize TPMU_POLICYELEMENT");
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPML_POLICYELEMENTS to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPML_POLICYELEMENTS.
+ */
+TSS2_RC
+ifapi_json_TPML_POLICYELEMENTS_serialize(const TPML_POLICYELEMENTS *in,
+        json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+
+    if (*jso == NULL)
+        *jso = json_object_new_array();
+    jso2 = NULL;
+    return_if_null(jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+    for (size_t i = 0; i < in->count; i++) {
+        jso2 = NULL;
+        r = ifapi_json_TPMT_POLICYELEMENT_serialize(&in->elements[i], &jso2);
+        return_if_error(r, "Serialize TPMT_POLICYELEMENT");
+
+        json_object_array_add(*jso, jso2);
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_POLICY_HARNESS to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_POLICY_HARNESS.
+ */
+TSS2_RC
+ifapi_json_TPMS_POLICY_HARNESS_serialize(const TPMS_POLICY_HARNESS *in,
+        json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+
+    if (*jso == NULL)
+        *jso = json_object_new_object();
+    jso2 = NULL;
+    r = ifapi_json_char_serialize(in->description, &jso2);
+    return_if_error(r, "Serialize char");
+
+    json_object_object_add(*jso, "description", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPML_DIGEST_VALUES_serialize(&in->policyDigests, &jso2);
+    return_if_error(r, "Serialize TPML_DIGEST_VALUES");
+
+    json_object_object_add(*jso, "policyDigests", jso2);
+    if (in->policyAuthorizations) {
+        jso2 = NULL;
+        r = ifapi_json_TPML_POLICYAUTHORIZATIONS_serialize(in->policyAuthorizations,
+                &jso2);
+        return_if_error(r, "Serialize TPML_POLICYAUTHORIZATIONS");
+
+        json_object_object_add(*jso, "policyAuthorizations", jso2);
+    }
+    jso2 = NULL;
+    r = ifapi_json_TPML_POLICYELEMENTS_serialize(in->policy, &jso2);
+    return_if_error(r, "Serialize TPML_POLICYELEMENTS");
+
+    json_object_object_add(*jso, "policy", jso2);
+    return TSS2_RC_SUCCESS;
+}
diff --git a/src/tss2-fapi/ifapi_policy_json_serialize.h b/src/tss2-fapi/ifapi_policy_json_serialize.h
new file mode 100644
index 0000000..274b503
--- /dev/null
+++ b/src/tss2-fapi/ifapi_policy_json_serialize.h
@@ -0,0 +1,137 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ ******************************************************************************/
+#ifndef IFAPI_POLICY_JSON_SERIALIZE_H
+#define IFAPI_POLICY_JSON_SERIALIZE_H
+
+#include <stdbool.h>
+#include <json-c/json.h>
+#include <json-c/json_util.h>
+
+#include "tss2_tpm2_types.h"
+#include "fapi_int.h"
+
+TSS2_RC
+ifapi_json_TPMI_POLICYTYPE_serialize(const TPMI_POLICYTYPE in,
+                                     json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMI_POLICYTYPE_serialize_txt(const TPMI_POLICYTYPE in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_POLICYSIGNED_serialize(const TPMS_POLICYSIGNED *in,
+                                       json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_POLICYSECRET_serialize(const TPMS_POLICYSECRET *in,
+                                       json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_POLICYLOCALITY_serialize(const TPMS_POLICYLOCALITY *in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_POLICYNV_serialize(const TPMS_POLICYNV *in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_POLICYCOUNTERTIMER_serialize(const TPMS_POLICYCOUNTERTIMER *in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_POLICYCOMMANDCODE_serialize(const TPMS_POLICYCOMMANDCODE *in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_POLICYPHYSICALPRESENCE_serialize(const
+        TPMS_POLICYPHYSICALPRESENCE *in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_POLICYCPHASH_serialize(const TPMS_POLICYCPHASH *in,
+                                       json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_POLICYNAMEHASH_serialize(const TPMS_POLICYNAMEHASH *in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_POLICYDUPLICATIONSELECT_serialize(const
+        TPMS_POLICYDUPLICATIONSELECT *in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_POLICYAUTHORIZE_serialize(const TPMS_POLICYAUTHORIZE *in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_POLICYAUTHVALUE_serialize(const TPMS_POLICYAUTHVALUE *in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_POLICYPASSWORD_serialize(const TPMS_POLICYPASSWORD *in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_POLICYNVWRITTEN_serialize(const TPMS_POLICYNVWRITTEN *in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_POLICYTEMPLATE_serialize(const TPMS_POLICYTEMPLATE *in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_POLICYAUTHORIZENV_serialize(const TPMS_POLICYAUTHORIZENV *in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_POLICYACTION_serialize(const TPMS_POLICYACTION *in,
+                                       json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_PCRVALUE_serialize(const TPMS_PCRVALUE *in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPML_PCRVALUES_serialize(const TPML_PCRVALUES *in,
+                                    json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_POLICYPCR_serialize(const TPMS_POLICYPCR *in,
+                                    json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_POLICYAUTHORIZATION_serialize(const TPMS_POLICYAUTHORIZATION
+        *in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPML_POLICYAUTHORIZATIONS_serialize(const TPML_POLICYAUTHORIZATIONS
+        *in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_POLICYBRANCH_serialize(const TPMS_POLICYBRANCH *in,
+                                       json_object **jso);
+
+TSS2_RC
+ifapi_json_TPML_POLICYBRANCHES_serialize(const TPML_POLICYBRANCHES *in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_POLICYOR_serialize(const TPMS_POLICYOR *in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMU_POLICYELEMENT_serialize(const TPMU_POLICYELEMENT *in,
+                                        UINT32 selector, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMT_POLICYELEMENT_serialize(const TPMT_POLICYELEMENT *in,
+                                        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPML_POLICYELEMENTS_serialize(const TPML_POLICYELEMENTS *in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_POLICY_HARNESS_serialize(const TPMS_POLICY_HARNESS *in,
+        json_object **jso);
+
+#endif /* IFAPI_POLICY_JSON_SERIALIZE_H */
diff --git a/src/tss2-fapi/ifapi_policy_store.c b/src/tss2-fapi/ifapi_policy_store.c
new file mode 100644
index 0000000..354f899
--- /dev/null
+++ b/src/tss2-fapi/ifapi_policy_store.c
@@ -0,0 +1,282 @@
+/* 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>
+#include <dirent.h>
+#endif
+
+#include "ifapi_io.h"
+#include "ifapi_helpers.h"
+#include "ifapi_policy_types.h"
+#include "ifapi_policy_store.h"
+#include "ifapi_macros.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+#include "ifapi_policy_json_deserialize.h"
+#include "ifapi_policy_json_serialize.h"
+
+/** Compute absolute path of policy for IO.
+ */
+static TSS2_RC
+policy_rel_path_to_abs_path(
+    IFAPI_POLICY_STORE *pstore,
+    const char *rel_path,
+    char **abs_path)
+{
+    TSS2_RC r;
+
+    if (ifapi_path_type_p(rel_path, IFAPI_POLICY_PATH)) {
+        r = ifapi_asprintf(abs_path, "%s%s%s.json", pstore->policydir,
+                           IFAPI_FILE_DELIM, rel_path);
+    } else {
+        r = ifapi_asprintf(abs_path, "%s%s%s%s%s.json", pstore->policydir,
+                           IFAPI_FILE_DELIM, IFAPI_POLICY_PATH, IFAPI_FILE_DELIM, rel_path);
+
+    }
+    return_if_error(r, "Create policy file name.");
+    return r;
+}
+/** Remove file storing a policy object.
+ *
+ * @parm[in] pstore The policy directory.
+ * @parm[in] path The relative name of the object be removed.
+ * @retval TSS2_RC_SUCCESS On success.
+ * @retval TSS2_FAPI_RC_MEMORY: If memory could not be allocated.
+ * @retval TSS2_FAPI_RC_PATH_NOT_FOUND If no file is found in policy store.
+ * @retval TSS2_FAPI_RC_IO_ERROR If the file can't be removed.
+ */
+TSS2_RC
+ifapi_policy_delete(
+     IFAPI_POLICY_STORE *pstore,
+     char *path)
+{
+    TSS2_RC r;
+    char *abs_path = NULL;
+
+    /* Convert relative path to abolute path in policy store */
+    r = policy_rel_path_to_abs_path(pstore, path, &abs_path);
+    goto_if_error2(r, "Path %s could not be created.", cleanup, path);
+
+    if (!ifapi_io_path_exists(abs_path)) {
+        goto_error(r, TSS2_FAPI_RC_PATH_NOT_FOUND,
+                   "Policy %s not found.", cleanup, path);
+    }
+
+    if (remove(abs_path) != 0) {
+        LOG_WARNING("File: %s can't be deleted.", abs_path);
+    }
+
+ cleanup:
+     SAFE_FREE(abs_path);
+     return r;
+}
+
+/** Store policy store parameters in the policy store context.
+ *
+ * Also the user directory will be created if it does not exist.
+ *
+ * @parm[out] policy store The keystore to be initialized.
+ * @parm[in] config_policydir The configured policy directory.
+ * @parm[in] config_userdir The configured user directory.
+ * @retval TSS2_RC_SUCCESS If the keystore can be initialized.
+ * @retval TSS2_FAPI_RC_IO_ERROR If the policy store can't be
+ *         initialized.
+ * @retval TSS2_FAPI_RC_MEMORY: if memory could not be allocated.
+ */
+TSS2_RC
+ifapi_policy_store_initialize(
+    IFAPI_POLICY_STORE *pstore,
+    const char *config_policydir)
+{
+    TSS2_RC r;
+    char *policy_dir = NULL;
+
+    memset(pstore, 0, sizeof(IFAPI_POLICY_STORE));
+    strdup_check(pstore->policydir, config_policydir, r, error);
+
+    r = ifapi_asprintf(&policy_dir, "%s%s%s", config_policydir, IFAPI_FILE_DELIM,
+                       IFAPI_POLICY_PATH);
+    goto_if_error(r, "Out of memory.", error);
+
+    r = ifapi_io_check_create_dir(policy_dir);
+    goto_if_error2(r, "Policy directory %s can't be created.", error, policy_dir);
+
+    SAFE_FREE(policy_dir);
+    return TSS2_RC_SUCCESS;
+
+ error:
+    SAFE_FREE(policy_dir);
+    return r;
+}
+
+/** Start loading FAPI policy from policy store.
+ *
+ * Keys objects, NV objects, and hierarchies can be loaded.
+ *
+ * @parm[in] keystore The key directories and default profile.
+ * @parm[in] io  The input/output context being used for file I/O.
+ * @parm[in] path The relative path of the object. For keys the path will
+ *           expanded if possible.
+ * @retval TSS2_RC_SUCCESS If the object can be read.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if an I/O error was encountered.
+ * @retval TSS2_FAPI_RC_PATH_NOT_FOUND if the file does not exist.
+ * @retval TSS2_FAPI_RC_MEMORY: if memory could not be allocated to hold the read data.
+ */
+TSS2_RC
+ifapi_policy_store_load_async(
+    IFAPI_POLICY_STORE *pstore,
+    IFAPI_IO *io,
+    const char *path)
+{
+    TSS2_RC r;
+    char *abs_path = NULL;
+
+    LOG_TRACE("Load policy: %s", path);
+
+    /* Free old input buffer if buffer exists */
+    SAFE_FREE(io->char_rbuffer);
+
+    /* Convert relative path to abolute path in keystore */
+    r = policy_rel_path_to_abs_path(pstore, path, &abs_path);
+    goto_if_error2(r, "Object %s not found.", cleanup, path);
+
+    /* Prepare read operation */
+    r = ifapi_io_read_async(io, abs_path);
+
+ cleanup:
+     SAFE_FREE(abs_path);
+     return r;
+}
+
+/** Finish loading FAPI policy from policy store.
+ *
+ *
+ * This function needs to be called repeatedly until it does not return TSS2_FAPI_RC_TRY_AGAIN.
+ *
+ * @parm[in] pstore The policy context with the policy directory.
+ * @param [in, out] io The input/output context being used for file I/O.
+ * @parm[in] policy The caller allocated policy which will loaded from policy store.
+ * @retval TSS2_RC_SUCCESS After successfully loading the object.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if an I/O error was encountered; such as the file was not found.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet complete.
+ */
+TSS2_RC
+ifapi_policy_store_load_finish(
+    IFAPI_POLICY_STORE *pstore,
+    IFAPI_IO *io,
+    TPMS_POLICY_HARNESS *policy)
+{
+    TSS2_RC r;
+    json_object *jso = NULL;
+    uint8_t  *buffer = NULL;
+    /* ptore parameter is used to be prepared if transmission of state information
+       between async and finish will be necessary in future extensions. */
+    (void)pstore;
+
+    r = ifapi_io_read_finish(io, &buffer, NULL);
+    return_try_again(r);
+    return_if_error(r, "keystore read_finish failed");
+
+    /* If json objects can't be parse the object store is corrupted */
+    jso = json_tokener_parse((char *)buffer);
+    SAFE_FREE(buffer);
+    return_if_null(jso, "Policy store is corrupted (Json error).", TSS2_FAPI_RC_GENERAL_FAILURE);
+
+    r = ifapi_json_TPMS_POLICY_HARNESS_deserialize(jso, policy);
+    goto_if_error(r, "Deserialize policy", cleanup);
+
+cleanup:
+    SAFE_FREE(buffer);
+    if (jso)
+        json_object_put(jso);
+    LOG_TRACE("Return %x", r);
+    return r;
+
+}
+
+/**  Start writing FAPI object to the key store.
+ *
+ * The relative path will be expanded, if the default policy directory (/policy)
+ * is not part of the path.
+ *
+ * @parm[in] pstore The policy context with the policy directory.
+ * @parm[in] io  The input/output context being used for file I/O.
+ * @parm[in] path The relative path of the policy.
+ * @parm[in] policy The policy to be written to the policy store.
+ * @retval TSS2_RC_SUCCESS If the policy is written successfully.
+ * @retval TSS2_FAPI_RC_IO_ERROR: If an I/O error was encountered;
+ * @retval TSS2_FAPI_RC_MEMORY: If memory could not be allocated to hold the output data.
+ */
+TSS2_RC
+ifapi_policy_store_store_async(
+    IFAPI_POLICY_STORE *pstore,
+    IFAPI_IO *io,
+    const char *path,
+    const TPMS_POLICY_HARNESS *policy)
+{
+    TSS2_RC r;
+    char *jso_string = NULL;
+    json_object *jso = NULL;
+    char *abs_path = NULL;
+
+    LOG_TRACE("Store policy: %s", path);
+
+    /* Convert relative path to abolute path in the policy store */
+    r = policy_rel_path_to_abs_path(pstore, path, &abs_path);
+    goto_if_error2(r, "Path %s could not be created.", cleanup, path);
+
+    /* Generate JSON string to be written to store */
+    r = ifapi_json_TPMS_POLICY_HARNESS_serialize(policy, &jso);
+    goto_if_error2(r, "Policy %s could not be serialized.", cleanup, path);
+
+    jso_string = strdup(json_object_to_json_string_ext(jso,
+                                                       JSON_C_TO_STRING_PRETTY));
+    goto_if_null2(jso_string, "Converting json to string", r, TSS2_FAPI_RC_MEMORY,
+                  cleanup);
+
+    /* Start writing the json string to disk */
+    r = ifapi_io_write_async(io, abs_path, (uint8_t *) jso_string, strlen(jso_string));
+    free(jso_string);
+    goto_if_error(r, "write_async failed", cleanup);
+
+ cleanup:
+    if (jso)
+        json_object_put(jso);
+    SAFE_FREE(abs_path);
+    return r;
+}
+
+/** Finish writing a FAPI policy object to the policy store.
+ *
+ * This function needs to be called repeatedly until it does not return TSS2_FAPI_RC_TRY_AGAIN.
+ *
+ * @param [in, out] io The input/output context being used for file I/O.
+ * @retval TSS2_RC_SUCCESS: if the function call was a success.
+ * @retval TSS2_FAPI_RC_IO_ERROR: if an I/O error was encountered; such as the file was not found.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet complete.
+           Call this function again later.
+ */
+TSS2_RC
+ifapi_policy_store_store_finish(
+    IFAPI_POLICY_STORE *pstore,
+    IFAPI_IO *io)
+{
+    TSS2_RC r;
+
+    /* Pstore parameter is used to be prepared if transmission of state infomation
+       between async and finish will be necessary in future extensions. */
+    (void)pstore;
+    /* Finish writing the policy */
+    r = ifapi_io_write_finish(io);
+    return_try_again(r);
+
+    LOG_TRACE("Return %x", r);
+    return_if_error(r, "read_finish failed");
+
+    return TSS2_RC_SUCCESS;
+}
diff --git a/src/tss2-fapi/ifapi_policy_store.h b/src/tss2-fapi/ifapi_policy_store.h
new file mode 100644
index 0000000..b5b225f
--- /dev/null
+++ b/src/tss2-fapi/ifapi_policy_store.h
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ ******************************************************************************/
+
+#ifndef IFAPI_POLICY_STORE_H
+#define IFAPI_POLICY_STORE_H
+
+#include <stdlib.h>
+
+#include "tss2_common.h"
+#include "tss2_tpm2_types.h"
+#include "fapi_types.h"
+#include "ifapi_policy_types.h"
+
+typedef struct IFAPI_POLICY_STORE {
+    char *policydir;
+} IFAPI_POLICY_STORE;
+
+TSS2_RC
+ifapi_policy_delete(
+     IFAPI_POLICY_STORE *pstore,
+     char *path);
+
+TSS2_RC
+ifapi_policy_store_initialize(
+    IFAPI_POLICY_STORE *pstore,
+    const char *config_policydir);
+
+TSS2_RC
+ifapi_policy_store_load_async(
+    IFAPI_POLICY_STORE *pstore,
+    IFAPI_IO *io,
+    const char *path);
+
+TSS2_RC
+ifapi_policy_store_load_finish(
+    IFAPI_POLICY_STORE *pstore,
+    IFAPI_IO *io,
+    TPMS_POLICY_HARNESS *policy);
+
+TSS2_RC
+ifapi_policy_store_store_async(
+    IFAPI_POLICY_STORE *pstore,
+    IFAPI_IO *io,
+    const char *path,
+    const TPMS_POLICY_HARNESS *policy);
+
+TSS2_RC
+ifapi_policy_store_store_finish(
+    IFAPI_POLICY_STORE *pstore,
+    IFAPI_IO *io);
+
+#endif /* IFAPI_POLICY_STORE_H */
diff --git a/src/tss2-fapi/ifapi_policy_types.h b/src/tss2-fapi/ifapi_policy_types.h
new file mode 100644
index 0000000..55ecd37
--- /dev/null
+++ b/src/tss2-fapi/ifapi_policy_types.h
@@ -0,0 +1,292 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ ******************************************************************************/
+#ifndef IFAPI_POLICY_TYPES_H
+#define IFAPI_POLICY_TYPES_H
+
+#include "tss2_tpm2_types.h"
+
+typedef UINT32 TPMI_POLICYTYPE;
+#define POLICYELEMENTS                 0
+#define POLICYOR                       1    /**< None */
+#define POLICYSIGNED                   2    /**< None */
+#define POLICYSECRET                   3    /**< None */
+#define POLICYPCR                      4    /**< None */
+#define POLICYLOCALITY                 5    /**< None */
+#define POLICYNV                       6    /**< None */
+#define POLICYCOUNTERTIMER             7    /**< None */
+#define POLICYCOMMANDCODE              8    /**< None */
+#define POLICYPHYSICALPRESENCE         9    /**< None */
+#define POLICYCPHASH                   10    /**< None */
+#define POLICYNAMEHASH                 11    /**< None */
+#define POLICYDUPLICATIONSELECT        12    /**< None */
+#define POLICYAUTHORIZE                13    /**< None */
+#define POLICYAUTHVALUE                14    /**< None */
+#define POLICYPASSWORD                 15    /**< None */
+#define POLICYNVWRITTEN                16    /**< None */
+#define POLICYTEMPLATE                 17    /**< None */
+#define POLICYAUTHORIZENV              18    /**< None */
+#define POLICYACTION                   19    /**< None */
+
+/** Policy type TPMS_POLICYSIGNED
+ */
+typedef struct {
+    TPM2B_NONCE                                nonceTPM;    /**< This is a value returned by TPM2_StartAuthSession and thus n */
+    TPM2B_DIGEST                                cpHashA;    /**< This value will be automatically generated by the FAPI. */
+    TPM2B_NONCE                               policyRef;    /**< Default is zero-length */
+    INT32                                    expiration;    /**< This value will be -1 by the FAPI */
+    TPMT_SIGNATURE                                 auth;    /**< This value is generated from at runtime via a callback. */
+    TPM2B_NAME                                publicKey;    /**< This will be automatically generated from keyPath, keyPublic */
+    char                                       *keyPath;    /**< A reference to a key inside the FAPI keystore */
+    TPMT_PUBLIC                               keyPublic;    /**< None */
+    char                                        *keyPEM;    /**< <p>The TPM2B_NAME is constructed with a TPMT_PUBLIC from this */
+    TPMI_ALG_HASH                         keyPEMhashAlg;    /**< (optional) Default = SHA256 */
+    TPMT_SIGNATURE                        signature_tpm;
+} TPMS_POLICYSIGNED;
+
+/** Policy type TPMS_POLICYSECRET
+ */
+typedef struct {
+    TPM2B_NONCE                                nonceTPM;    /**< None */
+    TPM2B_DIGEST                                cpHashA;    /**< None */
+    TPM2B_NONCE                               policyRef;    /**< Default is zero length */
+    INT32                                    expiration;    /**< None */
+    char                                    *objectPath;    /**< Path of the object */
+    TPM2B_NAME                               objectName;    /**< Public name of the object */
+} TPMS_POLICYSECRET;
+
+/** Policy type TPMS_POLICYLOCALITY
+ */
+typedef struct {
+    TPMA_LOCALITY                              locality;    /**< None */
+} TPMS_POLICYLOCALITY;
+
+/** Policy type TPMS_POLICYNV
+ */
+typedef struct {
+    char                                        *nvPath;    /**< None */
+    TPMI_RH_NV_INDEX                            nvIndex;    /**< None */
+    TPM2B_NV_PUBLIC                            nvPublic;    /**< None */
+    TPMI_RH_NV_AUTH                          authHandle;    /**< This is determined by FAPI at runtime. */
+    TPM2B_OPERAND                              operandB;    /**< None */
+    UINT16                                       offset;    /**< Default value is 0 */
+    TPM2_EO                                   operation;    /**< Default value is EQUAL */
+} TPMS_POLICYNV;
+
+/** Policy type TPMS_POLICYCOUNTERTIMER
+ */
+typedef struct {
+    TPM2B_OPERAND                              operandB;    /**< None */
+    UINT16                                       offset;    /**< Default is 0 */
+    TPM2_EO                                   operation;    /**< None */
+} TPMS_POLICYCOUNTERTIMER;
+
+/** Policy type TPMS_POLICYCOMMANDCODE
+ */
+typedef struct {
+    TPM2_CC                                        code;    /**< None */
+} TPMS_POLICYCOMMANDCODE;
+
+/** Policy type TPMS_POLICYPHYSICALPRESENCE
+ */
+typedef struct {
+} TPMS_POLICYPHYSICALPRESENCE;
+
+/** Policy type TPMS_POLICYCPHASH
+ */
+typedef struct {
+    TPM2B_DIGEST                                 cpHash;    /**< None */
+} TPMS_POLICYCPHASH;
+
+/** Policy type TPMS_POLICYNAMEHASH
+ */
+typedef struct {
+    UINT32                                          count;    /**< Computed during instantiation */
+    UINT32                                              i;    /**< Temporary index for policy calculation */
+    TPM2B_NAME                             objectNames[3];    /**< computed during instantiation (if not initialized) */
+    char                                    *namePaths[3];    /**< Paths of objects used for retrieving the names */
+    TPM2B_DIGEST                                 nameHash;    /**< computed during policy calculation */
+} TPMS_POLICYNAMEHASH;
+
+/** Policy type TPMS_POLICYDUPLICATIONSELECT
+ */
+typedef struct {
+    TPM2B_NAME                               objectName;    /**< Will not be used (see includeObject) */
+    TPM2B_NAME                            newParentName;    /**< Automatically calculated */
+    TPMI_YES_NO                           includeObject;    /**< Always NO */
+    char                                 *newParentPath;    /**< None */
+    TPM2B_PUBLIC                        newParentPublic;    /**< None */
+} TPMS_POLICYDUPLICATIONSELECT;
+
+/** Policy type TPMS_POLICYAUTHORIZATION
+ */
+typedef struct {
+    char                                          *type;    /**< tpm */
+    TPMT_PUBLIC                                     key;    /**< Selector of the algorithm used for the signature and the pub */
+    TPM2B_NONCE                               policyRef;    /**< None */
+    TPMT_SIGNATURE                            signature;    /**< None */
+} TPMS_POLICYAUTHORIZATION;
+
+typedef struct policy_object_node POLICY_OBJECT;
+
+/** Policy type TPMS_POLICYAUTHORIZE
+ */
+typedef struct {
+    TPM2B_DIGEST                         approvedPolicy;    /**< None */
+    TPM2B_NONCE                               policyRef;    /**< None */
+    TPM2B_NAME                                  keyName;    /**< Not exposed in JSON, but generated from keyPath, keyPublic o */
+    TPMT_TK_VERIFIED                        checkTicket;    /**< None */
+    char                                       *keyPath;    /**< A reference to a key inside the FAPI keystore */
+    TPMT_PUBLIC                               keyPublic;    /**< None */
+    char                                        *keyPEM;    /**< <p> everyone in favour<br /> The TPM2B_NAME is constructed w */
+    TPMI_ALG_HASH                         keyPEMhashAlg;    /**< (optional) Default = SHA256 */
+    POLICY_OBJECT                          *policy_list;
+    TPMS_POLICYAUTHORIZATION             *authorization;
+    TPMT_SIGNATURE                            signature;
+} TPMS_POLICYAUTHORIZE;
+
+/** Policy type TPMS_POLICYAUTHVALUE
+ */
+typedef struct {
+} TPMS_POLICYAUTHVALUE;
+
+/** Policy type TPMS_POLICYPASSWORD
+ */
+typedef struct {
+} TPMS_POLICYPASSWORD;
+
+/** Policy type TPMS_POLICYNVWRITTEN
+ */
+typedef struct {
+    TPMI_YES_NO                              writtenSet;    /**< Default is yes */
+} TPMS_POLICYNVWRITTEN;
+
+/** Policy type TPMS_POLICYTEMPLATE
+ */
+typedef struct {
+    TPM2B_DIGEST                           templateHash;    /**< None */
+    TPM2B_PUBLIC                         templatePublic;    /**< None */
+    char                                  *templateName;    /**< None */
+} TPMS_POLICYTEMPLATE;
+
+/** Policy type TPMS_POLICYAUTHORIZENV
+ */
+typedef struct {
+    char                                        *nvPath;    /**< None */
+    TPM2B_NV_PUBLIC                            nvPublic;    /**< None */
+    TPM2B_DIGEST                                 policy;    /**< Policy Digest */
+    TPMT_HA                                   nv_policy;    /**< Policy stored in NV ram */
+    uint8_t                               *policy_buffer;
+} TPMS_POLICYAUTHORIZENV;
+
+/** Policy type TPMS_POLICYACTION
+ */
+typedef struct {
+    char                                        *action;    /**< The FAPI will return a string representation of the JSON sub */
+} TPMS_POLICYACTION;
+
+/** Policy type TPMS_PCRVALUE
+ */
+typedef struct {
+    UINT32                                          pcr;    /**< None */
+    TPM2_ALG_ID                                 hashAlg;    /**< None */
+    TPMU_HA                                      digest;    /**< None */
+} TPMS_PCRVALUE;
+
+/** Policy type TPML_PCRVALUES
+ */
+typedef struct TPML_PCRVALUES {
+    UINT32                                        count;    /**< None */
+    TPMS_PCRVALUE                                pcrs[];    /**< Array of pcr values */
+} TPML_PCRVALUES;
+
+/** Policy type TPMS_POLICYPCR
+ */
+typedef struct {
+    struct TPML_PCRVALUES                         *pcrs;    /**< None */
+    TPMS_PCR_SELECT                         currentPCRs;    /**< The hashAlg are inferred from */
+    TPML_PCR_SELECTION               currentPCRandBanks;    /**< Complete selection with banks  */
+} TPMS_POLICYPCR;
+
+/** Policy type TPML_POLICYAUTHORIZATIONS
+ */
+typedef struct TPML_POLICYAUTHORIZATIONS {
+    UINT32                                        count;    /**< None */
+    TPMS_POLICYAUTHORIZATION             authorizations[];    /**< Array of policy elements */
+} TPML_POLICYAUTHORIZATIONS;
+
+typedef struct TPML_POLICYELEMENTS TPML_POLICYELEMENTS;
+
+/** Policy type TPMS_POLICYBRANCH
+ */
+typedef struct {
+    char                                          *name;    /**< None */
+    char                                   *description;    /**< None */
+    TPML_DIGEST_VALUES                    policyDigests;
+    struct TPML_POLICYELEMENTS                   *policy;    /**< Array of policy elements */
+} TPMS_POLICYBRANCH;
+
+/** Policy type TPML_POLICYBRANCHES
+ */
+typedef struct TPML_POLICYBRANCHES {
+    UINT32                                        count;    /**< None */
+    TPMS_POLICYBRANCH                    authorizations[];    /**< Array of policy elements */
+} TPML_POLICYBRANCHES;
+
+/** Policy type TPMS_POLICYOR
+ */
+typedef struct {
+    struct TPML_POLICYBRANCHES                 *branches;    /**< An (infinite) array of policy elements. This does not contai */
+} TPMS_POLICYOR;
+
+/** [u'']
+ */
+typedef union {
+    TPMS_POLICYOR                              PolicyOr;    /**< None */
+    TPMS_POLICYSIGNED                      PolicySigned;    /**< None */
+    TPMS_POLICYSECRET                      PolicySecret;    /**< None */
+    TPMS_POLICYPCR                            PolicyPCR;    /**< None */
+    TPMS_POLICYLOCALITY                  PolicyLocality;    /**< None */
+    TPMS_POLICYNV                              PolicyNV;    /**< None */
+    TPMS_POLICYCOUNTERTIMER          PolicyCounterTimer;    /**< None */
+    TPMS_POLICYCOMMANDCODE            PolicyCommandCode;    /**< None */
+    TPMS_POLICYPHYSICALPRESENCE    PolicyPhysicalPresence;  /**< None */
+    TPMS_POLICYCPHASH                      PolicyCpHash;    /**< None */
+    TPMS_POLICYNAMEHASH                  PolicyNameHash;    /**< None */
+    TPMS_POLICYDUPLICATIONSELECT   PolicyDuplicationSelect; /**< None */
+    TPMS_POLICYAUTHORIZE                PolicyAuthorize;    /**< None */
+    TPMS_POLICYAUTHVALUE                PolicyAuthValue;    /**< None */
+    TPMS_POLICYPASSWORD                  PolicyPassword;    /**< None */
+    TPMS_POLICYNVWRITTEN                PolicyNvWritten;    /**< None */
+    TPMS_POLICYTEMPLATE                  PolicyTemplate;    /**< None */
+    TPMS_POLICYAUTHORIZENV            PolicyAuthorizeNv;    /**< None */
+    TPMS_POLICYACTION                      PolicyAction;    /**< None */
+} TPMU_POLICYELEMENT;
+
+/** Policy type TPMT_POLICYELEMENT
+ */
+typedef struct {
+    TPMI_POLICYTYPE                                type;    /**< None */
+    TPML_DIGEST_VALUES                    policyDigests;    /**< None */
+    TPMU_POLICYELEMENT                          element;    /**< The union does is not embedded inside a field. */
+} TPMT_POLICYELEMENT;
+
+/** Policy type TPML_POLICYELEMENTS
+ */
+struct TPML_POLICYELEMENTS {
+    UINT32                                        count;    /**< None */
+    TPMT_POLICYELEMENT                         elements[];    /**< Array of policy elements */
+};
+
+/** Policy type TPMS_POLICY_HARNESS
+ */
+typedef struct TPMS_POLICY_HARNESS {
+    char                                   *description;    /**< O */
+    TPML_DIGEST_VALUES                    policyDigests;    /**< O */
+    struct TPML_POLICYAUTHORIZATIONS     *policyAuthorizations;    /**< O */
+    struct TPML_POLICYELEMENTS                   *policy;    /**< X */
+} TPMS_POLICY_HARNESS;
+
+#endif /* IFAPI_POLICY_TYPES_H */
diff --git a/src/tss2-fapi/ifapi_policyutil_execute.c b/src/tss2-fapi/ifapi_policyutil_execute.c
new file mode 100644
index 0000000..3245b49
--- /dev/null
+++ b/src/tss2-fapi/ifapi_policyutil_execute.c
@@ -0,0 +1,313 @@
+/* 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 <string.h>
+#include <stdlib.h>
+
+#include "tss2_mu.h"
+#include "fapi_util.h"
+#include "fapi_crypto.h"
+//#include "fapi_policy.h"
+#include "ifapi_policy_execute.h"
+#include "ifapi_policyutil_execute.h"
+#include "ifapi_helpers.h"
+#include "ifapi_json_deserialize.h"
+#include "tpm_json_deserialize.h"
+#include "ifapi_policy_callbacks.h"
+#include "ifapi_policyutil_execute.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+
+/** Create a new policy on policy stack.
+ *
+ * The structures for policy and callback execution are allocated
+ * and the callbacks are assigned.
+ */
+static TSS2_RC
+new_policy(
+    FAPI_CONTEXT *context,
+    TPMS_POLICY_HARNESS *harness,
+    IFAPI_POLICYUTIL_STACK **current_policy)
+{
+    LOG_DEBUG("ADD POLICY");
+    IFAPI_POLICY_EXEC_CTX *pol_exec_ctx;
+    IFAPI_POLICY_EXEC_CB_CTX *pol_exec_cb_ctx;
+
+    *current_policy = calloc(sizeof(IFAPI_POLICYUTIL_STACK), 1);
+    if (!*current_policy) {
+        return_error(TSS2_FAPI_RC_MEMORY, "Out of memory");
+    }
+
+    pol_exec_ctx = calloc(sizeof(IFAPI_POLICY_EXEC_CTX), 1);
+    if (!pol_exec_ctx) {
+        return_error(TSS2_FAPI_RC_MEMORY, "Out of memory");
+    }
+    (*current_policy)->pol_exec_ctx = pol_exec_ctx;
+    pol_exec_ctx->callbacks.cbauth = ifapi_policyeval_cbauth;
+    pol_exec_ctx->callbacks.cbauth_userdata = context;
+    pol_exec_ctx->callbacks.cbpolsel = ifapi_branch_selection;
+    pol_exec_ctx->callbacks.cbpolsel_userdata = context;
+    pol_exec_ctx->callbacks.cbsign = ifapi_sign_buffer;
+    pol_exec_ctx->callbacks.cbsign_userdata = context;
+    pol_exec_ctx->callbacks.cbauthpol = ifapi_exec_auth_policy;
+    pol_exec_ctx->callbacks.cbauthpol_userdata = context;
+    pol_exec_ctx->callbacks.cbauthnv = ifapi_exec_auth_nv_policy;
+    pol_exec_ctx->callbacks.cbauthnv_userdata = context;
+    pol_exec_ctx->callbacks.cbdup = ifapi_get_duplicate_name;
+    pol_exec_ctx->callbacks.cbdup_userdata = context;
+    pol_exec_ctx->callbacks.cbaction = ifapi_policy_action;
+    pol_exec_ctx->callbacks.cbaction_userdata = context;
+
+    pol_exec_cb_ctx =  calloc(sizeof(IFAPI_POLICY_EXEC_CB_CTX), 1);
+    if (!pol_exec_cb_ctx) {
+        return_error(TSS2_FAPI_RC_MEMORY, "Out of memory");
+    }
+    pol_exec_ctx->app_data = pol_exec_cb_ctx;
+    pol_exec_ctx->harness = harness;
+    if (!context->policy.policyutil_stack) {
+        context->policy.policyutil_stack = *current_policy;
+        context->policy.util_current_policy = *current_policy;
+    } else {
+        context->policy.util_current_policy->next = *current_policy;
+        (*current_policy)->prev = context->policy.util_current_policy;
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Compute a new session which will be uses as policy session.
+ */
+static TSS2_RC
+create_session(
+    FAPI_CONTEXT *context,
+    ESYS_TR *session,
+    TPMI_ALG_HASH hash_alg)
+{
+    TSS2_RC r = TSS2_RC_SUCCESS;
+
+    switch (context->policy.create_session_state) {
+    case CREATE_SESSION_INIT:
+        r = Esys_StartAuthSession_Async(context->esys,
+                                        context->srk_handle ? context->srk_handle : ESYS_TR_NONE,
+                                        ESYS_TR_NONE,
+                                        ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
+                                        NULL,
+                                        TPM2_SE_POLICY,
+                                        &context->profiles.default_profile.session_symmetric,
+                                        hash_alg);
+
+        return_if_error(r, "Creating session.");
+
+        context->policy.create_session_state = WAIT_FOR_CREATE_SESSION;
+        return TSS2_FAPI_RC_TRY_AGAIN;
+
+    case WAIT_FOR_CREATE_SESSION:
+        r = Esys_StartAuthSession_Finish(context->esys, session);
+        if (r != TSS2_RC_SUCCESS)
+            return r;
+        context->policy.create_session_state = CREATE_SESSION_INIT;
+        break;
+
+    default:
+        context->state = _FAPI_STATE_INTERNALERROR;
+        goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Invalid state for create session.",
+                   cleanup);
+    }
+
+cleanup:
+    return r;
+}
+
+/** Cleanup the current policy and adapt the policy stack.
+ */
+static TSS2_RC
+clear_current_policy(FAPI_CONTEXT *context)
+{
+    LOG_DEBUG("CLEAR POLICY");
+    IFAPI_POLICYUTIL_STACK *prev_pol;
+    if (!context->policy.util_current_policy) {
+        return_error(TSS2_FAPI_RC_GENERAL_FAILURE, "No current policy.");
+    }
+    prev_pol = context->policy.util_current_policy->prev;
+
+    SAFE_FREE(context->policy.util_current_policy->pol_exec_ctx->app_data);
+    SAFE_FREE(context->policy.util_current_policy->pol_exec_ctx);
+    SAFE_FREE(context->policy.util_current_policy);
+
+    if (!prev_pol) {
+        context->policy.policyutil_stack = NULL;
+    } else {
+        prev_pol->next = NULL;
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Cleanup the policy stack.
+  *
+  * Will be used if an error occurs.
+  */
+static void
+clear_all_policies(FAPI_CONTEXT *context)
+{
+    LOG_DEBUG("CLEAR ALL POLICIES");
+
+    IFAPI_POLICYUTIL_STACK *policy = context->policy.policyutil_stack;
+    IFAPI_POLICYUTIL_STACK *next_policy;
+
+    while (policy) {
+        next_policy = policy->next;
+        SAFE_FREE(policy->pol_exec_ctx->app_data);
+        if (policy->pol_exec_ctx->session)
+            Esys_FlushContext(context->esys, policy->pol_exec_ctx->session);
+        SAFE_FREE(policy->pol_exec_ctx);
+        ;
+        SAFE_FREE(policy);
+        policy = next_policy;
+    }
+    context->policy.policyutil_stack = NULL;
+}
+
+/** Prepare the execution of a new policy on policy stack.
+ *
+ * The context for the  policy utility, the policy execution and the needed
+ * callbacks is initialized.
+ * The policy execution will be prepared. In this step the list of policies
+ * to be executed will be computed.
+ * @param[in,out] context The fapi context with the pointer to the policy stack.
+ * @param[in] hash_alg The hash algorithm used for the policy computation.
+ * @param[in,out] harness The policy to be executed. Some policy elements will
+ *                be used to store computed parameters needed for policy
+ *                execution.
+ * @retval TSS2_RC_SUCCESS on success.
+ * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN If the callback for branch selection is
+ *         not defined. This callback will be needed of or policies have to be
+ *         executed.
+ * @retval TSS2_FAPI_RC_BAD_VALUE If the computed branch index deliverd by the
+ *         callback does not identify a branch.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE If no context is passed.
+ *
+ */
+TSS2_RC
+ifapi_policyutil_execute_prepare(
+    FAPI_CONTEXT *context,
+    TPMI_ALG_HASH hash_alg,
+    TPMS_POLICY_HARNESS *harness)
+{
+    TSS2_RC r;
+    IFAPI_POLICYUTIL_STACK *current_policy;
+
+    return_if_null(context, "Bad context.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    r = new_policy(context, harness, &current_policy);
+    goto_if_error(r, "Create new policy.", error);
+
+    r = ifapi_policyeval_execute_prepare(current_policy->pol_exec_ctx, hash_alg, harness);
+    goto_if_error(r, "Prepare policy execution.", error);
+
+    return r;
+
+ error:
+    while (context->policy.policyutil_stack) {
+        clear_all_policies(context);
+    }
+    SAFE_FREE(current_policy);
+    return r;
+}
+/** State machine to Execute the TPM policy commands needed for the current policy.
+ *
+ * In the first step a session will be created if no session is passed.
+ * In the second step the policy engine will execute the policy.
+ *
+ * @param[in,out] context The fapi context with the pointer to the policy stack.
+ * @param[in,out] session The policy session to be extended or if the value is
+ *                equal zero or ESYS_TR_NONE a new created session will been
+ *                be stored in this parameter.
+ * @retval TSS2_RC_SUCCESS on success.
+ * @retval TSS2_FAPI_RC_MEMORY: if not enough memory can be allocated.
+ * @retval TSS2_FAPI_RC_BAD_VALUE If wrong values are detected during execution.
+ * @retval TSS2_FAPI_RC_IO_ERROR If an error occurs during access to the policy
+ *         store.
+ * @retval TSS2_FAPI_RC_POLICY_UNKNOWN If policy search for a certain policy diges was
+           not successful.
+ * @retval TSS2_FAPI_RC_BAD_TEMPLATE In a invalid policy is loaded during execution.
+ * @retval TPM2_RC_BAD_AUTH If the authentication for an object needed for policy
+ *         execution fails.
+ */
+TSS2_RC
+ifapi_policyutil_execute(FAPI_CONTEXT *context, ESYS_TR *session)
+{
+    TSS2_RC r;
+    IFAPI_POLICYUTIL_STACK *pol_util_ctx;
+    TPMI_ALG_HASH hash_alg;
+
+    if (context->policy.util_current_policy) {
+        pol_util_ctx = context->policy.util_current_policy->next;
+        context->policy.util_current_policy = context->policy.util_current_policy->next;
+    } else {
+        pol_util_ctx = context->policy.policyutil_stack;
+        context->policy.util_current_policy = pol_util_ctx;
+    }
+    LOG_TRACE("Util context: %p", pol_util_ctx);
+
+    if (!pol_util_ctx) {
+        return_error(TSS2_FAPI_RC_GENERAL_FAILURE, "No policy util stack.");
+    }
+
+    switch (pol_util_ctx->state) {
+        statecase(pol_util_ctx->state, POLICY_UTIL_INIT);
+            LOG_DEBUG("Util session: %x", pol_util_ctx->policy_session);
+            if (*session == ESYS_TR_NONE  || *session == 0) {
+                /* Create a new  policy session for the current policy execution */
+                hash_alg = pol_util_ctx->pol_exec_ctx->hash_alg;
+                r = create_session(context, &pol_util_ctx->policy_session,
+                                  hash_alg);
+                if ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN) {
+                    context->policy.util_current_policy = pol_util_ctx->prev;
+                    return TSS2_FAPI_RC_TRY_AGAIN;
+                }
+                goto_if_error(r, "Create policy session", error);
+
+                pol_util_ctx->pol_exec_ctx->session = pol_util_ctx->policy_session;
+            } else {
+                pol_util_ctx->pol_exec_ctx->session = *session;
+            }
+            fallthrough;
+
+        statecase(pol_util_ctx->state, POLICY_UTIL_EXEC_POLICY);
+            r = ifapi_policyeval_execute(context->esys,
+                                         pol_util_ctx->pol_exec_ctx);
+            if ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN) {
+                context->policy.util_current_policy = pol_util_ctx->prev;
+                return TSS2_FAPI_RC_TRY_AGAIN;
+            }
+            goto_if_error(r, "Execute policy.", error);
+
+            break;
+
+        statecasedefault(pol_util_ctx->state);
+    }
+    *session = pol_util_ctx->policy_session;
+
+    pol_util_ctx = pol_util_ctx->prev;
+
+    r = clear_current_policy(context);
+    goto_if_error(r, "Clear policy.", error);
+
+    context->policy.util_current_policy = pol_util_ctx;
+
+    LOG_TRACE("success");
+    return r;
+
+ error:
+    while (context->policy.policyutil_stack) {
+        clear_all_policies(context);
+    }
+    return r;
+}
diff --git a/src/tss2-fapi/ifapi_policyutil_execute.h b/src/tss2-fapi/ifapi_policyutil_execute.h
new file mode 100644
index 0000000..ba4b56d
--- /dev/null
+++ b/src/tss2-fapi/ifapi_policyutil_execute.h
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ *******************************************************************************/
+#ifndef FAPI_POLICYUTIL_EXECUTE_H
+#define FAPI_POLICYUTIL_EXECUTE_H
+
+#include <stdint.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <sys/stat.h>
+#include <json-c/json.h>
+#include <json-c/json_util.h>
+
+#include "tss2_esys.h"
+#include "tss2_fapi.h"
+
+
+/** The states for the FAPI's policy util execution */
+enum IFAPI_STATE_POLICY_UTIL_EXEC {
+    POLICY_UTIL_INIT,
+    POLICY_UTIL_EXEC_POLICY,
+};
+
+/** The context of the policy execution */
+struct IFAPI_POLICYUTIL_STACK {
+    ESYS_TR policy_session;             /**< The policy session created for the current evaluation  */
+    IFAPI_POLICY_EXEC_CTX *pol_exec_ctx;    /**< The execution context for the current policy */
+    enum IFAPI_STATE_POLICY_UTIL_EXEC state;
+    IFAPI_POLICYUTIL_STACK *next;           /**< Pointer to next policy */
+    IFAPI_POLICYUTIL_STACK *prev;           /**< Pointer to previous policy */
+};
+
+TSS2_RC
+ifapi_new_policy(
+    FAPI_CONTEXT *context,
+    TPMS_POLICY_HARNESS *harness,
+    IFAPI_POLICY_EXEC_CTX **current_policy);
+
+TSS2_RC
+ifapi_policyutil_execute_prepare(
+    FAPI_CONTEXT *context,
+    TPMI_ALG_HASH hash_alg,
+    TPMS_POLICY_HARNESS *harness);
+
+TSS2_RC
+ifapi_policyutil_execute(
+    FAPI_CONTEXT *context,
+    ESYS_TR *session);
+
+#endif /* FAPI_POLICYUTIL_EXECUTE_H */
diff --git a/src/tss2-fapi/ifapi_profiles.c b/src/tss2-fapi/ifapi_profiles.c
new file mode 100644
index 0000000..a316722
--- /dev/null
+++ b/src/tss2-fapi/ifapi_profiles.c
@@ -0,0 +1,539 @@
+/* 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 <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "tss2_common.h"
+
+#include "ifapi_profiles.h"
+
+#include "tpm_json_deserialize.h"
+#include "ifapi_policy_json_deserialize.h"
+#include "ifapi_json_deserialize.h"
+#include "ifapi_helpers.h"
+#define LOGMODULE fapi
+#include "util/log.h"
+#include "util/aux_util.h"
+#include "ifapi_macros.h"
+
+#define PROFILES_EXTENSION ".json"
+#define PROFILES_PREFIX "P_"
+
+static TSS2_RC
+ifapi_profile_json_deserialize(
+    json_object *jso,
+    IFAPI_PROFILE *profile);
+
+static TSS2_RC
+ifapi_profile_checkpcrs(const TPML_PCR_SELECTION *pcr_profile);
+
+/** Initialize the profiles information in the context in an asynchronous way
+ *
+ * Load the profile information from disk, fill the dictionary of loaded profiles and fill
+ * the default profile information into the context.
+ *
+ * Call ifapi_profiles_initialize_finish to complete the operation.
+ *
+ * @param profiles [in, out] The context for the profiles information.
+ * @param profilesdir [in] The directory to load profile information from.
+ * @param defaultprofile [in] The name of the default profile to use.
+ * @retval TSS2_RC_SUCCESS on success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE if NULL pointers were passed in.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the profilesdir does not exist or is empty.
+ * @retval TSS2_FAPI_RC_IO_ERROR if creation of log_dir failed or log_dir is not writable.
+ * @retval TSS2_FAPI_RC_MEMORY if memory allocation failed.
+ */
+TSS2_RC
+ifapi_profiles_initialize_async(
+    IFAPI_PROFILES *profiles,
+    IFAPI_IO *io,
+    const char *profilesdir,
+    const char *defaultprofile)
+{
+    TSS2_RC r;
+    char *tmp;
+    size_t i, j;
+    check_not_null(profiles);
+    check_not_null(profilesdir);
+
+    memset(profiles, 0, sizeof(*profiles));
+
+    profiles->default_name = strdup(defaultprofile);
+    check_oom(profiles->default_name);
+
+    r = ifapi_io_dirfiles(profilesdir, &profiles->filenames, &profiles->num_profiles);
+    return_if_error(r, "Reading profiles from profiles dir");
+
+    profiles->profiles = calloc(profiles->num_profiles, sizeof(profiles->profiles[0]));
+    check_oom(profiles->profiles);
+
+    /* Clean up list of files to only include those that match our filename pattern
+       Expand the filenames with the directory
+       Set the names in the dictionary */
+    for (i = 0; i < profiles->num_profiles; ) {
+        char *ext = strstr(profiles->filenames[i], PROFILES_EXTENSION);
+        /* Path the filename with the expected pattern */
+        if (ext != NULL && strlen(ext) == strlen(PROFILES_EXTENSION) &&
+                strncmp(profiles->filenames[i], PROFILES_PREFIX, strlen(PROFILES_PREFIX)) == 0)
+        {
+            LOG_TRACE("Using file %s in profiles directory", profiles->filenames[i]);
+            /* Add the profile name */
+            profiles->profiles[i].name = strndup(profiles->filenames[i],
+                                                 ext - profiles->filenames[i]);
+            check_oom(profiles->profiles[i].name);
+            /* Expand the filename with the directory */
+            tmp = profiles->filenames[i];
+            r = ifapi_asprintf(&profiles->filenames[i], "%s/%s", profilesdir, tmp);
+            return_if_error(r, "Out of memory");
+
+            LOG_TRACE("Added profile-entry %s for file %s based on direntry %s",
+                      profiles->profiles[i].name, profiles->filenames[i], tmp);
+
+            /* Cleanup and continue */
+            free(tmp);
+            i++;
+        } else {
+            LOG_TRACE("Skipping file %s in profiles directory", profiles->filenames[i]);
+            free(profiles->filenames[i]);
+            profiles->num_profiles -= 1;
+            for (j = i; j < profiles->num_profiles; j++) {
+                profiles->filenames[j] = profiles->filenames[j + 1];
+            }
+        }
+    }
+
+    if (profiles->num_profiles == 0) {
+        LOG_ERROR("No files found in profile dir %s that match the pattern %s*%s",
+                  profilesdir, PROFILES_PREFIX, PROFILES_EXTENSION);
+        return TSS2_FAPI_RC_BAD_VALUE;
+    }
+
+#ifdef HAVE_REALLOCARRAY
+    profiles->profiles = reallocarray(profiles->profiles, profiles->num_profiles,
+                                      sizeof(profiles->profiles[0]));
+    profiles->filenames = reallocarray(profiles->filenames, profiles->num_profiles,
+                                      sizeof(profiles->filenames[0]));
+#else /* HAVE_REALLOCARRAY */
+    profiles->profiles = realloc(profiles->profiles, profiles->num_profiles *
+                                      sizeof(profiles->profiles[0]));
+    profiles->filenames = realloc(profiles->filenames, profiles->num_profiles *
+                                      sizeof(profiles->filenames[0]));
+#endif /* HAVE_REALLOCARRAY */
+    /* No need for OOM checks, since num_profiles may only have become smaller */
+
+    r = ifapi_io_read_async(io, profiles->filenames[profiles->profiles_idx]);
+    return_if_error2(r, "Reading profile %s", profiles->filenames[profiles->profiles_idx]);
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Initialize the profiles information in the context in an asynchronous way
+ *
+ * Call after ifapi_profiles_initialize_async to complete the operation.
+ *
+ * @param profiles [in, out] The context for the profiles information.
+ * @retval TSS2_RC_SUCCESS on success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE if NULL pointers were passed in.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if a profile could not be loaded.
+ * @retval TSS2_FAPI_RC_IO_ERROR if creation of log_dir failed or log_dir is not writable.
+ * @retval TSS2_FAPI_RC_MEMORY if memory allocation failed.
+ * @retval TSS2_FAPI_RC_TRY_AGAIN if the I/O operation is not finished yet and this function needs
+ *         to be called again.
+ */
+TSS2_RC
+ifapi_profiles_initialize_finish(
+    IFAPI_PROFILES *profiles,
+    IFAPI_IO *io)
+{
+    TSS2_RC r;
+    uint8_t *buffer;
+    size_t i;
+    json_object *jso;
+    check_not_null(profiles);
+    check_not_null(io);
+
+    r = ifapi_io_read_finish(io, &buffer, NULL);
+    return_if_error(r, "Reading profile failed");
+
+    jso = json_tokener_parse((char *) buffer);
+    free(buffer);
+    if (jso == NULL) {
+        LOG_ERROR("Failed to parse profile %s", profiles->filenames[profiles->profiles_idx]);
+        return TSS2_FAPI_RC_BAD_VALUE;
+    }
+
+    r = ifapi_profile_json_deserialize(jso,
+            &profiles->profiles[profiles->profiles_idx].profile);
+    json_object_put(jso);
+    return_if_error2(r, "Parsing profile %s failed",
+                     profiles->filenames[profiles->profiles_idx]);
+
+    r = ifapi_profile_checkpcrs(&profiles->profiles[profiles->profiles_idx].profile.pcr_selection);
+    return_if_error2(r, "Malformed profile pcr selection for profile %s",
+                     profiles->filenames[profiles->profiles_idx]);
+
+    profiles->profiles_idx += 1;
+
+    if (profiles->profiles_idx < profiles->num_profiles) {
+        r = ifapi_io_read_async(io, profiles->filenames[profiles->profiles_idx]);
+        return_if_error2(r, "Reading profile %s", profiles->filenames[profiles->profiles_idx]);
+
+        return TSS2_FAPI_RC_TRY_AGAIN;
+    }
+
+    /* Get the data of the default profile into the respective variable */
+    for (i = 0; i < profiles->num_profiles; i++) {
+        if (strcmp(profiles->default_name, profiles->profiles[i].name) == 0) {
+            profiles->default_profile = profiles->profiles[i].profile;
+            break;
+        }
+    }
+    if (i == profiles->num_profiles) {
+        LOG_ERROR("Default profile %s not in the list of loaded profiles",
+                  profiles->default_name);
+        return TSS2_FAPI_RC_BAD_VALUE;
+    }
+
+    for (i = 0; i < profiles->num_profiles; i++) {
+        free(profiles->filenames[i]);
+    }
+    SAFE_FREE(profiles->filenames);
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Return the profile data for a given profile name.
+ *
+ * Returns a (const, not to be free'd) pointer to the profile data for a reqeusted profile.
+ * If a NULL profile is requesten, then the default profile is returned.
+ * If a keypath is passed in, then the prefix is analysed. If that keypath starts with a profile
+ * then this profile is returned. Otherwise the default profile is returned.
+ *
+ * @param profiles [in] The profiles context
+ * @param name [in] The name of the profile or the keypath
+ * @param profile [out] The pointer to the profile data.
+ * @retval TSS2_RC_SUCCESS on success.
+ * @retval TSS2_FAPI_RC_BAD_REFERENCE if NULL pointers were passed in.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if a profile is not found.
+ */
+TSS2_RC
+ifapi_profiles_get(
+    const IFAPI_PROFILES *profiles,
+    const char *name,
+    const IFAPI_PROFILE **profile)
+{
+    check_not_null(profiles);
+    check_not_null(name);
+    check_not_null(profile);
+    char *split;
+    size_t len;
+
+    /* if no name or nor profile prefix is given, use the default profile */
+    if (!name || strncmp(name, "P_", 2) != 0|| strncmp(name, "/P_", 2) != 0) {
+        *profile = &profiles->default_profile;
+        return TSS2_RC_SUCCESS;
+    }
+
+    /* Search for path delimiter */
+    split = index(name, IFAPI_FILE_DELIM_CHAR);
+
+    /* If the path beging with delimiters, skip over those */
+    if (name == split) {
+        name += 1;
+        split = index(name, IFAPI_FILE_DELIM_CHAR);
+    }
+    if (split == NULL)
+        len = strlen(name);
+    else
+        len = split - name;
+
+    for (size_t i = 0; i < profiles->num_profiles; i++) {
+        if (len == strlen(profiles->profiles[i].name) &&
+                strncmp(name, profiles->profiles[i].name, len) == 0) {
+            *profile = &profiles->profiles[i].profile;
+            return TSS2_RC_SUCCESS;
+        }
+    }
+    LOG_ERROR("Profile %s not in the list of loaded profiles", name);
+    return TSS2_FAPI_RC_BAD_VALUE;
+}
+
+/** Sanitizes and frees internal data structures of loaded profiles' information.
+ *
+ * @param profiles [in, out] The context for the profiles information.
+ */
+void
+ifapi_profiles_finalize(
+    IFAPI_PROFILES *profiles)
+{
+    size_t i;
+    if (!profiles) {
+        LOG_ERROR("Called with bad reference");
+        return;
+    }
+
+    SAFE_FREE(profiles->default_name);
+
+    for (i = 0; i < profiles->num_profiles; i++) {
+        IFAPI_PROFILE_ENTRY * entry = &profiles->profiles[i];
+        SAFE_FREE(profiles->profiles[i].name);
+
+        IFAPI_PROFILE * profile = &entry->profile;
+
+        SAFE_FREE(profile->srk_template);
+        SAFE_FREE(profile->ek_template);
+
+        ifapi_cleanup_policy_harness(profile->eh_policy);
+        SAFE_FREE(profile->eh_policy);
+
+        ifapi_cleanup_policy_harness(profile->ek_policy);
+        SAFE_FREE(profile->ek_policy);
+
+        ifapi_cleanup_policy_harness(profile->sh_policy);
+        SAFE_FREE(profile->sh_policy);
+    }
+    SAFE_FREE(profiles->profiles);
+
+    memset(profiles, 0, sizeof(*profiles));
+}
+
+/** Deserialize a IFAPI_KEY_PROFILE 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.
+ */
+static TSS2_RC
+ifapi_profile_json_deserialize(
+    json_object *jso,
+    IFAPI_PROFILE *out)
+{
+//TODO: Cleanup
+    json_object *jso2;
+    TSS2_RC r;
+
+    const TPMT_SYM_DEF session_symmetric_default = {
+        .algorithm = TPM2_ALG_AES,
+        .keyBits = {.aes = 128},
+        .mode = {.aes = TPM2_ALG_CFB}
+    };
+
+    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, "srk_template", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    out->srk_template = strdup(json_object_get_string(jso2));
+    return_if_null(out->srk_template, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+    if (!ifapi_get_sub_object(jso, "ek_template", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    out->ek_template = strdup(json_object_get_string(jso2));
+    return_if_null(out->ek_template, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+    if (!ifapi_get_sub_object(jso, "ecc_signing_scheme", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_TPMT_SIG_SCHEME_deserialize(jso2, &out->ecc_signing_scheme);
+    return_if_error(r, "BAD VALUE");
+
+    if (!ifapi_get_sub_object(jso, "rsa_signing_scheme", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_TPMT_SIG_SCHEME_deserialize(jso2, &out->rsa_signing_scheme);
+    return_if_error(r, "BAD VALUE");
+
+    if (!ifapi_get_sub_object(jso, "rsa_decrypt_scheme", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_TPMT_RSA_DECRYPT_deserialize(jso2, &out->rsa_decrypt_scheme);
+    return_if_error(r, "BAD VALUE");
+
+    if (!ifapi_get_sub_object(jso, "sym_mode", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_TPMI_ALG_SYM_MODE_deserialize(jso2, &out->sym_mode);
+    return_if_error(r, "BAD VALUE");
+
+    if (!ifapi_get_sub_object(jso, "sym_parameters", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_TPMT_SYM_DEF_OBJECT_deserialize(jso2, &out->sym_parameters);
+    return_if_error(r, "BAD VALUE");
+
+    if (!ifapi_get_sub_object(jso, "sym_block_size", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_UINT16_deserialize(jso2, &out->sym_block_size);
+    return_if_error(r, "BAD VALUE");
+
+    if (!ifapi_get_sub_object(jso, "pcr_selection", &jso2)) {
+        LOG_ERROR("Bad value");
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    r =  ifapi_json_TPML_PCR_SELECTION_deserialize(jso2, &out->pcr_selection);
+    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 (out->type == TPM2_ALG_RSA) {
+        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");
+        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");
+
+    } else if (out->type == TPM2_ALG_ECC) {
+        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, "session_symmetric", &jso2)) {
+        out->session_symmetric = session_symmetric_default;
+    } else {
+        r =  ifapi_json_TPMT_SYM_DEF_deserialize(jso2, &out->session_symmetric);
+        return_if_error(r, "BAD VALUE");
+    }
+
+    if (ifapi_get_sub_object(jso, "eh_policy", &jso2)) {
+        out->eh_policy = calloc(1, sizeof(TPMS_POLICY_HARNESS));
+        goto_if_null2(out->eh_policy, "Out of memory.", r, TSS2_FAPI_RC_MEMORY,
+                      cleanup);
+
+        r =  ifapi_json_TPMS_POLICY_HARNESS_deserialize(jso2, out->eh_policy);
+        goto_if_error(r, "Deserialize policy harness.", cleanup);
+    }
+
+    if (ifapi_get_sub_object(jso, "sh_policy", &jso2)) {
+        out->sh_policy = calloc(1, sizeof(TPMS_POLICY_HARNESS));
+        goto_if_null2(out->sh_policy, "Out of memory.", r, TSS2_FAPI_RC_MEMORY,
+                      cleanup);
+
+        r =  ifapi_json_TPMS_POLICY_HARNESS_deserialize(jso2, out->sh_policy);
+        goto_if_error(r, "Deserialize policy harness.", cleanup);
+    }
+
+    if (ifapi_get_sub_object(jso, "ek_policy", &jso2)) {
+        out->ek_policy = calloc(1, sizeof(TPMS_POLICY_HARNESS));
+        goto_if_null2(out->ek_policy, "Out of memory.", r, TSS2_FAPI_RC_MEMORY,
+                      cleanup);
+
+        r =  ifapi_json_TPMS_POLICY_HARNESS_deserialize(jso2, out->ek_policy);
+        goto_if_error(r, "Deserialize policy harness.", cleanup);
+    }
+
+    if (ifapi_get_sub_object(jso, "srk_policy", &jso2)) {
+        out->srk_policy = calloc(1, sizeof(TPMS_POLICY_HARNESS));
+        goto_if_null2(out->srk_policy, "Out of memory.", r, TSS2_FAPI_RC_MEMORY,
+                      cleanup);
+
+        r =  ifapi_json_TPMS_POLICY_HARNESS_deserialize(jso2, out->srk_policy);
+        goto_if_error(r, "Deserialize policy harness.", cleanup);
+    }
+
+    if (ifapi_get_sub_object(jso, "lockout_policy", &jso2)) {
+        out->lockout_policy = calloc(1, sizeof(TPMS_POLICY_HARNESS));
+        goto_if_null2(out->lockout_policy, "Out of memory.", r, TSS2_FAPI_RC_MEMORY,
+                      cleanup);
+
+        r =  ifapi_json_TPMS_POLICY_HARNESS_deserialize(jso2, out->lockout_policy);
+        goto_if_error(r, "Deserialize policy harness.", cleanup);
+    }
+
+    if (!ifapi_get_sub_object(jso, "newMaxTries", &jso2)) {
+        out->newMaxTries = 5;
+    } else {
+        r =  ifapi_json_UINT32_deserialize(jso2, &out->newMaxTries);
+        return_if_error(r, "BAD VALUE");
+    }
+
+    if (!ifapi_get_sub_object(jso, "newRecoveryTime", &jso2)) {
+        out->newRecoveryTime = 1000;
+    } else {
+        r =  ifapi_json_UINT32_deserialize(jso2, &out->newRecoveryTime);
+        return_if_error(r, "BAD VALUE");
+    }
+
+    if (!ifapi_get_sub_object(jso, "lockoutRecovery", &jso2)) {
+        out->lockoutRecovery = 1000;
+    } else {
+        r =  ifapi_json_UINT32_deserialize(jso2, &out->lockoutRecovery);
+        return_if_error(r, "BAD VALUE");
+    }
+
+    LOG_TRACE("true");
+    return TSS2_RC_SUCCESS;
+
+ cleanup:
+    SAFE_FREE(out->eh_policy);
+    return r;
+}
+
+/**
+  * Check whether PCRs with muliple banks are defined in profile.
+  *
+  * This case is not allowed by FAPI.
+  */
+static TSS2_RC
+ifapi_profile_checkpcrs(const TPML_PCR_SELECTION *pcr_profile)
+{
+    size_t i, j, byte_idx;
+
+    for (i = 0; i < pcr_profile->count - 1; i++) {
+        for (j = i + 1; j <  pcr_profile->count; j++) {
+            for (byte_idx = 0; byte_idx < 3; byte_idx++) {
+                /* Check whether a PCR register flag does occur in two different banks. */
+                if (pcr_profile->pcrSelections[i].pcrSelect[byte_idx] &
+                        pcr_profile->pcrSelections[j].pcrSelect[byte_idx]) {
+                    return_error2(TSS2_FAPI_RC_BAD_VALUE,
+                                  "More than one bank selected for a PCR register.");
+                }
+            }
+        }
+    }
+    return TSS2_RC_SUCCESS;
+}
diff --git a/src/tss2-fapi/ifapi_profiles.h b/src/tss2-fapi/ifapi_profiles.h
new file mode 100644
index 0000000..8c13650
--- /dev/null
+++ b/src/tss2-fapi/ifapi_profiles.h
@@ -0,0 +1,82 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ ******************************************************************************/
+
+#ifndef IFAPI_PROFILES_H
+#define IFAPI_PROFILES_H
+
+#include "ifapi_io.h"
+#include "ifapi_policy_types.h"
+
+/** Internal structure for FAPI profiles
+ */
+typedef struct IFAPI_PROFILE {
+    TPMI_ALG_PUBLIC                                type;    /**< The algorithm used for key creation */
+    char                                  *srk_template;    /**< name of SRK template */
+    char                                   *ek_template;    /**< name of EK template */
+    TPMT_SIG_SCHEME                  ecc_signing_scheme;    /**< < Signing scheme for the ECC key. */
+    TPMT_SIG_SCHEME                  rsa_signing_scheme;    /**< < Signing scheme for the RSA key. */
+    TPMT_RSA_DECRYPT                 rsa_decrypt_scheme;    /**< < Decrypt scheme for the RSA key. */
+    TPMI_ALG_SYM_MODE                          sym_mode;    /**< < Mode for symmectric encryption. */
+    TPMT_SYM_DEF_OBJECT                  sym_parameters;    /**< < Parameters for symmectric encryption. */
+    UINT16                               sym_block_size;    /**< < Block size for symmectric encryption. */
+    TPML_PCR_SELECTION                    pcr_selection;    /**< < Parameters for symmectric encryption. */
+    TPMI_ALG_HASH                               nameAlg;
+    TPMI_RSA_KEY_BITS                           keyBits;
+    UINT32                                     exponent;
+    TPMI_ECC_CURVE                              curveID;
+    TPMT_SYM_DEF                      session_symmetric;
+    TPMS_POLICY_HARNESS                      *eh_policy;
+    TPMS_POLICY_HARNESS                      *sh_policy;
+    TPMS_POLICY_HARNESS                      *ek_policy;
+    TPMS_POLICY_HARNESS                     *srk_policy;
+    TPMS_POLICY_HARNESS                 *lockout_policy;
+    UINT32                                  newMaxTries;
+    UINT32                              newRecoveryTime;
+    UINT32                              lockoutRecovery;
+} IFAPI_PROFILE;
+
+/* An entry for the dictionary of loaded profiles */
+typedef struct IFAPI_PROFILE_ENTRY {
+    /** Name of a profile */
+    char *name;
+    /** Values for a profile */
+    struct IFAPI_PROFILE profile;
+} IFAPI_PROFILE_ENTRY;
+
+typedef struct IFAPI_PROFILES {
+    char *default_name;
+    struct IFAPI_PROFILE default_profile;
+    /* Dictionary of loaded profiles */
+    struct IFAPI_PROFILE_ENTRY *profiles;
+    char **filenames;
+    /* Size of the loaded profiles dictionary */
+    size_t num_profiles;
+    size_t profiles_idx;
+} IFAPI_PROFILES;
+
+TSS2_RC
+ifapi_profiles_initialize_async(
+    IFAPI_PROFILES *profiles,
+    IFAPI_IO *io,
+    const char *profilesdir,
+    const char *defaultprofile);
+
+TSS2_RC
+ifapi_profiles_initialize_finish(
+    IFAPI_PROFILES *profiles,
+    IFAPI_IO *io);
+
+TSS2_RC
+ifapi_profiles_get(
+    const IFAPI_PROFILES *profiles,
+    const char *name,
+    const IFAPI_PROFILE **profile);
+
+void
+ifapi_profiles_finalize(
+    IFAPI_PROFILES *profiles);
+
+#endif /* IFAPI_OBJECT_H */
diff --git a/src/tss2-fapi/tpm_json_deserialize.c b/src/tss2-fapi/tpm_json_deserialize.c
new file mode 100644
index 0000000..ca1e6ff
--- /dev/null
+++ b/src/tss2-fapi/tpm_json_deserialize.c
@@ -0,0 +1,4083 @@
+/* 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 accoring 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[in] in Structure to be deserialized.
+ */
+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 *jso2,
+    UINT32 max,
+    BYTE *out,
+    UINT16 *out_size)
+{
+    TSS2_RC r;
+
+    json_type jso_type = json_object_get_type(jso2);
+    if (jso_type == json_type_array) {
+        r = ifapi_json_BYTE_array_deserialize(max, jso2, out);
+        return_if_error(r, "BAD VALUE");
+        *out_size = json_object_array_length(jso2);
+    } else if (jso_type == json_type_string) {
+        const char *token = json_object_get_string(jso2);
+        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.
+ */
+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] in json array of pcr registers.
+ * @param[out] sizeofSelect size of bit mask for used pcr registers.
+ * @param[out] pcrSelect byte arrray with bit mask.
+ */
+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]in json object to be deserialized.
+ * @param[out] out the deserialized object.
+ */
+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]in json object to be deserialized.
+ * @param[out] out the deserialized object.
+ */
+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]in json object to be deserialized.
+ * @param[out] out the deserialized object.
+ */
+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] in Structure.
+ * @param[in] count Number of structures to be deserialized.
+ */
+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 26 - Definition of Types for Handles ***/
+
+/**  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.
+*
+*/
+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]  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_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.
+ */
+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.
+ */
+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.
+ */
+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_NONCETable 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.
+*/
+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_OPERANDTable 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.
+*/
+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.
+ */
+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.
+ */
+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.
+ */
+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.
+ */
+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.
+ */
+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.
+ */
+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.
+ */
+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.
+ */
+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.
+ */
+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.
+ */
+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.
+ */
+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.
+ */
+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.
+ */
+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.
+ */
+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.
+ */
+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.
+ */
+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]  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_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.
+ */
+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.
+*
+*/
+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]  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]  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.
+ */
+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.
+ */
+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.
+ */
+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.
+ */
+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.
+ */
+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_SCHEMETable 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.
+*/
+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.
+ */
+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]  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_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.
+ */
+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 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.
+*/
+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.
+*/
+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 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.
+*/
+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.
+*/
+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.
+*/
+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.
+*/
+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]  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_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.
+ */
+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 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.
+*/
+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 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.
+*/
+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 SchemesTable 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.
+*/
+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.
+*/
+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.
+*/
+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]  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_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.
+ */
+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[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_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.
+ */
+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.
+ */
+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.
+ */
+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.
+*
+*/
+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.
+ */
+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.
+ */
+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.
+*
+*/
+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.
+ */
+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.
+ */
+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 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.
+*/
+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.
+*/
+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.
+ */
+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 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.
+*/
+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.
+*/
+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.
+*/
+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.
+*/
+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]  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_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.
+ */
+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.
+ */
+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]  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_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.
+ */
+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.
+ */
+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.
+ */
+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]  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_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.
+ */
+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.
+ */
+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.
+ */
+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.
+ */
+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.
+ */
+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.
+ */
+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.
+ */
+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.
+ */
+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.
+ */
+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;
+}
diff --git a/src/tss2-fapi/tpm_json_deserialize.h b/src/tss2-fapi/tpm_json_deserialize.h
new file mode 100644
index 0000000..3d9baff
--- /dev/null
+++ b/src/tss2-fapi/tpm_json_deserialize.h
@@ -0,0 +1,544 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ ******************************************************************************/
+#ifndef FAPI_TPM_JSON_DESERIALIZE_H
+#define FAPI_TPM_JSON_DESERIALIZE_H
+
+#include <stdbool.h>
+#include <json-c/json.h>
+#include <json-c/json_util.h>
+
+#include "tss2_tpm2_types.h"
+#include "fapi_int.h"
+#define YES 1
+#define NO 0
+
+TSS2_RC
+ifapi_json_BYTE_array_deserialize(size_t max, json_object *jso, BYTE *out);
+
+TSS2_RC
+ifapi_json_UINT8_ARY_deserialize(json_object *jso, UINT8_ARY *out);
+
+bool
+ifapi_get_sub_object(json_object *jso, char *name, json_object **sub_jso);
+
+TSS2_RC
+ifapi_json_BYTE_array_deserialize(size_t in_size, json_object *jso, BYTE *out);
+
+TSS2_RC
+ifapi_json_BYTE_deserialize(json_object *jso, BYTE *out);
+
+TSS2_RC
+ifapi_json_UINT16_deserialize(json_object *jso, UINT16 *out);
+
+TSS2_RC
+ifapi_json_UINT32_deserialize(json_object *jso, UINT32 *out);
+
+TSS2_RC
+ifapi_json_UINT64_deserialize(json_object *jso, UINT64 *out);
+
+TSS2_RC
+ifapi_json_TPM2_GENERATED_deserialize(json_object *jso, TPM2_GENERATED *out);
+
+TSS2_RC
+ifapi_json_TPM2_GENERATED_deserialize_txt(json_object *jso,
+        TPM2_GENERATED *out);
+
+TSS2_RC
+ifapi_json_TPM2_ALG_ID_deserialize(json_object *jso, TPM2_ALG_ID *out);
+
+TSS2_RC
+ifapi_json_TPM2_ALG_ID_deserialize_txt(json_object *jso, TPM2_ALG_ID *out);
+
+TSS2_RC
+ifapi_json_TPM2_ECC_CURVE_deserialize(json_object *jso, TPM2_ECC_CURVE *out);
+
+TSS2_RC
+ifapi_json_TPM2_ECC_CURVE_deserialize_txt(json_object *jso,
+        TPM2_ECC_CURVE *out);
+
+TSS2_RC
+ifapi_json_TPM2_CC_deserialize(json_object *jso, TPM2_CC *out);
+
+TSS2_RC
+ifapi_json_TPM2_CC_deserialize_txt(json_object *jso, TPM2_CC *out);
+
+TSS2_RC
+ifapi_json_TPM2_EO_deserialize(json_object *jso, TPM2_EO *out);
+
+TSS2_RC
+ifapi_json_TPM2_EO_deserialize_txt(json_object *jso, TPM2_EO *out);
+
+TSS2_RC
+ifapi_json_TPM2_ST_deserialize(json_object *jso, TPM2_ST *out);
+
+TSS2_RC
+ifapi_json_TPM2_ST_deserialize_txt(json_object *jso, TPM2_ST *out);
+
+TSS2_RC
+ifapi_json_TPM2_PT_PCR_deserialize(json_object *jso, TPM2_PT_PCR *out);
+
+TSS2_RC
+ifapi_json_TPM2_PT_PCR_deserialize_txt(json_object *jso, TPM2_PT_PCR *out);
+
+TSS2_RC
+ifapi_json_TPM2_HANDLE_deserialize(json_object *jso, TPM2_HANDLE *out);
+
+TSS2_RC
+ifapi_json_TPMA_OBJECT_deserialize(json_object *jso, TPMA_OBJECT *out);
+
+TSS2_RC
+ifapi_json_TPMA_LOCALITY_deserialize(json_object *jso, TPMA_LOCALITY *out);
+
+TSS2_RC
+ifapi_json_TPMI_YES_NO_deserialize(json_object *jso, TPMI_YES_NO *out);
+
+TSS2_RC
+ifapi_json_TPMI_YES_NO_deserialize_txt(json_object *jso, TPMI_YES_NO *out);
+
+TSS2_RC
+ifapi_json_TPMI_RH_HIERARCHY_deserialize(json_object *jso,
+        TPMI_RH_HIERARCHY *out);
+
+TSS2_RC
+ifapi_json_TPMI_RH_HIERARCHY_deserialize_txt(json_object *jso,
+        TPMI_RH_HIERARCHY *out);
+
+TSS2_RC
+ifapi_json_TPMI_RH_NV_INDEX_deserialize(json_object *jso,
+                                        TPMI_RH_NV_INDEX *out);
+
+TSS2_RC
+ifapi_json_TPMI_RH_NV_INDEX_deserialize_txt(json_object *jso,
+        TPMI_RH_NV_INDEX *out);
+
+TSS2_RC
+ifapi_json_TPMI_ALG_HASH_deserialize(json_object *jso, TPMI_ALG_HASH *out);
+
+TSS2_RC
+ifapi_json_TPMI_ALG_HASH_deserialize_txt(json_object *jso, TPMI_ALG_HASH *out);
+
+TSS2_RC
+ifapi_json_TPMI_ALG_SYM_deserialize(json_object *jso, TPMI_ALG_SYM *out);
+
+TSS2_RC
+ifapi_json_TPMI_ALG_SYM_deserialize_txt(json_object *jso, TPMI_ALG_SYM *out);
+
+TSS2_RC
+ifapi_json_TPMI_ALG_SYM_OBJECT_deserialize(json_object *jso,
+        TPMI_ALG_SYM_OBJECT *out);
+
+TSS2_RC
+ifapi_json_TPMI_ALG_SYM_OBJECT_deserialize_txt(json_object *jso,
+        TPMI_ALG_SYM_OBJECT *out);
+
+TSS2_RC
+ifapi_json_TPMI_ALG_SYM_MODE_deserialize(json_object *jso,
+        TPMI_ALG_SYM_MODE *out);
+
+TSS2_RC
+ifapi_json_TPMI_ALG_SYM_MODE_deserialize_txt(json_object *jso,
+        TPMI_ALG_SYM_MODE *out);
+
+TSS2_RC
+ifapi_json_TPMI_ALG_KDF_deserialize(json_object *jso, TPMI_ALG_KDF *out);
+
+TSS2_RC
+ifapi_json_TPMI_ALG_KDF_deserialize_txt(json_object *jso, TPMI_ALG_KDF *out);
+
+TSS2_RC
+ifapi_json_TPMI_ALG_SIG_SCHEME_deserialize(json_object *jso,
+        TPMI_ALG_SIG_SCHEME *out);
+
+TSS2_RC
+ifapi_json_TPMI_ALG_SIG_SCHEME_deserialize_txt(json_object *jso,
+        TPMI_ALG_SIG_SCHEME *out);
+
+TSS2_RC
+ifapi_json_TPMS_EMPTY_deserialize(json_object *jso, TPMS_EMPTY *out);
+
+TSS2_RC
+ifapi_json_TPMU_HA_deserialize(UINT32 selector, json_object *jso, TPMU_HA *out);
+
+TSS2_RC
+ifapi_json_TPMT_HA_deserialize(json_object *jso, TPMT_HA *out);
+
+TSS2_RC
+ifapi_json_TPM2B_DIGEST_deserialize(json_object *jso, TPM2B_DIGEST *out);
+
+TSS2_RC
+ifapi_json_TPM2B_DATA_deserialize(json_object *jso, TPM2B_DATA *out);
+
+TSS2_RC
+ifapi_json_TPM2B_NONCE_deserialize(json_object *jso, TPM2B_NONCE *out);
+
+TSS2_RC
+ifapi_json_TPM2B_OPERAND_deserialize(json_object *jso, TPM2B_OPERAND *out);
+
+TSS2_RC
+ifapi_json_TPM2B_EVENT_deserialize(json_object *jso, TPM2B_EVENT *out);
+
+TSS2_RC
+ifapi_json_TPM2B_MAX_NV_BUFFER_deserialize(json_object *jso,
+        TPM2B_MAX_NV_BUFFER *out);
+
+TSS2_RC
+ifapi_json_TPM2B_NAME_deserialize(json_object *jso, TPM2B_NAME *out);
+
+TSS2_RC
+ifapi_json_TPMS_PCR_SELECT_deserialize(json_object *jso, TPMS_PCR_SELECT *out);
+
+TSS2_RC
+ifapi_json_TPMS_PCR_SELECTION_deserialize(json_object *jso,
+        TPMS_PCR_SELECTION *out);
+
+TSS2_RC
+ifapi_json_TPMT_TK_CREATION_deserialize(json_object *jso,
+                                        TPMT_TK_CREATION *out);
+
+TSS2_RC
+ifapi_json_TPMT_TK_VERIFIED_deserialize(json_object *jso,
+                                        TPMT_TK_VERIFIED *out);
+
+TSS2_RC
+ifapi_json_TPML_DIGEST_VALUES_deserialize(json_object *jso,
+        TPML_DIGEST_VALUES *out);
+
+TSS2_RC
+ifapi_json_TPML_PCR_SELECTION_deserialize(json_object *jso,
+        TPML_PCR_SELECTION *out);
+
+TSS2_RC
+ifapi_json_TPMS_CLOCK_INFO_deserialize(json_object *jso, TPMS_CLOCK_INFO *out);
+
+TSS2_RC
+ifapi_json_TPMS_TIME_INFO_deserialize(json_object *jso, TPMS_TIME_INFO *out);
+
+TSS2_RC
+ifapi_json_TPMS_TIME_ATTEST_INFO_deserialize(json_object *jso,
+        TPMS_TIME_ATTEST_INFO *out);
+
+TSS2_RC
+ifapi_json_TPMS_CERTIFY_INFO_deserialize(json_object *jso,
+        TPMS_CERTIFY_INFO *out);
+
+TSS2_RC
+ifapi_json_TPMS_QUOTE_INFO_deserialize(json_object *jso, TPMS_QUOTE_INFO *out);
+
+TSS2_RC
+ifapi_json_TPMS_COMMAND_AUDIT_INFO_deserialize(json_object *jso,
+        TPMS_COMMAND_AUDIT_INFO *out);
+
+TSS2_RC
+ifapi_json_TPMS_SESSION_AUDIT_INFO_deserialize(json_object *jso,
+        TPMS_SESSION_AUDIT_INFO *out);
+
+TSS2_RC
+ifapi_json_TPMS_CREATION_INFO_deserialize(json_object *jso,
+        TPMS_CREATION_INFO *out);
+
+TSS2_RC
+ifapi_json_TPMS_NV_CERTIFY_INFO_deserialize(json_object *jso,
+        TPMS_NV_CERTIFY_INFO *out);
+
+TSS2_RC
+ifapi_json_TPMI_ST_ATTEST_deserialize(json_object *jso, TPMI_ST_ATTEST *out);
+
+TSS2_RC
+ifapi_json_TPMI_ST_ATTEST_deserialize_txt(json_object *jso,
+        TPMI_ST_ATTEST *out);
+
+TSS2_RC
+ifapi_json_TPMU_ATTEST_deserialize(UINT32 selector, json_object *jso,
+                                   TPMU_ATTEST *out);
+
+TSS2_RC
+ifapi_json_TPMS_ATTEST_deserialize(json_object *jso, TPMS_ATTEST *out);
+
+TSS2_RC
+ifapi_json_TPMI_AES_KEY_BITS_deserialize(json_object *jso,
+        TPMI_AES_KEY_BITS *out);
+
+TSS2_RC
+ifapi_json_TPMI_AES_KEY_BITS_deserialize_txt(json_object *jso,
+        TPMI_AES_KEY_BITS *out);
+
+TSS2_RC
+ifapi_json_TPMU_SYM_KEY_BITS_deserialize(UINT32 selector, json_object *jso,
+        TPMU_SYM_KEY_BITS *out);
+
+TSS2_RC
+ifapi_json_TPMU_SYM_MODE_deserialize(UINT32 selector, json_object *jso,
+                                     TPMU_SYM_MODE *out);
+
+TSS2_RC
+ifapi_json_TPMT_SYM_DEF_deserialize(json_object *jso, TPMT_SYM_DEF *out);
+
+TSS2_RC
+ifapi_json_TPMT_SYM_DEF_OBJECT_deserialize(json_object *jso,
+        TPMT_SYM_DEF_OBJECT *out);
+
+TSS2_RC
+ifapi_json_TPMS_SYMCIPHER_PARMS_deserialize(json_object *jso,
+        TPMS_SYMCIPHER_PARMS *out);
+
+TSS2_RC
+ifapi_json_TPMS_SCHEME_HASH_deserialize(json_object *jso,
+                                        TPMS_SCHEME_HASH *out);
+
+TSS2_RC
+ifapi_json_TPMS_SCHEME_ECDAA_deserialize(json_object *jso,
+        TPMS_SCHEME_ECDAA *out);
+
+TSS2_RC
+ifapi_json_TPMI_ALG_KEYEDHASH_SCHEME_deserialize(json_object *jso,
+        TPMI_ALG_KEYEDHASH_SCHEME *out);
+
+TSS2_RC
+ifapi_json_TPMI_ALG_KEYEDHASH_SCHEME_deserialize_txt(json_object *jso,
+        TPMI_ALG_KEYEDHASH_SCHEME *out);
+
+TSS2_RC
+ifapi_json_TPMS_SCHEME_HMAC_deserialize(json_object *jso,
+                                        TPMS_SCHEME_HMAC *out);
+
+TSS2_RC
+ifapi_json_TPMS_SCHEME_XOR_deserialize(json_object *jso, TPMS_SCHEME_XOR *out);
+
+TSS2_RC
+ifapi_json_TPMU_SCHEME_KEYEDHASH_deserialize(UINT32 selector, json_object *jso,
+        TPMU_SCHEME_KEYEDHASH *out);
+
+TSS2_RC
+ifapi_json_TPMT_KEYEDHASH_SCHEME_deserialize(json_object *jso,
+        TPMT_KEYEDHASH_SCHEME *out);
+
+TSS2_RC
+ifapi_json_TPMS_SIG_SCHEME_RSASSA_deserialize(json_object *jso,
+        TPMS_SIG_SCHEME_RSASSA *out);
+
+TSS2_RC
+ifapi_json_TPMS_SIG_SCHEME_RSAPSS_deserialize(json_object *jso,
+        TPMS_SIG_SCHEME_RSAPSS *out);
+
+TSS2_RC
+ifapi_json_TPMS_SIG_SCHEME_ECDSA_deserialize(json_object *jso,
+        TPMS_SIG_SCHEME_ECDSA *out);
+
+TSS2_RC
+ifapi_json_TPMS_SIG_SCHEME_SM2_deserialize(json_object *jso,
+        TPMS_SIG_SCHEME_SM2 *out);
+
+TSS2_RC
+ifapi_json_TPMS_SIG_SCHEME_ECSCHNORR_deserialize(json_object *jso,
+        TPMS_SIG_SCHEME_ECSCHNORR *out);
+
+TSS2_RC
+ifapi_json_TPMS_SIG_SCHEME_ECDAA_deserialize(json_object *jso,
+        TPMS_SIG_SCHEME_ECDAA *out);
+
+TSS2_RC
+ifapi_json_TPMU_SIG_SCHEME_deserialize(UINT32 selector, json_object *jso,
+                                       TPMU_SIG_SCHEME *out);
+
+TSS2_RC
+ifapi_json_TPMT_SIG_SCHEME_deserialize(json_object *jso, TPMT_SIG_SCHEME *out);
+
+TSS2_RC
+ifapi_json_TPMS_ENC_SCHEME_OAEP_deserialize(json_object *jso,
+        TPMS_ENC_SCHEME_OAEP *out);
+
+TSS2_RC
+ifapi_json_TPMS_ENC_SCHEME_RSAES_deserialize(json_object *jso,
+        TPMS_ENC_SCHEME_RSAES *out);
+
+TSS2_RC
+ifapi_json_TPMS_KEY_SCHEME_ECDH_deserialize(json_object *jso,
+        TPMS_KEY_SCHEME_ECDH *out);
+
+TSS2_RC
+ifapi_json_TPMS_SCHEME_MGF1_deserialize(json_object *jso,
+                                        TPMS_SCHEME_MGF1 *out);
+
+TSS2_RC
+ifapi_json_TPMS_SCHEME_KDF1_SP800_56A_deserialize(json_object *jso,
+        TPMS_SCHEME_KDF1_SP800_56A *out);
+
+TSS2_RC
+ifapi_json_TPMS_SCHEME_KDF1_SP800_108_deserialize(json_object *jso,
+        TPMS_SCHEME_KDF1_SP800_108 *out);
+
+TSS2_RC
+ifapi_json_TPMU_KDF_SCHEME_deserialize(UINT32 selector, json_object *jso,
+                                       TPMU_KDF_SCHEME *out);
+
+TSS2_RC
+ifapi_json_TPMT_KDF_SCHEME_deserialize(json_object *jso, TPMT_KDF_SCHEME *out);
+
+TSS2_RC
+ifapi_json_TPMU_ASYM_SCHEME_deserialize(UINT32 selector, json_object *jso,
+                                        TPMU_ASYM_SCHEME *out);
+
+TSS2_RC
+ifapi_json_TPMI_ALG_RSA_SCHEME_deserialize(json_object *jso,
+        TPMI_ALG_RSA_SCHEME *out);
+
+TSS2_RC
+ifapi_json_TPMI_ALG_RSA_SCHEME_deserialize_txt(json_object *jso,
+        TPMI_ALG_RSA_SCHEME *out);
+
+TSS2_RC
+ifapi_json_TPMT_RSA_SCHEME_deserialize(json_object *jso, TPMT_RSA_SCHEME *out);
+
+TSS2_RC
+ifapi_json_TPMI_ALG_RSA_DECRYPT_deserialize(json_object *jso,
+        TPMI_ALG_RSA_DECRYPT *out);
+
+TSS2_RC
+ifapi_json_TPMI_ALG_RSA_DECRYPT_deserialize_txt(json_object *jso,
+        TPMI_ALG_RSA_DECRYPT *out);
+
+TSS2_RC
+ifapi_json_TPMT_RSA_DECRYPT_deserialize(json_object *jso,
+                                        TPMT_RSA_DECRYPT *out);
+
+TSS2_RC
+ifapi_json_TPM2B_PUBLIC_KEY_RSA_deserialize(json_object *jso,
+        TPM2B_PUBLIC_KEY_RSA *out);
+
+TSS2_RC
+ifapi_json_TPMI_RSA_KEY_BITS_deserialize(json_object *jso,
+        TPMI_RSA_KEY_BITS *out);
+
+TSS2_RC
+ifapi_json_TPMI_RSA_KEY_BITS_deserialize_txt(json_object *jso,
+        TPMI_RSA_KEY_BITS *out);
+
+TSS2_RC
+ifapi_json_TPM2B_ECC_PARAMETER_deserialize(json_object *jso,
+        TPM2B_ECC_PARAMETER *out);
+
+TSS2_RC
+ifapi_json_TPMS_ECC_POINT_deserialize(json_object *jso, TPMS_ECC_POINT *out);
+
+TSS2_RC
+ifapi_json_TPMI_ALG_ECC_SCHEME_deserialize(json_object *jso,
+        TPMI_ALG_ECC_SCHEME *out);
+
+TSS2_RC
+ifapi_json_TPMI_ALG_ECC_SCHEME_deserialize_txt(json_object *jso,
+        TPMI_ALG_ECC_SCHEME *out);
+
+TSS2_RC
+ifapi_json_TPMI_ECC_CURVE_deserialize(json_object *jso, TPMI_ECC_CURVE *out);
+
+TSS2_RC
+ifapi_json_TPMI_ECC_CURVE_deserialize_txt(json_object *jso,
+        TPMI_ECC_CURVE *out);
+
+TSS2_RC
+ifapi_json_TPMT_ECC_SCHEME_deserialize(json_object *jso, TPMT_ECC_SCHEME *out);
+
+TSS2_RC
+ifapi_json_TPMS_SIGNATURE_RSA_deserialize(json_object *jso,
+        TPMS_SIGNATURE_RSA *out);
+
+TSS2_RC
+ifapi_json_TPMS_SIGNATURE_RSASSA_deserialize(json_object *jso,
+        TPMS_SIGNATURE_RSASSA *out);
+
+TSS2_RC
+ifapi_json_TPMS_SIGNATURE_RSAPSS_deserialize(json_object *jso,
+        TPMS_SIGNATURE_RSAPSS *out);
+
+TSS2_RC
+ifapi_json_TPMS_SIGNATURE_ECC_deserialize(json_object *jso,
+        TPMS_SIGNATURE_ECC *out);
+
+TSS2_RC
+ifapi_json_TPMS_SIGNATURE_ECDSA_deserialize(json_object *jso,
+        TPMS_SIGNATURE_ECDSA *out);
+
+TSS2_RC
+ifapi_json_TPMS_SIGNATURE_ECDAA_deserialize(json_object *jso,
+        TPMS_SIGNATURE_ECDAA *out);
+
+TSS2_RC
+ifapi_json_TPMS_SIGNATURE_SM2_deserialize(json_object *jso,
+        TPMS_SIGNATURE_SM2 *out);
+
+TSS2_RC
+ifapi_json_TPMS_SIGNATURE_ECSCHNORR_deserialize(json_object *jso,
+        TPMS_SIGNATURE_ECSCHNORR *out);
+
+TSS2_RC
+ifapi_json_TPMU_SIGNATURE_deserialize(UINT32 selector, json_object *jso,
+                                      TPMU_SIGNATURE *out);
+
+TSS2_RC
+ifapi_json_TPMT_SIGNATURE_deserialize(json_object *jso, TPMT_SIGNATURE *out);
+
+TSS2_RC
+ifapi_json_TPM2B_ENCRYPTED_SECRET_deserialize(json_object *jso,
+        TPM2B_ENCRYPTED_SECRET *out);
+
+TSS2_RC
+ifapi_json_TPMI_ALG_PUBLIC_deserialize(json_object *jso, TPMI_ALG_PUBLIC *out);
+
+TSS2_RC
+ifapi_json_TPMI_ALG_PUBLIC_deserialize_txt(json_object *jso,
+        TPMI_ALG_PUBLIC *out);
+
+TSS2_RC
+ifapi_json_TPMU_PUBLIC_ID_deserialize(UINT32 selector, json_object *jso,
+                                      TPMU_PUBLIC_ID *out);
+
+TSS2_RC
+ifapi_json_TPMS_KEYEDHASH_PARMS_deserialize(json_object *jso,
+        TPMS_KEYEDHASH_PARMS *out);
+
+TSS2_RC
+ifapi_json_TPMS_RSA_PARMS_deserialize(json_object *jso, TPMS_RSA_PARMS *out);
+
+TSS2_RC
+ifapi_json_TPMS_ECC_PARMS_deserialize(json_object *jso, TPMS_ECC_PARMS *out);
+
+TSS2_RC
+ifapi_json_TPMU_PUBLIC_PARMS_deserialize(UINT32 selector, json_object *jso,
+        TPMU_PUBLIC_PARMS *out);
+
+TSS2_RC
+ifapi_json_TPMT_PUBLIC_deserialize(json_object *jso, TPMT_PUBLIC *out);
+
+TSS2_RC
+ifapi_json_TPM2B_PUBLIC_deserialize(json_object *jso, TPM2B_PUBLIC *out);
+
+TSS2_RC
+ifapi_json_TPM2B_PRIVATE_deserialize(json_object *jso, TPM2B_PRIVATE *out);
+
+TSS2_RC
+ifapi_json_TPM2_NT_deserialize(json_object *jso, TPM2_NT *out);
+
+TSS2_RC
+ifapi_json_TPM2_NT_deserialize_txt(json_object *jso, TPM2_NT *out);
+
+TSS2_RC
+ifapi_json_TPMA_NV_deserialize(json_object *jso, TPMA_NV *out);
+
+TSS2_RC
+ifapi_json_TPMS_NV_PUBLIC_deserialize(json_object *jso, TPMS_NV_PUBLIC *out);
+
+TSS2_RC
+ifapi_json_TPM2B_NV_PUBLIC_deserialize(json_object *jso, TPM2B_NV_PUBLIC *out);
+
+TSS2_RC
+ifapi_json_TPMS_CREATION_DATA_deserialize(json_object *jso,
+        TPMS_CREATION_DATA *out);
+
+TSS2_RC
+ifapi_json_TPM2B_CREATION_DATA_deserialize(json_object *jso,
+        TPM2B_CREATION_DATA *out);
+
+#endif /* FAPI_TPM_JSON_DESERIALIZE_H */
diff --git a/src/tss2-fapi/tpm_json_serialize.c b/src/tss2-fapi/tpm_json_serialize.c
new file mode 100644
index 0000000..2d1f72c
--- /dev/null
+++ b/src/tss2-fapi/tpm_json_serialize.c
@@ -0,0 +1,3905 @@
+/* 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 "tpm_json_serialize.h"
+#define LOGMODULE fapijson
+#include "util/log.h"
+#include "util/aux_util.h"
+
+#define CHECK_IN_LIST(type, needle, ...) \
+    type tab[] = { __VA_ARGS__ }; \
+    size_t i; \
+    for(i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) \
+        if (needle == tab[i]) \
+            break; \
+    if (i == sizeof(tab) / sizeof(tab[0])) { \
+        LOG_ERROR("Bad value"); \
+        return TSS2_FAPI_RC_BAD_VALUE; \
+    }
+
+/** Serialize a TPMS_EMPTY.
+ *
+ * @param[in] in Structure to be serialized.
+ * @retval TSS2_RC_SUCCESS is always returnde.
+ */
+TSS2_RC
+ifapi_json_TPMS_EMPTY_serialize(const TPMS_EMPTY *in, json_object **jso)
+{
+    (void)(in);
+    (void)(jso);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize a pcr selection to json
+ *
+ * @param[in]  sizeofSelect size of selection byte array.
+ * @param[in]  pcrSelect selection array.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if sizeofSelect is too big.
+ */
+TSS2_RC
+ifapi_json_pcr_select_serialize(
+    const UINT8 sizeofSelect,
+    const BYTE pcrSelect[],
+    json_object **jso)
+{
+    if (*jso == NULL) {
+        *jso = json_object_new_array();
+        return_if_null(*jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+    }
+    if (sizeofSelect > TPM2_PCR_SELECT_MAX) {
+        LOG_ERROR("Too many bytes for array (%"PRIuPTR" > %"PRIuPTR" = TPM2_PCR_SELECT_MAX)",
+                  (size_t)sizeofSelect, (size_t)TPM2_PCR_SELECT_MAX);
+        return TSS2_FAPI_RC_BAD_VALUE;
+    }
+    UINT32 i1, i2;
+    json_object *jso2;
+    for (i1 = 0; i1 < TPM2_PCR_LAST - TPM2_PCR_FIRST; i1++) {
+        i2 = i1 + TPM2_PCR_FIRST;
+        if (pcrSelect[i2 / 8] & (BYTE)(1 << (i2 % 8))) {
+            jso2 = json_object_new_int(i2);
+            if (jso2 == NULL) {
+                return_if_null(jso2, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+            }
+            json_object_array_add(*jso, jso2);
+        }
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize a TPMS_PCR_SELECT structure to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_PCR_SELECTION.
+ */
+TSS2_RC
+ifapi_json_TPMS_PCR_SELECT_serialize(const TPMS_PCR_SELECT *in,
+                                        json_object **jso)
+{
+    TSS2_RC r;
+
+    r = ifapi_json_pcr_select_serialize(in->sizeofSelect, &in->pcrSelect[0], jso);
+    return_if_error(r, "Serialize pcr selection");
+
+    return TSS2_RC_SUCCESS;
+}
+
+
+/** Serialize a TPMS_PCR_SELECTION structure to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_PCR_SELECTION.
+ */
+TSS2_RC
+ifapi_json_TPMS_PCR_SELECTION_serialize(const TPMS_PCR_SELECTION *in,
+                                        json_object **jso)
+{
+    if (*jso == NULL) {
+        *jso = json_object_new_object();
+        return_if_null(*jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+    }
+    TSS2_RC r;
+    json_object *jso2 = NULL;
+    r = ifapi_json_TPMI_ALG_HASH_serialize(in->hash, &jso2);
+    return_if_error(r, "Serialize pcr selection");
+
+    json_object_object_add(*jso, "hash", jso2);
+    jso2 = NULL;
+    r = ifapi_json_pcr_select_serialize(in->sizeofSelect, &in->pcrSelect[0], &jso2);
+    return_if_error(r, "Serialize pcr selection");
+
+    json_object_object_add(*jso, "pcrSelect", jso2);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize a TPMS_TAGGED_PCR_SELECT structure to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_TAGGED_PCR_SELECT.
+ */
+TSS2_RC
+ifapi_json_TPMS_TAGGED_PCR_SELECT_serialize(const TPMS_TAGGED_PCR_SELECT *in,
+        json_object **jso)
+{
+    TSS2_RC r;
+    if (*jso == NULL)
+        *jso = json_object_new_object();
+    json_object *jso2 = NULL;
+    r = ifapi_json_TPM2_PT_PCR_serialize(in->tag, &jso2);
+    return_if_error(r, "Serialize pcr selection");
+
+    json_object_object_add(*jso, "tag", jso2);
+    jso2 = NULL;
+    r = ifapi_json_pcr_select_serialize(in->sizeofSelect, &in->pcrSelect[0], &jso2);
+    return_if_error(r, "Serialize pcr selection");
+
+    json_object_object_add(*jso, "pcrSelect", jso2);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize a base_type UINT16 to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type UINT16.
+ */
+TSS2_RC
+ifapi_json_UINT16_serialize(const UINT16 in, json_object **jso)
+{
+    *jso = json_object_new_int64(in);
+    if (*jso == NULL) {
+        LOG_ERROR("Bad value %04"PRIx16"", in);
+        return TSS2_FAPI_RC_BAD_VALUE;
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize a base_type UINT32 to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type UINT32.
+ */
+TSS2_RC
+ifapi_json_UINT32_serialize(const UINT32 in, json_object **jso)
+{
+    *jso = json_object_new_int64(in);
+    if (*jso == NULL) {
+        LOG_ERROR("Bad value %"PRIx32 "", in);
+        return TSS2_FAPI_RC_BAD_VALUE;
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize a base_type INT32 to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type INT32.
+ */
+TSS2_RC
+ifapi_json_INT32_serialize(const INT32 in, json_object **jso)
+{
+    *jso = json_object_new_int64(in);
+    if (*jso == NULL) {
+        LOG_ERROR("Bad value %"PRIi32 "", in);
+        return TSS2_FAPI_RC_BAD_VALUE;
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize a base_type  UINT64 to json.
+ *
+ * @param[in] in variable to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type UINT64.
+ */
+TSS2_RC
+ifapi_json_UINT64_serialize(UINT64 in, json_object **jso)
+{
+    json_object *jso1 = NULL, *jso2 = NULL;
+    if (in < 0x1000000000000) {
+        *jso = json_object_new_int64(in);
+        if (*jso == NULL) {
+            LOG_ERROR("Bad value %"PRIu32 "", (uint32_t)in);
+            return TSS2_FAPI_RC_BAD_VALUE;
+        }
+        return TSS2_RC_SUCCESS;
+    }
+
+    jso1 = json_object_new_int64(in / 0x100000000);
+    return_if_null(jso1, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+    in %= 0x100000000;
+
+    jso2 = json_object_new_int64(in);
+    if (!jso2) json_object_put(jso1);
+    return_if_null(jso2, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+    *jso = json_object_new_array();
+    if (!*jso) json_object_put(jso1);
+    if (!*jso) json_object_put(jso2);
+    return_if_null(*jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+    json_object_array_add(*jso, jso1);
+    json_object_array_add(*jso, jso2);
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize TPM2_GENERATED to json.
+ *
+ * @param[in] in constant to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the constant is not of type TPM2_GENERATED.
+ */
+TSS2_RC
+ifapi_json_TPM2_GENERATED_serialize(const TPM2_GENERATED in, json_object **jso)
+{
+    if (in != TPM2_GENERATED_VALUE) {
+        return_error(TSS2_FAPI_RC_BAD_VALUE, "Undefined constant.");
+    }
+
+    *jso = json_object_new_string("VALUE");
+    check_oom(*jso);
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize TPM2_ALG_ID to json.
+ *
+ * @param[in] in constant to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the constant is not of type TPM2_ALG_ID.
+ */
+TSS2_RC
+ifapi_json_TPM2_ALG_ID_serialize(const TPM2_ALG_ID in, json_object **jso)
+{
+    static const struct { TPM2_ALG_ID in; const char *name; } tab[] = {
+        { TPM2_ALG_ERROR, "ERROR" },
+        { TPM2_ALG_RSA, "RSA" },
+        { TPM2_ALG_TDES, "TDES" },
+/* We prefer SHA1 as output over SHA */
+/*      { TPM2_ALG_SHA, "SHA" },*/
+        { TPM2_ALG_SHA1, "SHA1" },
+        { TPM2_ALG_CMAC, "CMAC" },
+        { 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" },
+    };
+
+    for (size_t i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
+        if (tab[i].in == in) {
+            *jso = json_object_new_string(tab[i].name);
+            check_oom(*jso);
+            return TSS2_RC_SUCCESS;
+        }
+    }
+    return_error(TSS2_FAPI_RC_BAD_VALUE, "Undefined constant.");
+}
+
+/** Serialize TPM2_ECC_CURVE to json.
+ *
+ * @param[in] in constant to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the constant is not of type TPM2_ECC_CURVE.
+ */
+TSS2_RC
+ifapi_json_TPM2_ECC_CURVE_serialize(const TPM2_ECC_CURVE in, json_object **jso)
+{
+    static const struct { TPM2_ECC_CURVE in; 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" },
+    };
+
+    for (size_t i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
+        if (tab[i].in == in) {
+            *jso = json_object_new_string(tab[i].name);
+            check_oom(*jso);
+            return TSS2_RC_SUCCESS;
+        }
+    }
+    return_error(TSS2_FAPI_RC_BAD_VALUE, "Undefined constant.");
+}
+
+/** Serialize TPM2_CC to json.
+ *
+ * @param[in] in constant to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the constant is not of type TPM2_CC.
+ */
+TSS2_RC
+ifapi_json_TPM2_CC_serialize(const TPM2_CC in, json_object **jso)
+{
+    static const struct { TPM2_CC in; char *name; } tab[] = {
+        /* We don't want to return FIRST but the actual value */
+        /* { 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" },
+        /* We don't want to return LAST but the actual value */
+        /* { TPM2_CC_LAST, "LAST" }, */
+        { TPM2_CC_Vendor_TCG_Test, "Vendor_TCG_Test" },
+    };
+
+    for (size_t i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
+        if (tab[i].in == in) {
+            *jso = json_object_new_string(tab[i].name);
+            check_oom(*jso);
+            return TSS2_RC_SUCCESS;
+        }
+    }
+    return_error(TSS2_FAPI_RC_BAD_VALUE, "Undefined constant.");
+}
+
+/** Serialize TPM2_EO to json.
+ *
+ * @param[in] in constant to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the constant is not of type TPM2_EO.
+ */
+TSS2_RC
+ifapi_json_TPM2_EO_serialize(const TPM2_EO in, json_object **jso)
+{
+    static const struct { TPM2_EO in; char *name; } tab[] = {
+        { TPM2_EO_EQ,          "EQ" },
+        { TPM2_EO_NEQ,         "TPM2_EO_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" },
+    };
+
+    for (size_t i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
+        if (tab[i].in == in) {
+            *jso = json_object_new_string(tab[i].name);
+            check_oom(*jso);
+            return TSS2_RC_SUCCESS;
+        }
+    }
+    return_error(TSS2_FAPI_RC_BAD_VALUE, "Undefined constant.");
+}
+
+/** Serialize TPM2_ST to json.
+ *
+ * @param[in] in constant to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the constant is not of type TPM2_ST.
+ */
+TSS2_RC
+ifapi_json_TPM2_ST_serialize(const TPM2_ST in, json_object **jso)
+{
+    static const struct { TPM2_ST in; 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" },
+    };
+
+    for (size_t i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
+        if (tab[i].in == in) {
+            *jso = json_object_new_string(tab[i].name);
+            check_oom(*jso);
+            return TSS2_RC_SUCCESS;
+        }
+    }
+    return_error(TSS2_FAPI_RC_BAD_VALUE, "Undefined constant.");
+}
+
+/** Serialize TPM2_CAP to json.
+ *
+ * @param[in] in constant to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the constant is not of type TPM2_CAP.
+ */
+TSS2_RC
+ifapi_json_TPM2_CAP_serialize(const TPM2_CAP in, json_object **jso)
+{
+    static const struct { TPM2_CAP in; char *name; } tab[] = {
+        { TPM2_CAP_ALGS, "ALGS" },
+        { TPM2_CAP_HANDLES, "HANDLES" },
+        { TPM2_CAP_COMMANDS, "COMMANDS" },
+        { TPM2_CAP_PP_COMMANDS, "PP_COMMANDS" },
+        { TPM2_CAP_AUDIT_COMMANDS, "AUDIT_COMMANDS" },
+        { TPM2_CAP_PCRS, "PCRS" },
+        { TPM2_CAP_TPM_PROPERTIES, "TPM_PROPERTIES" },
+        { TPM2_CAP_PCR_PROPERTIES, "PCR_PROPERTIES" },
+        { TPM2_CAP_ECC_CURVES, "ECC_CURVES" },
+        { TPM2_CAP_LAST, "LAST" },
+        { TPM2_CAP_VENDOR_PROPERTY, "VENDOR_PROPERTY" },
+    };
+
+    for (size_t i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
+        if (tab[i].in == in) {
+            *jso = json_object_new_string(tab[i].name);
+            check_oom(*jso);
+            return TSS2_RC_SUCCESS;
+        }
+    }
+    return_error(TSS2_FAPI_RC_BAD_VALUE, "Undefined constant.");
+}
+
+/** Serialize TPM2_PT to json.
+ *
+ * @param[in] in constant to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the constant is not of type TPM2_PT.
+ */
+TSS2_RC
+ifapi_json_TPM2_PT_serialize(const TPM2_PT in, json_object **jso)
+{
+    static const struct { TPM2_PT in; char *name; } tab[] = {
+        { TPM2_PT_NONE, "NONE" },
+        { TPM2_PT_GROUP, "GROUP" },
+        { TPM2_PT_FIXED, "FIXED" },
+        { TPM2_PT_FAMILY_INDICATOR, "FAMILY_INDICATOR" },
+        { TPM2_PT_LEVEL, "LEVEL" },
+        { TPM2_PT_REVISION, "REVISION" },
+        { TPM2_PT_DAY_OF_YEAR, "DAY_OF_YEAR" },
+        { TPM2_PT_YEAR, "YEAR" },
+        { TPM2_PT_MANUFACTURER, "MANUFACTURER" },
+        { TPM2_PT_VENDOR_STRING_1, "VENDOR_STRING_1" },
+        { TPM2_PT_VENDOR_STRING_2, "VENDOR_STRING_2" },
+        { TPM2_PT_VENDOR_STRING_3, "VENDOR_STRING_3" },
+        { TPM2_PT_VENDOR_STRING_4, "VENDOR_STRING_4" },
+        { TPM2_PT_VENDOR_TPM_TYPE, "VENDOR_TPM_TYPE" },
+        { TPM2_PT_FIRMWARE_VERSION_1, "FIRMWARE_VERSION_1" },
+        { TPM2_PT_FIRMWARE_VERSION_2, "FIRMWARE_VERSION_2" },
+        { TPM2_PT_INPUT_BUFFER, "INPUT_BUFFER" },
+        { TPM2_PT_HR_TRANSIENT_MIN, "HR_TRANSIENT_MIN" },
+        { TPM2_PT_HR_PERSISTENT_MIN, "HR_PERSISTENT_MIN" },
+        { TPM2_PT_HR_LOADED_MIN, "HR_LOADED_MIN" },
+        { TPM2_PT_ACTIVE_SESSIONS_MAX, "ACTIVE_SESSIONS_MAX" },
+        { TPM2_PT_PCR_COUNT, "PCR_COUNT" },
+        { TPM2_PT_PCR_SELECT_MIN, "PCR_SELECT_MIN" },
+        { TPM2_PT_CONTEXT_GAP_MAX, "CONTEXT_GAP_MAX" },
+        { TPM2_PT_NV_COUNTERS_MAX, "NV_COUNTERS_MAX" },
+        { TPM2_PT_NV_INDEX_MAX, "NV_INDEX_MAX" },
+        { TPM2_PT_MEMORY, "MEMORY" },
+        { TPM2_PT_CLOCK_UPDATE, "CLOCK_UPDATE" },
+        { TPM2_PT_CONTEXT_HASH, "CONTEXT_HASH" },
+        { TPM2_PT_CONTEXT_SYM, "CONTEXT_SYM" },
+        { TPM2_PT_CONTEXT_SYM_SIZE, "CONTEXT_SYM_SIZE" },
+        { TPM2_PT_ORDERLY_COUNT, "ORDERLY_COUNT" },
+        { TPM2_PT_MAX_COMMAND_SIZE, "MAX_COMMAND_SIZE" },
+        { TPM2_PT_MAX_RESPONSE_SIZE, "MAX_RESPONSE_SIZE" },
+        { TPM2_PT_MAX_DIGEST, "MAX_DIGEST" },
+        { TPM2_PT_MAX_OBJECT_CONTEXT, "MAX_OBJECT_CONTEXT" },
+        { TPM2_PT_MAX_SESSION_CONTEXT, "MAX_SESSION_CONTEXT" },
+        { TPM2_PT_PS_FAMILY_INDICATOR, "PS_FAMILY_INDICATOR" },
+        { TPM2_PT_PS_LEVEL, "PS_LEVEL" },
+        { TPM2_PT_PS_REVISION, "PS_REVISION" },
+        { TPM2_PT_PS_DAY_OF_YEAR, "PS_DAY_OF_YEAR" },
+        { TPM2_PT_PS_YEAR, "PS_YEAR" },
+        { TPM2_PT_SPLIT_MAX, "SPLIT_MAX" },
+        { TPM2_PT_TOTAL_COMMANDS, "TOTAL_COMMANDS" },
+        { TPM2_PT_LIBRARY_COMMANDS, "LIBRARY_COMMANDS" },
+        { TPM2_PT_VENDOR_COMMANDS, "VENDOR_COMMANDS" },
+        { TPM2_PT_NV_BUFFER_MAX, "NV_BUFFER_MAX" },
+        { TPM2_PT_MODES, "MODES" },
+        { TPM2_PT_MAX_CAP_BUFFER, "MAX_CAP_BUFFER" },
+        { TPM2_PT_VAR, "VAR" },
+        { TPM2_PT_PERMANENT, "PERMANENT" },
+        { TPM2_PT_STARTUP_CLEAR, "STARTUP_CLEAR" },
+        { TPM2_PT_HR_NV_INDEX, "HR_NV_INDEX" },
+        { TPM2_PT_HR_LOADED, "HR_LOADED" },
+        { TPM2_PT_HR_LOADED_AVAIL, "HR_LOADED_AVAIL" },
+        { TPM2_PT_HR_ACTIVE, "HR_ACTIVE" },
+        { TPM2_PT_HR_ACTIVE_AVAIL, "HR_ACTIVE_AVAIL" },
+        { TPM2_PT_HR_TRANSIENT_AVAIL, "HR_TRANSIENT_AVAIL" },
+        { TPM2_PT_HR_PERSISTENT, "HR_PERSISTENT" },
+        { TPM2_PT_HR_PERSISTENT_AVAIL, "HR_PERSISTENT_AVAIL" },
+        { TPM2_PT_NV_COUNTERS, "NV_COUNTERS" },
+        { TPM2_PT_NV_COUNTERS_AVAIL, "NV_COUNTERS_AVAIL" },
+        { TPM2_PT_ALGORITHM_SET, "ALGORITHM_SET" },
+        { TPM2_PT_LOADED_CURVES, "LOADED_CURVES" },
+        { TPM2_PT_LOCKOUT_COUNTER, "LOCKOUT_COUNTER" },
+        { TPM2_PT_MAX_AUTH_FAIL, "MAX_AUTH_FAIL" },
+        { TPM2_PT_LOCKOUT_INTERVAL, "LOCKOUT_INTERVAL" },
+        { TPM2_PT_LOCKOUT_RECOVERY, "LOCKOUT_RECOVERY" },
+        { TPM2_PT_NV_WRITE_RECOVERY, "NV_WRITE_RECOVERY" },
+        { TPM2_PT_AUDIT_COUNTER_0, "AUDIT_COUNTER_0" },
+        { TPM2_PT_AUDIT_COUNTER_1, "AUDIT_COUNTER_1" },
+    };
+
+    for (size_t i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
+        if (tab[i].in == in) {
+            *jso = json_object_new_string(tab[i].name);
+            check_oom(*jso);
+            return TSS2_RC_SUCCESS;
+        }
+    }
+    return_error2(TSS2_FAPI_RC_BAD_VALUE, "Undefined constant: %"PRIx32, in);
+}
+
+/** Serialize TPM2_PT_PCR to json.
+ *
+ * @param[in] in constant to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the constant is not of type TPM2_PT_PCR.
+ */
+TSS2_RC
+ifapi_json_TPM2_PT_PCR_serialize(const TPM2_PT_PCR in, json_object **jso)
+{
+    static const struct { TPM2_PT_PCR in; char *name; } tab[] = {
+        { 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" },
+    };
+
+    for (size_t i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
+        if (tab[i].in == in) {
+            *jso = json_object_new_string(tab[i].name);
+            check_oom(*jso);
+            return TSS2_RC_SUCCESS;
+        }
+    }
+    return_error2(TSS2_FAPI_RC_BAD_VALUE, "Undefined constant: %"PRIx32, in);
+}
+
+/** Serialize value of type TPM2_HANDLE to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPM2_HANDLE.
+ */
+TSS2_RC
+ifapi_json_TPM2_HANDLE_serialize(const TPM2_HANDLE in, json_object **jso)
+{
+    *jso = json_object_new_int(in);
+    if (*jso == NULL) {
+        LOG_ERROR("Bad value %"PRIx32 "", in);
+        return TSS2_FAPI_RC_BAD_VALUE;
+    }
+    return TSS2_RC_SUCCESS;
+}
+/** Serialize a TPMA_ALGORITHM to json.
+ *
+ * This function expects the Bitfield to be encoded as unsigned int in host-endianess.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the constant is not of type TPMA_ALGORITHM.
+ */
+TSS2_RC
+ifapi_json_TPMA_ALGORITHM_serialize(const TPMA_ALGORITHM in, json_object **jso)
+{
+    static const struct { TPMA_ALGORITHM in; char *name; } tab[] = {
+        { TPMA_ALGORITHM_ASYMMETRIC, "asymmetric" },
+        { TPMA_ALGORITHM_SYMMETRIC, "symmetric" },
+        { TPMA_ALGORITHM_HASH, "hash" },
+        { TPMA_ALGORITHM_OBJECT, "object" },
+        { TPMA_ALGORITHM_SIGNING, "signing" },
+        { TPMA_ALGORITHM_ENCRYPTING, "encrypting" },
+        { TPMA_ALGORITHM_METHOD, "method" },
+    };
+
+    UINT32 input;
+    input = (UINT32) in;
+    json_object *jso_bit;
+    if (*jso == NULL) {
+        *jso = json_object_new_object();
+        return_if_null(*jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+    }
+    for (size_t i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
+        if (tab[i].in & input)
+            jso_bit = json_object_new_int(1);
+        else
+            jso_bit = json_object_new_int(0);
+        return_if_null(jso_bit, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+        json_object_object_add(*jso, tab[i].name, jso_bit);
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize a TPMA_OBJECT to json.
+ *
+ * This function expects the Bitfield to be encoded as unsigned int in host-endianess.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the constant is not of type TPMA_OBJECT.
+ */
+TSS2_RC
+ifapi_json_TPMA_OBJECT_serialize(const TPMA_OBJECT in, json_object **jso)
+{
+    static const 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" },
+    };
+    UINT32 input;
+    input = (UINT32) in;
+    json_object *jso_bit;
+    if (*jso == NULL) {
+        *jso = json_object_new_object();
+        return_if_null(*jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+    }
+    for (size_t i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
+        if (tab[i].in & input)
+            jso_bit = json_object_new_int(1);
+        else
+            jso_bit = json_object_new_int(0);
+        return_if_null(jso_bit, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+        json_object_object_add(*jso, tab[i].name, jso_bit);
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize a TPMA_LOCALITY to json.
+ *
+ * This function expects the Bitfield to be encoded as unsigned int in host-endianess.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the constant is not of type TPMA_LOCALITY.
+ */
+TSS2_RC
+ifapi_json_TPMA_LOCALITY_serialize(const TPMA_LOCALITY in, json_object **jso)
+{
+    static const 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" },
+    };
+
+    UINT8 input;
+    input = (UINT8) in;
+    json_object *jso_bit;
+    json_object *jso_bit_idx;
+    if (*jso == NULL) {
+        *jso = json_object_new_object();
+        return_if_null(*jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+    }
+    for (size_t i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
+        if (tab[i].in & input)
+            jso_bit = json_object_new_int(1);
+        else
+            jso_bit = json_object_new_int(0);
+        return_if_null(jso_bit, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+        json_object_object_add(*jso, tab[i].name, jso_bit);
+    }
+    jso_bit_idx = json_object_new_int64((TPMA_LOCALITY_EXTENDED_MASK & input) >>
+                                         5);
+    return_if_null(jso_bit_idx, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+    json_object_object_add(*jso, "Extended", jso_bit_idx);
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize a TPMA_CC to json.
+ *
+ * This function expects the Bitfield to be encoded as unsigned int in host-endianess.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the constant is not of type TPMA_CC.
+ */
+
+TSS2_RC
+ifapi_json_TPMA_CC_serialize(const TPMA_CC in, json_object **jso)
+{
+    static const struct { TPMA_CC in; char *name; } tab[] = {
+        { TPMA_CC_NV, "nv" },
+        { TPMA_CC_EXTENSIVE, "extensive" },
+        { TPMA_CC_FLUSHED, "flushed" },
+        { TPMA_CC_RHANDLE, "rHandle" },
+        { TPMA_CC_V, "V" },
+    };
+    TPM2_CC input;
+    input = (TPM2_CC) in;
+    json_object *jso_bit;
+    json_object *jso_bit_idx;
+    if (*jso == NULL) {
+        *jso = json_object_new_object();
+        return_if_null(*jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+    }
+    for (size_t i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
+        if (tab[i].in & input)
+            jso_bit = json_object_new_int(1);
+        else
+            jso_bit = json_object_new_int(0);
+        return_if_null(jso_bit, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+        json_object_object_add(*jso, tab[i].name, jso_bit);
+    }
+    jso_bit_idx =  json_object_new_int64((TPMA_CC_COMMANDINDEX_MASK & input) >> 0);
+    return_if_null(jso_bit_idx, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+    json_object_object_add(*jso, "commandIndex", jso_bit_idx);
+
+    jso_bit_idx =  json_object_new_int64((TPMA_CC_CHANDLES_MASK & input) >> 25);
+    return_if_null(jso_bit_idx, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+    json_object_object_add(*jso, "cHandles", jso_bit_idx);
+
+    jso_bit_idx =  json_object_new_int64((TPMA_CC_RES_MASK & input) >> 30);
+    return_if_null(jso_bit_idx, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+    json_object_object_add(*jso, "Res", jso_bit_idx);
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize TPMI_YES_NO to json.
+ *
+ * @param[in] in variable to be serialized.
+ * @param[out] jso pointer to the json object.
+ */
+TSS2_RC
+ifapi_json_TPMI_YES_NO_serialize(const TPMI_YES_NO in, json_object **jso)
+{
+    if (in == YES) {
+        *jso = json_object_new_string("YES");
+    } else if (in == NO) {
+        *jso = json_object_new_string("NO");
+    } else {
+        return_error(TSS2_FAPI_RC_BAD_VALUE, "Undefined constant.");
+    }
+    check_oom(*jso);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize TPMI_RH_HIERARCHY to json.
+ *
+ * @param[in] in variable to be serialized.
+ * @param[out] jso pointer to the json object.
+ */
+TSS2_RC
+ifapi_json_TPMI_RH_HIERARCHY_serialize(const TPMI_RH_HIERARCHY in,
+                                       json_object **jso)
+{
+    static const struct { TPMI_RH_HIERARCHY in; char *name; } tab[] = {
+        { TPM2_RH_OWNER, "OWNER" },
+        { TPM2_RH_PLATFORM, "PLATFORM" },
+        { TPM2_RH_ENDORSEMENT, "ENDORSEMENT" },
+        { TPM2_RH_NULL, "NULL" },
+    };
+
+    for (size_t i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
+        if (tab[i].in == in) {
+            *jso = json_object_new_string(tab[i].name);
+            check_oom(*jso);
+            return TSS2_RC_SUCCESS;
+        }
+    }
+    return_error(TSS2_FAPI_RC_BAD_VALUE, "Undefined constant.");
+}
+
+/** Serialize value of type TPMI_RH_NV_INDEX to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMI_RH_NV_INDEX.
+ *
+ */
+TSS2_RC
+ifapi_json_TPMI_RH_NV_INDEX_serialize(const TPMI_RH_NV_INDEX in,
+                                      json_object **jso)
+{
+    if (in >= TPM2_NV_INDEX_FIRST && in <= TPM2_NV_INDEX_LAST) {
+        *jso = json_object_new_int64(in);
+    } else {
+        return_error(TSS2_FAPI_RC_BAD_VALUE, "Undefined constant.");
+    }
+    return_if_null(*jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize TPMI_ALG_HASH to json.
+ *
+ * @param[in] in variable to be serialized.
+ * @param[out] jso pointer to the json object.
+ */
+TSS2_RC
+ifapi_json_TPMI_ALG_HASH_serialize(const TPMI_ALG_HASH in, json_object **jso)
+{
+    CHECK_IN_LIST(TPMI_ALG_HASH, in, TPM2_ALG_SHA1, TPM2_ALG_SHA256, TPM2_ALG_SHA384,
+                      TPM2_ALG_SHA512, TPM2_ALG_NULL);
+    return ifapi_json_TPM2_ALG_ID_serialize(in, jso);
+}
+
+/** Serialize TPMI_ALG_SYM_OBJECT to json.
+ *
+ * @param[in] in variable to be serialized.
+ * @param[out] jso pointer to the json object.
+ */
+TSS2_RC
+ifapi_json_TPMI_ALG_SYM_OBJECT_serialize(const TPMI_ALG_SYM_OBJECT in,
+        json_object **jso)
+{
+    CHECK_IN_LIST(TPMI_ALG_SYM_OBJECT, in, TPM2_ALG_AES, TPM2_ALG_NULL);
+    return ifapi_json_TPM2_ALG_ID_serialize(in, jso);
+}
+
+/** Serialize TPMI_ALG_SYM_MODE to json.
+ *
+ * @param[in] in variable to be serialized.
+ * @param[out] jso pointer to the json object.
+ */
+TSS2_RC
+ifapi_json_TPMI_ALG_SYM_MODE_serialize(const TPMI_ALG_SYM_MODE in,
+                                       json_object **jso)
+{
+    CHECK_IN_LIST(TPMI_ALG_SYM_MODE, in, TPM2_ALG_CTR, TPM2_ALG_OFB,
+        TPM2_ALG_CBC, TPM2_ALG_CFB, TPM2_ALG_ECB, TPM2_ALG_NULL);
+    return ifapi_json_TPM2_ALG_ID_serialize(in, jso);
+}
+
+/** Serialize TPMI_ALG_KDF to json.
+ *
+ * @param[in] in variable to be serialized.
+ * @param[out] jso pointer to the json object.
+ */
+TSS2_RC
+ifapi_json_TPMI_ALG_KDF_serialize(const TPMI_ALG_KDF in, json_object **jso)
+{
+    CHECK_IN_LIST(TPMI_ALG_KDF, in, TPM2_ALG_MGF1, TPM2_ALG_KDF1_SP800_56A,
+        TPM2_ALG_KDF1_SP800_108, TPM2_ALG_NULL);
+    return ifapi_json_TPM2_ALG_ID_serialize(in, jso);
+}
+
+/** Serialize TPMI_ALG_SIG_SCHEME to json.
+ *
+ * @param[in] in variable to be serialized.
+ * @param[out] jso pointer to the json object.
+ */
+TSS2_RC
+ifapi_json_TPMI_ALG_SIG_SCHEME_serialize(const TPMI_ALG_SIG_SCHEME in,
+        json_object **jso)
+{
+    CHECK_IN_LIST(TPMI_ALG_SIG_SCHEME, in, TPM2_ALG_RSASSA, TPM2_ALG_RSAPSS,
+        TPM2_ALG_ECDSA, TPM2_ALG_ECDAA, TPM2_ALG_SM2, TPM2_ALG_ECSCHNORR,
+        TPM2_ALG_HMAC, TPM2_ALG_NULL);
+    return ifapi_json_TPM2_ALG_ID_serialize(in, jso);
+}
+
+/**  Serialize a TPMU_HA to json.
+ *
+ * This function expects the Bitfield to be encoded as unsigned int in host-endianess.
+ * @param[in] in the value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMU_HA.
+ */
+TSS2_RC
+ifapi_json_TPMU_HA_serialize(const TPMU_HA *in, UINT32 selector,
+                             json_object **jso)
+{
+    size_t size;
+    const uint8_t *buffer;
+
+    switch (selector) {
+    case TPM2_ALG_SHA1:
+        size = TPM2_SHA1_DIGEST_SIZE;
+        buffer = &in->sha1[0];
+        break;
+    case TPM2_ALG_SHA256:
+        size = TPM2_SHA256_DIGEST_SIZE;
+        buffer = &in->sha256[0];
+        break;
+    case TPM2_ALG_SHA384:
+        size = TPM2_SHA384_DIGEST_SIZE;
+        buffer = &in->sha384[0];
+        break;
+    case TPM2_ALG_SHA512:
+        size = TPM2_SHA512_DIGEST_SIZE;
+        buffer = &in->sha512[0];
+        break;
+    default:
+        LOG_ERROR("\nSelector %"PRIx32 " did not match", selector);
+        return TSS2_FAPI_RC_BAD_VALUE;
+    };
+    char hex_string[(size) * 2 + 1];
+    for (size_t i = 0, off = 0; i < size; i++, off += 2)
+        sprintf(&hex_string[off], "%02x", buffer[i]);
+    hex_string[(size) * 2] = '\0';
+    *jso = json_object_new_string(hex_string);
+    return_if_null(*jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMT_HA to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMT_HA.
+ */
+TSS2_RC
+ifapi_json_TPMT_HA_serialize(const TPMT_HA *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    if (*jso == NULL)
+        *jso = json_object_new_object();
+    jso2 = NULL;
+    r = ifapi_json_TPMI_ALG_HASH_serialize(in->hashAlg, &jso2);
+    return_if_error(r, "Serialize TPMI_ALG_HASH");
+
+    json_object_object_add(*jso, "hashAlg", jso2);
+    if (in->hashAlg != TPM2_ALG_NULL) {
+        json_object *jso2 = NULL;
+        r = ifapi_json_TPMU_HA_serialize(&in->digest, in->hashAlg, &jso2);
+        return_if_error(r, "Serialize TPMU_HA");
+
+        json_object_object_add(*jso, "digest", jso2);
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPM2B_DIGEST to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPM2B_DIGEST.
+ */
+TSS2_RC
+ifapi_json_TPM2B_DIGEST_serialize(const TPM2B_DIGEST *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    if (in->size > sizeof(TPMU_HA)) {
+        LOG_ERROR("Too many bytes for array (%"PRIuPTR" > %"PRIuPTR" = sizeof(TPMU_HA))",
+                  (size_t)in->size, (size_t)sizeof(TPMU_HA));
+        return TSS2_FAPI_RC_BAD_VALUE;
+    }
+    char hex_string[((size_t)in->size)*2+1];
+
+    for (size_t i = 0, off = 0; i < in->size; i++, off+=2)
+        sprintf(&hex_string[off], "%02x", in->buffer[i]);
+    hex_string[(in->size)*2] = '\0';
+    *jso = json_object_new_string (hex_string);
+    return_if_null(*jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPM2B_DATA to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPM2B_DATA.
+ */
+TSS2_RC
+ifapi_json_TPM2B_DATA_serialize(const TPM2B_DATA *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    if (in->size > sizeof(TPMT_HA)) {
+        LOG_ERROR("Too many bytes for array (%"PRIuPTR" > %"PRIuPTR" = sizeof(TPMT_HA))",
+                  (size_t)in->size, (size_t)sizeof(TPMT_HA));
+        return TSS2_FAPI_RC_BAD_VALUE;
+    }
+    char hex_string[((size_t)in->size)*2+1];
+
+    for (size_t i = 0, off = 0; i < in->size; i++, off+=2)
+        sprintf(&hex_string[off], "%02x", in->buffer[i]);
+    hex_string[(in->size)*2] = '\0';
+    *jso = json_object_new_string (hex_string);
+    return_if_null(*jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize a TPM2B_NONCE to json.
+ *
+ * @param[in] in value of type TPM2B_NONCE to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPM2B_NONCE.
+ */
+TSS2_RC
+ifapi_json_TPM2B_NONCE_serialize(const TPM2B_NONCE *in, json_object **jso)
+{
+    return ifapi_json_TPM2B_DIGEST_serialize(in, jso);
+}
+
+/** Serialize a TPM2B_OPERAND to json.
+ *
+ * @param[in] in value of type TPM2B_OPERAND to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPM2B_OPERAND.
+ */
+TSS2_RC
+ifapi_json_TPM2B_OPERAND_serialize(const TPM2B_OPERAND *in, json_object **jso)
+{
+    return ifapi_json_TPM2B_DIGEST_serialize(in, jso);
+}
+
+/** Serialize value of type TPM2B_EVENT to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPM2B_EVENT.
+ */
+TSS2_RC
+ifapi_json_TPM2B_EVENT_serialize(const TPM2B_EVENT *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    if (in->size > 1024) {
+        LOG_ERROR("Too many bytes for array (%"PRIuPTR" > %"PRIuPTR" = 1024)",
+                  (size_t)in->size, (size_t)1024);
+        return TSS2_FAPI_RC_BAD_VALUE;
+    }
+    char hex_string[((size_t)in->size)*2+1];
+
+    for (size_t i = 0, off = 0; i < in->size; i++, off+=2)
+        sprintf(&hex_string[off], "%02x", in->buffer[i]);
+    hex_string[(in->size)*2] = '\0';
+    *jso = json_object_new_string (hex_string);
+    return_if_null(*jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPM2B_MAX_NV_BUFFER to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPM2B_MAX_NV_BUFFER.
+ */
+TSS2_RC
+ifapi_json_TPM2B_MAX_NV_BUFFER_serialize(const TPM2B_MAX_NV_BUFFER *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    if (in->size > TPM2_MAX_NV_BUFFER_SIZE) {
+        LOG_ERROR("Too many bytes for array (%"PRIuPTR" > %"PRIuPTR" = TPM2_MAX_NV_BUFFER_SIZE)",
+                  (size_t)in->size, (size_t)TPM2_MAX_NV_BUFFER_SIZE);
+        return TSS2_FAPI_RC_BAD_VALUE;
+    }
+    char hex_string[((size_t)in->size)*2+1];
+
+    for (size_t i = 0, off = 0; i < in->size; i++, off+=2)
+        sprintf(&hex_string[off], "%02x", in->buffer[i]);
+    hex_string[(in->size)*2] = '\0';
+    *jso = json_object_new_string (hex_string);
+    return_if_null(*jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPM2B_NAME to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPM2B_NAME.
+ */
+TSS2_RC
+ifapi_json_TPM2B_NAME_serialize(const TPM2B_NAME *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    if (in->size > sizeof(TPMU_NAME)) {
+        LOG_ERROR("Too many bytes for array (%"PRIuPTR" > %"PRIuPTR" = sizeof(TPMU_NAME))",
+                  (size_t)in->size, (size_t)sizeof(TPMU_NAME));
+        return TSS2_FAPI_RC_BAD_VALUE;
+    }
+    char hex_string[((size_t)in->size)*2+1];
+
+    for (size_t i = 0, off = 0; i < in->size; i++, off+=2)
+        sprintf(&hex_string[off], "%02x", in->name[i]);
+    hex_string[(in->size)*2] = '\0';
+    *jso = json_object_new_string (hex_string);
+    return_if_null(*jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMT_TK_CREATION to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMT_TK_CREATION.
+ */
+TSS2_RC
+ifapi_json_TPMT_TK_CREATION_serialize(const TPMT_TK_CREATION *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    if (*jso == NULL)
+        *jso = json_object_new_object ();
+    if (in != NULL && in->tag != TPM2_ST_CREATION) {
+        LOG_ERROR("BAD VALUE %"PRIuPTR" != %"PRIuPTR,(size_t)in->tag,(size_t)TPM2_ST_CREATION);
+        return  TSS2_FAPI_RC_BAD_VALUE;
+    }
+    jso2 = NULL;
+    r = ifapi_json_TPM2_ST_serialize(in->tag, &jso2);
+    return_if_error(r, "Serialize TPM2_ST");
+
+    json_object_object_add(*jso, "tag", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPMI_RH_HIERARCHY_serialize(in->hierarchy, &jso2);
+    return_if_error(r, "Serialize TPMI_RH_HIERARCHY");
+
+    json_object_object_add(*jso, "hierarchy", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_DIGEST_serialize(&in->digest, &jso2);
+    return_if_error(r, "Serialize TPM2B_DIGEST");
+
+    json_object_object_add(*jso, "digest", jso2);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_ALG_PROPERTY to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_ALG_PROPERTY.
+ */
+TSS2_RC
+ifapi_json_TPMS_ALG_PROPERTY_serialize(const TPMS_ALG_PROPERTY *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    if (*jso == NULL)
+        *jso = json_object_new_object ();
+    jso2 = NULL;
+    r = ifapi_json_TPM2_ALG_ID_serialize(in->alg, &jso2);
+    return_if_error(r, "Serialize TPM2_ALG_ID");
+
+    json_object_object_add(*jso, "alg", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPMA_ALGORITHM_serialize(in->algProperties, &jso2);
+    return_if_error(r, "Serialize TPMA_ALGORITHM");
+
+    json_object_object_add(*jso, "algProperties", jso2);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_TAGGED_PROPERTY to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_TAGGED_PROPERTY.
+ */
+TSS2_RC
+ifapi_json_TPMS_TAGGED_PROPERTY_serialize(const TPMS_TAGGED_PROPERTY *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    if (*jso == NULL)
+        *jso = json_object_new_object ();
+    jso2 = NULL;
+    r = ifapi_json_TPM2_PT_serialize(in->property, &jso2);
+    return_if_error(r, "Serialize TPM2_PT");
+
+    json_object_object_add(*jso, "property", jso2);
+    jso2 = NULL;
+    r = ifapi_json_UINT32_serialize(in->value, &jso2);
+    return_if_error(r, "Serialize UINT32");
+
+    json_object_object_add(*jso, "value", jso2);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPML_CC to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPML_CC.
+ */
+TSS2_RC
+ifapi_json_TPML_CC_serialize(const TPML_CC *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    if (in->count > TPM2_MAX_CAP_CC) {
+        LOG_ERROR("Too many bytes for array (%"PRIuPTR" > %"PRIuPTR" = TPM2_MAX_CAP_CC)",
+                  (size_t)in->count, (size_t)TPM2_MAX_CAP_CC);
+        return TSS2_FAPI_RC_BAD_VALUE;
+    }
+    *jso = json_object_new_array();
+    return_if_null(*jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+    for (size_t i=0; i < in->count; i++) {
+        json_object *jso2 = NULL;
+        r = ifapi_json_TPM2_CC_serialize (in->commandCodes[i], &jso2);
+        return_if_error(r, "Serialize TPM2_CC");
+
+        json_object_array_add(*jso, jso2);
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPML_CCA to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPML_CCA.
+ */
+TSS2_RC
+ifapi_json_TPML_CCA_serialize(const TPML_CCA *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    if (in->count > TPM2_MAX_CAP_CC) {
+        LOG_ERROR("Too many bytes for array (%"PRIuPTR" > %"PRIuPTR" = TPM2_MAX_CAP_CC)",
+                  (size_t)in->count, (size_t)TPM2_MAX_CAP_CC);
+        return TSS2_FAPI_RC_BAD_VALUE;
+    }
+    *jso = json_object_new_array();
+    return_if_null(*jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+    for (size_t i=0; i < in->count; i++) {
+        json_object *jso2 = NULL;
+        r = ifapi_json_TPMA_CC_serialize (in->commandAttributes[i], &jso2);
+        return_if_error(r, "Serialize TPMA_CC");
+
+        json_object_array_add(*jso, jso2);
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPML_HANDLE to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPML_HANDLE.
+ */
+TSS2_RC
+ifapi_json_TPML_HANDLE_serialize(const TPML_HANDLE *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    if (in->count > TPM2_MAX_CAP_HANDLES) {
+        LOG_ERROR("Too many bytes for array (%"PRIuPTR" > %"PRIuPTR" = TPM2_MAX_CAP_HANDLES)",
+                  (size_t)in->count, (size_t)TPM2_MAX_CAP_HANDLES);
+        return TSS2_FAPI_RC_BAD_VALUE;
+    }
+    *jso = json_object_new_array();
+    return_if_null(*jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+    for (size_t i=0; i < in->count; i++) {
+        json_object *jso2 = NULL;
+        r = ifapi_json_TPM2_HANDLE_serialize (in->handle[i], &jso2);
+        return_if_error(r, "Serialize TPM2_HANDLE");
+
+        json_object_array_add(*jso, jso2);
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPML_DIGEST_VALUES to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPML_DIGEST_VALUES.
+ */
+TSS2_RC
+ifapi_json_TPML_DIGEST_VALUES_serialize(const TPML_DIGEST_VALUES *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    if (in->count > TPM2_NUM_PCR_BANKS) {
+        LOG_ERROR("Too many bytes for array (%"PRIuPTR" > %"PRIuPTR" = TPM2_NUM_PCR_BANKS)",
+                  (size_t)in->count, (size_t)TPM2_NUM_PCR_BANKS);
+        return TSS2_FAPI_RC_BAD_VALUE;
+    }
+    *jso = json_object_new_array();
+    return_if_null(*jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+    for (size_t i=0; i < in->count; i++) {
+        json_object *jso2 = NULL;
+        r = ifapi_json_TPMT_HA_serialize (&in->digests[i], &jso2);
+        return_if_error(r, "Serialize TPMT_HA");
+
+        json_object_array_add(*jso, jso2);
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPML_PCR_SELECTION to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPML_PCR_SELECTION.
+ */
+TSS2_RC
+ifapi_json_TPML_PCR_SELECTION_serialize(const TPML_PCR_SELECTION *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    if (in->count > TPM2_NUM_PCR_BANKS) {
+        LOG_ERROR("Too many bytes for array (%"PRIuPTR" > %"PRIuPTR" = TPM2_NUM_PCR_BANKS)",
+                  (size_t)in->count, (size_t)TPM2_NUM_PCR_BANKS);
+        return TSS2_FAPI_RC_BAD_VALUE;
+    }
+    *jso = json_object_new_array();
+    return_if_null(*jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+    for (size_t i=0; i < in->count; i++) {
+        json_object *jso2 = NULL;
+        r = ifapi_json_TPMS_PCR_SELECTION_serialize (&in->pcrSelections[i], &jso2);
+        return_if_error(r, "Serialize TPMS_PCR_SELECTION");
+
+        json_object_array_add(*jso, jso2);
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPML_ALG_PROPERTY to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPML_ALG_PROPERTY.
+ */
+TSS2_RC
+ifapi_json_TPML_ALG_PROPERTY_serialize(const TPML_ALG_PROPERTY *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    if (in->count > TPM2_MAX_CAP_ALGS) {
+        LOG_ERROR("Too many bytes for array (%"PRIuPTR" > %"PRIuPTR" = TPM2_MAX_CAP_ALGS)",
+                  (size_t)in->count, (size_t)TPM2_MAX_CAP_ALGS);
+        return TSS2_FAPI_RC_BAD_VALUE;
+    }
+    *jso = json_object_new_array();
+    return_if_null(*jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+    for (size_t i=0; i < in->count; i++) {
+        json_object *jso2 = NULL;
+        r = ifapi_json_TPMS_ALG_PROPERTY_serialize (&in->algProperties[i], &jso2);
+        return_if_error(r, "Serialize TPMS_ALG_PROPERTY");
+
+        json_object_array_add(*jso, jso2);
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPML_TAGGED_TPM_PROPERTY to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPML_TAGGED_TPM_PROPERTY.
+ */
+TSS2_RC
+ifapi_json_TPML_TAGGED_TPM_PROPERTY_serialize(const TPML_TAGGED_TPM_PROPERTY *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    if (in->count > TPM2_MAX_TPM_PROPERTIES) {
+        LOG_ERROR("Too many bytes for array (%"PRIuPTR" > %"PRIuPTR" = TPM2_MAX_TPM_PROPERTIES)",
+                  (size_t)in->count, (size_t)TPM2_MAX_TPM_PROPERTIES);
+        return TSS2_FAPI_RC_BAD_VALUE;
+    }
+    *jso = json_object_new_array();
+    return_if_null(*jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+    for (size_t i=0; i < in->count; i++) {
+        json_object *jso2 = NULL;
+        r = ifapi_json_TPMS_TAGGED_PROPERTY_serialize (&in->tpmProperty[i], &jso2);
+        return_if_error(r, "Serialize TPMS_TAGGED_PROPERTY");
+
+        json_object_array_add(*jso, jso2);
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPML_TAGGED_PCR_PROPERTY to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPML_TAGGED_PCR_PROPERTY.
+ */
+TSS2_RC
+ifapi_json_TPML_TAGGED_PCR_PROPERTY_serialize(const TPML_TAGGED_PCR_PROPERTY *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    if (in->count > TPM2_MAX_PCR_PROPERTIES) {
+        LOG_ERROR("Too many bytes for array (%"PRIuPTR" > %"PRIuPTR" = TPM2_MAX_PCR_PROPERTIES)",
+                  (size_t)in->count, (size_t)TPM2_MAX_PCR_PROPERTIES);
+        return TSS2_FAPI_RC_BAD_VALUE;
+    }
+    *jso = json_object_new_array();
+    return_if_null(*jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+    for (size_t i=0; i < in->count; i++) {
+        json_object *jso2 = NULL;
+        r = ifapi_json_TPMS_TAGGED_PCR_SELECT_serialize (&in->pcrProperty[i], &jso2);
+        return_if_error(r, "Serialize TPMS_TAGGED_PCR_SELECT");
+
+        json_object_array_add(*jso, jso2);
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPML_ECC_CURVE to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPML_ECC_CURVE.
+ */
+TSS2_RC
+ifapi_json_TPML_ECC_CURVE_serialize(const TPML_ECC_CURVE *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    if (in->count > TPM2_MAX_ECC_CURVES) {
+        LOG_ERROR("Too many bytes for array (%"PRIuPTR" > %"PRIuPTR" = TPM2_MAX_ECC_CURVES)",
+                  (size_t)in->count, (size_t)TPM2_MAX_ECC_CURVES);
+        return TSS2_FAPI_RC_BAD_VALUE;
+    }
+    *jso = json_object_new_array();
+    return_if_null(*jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+    for (size_t i=0; i < in->count; i++) {
+        json_object *jso2 = NULL;
+        r = ifapi_json_TPM2_ECC_CURVE_serialize (in->eccCurves[i], &jso2);
+        return_if_error(r, "Serialize TPM2_ECC_CURVE");
+
+        json_object_array_add(*jso, jso2);
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/**  Serialize a TPMU_CAPABILITIES to json.
+ *
+ * This function expects the Bitfield to be encoded as unsigned int in host-endianess.
+ * @param[in] in the value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMU_CAPABILITIES.
+ */
+TSS2_RC
+ifapi_json_TPMU_CAPABILITIES_serialize(const TPMU_CAPABILITIES *in, UINT32 selector, json_object **jso)
+{
+    switch (selector) {
+        case TPM2_CAP_ALGS:
+            return ifapi_json_TPML_ALG_PROPERTY_serialize(&in->algorithms, jso);
+        case TPM2_CAP_HANDLES:
+            return ifapi_json_TPML_HANDLE_serialize(&in->handles, jso);
+        case TPM2_CAP_COMMANDS:
+            return ifapi_json_TPML_CCA_serialize(&in->command, jso);
+        case TPM2_CAP_PP_COMMANDS:
+            return ifapi_json_TPML_CC_serialize(&in->ppCommands, jso);
+        case TPM2_CAP_AUDIT_COMMANDS:
+            return ifapi_json_TPML_CC_serialize(&in->auditCommands, jso);
+        case TPM2_CAP_PCRS:
+            return ifapi_json_TPML_PCR_SELECTION_serialize(&in->assignedPCR, jso);
+        case TPM2_CAP_TPM_PROPERTIES:
+            return ifapi_json_TPML_TAGGED_TPM_PROPERTY_serialize(&in->tpmProperties, jso);
+        case TPM2_CAP_PCR_PROPERTIES:
+            return ifapi_json_TPML_TAGGED_PCR_PROPERTY_serialize(&in->pcrProperties, jso);
+        case TPM2_CAP_ECC_CURVES:
+            return ifapi_json_TPML_ECC_CURVE_serialize(&in->eccCurves, jso);
+        default:
+            LOG_ERROR("\nSelector %"PRIx32 " did not match", selector);
+            return TSS2_FAPI_RC_BAD_VALUE;
+    };
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_CAPABILITY_DATA to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_CAPABILITY_DATA.
+ */
+TSS2_RC
+ifapi_json_TPMS_CAPABILITY_DATA_serialize(const TPMS_CAPABILITY_DATA *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    if (*jso == NULL)
+        *jso = json_object_new_object ();
+    jso2 = NULL;
+    r = ifapi_json_TPM2_CAP_serialize(in->capability, &jso2);
+    return_if_error(r, "Serialize TPM2_CAP");
+
+    json_object_object_add(*jso, "capability", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPMU_CAPABILITIES_serialize(&in->data, in->capability, &jso2);
+    return_if_error(r,"Serialize TPMU_CAPABILITIES");
+
+    json_object_object_add(*jso, "data", jso2);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_CLOCK_INFO to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_CLOCK_INFO.
+ */
+TSS2_RC
+ifapi_json_TPMS_CLOCK_INFO_serialize(const TPMS_CLOCK_INFO *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    if (*jso == NULL)
+        *jso = json_object_new_object ();
+    jso2 = NULL;
+    r = ifapi_json_UINT64_serialize(in->clock, &jso2);
+    return_if_error(r, "Serialize UINT64");
+
+    json_object_object_add(*jso, "clock", jso2);
+    jso2 = NULL;
+    r = ifapi_json_UINT32_serialize(in->resetCount, &jso2);
+    return_if_error(r, "Serialize UINT32");
+
+    json_object_object_add(*jso, "resetCount", jso2);
+    jso2 = NULL;
+    r = ifapi_json_UINT32_serialize(in->restartCount, &jso2);
+    return_if_error(r, "Serialize UINT32");
+
+    json_object_object_add(*jso, "restartCount", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPMI_YES_NO_serialize(in->safe, &jso2);
+    return_if_error(r, "Serialize TPMI_YES_NO");
+
+    json_object_object_add(*jso, "safe", jso2);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_TIME_INFO to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_TIME_INFO.
+ */
+TSS2_RC
+ifapi_json_TPMS_TIME_INFO_serialize(const TPMS_TIME_INFO *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    if (*jso == NULL)
+        *jso = json_object_new_object ();
+    jso2 = NULL;
+    r = ifapi_json_UINT64_serialize(in->time, &jso2);
+    return_if_error(r, "Serialize UINT64");
+
+    json_object_object_add(*jso, "time", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPMS_CLOCK_INFO_serialize(&in->clockInfo, &jso2);
+    return_if_error(r, "Serialize TPMS_CLOCK_INFO");
+
+    json_object_object_add(*jso, "clockInfo", jso2);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_TIME_ATTEST_INFO to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_TIME_ATTEST_INFO.
+ */
+TSS2_RC
+ifapi_json_TPMS_TIME_ATTEST_INFO_serialize(const TPMS_TIME_ATTEST_INFO *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    if (*jso == NULL)
+        *jso = json_object_new_object ();
+    jso2 = NULL;
+    r = ifapi_json_TPMS_TIME_INFO_serialize(&in->time, &jso2);
+    return_if_error(r, "Serialize TPMS_TIME_INFO");
+
+    json_object_object_add(*jso, "time", jso2);
+    jso2 = NULL;
+    r = ifapi_json_UINT64_serialize(in->firmwareVersion, &jso2);
+    return_if_error(r, "Serialize UINT64");
+
+    json_object_object_add(*jso, "firmwareVersion", jso2);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_CERTIFY_INFO to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_CERTIFY_INFO.
+ */
+TSS2_RC
+ifapi_json_TPMS_CERTIFY_INFO_serialize(const TPMS_CERTIFY_INFO *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    if (*jso == NULL)
+        *jso = json_object_new_object ();
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_NAME_serialize(&in->name, &jso2);
+    return_if_error(r, "Serialize TPM2B_NAME");
+
+    json_object_object_add(*jso, "name", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_NAME_serialize(&in->qualifiedName, &jso2);
+    return_if_error(r, "Serialize TPM2B_NAME");
+
+    json_object_object_add(*jso, "qualifiedName", jso2);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_QUOTE_INFO to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_QUOTE_INFO.
+ */
+TSS2_RC
+ifapi_json_TPMS_QUOTE_INFO_serialize(const TPMS_QUOTE_INFO *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    if (*jso == NULL)
+        *jso = json_object_new_object ();
+    jso2 = NULL;
+    r = ifapi_json_TPML_PCR_SELECTION_serialize(&in->pcrSelect, &jso2);
+    return_if_error(r, "Serialize TPML_PCR_SELECTION");
+
+    json_object_object_add(*jso, "pcrSelect", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_DIGEST_serialize(&in->pcrDigest, &jso2);
+    return_if_error(r, "Serialize TPM2B_DIGEST");
+
+    json_object_object_add(*jso, "pcrDigest", jso2);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_COMMAND_AUDIT_INFO to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_COMMAND_AUDIT_INFO.
+ */
+TSS2_RC
+ifapi_json_TPMS_COMMAND_AUDIT_INFO_serialize(const TPMS_COMMAND_AUDIT_INFO *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    if (*jso == NULL)
+        *jso = json_object_new_object ();
+    jso2 = NULL;
+    r = ifapi_json_UINT64_serialize(in->auditCounter, &jso2);
+    return_if_error(r, "Serialize UINT64");
+
+    json_object_object_add(*jso, "auditCounter", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPM2_ALG_ID_serialize(in->digestAlg, &jso2);
+    return_if_error(r, "Serialize TPM2_ALG_ID");
+
+    json_object_object_add(*jso, "digestAlg", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_DIGEST_serialize(&in->auditDigest, &jso2);
+    return_if_error(r, "Serialize TPM2B_DIGEST");
+
+    json_object_object_add(*jso, "auditDigest", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_DIGEST_serialize(&in->commandDigest, &jso2);
+    return_if_error(r, "Serialize TPM2B_DIGEST");
+
+    json_object_object_add(*jso, "commandDigest", jso2);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_SESSION_AUDIT_INFO to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_SESSION_AUDIT_INFO.
+ */
+TSS2_RC
+ifapi_json_TPMS_SESSION_AUDIT_INFO_serialize(const TPMS_SESSION_AUDIT_INFO *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    if (*jso == NULL)
+        *jso = json_object_new_object ();
+    jso2 = NULL;
+    r = ifapi_json_TPMI_YES_NO_serialize(in->exclusiveSession, &jso2);
+    return_if_error(r, "Serialize TPMI_YES_NO");
+
+    json_object_object_add(*jso, "exclusiveSession", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_DIGEST_serialize(&in->sessionDigest, &jso2);
+    return_if_error(r, "Serialize TPM2B_DIGEST");
+
+    json_object_object_add(*jso, "sessionDigest", jso2);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_CREATION_INFO to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_CREATION_INFO.
+ */
+TSS2_RC
+ifapi_json_TPMS_CREATION_INFO_serialize(const TPMS_CREATION_INFO *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    if (*jso == NULL)
+        *jso = json_object_new_object ();
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_NAME_serialize(&in->objectName, &jso2);
+    return_if_error(r, "Serialize TPM2B_NAME");
+
+    json_object_object_add(*jso, "objectName", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_DIGEST_serialize(&in->creationHash, &jso2);
+    return_if_error(r, "Serialize TPM2B_DIGEST");
+
+    json_object_object_add(*jso, "creationHash", jso2);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_NV_CERTIFY_INFO to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_NV_CERTIFY_INFO.
+ */
+TSS2_RC
+ifapi_json_TPMS_NV_CERTIFY_INFO_serialize(const TPMS_NV_CERTIFY_INFO *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    if (*jso == NULL)
+        *jso = json_object_new_object ();
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_NAME_serialize(&in->indexName, &jso2);
+    return_if_error(r, "Serialize TPM2B_NAME");
+
+    json_object_object_add(*jso, "indexName", jso2);
+    jso2 = NULL;
+    r = ifapi_json_UINT16_serialize(in->offset, &jso2);
+    return_if_error(r, "Serialize UINT16");
+
+    json_object_object_add(*jso, "offset", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_MAX_NV_BUFFER_serialize(&in->nvContents, &jso2);
+    return_if_error(r, "Serialize TPM2B_MAX_NV_BUFFER");
+
+    json_object_object_add(*jso, "nvContents", jso2);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize TPMI_ST_ATTEST to json.
+ *
+ * @param[in] in variable to be serialized.
+ * @param[out] jso pointer to the json object.
+ */
+TSS2_RC
+ifapi_json_TPMI_ST_ATTEST_serialize(const TPMI_ST_ATTEST in, json_object **jso)
+{
+    CHECK_IN_LIST(TPMI_ALG_HASH, in, 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);
+    return ifapi_json_TPM2_ST_serialize(in, jso);
+}
+
+/**  Serialize a TPMU_ATTEST to json.
+ *
+ * This function expects the Bitfield to be encoded as unsigned int in host-endianess.
+ * @param[in] in the value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMU_ATTEST.
+ */
+TSS2_RC
+ifapi_json_TPMU_ATTEST_serialize(const TPMU_ATTEST *in, UINT32 selector, json_object **jso)
+{
+    switch (selector) {
+        case TPM2_ST_ATTEST_CERTIFY:
+            return ifapi_json_TPMS_CERTIFY_INFO_serialize(&in->certify, jso);
+        case TPM2_ST_ATTEST_CREATION:
+            return ifapi_json_TPMS_CREATION_INFO_serialize(&in->creation, jso);
+        case TPM2_ST_ATTEST_QUOTE:
+            return ifapi_json_TPMS_QUOTE_INFO_serialize(&in->quote, jso);
+        case TPM2_ST_ATTEST_COMMAND_AUDIT:
+            return ifapi_json_TPMS_COMMAND_AUDIT_INFO_serialize(&in->commandAudit, jso);
+        case TPM2_ST_ATTEST_SESSION_AUDIT:
+            return ifapi_json_TPMS_SESSION_AUDIT_INFO_serialize(&in->sessionAudit, jso);
+        case TPM2_ST_ATTEST_TIME:
+            return ifapi_json_TPMS_TIME_ATTEST_INFO_serialize(&in->time, jso);
+        case TPM2_ST_ATTEST_NV:
+            return ifapi_json_TPMS_NV_CERTIFY_INFO_serialize(&in->nv, jso);
+        default:
+            LOG_ERROR("\nSelector %"PRIx32 " did not match", selector);
+            return TSS2_FAPI_RC_BAD_VALUE;
+    };
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_ATTEST to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_ATTEST.
+ */
+TSS2_RC
+ifapi_json_TPMS_ATTEST_serialize(const TPMS_ATTEST *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    if (*jso == NULL)
+        *jso = json_object_new_object ();
+    jso2 = NULL;
+    r = ifapi_json_TPM2_GENERATED_serialize(in->magic, &jso2);
+    return_if_error(r, "Serialize TPM2_GENERATED");
+
+    json_object_object_add(*jso, "magic", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPMI_ST_ATTEST_serialize(in->type, &jso2);
+    return_if_error(r, "Serialize TPMI_ST_ATTEST");
+
+    json_object_object_add(*jso, "type", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_NAME_serialize(&in->qualifiedSigner, &jso2);
+    return_if_error(r, "Serialize TPM2B_NAME");
+
+    json_object_object_add(*jso, "qualifiedSigner", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_DATA_serialize(&in->extraData, &jso2);
+    return_if_error(r, "Serialize TPM2B_DATA");
+
+    json_object_object_add(*jso, "extraData", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPMS_CLOCK_INFO_serialize(&in->clockInfo, &jso2);
+    return_if_error(r, "Serialize TPMS_CLOCK_INFO");
+
+    json_object_object_add(*jso, "clockInfo", jso2);
+    jso2 = NULL;
+    r = ifapi_json_UINT64_serialize(in->firmwareVersion, &jso2);
+    return_if_error(r, "Serialize UINT64");
+
+    json_object_object_add(*jso, "firmwareVersion", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPMU_ATTEST_serialize(&in->attested, in->type, &jso2);
+    return_if_error(r,"Serialize TPMU_ATTEST");
+
+    json_object_object_add(*jso, "attested", jso2);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMI_AES_KEY_BITS to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMI_AES_KEY_BITS.
+ *
+ */
+TSS2_RC
+ifapi_json_TPMI_AES_KEY_BITS_serialize(const TPMI_AES_KEY_BITS in, json_object **jso)
+{
+    CHECK_IN_LIST(UINT16, in, 128, 192, 256);
+    return ifapi_json_UINT16_serialize(in, jso);
+}
+
+/**  Serialize a TPMU_SYM_KEY_BITS to json.
+ *
+ * This function expects the Bitfield to be encoded as unsigned int in host-endianess.
+ * @param[in] in the value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMU_SYM_KEY_BITS.
+ */
+TSS2_RC
+ifapi_json_TPMU_SYM_KEY_BITS_serialize(const TPMU_SYM_KEY_BITS *in, UINT32 selector, json_object **jso)
+{
+    switch (selector) {
+        case TPM2_ALG_AES:
+            return ifapi_json_TPMI_AES_KEY_BITS_serialize(in->aes, jso);
+        case TPM2_ALG_XOR:
+            return ifapi_json_TPMI_ALG_HASH_serialize(in->exclusiveOr, jso);
+        default:
+            LOG_ERROR("\nSelector %"PRIx32 " did not match", selector);
+            return TSS2_FAPI_RC_BAD_VALUE;
+    };
+    return TSS2_RC_SUCCESS;
+}
+
+/**  Serialize a TPMU_SYM_MODE to json.
+ *
+ * This function expects the Bitfield to be encoded as unsigned int in host-endianess.
+ * @param[in] in the value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMU_SYM_MODE.
+ */
+TSS2_RC
+ifapi_json_TPMU_SYM_MODE_serialize(const TPMU_SYM_MODE *in, UINT32 selector, json_object **jso)
+{
+    switch (selector) {
+        case TPM2_ALG_AES:
+            return ifapi_json_TPMI_ALG_SYM_MODE_serialize(in->aes, jso);
+        default:
+            LOG_ERROR("\nSelector %"PRIx32 " did not match", selector);
+            return TSS2_FAPI_RC_BAD_VALUE;
+    };
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMT_SYM_DEF_OBJECT to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMT_SYM_DEF_OBJECT.
+ */
+TSS2_RC
+ifapi_json_TPMT_SYM_DEF_OBJECT_serialize(const TPMT_SYM_DEF_OBJECT *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    if (*jso == NULL)
+        *jso = json_object_new_object ();
+    jso2 = NULL;
+    r = ifapi_json_TPMI_ALG_SYM_OBJECT_serialize(in->algorithm, &jso2);
+    return_if_error(r, "Serialize TPMI_ALG_SYM_OBJECT");
+
+    json_object_object_add(*jso, "algorithm", jso2);
+    if (in->algorithm != TPM2_ALG_NULL) {
+        json_object *jso2 = NULL;
+        r = ifapi_json_TPMU_SYM_KEY_BITS_serialize(&in->keyBits, in->algorithm, &jso2);
+        return_if_error(r,"Serialize TPMU_SYM_KEY_BITS");
+
+        json_object_object_add(*jso, "keyBits", jso2);
+    }
+    if (in->algorithm != TPM2_ALG_NULL) {
+        json_object *jso2 = NULL;
+        r = ifapi_json_TPMU_SYM_MODE_serialize(&in->mode, in->algorithm, &jso2);
+        return_if_error(r,"Serialize TPMU_SYM_MODE");
+
+        json_object_object_add(*jso, "mode", jso2);
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_SYMCIPHER_PARMS to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_SYMCIPHER_PARMS.
+ */
+TSS2_RC
+ifapi_json_TPMS_SYMCIPHER_PARMS_serialize(const TPMS_SYMCIPHER_PARMS *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    if (*jso == NULL)
+        *jso = json_object_new_object ();
+    jso2 = NULL;
+    r = ifapi_json_TPMT_SYM_DEF_OBJECT_serialize(&in->sym, &jso2);
+    return_if_error(r, "Serialize TPMT_SYM_DEF_OBJECT");
+
+    json_object_object_add(*jso, "sym", jso2);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_SCHEME_HASH to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_SCHEME_HASH.
+ */
+TSS2_RC
+ifapi_json_TPMS_SCHEME_HASH_serialize(const TPMS_SCHEME_HASH *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    if (*jso == NULL)
+        *jso = json_object_new_object ();
+    jso2 = NULL;
+    r = ifapi_json_TPMI_ALG_HASH_serialize(in->hashAlg, &jso2);
+    return_if_error(r, "Serialize TPMI_ALG_HASH");
+
+    json_object_object_add(*jso, "hashAlg", jso2);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_SCHEME_ECDAA to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_SCHEME_ECDAA.
+ */
+TSS2_RC
+ifapi_json_TPMS_SCHEME_ECDAA_serialize(const TPMS_SCHEME_ECDAA *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    if (*jso == NULL)
+        *jso = json_object_new_object ();
+    jso2 = NULL;
+    r = ifapi_json_TPMI_ALG_HASH_serialize(in->hashAlg, &jso2);
+    return_if_error(r, "Serialize TPMI_ALG_HASH");
+
+    json_object_object_add(*jso, "hashAlg", jso2);
+    jso2 = NULL;
+    r = ifapi_json_UINT16_serialize(in->count, &jso2);
+    return_if_error(r, "Serialize UINT16");
+
+    json_object_object_add(*jso, "count", jso2);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize TPMI_ALG_KEYEDHASH_SCHEME to json.
+ *
+ * @param[in] in variable to be serialized.
+ * @param[out] jso pointer to the json object.
+ */
+TSS2_RC
+ifapi_json_TPMI_ALG_KEYEDHASH_SCHEME_serialize(const TPMI_ALG_KEYEDHASH_SCHEME in, json_object **jso)
+{
+    CHECK_IN_LIST(TPMI_ALG_HASH, in, TPM2_ALG_HMAC, TPM2_ALG_XOR, TPM2_ALG_NULL);
+    return ifapi_json_TPM2_ALG_ID_serialize(in, jso);
+}
+
+/** Serialize a TPMS_SCHEME_HMAC to json.
+ *
+ * @param[in] in value of type TPMS_SCHEME_HMAC to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_SCHEME_HMAC.
+ */
+TSS2_RC
+ifapi_json_TPMS_SCHEME_HMAC_serialize(const TPMS_SCHEME_HMAC *in, json_object **jso)
+{
+    return ifapi_json_TPMS_SCHEME_HASH_serialize(in, jso);
+}
+
+/** Serialize value of type TPMS_SCHEME_XOR to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_SCHEME_XOR.
+ */
+TSS2_RC
+ifapi_json_TPMS_SCHEME_XOR_serialize(const TPMS_SCHEME_XOR *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    if (*jso == NULL)
+        *jso = json_object_new_object ();
+    jso2 = NULL;
+    r = ifapi_json_TPMI_ALG_HASH_serialize(in->hashAlg, &jso2);
+    return_if_error(r, "Serialize TPMI_ALG_HASH");
+
+    json_object_object_add(*jso, "hashAlg", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPMI_ALG_KDF_serialize(in->kdf, &jso2);
+    return_if_error(r, "Serialize TPMI_ALG_KDF");
+
+    json_object_object_add(*jso, "kdf", jso2);
+    return TSS2_RC_SUCCESS;
+}
+
+/**  Serialize a TPMU_SCHEME_KEYEDHASH to json.
+ *
+ * This function expects the Bitfield to be encoded as unsigned int in host-endianess.
+ * @param[in] in the value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMU_SCHEME_KEYEDHASH.
+ */
+TSS2_RC
+ifapi_json_TPMU_SCHEME_KEYEDHASH_serialize(const TPMU_SCHEME_KEYEDHASH *in, UINT32 selector, json_object **jso)
+{
+    switch (selector) {
+        case TPM2_ALG_HMAC:
+            return ifapi_json_TPMS_SCHEME_HMAC_serialize(&in->hmac, jso);
+        case TPM2_ALG_XOR:
+            return ifapi_json_TPMS_SCHEME_XOR_serialize(&in->exclusiveOr, jso);
+        default:
+            LOG_ERROR("\nSelector %"PRIx32 " did not match", selector);
+            return TSS2_FAPI_RC_BAD_VALUE;
+    };
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMT_KEYEDHASH_SCHEME to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMT_KEYEDHASH_SCHEME.
+ */
+TSS2_RC
+ifapi_json_TPMT_KEYEDHASH_SCHEME_serialize(const TPMT_KEYEDHASH_SCHEME *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    if (*jso == NULL)
+        *jso = json_object_new_object ();
+    jso2 = NULL;
+    r = ifapi_json_TPMI_ALG_KEYEDHASH_SCHEME_serialize(in->scheme, &jso2);
+    return_if_error(r, "Serialize TPMI_ALG_KEYEDHASH_SCHEME");
+
+    json_object_object_add(*jso, "scheme", jso2);
+    if (in->scheme != TPM2_ALG_NULL) {
+        json_object *jso2 = NULL;
+        r = ifapi_json_TPMU_SCHEME_KEYEDHASH_serialize(&in->details, in->scheme, &jso2);
+        return_if_error(r,"Serialize TPMU_SCHEME_KEYEDHASH");
+
+        json_object_object_add(*jso, "details", jso2);
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize a TPMS_SIG_SCHEME_RSASSA to json.
+ *
+ * @param[in] in value of type TPMS_SIG_SCHEME_RSASSA to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_SIG_SCHEME_RSASSA.
+ */
+TSS2_RC
+ifapi_json_TPMS_SIG_SCHEME_RSASSA_serialize(const TPMS_SIG_SCHEME_RSASSA *in, json_object **jso)
+{
+    return ifapi_json_TPMS_SCHEME_HASH_serialize(in, jso);
+}
+
+/** Serialize a TPMS_SIG_SCHEME_RSAPSS to json.
+ *
+ * @param[in] in value of type TPMS_SIG_SCHEME_RSAPSS to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_SIG_SCHEME_RSAPSS.
+ */
+TSS2_RC
+ifapi_json_TPMS_SIG_SCHEME_RSAPSS_serialize(const TPMS_SIG_SCHEME_RSAPSS *in, json_object **jso)
+{
+    return ifapi_json_TPMS_SCHEME_HASH_serialize(in, jso);
+}
+
+/** Serialize a TPMS_SIG_SCHEME_ECDSA to json.
+ *
+ * @param[in] in value of type TPMS_SIG_SCHEME_ECDSA to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_SIG_SCHEME_ECDSA.
+ */
+TSS2_RC
+ifapi_json_TPMS_SIG_SCHEME_ECDSA_serialize(const TPMS_SIG_SCHEME_ECDSA *in, json_object **jso)
+{
+    return ifapi_json_TPMS_SCHEME_HASH_serialize(in, jso);
+}
+
+/** Serialize a TPMS_SIG_SCHEME_SM2 to json.
+ *
+ * @param[in] in value of type TPMS_SIG_SCHEME_SM2 to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_SIG_SCHEME_SM2.
+ */
+TSS2_RC
+ifapi_json_TPMS_SIG_SCHEME_SM2_serialize(const TPMS_SIG_SCHEME_SM2 *in, json_object **jso)
+{
+    return ifapi_json_TPMS_SCHEME_HASH_serialize(in, jso);
+}
+
+/** Serialize a TPMS_SIG_SCHEME_ECSCHNORR to json.
+ *
+ * @param[in] in value of type TPMS_SIG_SCHEME_ECSCHNORR to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_SIG_SCHEME_ECSCHNORR.
+ */
+TSS2_RC
+ifapi_json_TPMS_SIG_SCHEME_ECSCHNORR_serialize(const TPMS_SIG_SCHEME_ECSCHNORR *in, json_object **jso)
+{
+    return ifapi_json_TPMS_SCHEME_HASH_serialize(in, jso);
+}
+
+/** Serialize a TPMS_SIG_SCHEME_ECDAA to json.
+ *
+ * @param[in] in value of type TPMS_SIG_SCHEME_ECDAA to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_SIG_SCHEME_ECDAA.
+ */
+TSS2_RC
+ifapi_json_TPMS_SIG_SCHEME_ECDAA_serialize(const TPMS_SIG_SCHEME_ECDAA *in, json_object **jso)
+{
+    return ifapi_json_TPMS_SCHEME_ECDAA_serialize(in, jso);
+}
+
+/**  Serialize a TPMU_SIG_SCHEME to json.
+ *
+ * This function expects the Bitfield to be encoded as unsigned int in host-endianess.
+ * @param[in] in the value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMU_SIG_SCHEME.
+ */
+TSS2_RC
+ifapi_json_TPMU_SIG_SCHEME_serialize(const TPMU_SIG_SCHEME *in, UINT32 selector, json_object **jso)
+{
+    switch (selector) {
+        case TPM2_ALG_RSASSA:
+            return ifapi_json_TPMS_SIG_SCHEME_RSASSA_serialize(&in->rsassa, jso);
+        case TPM2_ALG_RSAPSS:
+            return ifapi_json_TPMS_SIG_SCHEME_RSAPSS_serialize(&in->rsapss, jso);
+        case TPM2_ALG_ECDSA:
+            return ifapi_json_TPMS_SIG_SCHEME_ECDSA_serialize(&in->ecdsa, jso);
+        case TPM2_ALG_ECDAA:
+            return ifapi_json_TPMS_SIG_SCHEME_ECDAA_serialize(&in->ecdaa, jso);
+        case TPM2_ALG_SM2:
+            return ifapi_json_TPMS_SIG_SCHEME_SM2_serialize(&in->sm2, jso);
+        case TPM2_ALG_ECSCHNORR:
+            return ifapi_json_TPMS_SIG_SCHEME_ECSCHNORR_serialize(&in->ecschnorr, jso);
+        case TPM2_ALG_HMAC:
+            return ifapi_json_TPMS_SCHEME_HMAC_serialize(&in->hmac, jso);
+        default:
+            LOG_ERROR("\nSelector %"PRIx32 " did not match", selector);
+            return TSS2_FAPI_RC_BAD_VALUE;
+    };
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMT_SIG_SCHEME to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMT_SIG_SCHEME.
+ */
+TSS2_RC
+ifapi_json_TPMT_SIG_SCHEME_serialize(const TPMT_SIG_SCHEME *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    if (*jso == NULL)
+        *jso = json_object_new_object ();
+    jso2 = NULL;
+    r = ifapi_json_TPMI_ALG_SIG_SCHEME_serialize(in->scheme, &jso2);
+    return_if_error(r, "Serialize TPMI_ALG_SIG_SCHEME");
+
+    json_object_object_add(*jso, "scheme", jso2);
+    if (in->scheme != TPM2_ALG_NULL) {
+        json_object *jso2 = NULL;
+        r = ifapi_json_TPMU_SIG_SCHEME_serialize(&in->details, in->scheme, &jso2);
+        return_if_error(r,"Serialize TPMU_SIG_SCHEME");
+
+        json_object_object_add(*jso, "details", jso2);
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize a TPMS_ENC_SCHEME_OAEP to json.
+ *
+ * @param[in] in value of type TPMS_ENC_SCHEME_OAEP to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_ENC_SCHEME_OAEP.
+ */
+TSS2_RC
+ifapi_json_TPMS_ENC_SCHEME_OAEP_serialize(const TPMS_ENC_SCHEME_OAEP *in, json_object **jso)
+{
+    return ifapi_json_TPMS_SCHEME_HASH_serialize(in, jso);
+}
+
+/** Serialize a TPMS_ENC_SCHEME_RSAES to json.
+ *
+ * @param[in] in value of type TPMS_ENC_SCHEME_RSAES to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_ENC_SCHEME_RSAES.
+ */
+TSS2_RC
+ifapi_json_TPMS_ENC_SCHEME_RSAES_serialize(const TPMS_ENC_SCHEME_RSAES *in, json_object **jso)
+{
+    return ifapi_json_TPMS_EMPTY_serialize(in, jso);
+}
+
+/** Serialize a TPMS_KEY_SCHEME_ECDH to json.
+ *
+ * @param[in] in value of type TPMS_KEY_SCHEME_ECDH to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_KEY_SCHEME_ECDH.
+ */
+TSS2_RC
+ifapi_json_TPMS_KEY_SCHEME_ECDH_serialize(const TPMS_KEY_SCHEME_ECDH *in, json_object **jso)
+{
+    return ifapi_json_TPMS_SCHEME_HASH_serialize(in, jso);
+}
+
+/** Serialize a TPMS_SCHEME_MGF1 to json.
+ *
+ * @param[in] in value of type TPMS_SCHEME_MGF1 to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_SCHEME_MGF1.
+ */
+TSS2_RC
+ifapi_json_TPMS_SCHEME_MGF1_serialize(const TPMS_SCHEME_MGF1 *in, json_object **jso)
+{
+    return ifapi_json_TPMS_SCHEME_HASH_serialize(in, jso);
+}
+
+/** Serialize a TPMS_SCHEME_KDF1_SP800_56A to json.
+ *
+ * @param[in] in value of type TPMS_SCHEME_KDF1_SP800_56A to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_SCHEME_KDF1_SP800_56A.
+ */
+TSS2_RC
+ifapi_json_TPMS_SCHEME_KDF1_SP800_56A_serialize(const TPMS_SCHEME_KDF1_SP800_56A *in, json_object **jso)
+{
+    return ifapi_json_TPMS_SCHEME_HASH_serialize(in, jso);
+}
+
+/** Serialize a TPMS_SCHEME_KDF1_SP800_108 to json.
+ *
+ * @param[in] in value of type TPMS_SCHEME_KDF1_SP800_108 to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_SCHEME_KDF1_SP800_108.
+ */
+TSS2_RC
+ifapi_json_TPMS_SCHEME_KDF1_SP800_108_serialize(const TPMS_SCHEME_KDF1_SP800_108 *in, json_object **jso)
+{
+    return ifapi_json_TPMS_SCHEME_HASH_serialize(in, jso);
+}
+
+/**  Serialize a TPMU_KDF_SCHEME to json.
+ *
+ * This function expects the Bitfield to be encoded as unsigned int in host-endianess.
+ * @param[in] in the value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMU_KDF_SCHEME.
+ */
+TSS2_RC
+ifapi_json_TPMU_KDF_SCHEME_serialize(const TPMU_KDF_SCHEME *in, UINT32 selector, json_object **jso)
+{
+    switch (selector) {
+        case TPM2_ALG_MGF1:
+            return ifapi_json_TPMS_SCHEME_MGF1_serialize(&in->mgf1, jso);
+        case TPM2_ALG_KDF1_SP800_56A:
+            return ifapi_json_TPMS_SCHEME_KDF1_SP800_56A_serialize(&in->kdf1_sp800_56a, jso);
+        case TPM2_ALG_KDF1_SP800_108:
+            return ifapi_json_TPMS_SCHEME_KDF1_SP800_108_serialize(&in->kdf1_sp800_108, jso);
+        default:
+            LOG_ERROR("\nSelector %"PRIx32 " did not match", selector);
+            return TSS2_FAPI_RC_BAD_VALUE;
+    };
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMT_KDF_SCHEME to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMT_KDF_SCHEME.
+ */
+TSS2_RC
+ifapi_json_TPMT_KDF_SCHEME_serialize(const TPMT_KDF_SCHEME *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    if (*jso == NULL)
+        *jso = json_object_new_object ();
+    jso2 = NULL;
+    r = ifapi_json_TPMI_ALG_KDF_serialize(in->scheme, &jso2);
+    return_if_error(r, "Serialize TPMI_ALG_KDF");
+
+    json_object_object_add(*jso, "scheme", jso2);
+    if (in->scheme != TPM2_ALG_NULL) {
+        json_object *jso2 = NULL;
+        r = ifapi_json_TPMU_KDF_SCHEME_serialize(&in->details, in->scheme, &jso2);
+        return_if_error(r,"Serialize TPMU_KDF_SCHEME");
+
+        json_object_object_add(*jso, "details", jso2);
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize TPMI_ALG_ASYM_SCHEME to json.
+ *
+ * @param[in] in variable to be serialized.
+ * @param[out] jso pointer to the json object.
+ */
+TSS2_RC
+ifapi_json_TPMI_ALG_ASYM_SCHEME_serialize(const TPMI_ALG_ASYM_SCHEME in, json_object **jso)
+{
+    CHECK_IN_LIST(TPMI_ALG_ASYM_SCHEME, in, TPM2_ALG_ECDH, TPM2_ALG_RSASSA, TPM2_ALG_RSAPSS,
+                  TPM2_ALG_ECDSA, TPM2_ALG_ECDAA, TPM2_ALG_SM2, TPM2_ALG_ECSCHNORR,
+                  TPM2_ALG_RSAES, TPM2_ALG_OAEP, TPM2_ALG_NULL);
+    return ifapi_json_TPM2_ALG_ID_serialize(in, jso);
+}
+
+/**  Serialize a TPMU_ASYM_SCHEME to json.
+ *
+ * This function expects the Bitfield to be encoded as unsigned int in host-endianess.
+ * @param[in] in the value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMU_ASYM_SCHEME.
+ */
+TSS2_RC
+ifapi_json_TPMU_ASYM_SCHEME_serialize(const TPMU_ASYM_SCHEME *in, UINT32 selector, json_object **jso)
+{
+    switch (selector) {
+        case TPM2_ALG_ECDH:
+            return ifapi_json_TPMS_KEY_SCHEME_ECDH_serialize(&in->ecdh, jso);
+        case TPM2_ALG_RSASSA:
+            return ifapi_json_TPMS_SIG_SCHEME_RSASSA_serialize(&in->rsassa, jso);
+        case TPM2_ALG_RSAPSS:
+            return ifapi_json_TPMS_SIG_SCHEME_RSAPSS_serialize(&in->rsapss, jso);
+        case TPM2_ALG_ECDSA:
+            return ifapi_json_TPMS_SIG_SCHEME_ECDSA_serialize(&in->ecdsa, jso);
+        case TPM2_ALG_ECDAA:
+            return ifapi_json_TPMS_SIG_SCHEME_ECDAA_serialize(&in->ecdaa, jso);
+        case TPM2_ALG_SM2:
+            return ifapi_json_TPMS_SIG_SCHEME_SM2_serialize(&in->sm2, jso);
+        case TPM2_ALG_ECSCHNORR:
+            return ifapi_json_TPMS_SIG_SCHEME_ECSCHNORR_serialize(&in->ecschnorr, jso);
+        case TPM2_ALG_RSAES:
+            return ifapi_json_TPMS_ENC_SCHEME_RSAES_serialize(&in->rsaes, jso);
+        case TPM2_ALG_OAEP:
+            return ifapi_json_TPMS_ENC_SCHEME_OAEP_serialize(&in->oaep, jso);
+        default:
+            LOG_ERROR("\nSelector %"PRIx32 " did not match", selector);
+            return TSS2_FAPI_RC_BAD_VALUE;
+    };
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMT_ASYM_SCHEME to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMT_ASYM_SCHEME.
+ */
+TSS2_RC
+ifapi_json_TPMT_ASYM_SCHEME_serialize(const TPMT_ASYM_SCHEME *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    if (*jso == NULL)
+        *jso = json_object_new_object ();
+    jso2 = NULL;
+    r = ifapi_json_TPMI_ALG_ASYM_SCHEME_serialize(in->scheme, &jso2);
+    return_if_error(r, "Serialize TPMI_ALG_ASYM_SCHEME");
+
+    json_object_object_add(*jso, "scheme", jso2);
+    if (in->scheme != TPM2_ALG_NULL) {
+        json_object *jso2 = NULL;
+        r = ifapi_json_TPMU_ASYM_SCHEME_serialize(&in->details, in->scheme, &jso2);
+        return_if_error(r,"Serialize TPMU_ASYM_SCHEME");
+
+        json_object_object_add(*jso, "details", jso2);
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize TPMI_ALG_RSA_SCHEME to json.
+ *
+ * @param[in] in variable to be serialized.
+ * @param[out] jso pointer to the json object.
+ */
+TSS2_RC
+ifapi_json_TPMI_ALG_RSA_SCHEME_serialize(const TPMI_ALG_RSA_SCHEME in, json_object **jso)
+{
+    CHECK_IN_LIST(TPMI_ALG_RSA_SCHEME, in, TPM2_ALG_RSAES, TPM2_ALG_OAEP, TPM2_ALG_RSASSA,
+                  TPM2_ALG_RSAPSS, TPM2_ALG_NULL);
+    return ifapi_json_TPM2_ALG_ID_serialize(in, jso);
+}
+
+/** Serialize value of type TPMT_RSA_SCHEME to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMT_RSA_SCHEME.
+ */
+TSS2_RC
+ifapi_json_TPMT_RSA_SCHEME_serialize(const TPMT_RSA_SCHEME *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    if (*jso == NULL)
+        *jso = json_object_new_object ();
+    jso2 = NULL;
+    r = ifapi_json_TPMI_ALG_RSA_SCHEME_serialize(in->scheme, &jso2);
+    return_if_error(r, "Serialize TPMI_ALG_RSA_SCHEME");
+
+    json_object_object_add(*jso, "scheme", jso2);
+    if (in->scheme != TPM2_ALG_NULL) {
+        json_object *jso2 = NULL;
+        r = ifapi_json_TPMU_ASYM_SCHEME_serialize(&in->details, in->scheme, &jso2);
+        return_if_error(r,"Serialize TPMU_ASYM_SCHEME");
+
+        json_object_object_add(*jso, "details", jso2);
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPM2B_PUBLIC_KEY_RSA to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPM2B_PUBLIC_KEY_RSA.
+ */
+TSS2_RC
+ifapi_json_TPM2B_PUBLIC_KEY_RSA_serialize(const TPM2B_PUBLIC_KEY_RSA *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    if (in->size > TPM2_MAX_RSA_KEY_BYTES) {
+        LOG_ERROR("Too many bytes for array (%"PRIuPTR" > %"PRIuPTR" = TPM2_MAX_RSA_KEY_BYTES)",
+                  (size_t)in->size, (size_t)TPM2_MAX_RSA_KEY_BYTES);
+        return TSS2_FAPI_RC_BAD_VALUE;
+    }
+    char hex_string[((size_t)in->size)*2+1];
+
+    for (size_t i = 0, off = 0; i < in->size; i++, off+=2)
+        sprintf(&hex_string[off], "%02x", in->buffer[i]);
+    hex_string[(in->size)*2] = '\0';
+    *jso = json_object_new_string (hex_string);
+    return_if_null(*jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMI_RSA_KEY_BITS to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMI_RSA_KEY_BITS.
+ *
+ */
+TSS2_RC
+ifapi_json_TPMI_RSA_KEY_BITS_serialize(const TPMI_RSA_KEY_BITS in, json_object **jso)
+{
+    CHECK_IN_LIST(TPMI_RSA_KEY_BITS, in, 1024, 2048);
+    return ifapi_json_UINT16_serialize(in, jso);
+}
+
+/** Serialize value of type TPM2B_ECC_PARAMETER to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPM2B_ECC_PARAMETER.
+ */
+TSS2_RC
+ifapi_json_TPM2B_ECC_PARAMETER_serialize(const TPM2B_ECC_PARAMETER *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    if (in->size > TPM2_MAX_ECC_KEY_BYTES) {
+        LOG_ERROR("Too many bytes for array (%"PRIuPTR" > %"PRIuPTR" = TPM2_MAX_ECC_KEY_BYTES)",
+                  (size_t)in->size, (size_t)TPM2_MAX_ECC_KEY_BYTES);
+        return TSS2_FAPI_RC_BAD_VALUE;
+    }
+    char hex_string[((size_t)in->size)*2+1];
+
+    for (size_t i = 0, off = 0; i < in->size; i++, off+=2)
+        sprintf(&hex_string[off], "%02x", in->buffer[i]);
+    hex_string[(in->size)*2] = '\0';
+    *jso = json_object_new_string (hex_string);
+    return_if_null(*jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_ECC_POINT to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_ECC_POINT.
+ */
+TSS2_RC
+ifapi_json_TPMS_ECC_POINT_serialize(const TPMS_ECC_POINT *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    if (*jso == NULL)
+        *jso = json_object_new_object ();
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_ECC_PARAMETER_serialize(&in->x, &jso2);
+    return_if_error(r, "Serialize TPM2B_ECC_PARAMETER");
+
+    json_object_object_add(*jso, "x", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_ECC_PARAMETER_serialize(&in->y, &jso2);
+    return_if_error(r, "Serialize TPM2B_ECC_PARAMETER");
+
+    json_object_object_add(*jso, "y", jso2);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize TPMI_ALG_ECC_SCHEME to json.
+ *
+ * @param[in] in variable to be serialized.
+ * @param[out] jso pointer to the json object.
+ */
+TSS2_RC
+ifapi_json_TPMI_ALG_ECC_SCHEME_serialize(const TPMI_ALG_ECC_SCHEME in, json_object **jso)
+{
+    CHECK_IN_LIST(TPMI_ALG_ECC_SCHEME, in, TPM2_ALG_ECDSA, TPM2_ALG_ECDAA,
+                  TPM2_ALG_SM2, TPM2_ALG_ECSCHNORR, TPM2_ALG_ECDH, TPM2_ALG_NULL);
+    return ifapi_json_TPM2_ALG_ID_serialize(in, jso);
+}
+
+/** Serialize value of type TPMI_ECC_CURVE to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMI_ECC_CURVE.
+ *
+ */
+TSS2_RC
+ifapi_json_TPMI_ECC_CURVE_serialize(const TPMI_ECC_CURVE in, json_object **jso)
+{
+    return ifapi_json_TPM2_ECC_CURVE_serialize(in, jso);
+}
+
+/** Serialize value of type TPMT_ECC_SCHEME to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMT_ECC_SCHEME.
+ */
+TSS2_RC
+ifapi_json_TPMT_ECC_SCHEME_serialize(const TPMT_ECC_SCHEME *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    if (*jso == NULL)
+        *jso = json_object_new_object ();
+    jso2 = NULL;
+    r = ifapi_json_TPMI_ALG_ECC_SCHEME_serialize(in->scheme, &jso2);
+    return_if_error(r, "Serialize TPMI_ALG_ECC_SCHEME");
+
+    json_object_object_add(*jso, "scheme", jso2);
+    if (in->scheme != TPM2_ALG_NULL) {
+        json_object *jso2 = NULL;
+        r = ifapi_json_TPMU_ASYM_SCHEME_serialize(&in->details, in->scheme, &jso2);
+        return_if_error(r,"Serialize TPMU_ASYM_SCHEME");
+
+        json_object_object_add(*jso, "details", jso2);
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_SIGNATURE_RSA to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_SIGNATURE_RSA.
+ */
+TSS2_RC
+ifapi_json_TPMS_SIGNATURE_RSA_serialize(const TPMS_SIGNATURE_RSA *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    if (*jso == NULL)
+        *jso = json_object_new_object ();
+    jso2 = NULL;
+    r = ifapi_json_TPMI_ALG_HASH_serialize(in->hash, &jso2);
+    return_if_error(r, "Serialize TPMI_ALG_HASH");
+
+    json_object_object_add(*jso, "hash", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_PUBLIC_KEY_RSA_serialize(&in->sig, &jso2);
+    return_if_error(r, "Serialize TPM2B_PUBLIC_KEY_RSA");
+
+    json_object_object_add(*jso, "sig", jso2);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize a TPMS_SIGNATURE_RSASSA to json.
+ *
+ * @param[in] in value of type TPMS_SIGNATURE_RSASSA to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_SIGNATURE_RSASSA.
+ */
+TSS2_RC
+ifapi_json_TPMS_SIGNATURE_RSASSA_serialize(const TPMS_SIGNATURE_RSASSA *in, json_object **jso)
+{
+    return ifapi_json_TPMS_SIGNATURE_RSA_serialize(in, jso);
+}
+
+/** Serialize a TPMS_SIGNATURE_RSAPSS to json.
+ *
+ * @param[in] in value of type TPMS_SIGNATURE_RSAPSS to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_SIGNATURE_RSAPSS.
+ */
+TSS2_RC
+ifapi_json_TPMS_SIGNATURE_RSAPSS_serialize(const TPMS_SIGNATURE_RSAPSS *in, json_object **jso)
+{
+    return ifapi_json_TPMS_SIGNATURE_RSA_serialize(in, jso);
+}
+
+/** Serialize value of type TPMS_SIGNATURE_ECC to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_SIGNATURE_ECC.
+ */
+TSS2_RC
+ifapi_json_TPMS_SIGNATURE_ECC_serialize(const TPMS_SIGNATURE_ECC *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    if (*jso == NULL)
+        *jso = json_object_new_object ();
+    jso2 = NULL;
+    r = ifapi_json_TPMI_ALG_HASH_serialize(in->hash, &jso2);
+    return_if_error(r, "Serialize TPMI_ALG_HASH");
+
+    json_object_object_add(*jso, "hash", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_ECC_PARAMETER_serialize(&in->signatureR, &jso2);
+    return_if_error(r, "Serialize TPM2B_ECC_PARAMETER");
+
+    json_object_object_add(*jso, "signatureR", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_ECC_PARAMETER_serialize(&in->signatureS, &jso2);
+    return_if_error(r, "Serialize TPM2B_ECC_PARAMETER");
+
+    json_object_object_add(*jso, "signatureS", jso2);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize a TPMS_SIGNATURE_ECDSA to json.
+ *
+ * @param[in] in value of type TPMS_SIGNATURE_ECDSA to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_SIGNATURE_ECDSA.
+ */
+TSS2_RC
+ifapi_json_TPMS_SIGNATURE_ECDSA_serialize(const TPMS_SIGNATURE_ECDSA *in, json_object **jso)
+{
+    return ifapi_json_TPMS_SIGNATURE_ECC_serialize(in, jso);
+}
+
+/** Serialize a TPMS_SIGNATURE_ECDAA to json.
+ *
+ * @param[in] in value of type TPMS_SIGNATURE_ECDAA to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_SIGNATURE_ECDAA.
+ */
+TSS2_RC
+ifapi_json_TPMS_SIGNATURE_ECDAA_serialize(const TPMS_SIGNATURE_ECDAA *in, json_object **jso)
+{
+    return ifapi_json_TPMS_SIGNATURE_ECC_serialize(in, jso);
+}
+
+/** Serialize a TPMS_SIGNATURE_SM2 to json.
+ *
+ * @param[in] in value of type TPMS_SIGNATURE_SM2 to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_SIGNATURE_SM2.
+ */
+TSS2_RC
+ifapi_json_TPMS_SIGNATURE_SM2_serialize(const TPMS_SIGNATURE_SM2 *in, json_object **jso)
+{
+    return ifapi_json_TPMS_SIGNATURE_ECC_serialize(in, jso);
+}
+
+/** Serialize a TPMS_SIGNATURE_ECSCHNORR to json.
+ *
+ * @param[in] in value of type TPMS_SIGNATURE_ECSCHNORR to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_SIGNATURE_ECSCHNORR.
+ */
+TSS2_RC
+ifapi_json_TPMS_SIGNATURE_ECSCHNORR_serialize(const TPMS_SIGNATURE_ECSCHNORR *in, json_object **jso)
+{
+    return ifapi_json_TPMS_SIGNATURE_ECC_serialize(in, jso);
+}
+
+/**  Serialize a TPMU_SIGNATURE to json.
+ *
+ * This function expects the Bitfield to be encoded as unsigned int in host-endianess.
+ * @param[in] in the value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMU_SIGNATURE.
+ */
+TSS2_RC
+ifapi_json_TPMU_SIGNATURE_serialize(const TPMU_SIGNATURE *in, UINT32 selector, json_object **jso)
+{
+    switch (selector) {
+        case TPM2_ALG_RSASSA:
+            return ifapi_json_TPMS_SIGNATURE_RSASSA_serialize(&in->rsassa, jso);
+        case TPM2_ALG_RSAPSS:
+            return ifapi_json_TPMS_SIGNATURE_RSAPSS_serialize(&in->rsapss, jso);
+        case TPM2_ALG_ECDSA:
+            return ifapi_json_TPMS_SIGNATURE_ECDSA_serialize(&in->ecdsa, jso);
+        case TPM2_ALG_ECDAA:
+            return ifapi_json_TPMS_SIGNATURE_ECDAA_serialize(&in->ecdaa, jso);
+        case TPM2_ALG_SM2:
+            return ifapi_json_TPMS_SIGNATURE_SM2_serialize(&in->sm2, jso);
+        case TPM2_ALG_ECSCHNORR:
+            return ifapi_json_TPMS_SIGNATURE_ECSCHNORR_serialize(&in->ecschnorr, jso);
+        case TPM2_ALG_HMAC:
+            return ifapi_json_TPMT_HA_serialize(&in->hmac, jso);
+        default:
+            LOG_ERROR("\nSelector %"PRIx32 " did not match", selector);
+            return TSS2_FAPI_RC_BAD_VALUE;
+    };
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMT_SIGNATURE to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMT_SIGNATURE.
+ */
+TSS2_RC
+ifapi_json_TPMT_SIGNATURE_serialize(const TPMT_SIGNATURE *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    if (*jso == NULL)
+        *jso = json_object_new_object ();
+    jso2 = NULL;
+    r = ifapi_json_TPMI_ALG_SIG_SCHEME_serialize(in->sigAlg, &jso2);
+    return_if_error(r, "Serialize TPMI_ALG_SIG_SCHEME");
+
+    json_object_object_add(*jso, "sigAlg", jso2);
+    if (in->sigAlg != TPM2_ALG_NULL) {
+        json_object *jso2 = NULL;
+        r = ifapi_json_TPMU_SIGNATURE_serialize(&in->signature, in->sigAlg, &jso2);
+        return_if_error(r,"Serialize TPMU_SIGNATURE");
+
+        json_object_object_add(*jso, "signature", jso2);
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPM2B_ENCRYPTED_SECRET to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPM2B_ENCRYPTED_SECRET.
+ */
+TSS2_RC
+ifapi_json_TPM2B_ENCRYPTED_SECRET_serialize(const TPM2B_ENCRYPTED_SECRET *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    if (in->size > sizeof(TPMU_ENCRYPTED_SECRET)) {
+        LOG_ERROR("Too many bytes for array (%"PRIuPTR" > %"PRIuPTR" = sizeof(TPMU_ENCRYPTED_SECRET))",
+                  (size_t)in->size, (size_t)sizeof(TPMU_ENCRYPTED_SECRET));
+        return TSS2_FAPI_RC_BAD_VALUE;
+    }
+    char hex_string[((size_t)in->size)*2+1];
+
+    for (size_t i = 0, off = 0; i < in->size; i++, off+=2)
+        sprintf(&hex_string[off], "%02x", in->secret[i]);
+    hex_string[(in->size)*2] = '\0';
+    *jso = json_object_new_string (hex_string);
+    return_if_null(*jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize TPMI_ALG_PUBLIC to json.
+ *
+ * @param[in] in variable to be serialized.
+ * @param[out] jso pointer to the json object.
+ */
+TSS2_RC
+ifapi_json_TPMI_ALG_PUBLIC_serialize(const TPMI_ALG_PUBLIC in, json_object **jso)
+{
+    CHECK_IN_LIST(TPMI_ALG_PUBLIC, in, TPM2_ALG_RSA, TPM2_ALG_KEYEDHASH,
+                  TPM2_ALG_ECC, TPM2_ALG_SYMCIPHER, TPM2_ALG_NULL);
+    return ifapi_json_TPM2_ALG_ID_serialize(in, jso);
+}
+
+/**  Serialize a TPMU_PUBLIC_ID to json.
+ *
+ * This function expects the Bitfield to be encoded as unsigned int in host-endianess.
+ * @param[in] in the value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMU_PUBLIC_ID.
+ */
+TSS2_RC
+ifapi_json_TPMU_PUBLIC_ID_serialize(const TPMU_PUBLIC_ID *in, UINT32 selector, json_object **jso)
+{
+    switch (selector) {
+        case TPM2_ALG_KEYEDHASH:
+            return ifapi_json_TPM2B_DIGEST_serialize(&in->keyedHash, jso);
+        case TPM2_ALG_SYMCIPHER:
+            return ifapi_json_TPM2B_DIGEST_serialize(&in->sym, jso);
+        case TPM2_ALG_RSA:
+            return ifapi_json_TPM2B_PUBLIC_KEY_RSA_serialize(&in->rsa, jso);
+        case TPM2_ALG_ECC:
+            return ifapi_json_TPMS_ECC_POINT_serialize(&in->ecc, jso);
+        default:
+            LOG_ERROR("\nSelector %"PRIx32 " did not match", selector);
+            return TSS2_FAPI_RC_BAD_VALUE;
+    };
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_KEYEDHASH_PARMS to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_KEYEDHASH_PARMS.
+ */
+TSS2_RC
+ifapi_json_TPMS_KEYEDHASH_PARMS_serialize(const TPMS_KEYEDHASH_PARMS *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    if (*jso == NULL)
+        *jso = json_object_new_object ();
+    jso2 = NULL;
+    r = ifapi_json_TPMT_KEYEDHASH_SCHEME_serialize(&in->scheme, &jso2);
+    return_if_error(r, "Serialize TPMT_KEYEDHASH_SCHEME");
+
+    json_object_object_add(*jso, "scheme", jso2);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_ASYM_PARMS to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_ASYM_PARMS.
+ */
+TSS2_RC
+ifapi_json_TPMS_ASYM_PARMS_serialize(const TPMS_ASYM_PARMS *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    if (*jso == NULL)
+        *jso = json_object_new_object ();
+    jso2 = NULL;
+    r = ifapi_json_TPMT_SYM_DEF_OBJECT_serialize(&in->symmetric, &jso2);
+    return_if_error(r, "Serialize TPMT_SYM_DEF_OBJECT");
+
+    json_object_object_add(*jso, "symmetric", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPMT_ASYM_SCHEME_serialize(&in->scheme, &jso2);
+    return_if_error(r, "Serialize TPMT_ASYM_SCHEME");
+
+    json_object_object_add(*jso, "scheme", jso2);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_RSA_PARMS to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_RSA_PARMS.
+ */
+TSS2_RC
+ifapi_json_TPMS_RSA_PARMS_serialize(const TPMS_RSA_PARMS *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    if (*jso == NULL)
+        *jso = json_object_new_object ();
+    jso2 = NULL;
+    r = ifapi_json_TPMT_SYM_DEF_OBJECT_serialize(&in->symmetric, &jso2);
+    return_if_error(r, "Serialize TPMT_SYM_DEF_OBJECT");
+
+    json_object_object_add(*jso, "symmetric", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPMT_RSA_SCHEME_serialize(&in->scheme, &jso2);
+    return_if_error(r, "Serialize TPMT_RSA_SCHEME");
+
+    json_object_object_add(*jso, "scheme", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPMI_RSA_KEY_BITS_serialize(in->keyBits, &jso2);
+    return_if_error(r, "Serialize TPMI_RSA_KEY_BITS");
+
+    json_object_object_add(*jso, "keyBits", jso2);
+    jso2 = NULL;
+    r = ifapi_json_UINT32_serialize(in->exponent, &jso2);
+    return_if_error(r, "Serialize UINT32");
+
+    json_object_object_add(*jso, "exponent", jso2);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_ECC_PARMS to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_ECC_PARMS.
+ */
+TSS2_RC
+ifapi_json_TPMS_ECC_PARMS_serialize(const TPMS_ECC_PARMS *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    if (*jso == NULL)
+        *jso = json_object_new_object ();
+    jso2 = NULL;
+    r = ifapi_json_TPMT_SYM_DEF_OBJECT_serialize(&in->symmetric, &jso2);
+    return_if_error(r, "Serialize TPMT_SYM_DEF_OBJECT");
+
+    json_object_object_add(*jso, "symmetric", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPMT_ECC_SCHEME_serialize(&in->scheme, &jso2);
+    return_if_error(r, "Serialize TPMT_ECC_SCHEME");
+
+    json_object_object_add(*jso, "scheme", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPMI_ECC_CURVE_serialize(in->curveID, &jso2);
+    return_if_error(r, "Serialize TPMI_ECC_CURVE");
+
+    json_object_object_add(*jso, "curveID", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPMT_KDF_SCHEME_serialize(&in->kdf, &jso2);
+    return_if_error(r, "Serialize TPMT_KDF_SCHEME");
+
+    json_object_object_add(*jso, "kdf", jso2);
+    return TSS2_RC_SUCCESS;
+}
+
+/**  Serialize a TPMU_PUBLIC_PARMS to json.
+ *
+ * This function expects the Bitfield to be encoded as unsigned int in host-endianess.
+ * @param[in] in the value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMU_PUBLIC_PARMS.
+ */
+TSS2_RC
+ifapi_json_TPMU_PUBLIC_PARMS_serialize(const TPMU_PUBLIC_PARMS *in, UINT32 selector, json_object **jso)
+{
+    switch (selector) {
+        case TPM2_ALG_KEYEDHASH:
+            return ifapi_json_TPMS_KEYEDHASH_PARMS_serialize(&in->keyedHashDetail, jso);
+        case TPM2_ALG_SYMCIPHER:
+            return ifapi_json_TPMS_SYMCIPHER_PARMS_serialize(&in->symDetail, jso);
+        case TPM2_ALG_RSA:
+            return ifapi_json_TPMS_RSA_PARMS_serialize(&in->rsaDetail, jso);
+        case TPM2_ALG_ECC:
+            return ifapi_json_TPMS_ECC_PARMS_serialize(&in->eccDetail, jso);
+        default:
+            LOG_ERROR("\nSelector %"PRIx32 " did not match", selector);
+            return TSS2_FAPI_RC_BAD_VALUE;
+    };
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMT_PUBLIC to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMT_PUBLIC.
+ */
+TSS2_RC
+ifapi_json_TPMT_PUBLIC_serialize(const TPMT_PUBLIC *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    if (*jso == NULL)
+        *jso = json_object_new_object ();
+    jso2 = NULL;
+    r = ifapi_json_TPMI_ALG_PUBLIC_serialize(in->type, &jso2);
+    return_if_error(r, "Serialize TPMI_ALG_PUBLIC");
+
+    json_object_object_add(*jso, "type", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPMI_ALG_HASH_serialize(in->nameAlg, &jso2);
+    return_if_error(r, "Serialize TPMI_ALG_HASH");
+
+    json_object_object_add(*jso, "nameAlg", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPMA_OBJECT_serialize(in->objectAttributes, &jso2);
+    return_if_error(r, "Serialize TPMA_OBJECT");
+
+    json_object_object_add(*jso, "objectAttributes", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_DIGEST_serialize(&in->authPolicy, &jso2);
+    return_if_error(r, "Serialize TPM2B_DIGEST");
+
+    json_object_object_add(*jso, "authPolicy", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPMU_PUBLIC_PARMS_serialize(&in->parameters, in->type, &jso2);
+    return_if_error(r,"Serialize TPMU_PUBLIC_PARMS");
+
+    json_object_object_add(*jso, "parameters", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPMU_PUBLIC_ID_serialize(&in->unique, in->type, &jso2);
+    return_if_error(r,"Serialize TPMU_PUBLIC_ID");
+
+    json_object_object_add(*jso, "unique", jso2);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize a TPM2B_PUBLIC to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPM2B_PUBLIC.
+ */
+TSS2_RC
+ifapi_json_TPM2B_PUBLIC_serialize(const TPM2B_PUBLIC *in, json_object **jso)
+{
+    if (*jso == NULL)
+        *jso = json_object_new_object ();
+    return_if_null(*jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+    json_object *jso2;
+
+    jso2 = NULL;
+    if (ifapi_json_UINT16_serialize(in->size, &jso2))
+        return TSS2_FAPI_RC_BAD_VALUE;
+
+    json_object_object_add(*jso, "size", jso2);
+
+    jso2 = NULL;
+    if (ifapi_json_TPMT_PUBLIC_serialize(&in->publicArea, &jso2))
+        return TSS2_FAPI_RC_BAD_VALUE;
+
+    json_object_object_add(*jso, "publicArea", jso2);
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPM2B_PRIVATE to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPM2B_PRIVATE.
+ */
+TSS2_RC
+ifapi_json_TPM2B_PRIVATE_serialize(const TPM2B_PRIVATE *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    if (in->size > sizeof(_PRIVATE)) {
+        LOG_ERROR("Too many bytes for array (%"PRIuPTR" > %"PRIuPTR" = sizeof(_PRIVATE))",
+                  (size_t)in->size, (size_t)sizeof(_PRIVATE));
+        return TSS2_FAPI_RC_BAD_VALUE;
+    }
+    char hex_string[((size_t)in->size)*2+1];
+
+    for (size_t i = 0, off = 0; i < in->size; i++, off+=2)
+        sprintf(&hex_string[off], "%02x", in->buffer[i]);
+    hex_string[(in->size)*2] = '\0';
+    *jso = json_object_new_string (hex_string);
+    return_if_null(*jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize TPM2_NT to json.
+ *
+ * @param[in] in constant to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the constant is not of type TPM2_NT.
+ */
+TSS2_RC
+ifapi_json_TPM2_NT_serialize(const TPM2_NT in, json_object **jso)
+{
+    static const struct { TPM2_NT in; 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" },
+    };
+
+    for (size_t i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
+        if (tab[i].in == in) {
+            *jso = json_object_new_string(tab[i].name);
+            check_oom(*jso);
+            return TSS2_RC_SUCCESS;
+        }
+    }
+    return_error(TSS2_FAPI_RC_BAD_VALUE, "Undefined constant.");
+}
+
+/** Serialize a TPMA_NV to json.
+ *
+ * This function expects the Bitfield to be encoded as unsigned int in host-endianess.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the constant is not of type TPMA_NV.
+ */
+
+TSS2_RC ifapi_json_TPMA_NV_serialize(const TPMA_NV in, json_object **jso)
+{
+    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" },
+    };
+
+    UINT32 input;
+    input = (UINT32) in;
+    json_object *jso_bit;
+    if (*jso == NULL) {
+        *jso = json_object_new_object();
+        return_if_null(*jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+    }
+    size_t n = sizeof(tab) / sizeof(tab[0]);
+    size_t i;
+    for (i = 0; i < n; i++) {
+        if (tab[i].in & input)
+            jso_bit = json_object_new_int(1);
+        else
+            jso_bit = json_object_new_int(0);
+        return_if_null(jso_bit, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+        json_object_object_add(*jso, tab[i].name, jso_bit);
+    }
+    TPM2_NT input2 = (TPMA_NV_TPM2_NT_MASK & input)>>4;
+    json_object *jso2 = NULL;
+    TSS2_RC r = ifapi_json_TPM2_NT_serialize(input2, &jso2);
+    return_if_error(r, "Bad value");
+
+    json_object_object_add(*jso, "TPM2_NT", jso2);
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_NV_PUBLIC to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_NV_PUBLIC.
+ */
+TSS2_RC
+ifapi_json_TPMS_NV_PUBLIC_serialize(const TPMS_NV_PUBLIC *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    if (*jso == NULL)
+        *jso = json_object_new_object ();
+    jso2 = NULL;
+    r = ifapi_json_TPMI_RH_NV_INDEX_serialize(in->nvIndex, &jso2);
+    return_if_error(r, "Serialize TPMI_RH_NV_INDEX");
+
+    json_object_object_add(*jso, "nvIndex", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPMI_ALG_HASH_serialize(in->nameAlg, &jso2);
+    return_if_error(r, "Serialize TPMI_ALG_HASH");
+
+    json_object_object_add(*jso, "nameAlg", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPMA_NV_serialize(in->attributes, &jso2);
+    return_if_error(r, "Serialize TPMA_NV");
+
+    json_object_object_add(*jso, "attributes", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_DIGEST_serialize(&in->authPolicy, &jso2);
+    return_if_error(r, "Serialize TPM2B_DIGEST");
+
+    json_object_object_add(*jso, "authPolicy", jso2);
+    jso2 = NULL;
+    r = ifapi_json_UINT16_serialize(in->dataSize, &jso2);
+    return_if_error(r, "Serialize UINT16");
+
+    json_object_object_add(*jso, "dataSize", jso2);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize a TPM2B_NV_PUBLIC to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPM2B_NV_PUBLIC.
+ */
+TSS2_RC
+ifapi_json_TPM2B_NV_PUBLIC_serialize(const TPM2B_NV_PUBLIC *in, json_object **jso)
+{
+    if (*jso == NULL)
+        *jso = json_object_new_object ();
+    return_if_null(*jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+    json_object *jso2;
+
+    jso2 = NULL;
+    if (ifapi_json_UINT16_serialize(in->size, &jso2))
+        return TSS2_FAPI_RC_BAD_VALUE;
+
+    json_object_object_add(*jso, "size", jso2);
+
+    jso2 = NULL;
+    if (ifapi_json_TPMS_NV_PUBLIC_serialize(&in->nvPublic, &jso2))
+        return TSS2_FAPI_RC_BAD_VALUE;
+
+    json_object_object_add(*jso, "nvPublic", jso2);
+
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize value of type TPMS_CREATION_DATA to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPMS_CREATION_DATA.
+ */
+TSS2_RC
+ifapi_json_TPMS_CREATION_DATA_serialize(const TPMS_CREATION_DATA *in, json_object **jso)
+{
+    return_if_null(in, "Bad reference.", TSS2_FAPI_RC_BAD_REFERENCE);
+
+    TSS2_RC r;
+    json_object *jso2;
+    if (*jso == NULL)
+        *jso = json_object_new_object ();
+    jso2 = NULL;
+    r = ifapi_json_TPML_PCR_SELECTION_serialize(&in->pcrSelect, &jso2);
+    return_if_error(r, "Serialize TPML_PCR_SELECTION");
+
+    json_object_object_add(*jso, "pcrSelect", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_DIGEST_serialize(&in->pcrDigest, &jso2);
+    return_if_error(r, "Serialize TPM2B_DIGEST");
+
+    json_object_object_add(*jso, "pcrDigest", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPMA_LOCALITY_serialize(in->locality, &jso2);
+    return_if_error(r, "Serialize TPMA_LOCALITY");
+
+    json_object_object_add(*jso, "locality", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPM2_ALG_ID_serialize(in->parentNameAlg, &jso2);
+    return_if_error(r, "Serialize TPM2_ALG_ID");
+
+    json_object_object_add(*jso, "parentNameAlg", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_NAME_serialize(&in->parentName, &jso2);
+    return_if_error(r, "Serialize TPM2B_NAME");
+
+    json_object_object_add(*jso, "parentName", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_NAME_serialize(&in->parentQualifiedName, &jso2);
+    return_if_error(r, "Serialize TPM2B_NAME");
+
+    json_object_object_add(*jso, "parentQualifiedName", jso2);
+    jso2 = NULL;
+    r = ifapi_json_TPM2B_DATA_serialize(&in->outsideInfo, &jso2);
+    return_if_error(r, "Serialize TPM2B_DATA");
+
+    json_object_object_add(*jso, "outsideInfo", jso2);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Serialize a TPM2B_CREATION_DATA to json.
+ *
+ * @param[in] in value to be serialized.
+ * @param[out] jso pointer to the json object.
+ * @retval TSS2_RC_SUCCESS if the function call was a success.
+ * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory.
+ * @retval TSS2_FAPI_RC_BAD_VALUE if the value is not of type TPM2B_CREATION_DATA.
+ */
+TSS2_RC
+ifapi_json_TPM2B_CREATION_DATA_serialize(const TPM2B_CREATION_DATA *in, json_object **jso)
+{
+    if (*jso == NULL)
+        *jso = json_object_new_object ();
+    return_if_null(*jso, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+
+    json_object *jso2;
+
+    jso2 = NULL;
+    if (ifapi_json_UINT16_serialize(in->size, &jso2))
+        return TSS2_FAPI_RC_BAD_VALUE;
+
+    json_object_object_add(*jso, "size", jso2);
+
+    jso2 = NULL;
+    if (ifapi_json_TPMS_CREATION_DATA_serialize(&in->creationData, &jso2))
+        return TSS2_FAPI_RC_BAD_VALUE;
+
+    json_object_object_add(*jso, "creationData", jso2);
+
+    return TSS2_RC_SUCCESS;
+}
diff --git a/src/tss2-fapi/tpm_json_serialize.h b/src/tss2-fapi/tpm_json_serialize.h
new file mode 100644
index 0000000..b9c66d7
--- /dev/null
+++ b/src/tss2-fapi/tpm_json_serialize.h
@@ -0,0 +1,605 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ ******************************************************************************/
+#ifndef FAPI_TPM_JSON_SERIALIZE_H
+#define FAPI_TPM_JSON_SERIALIZE_H
+
+#include <stdbool.h>
+#include <json-c/json.h>
+#include <json-c/json_util.h>
+
+#include "tss2_tpm2_types.h"
+#include "fapi_int.h"
+
+#define YES 1
+#define NO 0
+
+TSS2_RC
+ifapi_json_TPM2_HANDLE_serialize(const TPM2_HANDLE in, json_object **jso);
+
+TSS2_RC
+ifapi_json_UINT16_serialize(const UINT16 in, json_object **jso);
+
+TSS2_RC
+ifapi_json_UINT32_serialize(const UINT32 in, json_object **jso);
+
+TSS2_RC
+ifapi_json_INT32_serialize(const INT32 in, json_object **jso);
+
+TSS2_RC
+ifapi_json_UINT64_serialize(const UINT64 in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPM2_GENERATED_serialize(const TPM2_GENERATED in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPM2_GENERATED_serialize_txt(const TPM2_GENERATED in,
+                                        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPM2_ALG_ID_serialize(const TPM2_ALG_ID in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPM2_ALG_ID_serialize_txt(const TPM2_ALG_ID in,  json_object **jso);
+
+TSS2_RC
+ifapi_json_TPM2_ECC_CURVE_serialize(const TPM2_ECC_CURVE in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPM2_ECC_CURVE_serialize_txt(const TPM2_ECC_CURVE in,
+                                        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPM2_CC_serialize(const TPM2_CC in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPM2_CC_serialize_txt(const TPM2_CC in,  json_object **jso);
+
+TSS2_RC
+ifapi_json_TPM2_EO_serialize(const TPM2_EO in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPM2_EO_serialize_txt(const TPM2_EO in,  json_object **jso);
+
+TSS2_RC
+ifapi_json_TPM2_ST_serialize(const TPM2_ST in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPM2_ST_serialize_txt(const TPM2_ST in,  json_object **jso);
+
+TSS2_RC
+ifapi_json_TPM2_CAP_serialize(const TPM2_CAP in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPM2_CAP_serialize_txt(const TPM2_CAP in,  json_object **jso);
+
+TSS2_RC
+ifapi_json_TPM2_PT_serialize(const TPM2_PT in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPM2_PT_serialize_txt(const TPM2_PT in,  json_object **jso);
+
+TSS2_RC
+ifapi_json_TPM2_PT_PCR_serialize(const TPM2_PT_PCR in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPM2_PT_PCR_serialize_txt(const TPM2_PT_PCR in,  json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMA_ALGORITHM_serialize(const TPMA_ALGORITHM in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMA_OBJECT_serialize(const TPMA_OBJECT in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMA_LOCALITY_serialize(const TPMA_LOCALITY in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMA_CC_serialize(const TPMA_CC in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMI_YES_NO_serialize(const TPMI_YES_NO in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMI_YES_NO_serialize_txt(const TPMI_YES_NO in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMI_RH_HIERARCHY_serialize(const TPMI_RH_HIERARCHY in,
+                                       json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMI_RH_HIERARCHY_serialize_txt(const TPMI_RH_HIERARCHY in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMI_RH_NV_INDEX_serialize(const TPMI_RH_NV_INDEX in,
+                                      json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMI_RH_NV_INDEX_serialize_txt(const TPMI_RH_NV_INDEX in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMI_ALG_HASH_serialize(const TPMI_ALG_HASH in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMI_ALG_HASH_serialize_txt(const TPMI_ALG_HASH in,
+                                       json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMI_ALG_SYM_OBJECT_serialize(const TPMI_ALG_SYM_OBJECT in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMI_ALG_SYM_OBJECT_serialize_txt(const TPMI_ALG_SYM_OBJECT in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMI_ALG_SYM_MODE_serialize(const TPMI_ALG_SYM_MODE in,
+                                       json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMI_ALG_SYM_MODE_serialize_txt(const TPMI_ALG_SYM_MODE in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMI_ALG_KDF_serialize(const TPMI_ALG_KDF in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMI_ALG_KDF_serialize_txt(const TPMI_ALG_KDF in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMI_ALG_SIG_SCHEME_serialize(const TPMI_ALG_SIG_SCHEME in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMI_ALG_SIG_SCHEME_serialize_txt(const TPMI_ALG_SIG_SCHEME in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_EMPTY_serialize(const TPMS_EMPTY *in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMU_HA_serialize(const TPMU_HA *in, UINT32 selector,
+                             json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMT_HA_serialize(const TPMT_HA *in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPM2B_DIGEST_serialize(const TPM2B_DIGEST *in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPM2B_DATA_serialize(const TPM2B_DATA *in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPM2B_NONCE_serialize(const TPM2B_NONCE *in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPM2B_OPERAND_serialize(const TPM2B_OPERAND *in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPM2B_EVENT_serialize(const TPM2B_EVENT *in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPM2B_MAX_NV_BUFFER_serialize(const TPM2B_MAX_NV_BUFFER *in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPM2B_NAME_serialize(const TPM2B_NAME *in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_PCR_SELECT_serialize(const TPMS_PCR_SELECT *in,
+                                     json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_PCR_SELECTION_serialize(const TPMS_PCR_SELECTION *in,
+                                        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMT_TK_CREATION_serialize(const TPMT_TK_CREATION *in,
+                                      json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_ALG_PROPERTY_serialize(const TPMS_ALG_PROPERTY *in,
+                                       json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_TAGGED_PROPERTY_serialize(const TPMS_TAGGED_PROPERTY *in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_TAGGED_PCR_SELECT_serialize(const TPMS_TAGGED_PCR_SELECT *in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPML_CC_serialize(const TPML_CC *in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPML_CCA_serialize(const TPML_CCA *in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPML_HANDLE_serialize(const TPML_HANDLE *in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPML_DIGEST_VALUES_serialize(const TPML_DIGEST_VALUES *in,
+                                        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPML_PCR_SELECTION_serialize(const TPML_PCR_SELECTION *in,
+                                        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPML_ALG_PROPERTY_serialize(const TPML_ALG_PROPERTY *in,
+                                       json_object **jso);
+
+TSS2_RC
+ifapi_json_TPML_TAGGED_TPM_PROPERTY_serialize(const TPML_TAGGED_TPM_PROPERTY
+        *in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPML_TAGGED_PCR_PROPERTY_serialize(const TPML_TAGGED_PCR_PROPERTY
+        *in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPML_ECC_CURVE_serialize(const TPML_ECC_CURVE *in,
+                                    json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMU_CAPABILITIES_serialize(const TPMU_CAPABILITIES *in,
+                                       UINT32 selector, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_CAPABILITY_DATA_serialize(const TPMS_CAPABILITY_DATA *in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_CLOCK_INFO_serialize(const TPMS_CLOCK_INFO *in,
+                                     json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_TIME_INFO_serialize(const TPMS_TIME_INFO *in,
+                                    json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_TIME_ATTEST_INFO_serialize(const TPMS_TIME_ATTEST_INFO *in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_CERTIFY_INFO_serialize(const TPMS_CERTIFY_INFO *in,
+                                       json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_QUOTE_INFO_serialize(const TPMS_QUOTE_INFO *in,
+                                     json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_COMMAND_AUDIT_INFO_serialize(const TPMS_COMMAND_AUDIT_INFO *in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_SESSION_AUDIT_INFO_serialize(const TPMS_SESSION_AUDIT_INFO *in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_CREATION_INFO_serialize(const TPMS_CREATION_INFO *in,
+                                        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_NV_CERTIFY_INFO_serialize(const TPMS_NV_CERTIFY_INFO *in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMI_ST_ATTEST_serialize(const TPMI_ST_ATTEST in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMI_ST_ATTEST_serialize_txt(const TPMI_ST_ATTEST in,
+                                        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMU_ATTEST_serialize(const TPMU_ATTEST *in, UINT32 selector,
+                                 json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_ATTEST_serialize(const TPMS_ATTEST *in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMI_AES_KEY_BITS_serialize(const TPMI_AES_KEY_BITS in,
+                                       json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMI_AES_KEY_BITS_serialize_txt(const TPMI_AES_KEY_BITS in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMU_SYM_KEY_BITS_serialize(const TPMU_SYM_KEY_BITS *in,
+                                       UINT32 selector, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMU_SYM_MODE_serialize(const TPMU_SYM_MODE *in, UINT32 selector,
+                                   json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMT_SYM_DEF_OBJECT_serialize(const TPMT_SYM_DEF_OBJECT *in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_SYMCIPHER_PARMS_serialize(const TPMS_SYMCIPHER_PARMS *in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_SCHEME_HASH_serialize(const TPMS_SCHEME_HASH *in,
+                                      json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_SCHEME_ECDAA_serialize(const TPMS_SCHEME_ECDAA *in,
+                                       json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMI_ALG_KEYEDHASH_SCHEME_serialize(const TPMI_ALG_KEYEDHASH_SCHEME
+        in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMI_ALG_KEYEDHASH_SCHEME_serialize_txt(const
+        TPMI_ALG_KEYEDHASH_SCHEME in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_SCHEME_HMAC_serialize(const TPMS_SCHEME_HMAC *in,
+                                      json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_SCHEME_XOR_serialize(const TPMS_SCHEME_XOR *in,
+                                     json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMU_SCHEME_KEYEDHASH_serialize(const TPMU_SCHEME_KEYEDHASH *in,
+        UINT32 selector, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMT_KEYEDHASH_SCHEME_serialize(const TPMT_KEYEDHASH_SCHEME *in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_SIG_SCHEME_RSASSA_serialize(const TPMS_SIG_SCHEME_RSASSA *in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_SIG_SCHEME_RSAPSS_serialize(const TPMS_SIG_SCHEME_RSAPSS *in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_SIG_SCHEME_ECDSA_serialize(const TPMS_SIG_SCHEME_ECDSA *in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_SIG_SCHEME_SM2_serialize(const TPMS_SIG_SCHEME_SM2 *in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_SIG_SCHEME_ECSCHNORR_serialize(const TPMS_SIG_SCHEME_ECSCHNORR
+        *in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_SIG_SCHEME_ECDAA_serialize(const TPMS_SIG_SCHEME_ECDAA *in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMU_SIG_SCHEME_serialize(const TPMU_SIG_SCHEME *in, UINT32 selector,
+                                     json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMT_SIG_SCHEME_serialize(const TPMT_SIG_SCHEME *in,
+                                     json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_ENC_SCHEME_OAEP_serialize(const TPMS_ENC_SCHEME_OAEP *in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_ENC_SCHEME_RSAES_serialize(const TPMS_ENC_SCHEME_RSAES *in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_KEY_SCHEME_ECDH_serialize(const TPMS_KEY_SCHEME_ECDH *in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_SCHEME_MGF1_serialize(const TPMS_SCHEME_MGF1 *in,
+                                      json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_SCHEME_KDF1_SP800_56A_serialize(const TPMS_SCHEME_KDF1_SP800_56A
+        *in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_SCHEME_KDF1_SP800_108_serialize(const TPMS_SCHEME_KDF1_SP800_108
+        *in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMU_KDF_SCHEME_serialize(const TPMU_KDF_SCHEME *in, UINT32 selector,
+                                     json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMT_KDF_SCHEME_serialize(const TPMT_KDF_SCHEME *in,
+                                     json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMI_ALG_ASYM_SCHEME_serialize(const TPMI_ALG_ASYM_SCHEME in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMI_ALG_ASYM_SCHEME_serialize_txt(const TPMI_ALG_ASYM_SCHEME in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMU_ASYM_SCHEME_serialize(const TPMU_ASYM_SCHEME *in,
+                                      UINT32 selector, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMT_ASYM_SCHEME_serialize(const TPMT_ASYM_SCHEME *in,
+                                      json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMI_ALG_RSA_SCHEME_serialize(const TPMI_ALG_RSA_SCHEME in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMI_ALG_RSA_SCHEME_serialize_txt(const TPMI_ALG_RSA_SCHEME in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMT_RSA_SCHEME_serialize(const TPMT_RSA_SCHEME *in,
+                                     json_object **jso);
+
+TSS2_RC
+ifapi_json_TPM2B_PUBLIC_KEY_RSA_serialize(const TPM2B_PUBLIC_KEY_RSA *in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMI_RSA_KEY_BITS_serialize(const TPMI_RSA_KEY_BITS in,
+                                       json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMI_RSA_KEY_BITS_serialize_txt(const TPMI_RSA_KEY_BITS in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPM2B_ECC_PARAMETER_serialize(const TPM2B_ECC_PARAMETER *in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_ECC_POINT_serialize(const TPMS_ECC_POINT *in,
+                                    json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMI_ALG_ECC_SCHEME_serialize(const TPMI_ALG_ECC_SCHEME in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMI_ALG_ECC_SCHEME_serialize_txt(const TPMI_ALG_ECC_SCHEME in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMI_ECC_CURVE_serialize(const TPMI_ECC_CURVE in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMI_ECC_CURVE_serialize_txt(const TPMI_ECC_CURVE in,
+                                        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMT_ECC_SCHEME_serialize(const TPMT_ECC_SCHEME *in,
+                                     json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_SIGNATURE_RSA_serialize(const TPMS_SIGNATURE_RSA *in,
+                                        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_SIGNATURE_RSASSA_serialize(const TPMS_SIGNATURE_RSASSA *in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_SIGNATURE_RSAPSS_serialize(const TPMS_SIGNATURE_RSAPSS *in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_SIGNATURE_ECC_serialize(const TPMS_SIGNATURE_ECC *in,
+                                        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_SIGNATURE_ECDSA_serialize(const TPMS_SIGNATURE_ECDSA *in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_SIGNATURE_ECDAA_serialize(const TPMS_SIGNATURE_ECDAA *in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_SIGNATURE_SM2_serialize(const TPMS_SIGNATURE_SM2 *in,
+                                        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_SIGNATURE_ECSCHNORR_serialize(const TPMS_SIGNATURE_ECSCHNORR
+        *in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMU_SIGNATURE_serialize(const TPMU_SIGNATURE *in, UINT32 selector,
+                                    json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMT_SIGNATURE_serialize(const TPMT_SIGNATURE *in,
+                                    json_object **jso);
+
+TSS2_RC
+ifapi_json_TPM2B_ENCRYPTED_SECRET_serialize(const TPM2B_ENCRYPTED_SECRET *in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMI_ALG_PUBLIC_serialize(const TPMI_ALG_PUBLIC in,
+                                     json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMI_ALG_PUBLIC_serialize_txt(const TPMI_ALG_PUBLIC in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMU_PUBLIC_ID_serialize(const TPMU_PUBLIC_ID *in, UINT32 selector,
+                                    json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_KEYEDHASH_PARMS_serialize(const TPMS_KEYEDHASH_PARMS *in,
+        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_ASYM_PARMS_serialize(const TPMS_ASYM_PARMS *in,
+                                     json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_RSA_PARMS_serialize(const TPMS_RSA_PARMS *in,
+                                    json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_ECC_PARMS_serialize(const TPMS_ECC_PARMS *in,
+                                    json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMU_PUBLIC_PARMS_serialize(const TPMU_PUBLIC_PARMS *in,
+                                       UINT32 selector, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMT_PUBLIC_serialize(const TPMT_PUBLIC *in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPM2B_PUBLIC_serialize(const TPM2B_PUBLIC *in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPM2B_PRIVATE_serialize(const TPM2B_PRIVATE *in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPM2_NT_serialize(const TPM2_NT in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPM2_NT_serialize_txt(const TPM2_NT in,  json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMA_NV_serialize(const TPMA_NV in, json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_NV_PUBLIC_serialize(const TPMS_NV_PUBLIC *in,
+                                    json_object **jso);
+
+TSS2_RC
+ifapi_json_TPM2B_NV_PUBLIC_serialize(const TPM2B_NV_PUBLIC *in,
+                                     json_object **jso);
+
+TSS2_RC
+ifapi_json_TPMS_CREATION_DATA_serialize(const TPMS_CREATION_DATA *in,
+                                        json_object **jso);
+
+TSS2_RC
+ifapi_json_TPM2B_CREATION_DATA_serialize(const TPM2B_CREATION_DATA *in,
+        json_object **jso);
+
+#endif /* FAPI_TPM_JSON_SERIALIZE_H */
diff --git a/src/tss2-rc/tss2_rc.c b/src/tss2-rc/tss2_rc.c
index 9374304..b0c6f96 100644
--- a/src/tss2-rc/tss2_rc.c
+++ b/src/tss2-rc/tss2_rc.c
@@ -703,14 +703,14 @@
 /**
  * The default system code handler. This handles codes
  * from the RM (itself and simulated tpm responses), the marshaling
- * library (mu), and the tcti layers.
+ * library (mu), the tcti layers, sapi, esys and fapi.
  * @param rc
  *  The rc to decode.
  * @return
  *  An error string.
  */
 static const char *
-sys_err_handler (TSS2_RC rc)
+tss_err_handler (TSS2_RC rc)
 {
     /*
      * subtract 1 from the error number
@@ -767,7 +767,65 @@
         /* 21 - TSS2_BASE_RC_NOT_SUPPORTED */
         "Functionality not supported",
         /* 22 - TSS2_BASE_RC_BAD_TCTI_STRUCTURE */
-        "TCTI context is bad"
+        "TCTI context is bad",
+        /* 23 - TSS2_BASE_RC_MEMORY */
+        "Failed to allocate memory",
+        /* 24 - TSS2_BASE_RC_BAD_TR */
+        "The ESYS_TR resource object is bad",
+        /* 25 - TSS2_BASE_RC_MULTIPLE_DECRYPT_SESSIONS */
+        "Multiple sessions were marked with attribute decrypt",
+        /* 26 - TSS2_BASE_RC_MULTIPLE_ENCRYPT_SESSIONS */
+        "Multiple sessions were marked with attribute encrypt",
+        /* 27 - TSS2_BASE_RC_RSP_AUTH_FAILED */
+        "Authorizing the TPM response failed",
+        /* 28 - TSS2_BASE_RC_NO_CONFIG */
+        "No config is available",
+        /* 29 - TSS2_BASE_RC_BAD_PATH */
+        "The provided path is bad",
+        /* 30 - TSS2_BASE_RC_NOT_DELETABLE */
+        "The object is not deletable",
+        /* 31 - TSS2_BASE_RC_PATH_ALREADY_EXISTS */
+        "The provided path already exists",
+        /* 32 - TSS2_BASE_RC_KEY_NOT_FOUND */
+        "The key was not found",
+        /* 33 - TSS2_BASE_RC_SIGNATURE_VERIFICATION_FAILED */
+        "Signature verification failed",
+        /* 34 - TSS2_BASE_RC_HASH_MISMATCH */
+        "Hashes mismatch",
+        /* 35 - TSS2_BASE_RC_KEY_NOT_DUPLICABLE */
+        "Key is not duplicatable",
+        /* 36 - TSS2_BASE_RC_PATH_NOT_FOUND */
+        "The path was not found",
+        /* 37 - TSS2_BASE_RC_NO_CERT */
+        "No certificate",
+        /* 38 - TSS2_BASE_RC_NO_PCR */
+        "No PCR",
+        /* 39 - TSS2_BASE_RC_PCR_NOT_RESETTABLE */
+        "PCR not resettable",
+        /* 40 - TSS2_BASE_RC_BAD_TEMPLATE */
+        "The template is bad",
+        /* 41 - TSS2_BASE_RC_AUTHORIZATION_FAILED */
+        "Authorization failed",
+        /* 42 - TSS2_BASE_RC_AUTHORIZATION_UNKNOWN */
+        "Authorization is unknown",
+        /* 43 - TSS2_BASE_RC_NV_NOT_READABLE */
+        "NV is not readable",
+        /* 44 - TSS2_BASE_RC_NV_TOO_SMALL */
+        "NV is too small",
+        /* 45 - TSS2_BASE_RC_NV_NOT_WRITEABLE */
+        "NV is not writable",
+        /* 46 - TSS2_BASE_RC_POLICY_UNKNOWN */
+        "The policy is unknown",
+        /* 47 - TSS2_BASE_RC_NV_WRONG_TYPE */
+        "The NV type is wrong",
+        /* 48 - TSS2_BASE_RC_NAME_ALREADY_EXISTS */
+        "The name already exists",
+        /* 49 - TSS2_BASE_RC_NO_TPM */
+        "No TPM available",
+        /* 50 - TSS2_BASE_RC_BAD_KEY */
+        "The key is bad",
+        /* 51 - TSS2_BASE_RC_NO_HANDLE */
+        "No handle provided"
   };
 
     return (rc - 1u < ARRAY_LEN(errors)) ? errors[rc - 1u] : NULL;
@@ -784,12 +842,12 @@
     ADD_NULL_HANDLER,                       /* layer 3  is unused */
     ADD_NULL_HANDLER,                       /* layer 4  is unused */
     ADD_NULL_HANDLER,                       /* layer 5  is unused */
-    ADD_HANDLER("fapi", NULL),              /* layer 6  is the fapi rc */
-    ADD_HANDLER("esapi", sys_err_handler),  /* layer 7  is the esapi rc */
-    ADD_HANDLER("sys", sys_err_handler),    /* layer 8  is the sys rc */
-    ADD_HANDLER("mu",  sys_err_handler),    /* layer 9  is the mu rc */
+    ADD_HANDLER("fapi", tss_err_handler),   /* layer 6  is the fapi rc */
+    ADD_HANDLER("esapi", tss_err_handler),  /* layer 7  is the esapi rc */
+    ADD_HANDLER("sys", tss_err_handler),    /* layer 8  is the sys rc */
+    ADD_HANDLER("mu",  tss_err_handler),    /* layer 9  is the mu rc */
                                             /* Defaults to the system handler */
-    ADD_HANDLER("tcti", sys_err_handler),   /* layer 10 is the tcti rc */
+    ADD_HANDLER("tcti", tss_err_handler),   /* layer 10 is the tcti rc */
                                             /* Defaults to the system handler */
     ADD_HANDLER("rmt", tpm2_ehandler),      /* layer 11 is the resource manager TPM RC */
                                             /* The RM usually duplicates TPM responses */
diff --git a/src/tss2-tcti/tcti-mssim.c b/src/tss2-tcti/tcti-mssim.c
index ccc83ab..0dfca5c 100644
--- a/src/tss2-tcti/tcti-mssim.c
+++ b/src/tss2-tcti/tcti-mssim.c
@@ -304,9 +304,10 @@
     unsigned char *response_buffer,
     int32_t timeout)
 {
+#ifdef TEST_FAPI_ASYNC
     /* Used for simulating a timeout. */
     static int wait = 0;
-
+#endif
     TSS2_TCTI_MSSIM_CONTEXT *tcti_mssim = tcti_mssim_context_cast (tctiContext);
     TSS2_TCTI_COMMON_CONTEXT *tcti_common = tcti_mssim_down_cast (tcti_mssim);
     TSS2_RC rc;
@@ -322,16 +323,17 @@
     }
 
     if (timeout != TSS2_TCTI_TIMEOUT_BLOCK) {
-        LOG_TRACE ("Asynchronous I/O not actually implemented."
-            "A timeout is being simulated by requesting a second invocation.");
+        LOG_TRACE("Asynchronous I/O not actually implemented.");
+#ifdef TEST_FAPI_ASYNC
         if (wait < 1) {
-            LOG_TRACE("Requesting another invocation.");
+            LOG_TRACE("Simulating Async by requesting another invocation.");
             wait += 1;
             return TSS2_TCTI_RC_TRY_AGAIN;
         } else {
             LOG_TRACE("Sending the actual result.");
             wait = 0;
         }
+#endif /* TEST_FAPI_ASYNC */
     }
 
     if (tcti_common->header.size == 0) {
diff --git a/test/data/fapi/P_ECC.json b/test/data/fapi/P_ECC.json
new file mode 100644
index 0000000..ecfb21b
--- /dev/null
+++ b/test/data/fapi/P_ECC.json
@@ -0,0 +1,47 @@
+{
+    "type": "TPM2_ALG_ECC",
+    "nameAlg":"TPM2_ALG_SHA256",
+    "srk_template": "system,restricted,decrypt",
+    "srk_persistent": 0,
+    "ek_template":  "system,restricted,decrypt",
+    "ecc_signing_scheme": {
+        "scheme":"TPM2_ALG_ECDSA",
+        "details":{
+            "hashAlg":"TPM2_ALG_SHA1"
+        },
+    },
+    "rsa_signing_scheme": {
+        "scheme":"TPM2_ALG_NULL"
+    },
+    "rsa_decrypt_scheme": {
+        "scheme":"TPM2_ALG_OAEP",
+        "details":{
+            "hashAlg":"TPM2_ALG_SHA1"
+        }
+    },
+    "sym_mode":"TPM2_ALG_CFB",
+    "sym_parameters": {
+        "algorithm":"TPM2_ALG_AES",
+        "keyBits":"128",
+        "mode":"TPM2_ALG_CFB"
+    },
+    "sym_block_size": 16,
+    "pcr_selection": [
+       { "hash": "TPM2_ALG_SHA1",
+         "pcrSelect": [ 9, 15 , 13]
+       },
+       { "hash": "TPM2_ALG_SHA256",
+         "pcrSelect": [ 8, 16, 14 ]
+       }
+    ],
+    "curveID": "TPM2_ECC_NIST_P256",
+    "ek_policy": {
+        "description": "Endorsement hierarchy used for policy secret.",
+        "policy":[
+            {
+                "type":"POLICYSECRET",
+                "objectName": "4000000b",
+            }
+        ]
+    }
+}
diff --git a/test/data/fapi/P_RSA.json b/test/data/fapi/P_RSA.json
new file mode 100644
index 0000000..c98f695
--- /dev/null
+++ b/test/data/fapi/P_RSA.json
@@ -0,0 +1,58 @@
+{
+    "type": "TPM2_ALG_RSA",
+    "nameAlg":"TPM2_ALG_SHA256",
+    "srk_template": "system,restricted,decrypt,0x81000001",
+    "srk_persistent": 1,
+    "ek_template":  "system,restricted,decrypt",
+    "ecc_signing_scheme": {
+        "scheme":"TPM2_ALG_ECDSA",
+        "details":{
+            "hashAlg":"TPM2_ALG_SHA1"
+        },
+    },
+    "rsa_signing_scheme": {
+        "scheme":"TPM2_ALG_RSAPSS",
+        "details":{
+            "hashAlg":"TPM2_ALG_SHA1"
+        }
+    },
+    "rsa_decrypt_scheme": {
+        "scheme":"TPM2_ALG_OAEP",
+        "details":{
+            "hashAlg":"TPM2_ALG_SHA1"
+        }
+    },
+    "sym_mode":"TPM2_ALG_CFB",
+    "sym_parameters": {
+        "algorithm":"TPM2_ALG_AES",
+        "keyBits":"128",
+        "mode":"TPM2_ALG_CFB"
+    },
+    "sym_block_size": 16,
+    "pcr_selection": [
+        { "hash": "TPM2_ALG_SHA1",
+          "pcrSelect": [ 9, 15, 13 ]
+        },
+        { "hash": "TPM2_ALG_SHA256",
+          "pcrSelect": [ 8, 16, 14 ]
+        }
+    ],
+    "exponent": 0,
+    "keyBits": 2048,
+    "session_hash_alg": "TPM2_ALG_SHA256",
+    "session_symmetric":{
+        "algorithm":"TPM2_ALG_AES",
+        "keyBits":"128",
+        "mode":"TPM2_ALG_CFB"
+    },
+    "ek_policy": {
+        "description": "Endorsement hierarchy used for policy secret.",
+        "policy":[
+            {
+                "type":"POLICYSECRET",
+                "objectName": "4000000b",
+            }
+        ]
+    }
+
+}
diff --git a/test/data/fapi/P_RSA256.json b/test/data/fapi/P_RSA256.json
new file mode 100644
index 0000000..cf4fca0
--- /dev/null
+++ b/test/data/fapi/P_RSA256.json
@@ -0,0 +1,42 @@
+{
+    "type": "TPM2_ALG_RSA",
+    "nameAlg":"TPM2_ALG_SHA256",
+    "srk_template": "system,restricted,decrypt",
+    "srk_persistent": 0,
+    "ek_template":  "system,restricted,decrypt",
+    "ecc_signing_scheme": {
+        "scheme":"TPM2_ALG_ECDSA",
+        "details":{
+            "hashAlg":"TPM2_ALG_SHA1"
+        },
+    },
+    "rsa_signing_scheme": {
+                    "scheme":"TPM2_ALG_RSAPSS",
+                    "details":{
+                        "hashAlg":"TPM2_ALG_SHA256"
+                    }
+                },
+    "rsa_decrypt_scheme": {
+        "scheme":"TPM2_ALG_OAEP",
+        "details":{
+            "hashAlg":"TPM2_ALG_SHA1"
+        }
+    },
+    "sym_mode":"TPM2_ALG_CFB",
+    "sym_parameters": {
+        "algorithm":"TPM2_ALG_AES",
+        "keyBits":"128",
+        "mode":"TPM2_ALG_CFB"
+    },
+    "sym_block_size": 16,
+    "pcr_selection": [
+       { "hash": "TPM2_ALG_SHA1",
+         "pcrSelect": [ 9, 15, 13]
+       },
+       { "hash": "TPM2_ALG_SHA256",
+         "pcrSelect": [ 8, 16, 14 ]
+       }
+    ],
+    "exponent": 0,
+    "keyBits": 2048
+}
diff --git a/test/data/fapi/P_RSA_EK_persistent.json b/test/data/fapi/P_RSA_EK_persistent.json
new file mode 100644
index 0000000..ea4b2b0
--- /dev/null
+++ b/test/data/fapi/P_RSA_EK_persistent.json
@@ -0,0 +1,42 @@
+{
+    "type": "TPM2_ALG_RSA",
+    "nameAlg":"TPM2_ALG_SHA256",
+    "srk_template": "system,restricted,decrypt",
+    "srk_persistent": 0,
+    "ek_template": "system,restricted,decrypt,0x81000000",
+    "ecc_signing_scheme": {
+        "scheme":"TPM2_ALG_ECDSA",
+        "details":{
+            "hashAlg":"TPM2_ALG_SHA1"
+        },
+    },
+    "rsa_signing_scheme": {
+        "scheme":"TPM2_ALG_RSAPSS",
+        "details":{
+            "hashAlg":"TPM2_ALG_SHA1"
+        }
+    },
+    "rsa_decrypt_scheme": {
+        "scheme":"TPM2_ALG_OAEP",
+        "details":{
+            "hashAlg":"TPM2_ALG_SHA1"
+        }
+    },
+    "sym_mode":"TPM2_ALG_CFB",
+    "sym_parameters": {
+        "algorithm":"TPM2_ALG_AES",
+        "keyBits":"128",
+        "mode":"TPM2_ALG_CFB"
+    },
+    "sym_block_size": 16,
+    "pcr_selection": [
+        { "hash": "TPM2_ALG_SHA1",
+          "pcrSelect": [ 9, 15 ]
+        },
+        { "hash": "TPM2_ALG_SHA256",
+          "pcrSelect": [ 8, 16 ]
+        }
+    ],
+    "exponent": 0,
+    "keyBits": 2048
+}
diff --git a/test/data/fapi/P_RSA_sh_policy.json b/test/data/fapi/P_RSA_sh_policy.json
new file mode 100644
index 0000000..3bb9c69
--- /dev/null
+++ b/test/data/fapi/P_RSA_sh_policy.json
@@ -0,0 +1,64 @@
+{
+    "type": "TPM2_ALG_RSA",
+    "nameAlg":"TPM2_ALG_SHA256",
+    "srk_template": "system,restricted,decrypt,0x81000001",
+    "srk_persistent": 1,
+    "ek_template":  "system,restricted,decrypt",
+    "ecc_signing_scheme": {
+        "scheme":"TPM2_ALG_ECDSA",
+        "details":{
+            "hashAlg":"TPM2_ALG_SHA1"
+        },
+    },
+    "rsa_signing_scheme": {
+        "scheme":"TPM2_ALG_RSAPSS",
+        "details":{
+            "hashAlg":"TPM2_ALG_SHA1"
+        }
+    },
+    "rsa_decrypt_scheme": {
+        "scheme":"TPM2_ALG_OAEP",
+        "details":{
+            "hashAlg":"TPM2_ALG_SHA1"
+        }
+    },
+    "sym_mode":"TPM2_ALG_CFB",
+    "sym_parameters": {
+        "algorithm":"TPM2_ALG_AES",
+        "keyBits":"128",
+        "mode":"TPM2_ALG_CFB"
+    },
+    "sym_block_size": 16,
+    "pcr_selection": [
+        { "hash": "TPM2_ALG_SHA1",
+          "pcrSelect": [ 9, 15, 13 ]
+        },
+        { "hash": "TPM2_ALG_SHA256",
+          "pcrSelect": [ 8, 16, 14 ]
+        }
+    ],
+    "exponent": 0,
+    "keyBits": 2048,
+    "session_hash_alg": "TPM2_ALG_SHA256",
+    "session_symmetric":{
+        "algorithm":"TPM2_ALG_AES",
+        "keyBits":"128",
+        "mode":"TPM2_ALG_CFB"
+    },
+    "sh_policy": {
+        "description":"Description pol_16_0",
+
+        "policy":[
+            {
+                "type":"POLICYPCR",
+                "pcrs":[
+                    {
+                        "pcr":16,
+                        "hashAlg":"TPM2_ALG_SHA",
+                        "digest":"0000000000000000000000000000000000000000"
+                    }
+                ]
+            }
+        ]
+    }
+}
diff --git a/test/data/fapi/policies/pol_password.json b/test/data/fapi/policies/pol_password.json
new file mode 100644
index 0000000..fcfad29
--- /dev/null
+++ b/test/data/fapi/policies/pol_password.json
@@ -0,0 +1,16 @@
+{
+  "shortname":"pol_password",
+  "description":"Description pol_password",
+  "policyDigests":[
+  ],
+  "policyAuthorizations":[
+  ],
+    "policy":[
+        {
+            "type": "POLICYPASSWORD",
+             "policyDigests":[],
+                "element":{
+                }
+		}
+  ]
+}
diff --git a/test/data/fapi/policy/pol_action.json b/test/data/fapi/policy/pol_action.json
new file mode 100644
index 0000000..47e1517
--- /dev/null
+++ b/test/data/fapi/policy/pol_action.json
@@ -0,0 +1,9 @@
+{
+    "description":"The description",
+    "policy":[
+        {
+            "type": "POLICYACTION",
+			"action": "myaction"
+		}
+    ]
+}
diff --git a/test/data/fapi/policy/pol_auth_value.json b/test/data/fapi/policy/pol_auth_value.json
new file mode 100644
index 0000000..6c1cea2
--- /dev/null
+++ b/test/data/fapi/policy/pol_auth_value.json
@@ -0,0 +1,8 @@
+{
+    "description":"Description pol_auth_value",
+    "policy":[
+        {
+            "type": "POLICYAUTHVALUE",
+		}
+    ]
+}
diff --git a/test/data/fapi/policy/pol_authorize.json b/test/data/fapi/policy/pol_authorize.json
new file mode 100644
index 0000000..5cfbd34
--- /dev/null
+++ b/test/data/fapi/policy/pol_authorize.json
@@ -0,0 +1,9 @@
+{
+    "description":"Description pol_authorize",
+    "policy":[
+        {
+            "type": "POLICYAUTHORIZE",
+			"keyPath": "/HS/SRK/myPolicySignKey",
+		}
+    ]
+}
diff --git a/test/data/fapi/policy/pol_authorize_nv.json b/test/data/fapi/policy/pol_authorize_nv.json
new file mode 100644
index 0000000..d483b10
--- /dev/null
+++ b/test/data/fapi/policy/pol_authorize_nv.json
@@ -0,0 +1,9 @@
+{
+    "description":"Description pol_authorize_nv",
+    "policy":[
+        {
+            "type": "POLICYAUTHORIZENV",
+			"nvPath": "/nv/Owner/myNV",
+		}
+  ]
+}
diff --git a/test/data/fapi/policy/pol_command_code.json b/test/data/fapi/policy/pol_command_code.json
new file mode 100644
index 0000000..ab86bdf
--- /dev/null
+++ b/test/data/fapi/policy/pol_command_code.json
@@ -0,0 +1,9 @@
+{
+    "description":"Description pol_auth_value",
+    "policy":[
+        {
+            "type": "POLICYCOMMANDCODE",
+            "code": 349
+		}
+    ]
+}
diff --git a/test/data/fapi/policy/pol_countertimer.json b/test/data/fapi/policy/pol_countertimer.json
new file mode 100644
index 0000000..479c465
--- /dev/null
+++ b/test/data/fapi/policy/pol_countertimer.json
@@ -0,0 +1,10 @@
+{
+    "description":"Description pol_countertimer",
+    "policy":[
+        {
+            "type": "POLICYCOUNTERTIMER",
+		    "operandB": "ff",
+		    "operation": "UNSIGNED_LT"
+		}
+    ]
+}
diff --git a/test/data/fapi/policy/pol_cphash.json b/test/data/fapi/policy/pol_cphash.json
new file mode 100644
index 0000000..135c9e7
--- /dev/null
+++ b/test/data/fapi/policy/pol_cphash.json
@@ -0,0 +1,9 @@
+{
+    "description":"The description",
+    "policy":[
+        {
+            "type": "POLICYCPHASH",
+			"cpHash": "d1b4d44f20fa696f638e4f8a9cfceae97f9dee388143929eeea8982259b8f402"
+		}
+    ]
+}
diff --git a/test/data/fapi/policy/pol_duplicate.json b/test/data/fapi/policy/pol_duplicate.json
new file mode 100644
index 0000000..03a5e2b
--- /dev/null
+++ b/test/data/fapi/policy/pol_duplicate.json
@@ -0,0 +1,9 @@
+{
+    "description":"Description pol_duplicate",
+    "policy":[
+        {
+             "type": "POLICYDUPLICATIONSELECT",
+			"newParentPath": "ext/myNewParent",
+		}
+    ]
+}
diff --git a/test/data/fapi/policy/pol_locality.json b/test/data/fapi/policy/pol_locality.json
new file mode 100644
index 0000000..ff026ff
--- /dev/null
+++ b/test/data/fapi/policy/pol_locality.json
@@ -0,0 +1,9 @@
+{
+    "description":"Description pol_auth_value",
+    "policy":[
+        {
+            "type": "POLICYLOCALITY",
+            "locality": 1
+		}
+    ]
+}
diff --git a/test/data/fapi/policy/pol_name_hash.json b/test/data/fapi/policy/pol_name_hash.json
new file mode 100644
index 0000000..91624e5
--- /dev/null
+++ b/test/data/fapi/policy/pol_name_hash.json
@@ -0,0 +1,9 @@
+{
+    "description":"Description pol_authorize",
+    "policy":[
+        {
+            "type": "POLICYNAMEHASH",
+			"namePaths":  [ "/HS/SRK/mySignKey" ]
+		}
+    ]
+}
diff --git a/test/data/fapi/policy/pol_nv.json b/test/data/fapi/policy/pol_nv.json
new file mode 100644
index 0000000..44c51a6
--- /dev/null
+++ b/test/data/fapi/policy/pol_nv.json
@@ -0,0 +1,11 @@
+{
+    "description":"Description pol_nv",
+    "policy":[
+        {
+            "type": "POLICYNV",
+            "nvPath": "/nv/Owner/myNV",
+            "operandB": "01020304",
+            "operation": "EQ"
+        }
+    ]
+}
diff --git a/test/data/fapi/policy/pol_nv_change_auth.json b/test/data/fapi/policy/pol_nv_change_auth.json
new file mode 100644
index 0000000..b27cf1c
--- /dev/null
+++ b/test/data/fapi/policy/pol_nv_change_auth.json
@@ -0,0 +1,12 @@
+{
+    "description":"Description pol_auth_value",
+    "policy":[
+        {
+            "type": "POLICYAUTHVALUE",
+		},
+        {
+            "type": "POLICYCOMMANDCODE",
+            "code": 315
+	    }
+    ]
+}
diff --git a/test/data/fapi/policy/pol_nv_written.json b/test/data/fapi/policy/pol_nv_written.json
new file mode 100644
index 0000000..3a4a1e4
--- /dev/null
+++ b/test/data/fapi/policy/pol_nv_written.json
@@ -0,0 +1,9 @@
+{
+    "description":"Description pol_password",
+    "policy":[
+        {
+            "type": "POLICYNVWRITTEN",
+			"writtenSet": "NO"
+		}
+    ]
+}
diff --git a/test/data/fapi/policy/pol_password.json b/test/data/fapi/policy/pol_password.json
new file mode 100644
index 0000000..1eee31b
--- /dev/null
+++ b/test/data/fapi/policy/pol_password.json
@@ -0,0 +1,8 @@
+{
+    "description":"Description pol_password",
+    "policy":[
+        {
+            "type": "POLICYPASSWORD",
+		}
+    ]
+}
diff --git a/test/data/fapi/policy/pol_pcr16_0.json b/test/data/fapi/policy/pol_pcr16_0.json
new file mode 100644
index 0000000..7aaf105
--- /dev/null
+++ b/test/data/fapi/policy/pol_pcr16_0.json
@@ -0,0 +1,16 @@
+{
+    "description":"Description pol_16_0",
+
+    "policy":[
+        {
+            "type":"POLICYPCR",
+            "pcrs":[
+                {
+                    "pcr":16,
+                    "hashAlg":"TPM2_ALG_SHA",
+                    "digest":"0000000000000000000000000000000000000000"
+                }
+            ]
+        }
+    ]
+}
diff --git a/test/data/fapi/policy/pol_pcr16_0_fail.json b/test/data/fapi/policy/pol_pcr16_0_fail.json
new file mode 100644
index 0000000..451c4c3
--- /dev/null
+++ b/test/data/fapi/policy/pol_pcr16_0_fail.json
@@ -0,0 +1,15 @@
+{
+    "description":"Description pol_16_0",
+    "policy":[
+        {
+            "type":"POLICYPCR",
+            "pcrs":[
+                {
+                    "pcr":16,
+                    "hashAlg":"TPM2_ALG_SHA",
+                    "digest":"0000000000000000000000000000000000000001"
+                }
+            ]
+        }
+    ]
+}
diff --git a/test/data/fapi/policy/pol_pcr16_0_or.json b/test/data/fapi/policy/pol_pcr16_0_or.json
new file mode 100644
index 0000000..4cafc67
--- /dev/null
+++ b/test/data/fapi/policy/pol_pcr16_0_or.json
@@ -0,0 +1,42 @@
+{
+    "description":"hareness description",
+    "policy":[
+        {
+            "type":"POLICYOR",
+            "branches":[
+                {
+                    "name":"branch0",
+                    "description":"description branch 0",
+                    "policy":[
+                        {
+                            "type":"POLICYPCR",
+                            "pcrs":[
+                                {
+                                    "pcr":16,
+                                    "hashAlg":"TPM2_ALG_SHA",
+                                    "digest":"0000000000000000000000000000000000000000"
+                                }
+                            ]
+                        }
+                    ],
+                },
+                {
+                    "name":"branch1",
+                    "description":"description branch 1",
+                    "policy":[
+                        {
+                            "type":"POLICYPCR",
+                            "pcrs":[
+                                {
+                                    "pcr":16,
+                                    "hashAlg":"TPM2_ALG_SHA",
+                                    "digest":"0000000000000000000000000000000000000000"
+                                }
+                            ]
+                        }
+                    ],
+                }
+            ]
+        }
+    ]
+}
diff --git a/test/data/fapi/policy/pol_pcr16_read.json b/test/data/fapi/policy/pol_pcr16_read.json
new file mode 100644
index 0000000..5bd51ee
--- /dev/null
+++ b/test/data/fapi/policy/pol_pcr16_read.json
@@ -0,0 +1,10 @@
+{
+    "description":"Description pol_16_0",
+
+    "policy":[
+        {
+            "type":"POLICYPCR",
+            "currentPCRs":[ 15 ]
+        }
+    ]
+}
diff --git a/test/data/fapi/policy/pol_physical_presence.json b/test/data/fapi/policy/pol_physical_presence.json
new file mode 100644
index 0000000..5020677
--- /dev/null
+++ b/test/data/fapi/policy/pol_physical_presence.json
@@ -0,0 +1,9 @@
+{
+    "description":"Description pol_auth_value",
+    "policy":[
+        {
+            "type": "POLICYPHYSICALPRESENCE",
+
+		}
+  ]
+}
diff --git a/test/data/fapi/policy/pol_secret.json b/test/data/fapi/policy/pol_secret.json
new file mode 100644
index 0000000..77dcbf3
--- /dev/null
+++ b/test/data/fapi/policy/pol_secret.json
@@ -0,0 +1,9 @@
+{
+    "description":"Description pol_authorize",
+    "policy":[
+        {
+            "type": "POLICYSECRET",
+			"objectPath": "/nv/Owner/myNV",
+		}
+    ]
+}
diff --git a/test/data/fapi/policy/pol_signed.json b/test/data/fapi/policy/pol_signed.json
new file mode 100644
index 0000000..a0b26fc
--- /dev/null
+++ b/test/data/fapi/policy/pol_signed.json
@@ -0,0 +1,10 @@
+{
+    "description":"Description pol_signed",
+    "policy":[
+        {
+            "type": "POLICYSIGNED",
+            "keyPEM": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoGL6IrCSAznmIIzBessI\nmW7tPOUy78uWTIaub32KnYHn78KXprrZ3ykp6WDrOQeMjv4AA+14mJbg77apVYXy\nEnkFdOMa1hszSJnp6cJvx7ILngLvFUxzbVki\/ehvgS3nRk67Njal+nMTe8hpe3UK\nQeV\/Ij+F0r6Yz91W+4LPmncAiUesRZLetI2BZsKwHYRMznmpIYpoua1NtS8QpEXR\nMmsUue19eS\/XRAPmmCfnb5BX2Tn06iCpk6wO+RfMo9etcX5cLSAuIYEQYCvV2\/0X\nTfEw607vttBN0Y54LrVOKno1vRXd5sxyRlfB0WL42F4VG5TfcJo5u1Xq7k9m9K57\n8wIDAQAB\n-----END PUBLIC KEY-----\n",
+            "keyPEMhashAlg": "SHA1"
+        }
+    ]
+}
diff --git a/test/helper/tpm_getek.c b/test/helper/tpm_getek.c
new file mode 100644
index 0000000..02d88b0
--- /dev/null
+++ b/test/helper/tpm_getek.c
@@ -0,0 +1,163 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <openssl/evp.h>
+#include <openssl/rsa.h>
+#include <openssl/pem.h>
+
+#include "tss2_sys.h"
+#include "tss2_mu.h"
+
+#define LOGMODULE test
+#include "util/log.h"
+#include "test-options.h"
+#include "context-util.h"
+
+int
+main (int argc, char *argv[])
+{
+    TSS2_RC rc;
+    TSS2_SYS_CONTEXT *sapi_context;
+    TSS2L_SYS_AUTH_COMMAND auth_cmd = {
+        .auths = {{ .sessionHandle = TPM2_RS_PW }},
+        .count = 1
+    };
+    TPM2B_SENSITIVE_CREATE in_sensitive = { 0 };
+    TPM2B_PUBLIC in_public = {
+        .publicArea = {
+            .type = TPM2_ALG_RSA,
+            .nameAlg = TPM2_ALG_SHA256,
+            .objectAttributes = (
+                TPMA_OBJECT_FIXEDTPM |
+                TPMA_OBJECT_FIXEDPARENT |
+                TPMA_OBJECT_SENSITIVEDATAORIGIN |
+                TPMA_OBJECT_ADMINWITHPOLICY |
+                TPMA_OBJECT_RESTRICTED |
+                TPMA_OBJECT_DECRYPT
+             ),
+            .authPolicy = {
+                 .size = 32,
+                 .buffer = 0x83, 0x71, 0x97, 0x67, 0x44, 0x84,
+                           0xB3, 0xF8, 0x1A, 0x90, 0xCC, 0x8D,
+                           0x46, 0xA5, 0xD7, 0x24, 0xFD, 0x52,
+                           0xD7, 0x6E, 0x06, 0x52, 0x0B, 0x64,
+                           0xF2, 0xA1, 0xDA, 0x1B, 0x33, 0x14,
+                           0x69, 0xAA,
+             },
+            .parameters.rsaDetail = {
+                .symmetric = {
+                    .algorithm = TPM2_ALG_AES,
+                    .keyBits.aes = 128,
+                    .mode.aes = TPM2_ALG_CFB,
+                },
+                .scheme = {
+                    .scheme = TPM2_ALG_NULL,
+                },
+                .keyBits = 2048,
+                .exponent = 0,
+            },
+            .unique.rsa = {
+                .size = 256,
+                .buffer = {0},
+            }
+        }
+    };
+    TPML_PCR_SELECTION creation_pcr = { 0 };
+    TPM2_HANDLE handle;
+    TPM2B_PUBLIC out_public = { 0 };
+    TSS2L_SYS_AUTH_RESPONSE auth_rsp = {
+        .count = 0
+    };
+
+    test_opts_t opts = {
+        .tcti_type      = TCTI_DEFAULT,
+        .device_file    = DEVICE_PATH_DEFAULT,
+        .socket_address = HOSTNAME_DEFAULT,
+        .socket_port    = PORT_DEFAULT,
+    };
+
+    get_test_opts_from_env (&opts);
+    if (sanity_check_test_opts (&opts) != 0)
+        exit (1);
+
+    sapi_context = sapi_init_from_opts (&opts);
+    if (sapi_context == NULL)
+        exit (1);
+
+    /* Generate the EK key */
+
+    rc = Tss2_Sys_CreatePrimary(sapi_context, TPM2_RH_ENDORSEMENT, &auth_cmd,
+                                &in_sensitive, &in_public, NULL, &creation_pcr,
+                                &handle, &out_public, NULL, NULL, NULL, NULL, &auth_rsp);
+    if (rc != TSS2_RC_SUCCESS) {
+        LOG_ERROR("TPM CreatePrimary FAILED: 0x%"PRIx32, rc);
+        exit(1);
+    }
+
+    rc = Tss2_Sys_FlushContext(sapi_context, handle);
+    if (rc != TSS2_RC_SUCCESS) {
+        LOG_ERROR("TPM FlushContext FAILED: 0x%"PRIx32, rc);
+        exit(1);
+    }
+
+    sapi_teardown_full (sapi_context);
+
+    /* Convert the key from out_public to PEM */
+
+    EVP_PKEY *evp = EVP_PKEY_new();
+    BIO *bio = BIO_new_fp(stdout, BIO_NOCLOSE);
+    RSA *rsa = RSA_new();
+    BIGNUM *e = BN_new();
+    BIGNUM *d = BN_new();
+    BIGNUM *p = BN_new();
+    BIGNUM *q = BN_new();
+    BIGNUM *dmp1 = BN_new();
+    BIGNUM *dmq1 = BN_new();
+    BIGNUM *iqmp = BN_new();
+    BIGNUM *n = BN_bin2bn(out_public.publicArea.unique.rsa.buffer,
+                          out_public.publicArea.unique.rsa.size, NULL);
+    BN_set_word(d, 0);
+    BN_set_word(p, 0);
+    BN_set_word(q, 0);
+    BN_set_word(dmp1, 0);
+    BN_set_word(dmq1, 0);
+    BN_set_word(iqmp, 0);
+    uint32_t exp;
+    if (out_public.publicArea.parameters.rsaDetail.exponent == 0)
+        exp = 65537;
+    else
+        exp = out_public.publicArea.parameters.rsaDetail.exponent;
+    BN_set_word(e, exp);
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000
+    rsa->e = e;
+    rsa->n = n;
+    rsa->d = d;
+    rsa->p = p;
+    rsa->q = q;
+    rsa->dmp1 = dmp1;
+    rsa->dmq1 = dmq1;
+    rsa->iqmp = iqmp;
+#else /* OPENSSL_VERSION_NUMBER < 0x10100000 */
+    RSA_set0_key(rsa, n, e, d);
+    RSA_set0_factors(rsa, p, q);
+    RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp);
+#endif /* OPENSSL_VERSION_NUMBER < 0x10100000 */
+
+    EVP_PKEY_assign_RSA(evp, rsa);
+
+    if (!PEM_write_bio_PUBKEY(bio, evp)) {
+        LOG_ERROR("PEM_write failed");
+        exit(1);
+    }
+
+    EVP_PKEY_free(evp);
+    BIO_free(bio);
+
+    return 0;
+}
diff --git a/test/helper/tpm_getek_ecc.c b/test/helper/tpm_getek_ecc.c
new file mode 100644
index 0000000..e7f3dec
--- /dev/null
+++ b/test/helper/tpm_getek_ecc.c
@@ -0,0 +1,186 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <openssl/evp.h>
+#include <openssl/rsa.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+#include <string.h>
+
+#include "tss2_sys.h"
+#include "tss2_mu.h"
+
+#define LOGMODULE test
+#include "util/log.h"
+#include "test-options.h"
+#include "context-util.h"
+
+void handleErrors(void)
+{
+    unsigned long errCode;
+
+    printf("An error occurred\n");
+    while((errCode = ERR_get_error()))
+    {
+        char *err = ERR_error_string(errCode, NULL);
+        printf("%s\n", err);
+    }
+    abort();
+}
+
+int
+main (int argc, char *argv[])
+{
+    TSS2_RC rc;
+    TSS2_SYS_CONTEXT *sapi_context;
+    TSS2L_SYS_AUTH_COMMAND auth_cmd = {
+        .auths = {{ .sessionHandle = TPM2_RS_PW }},
+        .count = 1
+    };
+    TPM2B_SENSITIVE_CREATE in_sensitive = { 0 };
+    TPM2B_PUBLIC in_public = {
+        .publicArea = {
+            .type = TPM2_ALG_ECC,
+            .nameAlg = TPM2_ALG_SHA256,
+            .objectAttributes = (
+                                 TPMA_OBJECT_FIXEDTPM |
+                                 TPMA_OBJECT_FIXEDPARENT |
+                                 TPMA_OBJECT_SENSITIVEDATAORIGIN |
+                                 TPMA_OBJECT_ADMINWITHPOLICY |
+                                 TPMA_OBJECT_RESTRICTED |
+                                 TPMA_OBJECT_DECRYPT
+                                 ),
+            .authPolicy = {
+                .size = 32,
+                .buffer = 0x83, 0x71, 0x97, 0x67, 0x44, 0x84,
+                0xB3, 0xF8, 0x1A, 0x90, 0xCC, 0x8D,
+                0x46, 0xA5, 0xD7, 0x24, 0xFD, 0x52,
+                0xD7, 0x6E, 0x06, 0x52, 0x0B, 0x64,
+                0xF2, 0xA1, 0xDA, 0x1B, 0x33, 0x14,
+                0x69, 0xAA,
+            },
+            .parameters.eccDetail = {
+                .symmetric = {
+                    .algorithm = TPM2_ALG_AES,
+                    .keyBits.aes = 128,
+                    .mode.aes = TPM2_ALG_CFB,
+                },
+                .scheme = {
+                    .scheme = TPM2_ALG_NULL,
+                    .details = { 0 }
+                },
+                .curveID = TPM2_ECC_NIST_P256,
+                .kdf = {.scheme = TPM2_ALG_NULL,
+                        .details = { 0 }
+                }
+            },
+            .unique.ecc = {
+                .x = {.size = 32,.buffer = { 0 }},
+                .y = {.size = 32,.buffer = { 0 }}
+            }
+        }
+    };
+    TPML_PCR_SELECTION creation_pcr = { 0 };
+    TPM2_HANDLE handle;
+    TPM2B_PUBLIC out_public = { 0 };
+    TSS2L_SYS_AUTH_RESPONSE auth_rsp = {
+        .count = 0
+    };
+
+    test_opts_t opts = {
+        .tcti_type      = TCTI_DEFAULT,
+        .device_file    = DEVICE_PATH_DEFAULT,
+        .socket_address = HOSTNAME_DEFAULT,
+        .socket_port    = PORT_DEFAULT,
+    };
+
+    get_test_opts_from_env (&opts);
+    if (sanity_check_test_opts (&opts) != 0)
+        exit (1);
+
+    sapi_context = sapi_init_from_opts (&opts);
+    if (sapi_context == NULL)
+        exit (1);
+
+    /* Generate the EK key */
+
+    rc = Tss2_Sys_CreatePrimary(sapi_context, TPM2_RH_ENDORSEMENT, &auth_cmd,
+                                &in_sensitive, &in_public, NULL, &creation_pcr,
+                                &handle, &out_public, NULL, NULL, NULL, NULL, &auth_rsp);
+    if (rc != TSS2_RC_SUCCESS) {
+        LOG_ERROR("TPM CreatePrimary FAILED: 0x%"PRIx32, rc);
+        exit(1);
+    }
+
+    rc = Tss2_Sys_FlushContext(sapi_context, handle);
+    if (rc != TSS2_RC_SUCCESS) {
+        LOG_ERROR("TPM FlushContext FAILED: 0x%"PRIx32, rc);
+        exit(1);
+    }
+
+    sapi_teardown_full (sapi_context);
+
+    /* Convert the key from out_public to PEM */
+
+    EVP_PKEY *evp = EVP_PKEY_new();
+
+    OpenSSL_add_all_algorithms();
+
+    OpenSSL_add_all_algorithms();
+
+    ERR_load_crypto_strings();
+
+
+    EC_KEY *ecc_key = EC_KEY_new();
+    BIGNUM *x = NULL, *y = NULL;
+    BIO *bio = BIO_new_fp(stdout, BIO_NOCLOSE);
+    int nid;
+
+    nid = EC_curve_nist2nid("P-256");
+    EC_GROUP *ecgroup = EC_GROUP_new_by_curve_name(nid);
+
+    if (!EC_KEY_set_group(ecc_key, ecgroup))
+        exit(1);
+
+    EC_KEY_set_asn1_flag(ecc_key, OPENSSL_EC_NAMED_CURVE);
+    EC_GROUP_free(ecgroup);
+
+    /* Set the ECC parameters in the OpenSSL key */
+    x = BN_bin2bn(out_public.publicArea.unique.ecc.x.buffer,
+                  out_public.publicArea.unique.ecc.x.size, NULL);
+
+    y = BN_bin2bn(out_public.publicArea.unique.ecc.y.buffer,
+                  out_public.publicArea.unique.ecc.y.size, NULL);
+
+    if (!x || !y) {
+        exit(1);
+    }
+
+    if (!EC_KEY_set_public_key_affine_coordinates(ecc_key, x, y)) {
+        exit(1);
+    }
+
+    if (!EVP_PKEY_assign_EC_KEY(evp, ecc_key)) {
+        handleErrors();
+        LOG_ERROR("PEM_write failed");
+        exit(1);
+    }
+
+    if (!PEM_write_bio_PUBKEY(bio, evp)) {
+        handleErrors();
+        LOG_ERROR("PEM_write failed");
+        exit(1);
+    }
+
+    BN_free(y);
+    BN_free(x);
+    EVP_PKEY_free(evp);
+    BIO_free(bio);
+
+    return 0;
+}
diff --git a/test/helper/tpm_writeekcert.c b/test/helper/tpm_writeekcert.c
new file mode 100644
index 0000000..5bdbcde
--- /dev/null
+++ b/test/helper/tpm_writeekcert.c
@@ -0,0 +1,127 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <inttypes.h>
+
+#include "tss2_sys.h"
+#include "tss2_mu.h"
+
+#define LOGMODULE test
+#include "util/log.h"
+#include "test-options.h"
+#include "context-util.h"
+
+#define TAB_SIZE(x) (sizeof(x)/sizeof(x[0]))
+
+/* NOTE: CAP_PCRS and CAP_HANDLES->HR_PCR do not change until a reboot is
+  triggered. This should be improved if an approach is found. */
+struct {
+    TPM2_CAP cap;
+    UINT32 prop;
+    UINT32 count;
+} capabilities[] = {
+    { TPM2_CAP_PCRS, 0, 10 },
+    { TPM2_CAP_HANDLES, TPM2_HR_PCR, TPM2_MAX_CAP_HANDLES },
+    { TPM2_CAP_HANDLES, TPM2_HR_HMAC_SESSION, TPM2_MAX_CAP_HANDLES },
+    { TPM2_CAP_HANDLES, TPM2_HR_POLICY_SESSION, TPM2_MAX_CAP_HANDLES },
+    { TPM2_CAP_HANDLES, TPM2_HR_TRANSIENT, TPM2_MAX_CAP_HANDLES },
+    { TPM2_CAP_HANDLES, TPM2_HR_PERSISTENT, TPM2_MAX_CAP_HANDLES },
+    { TPM2_CAP_HANDLES, TPM2_HR_NV_INDEX, TPM2_MAX_CAP_HANDLES },
+};
+
+int
+main (int argc, char *argv[])
+{
+    TSS2_RC rc;
+    TSS2_SYS_CONTEXT *sapi_context;
+    TSS2L_SYS_AUTH_COMMAND auth_cmd = {
+        .auths = {{ .sessionHandle = TPM2_RS_PW }},
+        .count = 1
+    };
+    TPMI_RH_NV_INDEX nvIndex;
+
+    if (argv[1])
+        nvIndex = strtol(argv[1], NULL, 16);
+    else
+        nvIndex = 0x01c00002;
+
+    TPM2B_AUTH nv_auth = { 0 };
+    TPM2B_NV_PUBLIC public_info = {
+        .nvPublic = {
+            .nameAlg = TPM2_ALG_SHA1,
+            .attributes = TPMA_NV_PPWRITE | TPMA_NV_AUTHREAD | TPMA_NV_OWNERREAD |
+                TPMA_NV_PLATFORMCREATE | TPMA_NV_NO_DA,
+            .dataSize = 0,
+            .nvIndex = nvIndex,
+        },
+    };
+
+    TSS2L_SYS_AUTH_RESPONSE auth_rsp = {
+        .count = 0
+    };
+    TPM2B_MAX_NV_BUFFER buf1 = { 0 };
+    TPM2B_MAX_NV_BUFFER buf2 = { 0 };
+
+    buf1.size += fread(&buf1.buffer[buf1.size], sizeof(buf1.buffer[0]),
+                       sizeof(buf1.buffer) - buf1.size, stdin);
+    if (buf1.size >= sizeof(buf1.buffer)) {
+        LOG_ERROR("input to large");
+        exit(1);
+    }
+
+    test_opts_t opts = {
+        .tcti_type      = TCTI_DEFAULT,
+        .device_file    = DEVICE_PATH_DEFAULT,
+        .socket_address = HOSTNAME_DEFAULT,
+        .socket_port    = PORT_DEFAULT,
+    };
+
+    get_test_opts_from_env (&opts);
+    if (sanity_check_test_opts (&opts) != 0)
+        exit (1);
+
+    sapi_context = sapi_init_from_opts (&opts);
+    if (sapi_context == NULL)
+        exit (1);
+
+    /* First make sure that not EK certificate is currently loaded */
+    LOG_WARNING("Cert input size is %"PRIu16, buf1.size);
+    public_info.nvPublic.dataSize = buf1.size;
+
+    LOG_WARNING("Define NV cert with nv index: %x", public_info.nvPublic.nvIndex);
+
+    rc = Tss2_Sys_NV_DefineSpace(sapi_context, TPM2_RH_PLATFORM, &auth_cmd,
+                                 &nv_auth, &public_info, &auth_rsp);
+    if (rc != TSS2_RC_SUCCESS) {
+        LOG_ERROR("TPM NV DefineSpace FAILED: 0x%"PRIx32, rc);
+        exit(1);
+    }
+
+    /* Split the input buffer into 2 chunks */
+    buf2.size = buf1.size;
+    buf1.size /= 2;
+    buf2.size -= buf1.size;
+    memcpy(&buf2.buffer[0], &buf1.buffer[buf1.size], buf2.size);
+
+    rc = Tss2_Sys_NV_Write(sapi_context, TPM2_RH_PLATFORM, nvIndex, &auth_cmd,
+                           &buf1, 0, &auth_rsp);
+    if (rc != TSS2_RC_SUCCESS) {
+        LOG_ERROR("TPM NV Write FAILED: 0x%"PRIx32, rc);
+        exit(1);
+    }
+
+    rc = Tss2_Sys_NV_Write(sapi_context, TPM2_RH_PLATFORM, nvIndex, &auth_cmd,
+                           &buf2, buf1.size, &auth_rsp);
+    if (rc != TSS2_RC_SUCCESS) {
+        LOG_ERROR("TPM NV Write FAILED: 0x%"PRIx32, rc);
+        exit(1);
+    }
+
+    sapi_teardown_full (sapi_context);
+
+    return 0;
+}
diff --git a/test/integration/esys-audit.int.c b/test/integration/esys-audit.int.c
index eedb9c8..22ff091 100644
--- a/test/integration/esys-audit.int.c
+++ b/test/integration/esys-audit.int.c
@@ -52,6 +52,14 @@
     ESYS_TR session = ESYS_TR_NONE;
     int failure_return = EXIT_FAILURE;
 
+    TPM2B_PUBLIC *outPublic = NULL;
+    TPM2B_CREATION_DATA *creationData = NULL;
+    TPM2B_DIGEST *creationHash = NULL;
+    TPMT_TK_CREATION *creationTicket = NULL;
+    TPMS_CAPABILITY_DATA *capabilityData = NULL;
+    TPM2B_ATTEST *auditInfo = NULL;
+    TPMT_SIGNATURE *signature = NULL;
+
     /* Compute a signing key */
     TPM2B_AUTH authValuePrimary = {
         .size = 5,
@@ -128,11 +136,6 @@
     r = Esys_TR_SetAuth(esys_context, ESYS_TR_RH_OWNER, &authValue);
     goto_if_error(r, "Error: TR_SetAuth", error);
 
-    TPM2B_PUBLIC *outPublic;
-    TPM2B_CREATION_DATA *creationData;
-    TPM2B_DIGEST *creationHash;
-    TPMT_TK_CREATION *creationTicket;
-
     r = Esys_CreatePrimary(esys_context, ESYS_TR_RH_OWNER, ESYS_TR_PASSWORD,
                            ESYS_TR_NONE, ESYS_TR_NONE, &inSensitivePrimary,
                            &inPublic, &outsideInfo, &creationPCR,
@@ -161,7 +164,6 @@
     TPM2_CAP capability = TPM2_CAP_TPM_PROPERTIES;
     UINT32 property = TPM2_PT_LOCKOUT_COUNTER;
     UINT32 propertyCount = 1;
-    TPMS_CAPABILITY_DATA *capabilityData;
     TPMI_YES_NO moreData;
 
     r = Esys_GetCapability(esys_context,
@@ -174,8 +176,6 @@
     ESYS_TR privacyHandle = ESYS_TR_RH_ENDORSEMENT;
     TPM2B_DATA qualifyingData = {0};
     TPMT_SIG_SCHEME inScheme = { .scheme = TPM2_ALG_NULL };
-    TPM2B_ATTEST *auditInfo;
-    TPMT_SIGNATURE *signature;
 
     /* Test the audit commands */
     r = Esys_GetCommandAuditDigest(
@@ -198,6 +198,9 @@
         goto error;
     }
 
+    Esys_Free(auditInfo);
+    Esys_Free(signature);
+
     goto_if_error(r, "Error: GetCommandAuditDigest", error);
 
     r = Esys_GetSessionAuditDigest(
@@ -245,6 +248,13 @@
     r = Esys_FlushContext(esys_context, session);
     goto_if_error(r, "Error during FlushContext", error);
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+    Esys_Free(capabilityData);
+    Esys_Free(auditInfo);
+    Esys_Free(signature);
     return EXIT_SUCCESS;
 
  error:
@@ -260,6 +270,13 @@
             LOG_ERROR("Cleanup signHandle failed.");
         }
     }
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+    Esys_Free(capabilityData);
+    Esys_Free(auditInfo);
+    Esys_Free(signature);
     return failure_return;
 }
 
diff --git a/test/integration/esys-certify-creation.int.c b/test/integration/esys-certify-creation.int.c
index 79426f3..a4500e5 100644
--- a/test/integration/esys-certify-creation.int.c
+++ b/test/integration/esys-certify-creation.int.c
@@ -38,6 +38,13 @@
     TSS2_RC r;
     ESYS_TR signHandle = ESYS_TR_NONE;
 
+    TPM2B_PUBLIC *outPublic = NULL;
+    TPM2B_CREATION_DATA *creationData = NULL;
+    TPM2B_DIGEST *creationHash = NULL;
+    TPMT_TK_CREATION *creationTicket = NULL;
+    TPM2B_ATTEST *certifyInfo = NULL;
+    TPMT_SIGNATURE *signature = NULL;
+
     TPM2B_AUTH authValuePrimary = {
         .size = 5,
         .buffer = {1, 2, 3, 4, 5}
@@ -117,11 +124,6 @@
     r = Esys_TR_SetAuth(esys_context, ESYS_TR_RH_OWNER, &authValue);
     goto_if_error(r, "Error: TR_SetAuth", error);
 
-    TPM2B_PUBLIC *outPublic;
-    TPM2B_CREATION_DATA *creationData;
-    TPM2B_DIGEST *creationHash;
-    TPMT_TK_CREATION *creationTicket;
-
     r = Esys_CreatePrimary(esys_context, ESYS_TR_RH_OWNER, ESYS_TR_PASSWORD,
                            ESYS_TR_NONE, ESYS_TR_NONE, &inSensitivePrimary,
                            &inPublic, &outsideInfo, &creationPCR,
@@ -131,8 +133,6 @@
 
     TPM2B_DATA qualifyingData = {0};;
     TPMT_SIG_SCHEME inScheme = { .scheme = TPM2_ALG_NULL };;
-    TPM2B_ATTEST *certifyInfo;
-    TPMT_SIGNATURE *signature;
 
     r = Esys_CertifyCreation(
         esys_context,
@@ -152,6 +152,12 @@
     r = Esys_FlushContext(esys_context,signHandle);
     goto_if_error(r, "Error: FlushContext", error);
 
+    Esys_Free(certifyInfo);
+    Esys_Free(signature);
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
     return EXIT_SUCCESS;
 
  error:
@@ -161,6 +167,12 @@
             LOG_ERROR("Cleanup signHandle failed.");
         }
     }
+    Esys_Free(certifyInfo);
+    Esys_Free(signature);
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
     return EXIT_FAILURE;
 }
 
diff --git a/test/integration/esys-certify.int.c b/test/integration/esys-certify.int.c
index 765a7d1..c2f444b 100644
--- a/test/integration/esys-certify.int.c
+++ b/test/integration/esys-certify.int.c
@@ -38,6 +38,13 @@
     TSS2_RC r;
     ESYS_TR signHandle = ESYS_TR_NONE;
 
+    TPM2B_PUBLIC *outPublic = NULL;
+    TPM2B_CREATION_DATA *creationData = NULL;
+    TPM2B_DIGEST *creationHash = NULL;
+    TPMT_TK_CREATION *creationTicket = NULL;
+    TPM2B_ATTEST *certifyInfo = NULL;
+    TPMT_SIGNATURE *signature = NULL;
+
     TPM2B_AUTH authValuePrimary = {
         .size = 5,
         .buffer = {1, 2, 3, 4, 5}
@@ -117,11 +124,6 @@
     r = Esys_TR_SetAuth(esys_context, ESYS_TR_RH_OWNER, &authValue);
     goto_if_error(r, "Error: TR_SetAuth", error);
 
-    TPM2B_PUBLIC *outPublic;
-    TPM2B_CREATION_DATA *creationData;
-    TPM2B_DIGEST *creationHash;
-    TPMT_TK_CREATION *creationTicket;
-
     r = Esys_CreatePrimary(esys_context, ESYS_TR_RH_OWNER, ESYS_TR_PASSWORD,
                            ESYS_TR_NONE, ESYS_TR_NONE, &inSensitivePrimary,
                            &inPublic, &outsideInfo, &creationPCR,
@@ -131,8 +133,6 @@
 
     TPM2B_DATA qualifyingData = {0};
     TPMT_SIG_SCHEME inScheme = { .scheme = TPM2_ALG_NULL };
-    TPM2B_ATTEST *certifyInfo;
-    TPMT_SIGNATURE *signature;
 
     r = Esys_Certify (
         esys_context,
@@ -151,6 +151,12 @@
     r = Esys_FlushContext(esys_context,signHandle);
     goto_if_error(r, "Error: FlushContext", error);
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+    Esys_Free(certifyInfo);
+    Esys_Free(signature);
     return EXIT_SUCCESS;
 
  error:
@@ -160,6 +166,12 @@
             LOG_ERROR("Cleanup signHandle failed.");
         }
     }
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+    Esys_Free(certifyInfo);
+    Esys_Free(signature);
     return EXIT_FAILURE;
 }
 
diff --git a/test/integration/esys-commit.int.c b/test/integration/esys-commit.int.c
index d397362..450d46d 100644
--- a/test/integration/esys-commit.int.c
+++ b/test/integration/esys-commit.int.c
@@ -42,6 +42,16 @@
     ESYS_TR eccHandle = ESYS_TR_NONE;
     ESYS_TR session = ESYS_TR_NONE;
     int failure_return = EXIT_FAILURE;
+
+    TPM2B_PUBLIC *outPublic = NULL;
+    TPM2B_CREATION_DATA *creationData = NULL;
+    TPM2B_DIGEST *creationHash = NULL;
+    TPMT_TK_CREATION *creationTicket = NULL;
+
+    TPM2B_ECC_POINT *K = NULL;
+    TPM2B_ECC_POINT *L = NULL;
+    TPM2B_ECC_POINT *E = NULL;
+
     TPMT_SYM_DEF symmetric = {
         .algorithm = TPM2_ALG_AES,
         .keyBits = { .aes = 128 },
@@ -131,11 +141,6 @@
     r = Esys_TR_SetAuth(esys_context, ESYS_TR_RH_OWNER, &authValue);
     goto_if_error(r, "Error: TR_SetAuth", error);
 
-    TPM2B_PUBLIC *outPublic;
-    TPM2B_CREATION_DATA *creationData;
-    TPM2B_DIGEST *creationHash;
-    TPMT_TK_CREATION *creationTicket;
-
     r = Esys_CreatePrimary(esys_context, ESYS_TR_RH_OWNER, session,
                            ESYS_TR_NONE, ESYS_TR_NONE, &inSensitive, &inPublic,
                            &outsideInfo, &creationPCR, &eccHandle,
@@ -153,9 +158,6 @@
     TPM2B_ECC_POINT P1 = {0};
     TPM2B_SENSITIVE_DATA s2 = {0};
     TPM2B_ECC_PARAMETER y2 = {0};
-    TPM2B_ECC_POINT *K;
-    TPM2B_ECC_POINT *L;
-    TPM2B_ECC_POINT *E;
     UINT16 counter;
     r = Esys_Commit(esys_context, eccHandle,
                     session, ESYS_TR_NONE, ESYS_TR_NONE,
@@ -173,6 +175,13 @@
 
     session = ESYS_TR_NONE;
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+    Esys_Free(K);
+    Esys_Free(L);
+    Esys_Free(E);
     return EXIT_SUCCESS;
 
  error:
@@ -190,6 +199,13 @@
         }
     }
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+    Esys_Free(K);
+    Esys_Free(L);
+    Esys_Free(E);
     return failure_return;
 }
 
diff --git a/test/integration/esys-create-fail.int.c b/test/integration/esys-create-fail.int.c
index 04c85c6..8cc0b8b 100644
--- a/test/integration/esys-create-fail.int.c
+++ b/test/integration/esys-create-fail.int.c
@@ -42,6 +42,16 @@
     TSS2_RC r;
     ESYS_TR primaryHandle = ESYS_TR_NONE;
 
+    TPM2B_PUBLIC *outPublic = NULL;
+    TPM2B_CREATION_DATA *creationData = NULL;
+    TPM2B_DIGEST *creationHash = NULL;
+    TPMT_TK_CREATION *creationTicket = NULL;
+    TPM2B_PUBLIC *outPublic2 = NULL;
+    TPM2B_PRIVATE *outPrivate2 = NULL;
+    TPM2B_CREATION_DATA *creationData2 = NULL;
+    TPM2B_DIGEST *creationHash2 = NULL;
+    TPMT_TK_CREATION *creationTicket2 = NULL;
+
     TPM2B_AUTH authValuePrimary = {
         .size = 5,
         .buffer = {1, 2, 3, 4, 5}
@@ -154,10 +164,6 @@
     goto_if_error(r, "Error: TR_SetAuth", error);
 
     RSRC_NODE_T *primaryHandle_node;
-    TPM2B_PUBLIC *outPublic;
-    TPM2B_CREATION_DATA *creationData;
-    TPM2B_DIGEST *creationHash;
-    TPMT_TK_CREATION *creationTicket;
 
     r = Esys_CreatePrimary(esys_context, ESYS_TR_RH_OWNER, ESYS_TR_PASSWORD,
                            ESYS_TR_NONE, ESYS_TR_NONE, &inSensitivePrimary,
@@ -177,12 +183,6 @@
     r = Esys_TR_SetAuth(esys_context, primaryHandle, &authValuePrimary);
     goto_if_error(r, "Error: TR_SetAuth", error);
 
-    TPM2B_PUBLIC *outPublic2;
-    TPM2B_PRIVATE *outPrivate2;
-    TPM2B_CREATION_DATA *creationData2;
-    TPM2B_DIGEST *creationHash2;
-    TPMT_TK_CREATION *creationTicket2;
-
     r = Esys_Create(esys_context,
                     primaryHandle,
                     ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
@@ -208,6 +208,10 @@
     r = Esys_FlushContext(esys_context, primaryHandle);
     goto_if_error(r, "Error during FlushContext", error);
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
     return EXIT_SUCCESS;
 
  error:
@@ -217,6 +221,10 @@
             LOG_ERROR("Cleanup primaryHandle failed.");
         }
     }
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
     return EXIT_FAILURE;
 }
 
diff --git a/test/integration/esys-create-password-auth.int.c b/test/integration/esys-create-password-auth.int.c
index 5aa6de4..6f41ca0 100644
--- a/test/integration/esys-create-password-auth.int.c
+++ b/test/integration/esys-create-password-auth.int.c
@@ -46,6 +46,17 @@
     ESYS_TR primaryHandle = ESYS_TR_NONE;
     ESYS_TR loadedKeyHandle = ESYS_TR_NONE;
 
+    TPM2B_PUBLIC *outPublic = NULL;
+    TPM2B_CREATION_DATA *creationData = NULL;
+    TPM2B_DIGEST *creationHash = NULL;
+    TPMT_TK_CREATION *creationTicket = NULL;
+
+    TPM2B_PUBLIC *outPublic2 = NULL;
+    TPM2B_PRIVATE *outPrivate2 = NULL;
+    TPM2B_CREATION_DATA *creationData2 = NULL;
+    TPM2B_DIGEST *creationHash2 = NULL;
+    TPMT_TK_CREATION *creationTicket2 = NULL;
+
     TPM2B_AUTH authValuePrimary = {
         .size = 5,
         .buffer = {1, 2, 3, 4, 5}
@@ -157,12 +168,7 @@
     r = Esys_TR_SetAuth(esys_context, ESYS_TR_RH_OWNER, &authValue);
     goto_if_error(r, "Error: TR_SetAuth", error);
 
-    RSRC_NODE_T *primaryHandle_node;
-    TPM2B_PUBLIC *outPublic;
-    TPM2B_CREATION_DATA *creationData;
-    TPM2B_DIGEST *creationHash;
-    TPMT_TK_CREATION *creationTicket;
-
+    RSRC_NODE_T *primaryHandle_node = NULL;
     r = Esys_CreatePrimary(esys_context, ESYS_TR_RH_OWNER, ESYS_TR_PASSWORD,
                            ESYS_TR_NONE, ESYS_TR_NONE,
                            &inSensitivePrimary, &inPublic,
@@ -262,12 +268,6 @@
         .count = 0,
     };
 
-    TPM2B_PUBLIC *outPublic2;
-    TPM2B_PRIVATE *outPrivate2;
-    TPM2B_CREATION_DATA *creationData2;
-    TPM2B_DIGEST *creationHash2;
-    TPMT_TK_CREATION *creationTicket2;
-
     r = Esys_Create(esys_context,
                     primaryHandle,
                     ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
@@ -294,6 +294,12 @@
     r = Esys_TR_SetAuth(esys_context, loadedKeyHandle, &authKey2);
     goto_if_error(r, "Error esys TR_SetAuth ", error);
 
+    Esys_Free(outPublic2);
+    Esys_Free(outPrivate2);
+    Esys_Free(creationData2);
+    Esys_Free(creationHash2);
+    Esys_Free(creationTicket2);
+
     r = Esys_Create(esys_context,
                     loadedKeyHandle,
                     ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
@@ -314,6 +320,15 @@
     loadedKeyHandle = ESYS_TR_NONE;
     goto_if_error(r, "Error during FlushContext", error);
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+    Esys_Free(outPublic2);
+    Esys_Free(outPrivate2);
+    Esys_Free(creationData2);
+    Esys_Free(creationHash2);
+    Esys_Free(creationTicket2);
     return EXIT_SUCCESS;
 
  error:
@@ -330,6 +345,15 @@
         }
     }
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+    Esys_Free(outPublic2);
+    Esys_Free(outPrivate2);
+    Esys_Free(creationData2);
+    Esys_Free(creationHash2);
+    Esys_Free(creationTicket2);
     return EXIT_FAILURE;
 }
 
diff --git a/test/integration/esys-create-policy-auth.int.c b/test/integration/esys-create-policy-auth.int.c
index 1c53161..4534504 100644
--- a/test/integration/esys-create-policy-auth.int.c
+++ b/test/integration/esys-create-policy-auth.int.c
@@ -42,7 +42,11 @@
     ESYS_TR primaryHandle = ESYS_TR_NONE;
     ESYS_TR trialHandle = ESYS_TR_NONE;
     ESYS_TR policyHandle = ESYS_TR_NONE;
-    TPM2B_DIGEST *trialDigest;
+
+    TPM2B_DIGEST *trialDigest = NULL;
+    TPM2B_PUBLIC *outPublic = NULL;
+    TPM2B_PUBLIC *outPublic2 = NULL;
+    TPM2B_PRIVATE *outPrivate2 = NULL;
 
     TPMT_SYM_DEF policyAlgo = {
         .algorithm = TPM2_ALG_AES,
@@ -166,8 +170,6 @@
         .count = 0,
     };
 
-    TPM2B_PUBLIC *outPublic;
-
     r = Esys_CreatePrimary(esys_context, ESYS_TR_RH_OWNER, ESYS_TR_PASSWORD,
                            ESYS_TR_NONE, ESYS_TR_NONE,
                            &inSensitivePrimary, &inPublic,
@@ -250,9 +252,6 @@
         .count = 0,
     };
 
-    TPM2B_PUBLIC *outPublic2;
-    TPM2B_PRIVATE *outPrivate2;
-
     r = Esys_Create(esys_context, primaryHandle, policyHandle, ESYS_TR_NONE,
                     ESYS_TR_NONE, &inSensitive2, &inPublic2, &outsideInfo2,
                     &creationPCR2, &outPrivate2, &outPublic2, NULL, NULL, NULL);
@@ -268,6 +267,10 @@
     primaryHandle = ESYS_TR_NONE;
     goto_if_error(r, "Error during FlushContext", error);
 
+    Esys_Free(trialDigest);
+    Esys_Free(outPublic);
+    Esys_Free(outPublic2);
+    Esys_Free(outPrivate2);
     return EXIT_SUCCESS;
 
 error:
@@ -290,6 +293,10 @@
         }
     }
 
+    Esys_Free(trialDigest);
+    Esys_Free(outPublic);
+    Esys_Free(outPublic2);
+    Esys_Free(outPrivate2);
     return EXIT_FAILURE;
 }
 
diff --git a/test/integration/esys-create-primary-hmac.int.c b/test/integration/esys-create-primary-hmac.int.c
index d3b2746..9fd2987 100644
--- a/test/integration/esys-create-primary-hmac.int.c
+++ b/test/integration/esys-create-primary-hmac.int.c
@@ -42,6 +42,11 @@
     ESYS_TR session = ESYS_TR_NONE;
     TPMT_SYM_DEF symmetric = { .algorithm = TPM2_ALG_NULL };
 
+    TPM2B_PUBLIC *outPublic = NULL;
+    TPM2B_CREATION_DATA *creationData = NULL;
+    TPM2B_DIGEST *creationHash = NULL;
+    TPMT_TK_CREATION *creationTicket = NULL;
+
     r = Esys_StartAuthSession(esys_context, ESYS_TR_NONE, ESYS_TR_NONE,
                               ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
                               NULL,
@@ -164,10 +169,6 @@
     goto_if_error(r, "Error: TR_SetAuth", error);
 
     RSRC_NODE_T *objectHandle_node;
-    TPM2B_PUBLIC *outPublic;
-    TPM2B_CREATION_DATA *creationData;
-    TPM2B_DIGEST *creationHash;
-    TPMT_TK_CREATION *creationTicket;
 
     r = Esys_CreatePrimary(esys_context, ESYS_TR_RH_OWNER, session,
                            ESYS_TR_NONE, ESYS_TR_NONE, &inSensitive, &inPublic,
@@ -179,17 +180,21 @@
     r = esys_GetResourceObject(esys_context, objectHandle,
                                &objectHandle_node);
     goto_if_error(r, "Error Esys GetResourceObject", error);
-    LOG_INFO("Created Primary with TPM handle 0x%08x...",
-             objectHandle_node->rsrc.handle);
+    ESYS_TR tpmHandle = objectHandle_node->rsrc.handle;
+    LOG_INFO("Created Primary with TPM handle 0x%08x...", tpmHandle);
 
     r = Esys_FlushContext(esys_context, objectHandle);
     goto_if_error(r, "Error during FlushContext", error);
 
-    LOG_INFO("Done with handle 0x%08x...", objectHandle_node->rsrc.handle);
+    LOG_INFO("Done with handle 0x%08x...", tpmHandle);
 
     r = Esys_FlushContext(esys_context, session);
     goto_if_error(r, "Flushing context", error);
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
     return EXIT_SUCCESS;
 
  error:
@@ -207,7 +212,10 @@
         }
     }
 
-
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
     return EXIT_FAILURE;
 }
 
diff --git a/test/integration/esys-create-session-auth.int.c b/test/integration/esys-create-session-auth.int.c
index 27a61e5..12fe7e3 100644
--- a/test/integration/esys-create-session-auth.int.c
+++ b/test/integration/esys-create-session-auth.int.c
@@ -56,6 +56,24 @@
     ESYS_TR primaryHandle_AuthSession = ESYS_TR_NONE;
     ESYS_TR session = ESYS_TR_NONE;
 
+    TPM2B_PUBLIC *outPublic = NULL;
+    TPM2B_CREATION_DATA *creationData = NULL;
+    TPM2B_DIGEST *creationHash = NULL;
+    TPMT_TK_CREATION *creationTicket = NULL;
+
+#ifdef TEST_ECC
+    TPM2B_PUBLIC *outPublicEcc = NULL;
+    TPM2B_CREATION_DATA *creationDataEcc = NULL;
+    TPM2B_DIGEST *creationHashEcc = NULL;
+    TPMT_TK_CREATION *creationTicketEcc = NULL;
+#endif
+
+    TPM2B_PUBLIC *outPublic2 = NULL;
+    TPM2B_PRIVATE *outPrivate2 = NULL;
+    TPM2B_CREATION_DATA *creationData2 = NULL;
+    TPM2B_DIGEST *creationHash2 = NULL;
+    TPMT_TK_CREATION *creationTicket2 = NULL;
+
     TPM2B_AUTH authValuePrimary = {
         .size = 5,
         .buffer = {1, 2, 3, 4, 5}
@@ -165,10 +183,6 @@
     goto_if_error(r, "Error: TR_SetAuth", error);
 
     RSRC_NODE_T *primaryHandle_node;
-    TPM2B_PUBLIC *outPublic;
-    TPM2B_CREATION_DATA *creationData;
-    TPM2B_DIGEST *creationHash;
-    TPMT_TK_CREATION *creationTicket;
 
     r = Esys_CreatePrimary(esys_context, ESYS_TR_RH_OWNER, ESYS_TR_PASSWORD,
                            ESYS_TR_NONE, ESYS_TR_NONE, &inSensitivePrimary, &inPublic,
@@ -189,11 +203,6 @@
 
 
 #ifdef TEST_ECC
-    TPM2B_PUBLIC *outPublicEcc;
-    TPM2B_CREATION_DATA *creationDataEcc;
-    TPM2B_DIGEST *creationHashEcc;
-    TPMT_TK_CREATION *creationTicketEcc;
-
     r = Esys_CreatePrimary(esys_context, ESYS_TR_RH_OWNER, ESYS_TR_PASSWORD,
                            ESYS_TR_NONE, ESYS_TR_NONE, &inSensitivePrimary, &inPublicEcc,
                            &outsideInfo, &creationPCR, &primaryHandle_AuthSession,
@@ -358,12 +367,6 @@
         .count = 0,
     };
 
-    TPM2B_PUBLIC *outPublic2;
-    TPM2B_PRIVATE *outPrivate2;
-    TPM2B_CREATION_DATA *creationData2;
-    TPM2B_DIGEST *creationHash2;
-    TPMT_TK_CREATION *creationTicket2;
-
     r = Esys_Create(esys_context,
                     primaryHandle,
                     session, ESYS_TR_NONE, ESYS_TR_NONE,
@@ -390,6 +393,12 @@
     r = Esys_TR_SetAuth(esys_context, loadedKeyHandle, &authKey2);
     goto_if_error(r, "Error esys TR_SetAuth ", error);
 
+    Esys_Free(outPublic2);
+    Esys_Free(outPrivate2);
+    Esys_Free(creationData2);
+    Esys_Free(creationHash2);
+    Esys_Free(creationTicket2);
+
     r = Esys_Create(esys_context,
                     loadedKeyHandle,
                     session, ESYS_TR_NONE, ESYS_TR_NONE,
@@ -411,6 +420,23 @@
     r = Esys_FlushContext(esys_context, session);
     goto_if_error(r, "Flushing context", error);
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+
+#ifdef TEST_ECC
+    Esys_Free(outPublicEcc);
+    Esys_Free(creationDataEcc);
+    Esys_Free(creationHashEcc);
+    Esys_Free(creationTicketEcc);
+#endif
+
+    Esys_Free(outPublic2);
+    Esys_Free(outPrivate2);
+    Esys_Free(creationData2);
+    Esys_Free(creationHash2);
+    Esys_Free(creationTicket2);
     return EXIT_SUCCESS;
 
  error:
@@ -441,7 +467,23 @@
     }
 #endif
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
 
+#ifdef TEST_ECC
+    Esys_Free(outPublicEcc);
+    Esys_Free(creationDataEcc);
+    Esys_Free(creationHashEcc);
+    Esys_Free(creationTicketEcc);
+#endif
+
+    Esys_Free(outPublic2);
+    Esys_Free(outPrivate2);
+    Esys_Free(creationData2);
+    Esys_Free(creationHash2);
+    Esys_Free(creationTicket2);
     return EXIT_FAILURE;
 }
 
diff --git a/test/integration/esys-createloaded.int.c b/test/integration/esys-createloaded.int.c
index 118f2a3..85b5940 100644
--- a/test/integration/esys-createloaded.int.c
+++ b/test/integration/esys-createloaded.int.c
@@ -44,8 +44,8 @@
     result = memcmp(read_name->name, get_name->name, get_name->size) == 0;
 
 out:
-    free(read_name);
-    free(get_name);
+    Esys_Free(read_name);
+    Esys_Free(get_name);
 
     return result;
 }
@@ -79,6 +79,13 @@
     ESYS_TR objectHandle = ESYS_TR_NONE;
     int failure_return = EXIT_FAILURE;
 
+    TPM2B_PUBLIC *outPublic = NULL;
+    TPM2B_CREATION_DATA *creationData = NULL;
+    TPM2B_DIGEST *creationHash = NULL;
+    TPMT_TK_CREATION *creationTicket = NULL;
+    TPM2B_PRIVATE *outPrivate2 = NULL;
+    TPM2B_PUBLIC *outPublic2 = NULL;
+
 #ifdef TEST_SESSION
     ESYS_TR session = ESYS_TR_NONE;
     TPMT_SYM_DEF symmetric = {.algorithm = TPM2_ALG_AES,
@@ -168,11 +175,6 @@
     r = Esys_TR_SetAuth(esys_context, ESYS_TR_RH_OWNER, &authValue);
     goto_if_error(r, "Error: TR_SetAuth", error);
 
-    TPM2B_PUBLIC *outPublic;
-    TPM2B_CREATION_DATA *creationData;
-    TPM2B_DIGEST *creationHash;
-    TPMT_TK_CREATION *creationTicket;
-
     r = Esys_CreatePrimary(esys_context, ESYS_TR_RH_OWNER, ESYS_TR_PASSWORD,
                            ESYS_TR_NONE, ESYS_TR_NONE, &inSensitivePrimary, &inPublic,
                            &outsideInfo, &creationPCR, &primaryHandle,
@@ -200,8 +202,6 @@
     };
 
     TPM2B_TEMPLATE inPublic_template = {0};
-    TPM2B_PRIVATE *outPrivate2;
-    TPM2B_PUBLIC *outPublic2;
     TPMT_PUBLIC  inPublic2 = {
         .type = TPM2_ALG_ECC,
         .nameAlg = TPM2_ALG_SHA256,
@@ -291,6 +291,12 @@
     goto_if_error(r, "Error: FlushContext", error);
 #endif
 
+    SAFE_FREE(outPublic);
+    SAFE_FREE(creationData);
+    SAFE_FREE(creationHash);
+    SAFE_FREE(creationTicket);
+    SAFE_FREE(outPrivate2);
+    SAFE_FREE(outPublic2);
     return EXIT_SUCCESS;
 
  error:
@@ -315,6 +321,12 @@
         }
     }
 
+    SAFE_FREE(outPublic);
+    SAFE_FREE(creationData);
+    SAFE_FREE(creationHash);
+    SAFE_FREE(creationTicket);
+    SAFE_FREE(outPrivate2);
+    SAFE_FREE(outPublic2);
     return failure_return;
 }
 
diff --git a/test/integration/esys-duplicate.int.c b/test/integration/esys-duplicate.int.c
index d531543..f99bf68 100644
--- a/test/integration/esys-duplicate.int.c
+++ b/test/integration/esys-duplicate.int.c
@@ -56,6 +56,29 @@
     ESYS_TR policySession = ESYS_TR_NONE;
     int failure_return = EXIT_FAILURE;
 
+    TPM2B_DIGEST *policyDigestTrial = NULL;
+    TPM2B_PUBLIC *outPublic = NULL;
+    TPM2B_CREATION_DATA *creationData = NULL;
+    TPM2B_DIGEST *creationHash = NULL;
+    TPMT_TK_CREATION *creationTicket = NULL;
+
+    TPM2B_PUBLIC *outPublic2 = NULL;
+    TPM2B_PRIVATE *outPrivate2 = NULL;
+    TPM2B_CREATION_DATA *creationData2 = NULL;
+    TPM2B_DIGEST *creationHash2 = NULL;
+    TPMT_TK_CREATION *creationTicket2 = NULL;
+
+    TPM2B_PUBLIC *keyPublic = NULL;
+    TPM2B_NAME *keyName = NULL;
+    TPM2B_NAME *keyQualifiedName = NULL;
+
+    TPM2B_DATA *encryptionKeyOut = NULL;
+    TPM2B_PRIVATE *duplicate = NULL;
+    TPM2B_ENCRYPTED_SECRET *outSymSeed = NULL;
+
+    TPM2B_PRIVATE *outDuplicate = NULL;
+    TPM2B_ENCRYPTED_SECRET *outSymSeed2 = NULL;
+
     /*
      * First the policy value to be able to use Esys_Duplicate for an object has to be
      * determined with a policy trial session.
@@ -95,7 +118,6 @@
                                );
     goto_if_error(r, "Error: PolicyCommandCode", error);
 
-    TPM2B_DIGEST *policyDigestTrial;
     r = Esys_PolicyGetDigest(esys_context,
                              sessionTrial,
                              ESYS_TR_NONE,
@@ -176,10 +198,6 @@
     goto_if_error(r, "Error: TR_SetAuth", error);
 
     RSRC_NODE_T *primaryHandle_node;
-    TPM2B_PUBLIC *outPublic;
-    TPM2B_CREATION_DATA *creationData;
-    TPM2B_DIGEST *creationHash;
-    TPMT_TK_CREATION *creationTicket;
 
     r = Esys_CreatePrimary(esys_context, ESYS_TR_RH_OWNER, ESYS_TR_PASSWORD,
                            ESYS_TR_NONE, ESYS_TR_NONE,
@@ -189,6 +207,11 @@
                            &creationTicket);
     goto_if_error(r, "Error esys create primary", error);
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+
     r = Esys_CreatePrimary(esys_context, ESYS_TR_RH_OWNER, ESYS_TR_PASSWORD,
                            ESYS_TR_NONE, ESYS_TR_NONE,
                            &inSensitivePrimary, &inPublic,
@@ -272,12 +295,6 @@
         .count = 0,
     };
 
-    TPM2B_PUBLIC *outPublic2;
-    TPM2B_PRIVATE *outPrivate2;
-    TPM2B_CREATION_DATA *creationData2;
-    TPM2B_DIGEST *creationHash2;
-    TPMT_TK_CREATION *creationTicket2;
-
     inPublic2.publicArea.authPolicy = *policyDigestTrial;
 
     r = Esys_Create(esys_context,
@@ -306,10 +323,6 @@
     r = Esys_TR_SetAuth(esys_context, loadedKeyHandle, &authKey2);
     goto_if_error(r, "Error esys TR_SetAuth ", error);
 
-    TPM2B_PUBLIC *keyPublic;
-    TPM2B_NAME *keyName;
-    TPM2B_NAME *keyQualifiedName;
-
     r = Esys_ReadPublic(esys_context,
                         loadedKeyHandle,
                         ESYS_TR_NONE,
@@ -366,10 +379,6 @@
                                      .keyBits = {.aes = 128},
                                      .mode = {.aes = TPM2_ALG_CFB}};
 
-    TPM2B_DATA *encryptionKeyOut;
-    TPM2B_PRIVATE *duplicate;
-    TPM2B_ENCRYPTED_SECRET *outSymSeed;
-
     r = Esys_Duplicate(
         esys_context,
         loadedKeyHandle,
@@ -385,9 +394,6 @@
 
     goto_if_error(r, "Error: Duplicate", error);
 
-    TPM2B_PRIVATE *outDuplicate;
-    TPM2B_ENCRYPTED_SECRET *outSymSeed2;
-
     r = Esys_Rewrap(esys_context,
                     primaryHandle2,
                     primaryHandle,
@@ -429,7 +435,24 @@
     r = Esys_FlushContext(esys_context, policySession);
     goto_if_error(r, "Flushing context", error);
 
-
+    Esys_Free(policyDigestTrial);
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+    Esys_Free(outPublic2);
+    Esys_Free(outPrivate2);
+    Esys_Free(creationData2);
+    Esys_Free(creationHash2);
+    Esys_Free(creationTicket2);
+    Esys_Free(keyPublic);
+    Esys_Free(keyName);
+    Esys_Free(keyQualifiedName);
+    Esys_Free(encryptionKeyOut);
+    Esys_Free(duplicate);
+    Esys_Free(outSymSeed);
+    Esys_Free(outDuplicate);
+    Esys_Free(outSymSeed2);
     return EXIT_SUCCESS;
 
  error:
@@ -464,6 +487,24 @@
         }
     }
 
+    Esys_Free(policyDigestTrial);
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+    Esys_Free(outPublic2);
+    Esys_Free(outPrivate2);
+    Esys_Free(creationData2);
+    Esys_Free(creationHash2);
+    Esys_Free(creationTicket2);
+    Esys_Free(keyPublic);
+    Esys_Free(keyName);
+    Esys_Free(keyQualifiedName);
+    Esys_Free(encryptionKeyOut);
+    Esys_Free(duplicate);
+    Esys_Free(outSymSeed);
+    Esys_Free(outDuplicate);
+    Esys_Free(outSymSeed2);
     return failure_return;
 }
 
diff --git a/test/integration/esys-ecdh-keygen.int.c b/test/integration/esys-ecdh-keygen.int.c
index 181bf50..db97226 100644
--- a/test/integration/esys-ecdh-keygen.int.c
+++ b/test/integration/esys-ecdh-keygen.int.c
@@ -47,6 +47,14 @@
         .buffer = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}
     };
 
+    TPM2B_PUBLIC *outPublic = NULL;
+    TPM2B_CREATION_DATA *creationData = NULL;
+    TPM2B_DIGEST *creationHash = NULL;
+    TPMT_TK_CREATION *creationTicket = NULL;
+
+    TPM2B_ECC_POINT *zPoint = NULL;
+    TPM2B_ECC_POINT *pubPoint = NULL;
+
     memset(&sessionAttributes, 0, sizeof sessionAttributes);
 
     r = Esys_StartAuthSession(esys_context, ESYS_TR_NONE, ESYS_TR_NONE,
@@ -124,11 +132,6 @@
     r = Esys_TR_SetAuth(esys_context, ESYS_TR_RH_OWNER, &authValue);
     goto_if_error(r, "Error: TR_SetAuth", error);
 
-    TPM2B_PUBLIC *outPublic;
-    TPM2B_CREATION_DATA *creationData;
-    TPM2B_DIGEST *creationHash;
-    TPMT_TK_CREATION *creationTicket;
-
     r = Esys_CreatePrimary(esys_context, ESYS_TR_RH_OWNER, session,
                            ESYS_TR_NONE, ESYS_TR_NONE, &inSensitive, &inPublic,
                            &outsideInfo, &creationPCR, &eccHandle,
@@ -136,9 +139,6 @@
                            &creationTicket);
     goto_if_error(r, "Error esapi create primary", error);
 
-    TPM2B_ECC_POINT *zPoint;
-    TPM2B_ECC_POINT *pubPoint;
-
     r = Esys_ECDH_KeyGen(
         esys_context,
         eccHandle,
@@ -155,6 +155,13 @@
     r = Esys_FlushContext(esys_context, session);
     goto_if_error(r, "Flushing context", error);
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+
+    Esys_Free(zPoint);
+    Esys_Free(pubPoint);
     return EXIT_SUCCESS;
 
  error:
@@ -171,6 +178,13 @@
             LOG_ERROR("Cleanup eccHandle failed.");
         }
     }
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+
+    Esys_Free(zPoint);
+    Esys_Free(pubPoint);
     return EXIT_FAILURE;
 }
 
diff --git a/test/integration/esys-ecdh-zgen.int.c b/test/integration/esys-ecdh-zgen.int.c
index 5288e0b..2f3725b 100644
--- a/test/integration/esys-ecdh-zgen.int.c
+++ b/test/integration/esys-ecdh-zgen.int.c
@@ -49,6 +49,12 @@
         .buffer = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}
     };
 
+    TPM2B_PUBLIC *outPublic = NULL;
+    TPM2B_CREATION_DATA *creationData = NULL;
+    TPM2B_DIGEST *creationHash = NULL;
+    TPMT_TK_CREATION *creationTicket = NULL;
+    TPM2B_ECC_POINT *outPoint = NULL;
+
     memset(&sessionAttributes, 0, sizeof sessionAttributes);
 
     r = Esys_StartAuthSession(esys_context, ESYS_TR_NONE, ESYS_TR_NONE,
@@ -126,11 +132,6 @@
     r = Esys_TR_SetAuth(esys_context, ESYS_TR_RH_OWNER, &authValue);
     goto_if_error(r, "Error: TR_SetAuth", error);
 
-    TPM2B_PUBLIC *outPublic;
-    TPM2B_CREATION_DATA *creationData;
-    TPM2B_DIGEST *creationHash;
-    TPMT_TK_CREATION *creationTicket;
-
     r = Esys_CreatePrimary(esys_context, ESYS_TR_RH_OWNER, session,
                            ESYS_TR_NONE, ESYS_TR_NONE, &inSensitive, &inPublic,
                            &outsideInfo, &creationPCR, &eccHandle,
@@ -162,7 +163,6 @@
         }
     };
 
-    TPM2B_ECC_POINT *outPoint;
     r = Esys_ECDH_ZGen(
         esys_context,
         eccHandle,
@@ -179,6 +179,11 @@
     r = Esys_FlushContext(esys_context, session);
     goto_if_error(r, "Flushing context", error);
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+    Esys_Free(outPoint);
     return EXIT_SUCCESS;
 
  error:
@@ -196,6 +201,11 @@
         }
     }
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+    Esys_Free(outPoint);
     return EXIT_FAILURE;
 }
 
diff --git a/test/integration/esys-encrypt-decrypt.int.c b/test/integration/esys-encrypt-decrypt.int.c
index 5c231ce..3204a54 100644
--- a/test/integration/esys-encrypt-decrypt.int.c
+++ b/test/integration/esys-encrypt-decrypt.int.c
@@ -45,6 +45,20 @@
     ESYS_TR loadedKeyHandle = ESYS_TR_NONE;
     int failure_return = EXIT_FAILURE;
 
+    TPM2B_PUBLIC *outPublic = NULL;
+    TPM2B_CREATION_DATA *creationData = NULL;
+    TPM2B_DIGEST *creationHash = NULL;
+    TPMT_TK_CREATION *creationTicket = NULL;
+    TPM2B_MAX_BUFFER *outData = NULL;
+    TPM2B_IV *ivOut = NULL;
+
+    TPM2B_PUBLIC *outPublic2 = NULL;
+    TPM2B_PRIVATE *outPrivate2 = NULL;
+    TPM2B_CREATION_DATA *creationData2 = NULL;
+    TPM2B_DIGEST *creationHash2 = NULL;
+    TPMT_TK_CREATION *creationTicket2 = NULL;
+    TPM2B_MAX_BUFFER *outData2 = NULL;
+    TPM2B_IV *ivOut2 = NULL;
 
     TPM2B_AUTH authValuePrimary = {
         .size = 5,
@@ -116,11 +130,6 @@
     r = Esys_TR_SetAuth(esys_context, ESYS_TR_RH_OWNER, &authValue);
     goto_if_error(r, "Error: TR_SetAuth", error);
 
-    TPM2B_PUBLIC *outPublic;
-    TPM2B_CREATION_DATA *creationData;
-    TPM2B_DIGEST *creationHash;
-    TPMT_TK_CREATION *creationTicket;
-
     r = Esys_CreatePrimary(esys_context, ESYS_TR_RH_OWNER, ESYS_TR_PASSWORD,
                            ESYS_TR_NONE, ESYS_TR_NONE,
                            &inSensitivePrimary, &inPublic,
@@ -188,12 +197,6 @@
         .count = 0,
     };
 
-    TPM2B_PUBLIC *outPublic2;
-    TPM2B_PRIVATE *outPrivate2;
-    TPM2B_CREATION_DATA *creationData2;
-    TPM2B_DIGEST *creationHash2;
-    TPMT_TK_CREATION *creationTicket2;
-
     r = Esys_Create(esys_context,
                     primaryHandle,
                     ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
@@ -232,8 +235,6 @@
         .size = 16,
         .buffer = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 16}
     };
-    TPM2B_MAX_BUFFER *outData;
-    TPM2B_IV *ivOut;
 
     r = Esys_EncryptDecrypt(
         esys_context,
@@ -258,8 +259,6 @@
 
     goto_if_error(r, "Error: EncryptDecrypt", error);
 
-    TPM2B_MAX_BUFFER *outData2;
-    TPM2B_IV *ivOut2;
 
     r = Esys_EncryptDecrypt(
         esys_context,
@@ -300,6 +299,20 @@
     r = Esys_FlushContext(esys_context, loadedKeyHandle);
     goto_if_error(r, "Error during FlushContext", error);
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+    Esys_Free(outData);
+    Esys_Free(ivOut);
+
+    Esys_Free(outPublic2);
+    Esys_Free(outPrivate2);
+    Esys_Free(creationData2);
+    Esys_Free(creationHash2);
+    Esys_Free(creationTicket2);
+    Esys_Free(outData2);
+    Esys_Free(ivOut2);
     return EXIT_SUCCESS;
 
  error:
@@ -315,6 +328,20 @@
             LOG_ERROR("Cleanup loadedKeyHandle failed.");
         }
     }
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+    Esys_Free(outData);
+    Esys_Free(ivOut);
+
+    Esys_Free(outPublic2);
+    Esys_Free(outPrivate2);
+    Esys_Free(creationData2);
+    Esys_Free(creationHash2);
+    Esys_Free(creationTicket2);
+    Esys_Free(outData2);
+    Esys_Free(ivOut2);
     return failure_return;
 }
 
diff --git a/test/integration/esys-event-sequence-complete.int.c b/test/integration/esys-event-sequence-complete.int.c
index 557e07b..f5b6aea 100644
--- a/test/integration/esys-event-sequence-complete.int.c
+++ b/test/integration/esys-event-sequence-complete.int.c
@@ -41,6 +41,7 @@
 
     TPMI_ALG_HASH hashAlg = TPM2_ALG_NULL;   /**< enforce event Sequence */
     ESYS_TR sequenceHandle_handle;
+    TPML_DIGEST_VALUES *results = NULL;
 
     r = Esys_HashSequenceStart(esys_context,
                                ESYS_TR_NONE,
@@ -70,7 +71,6 @@
 
     ESYS_TR pcrHandle_handle = 16;
 
-    TPML_DIGEST_VALUES *results;
     r = Esys_EventSequenceComplete (
         esys_context,
         pcrHandle_handle,
@@ -82,9 +82,11 @@
         &results);
     goto_if_error(r, "Error: EventSequenceComplete", error);
 
+    Esys_Free(results);
     return EXIT_SUCCESS;
 
  error:
+    Esys_Free(results);
     return EXIT_FAILURE;
 }
 
diff --git a/test/integration/esys-evict-control-serialization.int.c b/test/integration/esys-evict-control-serialization.int.c
index e90cb72..aefe2dc 100644
--- a/test/integration/esys-evict-control-serialization.int.c
+++ b/test/integration/esys-evict-control-serialization.int.c
@@ -44,6 +44,16 @@
     ESYS_TR primaryHandle = ESYS_TR_NONE;
     ESYS_TR persistent_handle1 = ESYS_TR_NONE;
 
+    TPM2B_PUBLIC *outPublic = NULL;
+    TPM2B_CREATION_DATA *creationData = NULL;
+    TPM2B_DIGEST *creationHash = NULL;
+    TPMT_TK_CREATION *creationTicket = NULL;
+    TPM2B_PUBLIC *outPublic2 = NULL;
+    TPM2B_PRIVATE *outPrivate2 = NULL;
+    TPM2B_CREATION_DATA *creationData2 = NULL;
+    TPM2B_DIGEST *creationHash2 = NULL;
+    TPMT_TK_CREATION *creationTicket2 = NULL;
+
     TPM2B_AUTH authValuePrimary = {
         .size = 5,
         .buffer = {1, 2, 3, 4, 5}
@@ -116,10 +126,6 @@
     goto_if_error(r, "Error: TR_SetAuth", error);
 
     RSRC_NODE_T *primaryHandle_node;
-    TPM2B_PUBLIC *outPublic;
-    TPM2B_CREATION_DATA *creationData;
-    TPM2B_DIGEST *creationHash;
-    TPMT_TK_CREATION *creationTicket;
 
     r = Esys_CreatePrimary(esys_context, ESYS_TR_RH_OWNER, ESYS_TR_PASSWORD,
                            ESYS_TR_NONE, ESYS_TR_NONE, &inSensitivePrimary, &inPublic,
@@ -224,12 +230,6 @@
         .count = 0,
     };
 
-    TPM2B_PUBLIC *outPublic2;
-    TPM2B_PRIVATE *outPrivate2;
-    TPM2B_CREATION_DATA *creationData2;
-    TPM2B_DIGEST *creationHash2;
-    TPMT_TK_CREATION *creationTicket2;
-
     r = Esys_TR_SetAuth(esys_context, persistent_handle2, &authValuePrimary);
     goto_if_error(r, "Error: TR_SetAuth", error);
 
@@ -254,6 +254,15 @@
                           permanentHandle, &persistent_handle1);
     goto_if_error(r, "Error Esys EvictControl", error);
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+    Esys_Free(outPublic2);
+    Esys_Free(outPrivate2);
+    Esys_Free(creationData2);
+    Esys_Free(creationHash2);
+    Esys_Free(creationTicket2);
     return EXIT_SUCCESS;
 
  error:
@@ -273,6 +282,15 @@
         }
     }
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+    Esys_Free(outPublic2);
+    Esys_Free(outPrivate2);
+    Esys_Free(creationData2);
+    Esys_Free(creationHash2);
+    Esys_Free(creationTicket2);
     return EXIT_FAILURE;
 }
 
diff --git a/test/integration/esys-get-random.int.c b/test/integration/esys-get-random.int.c
index 273189b..ecdfab5 100644
--- a/test/integration/esys-get-random.int.c
+++ b/test/integration/esys-get-random.int.c
@@ -43,7 +43,7 @@
 
     LOGBLOB_DEBUG(&randomBytes->buffer[0], randomBytes->size,
                   "Randoms (count=%i):", randomBytes->size);
-    free(randomBytes);
+    Esys_Free(randomBytes);
 
     LOG_INFO("GetRandom Test Passed!");
 
@@ -65,7 +65,119 @@
     }
 
     r = Esys_TRSess_SetAttributes(esys_context, session, TPMA_SESSION_AUDIT,
-                                  TPMA_SESSION_AUDIT);
+                                  TPMA_SESSION_CONTINUESESSION | TPMA_SESSION_AUDIT);
+    if (r != TPM2_RC_SUCCESS) {
+        LOG_ERROR("SetAttributes on session FAILED! Response Code : 0x%x", r);
+        goto error_cleansession;
+    }
+
+    r = Esys_GetRandom(esys_context, session, ESYS_TR_NONE, ESYS_TR_NONE, 48,
+                       &randomBytes);
+    if (r != TPM2_RC_SUCCESS) {
+        LOG_ERROR("GetRandom with session FAILED! Response Code : 0x%x", r);
+        goto error_cleansession;
+    }
+
+    LOGBLOB_DEBUG(&randomBytes->buffer[0], randomBytes->size,
+                  "Randoms (count=%i):", randomBytes->size);
+    free(randomBytes);
+
+      r = Esys_StartAuthSession(esys_context, ESYS_TR_NONE, ESYS_TR_NONE,
+                              ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
+                              NULL,
+                              TPM2_SE_HMAC, &symmetric, TPM2_ALG_SHA1,
+                              &session);
+    if (r != TPM2_RC_SUCCESS) {
+        LOG_ERROR("Esys_StartAuthSession FAILED! Response Code : 0x%x", r);
+        goto error;
+    }
+
+    r = Esys_TRSess_SetAttributes(esys_context, session, TPMA_SESSION_AUDIT,
+                                  TPMA_SESSION_CONTINUESESSION | TPMA_SESSION_AUDIT);
+    if (r != TPM2_RC_SUCCESS) {
+        LOG_ERROR("SetAttributes on session FAILED! Response Code : 0x%x", r);
+        goto error_cleansession;
+    }
+
+    r = Esys_GetRandom(esys_context, session, ESYS_TR_NONE, ESYS_TR_NONE, 48,
+                       &randomBytes);
+    if (r != TPM2_RC_SUCCESS) {
+        LOG_ERROR("GetRandom with session FAILED! Response Code : 0x%x", r);
+        goto error_cleansession;
+    }
+
+    LOGBLOB_DEBUG(&randomBytes->buffer[0], randomBytes->size,
+                  "Randoms (count=%i):", randomBytes->size);
+    free(randomBytes);
+
+      r = Esys_StartAuthSession(esys_context, ESYS_TR_NONE, ESYS_TR_NONE,
+                              ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
+                              NULL,
+                              TPM2_SE_HMAC, &symmetric, TPM2_ALG_SHA1,
+                              &session);
+    if (r != TPM2_RC_SUCCESS) {
+        LOG_ERROR("Esys_StartAuthSession FAILED! Response Code : 0x%x", r);
+        goto error;
+    }
+
+    r = Esys_TRSess_SetAttributes(esys_context, session, TPMA_SESSION_AUDIT,
+                                  TPMA_SESSION_CONTINUESESSION | TPMA_SESSION_AUDIT);
+    if (r != TPM2_RC_SUCCESS) {
+        LOG_ERROR("SetAttributes on session FAILED! Response Code : 0x%x", r);
+        goto error_cleansession;
+    }
+
+    r = Esys_GetRandom(esys_context, session, ESYS_TR_NONE, ESYS_TR_NONE, 48,
+                       &randomBytes);
+    if (r != TPM2_RC_SUCCESS) {
+        LOG_ERROR("GetRandom with session FAILED! Response Code : 0x%x", r);
+        goto error_cleansession;
+    }
+
+    LOGBLOB_DEBUG(&randomBytes->buffer[0], randomBytes->size,
+                  "Randoms (count=%i):", randomBytes->size);
+    free(randomBytes);
+
+      r = Esys_StartAuthSession(esys_context, ESYS_TR_NONE, ESYS_TR_NONE,
+                              ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
+                              NULL,
+                              TPM2_SE_HMAC, &symmetric, TPM2_ALG_SHA1,
+                              &session);
+    if (r != TPM2_RC_SUCCESS) {
+        LOG_ERROR("Esys_StartAuthSession FAILED! Response Code : 0x%x", r);
+        goto error;
+    }
+
+    r = Esys_TRSess_SetAttributes(esys_context, session, TPMA_SESSION_AUDIT,
+                                  TPMA_SESSION_CONTINUESESSION | TPMA_SESSION_AUDIT);
+    if (r != TPM2_RC_SUCCESS) {
+        LOG_ERROR("SetAttributes on session FAILED! Response Code : 0x%x", r);
+        goto error_cleansession;
+    }
+
+    r = Esys_GetRandom(esys_context, session, ESYS_TR_NONE, ESYS_TR_NONE, 48,
+                       &randomBytes);
+    if (r != TPM2_RC_SUCCESS) {
+        LOG_ERROR("GetRandom with session FAILED! Response Code : 0x%x", r);
+        goto error_cleansession;
+    }
+
+    LOGBLOB_DEBUG(&randomBytes->buffer[0], randomBytes->size,
+                  "Randoms (count=%i):", randomBytes->size);
+    free(randomBytes);
+
+      r = Esys_StartAuthSession(esys_context, ESYS_TR_NONE, ESYS_TR_NONE,
+                              ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
+                              NULL,
+                              TPM2_SE_HMAC, &symmetric, TPM2_ALG_SHA1,
+                              &session);
+    if (r != TPM2_RC_SUCCESS) {
+        LOG_ERROR("Esys_StartAuthSession FAILED! Response Code : 0x%x", r);
+        goto error;
+    }
+
+    r = Esys_TRSess_SetAttributes(esys_context, session, TPMA_SESSION_AUDIT,
+                                  TPMA_SESSION_CONTINUESESSION | TPMA_SESSION_AUDIT);
     if (r != TPM2_RC_SUCCESS) {
         LOG_ERROR("SetAttributes on session FAILED! Response Code : 0x%x", r);
         goto error_cleansession;
@@ -84,7 +196,7 @@
 
     LOG_INFO("GetRandom with session Test Passed!");
 
-    r = Esys_FlushContext(esys_context, session);
+    //r = Esys_FlushContext(esys_context, session);
     if (r != TPM2_RC_SUCCESS) {
         LOG_ERROR("FlushContext with session FAILED! Response Code : 0x%x", r);
         goto error_cleansession;
diff --git a/test/integration/esys-get-time.int.c b/test/integration/esys-get-time.int.c
index 8422f8d..76a3e21 100644
--- a/test/integration/esys-get-time.int.c
+++ b/test/integration/esys-get-time.int.c
@@ -42,6 +42,13 @@
     ESYS_TR signHandle = ESYS_TR_NONE;
     int failure_return = EXIT_FAILURE;
 
+    TPM2B_PUBLIC *outPublic = NULL;
+    TPM2B_CREATION_DATA *creationData = NULL;
+    TPM2B_DIGEST *creationHash = NULL;
+    TPMT_TK_CREATION *creationTicket = NULL;
+    TPM2B_ATTEST *timeInfo = NULL;
+    TPMT_SIGNATURE *signature = NULL;
+
     TPM2B_AUTH authValuePrimary = {
         .size = 5,
         .buffer = {1, 2, 3, 4, 5}
@@ -122,10 +129,6 @@
     goto_if_error(r, "Error: TR_SetAuth", error);
 
     RSRC_NODE_T *primaryHandle_node;
-    TPM2B_PUBLIC *outPublic;
-    TPM2B_CREATION_DATA *creationData;
-    TPM2B_DIGEST *creationHash;
-    TPMT_TK_CREATION *creationTicket;
 
     r = Esys_CreatePrimary(esys_context, ESYS_TR_RH_OWNER, ESYS_TR_PASSWORD,
                            ESYS_TR_NONE, ESYS_TR_NONE, &inSensitivePrimary,
@@ -148,8 +151,6 @@
     ESYS_TR privacyAdminHandle= ESYS_TR_RH_ENDORSEMENT;
     TPMT_SIG_SCHEME inScheme = { .scheme = TPM2_ALG_NULL };
     TPM2B_DATA qualifyingData = {0};
-    TPM2B_ATTEST *timeInfo;
-    TPMT_SIGNATURE *signature;
 
     r = Esys_GetTime (
          esys_context,
@@ -178,6 +179,12 @@
     r = Esys_FlushContext(esys_context, signHandle);
     goto_if_error(r, "Error: FlushContext", error);
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+    Esys_Free(timeInfo);
+    Esys_Free(signature);
     return EXIT_SUCCESS;
 
  error:
@@ -187,6 +194,12 @@
             LOG_ERROR("Cleanup signHandle failed.");
         }
     }
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+    Esys_Free(timeInfo);
+    Esys_Free(signature);
     return failure_return;
 }
 
diff --git a/test/integration/esys-hash.int.c b/test/integration/esys-hash.int.c
index 3d9af8f..3c93c0d 100644
--- a/test/integration/esys-hash.int.c
+++ b/test/integration/esys-hash.int.c
@@ -38,8 +38,8 @@
                                        1, 2, 3, 4, 5, 6, 7, 8, 9}};
     TPMI_ALG_HASH hashAlg = TPM2_ALG_SHA1;
     TPMI_RH_HIERARCHY hierarchy = TPM2_RH_OWNER;
-    TPM2B_DIGEST *outHash;
-    TPMT_TK_HASHCHECK *validation;
+    TPM2B_DIGEST *outHash = NULL;
+    TPMT_TK_HASHCHECK *validation = NULL;
 
     r = Esys_Hash(
         esys_context,
@@ -53,9 +53,13 @@
         &validation);
     goto_if_error(r, "Error: Hash", error);
 
+    Esys_Free(outHash);
+    Esys_Free(validation);
     return EXIT_SUCCESS;
 
  error:
+    Esys_Free(outHash);
+    Esys_Free(validation);
     return EXIT_FAILURE;
 }
 
diff --git a/test/integration/esys-hashsequencestart.int.c b/test/integration/esys-hashsequencestart.int.c
index cd5bcb4..7ee827e 100644
--- a/test/integration/esys-hashsequencestart.int.c
+++ b/test/integration/esys-hashsequencestart.int.c
@@ -39,6 +39,9 @@
 {
     TSS2_RC r;
 
+    TPM2B_DIGEST *result = NULL;
+    TPMT_TK_HASHCHECK *validation = NULL;
+
 #ifdef TEST_SESSION
     ESYS_TR session = ESYS_TR_NONE;
     TPMT_SYM_DEF symmetric = {.algorithm = TPM2_ALG_AES,
@@ -99,9 +102,6 @@
                             );
     goto_if_error(r, "Error: SequenceUpdate", error);
 
-    TPM2B_DIGEST *result;
-    TPMT_TK_HASHCHECK *validation;
-
     r = Esys_SequenceComplete(esys_context,
                               sequenceHandle_handle,
 #ifdef TEST_SESSION
@@ -123,6 +123,8 @@
     goto_if_error(r, "Error: FlushContext", error);
 #endif
 
+    Esys_Free(result);
+    Esys_Free(validation);
     return EXIT_SUCCESS;
 
  error:
@@ -134,6 +136,8 @@
         }
     }
 #endif
+    Esys_Free(result);
+    Esys_Free(validation);
     return EXIT_FAILURE;
 }
 
diff --git a/test/integration/esys-hierarchy-control.int.c b/test/integration/esys-hierarchy-control.int.c
index 0beb74b..8180ef5 100644
--- a/test/integration/esys-hierarchy-control.int.c
+++ b/test/integration/esys-hierarchy-control.int.c
@@ -46,6 +46,11 @@
     ESYS_TR primaryHandle = ESYS_TR_NONE;
     int failure_return = EXIT_FAILURE;
 
+    TPM2B_PUBLIC *outPublic = NULL;
+    TPM2B_CREATION_DATA *creationData = NULL;
+    TPM2B_DIGEST *creationHash = NULL;
+    TPMT_TK_CREATION *creationTicket = NULL;
+
     r = Esys_HierarchyControl(
         esys_context,
         authHandle_handle,
@@ -121,11 +126,6 @@
 
     goto_if_error(r, "Error: TR_SetAuth", error);
 
-    TPM2B_PUBLIC *outPublic;
-    TPM2B_CREATION_DATA *creationData;
-    TPM2B_DIGEST *creationHash;
-    TPMT_TK_CREATION *creationTicket;
-
     r = Esys_CreatePrimary(esys_context, ESYS_TR_RH_OWNER, ESYS_TR_PASSWORD,
                            ESYS_TR_NONE, ESYS_TR_NONE, &inSensitivePrimary, &inPublic,
                            &outsideInfo, &creationPCR, &primaryHandle,
@@ -156,6 +156,10 @@
     r = Esys_FlushContext(esys_context, primaryHandle);
     goto_if_error(r, "Error: FlushContext", error);
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
     return EXIT_SUCCESS;
 
  error:
@@ -166,6 +170,10 @@
         }
     }
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
     return failure_return;
 }
 
diff --git a/test/integration/esys-hierarchychangeauth.int.c b/test/integration/esys-hierarchychangeauth.int.c
index 7465961..c554587 100644
--- a/test/integration/esys-hierarchychangeauth.int.c
+++ b/test/integration/esys-hierarchychangeauth.int.c
@@ -42,6 +42,12 @@
     ESYS_TR primaryHandle = ESYS_TR_NONE;
     bool auth_changed = false;
     ESYS_TR authHandle_handle = ESYS_TR_RH_OWNER;
+
+    TPM2B_PUBLIC *outPublic = NULL;
+    TPM2B_CREATION_DATA *creationData = NULL;
+    TPM2B_DIGEST *creationHash = NULL;
+    TPMT_TK_CREATION *creationTicket = NULL;
+
     TPM2B_AUTH newAuth = {
         .size = 5,
         .buffer = {1, 2, 3, 4, 5}
@@ -120,11 +126,6 @@
 
     goto_if_error(r, "Error: TR_SetAuth", error);
 
-    TPM2B_PUBLIC *outPublic;
-    TPM2B_CREATION_DATA *creationData;
-    TPM2B_DIGEST *creationHash;
-    TPMT_TK_CREATION *creationTicket;
-
     r = Esys_CreatePrimary(esys_context, ESYS_TR_RH_OWNER, ESYS_TR_PASSWORD,
                            ESYS_TR_NONE, ESYS_TR_NONE, &inSensitivePrimary, &inPublic,
                            &outsideInfo, &creationPCR, &primaryHandle,
@@ -140,6 +141,11 @@
     r = Esys_TR_SetAuth(esys_context, ESYS_TR_RH_OWNER, &newAuth);
     goto_if_error(r, "Error SetAuth", error);
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+
     /* Check whether HierarchyChangeAuth with auth equal NULL works */
 
     r = Esys_CreatePrimary(esys_context, ESYS_TR_RH_OWNER, ESYS_TR_PASSWORD,
@@ -160,6 +166,10 @@
                                  NULL);
     goto_if_error(r, "Error: HierarchyChangeAuth", error);
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
     return EXIT_SUCCESS;
 
 error:
@@ -184,6 +194,10 @@
         }
     }
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
     return EXIT_FAILURE;
 }
 
diff --git a/test/integration/esys-hmac.int.c b/test/integration/esys-hmac.int.c
index 80e2c05..cbfbd70 100644
--- a/test/integration/esys-hmac.int.c
+++ b/test/integration/esys-hmac.int.c
@@ -40,6 +40,12 @@
     TSS2_RC r;
     ESYS_TR primaryHandle = ESYS_TR_NONE;
 
+    TPM2B_PUBLIC *outPublic = NULL;
+    TPM2B_CREATION_DATA *creationData = NULL;
+    TPM2B_DIGEST *creationHash = NULL;
+    TPMT_TK_CREATION *creationTicket = NULL;
+    TPM2B_DIGEST *outHMAC = NULL;
+
     TPM2B_AUTH authValuePrimary = {
         .size = 5,
         .buffer = {1, 2, 3, 4, 5}
@@ -69,11 +75,6 @@
         .count = 0,
     };
 
-    TPM2B_PUBLIC *outPublic;
-    TPM2B_CREATION_DATA *creationData;
-    TPM2B_DIGEST *creationHash;
-    TPMT_TK_CREATION *creationTicket;
-
     inPublic.publicArea.nameAlg = TPM2_ALG_SHA1;
     inPublic.publicArea.type = TPM2_ALG_KEYEDHASH;
     inPublic.publicArea.objectAttributes |= TPMA_OBJECT_SIGN_ENCRYPT;
@@ -95,8 +96,6 @@
     TPM2B_MAX_BUFFER test_buffer = { .size = 20,
                                      .buffer={0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
                                               1, 2, 3, 4, 5, 6, 7, 8, 9}} ;
-    TPM2B_DIGEST *outHMAC;
-
     r = Esys_HMAC(
         esys_context,
         primaryHandle,
@@ -111,6 +110,11 @@
     r = Esys_FlushContext(esys_context, primaryHandle);
     goto_if_error(r, "Error: FlushContext", error);
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+    Esys_Free(outHMAC);
     return EXIT_SUCCESS;
 
  error:
@@ -121,6 +125,11 @@
         }
     }
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+    Esys_Free(outHMAC);
     return EXIT_FAILURE;
 }
 
diff --git a/test/integration/esys-hmacsequencestart.int.c b/test/integration/esys-hmacsequencestart.int.c
index f6aa121..9d7dcdd 100644
--- a/test/integration/esys-hmacsequencestart.int.c
+++ b/test/integration/esys-hmacsequencestart.int.c
@@ -42,6 +42,14 @@
     TSS2_RC r;
     ESYS_TR primaryHandle = ESYS_TR_NONE;
 
+    TPM2B_PUBLIC *outPublic = NULL;
+    TPM2B_CREATION_DATA *creationData = NULL;
+    TPM2B_DIGEST *creationHash = NULL;
+    TPMT_TK_CREATION *creationTicket = NULL;
+
+    TPM2B_DIGEST *result = NULL;
+    TPMT_TK_HASHCHECK *validation = NULL;
+
 #ifdef TEST_SESSION
     ESYS_TR session = ESYS_TR_NONE;
     TPMT_SYM_DEF symmetric = {.algorithm = TPM2_ALG_AES,
@@ -95,11 +103,6 @@
         .count = 0,
     };
 
-    TPM2B_PUBLIC *outPublic;
-    TPM2B_CREATION_DATA *creationData;
-    TPM2B_DIGEST *creationHash;
-    TPMT_TK_CREATION *creationTicket;
-
     inPublic.publicArea.nameAlg = TPM2_ALG_SHA1;
     inPublic.publicArea.type = TPM2_ALG_KEYEDHASH;
     inPublic.publicArea.objectAttributes |= TPMA_OBJECT_SIGN_ENCRYPT;
@@ -159,9 +162,6 @@
                             );
     goto_if_error(r, "Error: SequenceUpdate", error);
 
-    TPM2B_DIGEST *result;
-    TPMT_TK_HASHCHECK *validation;
-
     r = Esys_SequenceComplete(esys_context,
                               sequenceHandle,
 #ifdef TEST_SESSION
@@ -183,6 +183,9 @@
     goto_if_error(r, "Error: FlushContext", error);
 #endif
 
+    Esys_Free(result);
+    Esys_Free(validation);
+
     /* Check HMAC_Start with auth equal NULL */
 
 #ifdef TEST_SESSION
@@ -247,6 +250,12 @@
     goto_if_error(r, "Error: FlushContext", error);
 #endif
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+    Esys_Free(result);
+    Esys_Free(validation);
     return EXIT_SUCCESS;
 
  error:
@@ -265,6 +274,12 @@
     }
 #endif
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+    Esys_Free(result);
+    Esys_Free(validation);
     return EXIT_FAILURE;
 }
 
diff --git a/test/integration/esys-import.int.c b/test/integration/esys-import.int.c
index beeb40d..babdd94 100644
--- a/test/integration/esys-import.int.c
+++ b/test/integration/esys-import.int.c
@@ -53,6 +53,29 @@
     ESYS_TR loadedKeyHandle = ESYS_TR_NONE;
     ESYS_TR policySession = ESYS_TR_NONE;
 
+    TPM2B_DIGEST *policyDigestTrial = NULL;
+    TPM2B_PUBLIC *outPublic = NULL;
+    TPM2B_CREATION_DATA *creationData = NULL;
+    TPM2B_DIGEST *creationHash = NULL;
+    TPMT_TK_CREATION *creationTicket = NULL;
+
+    TPM2B_PUBLIC *outPublic2 = NULL;
+    TPM2B_PRIVATE *outPrivate2 = NULL;
+    TPM2B_CREATION_DATA *creationData2 = NULL;
+    TPM2B_DIGEST *creationHash2 = NULL;
+    TPMT_TK_CREATION *creationTicket2 = NULL;
+
+    TPM2B_DATA *encryptionKeyOut = NULL;
+    TPM2B_PRIVATE *duplicate = NULL;
+    TPM2B_ENCRYPTED_SECRET *outSymSeed = NULL;
+
+    TPM2B_PUBLIC *keyPublic = NULL;
+    TPM2B_NAME *keyName = NULL;
+    TPM2B_NAME *keyQualifiedName = NULL;
+
+    TPM2B_NAME *nameKeySign = NULL;
+    TPM2B_PRIVATE *outPrivate = NULL;
+
     /*
      * Firth the policy value to be able to use Esys_Duplicate for an object has to be
      * determined with a policy trial session.
@@ -92,7 +115,6 @@
                                );
     goto_if_error(r, "Error: PolicyCommandCode", error);
 
-    TPM2B_DIGEST *policyDigestTrial;
     r = Esys_PolicyGetDigest(esys_context,
                              sessionTrial,
                              ESYS_TR_NONE,
@@ -173,10 +195,6 @@
     goto_if_error(r, "Error: TR_SetAuth", error);
 
     RSRC_NODE_T *primaryHandle_node;
-    TPM2B_PUBLIC *outPublic;
-    TPM2B_CREATION_DATA *creationData;
-    TPM2B_DIGEST *creationHash;
-    TPMT_TK_CREATION *creationTicket;
 
     r = Esys_CreatePrimary(esys_context, ESYS_TR_RH_OWNER, ESYS_TR_PASSWORD,
                            ESYS_TR_NONE, ESYS_TR_NONE,
@@ -186,6 +204,11 @@
                            &creationTicket);
     goto_if_error(r, "Error esys create primary", error);
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+
     r = Esys_CreatePrimary(esys_context, ESYS_TR_RH_OWNER, ESYS_TR_PASSWORD,
                            ESYS_TR_NONE, ESYS_TR_NONE,
                            &inSensitivePrimary, &inPublic,
@@ -269,12 +292,6 @@
         .count = 0,
     };
 
-    TPM2B_PUBLIC *outPublic2;
-    TPM2B_PRIVATE *outPrivate2;
-    TPM2B_CREATION_DATA *creationData2;
-    TPM2B_DIGEST *creationHash2;
-    TPMT_TK_CREATION *creationTicket2;
-
     inPublic2.publicArea.authPolicy = *policyDigestTrial;
 
     r = Esys_Create(esys_context,
@@ -303,10 +320,6 @@
     r = Esys_TR_SetAuth(esys_context, loadedKeyHandle, &authKey2);
     goto_if_error(r, "Error esys TR_SetAuth ", error);
 
-    TPM2B_PUBLIC *keyPublic;
-    TPM2B_NAME *keyName;
-    TPM2B_NAME *keyQualifiedName;
-
     r = Esys_ReadPublic(esys_context,
                         loadedKeyHandle,
                         ESYS_TR_NONE,
@@ -316,6 +329,10 @@
                         &keyName,
                         &keyQualifiedName);
 
+    Esys_Free(keyPublic);
+    Esys_Free(keyName);
+    Esys_Free(keyQualifiedName);
+
     goto_if_error(r, "Error esys ReadPublic", error);
 
     TPMT_SYM_DEF policySymmetric = {.algorithm = TPM2_ALG_AES,
@@ -359,10 +376,6 @@
                                      .keyBits = {.aes = 128},
                                      .mode = {.aes = TPM2_ALG_CFB}};
 
-    TPM2B_DATA *encryptionKeyOut;
-    TPM2B_PRIVATE *duplicate;
-    TPM2B_ENCRYPTED_SECRET *outSymSeed;
-
     r = Esys_Duplicate(
         esys_context,
         loadedKeyHandle,
@@ -377,9 +390,7 @@
         &outSymSeed);
 
     goto_if_error(r, "Error: Duplicate", error);
-
-    TPM2B_NAME *nameKeySign;
-    TPM2B_PRIVATE *outPrivate;
+    Esys_Free(outPublic);
 
     r = Esys_ReadPublic(esys_context,
                         loadedKeyHandle,
@@ -429,6 +440,26 @@
     r = Esys_FlushContext(esys_context, policySession);
     goto_if_error(r, "Flushing context", error);
 
+    Esys_Free(policyDigestTrial);
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+
+    Esys_Free(outPublic2);
+    Esys_Free(outPrivate2);
+    Esys_Free(creationData2);
+    Esys_Free(creationHash2);
+    Esys_Free(creationTicket2);
+
+    Esys_Free(encryptionKeyOut);
+    Esys_Free(duplicate);
+    Esys_Free(outSymSeed);
+
+    Esys_Free(keyQualifiedName);
+
+    Esys_Free(nameKeySign);
+    Esys_Free(outPrivate);
     return EXIT_SUCCESS;
 
  error:
@@ -462,6 +493,28 @@
         }
     }
 
+    Esys_Free(policyDigestTrial);
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+
+    Esys_Free(outPublic2);
+    Esys_Free(outPrivate2);
+    Esys_Free(creationData2);
+    Esys_Free(creationHash2);
+    Esys_Free(creationTicket2);
+
+    Esys_Free(encryptionKeyOut);
+    Esys_Free(duplicate);
+    Esys_Free(outSymSeed);
+
+    Esys_Free(keyPublic);
+    Esys_Free(keyName);
+    Esys_Free(keyQualifiedName);
+
+    Esys_Free(nameKeySign);
+    Esys_Free(outPrivate);
     return EXIT_FAILURE;
 }
 
diff --git a/test/integration/esys-make-credential.int.c b/test/integration/esys-make-credential.int.c
index 6deb9aa..abc95ca 100644
--- a/test/integration/esys-make-credential.int.c
+++ b/test/integration/esys-make-credential.int.c
@@ -51,6 +51,26 @@
     ESYS_TR primaryHandle = ESYS_TR_NONE;
     ESYS_TR loadedKeyHandle = ESYS_TR_NONE;
 
+    TPM2B_PUBLIC *outPublic = NULL;
+    TPM2B_CREATION_DATA *creationData = NULL;
+    TPM2B_DIGEST *creationHash = NULL;
+    TPMT_TK_CREATION *creationTicket = NULL;
+
+    TPM2B_PUBLIC *outPublic2 = NULL;
+    TPM2B_PRIVATE *outPrivate2 = NULL;
+    TPM2B_CREATION_DATA *creationData2 = NULL;
+    TPM2B_DIGEST *creationHash2 = NULL;
+    TPMT_TK_CREATION *creationTicket2 = NULL;
+
+    TPM2B_PUBLIC *primaryKeyPublic = NULL;
+    TPM2B_NAME *primaryKeyName = NULL;
+    TPM2B_NAME *primaryKeyQualifiedName = NULL;
+
+    TPM2B_ID_OBJECT *credentialBlob = NULL;
+    TPM2B_ENCRYPTED_SECRET *secret = NULL;
+
+    TPM2B_DIGEST *certInfo = NULL;
+
 #ifdef TEST_SESSION
     ESYS_TR session = ESYS_TR_NONE;
     ESYS_TR session2 = ESYS_TR_NONE;
@@ -173,10 +193,6 @@
     goto_if_error(r, "Error: TR_SetAuth", error);
 
     RSRC_NODE_T *primaryHandle_node;
-    TPM2B_PUBLIC *outPublic;
-    TPM2B_CREATION_DATA *creationData;
-    TPM2B_DIGEST *creationHash;
-    TPMT_TK_CREATION *creationTicket;
 
     r = Esys_CreatePrimary(esys_context, ESYS_TR_RH_OWNER, ESYS_TR_PASSWORD,
                            ESYS_TR_NONE, ESYS_TR_NONE, &inSensitivePrimary, &inPublic,
@@ -262,12 +278,6 @@
         .count = 0,
     };
 
-    TPM2B_PUBLIC *outPublic2;
-    TPM2B_PRIVATE *outPrivate2;
-    TPM2B_CREATION_DATA *creationData2;
-    TPM2B_DIGEST *creationHash2;
-    TPMT_TK_CREATION *creationTicket2;
-
     r = Esys_Create(esys_context,
                     primaryHandle,
                     ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
@@ -292,10 +302,6 @@
                           &loadedKeyHandle);
     goto_if_error(r, "Error esys load external", error);
 
-    TPM2B_PUBLIC *primaryKeyPublic;
-    TPM2B_NAME *primaryKeyName;
-    TPM2B_NAME *primaryKeyQualifiedName;
-
     r = Esys_ReadPublic(esys_context,
                         primaryHandle,
                         ESYS_TR_NONE,
@@ -312,9 +318,6 @@
         .buffer = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
                    11, 12, 13, 14, 15, 16, 17, 18, 19, 20}};
 
-    TPM2B_ID_OBJECT                *credentialBlob;
-    TPM2B_ENCRYPTED_SECRET         *secret;
-
     r = Esys_MakeCredential(esys_context,
                             loadedKeyHandle,
                             ESYS_TR_NONE,
@@ -330,8 +333,6 @@
     r = Esys_FlushContext(esys_context, loadedKeyHandle);
     goto_if_error(r, "Error esys flush context", error);
 
-    TPM2B_DIGEST *certInfo;
-
     r = Esys_Load(esys_context,
                   primaryHandle,
 #ifdef TEST_SESSION
@@ -383,6 +384,26 @@
     goto_if_error(r, "Flushing context", error);
 #endif
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+
+    Esys_Free(outPublic2);
+    Esys_Free(outPrivate2);
+    Esys_Free(creationData2);
+    Esys_Free(creationHash2);
+    Esys_Free(creationTicket2);
+
+    Esys_Free(primaryKeyPublic);
+    Esys_Free(primaryKeyName);
+    Esys_Free(primaryKeyQualifiedName);
+
+    Esys_Free(credentialBlob);
+    Esys_Free(secret);
+
+    Esys_Free(certInfo);
+
     return EXIT_SUCCESS;
 
  error:
@@ -413,6 +434,25 @@
         }
     }
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+
+    Esys_Free(outPublic2);
+    Esys_Free(outPrivate2);
+    Esys_Free(creationData2);
+    Esys_Free(creationHash2);
+    Esys_Free(creationTicket2);
+
+    Esys_Free(primaryKeyPublic);
+    Esys_Free(primaryKeyName);
+    Esys_Free(primaryKeyQualifiedName);
+
+    Esys_Free(credentialBlob);
+    Esys_Free(secret);
+
+    Esys_Free(certInfo);
     return EXIT_FAILURE;
 }
 
diff --git a/test/integration/esys-nv-certify.int.c b/test/integration/esys-nv-certify.int.c
index 3e62970..453ff0b 100644
--- a/test/integration/esys-nv-certify.int.c
+++ b/test/integration/esys-nv-certify.int.c
@@ -45,6 +45,13 @@
     ESYS_TR nvHandle = ESYS_TR_NONE;
     int failure_return = EXIT_FAILURE;
 
+    TPM2B_PUBLIC *outPublic = NULL;
+    TPM2B_CREATION_DATA *creationData = NULL;
+    TPM2B_DIGEST *creationHash = NULL;
+    TPMT_TK_CREATION *creationTicket = NULL;
+    TPM2B_ATTEST *certifyInfo = NULL;
+    TPMT_SIGNATURE *signature = NULL;
+
     TPM2B_AUTH authValuePrimary = {
         .size = 5,
         .buffer = {1, 2, 3, 4, 5}
@@ -124,11 +131,6 @@
     r = Esys_TR_SetAuth(esys_context, ESYS_TR_RH_OWNER, &authValue);
     goto_if_error(r, "Error: TR_SetAuth", error);
 
-    TPM2B_PUBLIC *outPublic;
-    TPM2B_CREATION_DATA *creationData;
-    TPM2B_DIGEST *creationHash;
-    TPMT_TK_CREATION *creationTicket;
-
     r = Esys_CreatePrimary(esys_context, ESYS_TR_RH_OWNER, ESYS_TR_PASSWORD,
                            ESYS_TR_NONE, ESYS_TR_NONE, &inSensitivePrimary,
                            &inPublic, &outsideInfo, &creationPCR,
@@ -186,8 +188,6 @@
                       offset);
     goto_if_error(r, "Error esys nv write", error);
 
-    TPM2B_ATTEST *certifyInfo;
-    TPMT_SIGNATURE *signature;
     TPM2B_DATA qualifyingData = {0};
     TPMT_SIG_SCHEME inScheme = { .scheme = TPM2_ALG_NULL };
 
@@ -228,6 +228,12 @@
     r = Esys_FlushContext(esys_context,signHandle);
     goto_if_error(r, "Error: FlushContext", error);
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+    Esys_Free(certifyInfo);
+    Esys_Free(signature);
     return EXIT_SUCCESS;
 
  error:
@@ -249,6 +255,12 @@
         }
     }
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+    Esys_Free(certifyInfo);
+    Esys_Free(signature);
     return failure_return;
 }
 
diff --git a/test/integration/esys-nv-ram-counter.int.c b/test/integration/esys-nv-ram-counter.int.c
index a4fb8ea..4fb2621 100644
--- a/test/integration/esys-nv-ram-counter.int.c
+++ b/test/integration/esys-nv-ram-counter.int.c
@@ -41,6 +41,12 @@
 {
     TSS2_RC r;
     ESYS_TR nvHandle = ESYS_TR_NONE;
+
+    TPM2B_NV_PUBLIC *nvPublic = NULL;
+    TPM2B_NAME *nvName = NULL;
+
+    TPM2B_MAX_NV_BUFFER *nv_test_data = NULL;
+
 #ifdef TEST_SESSION
     ESYS_TR session = ESYS_TR_NONE;
     TPMT_SYM_DEF symmetric = {.algorithm = TPM2_ALG_AES,
@@ -104,9 +110,6 @@
 
     goto_if_error(r, "Error esys define nv space", error);
 
-    TPM2B_NV_PUBLIC *nvPublic;
-    TPM2B_NAME *nvName;
-
     r = Esys_NV_ReadPublic(esys_context,
                            nvHandle,
                            ESYS_TR_NONE,
@@ -139,6 +142,9 @@
 
     goto_if_error(r, "Error esys nv write", error);
 
+    Esys_Free(nvPublic);
+    Esys_Free(nvName);
+
     r = Esys_NV_ReadPublic(esys_context,
                            nvHandle,
                            ESYS_TR_NONE,
@@ -157,7 +163,8 @@
         goto error;
     }
 
-    TPM2B_MAX_NV_BUFFER *nv_test_data;
+    Esys_Free(nvPublic);
+    Esys_Free(nvName);
 
     r = Esys_NV_Read(esys_context,
                      nvHandle,
@@ -211,6 +218,10 @@
     r = Esys_FlushContext(esys_context, session);
     goto_if_error(r, "Error: FlushContext", error);
 #endif
+
+    Esys_Free(nvPublic);
+    Esys_Free(nvName);
+    Esys_Free(nv_test_data);
     return EXIT_SUCCESS;
 
  error:
@@ -238,6 +249,9 @@
     }
 #endif
 
+    Esys_Free(nvPublic);
+    Esys_Free(nvName);
+    Esys_Free(nv_test_data);
     return EXIT_FAILURE;
 }
 
diff --git a/test/integration/esys-nv-ram-extend-index.int.c b/test/integration/esys-nv-ram-extend-index.int.c
index a594561..a690d18 100644
--- a/test/integration/esys-nv-ram-extend-index.int.c
+++ b/test/integration/esys-nv-ram-extend-index.int.c
@@ -44,6 +44,11 @@
 
     TSS2_RC r;
     ESYS_TR nvHandle = ESYS_TR_NONE;
+
+    TPM2B_NV_PUBLIC *nvPublic = NULL;
+    TPM2B_NAME *nvName = NULL;
+    TPM2B_MAX_NV_BUFFER *nv_test_data2 = NULL;
+
 #ifdef TEST_SESSION
     ESYS_TR session = ESYS_TR_NONE;
     TPMT_SYM_DEF symmetric = {.algorithm = TPM2_ALG_AES,
@@ -112,9 +117,6 @@
                                          .buffer={0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
                                                   1, 2, 3, 4, 5, 6, 7, 8, 9}};
 
-    TPM2B_NV_PUBLIC *nvPublic;
-    TPM2B_NAME *nvName;
-
     r = Esys_NV_ReadPublic(
         esys_context,
         nvHandle,
@@ -149,6 +151,8 @@
         &nv_test_data);
 
     goto_if_error(r, "Error esys nv write", error);
+    Esys_Free(nvPublic);
+    Esys_Free(nvName);
 
     r = Esys_NV_ReadPublic(
         esys_context,
@@ -169,8 +173,6 @@
         goto error;
     }
 
-    TPM2B_MAX_NV_BUFFER *nv_test_data2;
-
     r = Esys_NV_Read(
         esys_context,
         nvHandle,
@@ -188,6 +190,9 @@
 
     goto_if_error(r, "Error esys nv read", error);
 
+    Esys_Free(nvPublic);
+    Esys_Free(nvName);
+
     r = Esys_NV_ReadPublic(
         esys_context,
         nvHandle,
@@ -225,6 +230,9 @@
     goto_if_error(r, "Flushing context", error);
 #endif
 
+    Esys_Free(nvPublic);
+    Esys_Free(nvName);
+    Esys_Free(nv_test_data2);
     return EXIT_SUCCESS;
 
  error:
@@ -252,6 +260,9 @@
     }
 #endif
 
+    Esys_Free(nvPublic);
+    Esys_Free(nvName);
+    Esys_Free(nv_test_data2);
     return EXIT_FAILURE;
 }
 
diff --git a/test/integration/esys-nv-ram-ordinary-index.int.c b/test/integration/esys-nv-ram-ordinary-index.int.c
index 5da28db..eefe2e5 100644
--- a/test/integration/esys-nv-ram-ordinary-index.int.c
+++ b/test/integration/esys-nv-ram-ordinary-index.int.c
@@ -49,6 +49,11 @@
 {
     TSS2_RC r;
     ESYS_TR nvHandle = ESYS_TR_NONE;
+
+    TPM2B_NV_PUBLIC *nvPublic = NULL;
+    TPM2B_NAME *nvName = NULL;
+    TPM2B_MAX_NV_BUFFER *nv_test_data2 = NULL;
+
 #ifdef TEST_SESSION
     ESYS_TR session = ESYS_TR_NONE;
     TPMT_SYM_DEF symmetric = {.algorithm = TPM2_ALG_AES,
@@ -118,9 +123,6 @@
                                          .buffer={0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
                                                   1, 2, 3, 4, 5, 6, 7, 8, 9}};
 
-    TPM2B_NV_PUBLIC *nvPublic;
-    TPM2B_NAME *nvName;
-
     r = Esys_NV_ReadPublic(esys_context,
                            nvHandle,
                            ESYS_TR_NONE,
@@ -155,6 +157,9 @@
 
     goto_if_error(r, "Error esys nv write", error);
 
+    Esys_Free(nvPublic);
+    Esys_Free(nvName);
+
     r = Esys_NV_ReadPublic(esys_context,
                            nvHandle,
                            ESYS_TR_NONE,
@@ -173,8 +178,6 @@
         goto error;
     }
 
-    TPM2B_MAX_NV_BUFFER *nv_test_data2;
-
     r = Esys_NV_Read(esys_context,
                      nvHandle,
                      nvHandle,
@@ -191,6 +194,10 @@
 
     goto_if_error(r, "Error esys nv read", error);
 
+    Esys_Free(nvPublic);
+    Esys_Free(nvName);
+    Esys_Free(nv_test_data2);
+
     r = Esys_NV_ReadPublic(esys_context,
                            nvHandle,
                            ESYS_TR_NONE,
@@ -223,6 +230,9 @@
                          );
     goto_if_error(r, "Error: NV_ReadLock", error);
 
+    Esys_Free(nvPublic);
+    Esys_Free(nvName);
+
     r = Esys_NV_ReadPublic(esys_context,
                            nvHandle,
                            ESYS_TR_NONE,
@@ -271,6 +281,9 @@
                           );
     goto_if_error(r, "Error: NV_WriteLock", error);
 
+    Esys_Free(nvPublic);
+    Esys_Free(nvName);
+
     r = Esys_NV_ReadPublic(esys_context,
                            nvHandle,
                            ESYS_TR_NONE,
@@ -321,6 +334,9 @@
     r = Esys_FlushContext(esys_context, session);
     goto_if_error(r, "Error: FlushContext", error);
 #endif
+
+    Esys_Free(nvPublic);
+    Esys_Free(nvName);
     return EXIT_SUCCESS;
 
  error:
@@ -347,6 +363,9 @@
         }
     }
 #endif
+    Esys_Free(nvPublic);
+    Esys_Free(nvName);
+    Esys_Free(nv_test_data2);
     return EXIT_FAILURE;
 }
 
diff --git a/test/integration/esys-nv-ram-set-bits.int.c b/test/integration/esys-nv-ram-set-bits.int.c
index a1b9335..92190b9 100644
--- a/test/integration/esys-nv-ram-set-bits.int.c
+++ b/test/integration/esys-nv-ram-set-bits.int.c
@@ -41,6 +41,11 @@
 {
     TSS2_RC r;
     ESYS_TR nvHandle = ESYS_TR_NONE;
+
+    TPM2B_NV_PUBLIC *nvPublic = NULL;
+    TPM2B_NAME *nvName = NULL;
+    TPM2B_MAX_NV_BUFFER *nv_test_data = NULL;
+
 #ifdef TEST_SESSION
     ESYS_TR session = ESYS_TR_NONE;
     TPMT_SYM_DEF symmetric = {.algorithm = TPM2_ALG_AES,
@@ -104,9 +109,6 @@
 
     goto_if_error(r, "Error esys define nv space", error);
 
-    TPM2B_NV_PUBLIC *nvPublic;
-    TPM2B_NAME *nvName;
-
     r = Esys_NV_ReadPublic(esys_context,
                            nvHandle,
                            ESYS_TR_NONE,
@@ -142,6 +144,8 @@
                         bits);
 
     goto_if_error(r, "Error esys nv write", error);
+    Esys_Free(nvPublic);
+    Esys_Free(nvName);
 
     r = Esys_NV_ReadPublic(esys_context,
                            nvHandle,
@@ -161,8 +165,6 @@
         goto error;
     }
 
-    TPM2B_MAX_NV_BUFFER *nv_test_data;
-
     r = Esys_NV_Read(esys_context,
                      nvHandle,
                      nvHandle,
@@ -179,6 +181,9 @@
 
     goto_if_error(r, "Error esys nv read", error);
 
+    Esys_Free(nvPublic);
+    Esys_Free(nvName);
+
     r = Esys_NV_ReadPublic(esys_context,
                            nvHandle,
                            ESYS_TR_NONE,
@@ -215,6 +220,9 @@
     goto_if_error(r, "Error: FlushContext", error);
 #endif
 
+    Esys_Free(nvPublic);
+    Esys_Free(nvName);
+    Esys_Free(nv_test_data);
     return EXIT_SUCCESS;
 
  error:
@@ -242,6 +250,9 @@
     }
 #endif
 
+    Esys_Free(nvPublic);
+    Esys_Free(nvName);
+    Esys_Free(nv_test_data);
     return EXIT_FAILURE;
 }
 
diff --git a/test/integration/esys-object-changeauth.int.c b/test/integration/esys-object-changeauth.int.c
index 65cda11..927974c 100644
--- a/test/integration/esys-object-changeauth.int.c
+++ b/test/integration/esys-object-changeauth.int.c
@@ -41,6 +41,19 @@
     ESYS_TR primaryHandle = ESYS_TR_NONE;
     ESYS_TR loadedKeyHandle = ESYS_TR_NONE;
 
+    TPM2B_PUBLIC *outPublic = NULL;
+    TPM2B_CREATION_DATA *creationData = NULL;
+    TPM2B_DIGEST *creationHash = NULL;
+    TPMT_TK_CREATION *creationTicket = NULL;
+
+    TPM2B_PUBLIC *outPublic2 = NULL;
+    TPM2B_PRIVATE *outPrivate2 = NULL;
+    TPM2B_CREATION_DATA *creationData2 = NULL;
+    TPM2B_DIGEST *creationHash2 = NULL;
+    TPMT_TK_CREATION *creationTicket2 = NULL;
+
+    TPM2B_PRIVATE *outPrivateChangeAuth = NULL;
+
     TPM2B_PUBLIC inPublic = {
         .size = 0,
         .publicArea = {
@@ -106,11 +119,6 @@
     r = Esys_TR_SetAuth(esys_context, ESYS_TR_RH_OWNER, &authValue);
     goto_if_error(r, "Error: TR_SetAuth", error);
 
-    TPM2B_PUBLIC *outPublic;
-    TPM2B_CREATION_DATA *creationData;
-    TPM2B_DIGEST *creationHash;
-    TPMT_TK_CREATION *creationTicket;
-
     r = Esys_CreatePrimary(esys_context, ESYS_TR_RH_OWNER, ESYS_TR_PASSWORD,
                            ESYS_TR_NONE, ESYS_TR_NONE, &inSensitivePrimary, &inPublic,
                            &outsideInfo, &creationPCR, &primaryHandle,
@@ -188,12 +196,6 @@
         .count = 0,
     };
 
-    TPM2B_PUBLIC *outPublic2;
-    TPM2B_PRIVATE *outPrivate2;
-    TPM2B_CREATION_DATA *creationData2;
-    TPM2B_DIGEST *creationHash2;
-    TPMT_TK_CREATION *creationTicket2;
-
     r = Esys_Create(esys_context,
                     primaryHandle,
                     ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
@@ -220,8 +222,6 @@
                           .buffer={30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
                                    40, 41, 42, 43, 44, 45, 46, 47, 48, 49}};
 
-    TPM2B_PRIVATE *outPrivateChangeAuth;
-
     r = Esys_ObjectChangeAuth(esys_context,
                               loadedKeyHandle,
                               primaryHandle,
@@ -239,6 +239,18 @@
     r = Esys_FlushContext(esys_context, primaryHandle);
     goto_if_error(r, "Error during FlushContext", error);
 
+    SAFE_FREE(outPublic);
+    SAFE_FREE(creationData);
+    SAFE_FREE(creationHash);
+    SAFE_FREE(creationTicket);
+
+    SAFE_FREE(outPublic2);
+    SAFE_FREE(outPrivate2);
+    SAFE_FREE(creationData2);
+    SAFE_FREE(creationHash2);
+    SAFE_FREE(creationTicket2);
+
+    SAFE_FREE(outPrivateChangeAuth);
     return EXIT_SUCCESS;
 
  error:
@@ -255,6 +267,18 @@
         }
     }
 
+    SAFE_FREE(outPublic);
+    SAFE_FREE(creationData);
+    SAFE_FREE(creationHash);
+    SAFE_FREE(creationTicket);
+
+    SAFE_FREE(outPublic2);
+    SAFE_FREE(outPrivate2);
+    SAFE_FREE(creationData2);
+    SAFE_FREE(creationHash2);
+    SAFE_FREE(creationTicket2);
+
+    SAFE_FREE(outPrivateChangeAuth);
     return EXIT_FAILURE;
 }
 
diff --git a/test/integration/esys-pcr-basic.int.c b/test/integration/esys-pcr-basic.int.c
index c1d76c4..5749e16 100644
--- a/test/integration/esys-pcr-basic.int.c
+++ b/test/integration/esys-pcr-basic.int.c
@@ -42,6 +42,9 @@
     int failure_return = EXIT_FAILURE;
 
     TPMS_CAPABILITY_DATA *savedPCRs = NULL;
+    TPML_PCR_SELECTION *pcrSelectionOut = NULL;
+    TPML_DIGEST *pcrValues = NULL;
+    TPML_DIGEST_VALUES *digestsEvent = NULL;
 
     ESYS_TR  pcrHandle_handle = 16;
     TPML_DIGEST_VALUES digests
@@ -81,8 +84,6 @@
         }
     };
     UINT32 pcrUpdateCounter;
-    TPML_PCR_SELECTION *pcrSelectionOut;
-    TPML_DIGEST *pcrValues;
 
     r = Esys_PCR_Read(
         esys_context,
@@ -107,8 +108,6 @@
     TPM2B_EVENT eventData = { .size = 20,
                               .buffer={0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
                                        1, 2, 3, 4, 5, 6, 7, 8, 9}};
-    TPML_DIGEST_VALUES *digestsEvent;
-
     r = Esys_PCR_Event(
         esys_context,
         pcrHandle_handle,
@@ -166,11 +165,16 @@
     goto_if_error(r, "Error: PCR_Allocate", error);
 
     Esys_Free(savedPCRs);
-
+    Esys_Free(pcrSelectionOut);
+    Esys_Free(pcrValues);
+    Esys_Free(digestsEvent);
     return EXIT_SUCCESS;
 
  error:
-    if (savedPCRs) Esys_Free(savedPCRs);
+    Esys_Free(savedPCRs);
+    Esys_Free(pcrSelectionOut);
+    Esys_Free(pcrValues);
+    Esys_Free(digestsEvent);
     return failure_return;
 
 }
diff --git a/test/integration/esys-policy-authorize.int.c b/test/integration/esys-policy-authorize.int.c
index 7030eb2..90c50e2 100644
--- a/test/integration/esys-policy-authorize.int.c
+++ b/test/integration/esys-policy-authorize.int.c
@@ -40,6 +40,15 @@
     ESYS_TR primaryHandle = ESYS_TR_NONE;
     ESYS_TR sessionTrial = ESYS_TR_NONE;
 
+    TPM2B_PUBLIC *outPublic = NULL;
+    TPM2B_CREATION_DATA *creationData = NULL;
+    TPM2B_DIGEST *creationHash = NULL;
+    TPMT_TK_CREATION *creationTicket = NULL;
+
+    TPM2B_NAME *nameKeySign = NULL;
+    TPM2B_NAME *keyQualifiedName = NULL;
+    TPM2B_DIGEST *policyAuthorizeDigest = NULL;
+
     /*
      * 1. Create Primary. This primary will be used for PolicyAuthorize.
      */
@@ -112,11 +121,6 @@
     r = Esys_TR_SetAuth(esys_context, ESYS_TR_RH_OWNER, &authValue);
     goto_if_error(r, "Error: TR_SetAuth", error);
 
-    TPM2B_PUBLIC *outPublic;
-    TPM2B_CREATION_DATA *creationData;
-    TPM2B_DIGEST *creationHash;
-    TPMT_TK_CREATION *creationTicket;
-
     r = Esys_CreatePrimary(esys_context, ESYS_TR_RH_OWNER, ESYS_TR_PASSWORD,
                            ESYS_TR_NONE, ESYS_TR_NONE,
                            &inSensitivePrimary, &inPublic,
@@ -125,6 +129,8 @@
                            &creationTicket);
     goto_if_error(r, "Error esys create primary", error);
 
+    Esys_Free(outPublic);
+
     /*
      * 2. Create a trial policy with PolicyAuthorized. The name primary key
      *    will be passed and the primary key will be used to sign policies.
@@ -146,9 +152,6 @@
                               &sessionTrial);
     goto_if_error(r, "Error: During initialization of policy trial session", error);
 
-    TPM2B_NAME *nameKeySign;
-    TPM2B_NAME *keyQualifiedName;
-
     /* Dummy data for first call of PolicyAuthorize */
     TPM2B_DIGEST approvedPolicy = {0};
     TPM2B_NONCE policyRef = {0};
@@ -181,7 +184,6 @@
         );
     goto_if_error(r, "Error: PolicyAuthorize", error);
 
-    TPM2B_DIGEST *policyAuthorizeDigest;
     r = Esys_PolicyGetDigest(esys_context,
                              sessionTrial,
                              ESYS_TR_NONE,
@@ -197,6 +199,14 @@
     r = Esys_FlushContext(esys_context, primaryHandle);
     goto_if_error(r, "Error: FlushContext", error);
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+
+    Esys_Free(nameKeySign);
+    Esys_Free(keyQualifiedName);
+    Esys_Free(policyAuthorizeDigest);
     return EXIT_SUCCESS;
 
  error:
@@ -213,6 +223,14 @@
         }
     }
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+
+    Esys_Free(nameKeySign);
+    Esys_Free(keyQualifiedName);
+    Esys_Free(policyAuthorizeDigest);
     return EXIT_FAILURE;
 }
 
diff --git a/test/integration/esys-policy-nv-changeauth.int.c b/test/integration/esys-policy-nv-changeauth.int.c
index 9e4f6b4..de87f64 100644
--- a/test/integration/esys-policy-nv-changeauth.int.c
+++ b/test/integration/esys-policy-nv-changeauth.int.c
@@ -49,6 +49,8 @@
     ESYS_TR nvHandle = ESYS_TR_NONE;
     ESYS_TR policySession = ESYS_TR_NONE;
 
+    TPM2B_DIGEST *policyDigestTrial = NULL;
+
     /*
      * Firth the policy value for changing the auth value of an NV index has to be
      * determined with a policy trial session.
@@ -88,7 +90,6 @@
                                );
     goto_if_error(r, "Error: PolicyCommandCode", error);
 
-    TPM2B_DIGEST *policyDigestTrial;
     r = Esys_PolicyGetDigest(esys_context,
                              sessionTrial,
                              ESYS_TR_NONE,
@@ -123,6 +124,7 @@
         }
     };
 
+
     r = Esys_NV_DefineSpace(esys_context,
                             ESYS_TR_RH_OWNER,
                             ESYS_TR_PASSWORD,
@@ -253,6 +255,7 @@
     r = Esys_FlushContext(esys_context, policySession);
     goto_if_error(r, "Flushing context", error);
 
+    Esys_Free(policyDigestTrial);
     return EXIT_SUCCESS;
 
  error:
@@ -280,6 +283,7 @@
         }
     }
 
+    Esys_Free(policyDigestTrial);
     return EXIT_FAILURE;
 }
 
diff --git a/test/integration/esys-policy-nv-undefine-special.int.c b/test/integration/esys-policy-nv-undefine-special.int.c
index 005d659..9b15392 100644
--- a/test/integration/esys-policy-nv-undefine-special.int.c
+++ b/test/integration/esys-policy-nv-undefine-special.int.c
@@ -50,6 +50,9 @@
     ESYS_TR policySession = ESYS_TR_NONE;
     ESYS_TR session = ESYS_TR_NONE;
     int failure_return = EXIT_FAILURE;
+
+    TPM2B_DIGEST *policyDigestTrial = NULL;
+
     /*
      * First the policy value for NV_UndefineSpaceSpecial has to be
      * determined with a policy trial session.
@@ -89,7 +92,6 @@
                                );
     goto_if_error(r, "Error: PolicyCommandCode", error);
 
-    TPM2B_DIGEST *policyDigestTrial;
     r = Esys_PolicyGetDigest(esys_context,
                              sessionTrial,
                              ESYS_TR_NONE,
@@ -216,6 +218,7 @@
     r = Esys_FlushContext(esys_context, policySession);
     goto_if_error(r, "Flushing context", error);
 
+    Esys_Free(policyDigestTrial);
     return EXIT_SUCCESS;
 
  error:
@@ -238,6 +241,7 @@
         }
     }
 
+    Esys_Free(policyDigestTrial);
     return failure_return;
 }
 
diff --git a/test/integration/esys-policy-password.int.c b/test/integration/esys-policy-password.int.c
index e444f65..554662f 100644
--- a/test/integration/esys-policy-password.int.c
+++ b/test/integration/esys-policy-password.int.c
@@ -47,6 +47,19 @@
     ESYS_TR primaryHandle = ESYS_TR_NONE;
     ESYS_TR policySession = ESYS_TR_NONE;
 
+    TPM2B_PUBLIC *outPublic = NULL;
+    TPM2B_CREATION_DATA *creationData = NULL;
+    TPM2B_DIGEST *creationHash = NULL;
+    TPMT_TK_CREATION *creationTicket = NULL;
+
+    TPM2B_DIGEST *policyDigestTrial = NULL;
+
+    TPM2B_PUBLIC *outPublic2 = NULL;
+    TPM2B_PRIVATE *outPrivate2 = NULL;
+    TPM2B_CREATION_DATA *creationData2 = NULL;
+    TPM2B_DIGEST *creationHash2 = NULL;
+    TPMT_TK_CREATION *creationTicket2 = NULL;
+
     /*
      * Firth the policy value for changing the auth value of an NV index has to be
      * determined with a policy trial session.
@@ -79,7 +92,6 @@
         );
     goto_if_error(r, "Error: PolicyPassword", error);
 
-    TPM2B_DIGEST *policyDigestTrial;
     r = Esys_PolicyGetDigest(
         esys_context,
         sessionTrial,
@@ -158,11 +170,6 @@
     r = Esys_TR_SetAuth(esys_context, ESYS_TR_RH_OWNER, &authValue);
     goto_if_error(r, "Error: TR_SetAuth", error);
 
-    TPM2B_PUBLIC *outPublic;
-    TPM2B_CREATION_DATA *creationData;
-    TPM2B_DIGEST *creationHash;
-    TPMT_TK_CREATION *creationTicket;
-
     r = Esys_CreatePrimary(esys_context, ESYS_TR_RH_OWNER, ESYS_TR_PASSWORD,
                            ESYS_TR_NONE, ESYS_TR_NONE, &inSensitivePrimary, &inPublic,
                            &outsideInfo, &creationPCR, &primaryHandle,
@@ -260,12 +267,6 @@
         .count = 0,
     };
 
-    TPM2B_PUBLIC *outPublic2;
-    TPM2B_PRIVATE *outPrivate2;
-    TPM2B_CREATION_DATA *creationData2;
-    TPM2B_DIGEST *creationHash2;
-    TPMT_TK_CREATION *creationTicket2;
-
     r = Esys_Create(esys_context,
                     primaryHandle,
                     policySession, ESYS_TR_NONE, ESYS_TR_NONE,
@@ -287,6 +288,18 @@
     r = Esys_FlushContext(esys_context, policySession);
     goto_if_error(r, "Flushing context", error);
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+
+    Esys_Free(policyDigestTrial);
+
+    Esys_Free(outPublic2);
+    Esys_Free(outPrivate2);
+    Esys_Free(creationData2);
+    Esys_Free(creationHash2);
+    Esys_Free(creationTicket2);
     return EXIT_SUCCESS;
 
  error:
@@ -303,6 +316,18 @@
         }
     }
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+
+    Esys_Free(policyDigestTrial);
+
+    Esys_Free(outPublic2);
+    Esys_Free(outPrivate2);
+    Esys_Free(creationData2);
+    Esys_Free(creationHash2);
+    Esys_Free(creationTicket2);
     return EXIT_FAILURE;
 }
 
diff --git a/test/integration/esys-policy-ticket.int.c b/test/integration/esys-policy-ticket.int.c
index 0199f05..3e96b5c 100644
--- a/test/integration/esys-policy-ticket.int.c
+++ b/test/integration/esys-policy-ticket.int.c
@@ -50,7 +50,20 @@
     ESYS_TR session = ESYS_TR_NONE;
     ESYS_TR sessionTrial = ESYS_TR_NONE;
     int failure_return = EXIT_FAILURE;
+
     TPM2B_NONCE *nonceTPM = NULL;
+    TPM2B_PUBLIC *outPublic = NULL;
+    TPM2B_CREATION_DATA *creationData = NULL;
+    TPM2B_DIGEST *creationHash = NULL;
+    TPMT_TK_CREATION *creationTicket = NULL;
+    TPM2B_NAME *nameKeySign = NULL;
+    TPM2B_NAME *keyQualifiedName = NULL;
+    TPM2B_DIGEST *signed_digest = NULL;
+    TPM2B_TIMEOUT *timeout = NULL;
+    TPMT_TK_AUTH *policySignedTicket = NULL;
+    TPMT_TK_HASHCHECK *validation = NULL;
+    TPMT_TK_AUTH *policySecretTicket = NULL;
+    TPMT_SIGNATURE *signature = NULL;
 
     /*
      * 1. Create Primary. This primary will be used as signing key.
@@ -124,11 +137,6 @@
     r = Esys_TR_SetAuth(esys_context, ESYS_TR_RH_OWNER, &authValue);
     goto_if_error(r, "Error: TR_SetAuth", error);
 
-    TPM2B_PUBLIC *outPublic;
-    TPM2B_CREATION_DATA *creationData;
-    TPM2B_DIGEST *creationHash;
-    TPMT_TK_CREATION *creationTicket;
-
     r = Esys_CreatePrimary(esys_context, ESYS_TR_RH_OWNER, ESYS_TR_PASSWORD,
                            ESYS_TR_NONE, ESYS_TR_NONE,
                            &inSensitivePrimary, &inPublic,
@@ -136,9 +144,10 @@
                            &outPublic, &creationData, &creationHash,
                            &creationTicket);
     goto_if_error(r, "Error esys create primary", error);
-
-    TPM2B_NAME *nameKeySign;
-    TPM2B_NAME *keyQualifiedName;
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
 
     r = Esys_ReadPublic(esys_context,
                         primaryHandle,
@@ -155,7 +164,6 @@
      *    ticket policySignedTicket will be created.
      *    With this ticket the function Esys_PolicyTicket will be tested.
      */
-    TPM2B_DIGEST *signed_digest;
     INT32 expiration = -(10*365*24*60*60); /* Expiration ten years */
 
     TPM2B_DIGEST expiration2b;
@@ -185,8 +193,6 @@
 
     TPM2B_NONCE policyRef = {0};
     TPM2B_DIGEST cpHashA = {0};
-    TPM2B_TIMEOUT *timeout;
-    TPMT_TK_AUTH *policySignedTicket;
 
     r = Esys_TRSess_GetNonceTPM(esys_context, session, &nonceTPM);
     goto_if_error(r, "Error: During initialization of policy trial session", error);
@@ -219,8 +225,6 @@
                             );
     goto_if_error(r, "Error: SequenceUpdate", error);
 
-    TPMT_TK_HASHCHECK *validation;
-
     r = Esys_SequenceComplete(esys_context,
                               sequenceHandle_handle,
                               ESYS_TR_PASSWORD,
@@ -239,7 +243,6 @@
         .hierarchy = TPM2_RH_OWNER,
         .digest = {0}
     };
-    TPMT_SIGNATURE *signature;
 
     /* Policy expiration of ten years will be signed */
 
@@ -309,6 +312,7 @@
 
         session = ESYS_TR_NONE;
     }
+    Esys_Free(timeout);
 
     /*
      * 3. A policy tial session will be created. With this trial policy the
@@ -332,8 +336,6 @@
                               &sessionTrial);
     goto_if_error(r, "Error: During initialization of policy trial session", error);
 
-    TPMT_TK_AUTH *policySecretTicket;
-
     r = Esys_PolicySecret(
         esys_context,
         primaryHandle,
@@ -357,7 +359,16 @@
     r = Esys_FlushContext(esys_context, primaryHandle);
     goto_if_error(r, "Error: FlushContext", error);
 
-    free(nonceTPM);
+    Esys_Free(outPublic);
+    Esys_Free(nameKeySign);
+    Esys_Free(keyQualifiedName);
+    Esys_Free(signed_digest);
+    Esys_Free(timeout);
+    Esys_Free(policySignedTicket);
+    Esys_Free(validation);
+    Esys_Free(policySecretTicket);
+    Esys_Free(nonceTPM);
+    Esys_Free(signature);
     return EXIT_SUCCESS;
 
  error:
@@ -380,8 +391,19 @@
         }
     }
 
-    if (nonceTPM)
-        free(nonceTPM);
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+    Esys_Free(nameKeySign);
+    Esys_Free(keyQualifiedName);
+    Esys_Free(signed_digest);
+    Esys_Free(timeout);
+    Esys_Free(policySignedTicket);
+    Esys_Free(validation);
+    Esys_Free(policySecretTicket);
+    Esys_Free(nonceTPM);
+    Esys_Free(signature);
 
     return failure_return;
 }
diff --git a/test/integration/esys-quote.int.c b/test/integration/esys-quote.int.c
index 8e6a322..194b1bf 100644
--- a/test/integration/esys-quote.int.c
+++ b/test/integration/esys-quote.int.c
@@ -39,6 +39,14 @@
     TSS2_RC r;
     ESYS_TR primaryHandle = ESYS_TR_NONE;
 
+    TPM2B_PUBLIC *outPublic = NULL;
+    TPM2B_CREATION_DATA *creationData = NULL;
+    TPM2B_DIGEST *creationHash = NULL;
+    TPMT_TK_CREATION *creationTicket = NULL;
+
+    TPM2B_ATTEST *attest = NULL;
+    TPMT_SIGNATURE *signature = NULL;
+
     TPM2B_AUTH authValuePrimary = {
         .size = 5,
         .buffer = {1, 2, 3, 4, 5}
@@ -119,10 +127,6 @@
     goto_if_error(r, "Error: TR_SetAuth", error);
 
     RSRC_NODE_T *primaryHandle_node;
-    TPM2B_PUBLIC *outPublic;
-    TPM2B_CREATION_DATA *creationData;
-    TPM2B_DIGEST *creationHash;
-    TPMT_TK_CREATION *creationTicket;
 
     r = Esys_CreatePrimary(esys_context, ESYS_TR_RH_OWNER, ESYS_TR_PASSWORD,
                            ESYS_TR_NONE, ESYS_TR_NONE, &inSensitivePrimary,
@@ -158,9 +162,6 @@
                 .pcrSelect = { 0,4,0 } },
         }};
 
-    TPM2B_ATTEST *attest;
-    TPMT_SIGNATURE *signature;
-
     r = Esys_Quote(esys_context, primaryHandle,
                    ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
                    &qualifyingData, &sig_scheme, &pcr_selection,
@@ -170,6 +171,13 @@
     r = Esys_FlushContext(esys_context, primaryHandle);
     goto_if_error(r, "Error: FlushContext", error);
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+
+    Esys_Free(attest);
+    Esys_Free(signature);
     return EXIT_SUCCESS;
 
  error:
diff --git a/test/integration/esys-rsa-encrypt-decrypt.int.c b/test/integration/esys-rsa-encrypt-decrypt.int.c
index 27cca74..4c7f171 100644
--- a/test/integration/esys-rsa-encrypt-decrypt.int.c
+++ b/test/integration/esys-rsa-encrypt-decrypt.int.c
@@ -41,6 +41,14 @@
     TSS2_RC r;
     ESYS_TR primaryHandle = ESYS_TR_NONE;
 
+    TPM2B_PUBLIC *outPublic = NULL;
+    TPM2B_CREATION_DATA *creationData = NULL;
+    TPM2B_DIGEST *creationHash = NULL;
+    TPMT_TK_CREATION *creationTicket = NULL;
+    TPM2B_PUBLIC_KEY_RSA *cipher = NULL;
+    TPM2B_PUBLIC_KEY_RSA *plain2 = NULL;
+    TPM2B_DATA * null_data = NULL;
+
     TPM2B_AUTH authValuePrimary = {
         .size = 5,
         .buffer = {1, 2, 3, 4, 5}
@@ -109,10 +117,6 @@
     goto_if_error(r, "Error: TR_SetAuth", error);
 
     RSRC_NODE_T *primaryHandle_node;
-    TPM2B_PUBLIC *outPublic;
-    TPM2B_CREATION_DATA *creationData;
-    TPM2B_DIGEST *creationHash;
-    TPMT_TK_CREATION *creationTicket;
 
     for (int mode = 0; mode <= 2; mode++) {
 
@@ -135,6 +139,10 @@
                                &primaryHandle, &outPublic, &creationData,
                                &creationHash, &creationTicket);
         goto_if_error(r, "Error esys create primary", error);
+        Esys_Free(outPublic);
+        Esys_Free(creationData);
+        Esys_Free(creationHash);
+        Esys_Free(creationTicket);
 
         r = esys_GetResourceObject(esys_context, primaryHandle,
                                    &primaryHandle_node);
@@ -151,9 +159,6 @@
         TPM2B_PUBLIC_KEY_RSA plain = {.size = plain_size,.buffer = {1, 2, 3}
         };
         TPMT_RSA_DECRYPT scheme;
-        TPM2B_DATA null_data = {.size = 0,.buffer = {}
-        };
-        TPM2B_PUBLIC_KEY_RSA *cipher;
 
         if (mode == 0) {
             scheme.scheme = TPM2_ALG_NULL;
@@ -165,15 +170,19 @@
         }
         r = Esys_RSA_Encrypt(esys_context, primaryHandle, ESYS_TR_NONE,
                              ESYS_TR_NONE, ESYS_TR_NONE, &plain, &scheme,
-                             &null_data, &cipher);
+                             null_data, &cipher);
         goto_if_error(r, "Error esys rsa encrypt", error);
 
-        TPM2B_PUBLIC_KEY_RSA *plain2;
+        Esys_Free(null_data);
+
         r = Esys_RSA_Decrypt(esys_context, primaryHandle,
                              ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
-                             cipher, &scheme, &null_data, &plain2);
+                             cipher, &scheme, null_data, &plain2);
         goto_if_error(r, "Error esys rsa decrypt", error);
 
+        Esys_Free(null_data);
+        Esys_Free(cipher);
+
         if (mode > 0 && memcmp(&plain.buffer[0], &plain2->buffer[0], plain_size)) {
             LOG_ERROR("plain texts are not equal for mode %i", mode);
             goto error;
@@ -181,7 +190,9 @@
 
         r = Esys_FlushContext(esys_context, primaryHandle);
         goto_if_error(r, "Error: FlushContext", error);
+        Esys_Free(plain2);
     }
+
     return EXIT_SUCCESS;
 
  error:
@@ -192,6 +203,13 @@
         }
     }
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+    Esys_Free(cipher);
+    Esys_Free(plain2);
+    Esys_Free(null_data);
     return EXIT_FAILURE;
 }
 
diff --git a/test/integration/esys-save-and-load-context.int.c b/test/integration/esys-save-and-load-context.int.c
index f30f3cc..978dc12 100644
--- a/test/integration/esys-save-and-load-context.int.c
+++ b/test/integration/esys-save-and-load-context.int.c
@@ -49,6 +49,19 @@
     ESYS_TR loadedKeyHandle1 = ESYS_TR_NONE;
     ESYS_TR loadedKeyHandle2 = ESYS_TR_NONE;
 
+    TPM2B_PUBLIC *outPublic = NULL;
+    TPM2B_CREATION_DATA *creationData = NULL;
+    TPM2B_DIGEST *creationHash = NULL;
+    TPMT_TK_CREATION *creationTicket = NULL;
+
+    TPM2B_PUBLIC *outPublic2 = NULL;
+    TPM2B_PRIVATE *outPrivate2 = NULL;
+    TPM2B_CREATION_DATA *creationData2 = NULL;
+    TPM2B_DIGEST *creationHash2 = NULL;
+    TPMT_TK_CREATION *creationTicket2 = NULL;
+
+    TPMS_CONTEXT *context = NULL;
+
     TPM2B_AUTH authValuePrimary = {
         .size = 5,
         .buffer = {1, 2, 3, 4, 5}
@@ -161,10 +174,6 @@
     goto_if_error(r, "Error: TR_SetAuth", error);
 
     RSRC_NODE_T *primaryHandle_node;
-    TPM2B_PUBLIC *outPublic;
-    TPM2B_CREATION_DATA *creationData;
-    TPM2B_DIGEST *creationHash;
-    TPMT_TK_CREATION *creationTicket;
 
     r = Esys_CreatePrimary(esys_context, ESYS_TR_RH_OWNER, ESYS_TR_PASSWORD,
                            ESYS_TR_NONE, ESYS_TR_NONE, &inSensitivePrimary, &inPublic,
@@ -264,12 +273,6 @@
         .count = 0,
     };
 
-    TPM2B_PUBLIC *outPublic2;
-    TPM2B_PRIVATE *outPrivate2;
-    TPM2B_CREATION_DATA *creationData2;
-    TPM2B_DIGEST *creationHash2;
-    TPMT_TK_CREATION *creationTicket2;
-
     r = Esys_Create(esys_context,
                     primaryHandle,
                     ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
@@ -291,9 +294,13 @@
                   ESYS_TR_NONE, outPrivate2, outPublic2, &loadedKeyHandle1);
     goto_if_error(r, "Error esys load ", error);
 
-    LOG_INFO("\nSecond Key loaded.");
+    Esys_Free(outPublic2);
+    Esys_Free(outPrivate2);
+    Esys_Free(creationData2);
+    Esys_Free(creationHash2);
+    Esys_Free(creationTicket2);
 
-    TPMS_CONTEXT *context;
+    LOG_INFO("\nSecond Key loaded.");
 
     r = Esys_ContextSave(esys_context, loadedKeyHandle1, &context);
     goto_if_error(r, "Error esys context save", error);
@@ -329,6 +336,18 @@
     r = Esys_FlushContext(esys_context, loadedKeyHandle2);
     goto_if_error(r, "Error: FlushContext", error);
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+
+    Esys_Free(outPublic2);
+    Esys_Free(outPrivate2);
+    Esys_Free(creationData2);
+    Esys_Free(creationHash2);
+    Esys_Free(creationTicket2);
+
+    Esys_Free(context);
     return EXIT_SUCCESS;
 
  error:
@@ -351,6 +370,18 @@
         }
     }
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+
+    Esys_Free(outPublic2);
+    Esys_Free(outPrivate2);
+    Esys_Free(creationData2);
+    Esys_Free(creationHash2);
+    Esys_Free(creationTicket2);
+
+    Esys_Free(context);
     return EXIT_FAILURE;
 }
 
diff --git a/test/integration/esys-session-attributes.int.c b/test/integration/esys-session-attributes.int.c
index 22c5e56..34838e0 100644
--- a/test/integration/esys-session-attributes.int.c
+++ b/test/integration/esys-session-attributes.int.c
@@ -43,6 +43,8 @@
     TSS2_RC r;
     ESYS_TR objectHandle = ESYS_TR_NONE;
     ESYS_TR session = ESYS_TR_NONE;
+    TPM2B_DIGEST *rdata = NULL;
+
     TPMT_SYM_DEF symmetric = {.algorithm = TPM2_ALG_XOR,
                               .keyBits = { .exclusiveOr = TPM2_ALG_SHA1 },
                               .mode = {.aes = TPM2_ALG_CFB}};
@@ -107,8 +109,6 @@
         .count = 0,
     };
 
-    TPM2B_DIGEST *rdata;
-
     r = Esys_StartAuthSession(esys_context, ESYS_TR_NONE, ESYS_TR_NONE,
                               ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
                               NULL,
@@ -159,6 +159,7 @@
 
     r = Esys_GetRandom(esys_context, session, ESYS_TR_NONE, ESYS_TR_NONE,
                        10, &rdata);
+    Esys_Free(rdata);
     transmit_hook = NULL;
     goto_if_error(r, "Error esapi create primary", error);
 
@@ -175,6 +176,7 @@
     r = Esys_FlushContext(esys_context, session);
     goto_if_error(r, "Flushing context", error);
 
+    Esys_Free(rdata);
     return EXIT_SUCCESS;
 
  error:
@@ -192,7 +194,7 @@
         }
     }
 
-
+    Esys_Free(rdata);
     return EXIT_FAILURE;
 }
 
diff --git a/test/integration/esys-unseal-password-auth.int.c b/test/integration/esys-unseal-password-auth.int.c
index dd1647b..e1a2def 100644
--- a/test/integration/esys-unseal-password-auth.int.c
+++ b/test/integration/esys-unseal-password-auth.int.c
@@ -47,7 +47,6 @@
 int
 test_esys_unseal_password_auth(ESYS_CONTEXT * esys_context)
 {
-
     /*
      * 1. Create Primary
      */
@@ -55,6 +54,17 @@
     ESYS_TR primaryHandle = ESYS_TR_NONE;
     ESYS_TR loadedKeyHandle = ESYS_TR_NONE;
 
+    TPM2B_PUBLIC *outPublic = NULL;
+    TPM2B_CREATION_DATA *creationData = NULL;
+    TPM2B_DIGEST *creationHash = NULL;
+    TPMT_TK_CREATION *creationTicket = NULL;
+    TPM2B_PUBLIC *outPublic2 = NULL;
+    TPM2B_PRIVATE *outPrivate2 = NULL;
+    TPM2B_CREATION_DATA *creationData2 = NULL;
+    TPM2B_DIGEST *creationHash2 = NULL;
+    TPMT_TK_CREATION *creationTicket2 = NULL;
+    TPM2B_SENSITIVE_DATA *outData = NULL;
+
     TPM2B_AUTH authValuePrimary = {
         .size = 5,
         .buffer = {1, 2, 3, 4, 5}
@@ -126,10 +136,6 @@
     goto_if_error(r, "Error: TR_SetAuth", error);
 
     RSRC_NODE_T *primaryHandle_node;
-    TPM2B_PUBLIC *outPublic;
-    TPM2B_CREATION_DATA *creationData;
-    TPM2B_DIGEST *creationHash;
-    TPMT_TK_CREATION *creationTicket;
 
     r = Esys_CreatePrimary(esys_context, ESYS_TR_RH_OWNER, ESYS_TR_PASSWORD,
                            ESYS_TR_NONE, ESYS_TR_NONE,
@@ -238,12 +244,6 @@
         .count = 0,
     };
 
-    TPM2B_PUBLIC *outPublic2;
-    TPM2B_PRIVATE *outPrivate2;
-    TPM2B_CREATION_DATA *creationData2;
-    TPM2B_DIGEST *creationHash2;
-    TPMT_TK_CREATION *creationTicket2;
-
     r = Esys_Create(esys_context,
                     primaryHandle,
                     ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
@@ -279,8 +279,6 @@
      * 4. Unseal key
      */
 
-    TPM2B_SENSITIVE_DATA *outData;
-
     r = Esys_Unseal(esys_context, loadedKeyHandle, ESYS_TR_PASSWORD,
         ESYS_TR_NONE, ESYS_TR_NONE, &outData);
     goto_if_error(r, "Error esys Unseal ", error);
@@ -305,6 +303,16 @@
     r = Esys_FlushContext(esys_context, loadedKeyHandle);
     goto_if_error(r, "Error during FlushContext", error);
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+    Esys_Free(outPublic2);
+    Esys_Free(outPrivate2);
+    Esys_Free(creationData2);
+    Esys_Free(creationHash2);
+    Esys_Free(creationTicket2);
+    Esys_Free(outData);
     return EXIT_SUCCESS;
 
     error:
@@ -321,6 +329,16 @@
         }
     }
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+    Esys_Free(outPublic2);
+    Esys_Free(outPrivate2);
+    Esys_Free(creationData2);
+    Esys_Free(creationHash2);
+    Esys_Free(creationTicket2);
+    Esys_Free(outData);
     return EXIT_FAILURE;
 }
 
diff --git a/test/integration/esys-verify-signature.int.c b/test/integration/esys-verify-signature.int.c
index 2749633..92c7d92 100644
--- a/test/integration/esys-verify-signature.int.c
+++ b/test/integration/esys-verify-signature.int.c
@@ -38,6 +38,17 @@
     TSS2_RC r;
     ESYS_TR primaryHandle = ESYS_TR_NONE;
 
+    TPM2B_PUBLIC *outPublic = NULL;
+    TPM2B_CREATION_DATA *creationData = NULL;
+    TPM2B_DIGEST *creationHash = NULL;
+    TPMT_TK_CREATION *creationTicket = NULL;
+
+    TPM2B_NAME *nameKeySign = NULL;
+    TPM2B_NAME *keyQualifiedName = NULL;
+    TPMT_SIGNATURE *signature = NULL;
+
+    TPMT_TK_VERIFIED *validation = NULL;
+
     /*
      * 1. Create Primary. This primary will be used as signing key.
      */
@@ -110,11 +121,6 @@
     r = Esys_TR_SetAuth(esys_context, ESYS_TR_RH_OWNER, &authValue);
     goto_if_error(r, "Error: TR_SetAuth", error);
 
-    TPM2B_PUBLIC *outPublic;
-    TPM2B_CREATION_DATA *creationData;
-    TPM2B_DIGEST *creationHash;
-    TPMT_TK_CREATION *creationTicket;
-
     r = Esys_CreatePrimary(esys_context, ESYS_TR_RH_OWNER, ESYS_TR_PASSWORD,
                            ESYS_TR_NONE, ESYS_TR_NONE,
                            &inSensitivePrimary, &inPublic,
@@ -122,9 +128,10 @@
                            &outPublic, &creationData, &creationHash,
                            &creationTicket);
     goto_if_error(r, "Error esys create primary", error);
-
-    TPM2B_NAME *nameKeySign;
-    TPM2B_NAME *keyQualifiedName;
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
 
     r = Esys_ReadPublic(esys_context,
                         primaryHandle,
@@ -143,7 +150,6 @@
         .hierarchy = TPM2_RH_OWNER,
         .digest = {0}
     };
-    TPMT_SIGNATURE *signature;
     /* SHA1 digest for PCR register with zeros */
     TPM2B_DIGEST pcr_digest_zero = {
         .size = 20,
@@ -167,8 +173,6 @@
         &signature);
     goto_if_error(r, "Error: Sign", error);
 
-    TPMT_TK_VERIFIED *validation;
-
     r = Esys_VerifySignature(
         esys_context,
         primaryHandle,
@@ -183,6 +187,12 @@
     r = Esys_FlushContext(esys_context, primaryHandle);
     goto_if_error(r, "Error: FlushContext", error);
 
+    Esys_Free(outPublic);
+
+    Esys_Free(nameKeySign);
+    Esys_Free(keyQualifiedName);
+    Esys_Free(signature);
+    Esys_Free(validation);
     return EXIT_SUCCESS;
 
  error:
@@ -193,6 +203,15 @@
         }
     }
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+
+    Esys_Free(nameKeySign);
+    Esys_Free(keyQualifiedName);
+    Esys_Free(signature);
+    Esys_Free(validation);
     return EXIT_FAILURE;
 }
 
diff --git a/test/integration/esys-zgen-2phase.int.c b/test/integration/esys-zgen-2phase.int.c
index cd7baf8..5283df2 100644
--- a/test/integration/esys-zgen-2phase.int.c
+++ b/test/integration/esys-zgen-2phase.int.c
@@ -56,6 +56,14 @@
                    11, 12, 13, 14, 15, 16, 17, 18, 19, 20}
     };
 
+    TPM2B_PUBLIC *outPublic = NULL;
+    TPM2B_CREATION_DATA *creationData = NULL;
+    TPM2B_DIGEST *creationHash = NULL;
+    TPMT_TK_CREATION *creationTicket = NULL;
+    TPM2B_ECC_POINT *outZ1 = NULL;
+    TPM2B_ECC_POINT *outZ2 = NULL;
+    TPM2B_ECC_POINT *Q = NULL;
+
     memset(&sessionAttributes, 0, sizeof sessionAttributes);
 
     r = Esys_StartAuthSession(esys_context, ESYS_TR_NONE, ESYS_TR_NONE,
@@ -133,11 +141,6 @@
     r = Esys_TR_SetAuth(esys_context, ESYS_TR_RH_OWNER, &authValue);
     goto_if_error(r, "Error: TR_SetAuth", error);
 
-    TPM2B_PUBLIC *outPublic;
-    TPM2B_CREATION_DATA *creationData;
-    TPM2B_DIGEST *creationHash;
-    TPMT_TK_CREATION *creationTicket;
-
     r = Esys_CreatePrimary(esys_context, ESYS_TR_RH_OWNER, session,
                            ESYS_TR_NONE, ESYS_TR_NONE, &inSensitive, &inPublic,
                            &outsideInfo, &creationPCR, &eccHandle,
@@ -146,7 +149,6 @@
     goto_if_error(r, "Error esapi create primary", error);
 
     TPMI_ECC_CURVE curveID = TPM2_ECC_NIST_P256;
-    TPM2B_ECC_POINT *Q;
     UINT16 counter;
 
     r = Esys_EC_Ephemeral(
@@ -172,10 +174,8 @@
         .size = 0,
         .point = outPublic->publicArea.unique.ecc
     };
-    TPM2B_ECC_POINT inQeB = *Q;
     TPMI_ECC_KEY_EXCHANGE inScheme = TPM2_ALG_ECDH;
-    TPM2B_ECC_POINT *outZ1;
-    TPM2B_ECC_POINT *outZ2;
+    TPM2B_ECC_POINT inQeB = *Q;
 
     r = Esys_ZGen_2Phase(
         esys_context,
@@ -206,6 +206,13 @@
     r = Esys_FlushContext(esys_context, session);
     goto_if_error(r, "Flushing context", error);
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+    Esys_Free(outZ1);
+    Esys_Free(outZ2);
+    Esys_Free(Q);
     return EXIT_SUCCESS;
 
  error:
@@ -223,6 +230,13 @@
         }
     }
 
+    Esys_Free(outPublic);
+    Esys_Free(creationData);
+    Esys_Free(creationHash);
+    Esys_Free(creationTicket);
+    Esys_Free(outZ1);
+    Esys_Free(outZ2);
+    Esys_Free(Q);
     return failure_return;
 }
 
diff --git a/test/integration/fapi-data-crypt-rsa.int.c b/test/integration/fapi-data-crypt-rsa.int.c
new file mode 100644
index 0000000..1a2ce99
--- /dev/null
+++ b/test/integration/fapi-data-crypt-rsa.int.c
@@ -0,0 +1,268 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ *******************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <openssl/evp.h>
+#include <openssl/rsa.h>
+#include <openssl/engine.h>
+#include <openssl/pem.h>
+
+#include "tss2_fapi.h"
+
+#include "test-fapi.h"
+
+#define LOGMODULE test
+#include "util/log.h"
+#include "util/aux_util.h"
+
+/** Test the FAPI functions for key creation and usage.
+ *
+ * Tested FAPI commands:
+ *  - Fapi_Provision()
+ *  - Fapi_CreateKey()
+ *  - Fapi_Sign(9
+ *  - Fapi_Delete(9
+ *
+ * @param[in,out] context The FAPI_CONTEXT.
+ * @retval EXIT_FAILURE
+ * @retval EXIT_SUCCESS
+ */
+
+#define SIZE 2000
+
+const char *priv_pem =
+    "-----BEGIN PRIVATE KEY-----\n"
+    "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCgYvoisJIDOeYg\n"
+    "jMF6ywiZbu085TLvy5ZMhq5vfYqdgefvwpemutnfKSnpYOs5B4yO/gAD7XiYluDv\n"
+    "tqlVhfISeQV04xrWGzNImenpwm/HsgueAu8VTHNtWSL96G+BLedGTrs2NqX6cxN7\n"
+    "yGl7dQpB5X8iP4XSvpjP3Vb7gs+adwCJR6xFkt60jYFmwrAdhEzOeakhimi5rU21\n"
+    "LxCkRdEyaxS57X15L9dEA+aYJ+dvkFfZOfTqIKmTrA75F8yj161xflwtIC4hgRBg\n"
+    "K9Xb/RdN8TDrTu+20E3RjngutU4qejW9Fd3mzHJGV8HRYvjYXhUblN9wmjm7Veru\n"
+    "T2b0rnvzAgMBAAECggEBAIwHvoJ5DRJ6A50Zp3dROxHTEphfOEi6xF/OGxBGWLbK\n"
+    "C7l+eS9d5gj8BJa5QsXI/IR/6X2EYQ1AdeV04oVD7CUKuqPiALU8jFrv3pV0aGm+\n"
+    "3nu37gv3crPe5jkvLeNoM4tkA/oCXom63SDuyoG6nxkHiSdatLlaJUse4em3vRAL\n"
+    "QivziZIMyswcleMe0xAoMi7LO+nUFFxBS8/xGya0vsU0dsMQEl1SRITv1VCXmPQD\n"
+    "T4dEI4+1cufv6Ax0EDbFKmnjyiGTjOeQKrGIqETUSQolbg5PgL1XZehaaxM822OY\n"
+    "Qpnp5T0XhUEmVrOb2Wrboj+dC/2tgAN/fWXjAAxnm2ECgYEA02UTZuZ+QnD6tqo3\n"
+    "/y3n5kaM9uA2mdOIqgECI9psGF1IBIC/iP2diKyuvmQL8hzymComb5YzZl3TOAga\n"
+    "WHQYbIeU3JhnYTG75/Dv5Zh32H4NjkIJHT2/8LUM25Ove9u6QAniVgIQpBZ47LjX\n"
+    "9jHjTYCW5n79qNSfu0egYJUvypECgYEAwjqWzzEINqnX/xIVCoB4XpuDuSdkM0JW\n"
+    "MZDIH9xHjZPp07/5XYEoITylk6Zwbh+djvWDNP4gzPtuK26VsqrNxoWMsFZeXn6U\n"
+    "xSOYL2UNCZiOgchdZCOr+6r8LRUuo8xHjbawVoJVK1+tZ2WsR3ilt3Gw34O8Z5ep\n"
+    "f4v7GOXw+EMCgYAUHjFrgJIRhqkFi0uK+HZyXtJ5iDsKBqyh6Tin6tiQtQfujcYs\n"
+    "pl5ArJZwvhq47vJTcud3hSbdHh7E3ViMhHfylDChkct833vPhgl+ozT8oHpvyG8P\n"
+    "nlnO8ZwIpZR0yCOAhrBImSe2RgE6HhlHb9X/ATbbNsizMZEGBLoJlwkWUQKBgQCy\n"
+    "4U7fh2LvJUF+82JZh7RUPZn1Pmg0JVZI0/TcEv37UEy77kR1b2xMIBTGhTVq1sc/\n"
+    "ULIEbkA7SR1P9sr7//8AZSMLjJ/hG2dcoMmabNCzE8O7l5MblRbh87nIs4d+57bG\n"
+    "t4h0RBi4l6eWYLdoI59L8fNaB3PPXIiIpZ0eczeZDQKBgQC2vuFYpUZqDb9CaJsn\n"
+    "Luee6P6n5v3ZBTAT4E+GG1kWS28BiebcCuLKNAY4ZtLo08ozaTWcMxooOTeka2ux\n"
+    "fQDE4M/LTNpam8QOJ2hqECF5a0uBYNcbmaGtfA9KwIgwCZZYuwb5IDq/DRPuR690\n"
+    "i8Kp6jR2wY0suObmZHKvbCB1Dw==\n"
+    "-----END PRIVATE KEY-----\n";
+
+const char *pub_pem =
+    "-----BEGIN PUBLIC KEY-----\n"
+    "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoGL6IrCSAznmIIzBessI\n"
+    "mW7tPOUy78uWTIaub32KnYHn78KXprrZ3ykp6WDrOQeMjv4AA+14mJbg77apVYXy\n"
+    "EnkFdOMa1hszSJnp6cJvx7ILngLvFUxzbVki/ehvgS3nRk67Njal+nMTe8hpe3UK\n"
+    "QeV/Ij+F0r6Yz91W+4LPmncAiUesRZLetI2BZsKwHYRMznmpIYpoua1NtS8QpEXR\n"
+    "MmsUue19eS/XRAPmmCfnb5BX2Tn06iCpk6wO+RfMo9etcX5cLSAuIYEQYCvV2/0X\n"
+    "TfEw607vttBN0Y54LrVOKno1vRXd5sxyRlfB0WL42F4VG5TfcJo5u1Xq7k9m9K57\n"
+    "8wIDAQAB\n"
+    "-----END PUBLIC KEY-----\n";
+
+#define RSA_SIG_SCHEME RSA_PKCS1_PSS_PADDING
+
+char *userDataTest = "test";
+
+#define chknull(X) if (!X) { LOG_ERROR(str(X) "should not be null"); \
+                             r = TSS2_FAPI_RC_GENERAL_FAILURE; \
+                             goto error_cleanup; }
+
+TSS2_RC
+signatureCallback(
+    FAPI_CONTEXT  *context,
+    char    const *description,
+    char    const *publicKey,
+    char    const *publicKeyHint,
+    uint32_t       hashAlg,
+    uint8_t const *dataToSign,
+    size_t         dataToSignSize,
+    uint8_t      **signature,
+    size_t        *signatureSize,
+    void          *userData)
+{
+    (void)description;
+    (void)publicKey;
+    (void)publicKeyHint;
+
+    if (userData != userDataTest) {
+        LOG_ERROR("userData is not correct, %p != %p", userData, userDataTest);
+        return TSS2_FAPI_RC_GENERAL_FAILURE;
+    }
+
+    if (hashAlg != TPM2_ALG_SHA1) {
+        LOG_ERROR("hashAlg is not correct, %u != %u", hashAlg, TPM2_ALG_SHA1);
+        return TSS2_FAPI_RC_GENERAL_FAILURE;
+    }
+
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    EVP_PKEY *priv_key = NULL;
+    BIO *bufio = NULL;
+    EVP_MD_CTX *mdctx =NULL;
+    EVP_PKEY_CTX *pctx = NULL;
+
+    const EVP_MD *ossl_hash = EVP_sha1();
+    chknull(ossl_hash);
+
+    LOGBLOB_DEBUG(dataToSign, dataToSignSize, "Data to be signed");
+
+    bufio = BIO_new_mem_buf((void *)priv_pem, strlen(priv_pem));
+    priv_key = PEM_read_bio_PrivateKey(bufio, NULL, NULL, NULL);
+    chknull(priv_key);
+
+    mdctx = EVP_MD_CTX_create();
+    chknull(mdctx);
+
+    if (1 != EVP_DigestSignInit(mdctx, &pctx, NULL, NULL, priv_key)) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "OSSL digest sign init.",
+                   error_cleanup);
+    }
+    if (EVP_PKEY_type(EVP_PKEY_id(priv_key)) == EVP_PKEY_RSA) {
+        int signing_scheme = RSA_SIG_SCHEME;
+        if (1 != EVP_PKEY_CTX_set_rsa_padding(pctx, signing_scheme)) {
+            goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "OSSL set RSA padding.",
+                       error_cleanup);
+        }
+    }
+    if (1 != EVP_DigestSignInit(mdctx, &pctx, ossl_hash, NULL, priv_key)) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "OSSL sign init.",
+                   error_cleanup);
+    }
+    if (1 != EVP_DigestSignUpdate(mdctx, dataToSign, dataToSignSize)) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "OSSL sign update.",
+                   error_cleanup);
+    }
+    if (1 != EVP_DigestSignFinal(mdctx, NULL, signatureSize)) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "OSSL sign final.",
+                   error_cleanup);
+    }
+    *signature = malloc(*signatureSize);
+    chknull(*signature);
+    if (1 != EVP_DigestSignFinal(mdctx, *signature, signatureSize)) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "OSSL sign final.",
+                   error_cleanup);
+    }
+error_cleanup:
+    if (priv_key)
+        EVP_PKEY_free(priv_key);
+    if (mdctx)
+        EVP_MD_CTX_destroy(mdctx);
+    if (bufio)
+        BIO_free(bufio);
+    return r;
+}
+
+int
+test_fapi_data_crypt_rsa(FAPI_CONTEXT *context)
+{
+
+    TSS2_RC r;
+    const char *policy_name = "/policy/pol_signed";
+    const char *policy_file = TOP_SOURCEDIR "/test/data/fapi/policy/pol_signed.json";
+    FILE *stream = NULL;
+    char *json_policy = NULL;
+    long policy_size;
+    char *cipherText = NULL;
+
+    r = Fapi_Provision(context, NULL, NULL, NULL);
+    goto_if_error(r, "Error Fapi_Provision", error);
+
+    r = pcr_reset(context, 16);
+    goto_if_error(r, "Error pcr_reset", error);
+
+    stream = fopen(policy_file, "r");
+    if (!stream) {
+        LOG_ERROR("File %s does not exist", policy_file);
+        goto error;
+    }
+    fseek(stream, 0L, SEEK_END);
+    policy_size = ftell(stream);
+    fclose(stream);
+    json_policy = malloc(policy_size + 1);
+    goto_if_null(json_policy,
+            "Could not allocate memory for the JSON policy",
+            TSS2_FAPI_RC_MEMORY, error);
+    stream = fopen(policy_file, "r");
+    ssize_t ret = read(fileno(stream), json_policy, policy_size);
+    if (ret != policy_size) {
+        LOG_ERROR("IO error %s.", policy_file);
+        goto error;
+    }
+    json_policy[policy_size] = '\0';
+
+    r = Fapi_Import(context, policy_name, json_policy);
+    goto_if_error(r, "Error Fapi_Import", error);
+
+    r = Fapi_CreateKey(context, "HS/SRK/myRsaCryptKey", "restricted,decrypt",
+                       policy_name, NULL);
+    goto_if_error(r, "Error Fapi_CreateKey", error);
+
+    uint8_t  plainText[SIZE];
+    int i;
+
+    for (i = 0; i < SIZE; i++)
+        plainText[i] = i % 256;
+
+    r = Fapi_SetSignCB(context, signatureCallback, userDataTest);
+    goto_if_error(r, "Error SetPolicySignatureCallback", error);
+
+    r = Fapi_Encrypt(context, "HS/SRK/myRsaCryptKey", policy_name, &plainText[0],
+                     SIZE, &cipherText);
+    goto_if_error(r, "Error Fapi_Encrypt", error);
+
+    uint8_t *plainText2 = NULL;
+    size_t plainText2_size = 0;
+
+    fprintf(stderr, "\n%s\n", cipherText);
+
+    r = Fapi_Decrypt(context, cipherText, &plainText2, &plainText2_size);
+    goto_if_error(r, "Error Fapi_Encrypt", error);
+
+    if (plainText2_size != SIZE ||
+            memcmp(plainText, plainText2, plainText2_size) != 0) {
+        LOG_ERROR("Error: decrypted text not  equal to origin");
+        goto error;
+    }
+
+    Fapi_Free(cipherText);
+    Fapi_Free(plainText2);
+    Fapi_Free(json_policy);
+    Fapi_Delete(context, "P_RSA");
+
+    return EXIT_SUCCESS;
+
+error:
+    Fapi_Free(cipherText);
+    Fapi_Free(json_policy);
+    Fapi_Delete(context, "P_RSA");
+
+    return EXIT_FAILURE;
+}
+
+int
+test_invoke_fapi(FAPI_CONTEXT *fapi_context)
+{
+    return test_fapi_data_crypt_rsa(fapi_context);
+}
diff --git a/test/integration/fapi-ext-public-key.int.c b/test/integration/fapi-ext-public-key.int.c
new file mode 100644
index 0000000..8cfc16c
--- /dev/null
+++ b/test/integration/fapi-ext-public-key.int.c
@@ -0,0 +1,195 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ *******************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <openssl/evp.h>
+#include <openssl/aes.h>
+#include <openssl/rsa.h>
+#include <openssl/engine.h>
+#include <openssl/pem.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "tss2_fapi.h"
+
+#define LOGMODULE test
+#include "util/log.h"
+#include "util/aux_util.h"
+
+/** Test the FAPI functions to store and use an external public key.
+ *
+ * Tested FAPI commands:
+ *  - Fapi_Provision()
+ *  - Fapi_Import()
+ *  - Fapi_Key_Verifysignature()
+ *  - Fapi_Delete()
+ *  - Fapi_GetCertificate)
+ *  - Fapi_SetCertificate)
+ *
+ * @param[in,out] context The FAPI_CONTEXT.
+ * @retval EXIT_FAILURE
+ * @retval EXIT_SUCCESS
+ */
+int
+test_fapi_ext_public_key(FAPI_CONTEXT *context)
+{
+
+    TSS2_RC r;
+    BIO *bufio = NULL;
+
+    EVP_PKEY *evp_key = NULL;
+    RSA *rsa_key = NULL;
+
+    const char *pub_pem =
+        "-----BEGIN PUBLIC KEY-----\n"
+        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoGL6IrCSAznmIIzBessI\n"
+        "mW7tPOUy78uWTIaub32KnYHn78KXprrZ3ykp6WDrOQeMjv4AA+14mJbg77apVYXy\n"
+        "EnkFdOMa1hszSJnp6cJvx7ILngLvFUxzbVki/ehvgS3nRk67Njal+nMTe8hpe3UK\n"
+        "QeV/Ij+F0r6Yz91W+4LPmncAiUesRZLetI2BZsKwHYRMznmpIYpoua1NtS8QpEXR\n"
+        "MmsUue19eS/XRAPmmCfnb5BX2Tn06iCpk6wO+RfMo9etcX5cLSAuIYEQYCvV2/0X\n"
+        "TfEw607vttBN0Y54LrVOKno1vRXd5sxyRlfB0WL42F4VG5TfcJo5u1Xq7k9m9K57\n"
+        "8wIDAQAB\n"
+        "-----END PUBLIC KEY-----\n";
+
+    const char *priv_pem =
+        "-----BEGIN PRIVATE KEY-----\n"
+        "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCgYvoisJIDOeYg\n"
+        "jMF6ywiZbu085TLvy5ZMhq5vfYqdgefvwpemutnfKSnpYOs5B4yO/gAD7XiYluDv\n"
+        "tqlVhfISeQV04xrWGzNImenpwm/HsgueAu8VTHNtWSL96G+BLedGTrs2NqX6cxN7\n"
+        "yGl7dQpB5X8iP4XSvpjP3Vb7gs+adwCJR6xFkt60jYFmwrAdhEzOeakhimi5rU21\n"
+        "LxCkRdEyaxS57X15L9dEA+aYJ+dvkFfZOfTqIKmTrA75F8yj161xflwtIC4hgRBg\n"
+        "K9Xb/RdN8TDrTu+20E3RjngutU4qejW9Fd3mzHJGV8HRYvjYXhUblN9wmjm7Veru\n"
+        "T2b0rnvzAgMBAAECggEBAIwHvoJ5DRJ6A50Zp3dROxHTEphfOEi6xF/OGxBGWLbK\n"
+        "C7l+eS9d5gj8BJa5QsXI/IR/6X2EYQ1AdeV04oVD7CUKuqPiALU8jFrv3pV0aGm+\n"
+        "3nu37gv3crPe5jkvLeNoM4tkA/oCXom63SDuyoG6nxkHiSdatLlaJUse4em3vRAL\n"
+        "QivziZIMyswcleMe0xAoMi7LO+nUFFxBS8/xGya0vsU0dsMQEl1SRITv1VCXmPQD\n"
+        "T4dEI4+1cufv6Ax0EDbFKmnjyiGTjOeQKrGIqETUSQolbg5PgL1XZehaaxM822OY\n"
+        "Qpnp5T0XhUEmVrOb2Wrboj+dC/2tgAN/fWXjAAxnm2ECgYEA02UTZuZ+QnD6tqo3\n"
+        "/y3n5kaM9uA2mdOIqgECI9psGF1IBIC/iP2diKyuvmQL8hzymComb5YzZl3TOAga\n"
+        "WHQYbIeU3JhnYTG75/Dv5Zh32H4NjkIJHT2/8LUM25Ove9u6QAniVgIQpBZ47LjX\n"
+        "9jHjTYCW5n79qNSfu0egYJUvypECgYEAwjqWzzEINqnX/xIVCoB4XpuDuSdkM0JW\n"
+        "MZDIH9xHjZPp07/5XYEoITylk6Zwbh+djvWDNP4gzPtuK26VsqrNxoWMsFZeXn6U\n"
+        "xSOYL2UNCZiOgchdZCOr+6r8LRUuo8xHjbawVoJVK1+tZ2WsR3ilt3Gw34O8Z5ep\n"
+        "f4v7GOXw+EMCgYAUHjFrgJIRhqkFi0uK+HZyXtJ5iDsKBqyh6Tin6tiQtQfujcYs\n"
+        "pl5ArJZwvhq47vJTcud3hSbdHh7E3ViMhHfylDChkct833vPhgl+ozT8oHpvyG8P\n"
+        "nlnO8ZwIpZR0yCOAhrBImSe2RgE6HhlHb9X/ATbbNsizMZEGBLoJlwkWUQKBgQCy\n"
+        "4U7fh2LvJUF+82JZh7RUPZn1Pmg0JVZI0/TcEv37UEy77kR1b2xMIBTGhTVq1sc/\n"
+        "ULIEbkA7SR1P9sr7//8AZSMLjJ/hG2dcoMmabNCzE8O7l5MblRbh87nIs4d+57bG\n"
+        "t4h0RBi4l6eWYLdoI59L8fNaB3PPXIiIpZ0eczeZDQKBgQC2vuFYpUZqDb9CaJsn\n"
+        "Luee6P6n5v3ZBTAT4E+GG1kWS28BiebcCuLKNAY4ZtLo08ozaTWcMxooOTeka2ux\n"
+        "fQDE4M/LTNpam8QOJ2hqECF5a0uBYNcbmaGtfA9KwIgwCZZYuwb5IDq/DRPuR690\n"
+        "i8Kp6jR2wY0suObmZHKvbCB1Dw==\n"
+        "-----END PRIVATE KEY-----\n";
+
+    const char *cert =
+        "-----BEGIN CERTIFICATE-----\n"
+        "MIIDBjCCAe4CCQDcvXBOEVM0UTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJE\n"
+        "RTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0\n"
+        "cyBQdHkgTHRkMB4XDTE5MDIyODEwNDkyM1oXDTM1MDgyNzEwNDkyM1owRTELMAkG\n"
+        "A1UEBhMCREUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0\n"
+        "IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\n"
+        "AKBi+iKwkgM55iCMwXrLCJlu7TzlMu/LlkyGrm99ip2B5+/Cl6a62d8pKelg6zkH\n"
+        "jI7+AAPteJiW4O+2qVWF8hJ5BXTjGtYbM0iZ6enCb8eyC54C7xVMc21ZIv3ob4Et\n"
+        "50ZOuzY2pfpzE3vIaXt1CkHlfyI/hdK+mM/dVvuCz5p3AIlHrEWS3rSNgWbCsB2E\n"
+        "TM55qSGKaLmtTbUvEKRF0TJrFLntfXkv10QD5pgn52+QV9k59OogqZOsDvkXzKPX\n"
+        "rXF+XC0gLiGBEGAr1dv9F03xMOtO77bQTdGOeC61Tip6Nb0V3ebMckZXwdFi+Nhe\n"
+        "FRuU33CaObtV6u5PZvSue/MCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAcamUPe8I\n"
+        "nMOHcv9x5lVN1joihVRmKc0QqNLFc6XpJY8+U5rGkZvOcDe9Da8L97wDNXpKmU/q\n"
+        "pprj3rT8l3v0Z5xs8Vdr8lxS6T5NhqQV0UCsn1x14gZJcE48y9/LazYi6Zcar+BX\n"
+        "Am4vewAV3HmQ8X2EctsRhXe4wlAq4slIfEWaaofa8ai7BzO9KwpMLsGPWoNetkB9\n"
+        "19+SFt0lFFOj/6vDw5pCpSd1nQlo1ug69mJYSX/wcGkV4t4LfGhV8jRPDsGs6I5n\n"
+        "ETHSN5KV1XCPYJmRCjFY7sIt1x4zN7JJRO9DVw+YheIlduVfkBiF+GlQgLlFTjrJ\n"
+        "VrpSGMIFSu301A==\n"
+        "-----END CERTIFICATE-----\n";
+
+    char *cert2 = NULL;
+    char *path_list = NULL;
+
+    r = Fapi_Import(context, "myExtPubKey", pub_pem);
+    goto_if_error(r, "Error Fapi_Import", error);
+
+    bufio = BIO_new_mem_buf((void *)priv_pem, strlen(priv_pem));
+    evp_key = PEM_read_bio_PrivateKey(bufio, NULL, NULL, NULL);
+    rsa_key  = EVP_PKEY_get1_RSA(evp_key);
+
+
+    if (!bufio || !evp_key || !rsa_key) {
+        LOG_ERROR("Generation of test key failed.");
+        goto error;
+    }
+
+    uint8_t digest[20] = {
+        0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, 0xba, 0x3e,
+        0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c, 0x9c, 0xd0, 0xd8, 0x9d
+    };
+    uint8_t signature[256];
+    unsigned int  signatureLength = 256;
+
+    if (!RSA_sign(NID_sha1, digest, 20, signature, &signatureLength, rsa_key)) {
+        LOG_ERROR("Test RSA_sign failed.");
+        goto error;
+    }
+
+    r = Fapi_VerifySignature(context, "/ext/myExtPubKey", digest, 20,
+                             signature, 256);
+    goto_if_error(r, "Error Fapi_VerifySignature", error);
+
+    r = Fapi_SetCertificate(context, "/ext/myExtPubKey", cert);
+    goto_if_error(r, "Error Fapi_SetCertificate", error);
+
+    r = Fapi_GetCertificate(context, "/ext/myExtPubKey", &cert2);
+    goto_if_error(r, "Error Fapi_SetCertificate", error);
+
+    if (strcmp(cert, cert2) != 0) {
+        goto_if_error(r, "Different certificates", error);
+    }
+
+    r = Fapi_List(context, "", &path_list);
+    goto_if_error(r, "Error Fapi_Delete", error);
+
+    fprintf(stderr, "\nPathList:\n%s\n", path_list);
+
+    r = Fapi_Delete(context, "/ext");
+    goto_if_error(r, "Error Fapi_Delete", error);
+    if (bufio) {
+        BIO_free(bufio);
+    }
+    if (evp_key) {
+        EVP_PKEY_free(evp_key);
+    }
+    if (rsa_key) {
+        RSA_free(rsa_key);
+    }
+    SAFE_FREE(path_list);
+    SAFE_FREE(cert2);
+    return EXIT_SUCCESS;
+
+error:
+    Fapi_Delete(context, "/");
+    if (bufio) {
+        BIO_free(bufio);
+    }
+    if (evp_key) {
+        EVP_PKEY_free(evp_key);
+    }
+    if (rsa_key) {
+        RSA_free(rsa_key);
+    }
+    SAFE_FREE(path_list);
+    SAFE_FREE(cert2);
+    return EXIT_FAILURE;
+}
+
+int
+test_invoke_fapi(FAPI_CONTEXT *fapi_context)
+{
+    return test_fapi_ext_public_key(fapi_context);
+}
diff --git a/test/integration/fapi-get-random.int.c b/test/integration/fapi-get-random.int.c
new file mode 100644
index 0000000..12ff602
--- /dev/null
+++ b/test/integration/fapi-get-random.int.c
@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ *******************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#include "tss2_fapi.h"
+
+#define LOGMODULE test
+#include "util/log.h"
+#include "util/aux_util.h"
+
+/** Test the FAPI function FAPI_GetRandom.
+ *
+ * Tested FAPI commands:
+ *  - Fapi_Provision()
+ *  - Fapi_GetRandom()
+ *
+ * @param[in,out] context The FAPI_CONTEXT.
+ * @retval EXIT_FAILURE
+ * @retval EXIT_SUCCESS
+ */
+int
+test_fapi_get_random(FAPI_CONTEXT *context)
+{
+
+    TSS2_RC r;
+    /* Ensure that more than one call of Esys_GetRandom is necessary */
+    size_t  bytesRequested = sizeof(TPMU_HA) + 10;
+    uint8_t *randomBytes;
+
+    r = Fapi_Provision(context, NULL, NULL, NULL);
+    goto_if_error(r, "Error Fapi_Provision", error);
+
+    r = Fapi_GetRandom(context, bytesRequested, &randomBytes);
+    Fapi_Free(randomBytes);
+    if (r != TPM2_RC_SUCCESS) {
+        LOG_ERROR("GetRandom FAILED! Response Code : 0x%x", r);
+        goto error;
+    }
+
+    /* Cleanup */
+    r = Fapi_Delete(context, "/HS/SRK");
+    goto_if_error(r, "Error Fapi_Delete", error);
+
+    return TSS2_RC_SUCCESS;
+
+error:
+    Fapi_Delete(context, "/HS/SRK");
+    return EXIT_FAILURE;
+}
+
+int
+test_invoke_fapi(FAPI_CONTEXT *fapi_context)
+{
+    return test_fapi_get_random(fapi_context);
+}
diff --git a/test/integration/fapi-info.int.c b/test/integration/fapi-info.int.c
new file mode 100644
index 0000000..b9ccc49
--- /dev/null
+++ b/test/integration/fapi-info.int.c
@@ -0,0 +1,61 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ *******************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#include "tss2_fapi.h"
+
+#define LOGMODULE test
+#include "util/log.h"
+#include "util/aux_util.h"
+
+/** Test the FAPI functions for quote commands.
+ *
+ * Tested FAPI commands:
+ *  - Fapi_Provision()
+ *  - Fapi_GetTPMInfo()
+ *
+ * @param[in,out] context The FAPI_CONTEXT.
+ * @retval EXIT_FAILURE
+ * @retval EXIT_SUCCESS
+ */
+int
+test_fapi_info(FAPI_CONTEXT *context)
+{
+
+    TSS2_RC r;
+    char *info = NULL;
+
+    r = Fapi_Provision(context, NULL, NULL, NULL);
+    goto_if_error(r, "Error Fapi_Provision", error);
+
+    r = Fapi_GetInfo(context, &info);
+    goto_if_error(r, "Error Fapi_Provision", error);
+
+    LOG_INFO("%s", info);
+
+    /* Cleanup */
+    r = Fapi_Delete(context, "/HS/SRK");
+    goto_if_error(r, "Error Fapi_Delete", error);
+
+    SAFE_FREE(info);
+    return EXIT_SUCCESS;
+
+error:
+    Fapi_Delete(context, "/HS/SRK");
+    SAFE_FREE(info);
+    return EXIT_FAILURE;
+}
+
+int
+test_invoke_fapi(FAPI_CONTEXT *fapi_context)
+{
+    return test_fapi_info(fapi_context);
+}
diff --git a/test/integration/fapi-key-change-auth.int.c b/test/integration/fapi-key-change-auth.int.c
new file mode 100644
index 0000000..9bcdc44
--- /dev/null
+++ b/test/integration/fapi-key-change-auth.int.c
@@ -0,0 +1,107 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ *******************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "tss2_fapi.h"
+
+#define LOGMODULE test
+#include "util/log.h"
+#include "util/aux_util.h"
+
+#define PASSWORD "abc"
+
+TSS2_RC
+auth_callback(
+    FAPI_CONTEXT *context,
+    char const *description,
+    char **auth,
+    void *userData)
+{
+    (void)description;
+    (void)userData;
+    *auth = strdup(PASSWORD);
+    return_if_null(*auth, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+    return TSS2_RC_SUCCESS;
+}
+
+
+/** Test the FAPI function for changing the key authorization.
+ *
+ * The setting of the authorization callback and usage of the
+ * key with Fapi_Sign afterwards is also tested.
+ *
+ * Tested FAPI commands:
+ *  - Fapi_Provision()
+ *  - Fapi_CreateKey()
+ *  - Fapi_Sign()
+ *  - Fapi_ChangeAuth()
+ *  - Fapi_Delete()
+ *  - Fapi_List()
+ *
+ * @param[in,out] context The FAPI_CONTEXT.
+ * @retval EXIT_FAILURE
+ * @retval EXIT_SUCCESS
+ */
+int
+test_fapi_change_key_auth(FAPI_CONTEXT *context)
+{
+
+    TSS2_RC r;
+    uint8_t *signature = NULL;
+    char    *publicKey = NULL;
+
+    r = Fapi_Provision(context, NULL, NULL, NULL);
+
+    goto_if_error(r, "Error Fapi_Provision", error);
+
+    r = Fapi_CreateKey(context, "HS/SRK/mySignKey", "sign,noDa", "", NULL);
+    goto_if_error(r, "Error Fapi_CreateKey", error);
+    size_t signatureSize = 0;
+
+    TPM2B_DIGEST digest = {
+        .size = 20,
+        .buffer = {
+            0x67, 0x68, 0x03, 0x3e, 0x21, 0x64, 0x68, 0x24, 0x7b, 0xd0,
+            0x31, 0xa0, 0xa2, 0xd9, 0x87, 0x6d, 0x79, 0x81, 0x8f, 0x8f
+        }
+    };
+
+    r = Fapi_ChangeAuth(context, "HS/SRK/mySignKey", PASSWORD);
+    goto_if_error(r, "Error Fapi_Provision", error);
+
+    r = Fapi_SetAuthCB(context, auth_callback, "");
+    goto_if_error(r, "Error SetPolicyAuthCallback", error);
+
+    r = Fapi_Sign(context, "HS/SRK/mySignKey", NULL,
+                  &digest.buffer[0], digest.size, &signature, &signatureSize,
+                  &publicKey, NULL);
+    goto_if_error(r, "Error Fapi_Provision", error);
+
+    Fapi_Free(publicKey);
+
+    r = Fapi_Delete(context, "/HS/SRK");
+    goto_if_error(r, "Error Fapi_Delete", error);
+
+    SAFE_FREE(signature);
+    return EXIT_SUCCESS;
+
+error:
+    Fapi_Delete(context, "/HS/SRK");
+    SAFE_FREE(signature);
+    return EXIT_FAILURE;
+}
+
+int
+test_invoke_fapi(FAPI_CONTEXT *fapi_context)
+{
+    return test_fapi_change_key_auth(fapi_context);
+}
diff --git a/test/integration/fapi-key-create-ecc-sign.int.c b/test/integration/fapi-key-create-ecc-sign.int.c
new file mode 100644
index 0000000..3fa77bf
--- /dev/null
+++ b/test/integration/fapi-key-create-ecc-sign.int.c
@@ -0,0 +1,112 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ *******************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "tss2_fapi.h"
+
+#define LOGMODULE test
+#include "util/log.h"
+#include "util/aux_util.h"
+
+#ifdef FAPI_PASSWORD
+
+#define PASSWORD "abc"
+
+TSS2_RC
+auth_callback(
+    FAPI_CONTEXT *context,
+    char const *description,
+    char **auth,
+    void *userData)
+{
+    (void)description;
+    (void)userData;
+    *auth = strdup(PASSWORD);
+    return_if_null(*auth, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+    return TSS2_RC_SUCCESS;
+}
+#else /*FAPI_PASSWORD */
+#define PASSWORD NULL
+#endif /* FAPI_PASSWORD */
+
+#ifdef FAPI_DA
+#define SIGN_TEMPLATE  "sign"
+#else
+#define SIGN_TEMPLATE  "sign, noDa"
+#endif
+
+/** Test the FAPI functions for key creation and usage.
+ *
+ * Tested FAPI commands:
+ *  - Fapi_Provision()
+ *  - Fapi_CreateKey()
+ *  - Fapi_Sign()
+ *  - Fapi_Delete()
+ *  - Fapi_List()
+ *
+ * @param[in,out] context The FAPI_CONTEXT.
+ * @retval EXIT_FAILURE
+ * @retval EXIT_SUCCESS
+ */
+int
+test_fapi_key_create_ecc(FAPI_CONTEXT *context)
+{
+    TSS2_RC r;
+
+    uint8_t *signature = NULL;
+    char    *publicKey = NULL;
+
+    r = Fapi_Provision(context, NULL, NULL, NULL);
+    goto_if_error(r, "Error Fapi_Provision", error);
+
+    r = Fapi_CreateKey(context, "HS/SRK/mySignKey", SIGN_TEMPLATE, "",
+                       PASSWORD);
+    goto_if_error(r, "Error Fapi_CreateKey", error);
+    size_t signatureSize = 0;
+
+    TPM2B_DIGEST digest = {
+        .size = 20,
+        .buffer = {
+            0x67, 0x68, 0x03, 0x3e, 0x21, 0x64, 0x68, 0x24, 0x7b, 0xd0,
+            0x31, 0xa0, 0xa2, 0xd9, 0x87, 0x6d, 0x79, 0x81, 0x8f, 0x8f
+        }
+    };
+
+#ifdef FAPI_PASSWORD
+    r = Fapi_SetAuthCB(context, auth_callback, "");
+    goto_if_error(r, "Error SetPolicyAuthCallback", error);
+#endif
+
+    r = Fapi_Sign(context, "HS/SRK/mySignKey", NULL,
+                  &digest.buffer[0], digest.size, &signature, &signatureSize,
+                  &publicKey, NULL);
+    goto_if_error(r, "Error Fapi_Sign", error);
+
+    r = Fapi_Delete(context, "/HS/SRK");
+    goto_if_error(r, "Error Fapi_Delete", error);
+
+    SAFE_FREE(signature);
+    SAFE_FREE(publicKey);
+
+    return EXIT_SUCCESS;
+
+error:
+    SAFE_FREE(signature);
+    SAFE_FREE(publicKey);
+    return EXIT_FAILURE;
+}
+
+int
+test_invoke_fapi(FAPI_CONTEXT *fapi_context)
+{
+    return test_fapi_key_create_ecc(fapi_context);
+}
diff --git a/test/integration/fapi-key-create-policies-sign.int.c b/test/integration/fapi-key-create-policies-sign.int.c
new file mode 100644
index 0000000..fbc2b30
--- /dev/null
+++ b/test/integration/fapi-key-create-policies-sign.int.c
@@ -0,0 +1,193 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ *******************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "tss2_fapi.h"
+
+#define LOGMODULE test
+#include "util/log.h"
+#include "util/aux_util.h"
+#include "test-fapi.h"
+
+#ifdef TEST_PASSWORD
+#define PASSWORD "abc"
+#else
+#define PASSWORD ""
+#endif
+
+TSS2_RC
+auth_callback(
+    FAPI_CONTEXT *context,
+    char const *description,
+    char **auth,
+    void *userData)
+{
+    (void)description;
+    (void)userData;
+    *auth = strdup(PASSWORD);
+    return_if_null(*auth, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+    return TSS2_RC_SUCCESS;
+}
+#define SIGN_TEMPLATE  "sign,noDa"
+
+/** Test the FAPI PolicyPassword and PolicyAuthValue by usage of signing key.
+ *
+ * Which test case will be executed is determined by the compiler switches:
+ *   TEST_POLICY_PASSWORD and TEST_POLICY_AUTH_VALUE.
+ *
+ * Tested FAPI commands:
+ *  - Fapi_Provision()
+ *  - Fapi_CreateKey()
+ *  - Fapi_Sign()
+ *  - Fapi_Delete()
+ *
+ * @param[in,out] context The FAPI_CONTEXT.
+ * @retval EXIT_FAILURE
+ * @retval EXIT_SUCCESS
+ */
+int
+test_fapi_policy_password(FAPI_CONTEXT *context)
+{
+    TSS2_RC r;
+
+#if defined(TEST_POLICY_PASSWORD)
+    char *policy_name = "/policy/pol_password";
+    char *policy_file = FAPI_POLICIES "/policy/pol_password.json";
+#elif defined(TEST_POLICY_AUTH_VALUE)
+    char *policy_name = "/policy/pol_auth_value";
+    char *policy_file = FAPI_POLICIES "/policy/pol_auth_value.json";
+#elif defined(TEST_POLICY_LOCALITY)
+    char *policy_name = "/policy/pol_locality";
+    char *policy_file = FAPI_POLICIES "/policy/pol_locality.json";
+#elif defined(TEST_POLICY_PHYSICAL_PRESENCE)
+    char *policy_name = "/policy/pol_physical_presence";
+    char *policy_file = FAPI_POLICIES "/policy/pol_physical_presence.json";
+#elif defined(TEST_POLICY_COMMAND_CODE)
+    char *policy_name = "/policy/pol_command_code";
+    char *policy_file = FAPI_POLICIES "/policy/pol_command_code.json";
+#elif defined(TEST_POLICY_COUNTERTIMER)
+    char *policy_name = "/policy/pol_countertimer";
+    char *policy_file = FAPI_POLICIES "/policy/pol_countertimer.json";
+#else
+#error "Please define POLICY_PASSWORD,_AUTH_VALUE,_LOCALITY,_PHYSICAL_PRESENCE,_COMMAND_CODE,_COUNTERTIMER"
+#endif
+
+    FILE *stream = NULL;
+    uint8_t *signature =NULL;
+    char    *publicKey = NULL;
+    char *json_policy = NULL;
+    long policy_size;
+
+    r = Fapi_Provision(context, NULL, NULL, NULL);
+    goto_if_error(r, "Error Fapi_Provision", error);
+
+    r = pcr_reset(context, 16);
+    goto_if_error(r, "Error pcr_reset", error);
+
+    stream = fopen(policy_file, "r");
+    if (!stream) {
+        LOG_ERROR("File %s does not exist", policy_file);
+        goto error;
+    }
+    fseek(stream, 0L, SEEK_END);
+    policy_size = ftell(stream);
+    fclose(stream);
+    json_policy = malloc(policy_size + 1);
+    goto_if_null(json_policy,
+            "Could not allocate memory for the JSON policy",
+            TSS2_FAPI_RC_MEMORY, error);
+    stream = fopen(policy_file, "r");
+    ssize_t ret = read(fileno(stream), json_policy, policy_size);
+    if (ret != policy_size) {
+        LOG_ERROR("IO error %s.", policy_file);
+        goto error;
+    }
+    json_policy[policy_size] = '\0';
+
+    r = Fapi_Import(context, policy_name, json_policy);
+    goto_if_error(r, "Error Fapi_Import", error);
+
+    r = Fapi_CreateKey(context, "HS/SRK/mySignKey", SIGN_TEMPLATE,
+                       policy_name, PASSWORD);
+    goto_if_error(r, "Error Fapi_CreateKey", error);
+    size_t signatureSize = 0;
+
+    TPM2B_DIGEST digest = {
+        .size = 20,
+        .buffer = {
+            0x67, 0x68, 0x03, 0x3e, 0x21, 0x64, 0x68, 0x24, 0x7b, 0xd0,
+            0x31, 0xa0, 0xa2, 0xd9, 0x87, 0x6d, 0x79, 0x81, 0x8f, 0x8f
+        }
+    };
+
+    r = Fapi_SetAuthCB(context, auth_callback, "");
+    goto_if_error(r, "Error SetPolicyAuthCallback", error);
+
+    r = Fapi_Sign(context, "HS/SRK/mySignKey", NULL,
+                  &digest.buffer[0], digest.size, &signature, &signatureSize,
+                  &publicKey, NULL);
+
+#if defined(TEST_POLICY_PHYSICAL_PRESENCE)
+    if ((r & ~TPM2_RC_N_MASK) == TPM2_RC_PP) {
+        LOG_WARNING("Test requires physical presence.");
+        goto skip;
+    } else if (r == TPM2_RC_COMMAND_CODE) {
+        LOG_WARNING("Command not supported, probably PolicyPhysicalPresence");
+        goto skip;
+    }
+#endif /* TEST_POLICY_PHYSICAL_PRESENCE */
+    goto_if_error(r, "Error Fapi_Sign", error);
+
+    r = Fapi_Delete(context, "/HS/SRK/mySignKey");
+    goto_if_error(r, "Error Fapi_Delete", error);
+
+    r = Fapi_Delete(context, "/HS/SRK");
+    goto_if_error(r, "Error Fapi_Delete", error);
+
+    SAFE_FREE(json_policy);
+    SAFE_FREE(signature);
+    SAFE_FREE(publicKey);
+    return EXIT_SUCCESS;
+
+#if defined(TEST_POLICY_PHYSICAL_PRESENCE)
+    r = Fapi_Delete(context, "/HS/SRK/mySignKey");
+    goto_if_error(r, "Error Fapi_Delete", error);
+
+    r = Fapi_Delete(context, "/HS/SRK");
+    goto_if_error(r, "Error Fapi_Delete", error);
+
+skip:
+    Fapi_Delete(context, "/HS/SRK");
+    SAFE_FREE(json_policy);
+    SAFE_FREE(signature);
+    SAFE_FREE(publicKey);
+    return EXIT_SKIP;
+#endif /* TEST_POLICY_PHYSICAL_PRESENCE */
+
+error:
+    Fapi_Delete(context, "/HS/SRK");
+
+    SAFE_FREE(json_policy);
+    SAFE_FREE(signature);
+    SAFE_FREE(publicKey);
+    return EXIT_FAILURE;
+}
+
+int
+test_invoke_fapi(FAPI_CONTEXT *fapi_context)
+{
+    return test_fapi_policy_password(fapi_context);
+}
diff --git a/test/integration/fapi-key-create-policy-authorize-nv-sign.int.c b/test/integration/fapi-key-create-policy-authorize-nv-sign.int.c
new file mode 100644
index 0000000..d2673c5
--- /dev/null
+++ b/test/integration/fapi-key-create-policy-authorize-nv-sign.int.c
@@ -0,0 +1,214 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ *******************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+
+#include "tss2_fapi.h"
+#include "tss2_esys.h"
+#include "tss2_tcti.h"
+
+#include "test-fapi.h"
+
+#define LOGMODULE test
+#include "util/log.h"
+#include "util/aux_util.h"
+
+#define NV_SIZE 34
+#define PASSWORD ""
+#define SIGN_TEMPLATE  "sign"
+
+TSS2_RC
+check_tpm_cmd(FAPI_CONTEXT *context, TPM2_CC command_code)
+{
+    TSS2_RC r;
+    TSS2_TCTI_CONTEXT *tcti;
+    ESYS_CONTEXT *esys;
+    TPMS_CAPABILITY_DATA *cap_data;
+
+    r = Fapi_GetTcti(context, &tcti);
+    goto_if_error(r, "Error Fapi_GetTcti", error);
+
+    r = Esys_Initialize(&esys, tcti, NULL);
+    goto_if_error(r, "Error Fapi_GetTcti", error);
+
+    r = Esys_GetCapability(esys,
+                           ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
+                           TPM2_CAP_COMMANDS, command_code, 1, NULL, &cap_data);
+    Esys_Finalize(&esys);
+    return_if_error(r, "Error: GetCapabilities");
+
+    if ((cap_data->data.command.commandAttributes[0] & TPMA_CC_COMMANDINDEX_MASK) ==
+            command_code) {
+        free(cap_data);
+        return TSS2_RC_SUCCESS;
+    } else {
+        free(cap_data);
+        return TSS2_FAPI_RC_NOT_IMPLEMENTED;
+    }
+
+error:
+    return r;
+}
+
+TSS2_RC
+auth_callback(
+    FAPI_CONTEXT *context,
+    char const *description,
+    char **auth,
+    void *userData)
+{
+    (void)description;
+    (void)userData;
+    *auth = strdup(PASSWORD);
+    return_if_null(*auth, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+    return TSS2_RC_SUCCESS;
+}
+
+char *
+read_policy(FAPI_CONTEXT *context, char *policy_name)
+{
+    FILE *stream = NULL;
+    long policy_size;
+    char *json_policy = NULL;
+    char policy_file[1024];
+
+    if (snprintf(&policy_file[0], 1023, TOP_SOURCEDIR "/test/data/fapi/%s.json", policy_name) < 0)
+        return NULL;
+
+    stream = fopen(policy_file, "r");
+    if (!stream) {
+        LOG_ERROR("File %s does not exist", policy_file);
+        return NULL;
+    }
+    fseek(stream, 0L, SEEK_END);
+    policy_size = ftell(stream);
+    fclose(stream);
+    json_policy = malloc(policy_size + 1);
+    stream = fopen(policy_file, "r");
+    ssize_t ret = read(fileno(stream), json_policy, policy_size);
+    if (ret != policy_size) {
+        LOG_ERROR("IO error %s.", policy_file);
+        return NULL;
+    }
+    json_policy[policy_size] = '\0';
+    return json_policy;
+}
+
+/** Test the FAPI key signing with PolicyAuthorizeNV.
+ *
+ * Tested FAPI commands:
+ *  - Fapi_Provision()
+ *  - Fapi_CreateNv()
+ *  - Fapi_NvWrite()
+ *
+ * @param[in,out] context The FAPI_CONTEXT.
+ * @retval EXIT_FAILURE
+ * @retval EXIT_SUCCESS
+ */
+int
+test_fapi_policy_authorize_nv(FAPI_CONTEXT *context)
+{
+    TSS2_RC r;
+    char *nvPathPolicy = "/nv/Owner/myNV";
+    char *policy_authorize_nv = "/policy/pol_authorize_nv";
+    char *policy_pcr2 = "/policy/pol_pcr16_0";
+    char *json_policy = NULL;
+
+    uint8_t *signature = NULL;
+    char    *publicKey = NULL;
+
+    if (check_tpm_cmd(context, TPM2_CC_PolicyAuthorizeNV) != TPM2_RC_SUCCESS) {
+        LOG_WARNING("Command PolicyAuthorizeNV not available.");
+        return EXIT_SKIP;
+    }
+
+    r = Fapi_Provision(context, NULL, NULL, NULL);
+    goto_if_error(r, "Error Fapi_Provision", error);
+
+    /* Create NV object for storing the policy */
+    r = Fapi_CreateNv(context, nvPathPolicy, "noda", 34, "", "");
+    goto_if_error(r, "Error Fapi_CreateNv", error);
+
+    r = pcr_reset(context, 16);
+    goto_if_error(r, "Error pcr_reset", error);
+
+    json_policy = read_policy(context, policy_authorize_nv);
+    if (!json_policy)
+        goto error;
+
+    r = Fapi_Import(context, policy_authorize_nv, json_policy);
+    goto_if_error(r, "Error Fapi_Import", error);
+    SAFE_FREE(json_policy);
+
+    json_policy = read_policy(context, policy_pcr2);
+    if (!json_policy)
+        goto error;
+
+    r = Fapi_Import(context, policy_pcr2, json_policy);
+    goto_if_error(r, "Error Fapi_Import", error);
+
+    r = Fapi_WriteAuthorizeNv(context,nvPathPolicy, policy_pcr2);
+    goto_if_error(r, "Error Fapi_WriteAuthorizeNv", error);
+
+    r = Fapi_CreateKey(context, "/HS/SRK/myPolicySignKey", "sign",
+                       "", PASSWORD);
+    goto_if_error(r, "Error Fapi_CreateKey", error);
+
+    r = Fapi_CreateKey(context, "/HS/SRK/mySignKey", SIGN_TEMPLATE,
+                       policy_authorize_nv, PASSWORD);
+    goto_if_error(r, "Error Fapi_CreateKey", error);
+
+    size_t signatureSize = 0;
+
+    TPM2B_DIGEST digest = {
+        .size = 20,
+        .buffer = {
+            0x67, 0x68, 0x03, 0x3e, 0x21, 0x64, 0x68, 0x24, 0x7b, 0xd0,
+            0x31, 0xa0, 0xa2, 0xd9, 0x87, 0x6d, 0x79, 0x81, 0x8f, 0x8f,
+            0x31, 0xa0, 0xa2, 0xd9, 0x87, 0x6d, 0x79, 0x81, 0x8f, 0x8f,
+            0x41, 0x42
+        }
+    };
+
+    r = Fapi_Sign(context, "/HS/SRK/mySignKey", NULL,
+                  &digest.buffer[0], digest.size, &signature, &signatureSize,
+                  &publicKey, NULL);
+    goto_if_error(r, "Error Fapi_Sign", error);
+
+    r = Fapi_Delete(context, nvPathPolicy);
+    goto_if_error(r, "Error Fapi_NV_Undefine", error);
+
+    r = Fapi_Delete(context, "/");
+    goto_if_error(r, "Error Fapi_Delete", error);
+
+    SAFE_FREE(json_policy);
+    SAFE_FREE(signature);
+    SAFE_FREE(publicKey);
+    return EXIT_SUCCESS;
+
+error:
+    SAFE_FREE(json_policy);
+    SAFE_FREE(signature);
+    SAFE_FREE(publicKey);
+    return EXIT_FAILURE;
+}
+
+int
+test_invoke_fapi(FAPI_CONTEXT *context)
+{
+    return test_fapi_policy_authorize_nv(context);
+}
diff --git a/test/integration/fapi-key-create-policy-authorize-sign.int.c b/test/integration/fapi-key-create-policy-authorize-sign.int.c
new file mode 100644
index 0000000..2189d25
--- /dev/null
+++ b/test/integration/fapi-key-create-policy-authorize-sign.int.c
@@ -0,0 +1,197 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ *******************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "tss2_fapi.h"
+
+#include "test-fapi.h"
+
+#define LOGMODULE test
+#include "util/log.h"
+#include "util/aux_util.h"
+
+/** Test the FAPI functions for key creation and usage.
+ *
+ * Tested FAPI commands:
+ *  - Fapi_Provision()
+ *  - Fapi_CreateKey()
+ *  - Fapi_Sign()
+ *  - Fapi_Delete()
+ *  - Fapi_List()
+ *
+ * @param[in,out] context The FAPI_CONTEXT.
+ * @retval EXIT_FAILURE
+ * @retval EXIT_SUCCESS
+ */
+int
+test_fapi_key_create_policy_authorize_sign(FAPI_CONTEXT *context)
+{
+    TSS2_RC r;
+    char *policy_name_hash = "/policy/pol_name_hash";
+    char *policy_file_name_hash = TOP_SOURCEDIR "/test/data/fapi/policy/pol_name_hash.json";
+    char *policy_name_authorize = "/policy/pol_authorize";
+    char *policy_file_authorize = TOP_SOURCEDIR "/test/data/fapi/policy/pol_authorize.json";
+    FILE *stream = NULL;
+    char *json_policy = NULL;
+    long policy_size;
+
+    uint8_t *signature = NULL;
+    char *publicKey = NULL;
+    char *pathList = NULL;
+
+
+    r = Fapi_Provision(context, NULL, NULL, NULL);
+    goto_if_error(r, "Error Fapi_Provision", error);
+
+    r = pcr_reset(context, 16);
+    goto_if_error(r, "Error pcr_reset", error);
+
+    /* Read in the first policy */
+    stream = fopen(policy_file_name_hash, "r");
+    if (!stream) {
+        LOG_ERROR("File %s does not exist", policy_file_name_hash);
+        goto error;
+    }
+    fseek(stream, 0L, SEEK_END);
+    policy_size = ftell(stream);
+    fclose(stream);
+    json_policy = malloc(policy_size + 1);
+    goto_if_null(json_policy,
+            "Could not allocate memory for the JSON policy",
+            TSS2_FAPI_RC_MEMORY, error);
+    stream = fopen(policy_file_name_hash, "r");
+    ssize_t ret = read(fileno(stream), json_policy, policy_size);
+    if (ret != policy_size) {
+        LOG_ERROR("IO error %s.", policy_file_name_hash);
+        goto error;
+    }
+    json_policy[policy_size] = '\0';
+
+    r = Fapi_Import(context, policy_name_hash, json_policy);
+    SAFE_FREE(json_policy);
+    goto_if_error(r, "Error Fapi_List", error);
+
+    /* Read in the second policy */
+    stream = fopen(policy_file_authorize, "r");
+    if (!stream) {
+        LOG_ERROR("File %s does not exist", policy_file_authorize);
+        goto error;
+    }
+    fseek(stream, 0L, SEEK_END);
+    policy_size = ftell(stream);
+    fclose(stream);
+    json_policy = malloc(policy_size + 1);
+    goto_if_null(json_policy,
+            "Could not allocate memory for the JSON policy",
+            TSS2_FAPI_RC_MEMORY, error);
+    stream = fopen(policy_file_authorize, "r");
+    ret = read(fileno(stream), json_policy, policy_size);
+    if (ret != policy_size) {
+        LOG_ERROR("IO error %s.", policy_file_authorize);
+        goto error;
+    }
+    json_policy[policy_size] = '\0';
+
+    r = Fapi_Import(context, policy_name_authorize, json_policy);
+    SAFE_FREE(json_policy);
+    goto_if_error(r, "Error Fapi_Import", error);
+
+    /* Create keys and use them to authorize policies */
+    r = Fapi_CreateKey(context, "HS/SRK/myPolicySignKey", "sign,noDa",
+                       "", NULL);
+    goto_if_error(r, "Error Fapi_CreateKey", error);
+
+    /* Create the actual key */
+    r = Fapi_CreateKey(context, "HS/SRK/mySignKey", "sign, noda",
+                       policy_name_authorize, NULL);
+    goto_if_error(r, "Error Fapi_CreateKey", error);
+
+    r = Fapi_AuthorizePolicy(context, policy_name_hash,
+                             "HS/SRK/myPolicySignKey", NULL, 0);
+    goto_if_error(r, "Authorize policy", error);
+
+    /* The policy is authorized twice with idfferent keys in order to test the code that
+       stores multiple authorizations inside the policy statements. */
+    r = Fapi_CreateKey(context, "HS/SRK/myPolicySignKey2", "sign,noDa",
+                       "", NULL);
+    goto_if_error(r, "Error Fapi_CreateKey", error);
+
+    /* Use the key */
+    size_t signatureSize = 0;
+
+    TPM2B_DIGEST digest = {
+        .size = 32,
+        .buffer = {
+            0x67, 0x68, 0x03, 0x3e, 0x21, 0x64, 0x68, 0x24, 0x7b, 0xd0,
+            0x31, 0xa0, 0xa2, 0xd9, 0x87, 0x6d, 0x79, 0x81, 0x8f, 0x8f,
+            0x31, 0xa0, 0xa2, 0xd9, 0x87, 0x6d, 0x79, 0x81, 0x8f, 0x8f,
+            0x41, 0x42
+        }
+    };
+
+    r = Fapi_Sign(context, "HS/SRK/mySignKey", NULL,
+                  &digest.buffer[0], digest.size, &signature, &signatureSize,
+                  &publicKey, NULL);
+    goto_if_error(r, "Error Fapi_Sign", error);
+
+    r = Fapi_List(context, "/", &pathList);
+    goto_if_error(r, "Error Fapi_List", error);
+    SAFE_FREE(pathList);
+
+    r = Fapi_List(context, "/SRK/", &pathList);
+    goto_if_error(r, "Error Fapi_List", error);
+    fprintf(stderr, "\n%s\n", pathList);
+    SAFE_FREE(pathList);
+
+    r = Fapi_List(context, "/HS/", &pathList);
+    goto_if_error(r, "Error Fapi_List", error);
+    fprintf(stderr, "\n%s\n", pathList);
+    SAFE_FREE(pathList);
+
+    LOG_WARNING("Next is a failure-test, and we expect errors in the log");
+    r = Fapi_List(context, "XXX", &pathList);
+    if (r == TSS2_RC_SUCCESS) {
+        LOG_ERROR("Path XXX was found");
+        goto error;
+    }
+    SAFE_FREE(pathList);
+
+    r = Fapi_List(context, "/HS/", &pathList);
+    goto_if_error(r, "Error Fapi_List", error);
+    fprintf(stderr, "\n%s\n", pathList);
+    SAFE_FREE(pathList);
+
+    /* Cleanup */
+    r = Fapi_Delete(context, "/HS/SRK");
+    goto_if_error(r, "Error Fapi_Delete", error);
+
+    SAFE_FREE(signature);
+    SAFE_FREE(publicKey);
+    return EXIT_SUCCESS;
+
+error:
+    SAFE_FREE(json_policy);
+    SAFE_FREE(signature);
+    SAFE_FREE(publicKey);
+    SAFE_FREE(pathList);
+    Fapi_Delete(context, "/HS/SRK");
+    return EXIT_FAILURE;
+}
+
+int
+test_invoke_fapi(FAPI_CONTEXT *fapi_context)
+{
+    return test_fapi_key_create_policy_authorize_sign(fapi_context);
+}
diff --git a/test/integration/fapi-key-create-policy-nv-sign.int.c b/test/integration/fapi-key-create-policy-nv-sign.int.c
new file mode 100644
index 0000000..6567707
--- /dev/null
+++ b/test/integration/fapi-key-create-policy-nv-sign.int.c
@@ -0,0 +1,127 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ *******************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "tss2_fapi.h"
+
+#define LOGMODULE test
+#include "util/log.h"
+#include "util/aux_util.h"
+
+#define SIGN_TEMPLATE  "sign,noDa"
+#define PASSWORD NULL
+
+/** Test the FAPI functions for key creation and usage.
+ *
+ * Tested FAPI commands:
+ *  - Fapi_Provision()
+ *  - Fapi_CreateKey()
+ *  - Fapi_Sign()
+ *  - Fapi_Delete()
+ *
+ * @param[in,out] context The FAPI_CONTEXT.
+ * @retval EXIT_FAILURE
+ * @retval EXIT_SUCCESS
+ */
+
+#define NV_SIZE 4
+
+int
+test_fapi_key_create_policy_nv_sign(FAPI_CONTEXT *context)
+{
+    TSS2_RC r;
+    char *policy_name = "/policy/pol_nv";
+    char *policy_file = TOP_SOURCEDIR "/test/data/fapi/policy/pol_nv.json";;
+    FILE *stream = NULL;
+    char *json_policy = NULL;
+    uint8_t *signature = NULL;
+    char    *publicKey = NULL;
+    long policy_size;
+    char *nvPathOrdinary = "/nv/Owner/myNV";
+    uint8_t data_nv[NV_SIZE] = { 1, 2, 3, 4 };
+
+    r = Fapi_Provision(context, NULL, NULL, NULL);
+    goto_if_error(r, "Error Fapi_Provision", error);
+
+    r = Fapi_CreateNv(context, nvPathOrdinary, "noda", 4,  "", "");
+    goto_if_error(r, "Error Fapi_CreateNv", error);
+
+    r = Fapi_NvWrite(context, nvPathOrdinary, &data_nv[0], NV_SIZE);
+    goto_if_error(r, "Error Fapi_NvWrite", error);
+
+    stream = fopen(policy_file, "r");
+    if (!stream) {
+        LOG_ERROR("File %s does not exist", policy_file);
+        goto error;
+    }
+    fseek(stream, 0L, SEEK_END);
+    policy_size = ftell(stream);
+    fclose(stream);
+    json_policy = malloc(policy_size + 1);
+    goto_if_null(json_policy,
+            "Could not allocate memory for the JSON policy",
+            TSS2_FAPI_RC_MEMORY, error);
+    stream = fopen(policy_file, "r");
+    ssize_t ret = read(fileno(stream), json_policy, policy_size);
+    if (ret != policy_size) {
+        LOG_ERROR("IO error %s.", policy_file);
+        goto error;
+    }
+    json_policy[policy_size] = '\0';
+
+    r = Fapi_Import(context, policy_name, json_policy);
+    goto_if_error(r, "Error Fapi_Import", error);
+
+    r = Fapi_CreateKey(context, "HS/SRK/mySignKey", SIGN_TEMPLATE,
+                       policy_name, PASSWORD);
+    goto_if_error(r, "Error Fapi_CreateKey", error);
+    size_t signatureSize = 0;
+
+    TPM2B_DIGEST digest = {
+        .size = 20,
+        .buffer = {
+            0x67, 0x68, 0x03, 0x3e, 0x21, 0x64, 0x68, 0x24, 0x7b, 0xd0,
+            0x31, 0xa0, 0xa2, 0xd9, 0x87, 0x6d, 0x79, 0x81, 0x8f, 0x8f
+        }
+    };
+
+    r = Fapi_Sign(context, "HS/SRK/mySignKey", NULL,
+                  &digest.buffer[0], digest.size, &signature, &signatureSize,
+                  &publicKey, NULL);
+    goto_if_error(r, "Error Fapi_Sign", error);
+
+    r = Fapi_Delete(context, nvPathOrdinary);
+    goto_if_error(r, "Error Fapi_NV_Undefine", error);
+
+    r = Fapi_Delete(context, "/HS/SRK");
+    goto_if_error(r, "Error Fapi_Delete", error);
+
+    SAFE_FREE(signature);
+    SAFE_FREE(publicKey);
+    SAFE_FREE(json_policy);
+    return EXIT_SUCCESS;
+
+error:
+    SAFE_FREE(signature);
+    SAFE_FREE(publicKey);
+    SAFE_FREE(json_policy);
+    return EXIT_FAILURE;
+}
+
+int
+test_invoke_fapi(FAPI_CONTEXT *fapi_context)
+{
+    return test_fapi_key_create_policy_nv_sign(fapi_context);
+}
diff --git a/test/integration/fapi-key-create-policy-or-sign.int.c b/test/integration/fapi-key-create-policy-or-sign.int.c
new file mode 100644
index 0000000..1a976a8
--- /dev/null
+++ b/test/integration/fapi-key-create-policy-or-sign.int.c
@@ -0,0 +1,140 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ *******************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "tss2_fapi.h"
+
+#include "test-fapi.h"
+
+#define LOGMODULE test
+#include "util/log.h"
+#include "util/aux_util.h"
+
+#define PASSWORD NULL
+#define SIGN_TEMPLATE  "sign,noDa"
+
+TSS2_RC
+branch_callback(
+    FAPI_CONTEXT *context,
+    char   const *description,
+    char  const **branchNames,
+    size_t        numBranches,
+    size_t       *selectedBranch,
+    void         *userData)
+{
+    (void) description;
+    (void) numBranches;
+    (void) branchNames;
+    (void) userData;
+
+    *selectedBranch = 1;
+    return TSS2_RC_SUCCESS;
+}
+
+
+/** Test the FAPI functions for key creation and usage.
+ *
+ * Tested FAPI commands:
+ *  - Fapi_Provision()
+ *  - Fapi_CreateKey()
+ *  - Fapi_Sign()
+ *  - Fapi_Delete()
+ *
+ * @param[in,out] context The FAPI_CONTEXT.
+ * @retval EXIT_FAILURE
+ * @retval EXIT_SUCCESS
+ */
+int
+test_fapi_key_create_policy_or_sign(FAPI_CONTEXT *context)
+{
+    TSS2_RC r;
+    char *policy_name = "/policy/pol_pcr16_0_or";
+    char *policy_file = TOP_SOURCEDIR "/test/data/fapi/policy/pol_pcr16_0_or.json";
+    FILE *stream = NULL;
+    char *json_policy = NULL;
+    uint8_t *signature = NULL;
+    char    *publicKey = NULL;
+    long policy_size;
+
+    r = Fapi_Provision(context, NULL, NULL, NULL);
+    goto_if_error(r, "Error Fapi_Provision", error);
+
+    r = pcr_reset(context, 16);
+    goto_if_error(r, "Error pcr_reset", error);
+
+    stream = fopen(policy_file, "r");
+    if (!stream) {
+        LOG_ERROR("File %s does not exist", policy_file);
+        goto error;
+    }
+    fseek(stream, 0L, SEEK_END);
+    policy_size = ftell(stream);
+    fclose(stream);
+    json_policy = malloc(policy_size + 1);
+    goto_if_null(json_policy,
+            "Could not allocate memory for the JSON policy",
+            TSS2_FAPI_RC_MEMORY, error);
+    stream = fopen(policy_file, "r");
+    ssize_t ret = read(fileno(stream), json_policy, policy_size);
+    if (ret != policy_size) {
+        LOG_ERROR("IO error %s.", policy_file);
+        goto error;
+    }
+    json_policy[policy_size] = '\0';
+
+    r = Fapi_Import(context, policy_name, json_policy);
+    goto_if_error(r, "Error Fapi_Import", error);
+
+    r = Fapi_CreateKey(context, "/HS/SRK/mySignKey", SIGN_TEMPLATE,
+                       policy_name, PASSWORD);
+    goto_if_error(r, "Error Fapi_CreateKey", error);
+    size_t signatureSize = 0;
+
+    TPM2B_DIGEST digest = {
+        .size = 20,
+        .buffer = {
+            0x67, 0x68, 0x03, 0x3e, 0x21, 0x64, 0x68, 0x24, 0x7b, 0xd0,
+            0x31, 0xa0, 0xa2, 0xd9, 0x87, 0x6d, 0x79, 0x81, 0x8f, 0x8f
+        }
+    };
+
+    r = Fapi_SetBranchCB(context, branch_callback, NULL);
+    goto_if_error(r, "Error SetPolicybranchselectioncallback", error);
+
+    r = Fapi_Sign(context, "/HS/SRK/mySignKey", NULL,
+                  &digest.buffer[0], digest.size, &signature, &signatureSize,
+                  &publicKey, NULL);
+    goto_if_error(r, "Error Fapi_Sign", error);
+
+    r = Fapi_Delete(context, "/HS/SRK");
+    goto_if_error(r, "Error Fapi_Delete", error);
+
+    SAFE_FREE(json_policy);
+    SAFE_FREE(signature);
+    SAFE_FREE(publicKey);
+    return EXIT_SUCCESS;
+
+error:
+    SAFE_FREE(json_policy);
+    SAFE_FREE(signature);
+    SAFE_FREE(publicKey);
+    return EXIT_FAILURE;
+}
+
+int
+test_invoke_fapi(FAPI_CONTEXT *fapi_context)
+{
+    return test_fapi_key_create_policy_or_sign(fapi_context);
+}
diff --git a/test/integration/fapi-key-create-policy-password-sign.int.c b/test/integration/fapi-key-create-policy-password-sign.int.c
new file mode 100644
index 0000000..6a9ead2
--- /dev/null
+++ b/test/integration/fapi-key-create-policy-password-sign.int.c
@@ -0,0 +1,142 @@
+/* SPDX-License-Identifier: BSD-2 */
+/*******************************************************************************
+ * Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ *******************************************************************************/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "tss2_fapi.h"
+#include "fapi_util.h"
+#include "fapi_int.h"
+
+#include "esys_iutil.h"
+#define LOGMODULE test
+#include "util/log.h"
+#include "util/aux_util.h"
+
+#define PASSWORD "abc"
+
+TSS2_RC
+auth_callback(
+    FAPI_CONTEXT *context,
+    char const *description,
+    char **auth,
+    void *userData)
+{
+    (void)description;
+    (void)userData;
+    *auth = strdup(PASSWORD);
+    return TSS2_RC_SUCCESS;
+}
+#define SIGN_TEMPLATE  "T_RSA_SIGN"
+#define PROFILE "P_RSA"
+#define PROFILE_DIR  ""
+
+
+/** Test the FAPI functions for key creation and usage.
+ *
+ * Tested FAPI commands:
+ *  - Fapi_Provision()
+ *  - Fapi_Key_Create()
+ *  - Fapi_Key_Sign()
+ *  - Fapi_Entity_Delete()
+ *  - Fapi_Entities_List()
+ *
+ * @param[in,out] esys_context The FAPI_CONTEXT.
+ * @retval EXIT_FAILURE
+ * @retval EXIT_SUCCESS
+ */
+int
+test_fapi_key_create(FAPI_CONTEXT *context)
+{
+    TSS2_RC r;
+    char* policy_name = "policies/pol_password";
+    char* policy_file = NULL;
+    FILE *stream = NULL;
+    char *json_policy = NULL;
+    long policy_size;
+
+    r = Fapi_Provision(context, PROFILE, NULL, NULL, NULL, NULL, NULL);
+    goto_if_error(r, "Error Fapi_Provision", error);
+
+    r = ifapi_asprintf(&policy_file, "%s/%s.json", context->config.profile_dir,
+                       policy_name);
+    goto_if_error(r, "Create file name", error);
+
+    r = Fapi_PCR_Reset(context, 16);
+    goto_if_error(r, "Reset PCR 16", error);
+
+    stream = fopen(policy_file, "r");
+    if (!stream) {
+        LOG_ERROR("File %s does not exist", policy_file);
+        goto error;
+    }
+    fseek(stream, 0L, SEEK_END);
+    policy_size = ftell(stream);
+    fclose(stream);
+    json_policy = malloc(policy_size + 1);
+    stream = fopen(policy_file, "r");
+    ssize_t ret = read(fileno(stream), json_policy, policy_size);
+    if (ret != policy_size) {
+         LOG_ERROR("IO error %s.", policy_file);
+         goto error;
+    }
+    json_policy[policy_size] = '\0';
+
+    r = Fapi_PolicyImport(context, policy_name, json_policy);
+    goto_if_error(r, "Error Fapi_Entities_List", error);
+
+    r = Fapi_Key_Create(context, PROFILE_DIR "HS/SNK/mySignKey", SIGN_TEMPLATE,
+                        policy_name, PASSWORD);
+    goto_if_error(r, "Error Fapi_Key_Create", error);
+    size_t signatureSize = 0;
+    size_t publicKeySize = 0;
+    size_t certificateSize = 0;
+
+    TPM2B_DIGEST digest = {
+        .size = 20,
+        .buffer = { 0x67, 0x68, 0x03, 0x3e, 0x21, 0x64, 0x68, 0x24, 0x7b, 0xd0,
+                    0x31, 0xa0, 0xa2, 0xd9, 0x87, 0x6d, 0x79, 0x81, 0x8f, 0x8f }
+    };
+
+    uint8_t *signature;
+    uint8_t *publicKey;
+
+    r = Fapi_SetPolicyAuthCallback(context, auth_callback, "");
+    goto_if_error(r, "Error SetPolicyAuthCallback", error);
+
+    r = Fapi_Key_Sign(context, PROFILE_DIR "HS/SNK/mySignKey",
+                      &digest.buffer[0], digest.size, &signature, &signatureSize,
+                      &publicKey, &publicKeySize, NULL, &certificateSize);
+    goto_if_error(r, "Error Fapi_Key_Sign", error);
+
+    r = Fapi_Entity_Delete(context, PROFILE "/HE/EK");
+    goto_if_error(r, "Error Fapi_Entity_Delete", error);
+
+    size_t numPaths;
+    char  **pathlist;
+
+    r = Fapi_Entities_List(context, PROFILE "/", &pathlist ,&numPaths);
+    goto_if_error(r, "Error Fapi_Entities_List", error);
+
+    /* The two storage keys should remain */
+    if (numPaths != 2) {
+        LOG_ERROR("Wrong number of objects in key store");
+        goto error;
+    }
+
+    return EXIT_SUCCESS;
+
+ error:
+    return EXIT_FAILURE;
+}
+
+int
+test_invoke_fapi(FAPI_CONTEXT * fapi_context) {
+    return test_fapi_key_create(fapi_context);
+}
diff --git a/test/integration/fapi-key-create-policy-pcr-sign.int.c b/test/integration/fapi-key-create-policy-pcr-sign.int.c
new file mode 100644
index 0000000..edaff34
--- /dev/null
+++ b/test/integration/fapi-key-create-policy-pcr-sign.int.c
@@ -0,0 +1,198 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ *******************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "tss2_fapi.h"
+
+#include "test-fapi.h"
+#define LOGMODULE test
+#include "util/log.h"
+#include "util/aux_util.h"
+
+#define PASSWORD NULL
+#define SIGN_TEMPLATE  "sign,noDa"
+
+
+/** Test the FAPI functions for key creation and usage.
+ *
+ * Tested FAPI commands:
+ *  - Fapi_Provision()
+ *  - Fapi_CreateKey()
+ *  - Fapi_Sign()
+ *  - Fapi_Delete()
+ *
+ * @param[in,out] context The FAPI_CONTEXT.
+ * @retval EXIT_FAILURE
+ * @retval EXIT_SUCCESS
+ */
+int
+test_fapi_key_create_policy_pcr_sign(FAPI_CONTEXT *context)
+{
+    TSS2_RC r;
+    char *policy_name = "/policy/pol_pcr16_0";
+    char *policy_pcr_read = "/policy/pol_pcr16_read";
+    char *policy_file = TOP_SOURCEDIR "/test/data/fapi/policy/pol_pcr16_0.json";
+    char *policy_pcr_read_file = TOP_SOURCEDIR "/test/data/fapi/policy/pol_pcr16_read.json";
+    FILE *stream = NULL;
+    char *json_policy = NULL;
+    long policy_size;
+
+    uint8_t *signature = NULL;
+    char   *publicKey = NULL;
+    char *policy = NULL;
+    char *path_list = NULL;
+
+    r = Fapi_Provision(context, NULL, NULL, NULL);
+    goto_if_error(r, "Error Fapi_Provision", error);
+
+    r = pcr_reset(context, 16);
+    goto_if_error(r, "Error pcr_reset", error);
+
+    stream = fopen(policy_file, "r");
+    if (!stream) {
+        LOG_ERROR("File %s does not exist", policy_file);
+        goto error;
+    }
+    fseek(stream, 0L, SEEK_END);
+    policy_size = ftell(stream);
+    fclose(stream);
+    json_policy = malloc(policy_size + 1);
+    goto_if_null(json_policy,
+            "Could not allocate memory for the JSON policy",
+            TSS2_FAPI_RC_MEMORY, error);
+    stream = fopen(policy_file, "r");
+    ssize_t ret = read(fileno(stream), json_policy, policy_size);
+    if (ret != policy_size) {
+        LOG_ERROR("IO error %s.", policy_file);
+        goto error;
+    }
+    json_policy[policy_size] = '\0';
+
+    r = Fapi_Import(context, policy_name, json_policy);
+    goto_if_error(r, "Error Fapi_Import", error);
+
+    r = Fapi_CreateKey(context, "/HS/SRK/mySignKey", SIGN_TEMPLATE,
+                       policy_name, PASSWORD);
+    goto_if_error(r, "Error Fapi_CreateKey", error);
+    size_t signatureSize = 0;
+
+    TPM2B_DIGEST digest = {
+        .size = 20,
+        .buffer = {
+            0x67, 0x68, 0x03, 0x3e, 0x21, 0x64, 0x68, 0x24, 0x7b, 0xd0,
+            0x31, 0xa0, 0xa2, 0xd9, 0x87, 0x6d, 0x79, 0x81, 0x8f, 0x8f
+        }
+    };
+
+    r = Fapi_Sign(context, "/HS/SRK/mySignKey", NULL,
+                  &digest.buffer[0], digest.size, &signature, &signatureSize,
+                  &publicKey, NULL);
+    goto_if_error(r, "Error Fapi_Sign", error);
+
+    r = Fapi_ExportPolicy(context, "HS/SRK/mySignKey", &policy);
+    goto_if_error(r, "Error Fapi_ExportPolicy", error);
+    fprintf(stderr, "\nPolicy from key:\n%s\n", policy);
+
+    SAFE_FREE(policy);
+
+    r = Fapi_ExportPolicy(context, policy_name, &policy);
+    goto_if_error(r, "Error Fapi_ExportPolicy", error);
+    fprintf(stderr, "\nPolicy from policy file:\n%s\n", policy);
+
+    /* Run test with current PCRs defined in policy */
+
+    r = Fapi_Delete(context, "/HS/SRK/mySignKey");
+    goto_if_error(r, "Error Fapi_Delete", error);
+
+    fclose(stream);
+    stream = fopen(policy_pcr_read_file, "r");
+    if (!stream) {
+        LOG_ERROR("File %s does not exist", policy_pcr_read_file);
+        goto error;
+    }
+    fseek(stream, 0L, SEEK_END);
+    policy_size = ftell(stream);
+    fclose(stream);
+
+    SAFE_FREE(json_policy);
+    SAFE_FREE(signature);
+    SAFE_FREE(publicKey);
+    SAFE_FREE(policy);
+    SAFE_FREE(path_list);
+
+    json_policy = malloc(policy_size + 1);
+    goto_if_null(json_policy,
+            "Could not allocate memory for the JSON policy",
+            TSS2_FAPI_RC_MEMORY, error);
+    stream = fopen(policy_pcr_read_file, "r");
+    ret = read(fileno(stream), json_policy, policy_size);
+    if (ret != policy_size) {
+        LOG_ERROR("IO error %s.", policy_pcr_read_file);
+        goto error;
+    }
+    json_policy[policy_size] = '\0';
+
+    r = Fapi_Import(context, policy_pcr_read, json_policy);
+    goto_if_error(r, "Error Fapi_Import", error);
+
+    r = Fapi_CreateKey(context, "/HS/SRK/mySignKey", SIGN_TEMPLATE,
+                       policy_pcr_read, PASSWORD);
+    goto_if_error(r, "Error Fapi_CreateKey", error);
+    signatureSize = 0;
+
+    r = Fapi_Sign(context, "/HS/SRK/mySignKey", NULL,
+                  &digest.buffer[0], digest.size, &signature, &signatureSize,
+                  &publicKey, NULL);
+    goto_if_error(r, "Error Fapi_Sign", error);
+
+    r = Fapi_ExportPolicy(context, "HS/SRK/mySignKey", &policy);
+    goto_if_error(r, "Error Fapi_ExportPolicy", error);
+    fprintf(stderr, "\nPolicy from key:\n%s\n", policy);
+
+    SAFE_FREE(policy);
+
+    r = Fapi_ExportPolicy(context, policy_pcr_read, &policy);
+    goto_if_error(r, "Error Fapi_ExportPolicy", error);
+    fprintf(stderr, "\nPolicy from policy file:\n%s\n", policy);
+
+    r = Fapi_Delete(context, "/HS/SRK");
+    goto_if_error(r, "Error Fapi_Delete", error);
+
+    r = Fapi_List(context, "", &path_list);
+    goto_if_error(r, "Error Fapi_Delete", error);
+
+    fprintf(stderr, "\nPathList:\n%s\n", path_list);
+
+    SAFE_FREE(json_policy);
+    SAFE_FREE(signature);
+    SAFE_FREE(publicKey);
+    SAFE_FREE(policy);
+    SAFE_FREE(path_list);
+    return EXIT_SUCCESS;
+
+error:
+    SAFE_FREE(json_policy);
+    SAFE_FREE(signature);
+    SAFE_FREE(publicKey);
+    SAFE_FREE(policy);
+    SAFE_FREE(path_list);
+    return EXIT_FAILURE;
+}
+
+int
+test_invoke_fapi(FAPI_CONTEXT *fapi_context)
+{
+    return test_fapi_key_create_policy_pcr_sign(fapi_context);
+}
diff --git a/test/integration/fapi-key-create-policy-secret-nv-sign.int.c b/test/integration/fapi-key-create-policy-secret-nv-sign.int.c
new file mode 100644
index 0000000..a8907f2
--- /dev/null
+++ b/test/integration/fapi-key-create-policy-secret-nv-sign.int.c
@@ -0,0 +1,182 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ *******************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+
+#include "tss2_fapi.h"
+
+#include "test-fapi.h"
+
+#define LOGMODULE test
+#include "util/log.h"
+#include "util/aux_util.h"
+
+#define NV_SIZE 34
+#define PASSWORD "abc"
+#define SIGN_TEMPLATE "sign"
+
+TSS2_RC
+auth_callback(
+    FAPI_CONTEXT *context,
+    char const *description,
+    char **auth,
+    void *userData)
+{
+    (void)description;
+    (void)userData;
+    *auth = strdup(PASSWORD);
+    return_if_null(*auth, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+    return TSS2_RC_SUCCESS;
+}
+
+char *
+read_policy(FAPI_CONTEXT *context, char *policy_name)
+{
+    FILE *stream = NULL;
+    long policy_size;
+    char *json_policy = NULL;
+    char policy_file[1024];
+
+    if (snprintf(&policy_file[0], 1023, TOP_SOURCEDIR "/test/data/fapi/%s.json", policy_name) < 0)
+        return NULL;
+
+    stream = fopen(policy_file, "r");
+    if (!stream) {
+        LOG_ERROR("File %s does not exist", policy_file);
+        return NULL;
+    }
+    fseek(stream, 0L, SEEK_END);
+    policy_size = ftell(stream);
+    fclose(stream);
+    json_policy = malloc(policy_size + 1);
+    return_if_null(json_policy,
+            "Could not allocate memory for the JSON policy",
+            NULL);
+    stream = fopen(policy_file, "r");
+    ssize_t ret = read(fileno(stream), json_policy, policy_size);
+    if (ret != policy_size) {
+        LOG_ERROR("IO error %s.", policy_file);
+        return NULL;
+    }
+    json_policy[policy_size] = '\0';
+    return json_policy;
+}
+
+/** Test the FAPI key signing with PolicyAuthorizeNV.
+ *
+ * Tested FAPI commands:
+ *  - Fapi_Provision()
+ *  - Fapi_CreateNv()
+ *  - Fapi_NvWrite()
+ *
+ * @param[in,out] context The FAPI_CONTEXT.
+ * @retval EXIT_FAILURE
+ * @retval EXIT_SUCCESS
+ */
+int
+test_fapi_policy_secret(FAPI_CONTEXT *context)
+{
+    TSS2_RC r;
+    char *nv_path_auth_object = "/nv/Owner/myNV";
+    char *policy_nv = "/policy/pol_auth_value";
+    char *policy_secret = "/policy/pol_secret";
+    char *sign_key = "/HS/SRK/mySignkey";
+    char *json_policy = NULL;
+
+    uint8_t *signature = NULL;
+    char    *publicKey = NULL;
+
+    r = Fapi_Provision(context, NULL, NULL, NULL);
+    goto_if_error(r, "Error Fapi_Provision", error);
+
+    json_policy = read_policy(context, policy_nv);
+    if (!json_policy)
+        goto error;
+
+    r = Fapi_Import(context, policy_nv, json_policy);
+    goto_if_error(r, "Error Fapi_Import", error);
+
+    /* Create NV Object with policy wich will be used for key authorization */
+    r = Fapi_CreateNv(context, nv_path_auth_object, "noda", 34, policy_nv, PASSWORD);
+    goto_if_error(r, "Error Fapi_CreateNv", error);
+
+    SAFE_FREE(json_policy);
+
+    json_policy = read_policy(context, policy_secret);
+    if (!json_policy)
+        goto error;
+
+    r = Fapi_Import(context, policy_secret, json_policy);
+    goto_if_error(r, "Error Fapi_Import", error);
+
+    r = Fapi_CreateKey(context, sign_key, SIGN_TEMPLATE,
+                       policy_secret, "");
+    goto_if_error(r, "Error Fapi_CreateKey", error);
+
+    size_t signatureSize = 0;
+
+    TPM2B_DIGEST digest = {
+        .size = 32,
+        .buffer = {
+            0x67, 0x68, 0x03, 0x3e, 0x21, 0x64, 0x68, 0x24, 0x7b, 0xd0,
+            0x31, 0xa0, 0xa2, 0xd9, 0x87, 0x6d, 0x79, 0x81, 0x8f, 0x8f,
+            0x31, 0xa0, 0xa2, 0xd9, 0x87, 0x6d, 0x79, 0x81, 0x8f, 0x8f,
+            0x41, 0x42
+        }
+    };
+
+    LOG_ERROR("***** START TEST ERROR ******");
+    r = Fapi_Sign(context, sign_key, NULL,
+                  &digest.buffer[0], digest.size, &signature, &signatureSize,
+                  &publicKey, NULL);
+
+    LOG_ERROR("***** END TEST ERROR ******");
+
+    if (r == TSS2_RC_SUCCESS)
+        goto error;
+
+    r = Fapi_SetAuthCB(context, auth_callback, "");
+    goto_if_error(r, "Error SetPolicyAuthCallback", error);
+
+    r = Fapi_Sign(context, sign_key, NULL,
+                  &digest.buffer[0], digest.size, &signature, &signatureSize,
+                  &publicKey, NULL);
+    goto_if_error(r, "Error Fapi_Sign", error);
+
+    r = Fapi_Delete(context, nv_path_auth_object);
+    goto_if_error(r, "Error Fapi_NV_Undefine", error);
+
+    r = Fapi_Delete(context, "/HS/SRK");
+    goto_if_error(r, "Error Fapi_Delete", error);
+
+    SAFE_FREE(signature);
+    SAFE_FREE(publicKey);
+    SAFE_FREE(json_policy);
+    return EXIT_SUCCESS;
+
+error:
+    SAFE_FREE(signature);
+    SAFE_FREE(publicKey);
+    SAFE_FREE(json_policy);
+    return EXIT_FAILURE;
+}
+
+int
+test_invoke_fapi(FAPI_CONTEXT *context)
+{
+    return test_fapi_policy_secret(context);
+}
diff --git a/test/integration/fapi-key-create-policy-signed.int.c b/test/integration/fapi-key-create-policy-signed.int.c
new file mode 100644
index 0000000..9fdb824
--- /dev/null
+++ b/test/integration/fapi-key-create-policy-signed.int.c
@@ -0,0 +1,271 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ *******************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <openssl/evp.h>
+#include <openssl/rsa.h>
+#include <openssl/engine.h>
+#include <openssl/pem.h>
+
+#include "tss2_fapi.h"
+
+#include "test-fapi.h"
+#define LOGMODULE test
+#include "util/log.h"
+#include "util/aux_util.h"
+
+const char *priv_pem =
+    "-----BEGIN PRIVATE KEY-----\n"
+    "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCgYvoisJIDOeYg\n"
+    "jMF6ywiZbu085TLvy5ZMhq5vfYqdgefvwpemutnfKSnpYOs5B4yO/gAD7XiYluDv\n"
+    "tqlVhfISeQV04xrWGzNImenpwm/HsgueAu8VTHNtWSL96G+BLedGTrs2NqX6cxN7\n"
+    "yGl7dQpB5X8iP4XSvpjP3Vb7gs+adwCJR6xFkt60jYFmwrAdhEzOeakhimi5rU21\n"
+    "LxCkRdEyaxS57X15L9dEA+aYJ+dvkFfZOfTqIKmTrA75F8yj161xflwtIC4hgRBg\n"
+    "K9Xb/RdN8TDrTu+20E3RjngutU4qejW9Fd3mzHJGV8HRYvjYXhUblN9wmjm7Veru\n"
+    "T2b0rnvzAgMBAAECggEBAIwHvoJ5DRJ6A50Zp3dROxHTEphfOEi6xF/OGxBGWLbK\n"
+    "C7l+eS9d5gj8BJa5QsXI/IR/6X2EYQ1AdeV04oVD7CUKuqPiALU8jFrv3pV0aGm+\n"
+    "3nu37gv3crPe5jkvLeNoM4tkA/oCXom63SDuyoG6nxkHiSdatLlaJUse4em3vRAL\n"
+    "QivziZIMyswcleMe0xAoMi7LO+nUFFxBS8/xGya0vsU0dsMQEl1SRITv1VCXmPQD\n"
+    "T4dEI4+1cufv6Ax0EDbFKmnjyiGTjOeQKrGIqETUSQolbg5PgL1XZehaaxM822OY\n"
+    "Qpnp5T0XhUEmVrOb2Wrboj+dC/2tgAN/fWXjAAxnm2ECgYEA02UTZuZ+QnD6tqo3\n"
+    "/y3n5kaM9uA2mdOIqgECI9psGF1IBIC/iP2diKyuvmQL8hzymComb5YzZl3TOAga\n"
+    "WHQYbIeU3JhnYTG75/Dv5Zh32H4NjkIJHT2/8LUM25Ove9u6QAniVgIQpBZ47LjX\n"
+    "9jHjTYCW5n79qNSfu0egYJUvypECgYEAwjqWzzEINqnX/xIVCoB4XpuDuSdkM0JW\n"
+    "MZDIH9xHjZPp07/5XYEoITylk6Zwbh+djvWDNP4gzPtuK26VsqrNxoWMsFZeXn6U\n"
+    "xSOYL2UNCZiOgchdZCOr+6r8LRUuo8xHjbawVoJVK1+tZ2WsR3ilt3Gw34O8Z5ep\n"
+    "f4v7GOXw+EMCgYAUHjFrgJIRhqkFi0uK+HZyXtJ5iDsKBqyh6Tin6tiQtQfujcYs\n"
+    "pl5ArJZwvhq47vJTcud3hSbdHh7E3ViMhHfylDChkct833vPhgl+ozT8oHpvyG8P\n"
+    "nlnO8ZwIpZR0yCOAhrBImSe2RgE6HhlHb9X/ATbbNsizMZEGBLoJlwkWUQKBgQCy\n"
+    "4U7fh2LvJUF+82JZh7RUPZn1Pmg0JVZI0/TcEv37UEy77kR1b2xMIBTGhTVq1sc/\n"
+    "ULIEbkA7SR1P9sr7//8AZSMLjJ/hG2dcoMmabNCzE8O7l5MblRbh87nIs4d+57bG\n"
+    "t4h0RBi4l6eWYLdoI59L8fNaB3PPXIiIpZ0eczeZDQKBgQC2vuFYpUZqDb9CaJsn\n"
+    "Luee6P6n5v3ZBTAT4E+GG1kWS28BiebcCuLKNAY4ZtLo08ozaTWcMxooOTeka2ux\n"
+    "fQDE4M/LTNpam8QOJ2hqECF5a0uBYNcbmaGtfA9KwIgwCZZYuwb5IDq/DRPuR690\n"
+    "i8Kp6jR2wY0suObmZHKvbCB1Dw==\n"
+    "-----END PRIVATE KEY-----\n";
+
+const char *pub_pem =
+    "-----BEGIN PUBLIC KEY-----\n"
+    "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoGL6IrCSAznmIIzBessI\n"
+    "mW7tPOUy78uWTIaub32KnYHn78KXprrZ3ykp6WDrOQeMjv4AA+14mJbg77apVYXy\n"
+    "EnkFdOMa1hszSJnp6cJvx7ILngLvFUxzbVki/ehvgS3nRk67Njal+nMTe8hpe3UK\n"
+    "QeV/Ij+F0r6Yz91W+4LPmncAiUesRZLetI2BZsKwHYRMznmpIYpoua1NtS8QpEXR\n"
+    "MmsUue19eS/XRAPmmCfnb5BX2Tn06iCpk6wO+RfMo9etcX5cLSAuIYEQYCvV2/0X\n"
+    "TfEw607vttBN0Y54LrVOKno1vRXd5sxyRlfB0WL42F4VG5TfcJo5u1Xq7k9m9K57\n"
+    "8wIDAQAB\n"
+    "-----END PUBLIC KEY-----\n";
+
+#define RSA_SIG_SCHEME RSA_PKCS1_PSS_PADDING
+
+char *userDataTest = "test";
+
+#define chknull(X) if (!X) { LOG_ERROR(str(X) "should not be null"); \
+                             r = TSS2_FAPI_RC_GENERAL_FAILURE; \
+                             goto error_cleanup; }
+
+TSS2_RC
+signatureCallback(
+    FAPI_CONTEXT  *context,
+    char    const *description,
+    char    const *publicKey,
+    char    const *publicKeyHint,
+    uint32_t       hashAlg,
+    uint8_t const *dataToSign,
+    size_t         dataToSignSize,
+    uint8_t      **signature,
+    size_t        *signatureSize,
+    void          *userData)
+{
+    (void)description;
+    (void)publicKey;
+    (void)publicKeyHint;
+
+    if (userData != userDataTest) {
+        LOG_ERROR("userData is not correct, %p != %p", userData, userDataTest);
+        return TSS2_FAPI_RC_GENERAL_FAILURE;
+    }
+
+    if (hashAlg != TPM2_ALG_SHA1) {
+        LOG_ERROR("hashAlg is not correct, %u != %u", hashAlg, TPM2_ALG_SHA256);
+        return TSS2_FAPI_RC_GENERAL_FAILURE;
+    }
+
+    TSS2_RC r = TSS2_RC_SUCCESS;
+    EVP_PKEY *priv_key = NULL;
+    BIO *bufio = NULL;
+    EVP_MD_CTX *mdctx = NULL;
+    EVP_PKEY_CTX *pctx = NULL;
+
+    const EVP_MD *ossl_hash = EVP_sha1();
+    chknull(ossl_hash);
+
+    LOGBLOB_DEBUG(dataToSign, dataToSignSize, "Data to be signed");
+
+    bufio = BIO_new_mem_buf((void *)priv_pem, strlen(priv_pem));
+    priv_key = PEM_read_bio_PrivateKey(bufio, NULL, NULL, NULL);
+    chknull(priv_key);
+
+    mdctx = EVP_MD_CTX_create();
+    chknull(mdctx);
+
+    if (1 != EVP_DigestSignInit(mdctx, &pctx, NULL, NULL, priv_key)) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "OSSL digest sign init.",
+                   error_cleanup);
+    }
+    if (EVP_PKEY_type(EVP_PKEY_id(priv_key)) == EVP_PKEY_RSA) {
+        int signing_scheme = RSA_SIG_SCHEME;
+        if (1 != EVP_PKEY_CTX_set_rsa_padding(pctx, signing_scheme)) {
+            goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "OSSL set RSA padding.",
+                       error_cleanup);
+        }
+    }
+    if (1 != EVP_DigestSignInit(mdctx, &pctx, ossl_hash, NULL, priv_key)) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "OSSL sign init.",
+                   error_cleanup);
+    }
+    if (1 != EVP_DigestSignUpdate(mdctx, dataToSign, dataToSignSize)) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "OSSL sign update.",
+                   error_cleanup);
+    }
+    if (1 != EVP_DigestSignFinal(mdctx, NULL, signatureSize)) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "OSSL sign final.",
+                   error_cleanup);
+    }
+    *signature = malloc(*signatureSize);
+    chknull(*signature);
+    if (1 != EVP_DigestSignFinal(mdctx, *signature, signatureSize)) {
+        goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "OSSL sign final.",
+                   error_cleanup);
+    }
+error_cleanup:
+    if (priv_key)
+        EVP_PKEY_free(priv_key);
+    if (bufio)
+        BIO_free(bufio);
+    if (mdctx)
+        EVP_MD_CTX_destroy(mdctx);
+    return r;
+}
+
+#define PASSWORD NULL
+
+#define SIGN_TEMPLATE  "sign,noDa"
+
+/** Test the FAPI functions for key creation and usage with a signed policy.
+ *
+ * Tested FAPI commands:
+ *  - Fapi_Provision()
+ *  - Fapi_CreateKey()
+ *  - Fapi_Sign()
+ *  - Fapi_Delete()
+ *  - Fapi_List()
+ *
+ * @param[in,out] context The FAPI_CONTEXT.
+ * @retval EXIT_FAILURE
+ * @retval EXIT_SUCCESS
+ */
+int
+test_fapi_key_create_policy_signed(FAPI_CONTEXT *context)
+{
+    TSS2_RC r;
+    char *policy_name = "/policy/pol_signed";
+    char *policy_file = TOP_SOURCEDIR "/test/data/fapi/policy/pol_signed.json";
+    FILE *stream = NULL;
+    char *json_policy = NULL;
+    long policy_size;
+
+    uint8_t *signature = NULL;
+    char    *publicKey = NULL;
+    char  *pathList = NULL;
+
+    r = Fapi_Provision(context, NULL, NULL, NULL);
+    goto_if_error(r, "Error Fapi_Provision", error);
+
+    r = pcr_reset(context, 16);
+    goto_if_error(r, "Error pcr_reset", error);
+
+    stream = fopen(policy_file, "r");
+    if (!stream) {
+        LOG_ERROR("File %s does not exist", policy_file);
+        goto error;
+    }
+    fseek(stream, 0L, SEEK_END);
+    policy_size = ftell(stream);
+    fclose(stream);
+    json_policy = malloc(policy_size + 1);
+		goto_if_null(json_policy,
+				"Could not allocate memory for the JSON policy",
+				TSS2_FAPI_RC_MEMORY, error);
+    stream = fopen(policy_file, "r");
+    ssize_t ret = read(fileno(stream), json_policy, policy_size);
+    if (ret != policy_size) {
+        LOG_ERROR("IO error %s.", policy_file);
+        goto error;
+    }
+    json_policy[policy_size] = '\0';
+
+    r = Fapi_Import(context, policy_name, json_policy);
+    goto_if_error(r, "Error Fapi_Import", error);
+
+    r = Fapi_CreateKey(context, "/HS/SRK/mySignKey", SIGN_TEMPLATE,
+                       policy_name, PASSWORD);
+    goto_if_error(r, "Error Fapi_CreateKey", error);
+    size_t signatureSize = 0;
+
+    TPM2B_DIGEST digest = {
+        .size = 20,
+        .buffer = {
+            0x67, 0x68, 0x03, 0x3e, 0x21, 0x64, 0x68, 0x24, 0x7b, 0xd0,
+            0x31, 0xa0, 0xa2, 0xd9, 0x87, 0x6d, 0x79, 0x81, 0x8f, 0x8f
+        }
+    };
+
+    r = Fapi_SetSignCB(context, signatureCallback, userDataTest);
+    goto_if_error(r, "Error SetPolicySignatureCallback", error);
+
+    r = Fapi_Sign(context, "/HS/SRK/mySignKey", NULL,
+                  &digest.buffer[0], digest.size, &signature, &signatureSize,
+                  &publicKey, NULL);
+    goto_if_error(r, "Error Fapi_Sign", error);
+
+    r = Fapi_Delete(context, "/HS/SRK");
+    goto_if_error(r, "Error Fapi_Delete", error);
+
+    r = Fapi_List(context, "/", &pathList);
+    goto_if_error(r, "Error Fapi_List", error);
+
+    fprintf(stderr, "\n%s\n", pathList);
+
+    fclose(stream);
+    SAFE_FREE(json_policy);
+    SAFE_FREE(signature);
+    SAFE_FREE(publicKey);
+    SAFE_FREE(pathList);
+    return EXIT_SUCCESS;
+
+error:
+    SAFE_FREE(json_policy);
+    SAFE_FREE(signature);
+    SAFE_FREE(publicKey);
+    SAFE_FREE(pathList);
+    return EXIT_FAILURE;
+}
+
+int
+test_invoke_fapi(FAPI_CONTEXT *fapi_context)
+{
+    return test_fapi_key_create_policy_signed(fapi_context);
+}
diff --git a/test/integration/fapi-key-create-sign-password-provision.int.c b/test/integration/fapi-key-create-sign-password-provision.int.c
new file mode 100644
index 0000000..63634fa
--- /dev/null
+++ b/test/integration/fapi-key-create-sign-password-provision.int.c
@@ -0,0 +1,164 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ *******************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#include "tss2_fapi.h"
+
+#include "test-fapi.h"
+#include "fapi_util.h"
+#include "fapi_int.h"
+
+#include "esys_iutil.h"
+#define LOGMODULE test
+#include "util/log.h"
+#include "util/aux_util.h"
+
+#define PASSWORD "abc"
+#define SIGN_TEMPLATE "sign,noDa"
+
+
+TSS2_RC
+auth_callback(
+    FAPI_CONTEXT *context,
+    char const *description,
+    char **auth,
+    void *userData)
+{
+    (void)description;
+    (void)userData;
+    char *pw = PASSWORD;
+    if (!pw)
+        return TSS2_FAPI_RC_GENERAL_FAILURE;
+
+    *auth = strdup(pw);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Test the FAPI functions for key creation and usage with a SH password.
+ *
+ * Tested FAPI commands:
+ *  - Fapi_Provision()
+ *  - Fapi_CreateKey()
+ *  - Fapi_Sign()
+ *  - Fapi_Delete()
+ *  - Fapi_ChangeAuth()
+ *  - Fapi_SetCertificate()
+ *
+ * @param[in,out] context The FAPI_CONTEXT.
+ * @retval EXIT_FAILURE
+ * @retval EXIT_SUCCESS
+ */
+int
+test_fapi_key_create_sign_password_provision(FAPI_CONTEXT *context)
+{
+    TSS2_RC r;
+    char *sigscheme = NULL;
+    uint8_t       *publicblob = NULL;
+    uint8_t       *privateblob = NULL;
+    uint8_t *signature = NULL;
+    char    *publicKey = NULL;
+    char *path_list = NULL;
+
+    size_t         publicsize;
+    size_t         privatesize;
+
+    const char *cert =
+        "-----BEGIN CERTIFICATE-----\n"
+        "MIIDBjCCAe4CCQDcvXBOEVM0UTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJE\n"
+        "RTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0\n"
+        "cyBQdHkgTHRkMB4XDTE5MDIyODEwNDkyM1oXDTM1MDgyNzEwNDkyM1owRTELMAkG\n"
+        "A1UEBhMCREUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0\n"
+        "IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\n"
+        "AKBi+iKwkgM55iCMwXrLCJlu7TzlMu/LlkyGrm99ip2B5+/Cl6a62d8pKelg6zkH\n"
+        "jI7+AAPteJiW4O+2qVWF8hJ5BXTjGtYbM0iZ6enCb8eyC54C7xVMc21ZIv3ob4Et\n"
+        "50ZOuzY2pfpzE3vIaXt1CkHlfyI/hdK+mM/dVvuCz5p3AIlHrEWS3rSNgWbCsB2E\n"
+        "TM55qSGKaLmtTbUvEKRF0TJrFLntfXkv10QD5pgn52+QV9k59OogqZOsDvkXzKPX\n"
+        "rXF+XC0gLiGBEGAr1dv9F03xMOtO77bQTdGOeC61Tip6Nb0V3ebMckZXwdFi+Nhe\n"
+        "FRuU33CaObtV6u5PZvSue/MCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAcamUPe8I\n"
+        "nMOHcv9x5lVN1joihVRmKc0QqNLFc6XpJY8+U5rGkZvOcDe9Da8L97wDNXpKmU/q\n"
+        "pprj3rT8l3v0Z5xs8Vdr8lxS6T5NhqQV0UCsn1x14gZJcE48y9/LazYi6Zcar+BX\n"
+        "Am4vewAV3HmQ8X2EctsRhXe4wlAq4slIfEWaaofa8ai7BzO9KwpMLsGPWoNetkB9\n"
+        "19+SFt0lFFOj/6vDw5pCpSd1nQlo1ug69mJYSX/wcGkV4t4LfGhV8jRPDsGs6I5n\n"
+        "ETHSN5KV1XCPYJmRCjFY7sIt1x4zN7JJRO9DVw+YheIlduVfkBiF+GlQgLlFTjrJ\n"
+        "VrpSGMIFSu301A==\n"
+        "-----END CERTIFICATE-----\n";
+
+    if (strcmp("P_ECC", fapi_profile) != 0)
+        sigscheme = "RSA_PSS";
+
+    /* We need to reset the passwords again, in order to not brick physical TPMs */
+    r = Fapi_Provision(context, NULL, PASSWORD, NULL);
+    goto_if_error(r, "Error Fapi_Provision", error);
+
+    r = Fapi_SetAuthCB(context, auth_callback, NULL);
+    goto_if_error(r, "Error SetPolicyAuthCallback", error);
+
+    r = Fapi_CreateKey(context, "HS/SRK/mySignKey", SIGN_TEMPLATE, "",
+                       PASSWORD);
+
+    goto_if_error(r, "Error Fapi_CreateKey", error);
+    size_t signatureSize = 0;
+
+    TPM2B_DIGEST digest = {
+        .size = 20,
+        .buffer = {
+            0x67, 0x68, 0x03, 0x3e, 0x21, 0x64, 0x68, 0x24, 0x7b, 0xd0,
+            0x31, 0xa0, 0xa2, 0xd9, 0x87, 0x6d, 0x79, 0x81, 0x8f, 0x8f
+        }
+    };
+
+    r = Fapi_GetTpmBlobs(context,  "HS/SRK/mySignKey", &publicblob,
+                         &publicsize,
+                         &privateblob, &privatesize, NULL);
+    goto_if_error(r, "Error Fapi_GetTpmBlobs", error);
+
+    r = Fapi_Sign(context, "HS/SRK/mySignKey", sigscheme,
+                  &digest.buffer[0], digest.size, &signature, &signatureSize,
+                  &publicKey, NULL);
+    goto_if_error(r, "Error Fapi_Sign", error);
+
+    r = Fapi_SetCertificate(context, "HS/SRK/mySignKey", cert);
+    goto_if_error(r, "Error Fapi_SetCertificate", error);
+
+    r = Fapi_List(context, "/", &path_list);
+    goto_if_error(r, "Error Fapi_Delete", error);
+
+    fprintf(stderr, "\nPathList:\n%s\n", path_list);
+
+    /* We need to reset the passwords again, in order to not brick physical TPMs */
+    r = Fapi_ChangeAuth(context, "/HS", NULL);
+    goto_if_error(r, "Error Fapi_ChangeAuth", error);
+
+    r = Fapi_Delete(context, "/");
+    goto_if_error(r, "Error Fapi_Delete", error);
+
+    SAFE_FREE(publicblob);
+    SAFE_FREE(privateblob);
+    SAFE_FREE(signature);
+    SAFE_FREE(publicKey);
+    SAFE_FREE(path_list);
+    return EXIT_SUCCESS;
+
+error:
+    Fapi_Delete(context, "/HS/SRK");
+    SAFE_FREE(publicblob);
+    SAFE_FREE(privateblob);
+    SAFE_FREE(signature);
+    SAFE_FREE(publicKey);
+    SAFE_FREE(path_list);
+    return EXIT_FAILURE;
+}
+
+int
+test_invoke_fapi(FAPI_CONTEXT *fapi_context)
+{
+    return test_fapi_key_create_sign_password_provision(fapi_context);
+}
diff --git a/test/integration/fapi-key-create-sign-policy-provision.int.c b/test/integration/fapi-key-create-sign-policy-provision.int.c
new file mode 100644
index 0000000..a45fbf5
--- /dev/null
+++ b/test/integration/fapi-key-create-sign-policy-provision.int.c
@@ -0,0 +1,158 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ *******************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "tss2_fapi.h"
+
+#include "test-fapi.h"
+#define LOGMODULE test
+#include "util/log.h"
+#include "util/aux_util.h"
+
+#define PASSWORD NULL
+#define SIGN_TEMPLATE  "sign,noDa"
+
+
+TSS2_RC
+auth_callback(
+    FAPI_CONTEXT *context,
+    char const *description,
+    char **auth,
+    void *userData)
+{
+    (void)description;
+    (void)userData;
+    char *pw = PASSWORD;
+    if (!pw)
+        return TSS2_FAPI_RC_GENERAL_FAILURE;
+
+    *auth = strdup(pw);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Test the FAPI functions for key creation and usage.
+ *
+ * Tested FAPI commands:
+ *  - Fapi_Provision()
+ *  - Fapi_CreateKey()
+ *  - Fapi_Sign()
+ *  - Fapi_Delete()
+ *  - Fapi_ChangeAuth()
+ *  - Fapi_SetCertificate()
+ *
+ * @param[in,out] context The FAPI_CONTEXT.
+ * @retval EXIT_FAILURE
+ * @retval EXIT_SUCCESS
+ */
+int
+test_fapi_key_create_sign_policy_provision(FAPI_CONTEXT *context)
+{
+    TSS2_RC r;
+    char *sigscheme = NULL;
+    uint8_t *publicblob = NULL;
+    uint8_t *privateblob = NULL;
+    uint8_t *signature = NULL;
+    char *publicKey = NULL;
+    char *path_list = NULL;
+
+    const char *cert =
+        "-----BEGIN CERTIFICATE-----\n"
+        "MIIDBjCCAe4CCQDcvXBOEVM0UTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJE\n"
+        "RTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0\n"
+        "cyBQdHkgTHRkMB4XDTE5MDIyODEwNDkyM1oXDTM1MDgyNzEwNDkyM1owRTELMAkG\n"
+        "A1UEBhMCREUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0\n"
+        "IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\n"
+        "AKBi+iKwkgM55iCMwXrLCJlu7TzlMu/LlkyGrm99ip2B5+/Cl6a62d8pKelg6zkH\n"
+        "jI7+AAPteJiW4O+2qVWF8hJ5BXTjGtYbM0iZ6enCb8eyC54C7xVMc21ZIv3ob4Et\n"
+        "50ZOuzY2pfpzE3vIaXt1CkHlfyI/hdK+mM/dVvuCz5p3AIlHrEWS3rSNgWbCsB2E\n"
+        "TM55qSGKaLmtTbUvEKRF0TJrFLntfXkv10QD5pgn52+QV9k59OogqZOsDvkXzKPX\n"
+        "rXF+XC0gLiGBEGAr1dv9F03xMOtO77bQTdGOeC61Tip6Nb0V3ebMckZXwdFi+Nhe\n"
+        "FRuU33CaObtV6u5PZvSue/MCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAcamUPe8I\n"
+        "nMOHcv9x5lVN1joihVRmKc0QqNLFc6XpJY8+U5rGkZvOcDe9Da8L97wDNXpKmU/q\n"
+        "pprj3rT8l3v0Z5xs8Vdr8lxS6T5NhqQV0UCsn1x14gZJcE48y9/LazYi6Zcar+BX\n"
+        "Am4vewAV3HmQ8X2EctsRhXe4wlAq4slIfEWaaofa8ai7BzO9KwpMLsGPWoNetkB9\n"
+        "19+SFt0lFFOj/6vDw5pCpSd1nQlo1ug69mJYSX/wcGkV4t4LfGhV8jRPDsGs6I5n\n"
+        "ETHSN5KV1XCPYJmRCjFY7sIt1x4zN7JJRO9DVw+YheIlduVfkBiF+GlQgLlFTjrJ\n"
+        "VrpSGMIFSu301A==\n"
+        "-----END CERTIFICATE-----\n";
+
+    if (strcmp("P_ECC", fapi_profile) != 0)
+        sigscheme = "RSA_PSS";
+
+    /* We need to reset the passwords again, in order to not brick physical TPMs */
+    r = Fapi_Provision(context, NULL, PASSWORD, NULL);
+    goto_if_error(r, "Error Fapi_Provision", error);
+
+    r = Fapi_SetAuthCB(context, auth_callback, NULL);
+    goto_if_error(r, "Error SetPolicyAuthCallback", error);
+
+    r = Fapi_CreateKey(context, "HS/SRK/mySignKey", SIGN_TEMPLATE, "",
+                       PASSWORD);
+
+    goto_if_error(r, "Error Fapi_CreateKey", error);
+    size_t signatureSize = 0;
+
+    TPM2B_DIGEST digest = {
+        .size = 20,
+        .buffer = {
+            0x67, 0x68, 0x03, 0x3e, 0x21, 0x64, 0x68, 0x24, 0x7b, 0xd0,
+            0x31, 0xa0, 0xa2, 0xd9, 0x87, 0x6d, 0x79, 0x81, 0x8f, 0x8f
+        }
+    };
+
+    size_t         publicsize;
+    size_t         privatesize;
+
+    r = Fapi_GetTpmBlobs(context,  "HS/SRK/mySignKey", &publicblob,
+                         &publicsize,
+                         &privateblob, &privatesize, NULL);
+    goto_if_error(r, "Error Fapi_GetTpmBlobs", error);
+
+    r = Fapi_Sign(context, "HS/SRK/mySignKey", sigscheme,
+                  &digest.buffer[0], digest.size, &signature, &signatureSize,
+                  &publicKey, NULL);
+    goto_if_error(r, "Error Fapi_Sign", error);
+
+
+    r = Fapi_SetCertificate(context, "HS/SRK/mySignKey", cert);
+    goto_if_error(r, "Error Fapi_SetCertificate", error);
+
+    r = Fapi_List(context, "/", &path_list);
+    goto_if_error(r, "Error Fapi_Delete", error);
+
+    LOG_INFO("\nPathList:\n%s\n", path_list);
+
+    r = Fapi_Delete(context, "/");
+    goto_if_error(r, "Error Fapi_Delete", error);
+
+    SAFE_FREE(publicblob);
+    SAFE_FREE(privateblob);
+    SAFE_FREE(signature);
+    SAFE_FREE(publicKey);
+    SAFE_FREE(path_list);
+    return EXIT_SUCCESS;
+
+error:
+    Fapi_Delete(context, "/HS/SRK");
+    SAFE_FREE(publicblob);
+    SAFE_FREE(privateblob);
+    SAFE_FREE(signature);
+    SAFE_FREE(publicKey);
+    SAFE_FREE(path_list);
+    return EXIT_FAILURE;
+}
+
+int
+test_invoke_fapi(FAPI_CONTEXT *fapi_context)
+{
+    return test_fapi_key_create_sign_policy_provision(fapi_context);
+}
diff --git a/test/integration/fapi-key-create-sign.int.c b/test/integration/fapi-key-create-sign.int.c
new file mode 100644
index 0000000..e2c695d
--- /dev/null
+++ b/test/integration/fapi-key-create-sign.int.c
@@ -0,0 +1,167 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ *******************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#include "tss2_fapi.h"
+
+#include "test-fapi.h"
+#include "fapi_util.h"
+#include "fapi_int.h"
+
+#include "esys_iutil.h"
+#define LOGMODULE test
+#include "util/log.h"
+#include "util/aux_util.h"
+
+#define PASSWORD "abc"
+#define SIGN_TEMPLATE  "sign,noDa"
+
+
+TSS2_RC
+auth_callback(
+    FAPI_CONTEXT *context,
+    char const *description,
+    char **auth,
+    void *userData)
+{
+    (void)description;
+    (void)userData;
+    *auth = strdup(PASSWORD);
+    return_if_null(*auth, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Test the FAPI functions for key creation and usage.
+ *
+ * Tested FAPI commands:
+ *  - Fapi_Provision()
+ *  - Fapi_CreateKey()
+ *  - Fapi_Sign()
+ *  - Fapi_Delete()
+ *  - Fapi_ChangeAuth()
+ *  - Fapi_SetCertificate()
+ *
+ * @param[in,out] context The FAPI_CONTEXT.
+ * @retval EXIT_FAILURE
+ * @retval EXIT_SUCCESS
+ */
+int
+test_fapi_key_create(FAPI_CONTEXT *context)
+{
+    TSS2_RC r;
+    char *sigscheme = NULL;
+
+    const char *cert =
+        "-----BEGIN CERTIFICATE-----\n"
+        "MIIDBjCCAe4CCQDcvXBOEVM0UTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJE\n"
+        "RTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0\n"
+        "cyBQdHkgTHRkMB4XDTE5MDIyODEwNDkyM1oXDTM1MDgyNzEwNDkyM1owRTELMAkG\n"
+        "A1UEBhMCREUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0\n"
+        "IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\n"
+        "AKBi+iKwkgM55iCMwXrLCJlu7TzlMu/LlkyGrm99ip2B5+/Cl6a62d8pKelg6zkH\n"
+        "jI7+AAPteJiW4O+2qVWF8hJ5BXTjGtYbM0iZ6enCb8eyC54C7xVMc21ZIv3ob4Et\n"
+        "50ZOuzY2pfpzE3vIaXt1CkHlfyI/hdK+mM/dVvuCz5p3AIlHrEWS3rSNgWbCsB2E\n"
+        "TM55qSGKaLmtTbUvEKRF0TJrFLntfXkv10QD5pgn52+QV9k59OogqZOsDvkXzKPX\n"
+        "rXF+XC0gLiGBEGAr1dv9F03xMOtO77bQTdGOeC61Tip6Nb0V3ebMckZXwdFi+Nhe\n"
+        "FRuU33CaObtV6u5PZvSue/MCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAcamUPe8I\n"
+        "nMOHcv9x5lVN1joihVRmKc0QqNLFc6XpJY8+U5rGkZvOcDe9Da8L97wDNXpKmU/q\n"
+        "pprj3rT8l3v0Z5xs8Vdr8lxS6T5NhqQV0UCsn1x14gZJcE48y9/LazYi6Zcar+BX\n"
+        "Am4vewAV3HmQ8X2EctsRhXe4wlAq4slIfEWaaofa8ai7BzO9KwpMLsGPWoNetkB9\n"
+        "19+SFt0lFFOj/6vDw5pCpSd1nQlo1ug69mJYSX/wcGkV4t4LfGhV8jRPDsGs6I5n\n"
+        "ETHSN5KV1XCPYJmRCjFY7sIt1x4zN7JJRO9DVw+YheIlduVfkBiF+GlQgLlFTjrJ\n"
+        "VrpSGMIFSu301A==\n"
+        "-----END CERTIFICATE-----\n";
+
+    uint8_t *signature = NULL;
+    char    *publicKey = NULL;
+    uint8_t       *publicblob = NULL;
+    uint8_t       *privateblob = NULL;
+    char *path_list = NULL;
+    size_t         publicsize;
+    size_t         privatesize;
+
+    if (strcmp("P_ECC", fapi_profile) != 0)
+        sigscheme = "RSA_PSS";
+
+    /* We need to reset the passwords again, in order to not brick physical TPMs */
+    r = Fapi_Provision(context, NULL, PASSWORD, NULL);
+    goto_if_error(r, "Error Fapi_Provision", error);
+
+    r = Fapi_SetAuthCB(context, auth_callback, NULL);
+    goto_if_error(r, "Error SetPolicyAuthCallback", error);
+
+    r = Fapi_CreateKey(context, "HS/SRK/mySignKey", SIGN_TEMPLATE, "",
+                       PASSWORD);
+    goto_if_error(r, "Error Fapi_CreateKey_Async", error);
+
+    goto_if_error(r, "Error Fapi_CreateKey_Finish", error);
+    size_t signatureSize = 0;
+
+    TPM2B_DIGEST digest = {
+        .size = 20,
+        .buffer = {
+            0x67, 0x68, 0x03, 0x3e, 0x21, 0x64, 0x68, 0x24, 0x7b, 0xd0,
+            0x31, 0xa0, 0xa2, 0xd9, 0x87, 0x6d, 0x79, 0x81, 0x8f, 0x8f
+        }
+    };
+
+    r = Fapi_GetTpmBlobs(context,  "HS/SRK/mySignKey", &publicblob,
+                         &publicsize,
+                         &privateblob, &privatesize, NULL);
+    goto_if_error(r, "Error Fapi_GetTpmBlobs", error);
+
+    r = Fapi_Sign(context, "HS/SRK/mySignKey", sigscheme,
+                  &digest.buffer[0], digest.size, &signature, &signatureSize,
+                  &publicKey, NULL);
+    goto_if_error(r, "Error Fapi_Sign", error);
+
+    r = Fapi_VerifySignature(context, "HS/SRK/mySignKey",
+                  &digest.buffer[0], digest.size, signature, signatureSize);
+    goto_if_error(r, "Error Fapi_VerifySignature", error);
+
+
+    r = Fapi_SetCertificate(context, "HS/SRK/mySignKey", cert);
+    goto_if_error(r, "Error Fapi_SetCertificate", error);
+
+    r = Fapi_List(context, "/", &path_list);
+    goto_if_error(r, "Error Fapi_Delete", error);
+
+    fprintf(stderr, "\nPathList:\n%s\n", path_list);
+
+    /* We need to reset the passwords again, in order to not brick physical TPMs */
+    r = Fapi_ChangeAuth(context, "/HS", NULL);
+    goto_if_error(r, "Error Fapi_ChangeAuth", error);
+
+    r = Fapi_Delete(context, "/");
+    goto_if_error(r, "Error Fapi_Delete", error);
+
+    SAFE_FREE(path_list);
+    SAFE_FREE(publicblob);
+    SAFE_FREE(privateblob);
+    SAFE_FREE(publicKey);
+    SAFE_FREE(signature);
+    return EXIT_SUCCESS;
+
+error:
+    Fapi_Delete(context, "/HS/SRK");
+    SAFE_FREE(path_list);
+    SAFE_FREE(publicblob);
+    SAFE_FREE(privateblob);
+    SAFE_FREE(publicKey);
+    SAFE_FREE(signature);
+    return EXIT_FAILURE;
+}
+
+int
+test_invoke_fapi(FAPI_CONTEXT *fapi_context)
+{
+    return test_fapi_key_create(fapi_context);
+}
diff --git a/test/integration/fapi-nv-authorizenv-cphash.int.c b/test/integration/fapi-nv-authorizenv-cphash.int.c
new file mode 100644
index 0000000..184dcf0
--- /dev/null
+++ b/test/integration/fapi-nv-authorizenv-cphash.int.c
@@ -0,0 +1,152 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ *******************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "tss2_fapi.h"
+#include "tss2_esys.h"
+
+#include "test-fapi.h"
+#define LOGMODULE test
+#include "util/log.h"
+#include "util/aux_util.h"
+
+TSS2_RC
+check_tpm_cmd(FAPI_CONTEXT *context, TPM2_CC command_code)
+{
+    TSS2_RC r;
+    TSS2_TCTI_CONTEXT *tcti;
+    ESYS_CONTEXT *esys;
+    TPMS_CAPABILITY_DATA *cap_data;
+
+    r = Fapi_GetTcti(context, &tcti);
+    goto_if_error(r, "Error Fapi_GetTcti", error);
+
+    r = Esys_Initialize(&esys, tcti, NULL);
+    goto_if_error(r, "Error Fapi_GetTcti", error);
+
+    r = Esys_GetCapability(esys,
+                           ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
+                           TPM2_CAP_COMMANDS, command_code, 1, NULL, &cap_data);
+    Esys_Finalize(&esys);
+    return_if_error(r, "Error: GetCapabilities");
+
+    if ((cap_data->data.command.commandAttributes[0] & TPMA_CC_COMMANDINDEX_MASK) ==
+            command_code) {
+        free(cap_data);
+        return TSS2_RC_SUCCESS;
+    } else {
+        free(cap_data);
+        return TSS2_FAPI_RC_NOT_IMPLEMENTED;
+    }
+
+error:
+    return r;
+}
+
+/** Test the FAPI NV functions.
+ *
+ * Tested FAPI commands:
+ *  - Fapi_Provision()
+ *  - Fapi_CreateNv()
+ *  - Fapi_NvWrite()
+ *  - Fapi_AuthorizeNv
+ *  - PolicyCpHash
+ *
+ * @param[in,out] context The FAPI_CONTEXT.
+ * @retval EXIT_FAILURE
+ * @retval EXIT_SUCCESS
+ */
+int
+test_fapi_nv_authorizenv_cphash(FAPI_CONTEXT *context)
+{
+    TSS2_RC r;
+    ssize_t ret;
+    uint8_t data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+    char *policy1_name = "/policy/pol_authorize_nv";
+    char *policy1_file = TOP_SOURCEDIR "/test/data/fapi/policy/pol_authorize_nv.json";
+    char *policy2_name = "/policy/pol_cphash";
+    char *policy2_file = TOP_SOURCEDIR "/test/data/fapi/policy/pol_pcr16_0.json";
+    FILE *stream = NULL;
+    char json[1024];
+
+    if (check_tpm_cmd(context, TPM2_CC_PolicyAuthorizeNV) != TPM2_RC_SUCCESS) {
+        LOG_WARNING("Command PolicyAuthorizeNV not available.");
+        return EXIT_SKIP;
+    }
+
+    r = Fapi_Provision(context, NULL, NULL, NULL);
+    goto_if_error(r, "Error Fapi_Provision", error);
+
+    memset(&json[0], 0, sizeof(json));
+    stream = fopen(policy1_file, "r");
+    ret = read(fileno(stream), &json[0], sizeof(json));
+    fclose(stream);
+    if (ret < 0) {
+        LOG_ERROR("IO error %s.", policy1_file);
+        goto error;
+    }
+    json[ret] = '\0';
+    r = Fapi_Import(context, policy1_name, json);
+    goto_if_error(r, "Error Fapi_Import", error);
+
+    memset(&json[0], 0, sizeof(json));
+    stream = fopen(policy2_file, "r");
+    ret = read(fileno(stream), &json[0], sizeof(json));
+    fclose(stream);
+    if (ret < 0) {
+        LOG_ERROR("IO error %s.", policy2_file);
+        goto error;
+    }
+    json[ret] = '\0';
+    r = Fapi_Import(context, policy2_name, json);
+    goto_if_error(r, "Error Fapi_Import", error);
+
+    /* Start the test */
+
+    r = Fapi_CreateNv(context, "/nv/Owner/myNV", "", 34, "", "");
+    goto_if_error(r, "Error Fapi_CreateNv", error);
+
+//TODO: Starts failing if moved after CreateNV2
+    r = Fapi_WriteAuthorizeNv(context, "/nv/Owner/myNV", policy2_name);
+    goto_if_error(r, "Error Fapi_WriteAuthorizeNv", error);
+
+    r = Fapi_CreateNv(context, "/nv/Owner/myNV2", "", sizeof(data), policy1_name, "");
+    goto_if_error(r, "Error Fapi_CreateNv", error);
+
+    r = Fapi_NvWrite(context, "/nv/Owner/myNV2", &data[0], sizeof(data));
+    goto_if_error(r, "Error Fapi_NvWrite", error);
+
+    /* Cleanup */
+
+    r = Fapi_Delete(context, "/nv/Owner/myNV");
+    goto_if_error(r, "Error Fapi_NV_Undefine", error);
+
+    r = Fapi_Delete(context, "/nv/Owner/myNV2");
+    goto_if_error(r, "Error Fapi_NV_Undefine", error);
+
+    r = Fapi_Delete(context, "/");
+    goto_if_error(r, "Error Fapi_Delete", error);
+
+    return EXIT_SUCCESS;
+
+error:
+    return EXIT_FAILURE;
+}
+
+int
+test_invoke_fapi(FAPI_CONTEXT *context)
+{
+    return test_fapi_nv_authorizenv_cphash(context);
+}
diff --git a/test/integration/fapi-nv-extend.int.c b/test/integration/fapi-nv-extend.int.c
new file mode 100644
index 0000000..ce1d69d
--- /dev/null
+++ b/test/integration/fapi-nv-extend.int.c
@@ -0,0 +1,157 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ *******************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <string.h>
+
+#include "tss2_fapi.h"
+
+#define LOGMODULE test
+#include "util/log.h"
+#include "util/aux_util.h"
+
+#define NV_SIZE 32
+
+#define PASSWORD "abc"
+
+static char *password;
+
+TSS2_RC
+auth_callback(
+    FAPI_CONTEXT *context,
+    char const *description,
+    char **auth,
+    void *userData)
+{
+    (void)description;
+    (void)userData;
+    *auth = strdup(password);
+    return_if_null(*auth, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+    return TSS2_RC_SUCCESS;
+}
+
+
+/** Test the FAPI function FAPI_NV_Extend.
+ *
+ * Tested FAPI commands:
+ *  - Fapi_Provision()
+ *  - Fapi_CreateNv()
+ *  - Fapi_NvExtend()
+ *
+ * @param[in,out] context The FAPI_CONTEXT.
+ * @retval EXIT_FAILURE
+ * @retval EXIT_SUCCESS
+ */
+int
+test_fapi_nv_extend(FAPI_CONTEXT *context)
+{
+    TSS2_RC r;
+    char *nvPathExtend = "/nv/Owner/myNVextend";
+    uint8_t *data_dest = NULL;
+    char *log = NULL;
+    size_t dest_size;
+
+    r = Fapi_Provision(context, NULL, NULL, NULL);
+    goto_if_error(r, "Error Fapi_Provision", error);
+
+    /* Test no password, noda set */
+    r = Fapi_CreateNv(context, nvPathExtend, "pcr, noda", 0, "", "");
+    goto_if_error(r, "Error Fapi_CreateNv", error);
+
+    uint8_t data_src[NV_SIZE] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+                                 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+                                 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+                                 0, 1
+                                };
+
+
+    r = Fapi_NvExtend(context, nvPathExtend, &data_src[0], NV_SIZE, "{ \"test\": \"myfile\" }");
+    goto_if_error(r, "Error Fapi_NV_EXTEND", error);
+
+    r = Fapi_NvRead(context, nvPathExtend, &data_dest, &dest_size, &log);
+    goto_if_error(r, "Error Fapi_NvRead", error);
+
+    fprintf(stderr, "\nLog:\n%s\n", log);
+    SAFE_FREE(data_dest);
+
+    r = Fapi_NvExtend(context, nvPathExtend, &data_src[0], NV_SIZE, "{ \"test\": \"myfile\" }");
+    goto_if_error(r, "Error Fapi_NV_EXTEND", error);
+
+    SAFE_FREE(log);
+    r = Fapi_NvRead(context, nvPathExtend, &data_dest, &dest_size, &log);
+    goto_if_error(r, "Error Fapi_NvRead", error);
+
+    fprintf(stderr, "\nLog:\n%s\n", log);
+
+    r = Fapi_Delete(context, nvPathExtend);
+    goto_if_error(r, "Error Fapi_NV_Undefine", error);
+
+    r = Fapi_SetAuthCB(context, auth_callback, "");
+    goto_if_error(r, "Error SetPolicyAuthCallback", error);
+
+    /* Test with password noda  set */
+    password = PASSWORD;
+    r = Fapi_CreateNv(context, nvPathExtend, "pcr, noda", 0, "", PASSWORD);
+    goto_if_error(r, "Error Fapi_CreateNv", error);
+
+    r = Fapi_SetAuthCB(context, auth_callback, "");
+    goto_if_error(r, "Error SetPolicyAuthCallback", error);
+
+    r = Fapi_NvExtend(context, nvPathExtend, &data_src[0], NV_SIZE, "{ \"test\": \"myfile\" }");
+    goto_if_error(r, "Error Fapi_NV_EXTEN", error);
+
+    r = Fapi_Delete(context, nvPathExtend);
+    goto_if_error(r, "Error Fapi_NV_Undefine", error);
+
+    /* Test no password, noda clear */
+    password = "";
+    r = Fapi_CreateNv(context, nvPathExtend, "pcr", 0, "", "");
+    goto_if_error(r, "Error Fapi_CreateNv", error);
+
+    r = Fapi_NvExtend(context, nvPathExtend, &data_src[0], NV_SIZE, "{ \"test\": \"myfile\" }");
+    goto_if_error(r, "Error Fapi_NV_EXTEN", error);
+
+    r = Fapi_Delete(context, nvPathExtend);
+    goto_if_error(r, "Error Fapi_NV_Undefine", error);
+
+    /* Test with password noda clear */
+    password = PASSWORD;
+    r = Fapi_CreateNv(context, nvPathExtend, "pcr", 0, "", PASSWORD);
+    goto_if_error(r, "Error Fapi_CreateNv", error);
+
+    r = Fapi_SetAuthCB(context, auth_callback, "");
+    goto_if_error(r, "Error SetPolicyAuthCallback", error);
+
+    r = Fapi_NvExtend(context, nvPathExtend, &data_src[0], NV_SIZE, "{ \"test\": \"myfile\" }");
+    goto_if_error(r, "Error Fapi_NV_EXTEN", error);
+
+    r = Fapi_Delete(context, nvPathExtend);
+    goto_if_error(r, "Error Fapi_NV_Undefine", error);
+
+    r = Fapi_Delete(context, "/");
+    goto_if_error(r, "Error Fapi_Delete", error);
+
+    SAFE_FREE(log);
+    SAFE_FREE(data_dest);
+    return EXIT_SUCCESS;
+
+error:
+    SAFE_FREE(log);
+    SAFE_FREE(data_dest);
+    return EXIT_FAILURE;
+}
+
+int
+test_invoke_fapi(FAPI_CONTEXT *context)
+{
+    return test_fapi_nv_extend(context);
+}
diff --git a/test/integration/fapi-nv-increment.int.c b/test/integration/fapi-nv-increment.int.c
new file mode 100644
index 0000000..3051623
--- /dev/null
+++ b/test/integration/fapi-nv-increment.int.c
@@ -0,0 +1,167 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ *******************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "tss2_fapi.h"
+
+#include "test-fapi.h"
+#define LOGMODULE test
+#include "util/log.h"
+#include "util/aux_util.h"
+
+#define PASSWORD "abc"
+
+TSS2_RC
+auth_callback(
+    FAPI_CONTEXT *context,
+    char const *description,
+    char **auth,
+    void *userData)
+{
+    (void)description;
+    (void)userData;
+    *auth = strdup(PASSWORD);
+    return_if_null(*auth, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Test the FAPI function FAPI_Increment.
+ *
+ * Tested FAPI commands:
+ *  - Fapi_Provision()
+ *  - Fapi_CreateNv()
+ *  - Fapi_NvIncrement()
+ *  - Fapi_ChangeAuth()
+ *
+ * @param[in,out] context The FAPI_CONTEXT.
+ * @retval EXIT_FAILURE
+ * @retval EXIT_SUCCESS
+ */
+int
+test_fapi_nv_increment(FAPI_CONTEXT *context)
+{
+    TSS2_RC r;
+    char *nvPathCounter = "nv/Owner/myNV_Counter";
+    char *policy_name = "/policy/pol_nv_change_auth";
+    char *policy_file = TOP_SOURCEDIR "/test/data/fapi/policy/pol_nv_change_auth.json";
+    FILE *stream = NULL;
+    char *json_policy = NULL;
+    long policy_size;
+
+    r = Fapi_Provision(context, NULL, NULL, NULL);
+    goto_if_error(r, "Error Fapi_Provision", error);
+
+    r = pcr_reset(context, 16);
+    goto_if_error(r, "Error pcr_reset", error);
+
+    stream = fopen(policy_file, "r");
+    if (!stream) {
+        LOG_ERROR("File %s does not exist", policy_file);
+        goto error;
+    }
+    fseek(stream, 0L, SEEK_END);
+    policy_size = ftell(stream);
+    fclose(stream);
+    json_policy = malloc(policy_size + 1);
+    goto_if_null(json_policy,
+            "Could not allocate memory for the JSON policy",
+            TSS2_FAPI_RC_MEMORY, error);
+    stream = fopen(policy_file, "r");
+    ssize_t ret = read(fileno(stream), json_policy, policy_size);
+    if (ret != policy_size) {
+        LOG_ERROR("IO error %s.", policy_file);
+        goto error;
+    }
+    json_policy[policy_size] = '\0';
+
+    r = Fapi_Import(context, policy_name, json_policy);
+    goto_if_error(r, "Error Fapi_Import", error);
+
+    /* Test no password, noda set */
+    r = Fapi_CreateNv(context, nvPathCounter, "counter, noda", 0, policy_name, "abc");
+    goto_if_error(r, "Error Fapi_CreateNv", error);
+
+    r = Fapi_SetAuthCB(context, auth_callback, "");
+    goto_if_error(r, "Error SetPolicyAuthCallback", error);
+
+    r = Fapi_ChangeAuth(context, nvPathCounter, "abc");
+    goto_if_error(r, "Error Fapi_CreateNv", error);
+
+    r = Fapi_Delete(context, nvPathCounter);
+    goto_if_error(r, "Error Fapi_NV_Undefine", error);
+
+    /* Test no password, noda set */
+    r = Fapi_CreateNv(context, nvPathCounter, "counter, noda", 0, "", "");
+    goto_if_error(r, "Error Fapi_CreateNv", error);
+
+    r = Fapi_NvIncrement(context, nvPathCounter);
+    goto_if_error(r, "Error Fapi_CreateNv", error);
+
+       r = Fapi_Delete(context, nvPathCounter);
+    goto_if_error(r, "Error Fapi_NV_Undefine", error);
+
+    /* Test with password noda set */
+    r = Fapi_CreateNv(context, nvPathCounter, "counter, noda", 0, "", PASSWORD);
+    goto_if_error(r, "Error Fapi_CreateNv", error);
+
+    r = Fapi_SetAuthCB(context, auth_callback, "");
+    goto_if_error(r, "Error SetPolicyAuthCallback", error);
+
+    r = Fapi_NvIncrement(context, nvPathCounter);
+    goto_if_error(r, "Error Fapi_CreateNv", error);
+
+    r = Fapi_Delete(context, nvPathCounter);
+    goto_if_error(r, "Error Fapi_NV_Undefine", error);
+
+    /* Test no password, noda clear */
+    r = Fapi_CreateNv(context, nvPathCounter, "counter", 0, "", "");
+    goto_if_error(r, "Error Fapi_CreateNv", error);
+
+    r = Fapi_NvIncrement(context, nvPathCounter);
+    goto_if_error(r, "Error Fapi_CreateNv", error);
+
+    r = Fapi_Delete(context, nvPathCounter);
+    goto_if_error(r, "Error Fapi_NV_Undefine", error);
+
+    /* Test with password noda clear */
+    r = Fapi_CreateNv(context, nvPathCounter, "counter", 0, "", PASSWORD);
+    goto_if_error(r, "Error Fapi_CreateNv", error);
+
+    r = Fapi_SetAuthCB(context, auth_callback, "");
+    goto_if_error(r, "Error SetPolicyAuthCallback", error);
+
+    r = Fapi_NvIncrement(context, nvPathCounter);
+    goto_if_error(r, "Error Fapi_CreateNv", error);
+
+    r = Fapi_Delete(context, nvPathCounter);
+    goto_if_error(r, "Error Fapi_NV_Undefine", error);
+
+
+    r = Fapi_Delete(context, "/");
+    goto_if_error(r, "Error Fapi_Delete", error);
+
+    SAFE_FREE(json_policy);
+    return EXIT_SUCCESS;
+
+error:
+    SAFE_FREE(json_policy);
+    return EXIT_FAILURE;
+}
+
+int
+test_invoke_fapi(FAPI_CONTEXT *context)
+{
+    return test_fapi_nv_increment(context);
+}
diff --git a/test/integration/fapi-nv-ordinary.int.c b/test/integration/fapi-nv-ordinary.int.c
new file mode 100644
index 0000000..ce93bae
--- /dev/null
+++ b/test/integration/fapi-nv-ordinary.int.c
@@ -0,0 +1,261 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ *******************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "tss2_fapi.h"
+
+#include "test-fapi.h"
+#define LOGMODULE test
+#include "util/log.h"
+#include "util/aux_util.h"
+
+#define NV_SIZE 10
+
+#define PASSWORD "abc"
+
+static char *password;
+
+TSS2_RC
+auth_callback(
+    FAPI_CONTEXT *context,
+    char const *description,
+    char **auth,
+    void *userData)
+{
+    (void)(context);
+    (void)description;
+    (void)userData;
+    *auth = strdup(PASSWORD);
+    return_if_null(*auth, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+    return TSS2_RC_SUCCESS;
+}
+
+TSS2_RC
+action_callback(
+    FAPI_CONTEXT *context,
+    const char *action,
+    void *userData)
+{
+    (void)(context);
+    (void)(userData);
+    if (strcmp(action, "myaction")) {
+        LOG_ERROR("Bad action: %s", action);
+        return TSS2_FAPI_RC_GENERAL_FAILURE;
+    }
+    return TSS2_RC_SUCCESS;
+}
+
+/** Test the FAPI NV functions.
+ *
+ * Tested FAPI commands:
+ *  - Fapi_Provision()
+ *  - Fapi_CreateNv()
+ *  - Fapi_NvWrite()
+ *  - Fapi_NvRead()
+ *  - Fapi_SetDescription()
+ *  - Fapi_GetDescription()
+ *
+ * @param[in,out] context The FAPI_CONTEXT.
+ * @retval EXIT_FAILURE
+ * @retval EXIT_SUCCESS
+ */
+int
+test_fapi_nv_ordinary(FAPI_CONTEXT *context)
+{
+    TSS2_RC r;
+    char *nvPathOrdinary = "/nv/Owner/myNV";
+    uint8_t data_src[NV_SIZE] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+    uint8_t *data_dest = NULL;
+    size_t dest_size = NV_SIZE;
+    char *description1 = "nvDescription";
+    char *description2 = NULL;
+    char *policy_name = "/policy/pol_pcr16_0";
+    char *policy_file = TOP_SOURCEDIR "/test/data/fapi/policy/pol_pcr16_0.json";
+    FILE *stream = NULL;
+    char *json_policy = NULL;
+    long policy_size;
+
+    r = Fapi_Provision(context, NULL, NULL, NULL);
+    goto_if_error(r, "Error Fapi_Provision", error);
+
+    r = pcr_reset(context, 16);
+    goto_if_error(r, "Error pcr_reset", error);
+
+    stream = fopen(policy_file, "r");
+    if (!stream) {
+        LOG_ERROR("File %s does not exist", policy_file);
+        goto error;
+    }
+    fseek(stream, 0L, SEEK_END);
+    policy_size = ftell(stream);
+    fclose(stream);
+    json_policy = malloc(policy_size + 1);
+    goto_if_null(json_policy,
+            "Could not allocate memory for the JSON policy",
+            TSS2_FAPI_RC_MEMORY, error);
+    stream = fopen(policy_file, "r");
+    ssize_t ret = read(fileno(stream), json_policy, policy_size);
+    if (ret != policy_size) {
+        LOG_ERROR("IO error %s.", policy_file);
+        goto error;
+    }
+    json_policy[policy_size] = '\0';
+
+    r = Fapi_Import(context, policy_name, json_policy);
+    goto_if_error(r, "Error Fapi_Import", error);
+
+    r = Fapi_SetPolicyActionCB(context, action_callback, "");
+    goto_if_error(r, "Error Fapi_SetPolicyActionCB", error);
+
+    /* Test with policy */
+    r = Fapi_CreateNv(context, nvPathOrdinary, "noda", 10, policy_name, "");
+    goto_if_error(r, "Error Fapi_CreateNv", error);
+
+    r = Fapi_NvWrite(context, nvPathOrdinary, &data_src[0], NV_SIZE);
+    goto_if_error(r, "Error Fapi_NvWrite", error);
+
+    r = Fapi_NvRead(context, nvPathOrdinary, &data_dest, &dest_size, NULL);
+    goto_if_error(r, "Error Fapi_NvRead", error);
+
+    if (dest_size != NV_SIZE &&
+            memcmp(data_src, data_dest, dest_size) != 0) {
+        LOG_ERROR("Error: result of nv read is wrong.");
+        goto error;
+    }
+
+    r = Fapi_Delete(context, nvPathOrdinary);
+    goto_if_error(r, "Error Fapi_NV_Undefine", error);
+    SAFE_FREE(data_dest);
+
+    /* Empty auth noda set */
+    r = Fapi_CreateNv(context, nvPathOrdinary, "noda", 10, "", "");
+    goto_if_error(r, "Error Fapi_CreateNv", error);
+
+    r = Fapi_NvWrite(context, nvPathOrdinary, &data_src[0], NV_SIZE);
+    goto_if_error(r, "Error Fapi_NvWrite", error);
+
+    r = Fapi_NvRead(context, nvPathOrdinary, &data_dest, &dest_size, NULL);
+    goto_if_error(r, "Error Fapi_NvRead", error);
+
+    if (dest_size != NV_SIZE &&
+            memcmp(data_src, data_dest, dest_size) != 0) {
+        LOG_ERROR("Error: result of nv read is wrong.");
+        goto error;
+    }
+
+    r = Fapi_Delete(context, nvPathOrdinary);
+    goto_if_error(r, "Error Fapi_NV_Undefine", error);
+    SAFE_FREE(data_dest);
+
+    r = Fapi_SetAuthCB(context, auth_callback, "");
+    goto_if_error(r, "Error Fapi_SetAuthCB", error);
+
+    /* Password set and noda set */
+    password = PASSWORD;
+    r = Fapi_CreateNv(context, nvPathOrdinary, "", 10, "", password);
+    goto_if_error(r, "Error Fapi_CreateNv", error);
+
+    r = Fapi_SetAuthCB(context, auth_callback, "");
+    goto_if_error(r, "Error SetPolicyAuthCallback", error);
+
+    r = Fapi_NvWrite(context, nvPathOrdinary, &data_src[0], NV_SIZE);
+    goto_if_error(r, "Error Fapi_NvWrite", error);
+
+    r = Fapi_NvRead(context, nvPathOrdinary, &data_dest, &dest_size, NULL);
+    goto_if_error(r, "Error Fapi_NvRead", error);
+
+    if (dest_size != NV_SIZE &&
+            memcmp(data_src, data_dest, dest_size) != 0) {
+        LOG_ERROR("Error: result of nv read is wrong.");
+        goto error;
+    }
+
+    r = Fapi_Delete(context, nvPathOrdinary);
+    goto_if_error(r, "Error Fapi_NV_Undefine", error);
+    SAFE_FREE(data_dest);
+
+    /* Empty auth noda clear */
+    password = "";
+    r = Fapi_CreateNv(context, nvPathOrdinary, "", 10, "", "");
+    goto_if_error(r, "Error Fapi_CreateNv", error);
+
+    r = Fapi_SetDescription(context, nvPathOrdinary, description1);
+    goto_if_error(r, "Error Fapi_SetDescription", error);
+
+    r = Fapi_GetDescription(context, nvPathOrdinary, &description2);
+    goto_if_error(r, "Error Fapi_GetDescription", error);
+
+    if (strcmp(description1, description2) != 0) {
+        goto_if_error(r, "Different descriptions", error);
+    }
+
+    r = Fapi_NvWrite(context, nvPathOrdinary, &data_src[0], NV_SIZE);
+    goto_if_error(r, "Error Fapi_NvWrite", error);
+
+    r = Fapi_NvRead(context, nvPathOrdinary, &data_dest, &dest_size, NULL);
+    goto_if_error(r, "Error Fapi_NvRead", error);
+
+    if (dest_size != NV_SIZE &&
+            memcmp(data_src, data_dest, dest_size) != 0) {
+        LOG_ERROR("Error: result of nv read is wrong.");
+        goto error;
+    }
+
+    r = Fapi_Delete(context, nvPathOrdinary);
+    goto_if_error(r, "Error Fapi_NV_Undefine", error);
+    SAFE_FREE(data_dest);
+
+    /* Password set and noda clear  */
+    password = PASSWORD;
+    r = Fapi_CreateNv(context, nvPathOrdinary, "", 10, "", password);
+    goto_if_error(r, "Error Fapi_CreateNv", error);
+
+    r = Fapi_SetAuthCB(context, auth_callback, "");
+    goto_if_error(r, "Error SetPolicyAuthCallback", error);
+
+    r = Fapi_NvWrite(context, nvPathOrdinary, &data_src[0], NV_SIZE);
+    goto_if_error(r, "Error Fapi_NvWrite", error);
+
+    r = Fapi_NvRead(context, nvPathOrdinary, &data_dest, &dest_size, NULL);
+    goto_if_error(r, "Error Fapi_NvRead", error);
+
+    if (dest_size != NV_SIZE &&
+            memcmp(data_src, data_dest, dest_size) != 0) {
+        LOG_ERROR("Error: result of nv read is wrong.");
+        goto error;
+    }
+    r = Fapi_Delete(context, nvPathOrdinary);
+    goto_if_error(r, "Error Fapi_NV_Undefine", error);
+
+    r = Fapi_Delete(context, "/");
+    goto_if_error(r, "Error Fapi_Delete", error);
+
+    SAFE_FREE(data_dest);
+    SAFE_FREE(description2);
+    SAFE_FREE(json_policy);
+    return EXIT_SUCCESS;
+
+error:
+    SAFE_FREE(data_dest);
+    SAFE_FREE(description2);
+    SAFE_FREE(json_policy);
+    return EXIT_FAILURE;
+}
+
+int
+test_invoke_fapi(FAPI_CONTEXT *context)
+{
+    return test_fapi_nv_ordinary(context);
+}
diff --git a/test/integration/fapi-nv-set-bits.int.c b/test/integration/fapi-nv-set-bits.int.c
new file mode 100644
index 0000000..db29bbd
--- /dev/null
+++ b/test/integration/fapi-nv-set-bits.int.c
@@ -0,0 +1,129 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ *******************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <string.h>
+
+#include "tss2_fapi.h"
+
+#define LOGMODULE test
+#include "util/log.h"
+#include "util/aux_util.h"
+
+#define PASSWORD "abc"
+
+TSS2_RC
+auth_callback(
+    FAPI_CONTEXT *context,
+    char const *description,
+    char **auth,
+    void *userData)
+{
+    (void)description;
+    (void)userData;
+    *auth = strdup(PASSWORD);
+    return_if_null(*auth, "Out of memory.", TSS2_FAPI_RC_MEMORY);
+    return TSS2_RC_SUCCESS;
+}
+
+/** Test the FAPI function FAPI_Increment.
+ *
+ * Tested FAPI commands:
+ *  - Fapi_Provision()
+ *  - Fapi_CreateNv()
+ *  - Fapi_NvIncrement()
+ *
+ * @param[in,out] context The FAPI_CONTEXT.
+ * @retval EXIT_FAILURE
+ * @retval EXIT_SUCCESS
+ */
+int
+test_fapi_nv_set_bits(FAPI_CONTEXT *context)
+{
+    TSS2_RC r;
+    char *nvPathBitMap = "/nv/Owner/myNV_BitMap";
+
+    r = Fapi_Provision(context, NULL, NULL, NULL);
+    goto_if_error(r, "Error Fapi_Provision", error);
+
+    /* Test no password, noda set */
+    r = Fapi_CreateNv(context, nvPathBitMap, "bitfield, noda", 0, "", "");
+    goto_if_error(r, "Error Fapi_CreateNv", error);
+
+    uint64_t bitmap = 0x0102030405060608;
+
+    r = Fapi_NvSetBits(context, nvPathBitMap, bitmap);
+    goto_if_error(r, "Error Fapi_SetBits", error);
+
+    r = Fapi_Delete(context, nvPathBitMap);
+    goto_if_error(r, "Error Fapi_Delete", error);
+
+    /* Test with password noda set */
+    r = Fapi_CreateNv(context, nvPathBitMap, "bitfield, noda", 0, "", PASSWORD);
+    goto_if_error(r, "Error Fapi_CreateNv", error);
+
+    r = Fapi_SetAuthCB(context, auth_callback, "");
+    goto_if_error(r, "Error SetPolicyAuthCallback", error);
+
+    r = Fapi_NvSetBits(context, nvPathBitMap, bitmap);
+    goto_if_error(r, "Error Fapi_CreateNv", error);
+
+    r = Fapi_Delete(context, nvPathBitMap);
+    goto_if_error(r, "Error Fapi_Delete", error);
+
+    /* Cleanup */
+    r = Fapi_Delete(context, "/HS/SRK");
+    goto_if_error(r, "Error Fapi_Delete", error);
+
+    r = Fapi_Provision(context, NULL, NULL, NULL);
+    goto_if_error(r, "Error Fapi_Provision", error);
+
+    /* Test no password, noda set */
+    r = Fapi_CreateNv(context, nvPathBitMap, "bitfield, noda", 0, "", "");
+    goto_if_error(r, "Error Fapi_CreateNv", error);
+
+    r = Fapi_NvSetBits(context, nvPathBitMap, bitmap);
+    goto_if_error(r, "Error Fapi_NvSetbits", error);
+
+    r = Fapi_Delete(context, nvPathBitMap);
+    goto_if_error(r, "Error Fapi_Delete", error);
+
+    /* Test with password noda set */
+    r = Fapi_CreateNv(context, nvPathBitMap, "bitfield, noda", 0, "", PASSWORD);
+    goto_if_error(r, "Error Fapi_CreateNv", error);
+
+    r = Fapi_SetAuthCB(context, auth_callback, "");
+    goto_if_error(r, "Error SetPolicyAuthCallback", error);
+
+    r = Fapi_NvSetBits(context, nvPathBitMap, bitmap);
+    goto_if_error(r, "Error Fapi_SetBits", error);
+
+    r = Fapi_Delete(context, nvPathBitMap);
+    goto_if_error(r, "Error Fapi_Delete", error);
+
+
+    r = Fapi_Delete(context, "/");
+
+    goto_if_error(r, "Error Fapi_Delete", error);
+
+    return EXIT_SUCCESS;
+
+error:
+    Fapi_Delete(context, "/HS/SRK");
+    return EXIT_FAILURE;
+}
+
+int
+test_invoke_fapi(FAPI_CONTEXT *context)
+{
+    return test_fapi_nv_set_bits(context);
+}
diff --git a/test/integration/fapi-nv-written-policy.int.c b/test/integration/fapi-nv-written-policy.int.c
new file mode 100644
index 0000000..14c1bfd
--- /dev/null
+++ b/test/integration/fapi-nv-written-policy.int.c
@@ -0,0 +1,121 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ *******************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "tss2_fapi.h"
+
+#define LOGMODULE test
+#include "util/log.h"
+#include "util/aux_util.h"
+
+#define NV_SIZE 10
+
+/** Test the FAPI policy Policy_NvWritten.
+ *
+ * Tested FAPI commands:
+ *  - Fapi_Provision()
+ *  - Fapi_CreateNv()
+ *  - Fapi_NvWrite()
+ *  - Fapi_NvRead()
+ *
+ * @param[in,out] context The FAPI_CONTEXT.
+ * @retval EXIT_FAILURE
+ * @retval EXIT_SUCCESS
+ */
+int
+test_fapi_nv_written(FAPI_CONTEXT *context)
+{
+    TSS2_RC r;
+    char *nvPathOrdinary = "/nv/Owner/myNV";
+    char *policy_name =  "/policy/pol_nv_written";
+    char *policy_file = TOP_SOURCEDIR "/test/data/fapi/policy/pol_nv_written.json";
+    FILE *stream = NULL;
+    char *json_policy = NULL;
+    long policy_size;
+    uint8_t *appData = NULL;
+    size_t appDataSize;
+
+    r = Fapi_Provision(context, NULL, NULL, NULL);
+    goto_if_error(r, "Error Fapi_Provision", error);
+
+    uint8_t data_src[NV_SIZE] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+
+    stream = fopen(policy_file, "r");
+    if (!stream) {
+        LOG_ERROR("File %s does not exist", policy_file);
+        goto error;
+    }
+    fseek(stream, 0L, SEEK_END);
+    policy_size = ftell(stream);
+    fclose(stream);
+    json_policy = malloc(policy_size + 1);
+    goto_if_null(json_policy,
+            "Could not allocate memory for the JSON policy",
+            TSS2_FAPI_RC_MEMORY, error);
+
+    stream = fopen(policy_file, "r");
+    ssize_t ret = read(fileno(stream), json_policy, policy_size);
+    if (ret != policy_size) {
+        LOG_ERROR("IO error %s.", policy_file);
+        goto error;
+    }
+    json_policy[policy_size] = '\0';
+
+    r = Fapi_Import(context, policy_name, json_policy);
+    goto_if_error(r, "Error Fapi_Import", error);
+
+    /* Empty auth noda set */
+    r = Fapi_CreateNv(context, nvPathOrdinary, "noda", 10, policy_name, "");
+    goto_if_error(r, "Error Fapi_CreateNv", error);
+
+    r = Fapi_SetAppData(context, nvPathOrdinary, data_src, NV_SIZE);
+    goto_if_error(r, "Error Fapi_SetAppData", error);
+
+    r = Fapi_GetAppData(context, nvPathOrdinary, &appData, &appDataSize);
+    goto_if_error(r, "Error Fapi_GetAppData", error);
+
+    if (NV_SIZE != appDataSize ||
+            memcmp(appData, &data_src[0], appDataSize) != 0) {
+        LOG_ERROR("Error: AppData  equal to origin");
+        goto error;
+    }
+
+    r = Fapi_NvWrite(context, nvPathOrdinary, &data_src[0], NV_SIZE);
+    goto_if_error(r, "Error Fapi_NvWrite", error);
+
+    r = Fapi_Delete(context, nvPathOrdinary);
+    goto_if_error(r, "Error Fapi_NV_Undefine", error);
+
+    r = Fapi_Delete(context, "/");
+    goto_if_error(r, "Error Fapi_Delete", error);
+
+
+    SAFE_FREE(json_policy);
+    SAFE_FREE(appData);
+
+    return EXIT_SUCCESS;
+
+error:
+    SAFE_FREE(json_policy);
+    SAFE_FREE(appData);
+
+    return EXIT_FAILURE;
+}
+
+int
+test_invoke_fapi(FAPI_CONTEXT *context)
+{
+    return test_fapi_nv_written(context);
+}
diff --git a/test/integration/fapi-pcr-test.int.c b/test/integration/fapi-pcr-test.int.c
new file mode 100644
index 0000000..73e8214
--- /dev/null
+++ b/test/integration/fapi-pcr-test.int.c
@@ -0,0 +1,209 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ *******************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "tss2_fapi.h"
+
+#include "test-fapi.h"
+#define LOGMODULE test
+#include "util/log.h"
+#include "util/aux_util.h"
+
+#define EVENT_SIZE 10
+
+//TODO: event should contain json directly, not a string with json inside
+/* This is a list of expected value from the test. Possible returns (for different PCR bank
+   configurations) are concatenated into a long string and the test uses strstr() to find a match.*/
+const char *log_exp[] = {
+"[\n\
+  {\n\
+    \"recnum\":1,\n\
+    \"pcr\":16,\n\
+    \"digests\":[\n\
+      {\n\
+        \"hashAlg\":\"SHA1\",\n\
+        \"digest\":\"494179714a6cd627239dfededf2de9ef994caf03\"\n\
+      },\n\
+      {\n\
+        \"hashAlg\":\"SHA256\",\n\
+        \"digest\":\"1f825aa2f0020ef7cf91dfa30da4668d791c5d4824fc8e41354b89ec05795ab3\"\n\
+      },\n\
+      {\n\
+        \"hashAlg\":\"SHA384\",\n\
+        \"digest\":\"182e95266adff49059e706c61483478fe0688150c8d08b95fab5cfde961f12d903aaf44104af4ce72ba6a4bf20302b2e\"\n\
+      },\n\
+      {\n\
+        \"hashAlg\":\"SHA512\",\n\
+        \"digest\":\"0f89ee1fcb7b0a4f7809d1267a029719004c5a5e5ec323a7c3523a20974f9a3f202f56fadba4cd9e8d654ab9f2e96dc5c795ea176fa20ede8d854c342f903533\"\n\
+      }\n\
+    ],\n\
+    \"type\":\"tss2\",\n\
+    \"sub_event\":{\n\
+      \"data\":\"00010203040506070809\",\n\
+      \"event\":\"{ \\\"test\\\": \\\"myfile\\\" }\"\n\
+    }\n\
+  }\n\
+]",
+"[\n\
+  {\n\
+    \"recnum\":1,\n\
+    \"pcr\":16,\n\
+    \"digests\":[\n\
+      {\n\
+        \"hashAlg\":\"SHA1\",\n\
+        \"digest\":\"494179714a6cd627239dfededf2de9ef994caf03\"\n\
+      },\n\
+      {\n\
+        \"hashAlg\":\"SHA256\",\n\
+        \"digest\":\"1f825aa2f0020ef7cf91dfa30da4668d791c5d4824fc8e41354b89ec05795ab3\"\n\
+      },\n\
+      {\n\
+        \"hashAlg\":\"SHA384\",\n\
+        \"digest\":\"182e95266adff49059e706c61483478fe0688150c8d08b95fab5cfde961f12d903aaf44104af4ce72ba6a4bf20302b2e\"\n\
+      }\n\
+    ],\n\
+    \"type\":\"tss2\",\n\
+    \"sub_event\":{\n\
+      \"data\":\"00010203040506070809\",\n\
+      \"event\":\"{ \\\"test\\\": \\\"myfile\\\" }\"\n\
+    }\n\
+  }\n\
+]",
+"[\n\
+  {\n\
+    \"recnum\":1,\n\
+    \"pcr\":16,\n\
+    \"digests\":[\n\
+      {\n\
+        \"hashAlg\":\"SHA1\",\n\
+        \"digest\":\"494179714a6cd627239dfededf2de9ef994caf03\"\n\
+      },\n\
+      {\n\
+        \"hashAlg\":\"SHA256\",\n\
+        \"digest\":\"1f825aa2f0020ef7cf91dfa30da4668d791c5d4824fc8e41354b89ec05795ab3\"\n\
+      }\n\
+    ],\n\
+    \"type\":\"tss2\",\n\
+    \"sub_event\":{\n\
+      \"data\":\"00010203040506070809\",\n\
+      \"event\":\"{ \\\"test\\\": \\\"myfile\\\" }\"\n\
+    }\n\
+  }\n\
+]",
+"[\n\
+  {\n\
+    \"recnum\":1,\n\
+    \"pcr\":16,\n\
+    \"digests\":[\n\
+      {\n\
+        \"hashAlg\":\"SHA1\",\n\
+        \"digest\":\"494179714a6cd627239dfededf2de9ef994caf03\"\n\
+      }\n\
+    ],\n\
+    \"type\":\"tss2\",\n\
+    \"sub_event\":{\n\
+      \"data\":\"00010203040506070809\",\n\
+      \"event\":\"{ \\\"test\\\": \\\"myfile\\\" }\"\n\
+    }\n\
+  }\n\
+]",
+"[\n\
+  {\n\
+    \"recnum\":1,\n\
+    \"pcr\":16,\n\
+    \"digests\":[\n\
+      {\n\
+        \"hashAlg\":\"SHA256\",\n\
+        \"digest\":\"1f825aa2f0020ef7cf91dfa30da4668d791c5d4824fc8e41354b89ec05795ab3\"\n\
+      }\n\
+    ],\n\
+    \"type\":\"tss2\",\n\
+    \"sub_event\":{\n\
+      \"data\":\"00010203040506070809\",\n\
+      \"event\":\"{ \\\"test\\\": \\\"myfile\\\" }\"\n\
+    }\n\
+  }\n\
+]" };
+
+/** Test the FAPI function FAPI_PCR_Extend.
+ *
+ * Tested FAPI commands:
+ *  - Fapi_Provision()
+ *  - Fapi_PcrExtend()
+ *
+ * @param[in,out] context The FAPI_CONTEXT.
+ * @retval EXIT_FAILURE
+ * @retval EXIT_SUCCESS
+ */
+int
+test_fapi_pcr_test(FAPI_CONTEXT *context)
+{
+    TSS2_RC r;
+    size_t i;
+    uint8_t data[EVENT_SIZE] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+    size_t pcr_digest_size;
+    uint8_t *pcr_digest = NULL;
+    char *log = NULL;
+
+    r = Fapi_Provision(context, NULL, NULL, NULL);
+    goto_if_error(r, "Error Fapi_Provision", error);
+
+    r = pcr_reset(context, 16);
+    goto_if_error(r, "Error pcr_reset", error);
+
+    r = Fapi_PcrExtend(context, 16, data, EVENT_SIZE, "{ \"test\": \"myfile\" }");
+    goto_if_error(r, "Error Fapi_PcrExtend", error);
+
+    r = Fapi_PcrRead(context, 16, &pcr_digest,
+                     &pcr_digest_size, &log);
+    goto_if_error(r, "Error Fapi_PcrRead", error);
+
+    for (i = 0; i < ( sizeof(log_exp) / sizeof(log_exp[0]) ); i++)
+        if (strcmp(log_exp[i], log) == 0)
+            break;
+    if (i >= 3) {
+        LOG_ERROR("Log mismatch. Received: %s", log);
+        goto error;
+    }
+
+    fprintf(stderr, "\n\Event Log:\n%s\n", log);
+
+    SAFE_FREE(pcr_digest);
+    SAFE_FREE(log);
+    r = pcr_reset(context, 16);
+    goto_if_error(r, "Error pcr_reset", error);
+
+    r = Fapi_PcrRead(context, 16, &pcr_digest,
+                     &pcr_digest_size, &log);
+    goto_if_error(r, "Error Fapi_PcrRead", error);
+
+    r = Fapi_Delete(context, "/HS/SRK");
+    goto_if_error(r, "Error Fapi_Delete", error);
+
+    SAFE_FREE(pcr_digest);
+    SAFE_FREE(log);
+    return EXIT_SUCCESS;
+
+error:
+    Fapi_Delete(context, "/HS/SRK");
+    SAFE_FREE(pcr_digest);
+    SAFE_FREE(log);
+    return EXIT_FAILURE;
+}
+
+int
+test_invoke_fapi(FAPI_CONTEXT *context)
+{
+    return test_fapi_pcr_test(context);
+}
diff --git a/test/integration/fapi-platform-certificates.int.c b/test/integration/fapi-platform-certificates.int.c
new file mode 100644
index 0000000..be3355b
--- /dev/null
+++ b/test/integration/fapi-platform-certificates.int.c
@@ -0,0 +1,67 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ *******************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#include "tss2_fapi.h"
+
+#include "test-fapi.h"
+
+#define LOGMODULE test
+#include "util/log.h"
+#include "util/aux_util.h"
+
+/** Test the FAPI functions for platform certificates.
+ *
+ * Tested FAPI commands:
+ *  - Fapi_Provision()
+ *  - Fapi_GetPlatformCertificates()
+ *
+ * @param[in,out] context The FAPI_CONTEXT.
+ * @retval EXIT_FAILURE
+ * @retval EXIT_SUCCESS
+ */
+int
+test_fapi_get_platform_certificates(FAPI_CONTEXT *context)
+{
+    TSS2_RC r;
+    uint8_t *certs = NULL;
+    size_t certsSize = 0;
+
+    r = Fapi_Provision(context, NULL, NULL, NULL);
+    goto_if_error(r, "Error Fapi_Provision", error);
+
+    r = Fapi_GetPlatformCertificates(context, &certs, &certsSize);
+    if (r == TSS2_FAPI_RC_NO_CERT)
+        goto skip;
+    goto_if_error(r, "Error Fapi_GetPlatformCertificates", error);
+
+    Fapi_Free(certs);
+
+    /* Cleanup */
+    r = Fapi_Delete(context, "/HS/SRK");
+    goto_if_error(r, "Error Fapi_Delete", error);
+
+    return EXIT_SUCCESS;
+
+error:
+    Fapi_Delete(context, "/HS/SRK");
+    return EXIT_FAILURE;
+
+ skip:
+    Fapi_Delete(context, "/HS/SRK");
+    return EXIT_SKIP;
+}
+
+int
+test_invoke_fapi(FAPI_CONTEXT *fapi_context)
+{
+    return test_fapi_get_platform_certificates(fapi_context);
+}
diff --git a/test/integration/fapi-quote.int.c b/test/integration/fapi-quote.int.c
new file mode 100644
index 0000000..e8258dc
--- /dev/null
+++ b/test/integration/fapi-quote.int.c
@@ -0,0 +1,172 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ *******************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <json-c/json.h>
+#include <json-c/json_util.h>
+#include <json-c/json_tokener.h>
+
+#include "tss2_fapi.h"
+
+#include "test-fapi.h"
+#define LOGMODULE test
+#include "util/log.h"
+#include "util/aux_util.h"
+
+#define EVENT_SIZE 10
+
+/** Test the FAPI functions for quote commands.
+ *
+ * Tested FAPI commands:
+ *  - Fapi_Provision()
+ *  - Fapi_CreateKey()
+ *  - Fapi_Quote()
+ *  - Fapi_Delete()
+ *  - Fapi_List()
+ *  - Fapi_VerifyQuote()
+ *
+ * @param[in,out] context The FAPI_CONTEXT.
+ * @retval EXIT_FAILURE
+ * @retval EXIT_SUCCESS
+ */
+int
+test_fapi_quote(FAPI_CONTEXT *context)
+{
+    TSS2_RC r;
+    json_object *jso = NULL;
+    char *pubkey_pem = NULL;
+    uint8_t *signature = NULL;
+    char *quoteInfo = NULL;
+    char *pcrEventLog = NULL;
+    char *certificate = NULL;
+    char *export_data = NULL;
+    json_object *jso_public = NULL;
+    uint8_t *pcr_digest = NULL;
+    char *log = NULL;
+    char *pathlist = NULL;
+
+    uint8_t data[EVENT_SIZE] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+    size_t signatureSize = 0;
+    uint32_t pcrList[1] = { 16 };
+    size_t pcr_digest_size = 0;
+
+    r = Fapi_Provision(context, NULL, NULL, NULL);
+
+    goto_if_error(r, "Error Fapi_Provision", error);
+
+    r = Fapi_CreateKey(context, "HS/SRK/mySignKey", "sign,noDa", "", NULL);
+    goto_if_error(r, "Error Fapi_CreateKey", error);
+
+    uint8_t qualifyingData[20] = {
+        0x67, 0x68, 0x03, 0x3e, 0x21, 0x64, 0x68, 0x24, 0x7b, 0xd0,
+        0x31, 0xa0, 0xa2, 0xd9, 0x87, 0x6d, 0x79, 0x81, 0x8f, 0x8f
+    };
+
+    r = pcr_reset(context, 16);
+    goto_if_error(r, "Error pcr_reset", error);
+
+    r = Fapi_PcrExtend(context, 16, data, EVENT_SIZE, "{ \"test\": \"myfile\" }");
+    goto_if_error(r, "Error Fapi_PcrExtend", error);
+
+    r = Fapi_Quote(context, pcrList, 1, "HS/SRK/mySignKey",
+                   "TPM-Quote",
+                   qualifyingData, 20,
+                   &quoteInfo,
+                   &signature, &signatureSize,
+                   &pcrEventLog, &certificate);
+    goto_if_error(r, "Error Fapi_Quote", error);
+
+    r = Fapi_ExportKey(context, "HS/SRK/mySignKey", NULL, &export_data);
+    goto_if_error(r, "Export.", error);
+
+    jso = json_tokener_parse(export_data);
+
+    LOG_INFO("\nExported: %s\n", export_data);
+
+    if (!jso || !json_object_object_get_ex(jso, "pem_ext_public",  &jso_public)) {
+        LOG_ERROR("No public key eyported.");
+        goto error;
+    }
+    pubkey_pem = strdup(json_object_get_string(jso_public));
+    if (!pubkey_pem) {
+        LOG_ERROR("Out of memory.");
+        goto error;
+    }
+
+    r = Fapi_Import(context, "/ext/myExtPubKey", pubkey_pem);
+    goto_if_error(r, "Error Fapi_Import", error);
+
+    r = Fapi_PcrRead(context, 16, &pcr_digest,
+                     &pcr_digest_size, &log);
+    goto_if_error(r, "Error Fapi_PcrRead", error);
+
+    LOG_INFO("\nLog:\n%s\n", log);
+    LOG_INFO("Quote Info:\n%s\n", quoteInfo);
+
+    r = Fapi_VerifyQuote(context, "HS/SRK/mySignKey",
+                         qualifyingData, 20,  quoteInfo,
+                         signature, signatureSize, log);
+    goto_if_error(r, "Error Fapi_Verfiy_Quote", error);
+
+    r = Fapi_Delete(context, "/HS/SRK");
+    goto_if_error(r, "Error Fapi_Delete", error);
+
+//TODO: Move to context2 once we are able to signal non-tpm mode using setenv()
+//    r = Fapi_Initialize(&context2, NULL);
+//    goto_if_error(r, "Error Fapi_Initialize", error);
+
+    r = Fapi_VerifyQuote(context, "/ext/myExtPubKey",
+                         qualifyingData, 20,  quoteInfo,
+                         signature, signatureSize, log);
+    goto_if_error(r, "Error Fapi_Verfiy_Quote", error);
+
+    r = Fapi_Delete(context, "/ext/myExtPubKey");
+    goto_if_error(r, "Error Fapi_Delete", error);
+
+    r = Fapi_List(context, "/", &pathlist);
+    goto_if_error(r, "Pathlist", error);
+
+//    Fapi_Finalize(&context2);
+    json_object_put(jso);
+    SAFE_FREE(pubkey_pem);
+    SAFE_FREE(signature);
+    SAFE_FREE(quoteInfo);
+    SAFE_FREE(pcrEventLog);
+    SAFE_FREE(certificate);
+    SAFE_FREE(export_data);
+    SAFE_FREE(pcr_digest);
+    SAFE_FREE(log);
+    SAFE_FREE(pathlist);
+    return EXIT_SUCCESS;
+
+error:
+    if (jso)
+        json_object_put(jso);
+    SAFE_FREE(pubkey_pem);
+    SAFE_FREE(signature);
+    SAFE_FREE(quoteInfo);
+    SAFE_FREE(pcrEventLog);
+    SAFE_FREE(certificate);
+    SAFE_FREE(export_data);
+    SAFE_FREE(pcr_digest);
+    SAFE_FREE(log);
+    SAFE_FREE(pathlist);
+    return EXIT_FAILURE;
+}
+
+int
+test_invoke_fapi(FAPI_CONTEXT *fapi_context)
+{
+    return test_fapi_quote(fapi_context);
+}
diff --git a/test/integration/fapi-rsa-duplicate.int.c b/test/integration/fapi-rsa-duplicate.int.c
new file mode 100644
index 0000000..107c966
--- /dev/null
+++ b/test/integration/fapi-rsa-duplicate.int.c
@@ -0,0 +1,130 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ *******************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "tss2_fapi.h"
+
+#include "test-fapi.h"
+#define LOGMODULE test
+#include "util/log.h"
+#include "util/aux_util.h"
+
+/** Test the FAPI functions for key creation and usage.
+ *
+ * Tested FAPI commands:
+ *  - Fapi_Provision()
+ *  - Fapi_CreateKey()
+ *  - Fapi_Sign()
+ *  - Fapi_Delete()
+ *  - Fapi_List()
+ *
+ * @param[in,out] context The FAPI_CONTEXT.
+ * @retval EXIT_FAILURE
+ * @retval EXIT_SUCCESS
+ */
+
+#define SIZE 2000
+
+int
+test_fapi_duplicate(FAPI_CONTEXT *context)
+{
+    TSS2_RC r;
+    char *policy_name = "/policy/pol_duplicate";
+    char *policy_file = TOP_SOURCEDIR "/test/data/fapi/policy/pol_duplicate.json";
+    FILE *stream = NULL;
+    char *json_policy = NULL;
+    long policy_size;
+    char *json_duplicate = NULL;
+    char *json_string_pub_key = NULL;
+
+    r = Fapi_Provision(context, NULL, NULL, NULL);
+    goto_if_error(r, "Error Fapi_Provision", error);
+
+    r = pcr_reset(context, 16);
+    goto_if_error(r, "Error pcr_reset", error);
+
+    stream = fopen(policy_file, "r");
+    if (!stream) {
+        LOG_ERROR("File %s does not exist", policy_file);
+        goto error;
+    }
+    fseek(stream, 0L, SEEK_END);
+    policy_size = ftell(stream);
+    fclose(stream);
+    json_policy = malloc(policy_size + 1);
+    goto_if_null(json_policy,
+            "Could not allocate memory for the JSON policy",
+            TSS2_FAPI_RC_MEMORY, error);
+    stream = fopen(policy_file, "r");
+    ssize_t ret = read(fileno(stream), json_policy, policy_size);
+    if (ret != policy_size) {
+        LOG_ERROR("IO error %s.", policy_file);
+        goto error;
+    }
+    json_policy[policy_size] = '\0';
+
+    r = Fapi_Import(context, policy_name, json_policy);
+    goto_if_error(r, "Error Fapi_List", error);
+
+    r = Fapi_CreateKey(context, "HS/SRK/myRsaCryptKey", "restricted,decrypt,noDa",
+                       "", NULL);
+    goto_if_error(r, "Error Fapi_CreateKey", error);
+
+    r = Fapi_ExportKey(context, "HS/SRK/myRsaCryptKey", NULL, &json_string_pub_key);
+    goto_if_error(r, "Error Fapi_CreateKey", error);
+
+    r = Fapi_Import(context, "ext/myNewParent", json_string_pub_key);
+    goto_if_error(r, "Error Fapi_Import", error);
+
+    r = Fapi_CreateKey(context, "HS/SRK/myRsaCryptKey/myRsaCryptKey2",
+                       "exportable,decrypt,noDa", policy_name, NULL);
+    goto_if_error(r, "Error Fapi_CreateKey", error);
+
+    r = Fapi_ExportKey(context, "HS/SRK/myRsaCryptKey/myRsaCryptKey2",
+                       "ext/myNewParent", &json_duplicate);
+    goto_if_error(r, "Error Fapi_CreateKey", error);
+
+    fprintf(stderr, "\nExport Data:\n%s\n", json_duplicate);
+
+    r = Fapi_Import(context, "importedKey", json_duplicate);
+    goto_if_error(r, "Error Fapi_Import", error);
+
+    fprintf(stderr, "Duplicate:\n%s\n", json_duplicate);
+
+#ifdef EK_PERSISTENT
+    Fapi_Delete(context, "P_RSA_EK_persistent");
+#else
+    Fapi_Delete(context, "P_RSA");
+#endif
+    SAFE_FREE(json_string_pub_key);
+    SAFE_FREE(json_duplicate);
+    SAFE_FREE(json_policy);
+    return EXIT_SUCCESS;
+
+error:
+#ifdef EK_PERSISTENT
+    Fapi_Delete(context, "P_RSA_EK_persistent");
+#else
+    Fapi_Delete(context, "P_RSA");
+#endif
+    SAFE_FREE(json_string_pub_key);
+    SAFE_FREE(json_duplicate);
+    SAFE_FREE(json_policy);
+    return EXIT_FAILURE;
+}
+
+int
+test_invoke_fapi(FAPI_CONTEXT *fapi_context)
+{
+    return test_fapi_duplicate(fapi_context);
+}
diff --git a/test/integration/fapi-unseal.int.c b/test/integration/fapi-unseal.int.c
new file mode 100644
index 0000000..e5eda75
--- /dev/null
+++ b/test/integration/fapi-unseal.int.c
@@ -0,0 +1,85 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ *******************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "tss2_fapi.h"
+
+#include "test-fapi.h"
+#define LOGMODULE test
+#include "util/log.h"
+#include "util/aux_util.h"
+
+
+/** Test the FAPI functions for sealing.
+ *
+ * Tested FAPI commands:
+ *  - Fapi_Provision()
+ *  - Fapi_CreateKeySeal()
+ *  - Fapi_Unseal()
+ *  - Fapi_List()
+ *
+ * @param[in,out] context The FAPI_CONTEXT.
+ * @retval EXIT_FAILURE
+ * @retval EXIT_SUCCESS
+ */
+int
+test_fapi_seal(FAPI_CONTEXT *context)
+{
+    TSS2_RC r;
+    size_t resultSize;
+    uint8_t *result = NULL;
+
+    TPM2B_DIGEST digest = {
+        .size = 20,
+        .buffer = {
+            0x67, 0x68, 0x03, 0x3e, 0x21, 0x64, 0x68, 0x24, 0x7b, 0xd0,
+            0x31, 0xa0, 0xa2, 0xd9, 0x87, 0x6d, 0x79, 0x81, 0x8f, 0x8f
+        }
+    };
+
+    r = Fapi_Provision(context, NULL, NULL, NULL);
+    goto_if_error(r, "Error Fapi_Provision", error);
+
+    r = Fapi_CreateSeal(context, "/HS/SRK/mySealObject", "noDa",
+                        digest.size,
+                        "", "",  &digest.buffer[0]);
+    goto_if_error(r, "Error Fapi_CreateSeal", error);
+
+    r = Fapi_Unseal(context, "/HS/SRK/mySealObject", &result,
+                    &resultSize);
+    goto_if_error(r, "Error Fapi_CreateSeal", error);
+
+    r = Fapi_Delete(context, "/HS/SRK/mySealObject");
+    goto_if_error(r, "Error Fapi_Delete", error);
+
+    r = Fapi_Delete(context, "/HS/SRK");
+    goto_if_error(r, "Error Fapi_Delete", error);
+
+    if (resultSize != digest.size ||
+            memcmp(result, &digest.buffer[0], resultSize) != 0) {
+        LOG_ERROR("Error: unealed data not  equal to origin");
+        goto error;
+    }
+
+    SAFE_FREE(result);
+    return EXIT_SUCCESS;
+
+error:
+    SAFE_FREE(result);
+    return EXIT_FAILURE;
+}
+
+int
+test_invoke_fapi(FAPI_CONTEXT *fapi_context)
+{
+    return test_fapi_seal(fapi_context);
+}
diff --git a/test/integration/main-fapi.c b/test/integration/main-fapi.c
new file mode 100644
index 0000000..f17035c
--- /dev/null
+++ b/test/integration/main-fapi.c
@@ -0,0 +1,210 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2017, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ *******************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include "tss2_esys.h"
+#include "tss2_fapi.h"
+
+#include "test-fapi.h"
+
+#define LOGDEFAULT LOGLEVEL_INFO
+#define LOGMODULE test
+#include "util/log.h"
+#include "util/aux_util.h"
+
+#ifndef FAPI_PROFILE
+#define FAPI_PROFILE "P_RSA"
+#endif /* FAPI_PROFILE */
+
+char *fapi_profile = NULL;
+
+TSS2_RC
+pcr_reset(FAPI_CONTEXT *context, UINT32 pcr)
+{
+    TSS2_RC r;
+    TSS2_TCTI_CONTEXT *tcti;
+    ESYS_CONTEXT *esys;
+
+    r = Fapi_GetTcti(context, &tcti);
+    goto_if_error(r, "Error Fapi_GetTcti", error);
+
+    r = Esys_Initialize(&esys, tcti, NULL);
+    goto_if_error(r, "Error Fapi_GetTcti", error);
+
+    r = Esys_PCR_Reset(esys, pcr,
+                       ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE);
+    Esys_Finalize(&esys);
+    goto_if_error(r, "Error Eys_PCR_Reset", error);
+
+error:
+    return r;
+}
+
+/**
+ * This program is a template for integration tests (ones that use the TCTI,
+ * the ESAPI, and FAPI contexts / API directly). It does nothing more than
+ * parsing  command line options that allow the caller (likely a script)
+ * to specifywhich TCTI to use for the test using getenv("TPM20TEST_TCTI").
+ */
+int
+main(int argc, char *argv[])
+{
+    TSS2_RC rc;
+    FAPI_CONTEXT *fapi_context = NULL;
+
+    int ret, size;
+    char *config = NULL;
+    char *config_path = NULL;
+    char *config_env = NULL;
+    char *remove_cmd = NULL;
+    char *system_dir = NULL;
+
+    FILE *config_file;
+
+    char template[] = "/tmp/fapi_tmpdir.XXXXXX";
+
+    char *tmpdir = mkdtemp(template);
+    if (!tmpdir) {
+        LOG_ERROR("No temp dir created");
+        return EXIT_ERROR;
+    }
+
+    fapi_profile = FAPI_PROFILE;
+
+    /* First we construct a fapi config file */
+#ifdef FAPI_NONTPM
+    size = asprintf(&config, "{\n"
+                    "     \"profile_name\": \"" FAPI_PROFILE "\",\n"
+                    "     \"profile_dir\": \"" TOP_SOURCEDIR "/test/data/fapi/\",\n"
+                    "     \"user_dir\": \"%s/user/dir\",\n"
+                    "     \"system_dir\": \"%s/system_dir\",\n"
+                    "     \"system_pcrs\" : [],\n"
+                    "     \"log_dir\" : \"%s\",\n"
+                    "     \"tcti\": \"none\",\n"
+                    "}\n",
+                    tmpdir, tmpdir, tmpdir);
+#else /* FAPI_NONTPM */
+    size = asprintf(&config, "{\n"
+                    "     \"profile_name\": \"" FAPI_PROFILE "\",\n"
+                    "     \"profile_dir\": \"" TOP_SOURCEDIR "/test/data/fapi/\",\n"
+                    "     \"user_dir\": \"%s/user/dir\",\n"
+                    "     \"system_dir\": \"%s/system_dir\",\n"
+                    "     \"system_pcrs\" : [],\n"
+                    "     \"log_dir\" : \"%s\",\n"
+                    "     \"tcti\": \"%s\",\n"
+                    "}\n",
+                    tmpdir, tmpdir, tmpdir,
+                    getenv("TPM20TEST_TCTI"));
+#endif /* FAPI_NONTPM */
+
+    if (size < 0) {
+        LOG_ERROR("Out of memory");
+        ret = EXIT_ERROR;
+        goto error;
+    }
+
+    size = asprintf(&system_dir, "%s/system_dir/", tmpdir);
+    if (size < 0) {
+        LOG_ERROR("Out of memory");
+        ret = EXIT_ERROR;
+        goto error;
+    }
+
+    int rc_mkdir = mkdir(system_dir, 0777);
+    if (rc_mkdir != 0) {
+        LOG_ERROR("mkdir not possible: %i %s", rc_mkdir, system_dir);
+        ret = EXIT_ERROR;
+        goto error;
+    }
+
+    if (size < 0) {
+        LOG_ERROR("Out of memory");
+        ret = EXIT_ERROR;
+        goto error;
+    }
+    LOG_INFO("Using config:\n%s", config);
+
+    /* We construct the path for the config file */
+    size = asprintf(&config_path, "%s/fapi-config.json", tmpdir);
+    if (size < 0) {
+        LOG_ERROR("Out of memory");
+        ret = EXIT_ERROR;
+        goto error;
+    }
+
+    /* We write the config file to disk */
+    config_file = fopen(config_path, "w");
+    if (!config_file) {
+        LOG_ERROR("Opening config file for writing");
+        perror(config_path);
+        ret = EXIT_ERROR;
+        goto error;
+    }
+    size = fprintf(config_file, "%s", config);
+    fclose(config_file);
+    if (size < 0) {
+        LOG_ERROR("Writing config file");
+        perror(config_path);
+        ret = EXIT_ERROR;
+        goto error;
+    }
+
+    /* We set the environment variable for FAPI to consume the config file */
+    size = asprintf(&config_env, "TSS2_FAPICONF=%s", config_path);
+    if (size < 0) {
+        LOG_ERROR("Out of memory");
+        ret = EXIT_ERROR;
+        goto error;
+    }
+    putenv(config_env);
+
+    /***********
+     * Call FAPI
+     ***********/
+
+    rc = Fapi_Initialize(&fapi_context, NULL);
+    if (rc != TSS2_RC_SUCCESS) {
+        LOG_ERROR("Esys_Initialize FAILED! Response Code : 0x%x", rc);
+        ret = EXIT_FAILURE;
+        goto error;
+    }
+
+    ret = test_invoke_fapi(fapi_context);
+    LOG_INFO("Test returned %i", ret);
+    if (ret) goto error;
+
+    size = asprintf(&remove_cmd, "rm -r -f %s", tmpdir);
+    if (size < 0) {
+        LOG_ERROR("Out of memory");
+        ret = EXIT_ERROR;
+        goto error;
+    }
+    if (system(remove_cmd) != 0) {
+        LOG_ERROR("Directory %s can't be deleted.", tmpdir);
+        ret = EXIT_ERROR;
+        goto error;
+    }
+
+error:
+    Fapi_Finalize(&fapi_context);
+
+    if (system_dir) free(system_dir);
+    if (config) free(config);
+    if (config_path) free(config_path);
+    if (config_env) free(config_env);
+    if (remove_cmd) free(remove_cmd);
+
+    return ret;
+}
diff --git a/test/integration/test-fapi.h b/test/integration/test-fapi.h
new file mode 100644
index 0000000..b4bcb98
--- /dev/null
+++ b/test/integration/test-fapi.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/***********************************************************************
+ * Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * Copyright (c) 2017-2018, Intel Corporation
+ *
+ * All rights reserved.
+ ***********************************************************************/
+#include "tss2_fapi.h"
+
+#define EXIT_SKIP 77
+#define EXIT_ERROR 99
+
+#define goto_error_if_not_failed(rc,msg,label)                          \
+    if (rc == TSS2_RC_SUCCESS) {                                        \
+        LOG_ERROR("Error %s (%x) in Line %i: \n", msg, __LINE__, rc);   \
+        goto label; }
+
+/* This variable is set to the same value in order to allow usage in if-statements etc. */
+extern char *fapi_profile;
+
+#define FAPI_POLICIES TOP_SOURCEDIR "/test/data/fapi"
+
+TSS2_RC
+pcr_reset(FAPI_CONTEXT *context, UINT32 pcr);
+/*
+ * This is the prototype for all integration tests in the tpm2-tss
+ * project. Integration tests are intended to exercise the combined
+ * components in the software stack. This typically means executing some
+ * SAPI function using the socket TCTI to communicate with a software
+ * TPM2 simulator.
+ * Return values:
+ * A successful test will return 0, any other value indicates failure.
+ */
+
+int test_invoke_fapi(FAPI_CONTEXT * fapi_context);
diff --git a/test/tpmclient/tpmclient.int.c b/test/tpmclient/tpmclient.int.c
index b9c5936..f21bdbc 100644
--- a/test/tpmclient/tpmclient.int.c
+++ b/test/tpmclient/tpmclient.int.c
@@ -411,6 +411,7 @@
 
         end_auth_session(sessions[i]);
     }
+    end_auth_session(sessions[0]);
 
     for( i = 0; i < ( sizeof(sessions) / sizeof (SESSION *) ); i++ )
     {
@@ -2219,20 +2220,26 @@
     }
 
     /* Test for insufficient size. */
+    /* Create a buffer that is too large */
+    size_t testBufferSize = TPM2_MAX_COMMAND_SIZE -
+            BE_TO_HOST_32(((TPM20_Header_In *)(((_TSS2_SYS_CONTEXT_BLOB *)decryptParamTestSysContext)->cmdBuffer))->commandSize) + 1;
+    UINT8 testBuffer [testBufferSize];
+    memset(testBuffer, 0, testBufferSize);
+    memcpy(testBuffer, nvWriteData.buffer, nvWriteData.size);
+
     rval = Tss2_Sys_GetCpBuffer(decryptParamTestSysContext, &cpBufferUsedSize2, &cpBuffer2);
     CheckPassed(rval);
-    nvWriteData.size = TPM2_MAX_COMMAND_SIZE -
-            BE_TO_HOST_32(((TPM20_Header_In *)(((_TSS2_SYS_CONTEXT_BLOB *)decryptParamTestSysContext)->cmdBuffer))->commandSize) + 1;
-
-    rval = Tss2_Sys_SetDecryptParam(decryptParamTestSysContext, nvWriteData.size, nvWriteData.buffer);
+    rval = Tss2_Sys_SetDecryptParam(decryptParamTestSysContext, testBufferSize,
+            testBuffer);
     CheckFailed(rval, TSS2_SYS_RC_INSUFFICIENT_CONTEXT);
 
     /*
      * Test that one less will work.
      * This tests that we're checking the correct corner case.
      */
-    nvWriteData.size -= 1;
-    rval = Tss2_Sys_SetDecryptParam(decryptParamTestSysContext, nvWriteData.size, nvWriteData.buffer);
+    testBufferSize -= 1;
+    rval = Tss2_Sys_SetDecryptParam(decryptParamTestSysContext, testBufferSize,
+            testBuffer);
     CheckPassed(rval);
 
     rval = Tss2_Sys_NV_Write_Prepare( decryptParamTestSysContext, TPM20_INDEX_PASSWORD_TEST,
diff --git a/test/unit/esys-nulltcti.c b/test/unit/esys-nulltcti.c
index 35f4cdf..04677f1 100644
--- a/test/unit/esys-nulltcti.c
+++ b/test/unit/esys-nulltcti.c
@@ -56,9 +56,10 @@
 }
 
 void
-tctildr_finalize_data (void **data)
+__wrap_Tss2_TctiLdr_Finalize (TSS2_TCTI_CONTEXT **tcti)
 {
-    return;
+    free(*tcti);
+    *tcti = NULL;
 }
 
 static void
diff --git a/test/unit/fapi-json.c b/test/unit/fapi-json.c
new file mode 100644
index 0000000..011e848
--- /dev/null
+++ b/test/unit/fapi-json.c
@@ -0,0 +1,1360 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*******************************************************************************
+ * Copyright 2018, Fraunhofer SIT sponsored by Infineon Technologies AG
+ * All rights reserved.
+ ******************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdarg.h>
+#include <inttypes.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <json-c/json_util.h>
+#include <json-c/json_tokener.h>
+
+#include <setjmp.h>
+#include <cmocka.h>
+
+#include "tss2_fapi.h"
+#include "tpm_json_serialize.h"
+#include "tpm_json_deserialize.h"
+#include "ifapi_json_serialize.h"
+#include "ifapi_json_deserialize.h"
+#include "fapi_policy.h"
+
+#include "util/aux_util.h"
+
+#define LOGMODULE tests
+#include "util/log.h"
+
+/* 3 copies from ifapi_helpers.c */
+static void
+cleanup_policy_element(TPMT_POLICYELEMENT *policy)
+{
+        switch (policy->type) {
+        case POLICYSECRET:
+            SAFE_FREE(policy->element.PolicySecret.objectPath);
+            break;
+        case POLICYAUTHORIZE:
+            SAFE_FREE(policy->element.PolicyAuthorize.keyPath);
+            SAFE_FREE(policy->element.PolicyAuthorize.keyPEM);
+            break;
+        case POLICYAUTHORIZENV:
+            SAFE_FREE( policy->element.PolicyAuthorizeNv.nvPath);
+            SAFE_FREE( policy->element.PolicyAuthorizeNv.policy_buffer);
+            break;
+        case POLICYSIGNED:
+            SAFE_FREE(policy->element.PolicySigned.keyPath);
+            SAFE_FREE(policy->element.PolicySigned.keyPEM);
+            break;
+        case POLICYPCR:
+            SAFE_FREE(policy->element.PolicyPCR.pcrs);
+            break;
+        case POLICYNV:
+            SAFE_FREE(policy->element.PolicyNV.nvPath);
+            break;
+        case POLICYDUPLICATIONSELECT:
+            SAFE_FREE(policy->element.PolicyDuplicationSelect.newParentPath);
+            break;
+        }
+}
+
+static void cleanup_policy_elements(TPML_POLICYELEMENTS *policy)
+{
+    size_t i, j;
+    if (policy != NULL) {
+        for (i = 0; i < policy->count; i++) {
+            if (policy->elements[i].type ==  POLICYOR) {
+                /* Policy with sub policies */
+                TPML_POLICYBRANCHES *branches = policy->elements[i].element.PolicyOr.branches;
+                for (j = 0; j < branches->count; j++) {
+                    SAFE_FREE(branches->authorizations[j].name);
+                    SAFE_FREE(branches->authorizations[j].description);
+                    cleanup_policy_elements(branches->authorizations[j].policy);
+                }
+                SAFE_FREE(branches);
+            } else {
+                cleanup_policy_element(&policy->elements[i]);
+            }
+        }
+        SAFE_FREE(policy);
+    }
+}
+
+/** Free memory allocated during deserialization of policy.
+ *
+ * The object will not be freed (might be declared on the stack).
+ *
+ * @param[in]  object The policy to be cleaned up.
+ *
+ */
+static void ifapi_cleanup_policy_harness(TPMS_POLICY_HARNESS *harness)
+{
+    if (harness) {
+       SAFE_FREE(harness->description);
+       SAFE_FREE(harness->policyAuthorizations);
+       cleanup_policy_elements(harness->policy);
+    }
+}
+
+char * normalize(const char *string) {
+    char *string2 = malloc(strlen(string)+1);
+    int i;
+    int j = 0;
+    for(i = 0; string[i] != '\0'; i++) {
+        if ((string[i] != '\n' && string[i] != ' ')) {
+            string2[j] = string[i];
+            j += 1;
+        }
+    }
+    string2[j] = '\0';
+	return string2;
+}
+
+#define CHECK_ERROR(TYPE, SRC, RC) \
+        { \
+            TYPE out; \
+            TSS2_RC rc; \
+            json_object *jso = json_tokener_parse((SRC)); \
+            assert_non_null(jso); \
+            rc = ifapi_json_ ## TYPE ## _deserialize (jso, &out); \
+            assert_int_equal (rc, RC); \
+            json_object_put(jso); \
+        }
+
+
+
+#define CHECK_JSON2(TYPE, SRC, DST, PSERIALIZE)  \
+        { \
+            TYPE out; \
+            TSS2_RC rc; \
+            json_object *jso = json_tokener_parse((SRC)); \
+            if (!jso) fprintf(stderr, "JSON parsing failed\n"); \
+            assert_non_null(jso); \
+            rc = ifapi_json_ ## TYPE ## _deserialize (jso, &out); \
+            if (rc) fprintf(stderr, "Deserialization failed\n"); \
+            assert_int_equal (rc, TSS2_RC_SUCCESS); \
+            json_object_put(jso); \
+            jso = NULL; \
+            rc = ifapi_json_ ## TYPE ## _serialize (PSERIALIZE, &jso); \
+            assert_int_equal (rc, TSS2_RC_SUCCESS); \
+            assert_non_null(jso); \
+            const char *jso_string = json_object_to_json_string_ext(jso, JSON_C_TO_STRING_PRETTY); \
+            assert_non_null(jso_string); \
+            char *string1 = normalize(jso_string); \
+            char *string2 =  normalize(DST); \
+            assert_string_equal(string1, string2); \
+            json_object_put(jso); \
+            free(string1); \
+            free(string2); \
+        }
+
+#define CHECK_JSON(TYPE, SRC, DST)  \
+    CHECK_JSON2(TYPE, SRC, DST, &out)
+
+#define CHECK_JSON_SIMPLE(TYPE, SRC, DST)  \
+    CHECK_JSON2(TYPE, SRC, DST, out)
+
+#define CHECK_JSON_TO_BIN(TYPE, SRC, DST) \
+        { \
+            TYPE out; \
+            TSS2_RC rc; \
+            TYPE expected = DST; \
+            json_object *jso = json_tokener_parse((SRC)); \
+            assert_non_null(jso); \
+            rc = ifapi_json_ ## TYPE ## _deserialize (jso, &out); \
+            assert_int_equal (rc, TSS2_RC_SUCCESS); \
+            json_object_put(jso); \
+            assert_true(out == expected);       \
+        }
+
+#define CHECK_BIN2(TYPE, BIN, PSERIALIZE)                  \
+    TYPE BIN ## 2; \
+    { \
+        char *jso_string1, *jso_string2; \
+        json_object *jso = NULL; \
+        TSS2_RC rc = ifapi_json_ ## TYPE ## _serialize (PSERIALIZE, &jso); \
+        jso_string1 = strdup(json_object_to_json_string_ext(jso, JSON_C_TO_STRING_PRETTY)); \
+        assert_int_equal (rc, TSS2_RC_SUCCESS); \
+        rc = ifapi_json_ ## TYPE ## _deserialize (jso, &BIN ## 2); \
+        assert_int_equal (rc, TSS2_RC_SUCCESS); \
+        json_object_put(jso); \
+        jso = NULL; \
+        rc = ifapi_json_ ## TYPE ## _serialize (PSERIALIZE ## 2, &jso); \
+        jso_string2 = strdup(json_object_to_json_string_ext(jso, JSON_C_TO_STRING_PRETTY)); \
+        assert_int_equal (rc, TSS2_RC_SUCCESS); \
+        if (strcmp(jso_string1, jso_string2)) { \
+            fprintf(stderr,"\n jso: %s\n", jso_string1); \
+            fprintf(stderr,"\n jso: %s\n", jso_string2); \
+        } \
+        assert_string_equal(jso_string1, jso_string2); \
+        json_object_put(jso); \
+        free(jso_string1); \
+        free(jso_string2); \
+    }
+
+#define CHECK_BIN(TYPE, BIN) \
+    CHECK_BIN2(TYPE, BIN, &BIN)
+
+#define CHECK_BIN_SIMPLE(TYPE, BIN) \
+    CHECK_BIN2(TYPE, BIN, BIN)
+
+static void
+check_bin(void **state)
+{
+    TPM2B_PUBLIC inPublicAES = {
+        .size = 0,
+        .publicArea = {
+            .type = TPM2_ALG_SYMCIPHER,
+            .nameAlg = TPM2_ALG_SHA256,
+            .objectAttributes = (TPMA_OBJECT_USERWITHAUTH |
+                                 TPMA_OBJECT_SIGN_ENCRYPT |
+                                 TPMA_OBJECT_DECRYPT),
+
+            .authPolicy = {
+                 .size = 0,
+             },
+            .parameters.symDetail = {
+                 .sym = {
+                     .algorithm = TPM2_ALG_AES,
+                     .keyBits = {.aes = 128},
+                     .mode = {.aes = TPM2_ALG_CFB}}
+             },
+            .unique.sym = {
+                 .size = 0,
+                 .buffer = {}
+             }
+        }
+    };
+
+    CHECK_BIN(TPM2B_PUBLIC, inPublicAES);
+
+    TPM2B_PUBLIC inPublicECC = {
+            .size = 0,
+            .publicArea = {
+                .type = TPM2_ALG_ECC,
+                .nameAlg = TPM2_ALG_SHA1,
+                .objectAttributes = (
+                             TPMA_OBJECT_USERWITHAUTH |
+                             TPMA_OBJECT_RESTRICTED |
+                             TPMA_OBJECT_SIGN_ENCRYPT |
+                             TPMA_OBJECT_FIXEDTPM |
+                             TPMA_OBJECT_FIXEDPARENT |
+                             TPMA_OBJECT_SENSITIVEDATAORIGIN
+                             ),
+                .authPolicy = {
+                         .size = 0,
+                     },
+
+                .parameters.eccDetail = {
+                     .symmetric = {
+                         .algorithm = TPM2_ALG_NULL,
+                         .keyBits.aes = 128,
+                         .mode.aes = TPM2_ALG_ECB,
+                     },
+                     .scheme = {
+                          .scheme = TPM2_ALG_ECDAA,
+                          .details = { .ecdaa = { .hashAlg = TPM2_ALG_SHA256 }},
+                      },
+                     .curveID = TPM2_ECC_BN_P256,
+                     .kdf = { .scheme = TPM2_ALG_NULL, .details = {} }
+                 },
+                /*
+                  .parameters.asymDetail.symmetric.algorithm = TPM2_ALG_NULL,
+                */
+                .unique.ecc = {
+                     .x = { .size = 0, .buffer = {} } ,
+                     .y = { .size = 0, .buffer = {} } ,
+                 },
+            },
+        };
+
+
+    CHECK_BIN(TPM2B_PUBLIC, inPublicECC);
+
+    TPM2B_PUBLIC inPublicRSA2 = {
+        .size = 0,
+        .publicArea = {
+            .type = TPM2_ALG_RSA,
+            .nameAlg = TPM2_ALG_SHA1,
+            .objectAttributes = (TPMA_OBJECT_USERWITHAUTH |
+                                 TPMA_OBJECT_SIGN_ENCRYPT  |
+                                 TPMA_OBJECT_FIXEDTPM |
+                                 TPMA_OBJECT_FIXEDPARENT |
+                                 TPMA_OBJECT_SENSITIVEDATAORIGIN),
+            .authPolicy = {
+                 .size = 0,
+             },
+            .parameters.rsaDetail = {
+                 .symmetric = {
+                     .algorithm = TPM2_ALG_NULL,
+                     .keyBits.aes = 128,
+                     .mode.aes = TPM2_ALG_CFB},
+                 .scheme = {
+                      .scheme = TPM2_ALG_RSAPSS,
+                      .details = {
+                          .rsapss = { .hashAlg = TPM2_ALG_SHA1 }
+                      }
+                  },
+                 .keyBits = 2048,
+                 .exponent = 0,
+             },
+            .unique.rsa = {
+                 .size = 0,
+                 .buffer = {},
+             },
+        },
+    };
+
+    CHECK_BIN(TPM2B_PUBLIC, inPublicRSA2);
+
+    TPMT_SIG_SCHEME ecc_scheme = { .scheme = TPM2_ALG_ECDSA, .details.ecdsa = TPM2_ALG_SHA1 };
+
+    CHECK_BIN(TPMT_SIG_SCHEME, ecc_scheme);
+
+    TPMT_SIG_SCHEME rsa_scheme = { .scheme = TPM2_ALG_NULL };
+
+    CHECK_BIN(TPMT_SIG_SCHEME, rsa_scheme);
+
+    TPMA_NV testNV = 0xffffff0f ;
+
+    CHECK_BIN_SIMPLE(TPMA_NV, testNV);
+
+    TPML_PCR_SELECTION pcr_selection = {
+        .count = 3,
+        .pcrSelections = {
+         {
+            .hash = TPM2_ALG_SHA1,
+            .sizeofSelect = 3,
+            .pcrSelect = { 01, 00, 03 }},
+        {
+            .hash = TPM2_ALG_SHA256,
+            .sizeofSelect = 3,
+            .pcrSelect = { 01 ,00 ,03 }},
+        {
+            .hash = TPM2_ALG_SHA384,
+            .sizeofSelect = 3,
+            .pcrSelect = { 02, 00, 02 }}
+        }
+    };
+
+    CHECK_BIN(TPML_PCR_SELECTION, pcr_selection);
+
+    IFAPI_ENCRYPTED_DATA encryptedData = {
+        .type = 0,
+        .key_name = {
+            .size = 1,
+            .name = {1}
+        },
+        .cipher = {
+            .size = 0,
+            .buffer = NULL
+        },
+        .sym_private = {
+            .size = 0,
+            .buffer = NULL
+        },
+        .sym_public = {
+            .size = 0,
+            .publicArea = {
+                .type = TPM2_ALG_RSA,
+                .nameAlg = TPM2_ALG_SHA1,
+                .objectAttributes =
+                (TPMA_OBJECT_USERWITHAUTH |
+                 TPMA_OBJECT_SIGN_ENCRYPT |
+                 TPMA_OBJECT_FIXEDTPM |
+                 TPMA_OBJECT_FIXEDPARENT |
+                 TPMA_OBJECT_SENSITIVEDATAORIGIN),
+                .authPolicy = {
+                    .size = 0,
+                    .buffer = { 0 }
+                },
+                .parameters.rsaDetail = {
+                    .symmetric = {.algorithm = TPM2_ALG_NULL, .keyBits.aes = 128, .mode.aes = TPM2_ALG_CFB},
+                    .scheme = {.scheme = TPM2_ALG_RSAPSS, .details = {.rsapss = {.hashAlg = TPM2_ALG_SHA1}}},
+                    .keyBits = 2048,
+                    .exponent = 0,
+                },
+                .unique.rsa = {
+                    .size = 0,
+                    .buffer = { 0 },
+                },
+            },
+        },
+        .sym_key_size = 0,
+        .sym_iv = {.size = 0, .buffer = {0}},
+        .sym_policy_harness = {
+            .description = "",
+            .policyDigests = {
+                .count = 1,
+                .digests = {
+                    {
+                        .hashAlg = TPM2_ALG_SHA256,
+                        .digest = {
+                            .sha256 = {0}
+                        }
+                    }
+                }
+            }
+        }
+    };
+
+    CHECK_BIN(IFAPI_ENCRYPTED_DATA, encryptedData);
+    free(encryptedData2.cipher.buffer);
+
+    IFAPI_IMA_EVENT imaEvent = {
+        .eventData = {
+            .size = 0,
+            .buffer = { 0 }
+        },
+        .eventName = "Event"
+    };
+
+    CHECK_BIN(IFAPI_IMA_EVENT, imaEvent);
+    free(imaEvent2.eventName);
+}
+
+static void
+check_policy_bin(void **state)
+{
+    TPMS_PCRVALUE pcr_value;
+    TPML_PCRVALUES *pcr_value_list;
+    TPML_POLICYBRANCHES *or_branch_list;
+    TPMS_POLICYPCR pcr_policy;
+    TPMT_POLICYELEMENT policy_element0;
+    TPMT_POLICYELEMENT policy_element1;
+    TPMT_POLICYELEMENT policy_element_or;
+    TPML_POLICYELEMENTS *policy_elements_or;
+    TPML_POLICYELEMENTS *policy_elements0;
+    TPML_POLICYELEMENTS *policy_elements1;
+    TPMS_POLICY_HARNESS policy_harness;
+    TPMS_POLICYBRANCH branch0;
+    TPMS_POLICYBRANCH branch1;
+
+    pcr_value.pcr = 16;
+    pcr_value.hashAlg = TPM2_ALG_SHA1;
+    memset(&pcr_value.digest, 0, sizeof(TPMU_HA));
+    memset(&pcr_policy, 0, sizeof(TPMS_POLICYPCR));
+    pcr_value_list = calloc(1, sizeof(TPML_PCRVALUES) + sizeof(TPMS_PCRVALUE));
+    if (pcr_value_list == NULL) {
+        LOG_ERROR("%s", "Out of memory.");
+        return;
+    }
+    pcr_value_list->count = 1;
+    pcr_value_list->pcrs[0] = pcr_value;
+    pcr_policy.pcrs = pcr_value_list;
+    memset(&policy_element0, 0, sizeof(TPMT_POLICYELEMENT));
+    policy_element0.element.PolicyPCR = pcr_policy;
+    policy_element0.type = POLICYPCR;
+    memset(&policy_element1, 0, sizeof(TPMT_POLICYELEMENT));
+    policy_element1.element.PolicyPCR = pcr_policy;
+    policy_element1.type = POLICYPCR;
+    policy_elements0 = calloc(1, sizeof(TPML_POLICYELEMENTS) + sizeof(TPMT_POLICYELEMENT));
+    if (policy_elements0 == NULL) {
+        LOG_ERROR("%s", "Out of memory.");
+        if (pcr_policy.pcrs){
+            free(pcr_policy.pcrs);
+        }
+        return;
+    }
+    policy_elements0->count = 1;
+    policy_elements0->elements[0] = policy_element0;
+    policy_harness.policy = policy_elements0;
+    policy_harness.description = "hareness description";
+    policy_harness.policyAuthorizations = NULL;
+    memset(&policy_harness.policyDigests, 0, sizeof(TPML_DIGEST_VALUES));
+
+    //CHECK_BIN(TPMS_POLICY_HARNESS, policy_harness);
+    {
+        char *jso_string1, *jso_string2;
+        json_object *jso = NULL;
+        TSS2_RC rc = ifapi_json_TPMS_POLICY_HARNESS_serialize (&policy_harness, &jso);
+        jso_string1 = strdup(json_object_to_json_string_ext(jso, JSON_C_TO_STRING_PRETTY));
+        assert_int_equal (rc, TSS2_RC_SUCCESS);
+        rc = ifapi_json_TPMS_POLICY_HARNESS_deserialize (jso, &policy_harness);
+        assert_int_equal (rc, TSS2_RC_SUCCESS);
+        json_object_put(jso);
+        jso = NULL;
+        rc = ifapi_json_TPMS_POLICY_HARNESS_serialize (&policy_harness, &jso);
+        jso_string2 = strdup(json_object_to_json_string_ext(jso, JSON_C_TO_STRING_PRETTY));
+        assert_int_equal (rc, TSS2_RC_SUCCESS);
+        if (strcmp(jso_string1, jso_string2)) {
+            fprintf(stderr,"\n jso: %s\n", jso_string1);
+            fprintf(stderr,"\n jso: %s\n", jso_string2);
+        }
+        assert_string_equal(jso_string1, jso_string2);
+        json_object_put(jso);
+        free(jso_string1);
+        free(jso_string2);
+    }
+    ifapi_cleanup_policy_harness(&policy_harness);
+
+    or_branch_list = calloc(2, sizeof(TPML_POLICYBRANCHES) + (2 * sizeof(TPMS_POLICYBRANCH)));
+    if (or_branch_list == NULL) {
+        LOG_ERROR("%s", "Out of memory.");
+        return;
+    }
+    or_branch_list->count = 2;
+
+    policy_elements1 = calloc(1, sizeof(TPML_POLICYELEMENTS) + sizeof(TPMT_POLICYELEMENT));
+    if (policy_elements1 == NULL) {
+        LOG_ERROR("%s", "Out of memory.");
+        if (or_branch_list){
+            free(or_branch_list);
+        }
+        return;
+    }
+    policy_elements1->count = 1;
+    policy_elements1->elements[0] = policy_element1;
+
+    memset(&branch0, 0, sizeof(TPMS_POLICYBRANCH));
+    memset(&branch1, 0, sizeof(TPMS_POLICYBRANCH));
+    branch0.policy = policy_elements0;
+    branch0.name = "branch0";
+    branch0.description = "description branch 0";
+    branch1.policy = policy_elements1;
+    branch1.name = "branch1";
+    branch1.description = "description branch 1";
+    memcpy(&or_branch_list->authorizations[0], &branch0, sizeof(TPMS_POLICYBRANCH));
+    memcpy(&or_branch_list->authorizations[1], &branch1, sizeof(TPMS_POLICYBRANCH));
+    //or_policy.pcrs = pcr_branch_list;
+
+    policy_elements_or = calloc(1, sizeof(TPML_POLICYELEMENTS) + sizeof(TPMT_POLICYELEMENT));
+    if (policy_elements_or == NULL) {
+        LOG_ERROR("%s", "Out of memory.");
+        if (or_branch_list) {
+            free(or_branch_list);
+        }
+        return;
+    }
+    policy_elements_or->count = 1;
+
+    memset(&policy_element_or, 0, sizeof(TPMT_POLICYELEMENT));
+    policy_element_or.element.PolicyOr.branches = or_branch_list;
+    policy_element_or.type = POLICYOR;
+    policy_elements_or->elements[0] = policy_element_or;
+    policy_harness.policy =  policy_elements_or;
+
+    //CHECK_BIN(TPMS_POLICY_HARNESS, policy_harness);
+    {
+        char *jso_string1, *jso_string2;
+        json_object *jso = NULL;
+        TSS2_RC rc = ifapi_json_TPMS_POLICY_HARNESS_serialize (&policy_harness, &jso);
+        jso_string1 = strdup(json_object_to_json_string_ext(jso, JSON_C_TO_STRING_PRETTY));
+        assert_int_equal (rc, TSS2_RC_SUCCESS);
+        rc = ifapi_json_TPMS_POLICY_HARNESS_deserialize (jso, &policy_harness);
+        assert_int_equal (rc, TSS2_RC_SUCCESS);
+        json_object_put(jso);
+        jso = NULL;
+        rc = ifapi_json_TPMS_POLICY_HARNESS_serialize (&policy_harness, &jso);
+        jso_string2 = strdup(json_object_to_json_string_ext(jso, JSON_C_TO_STRING_PRETTY));
+        assert_int_equal (rc, TSS2_RC_SUCCESS);
+        if (strcmp(jso_string1, jso_string2)) {
+            fprintf(stderr,"\n jso: %s\n", jso_string1);
+            fprintf(stderr,"\n jso: %s\n", jso_string2);
+        }
+        assert_string_equal(jso_string1, jso_string2);
+        json_object_put(jso);
+        free(jso_string1);
+        free(jso_string2);
+    }
+    ifapi_cleanup_policy_harness(&policy_harness);
+
+    free(policy_elements_or);
+    free(policy_elements0);
+    free(policy_elements1);
+    free(or_branch_list);
+    free(pcr_value_list);
+}
+
+static void
+check_json_to_bin(void **state)
+{
+    CHECK_JSON_TO_BIN(UINT64, "22147483647", 22147483647);
+    CHECK_JSON_TO_BIN(UINT64, "\"0xffffffff\"", 0xffffffff);
+    CHECK_JSON_TO_BIN(UINT64, "\"0xfffffffff\"", 0xfffffffff);
+    CHECK_JSON_TO_BIN(UINT32,  "\"0xFfffffff\"", 0xffffffff);
+    CHECK_JSON_TO_BIN(UINT16, "\"0xffff\"", 0xffff);
+}
+
+static void
+check_json_structs(void **state)
+{
+    const char *test_json_TPMS_POLICYTEMPLATE =
+        "{\n"
+        "  \"templateHash\": \"0011223344556677889900112233445566778899\"\n"
+        "}";
+    CHECK_JSON(TPMS_POLICYTEMPLATE, test_json_TPMS_POLICYTEMPLATE, test_json_TPMS_POLICYTEMPLATE);
+
+    const char *test_json_TPM2B_PUBLIC_expected =
+        "{\n"
+        "  \"size\":0,\n"
+        "  \"publicArea\":{\n"
+        "    \"type\":\"ECC\",\n"
+        "    \"nameAlg\":\"SHA1\",\n"
+        "\"objectAttributes\":{"
+        "      \"fixedTPM\":1,"
+        "      \"stClear\":0,"
+        "      \"fixedParent\":1,"
+        "      \"sensitiveDataOrigin\":1,"
+        "      \"userWithAuth\":1,"
+        "      \"adminWithPolicy\":0,"
+        "      \"noDA\":0,"
+        "      \"encryptedDuplication\":0,"
+        "      \"restricted\":1,"
+        "      \"decrypt\":0,"
+        "      \"sign\":1"
+        "    },"
+        "    \"authPolicy\":\"\",\n"
+        "    \"parameters\":{\n"
+        "      \"symmetric\":{\n"
+        "        \"algorithm\":\"NULL\"\n"
+        "      },\n"
+        "      \"scheme\":{\n"
+        "        \"scheme\":\"ECDAA\",\n"
+        "        \"details\":{\n"
+        "          \"hashAlg\":\"SHA256\",\n"
+        "          \"count\":0\n"
+        "        }\n"
+        "      },\n"
+        "      \"curveID\":\"BN_P256\",\n"
+        "      \"kdf\":{\n"
+        "        \"scheme\":\"NULL\"\n"
+        "      }\n"
+        "    },\n"
+        "    \"unique\":{\n"
+        "      \"x\": \"\",\n"
+        "      \"y\": \"\"\n"
+        "    }\n"
+        "  }\n"
+        "}";
+
+    const char *test_json_TPM2B_PUBLIC_src=
+        "{"
+        "  \"size\":0,"
+        "  \"publicArea\":{"
+        "    \"type\":\"ECC\","
+        "    \"nameAlg\":\"SHA1\","
+        "    \"objectAttributes\":["
+        "      \"fixedTPM\","
+        "      \"fixedParent\","
+        "      \"sensitiveDataOrigin\","
+        "      \"userWithAuth\","
+        "      \"restricted\","
+        "      \"sign\""
+        "    ],"
+        "    \"authPolicy\":\"\","
+        "    \"parameters\":{"
+        "      \"symmetric\":{"
+        "        \"algorithm\":\"NULL\""
+        "      },"
+        "      \"scheme\":{"
+        "        \"scheme\":\"ECDAA\","
+        "        \"details\":{"
+        "          \"hashAlg\":\"SHA256\","
+        "          \"count\":0"
+        "        }"
+        "      },"
+        "      \"curveID\":\"ECC_BN_P256\","
+        "      \"kdf\":{"
+        "        \"scheme\":\"NULL\""
+        "      }"
+        "    },"
+        "    \"unique\":{"
+        "      \"x\": \"\",\n"
+        "      \"y\": \"\"\n"
+        "    }"
+        "  }"
+        "}"
+        "";
+    const char *test_json_TPM2B_PUBLIC_dwnc_src =
+        "{"
+        "  \"size\":0,"
+        "  \"publicArea\":{"
+        "    \"type\":\"ecc\","
+        "    \"nameAlg\":\"sha1\","
+        "    \"objectAttributes\":["
+        "      \"fixedTPM\","
+        "      \"fixedParent\","
+        "      \"sensitiveDataOrigin\","
+        "      \"userWithAuth\","
+        "      \"restricted\","
+        "      \"sign\""
+        "    ],"
+        "    \"authPolicy\":\"\","
+        "    \"parameters\":{"
+        "      \"symmetric\":{"
+        "        \"algorithm\":\"null\""
+        "      },"
+        "      \"scheme\":{"
+        "        \"scheme\":\"ecdaa\","
+        "        \"details\":{"
+        "          \"hashAlg\":\"sha256\","
+        "          \"count\":0"
+        "        }"
+        "      },"
+        "      \"curveID\":\"ecc_BN_P256\","
+        "      \"kdf\":{"
+        "        \"scheme\":\"null\""
+        "      }"
+        "    },"
+        "    \"unique\":{"
+        "      \"x\": \"\",\n"
+        "      \"y\": \"\"\n"
+        "      }"
+        "    }"
+        "  }"
+        "}"
+        "";
+
+    CHECK_JSON(TPM2B_PUBLIC, test_json_TPM2B_PUBLIC_src, test_json_TPM2B_PUBLIC_expected);
+    CHECK_JSON(TPM2B_PUBLIC, test_json_TPM2B_PUBLIC_dwnc_src, test_json_TPM2B_PUBLIC_expected);
+
+    const char *test_json_TPMS_ATTEST_certify_src =
+        "{\n"
+        "    \"magic\": \"0xff544347\",\n"
+        "    \"type\": \"ST_ATTEST_CERTIFY\",\n"
+        "    \"qualifiedSigner\": \"0x00010203040506070809a0a1a2a3a4a5a6a7a8a9\",\n"
+        "    \"extraData\": \"0x00010203040506070809b0b1b2b3b4b5b6b7b8b9\",\n"
+        "    \"clockInfo\": {\n"
+        "        \"clock\": 123,\n"
+        "        \"resetCount\": 23,\n"
+        "        \"restartCount\": 1,\n"
+        "        \"safe\": \"yes\"\n"
+        "    },\n"
+        "    \"firmwareVersion\": 783,\n"
+        "    \"attested\": {\n"
+        "        \"name\": \"0x00010203040506070809c0c1c2c3c4c5c6c7c8c9\",\n"
+        "        \"qualifiedName\": \"0x00010203040506070809d0d1d2d3d4d5d6d7d8d9\"\n"
+        "    }\n"
+        "}";
+    const char *test_json_TPMS_ATTEST_certify_expt =
+        "{\n"
+        "    \"magic\": \"VALUE\",\n"
+        "    \"type\": \"ATTEST_CERTIFY\",\n"
+        "    \"qualifiedSigner\": \"00010203040506070809a0a1a2a3a4a5a6a7a8a9\",\n"
+        "    \"extraData\": \"00010203040506070809b0b1b2b3b4b5b6b7b8b9\",\n"
+        "    \"clockInfo\": {\n"
+        "        \"clock\": 123,\n"
+        "        \"resetCount\": 23,\n"
+        "        \"restartCount\": 1,\n"
+        "        \"safe\": \"YES\"\n"
+        "    },\n"
+        "    \"firmwareVersion\": 783,\n"
+        "    \"attested\": {\n"
+        "        \"name\": \"00010203040506070809c0c1c2c3c4c5c6c7c8c9\",\n"
+        "        \"qualifiedName\": \"00010203040506070809d0d1d2d3d4d5d6d7d8d9\"\n"
+        "    }\n"
+        "}";
+    CHECK_JSON(TPMS_ATTEST, test_json_TPMS_ATTEST_certify_src, test_json_TPMS_ATTEST_certify_expt);
+
+    const char *test_json_TPMS_ATTEST_sessionaudit_src =
+        "{\n"
+        "    \"magic\": \"0xff544347\",\n"
+        "    \"type\": \"ST_ATTEST_SESSION_AUDIT\",\n"
+        "    \"qualifiedSigner\": \"0x00010203040506070809a0a1a2a3a4a5a6a7a8a9\",\n"
+        "    \"extraData\": \"0x00010203040506070809b0b1b2b3b4b5b6b7b8b9\",\n"
+        "    \"clockInfo\": {\n"
+        "        \"clock\": [12345,0],\n"
+        "        \"resetCount\": 23,\n"
+        "        \"restartCount\": 1,\n"
+        "        \"safe\": \"yes\"\n"
+        "    },\n"
+        "    \"firmwareVersion\": [783783,0],\n"
+        "    \"attested\": {\n"
+        "        \"exclusiveSession\": \"yes\",\n"
+        "        \"sessionDigest\": \"0x00010203040506070809d0d1d2d3d4d5d6d7d8d9\"\n"
+        "    }\n"
+        "}";
+    const char *test_json_TPMS_ATTEST_sessionaudit_expt =
+        "{\n"
+        "    \"magic\": \"VALUE\",\n"
+        "    \"type\": \"ATTEST_SESSION_AUDIT\",\n"
+        "    \"qualifiedSigner\": \"00010203040506070809a0a1a2a3a4a5a6a7a8a9\",\n"
+        "    \"extraData\": \"00010203040506070809b0b1b2b3b4b5b6b7b8b9\",\n"
+        "    \"clockInfo\": {\n"
+        "        \"clock\": 53021371269120,\n"
+        "        \"resetCount\": 23,\n"
+        "        \"restartCount\": 1,\n"
+        "        \"safe\": \"YES\"\n"
+        "    },\n"
+        "    \"firmwareVersion\": [783783,0],\n"
+        "    \"attested\": {\n"
+        "        \"exclusiveSession\": \"YES\",\n"
+        "        \"sessionDigest\": \"00010203040506070809d0d1d2d3d4d5d6d7d8d9\"\n"
+        "    }\n"
+        "}";
+    CHECK_JSON(TPMS_ATTEST, test_json_TPMS_ATTEST_sessionaudit_src, test_json_TPMS_ATTEST_sessionaudit_expt);
+
+    const char *test_json_TPMS_ATTEST_certifycreation_src =
+        "{\n"
+        "    \"magic\": \"0xff544347\",\n"
+        "    \"type\": \"ST_ATTEST_CREATION\",\n"
+        "    \"qualifiedSigner\": \"0x00010203040506070809a0a1a2a3a4a5a6a7a8a9\",\n"
+        "    \"extraData\": \"0x00010203040506070809b0b1b2b3b4b5b6b7b8b9\",\n"
+        "    \"clockInfo\": {\n"
+        "        \"clock\": 123,\n"
+        "        \"resetCount\": 23,\n"
+        "        \"restartCount\": 1,\n"
+        "        \"safe\": \"yes\"\n"
+        "    },\n"
+        "    \"firmwareVersion\": [0,783],\n"
+        "    \"attested\": {\n"
+        "        \"objectName\": \"0x00010203040506070809c0c1c2c3c4c5c6c7c8c9\",\n"
+        "        \"creationHash\": \"0x00010203040506070809d0d1d2d3d4d5d6d7d8d9\"\n"
+        "    }\n"
+        "}";
+    const char *test_json_TPMS_ATTEST_certifycreation_expt =
+        "{\n"
+        "    \"magic\": \"VALUE\",\n"
+        "    \"type\": \"ATTEST_CREATION\",\n"
+        "    \"qualifiedSigner\": \"00010203040506070809a0a1a2a3a4a5a6a7a8a9\",\n"
+        "    \"extraData\": \"00010203040506070809b0b1b2b3b4b5b6b7b8b9\",\n"
+        "    \"clockInfo\": {\n"
+        "        \"clock\": 123,\n"
+        "        \"resetCount\": 23,\n"
+        "        \"restartCount\": 1,\n"
+        "        \"safe\": \"YES\"\n"
+        "    },\n"
+        "    \"firmwareVersion\": 783,\n"
+        "    \"attested\": {\n"
+        "        \"objectName\": \"00010203040506070809c0c1c2c3c4c5c6c7c8c9\",\n"
+        "        \"creationHash\": \"00010203040506070809d0d1d2d3d4d5d6d7d8d9\"\n"
+        "    }\n"
+        "}";
+    CHECK_JSON(TPMS_ATTEST, test_json_TPMS_ATTEST_certifycreation_src, test_json_TPMS_ATTEST_certifycreation_expt);
+
+    const char *test_json_TPMS_ATTEST_commandaudit_src =
+        "{\n"
+        "    \"magic\": \"0xff544347\",\n"
+        "    \"type\": \"ST_ATTEST_COMMAND_AUDIT\",\n"
+        "    \"qualifiedSigner\": \"0x00010203040506070809a0a1a2a3a4a5a6a7a8a9\",\n"
+        "    \"extraData\": \"0x00010203040506070809b0b1b2b3b4b5b6b7b8b9\",\n"
+        "    \"clockInfo\": {\n"
+        "        \"clock\": 123,\n"
+        "        \"resetCount\": 23,\n"
+        "        \"restartCount\": 1,\n"
+        "        \"safe\": \"yes\"\n"
+        "    },\n"
+        "    \"firmwareVersion\": 783,\n"
+        "    \"attested\": {\n"
+        "        \"auditCounter\": 456,\n"
+        "        \"digestAlg\": \"sha1\",\n"
+        "        \"auditDigest\": \"0x00010203040506070809c0c1c2c3c4c5c6c7c8c9\",\n"
+        "        \"commandDigest\": \"0x00010203040506070809d0d1d2d3d4d5d6d7d8d9\"\n"
+        "    }\n"
+        "}";
+    const char *test_json_TPMS_ATTEST_commandaudit_expt =
+        "{\n"
+        "    \"magic\": \"VALUE\",\n"
+        "    \"type\": \"ATTEST_COMMAND_AUDIT\",\n"
+        "    \"qualifiedSigner\": \"00010203040506070809a0a1a2a3a4a5a6a7a8a9\",\n"
+        "    \"extraData\": \"00010203040506070809b0b1b2b3b4b5b6b7b8b9\",\n"
+        "    \"clockInfo\": {\n"
+        "        \"clock\": 123,\n"
+        "        \"resetCount\": 23,\n"
+        "        \"restartCount\": 1,\n"
+        "        \"safe\": \"YES\"\n"
+        "    },\n"
+        "    \"firmwareVersion\": 783,\n"
+        "    \"attested\": {\n"
+        "        \"auditCounter\": 456,\n"
+        "        \"digestAlg\": \"SHA1\",\n"
+        "        \"auditDigest\": \"00010203040506070809c0c1c2c3c4c5c6c7c8c9\",\n"
+        "        \"commandDigest\": \"00010203040506070809d0d1d2d3d4d5d6d7d8d9\"\n"
+        "    }\n"
+        "}";
+    CHECK_JSON(TPMS_ATTEST, test_json_TPMS_ATTEST_commandaudit_src, test_json_TPMS_ATTEST_commandaudit_expt);
+
+    const char *test_json_TPMS_ATTEST_time_src =
+        "{\n"
+        "    \"magic\": \"0xff544347\",\n"
+        "    \"type\": \"ST_ATTEST_TIME\",\n"
+        "    \"qualifiedSigner\": \"0x00010203040506070809a0a1a2a3a4a5a6a7a8a9\",\n"
+        "    \"extraData\": \"0x00010203040506070809b0b1b2b3b4b5b6b7b8b9\",\n"
+        "    \"clockInfo\": {\n"
+        "        \"clock\": 123,\n"
+        "        \"resetCount\": 23,\n"
+        "        \"restartCount\": 1,\n"
+        "        \"safe\": \"yes\"\n"
+        "    },\n"
+        "    \"firmwareVersion\": 783,\n"
+        "    \"attested\": {\n"
+        "        \"time\": {\n"
+        "            \"time\": 234,\n"
+        "            \"clockInfo\": {\n"
+        "                \"clock\": 123,\n"
+        "                \"resetCount\": 23,\n"
+        "                \"restartCount\": 1,\n"
+        "                \"safe\": \"yes\"\n"
+        "            }\n"
+        "        },\n"
+        "        \"firmwareVersion\": 783\n"
+        "    }\n"
+        "}";
+    const char *test_json_TPMS_ATTEST_time_expt =
+        "{\n"
+        "    \"magic\": \"VALUE\",\n"
+        "    \"type\": \"ATTEST_TIME\",\n"
+        "    \"qualifiedSigner\": \"00010203040506070809a0a1a2a3a4a5a6a7a8a9\",\n"
+        "    \"extraData\": \"00010203040506070809b0b1b2b3b4b5b6b7b8b9\",\n"
+        "    \"clockInfo\": {\n"
+        "        \"clock\": 123,\n"
+        "        \"resetCount\": 23,\n"
+        "        \"restartCount\": 1,\n"
+        "        \"safe\": \"YES\"\n"
+        "    },\n"
+        "    \"firmwareVersion\": 783,\n"
+        "    \"attested\": {\n"
+        "        \"time\": {\n"
+        "            \"time\": 234,\n"
+        "            \"clockInfo\": {\n"
+        "                \"clock\": 123,\n"
+        "                \"resetCount\": 23,\n"
+        "                \"restartCount\": 1,\n"
+        "                \"safe\": \"YES\"\n"
+        "            }\n"
+        "        },\n"
+        "        \"firmwareVersion\": 783\n"
+        "    }\n"
+        "}";
+    CHECK_JSON(TPMS_ATTEST, test_json_TPMS_ATTEST_time_src, test_json_TPMS_ATTEST_time_expt);
+
+    const char *test_json_TPMS_ATTEST_certifynv_src =
+        "{\n"
+        "    \"magic\": \"0xff544347\",\n"
+        "    \"type\": \"ST_ATTEST_NV\",\n"
+        "    \"qualifiedSigner\": \"0x00010203040506070809a0a1a2a3a4a5a6a7a8a9\",\n"
+        "    \"extraData\": \"0x00010203040506070809b0b1b2b3b4b5b6b7b8b9\",\n"
+        "    \"clockInfo\": {\n"
+        "        \"clock\": 123,\n"
+        "        \"resetCount\": 23,\n"
+        "        \"restartCount\": 1,\n"
+        "        \"safe\": \"yes\"\n"
+        "    },\n"
+        "    \"firmwareVersion\": 783,\n"
+        "    \"attested\": {\n"
+        "        \"indexName\": \"0x00010203040506070809c0c1c2c3c4c5c6c7c8c9\",\n"
+        "        \"offset\": 10,\n"
+        "        \"nvContents\": \"0x00010203040506070809d0d1d2d3d4d5d6d7d8d9\"\n"
+        "    }\n"
+        "}";
+    const char *test_json_TPMS_ATTEST_certifynv_expt =
+        "{\n"
+        "    \"magic\": \"VALUE\",\n"
+        "    \"type\": \"ATTEST_NV\",\n"
+        "    \"qualifiedSigner\": \"00010203040506070809a0a1a2a3a4a5a6a7a8a9\",\n"
+        "    \"extraData\": \"00010203040506070809b0b1b2b3b4b5b6b7b8b9\",\n"
+        "    \"clockInfo\": {\n"
+        "        \"clock\": 123,\n"
+        "        \"resetCount\": 23,\n"
+        "        \"restartCount\": 1,\n"
+        "        \"safe\": \"YES\"\n"
+        "    },\n"
+        "    \"firmwareVersion\": 783,\n"
+        "    \"attested\": {\n"
+        "        \"indexName\": \"00010203040506070809c0c1c2c3c4c5c6c7c8c9\",\n"
+        "        \"offset\": 10,\n"
+        "        \"nvContents\": \"00010203040506070809d0d1d2d3d4d5d6d7d8d9\"\n"
+        "    }\n"
+        "}";
+    CHECK_JSON(TPMS_ATTEST, test_json_TPMS_ATTEST_certifynv_src, test_json_TPMS_ATTEST_certifynv_expt);
+
+    const char *test_json_TPMT_KEYEDHASH_SCHEME_hmac_src =
+        "{\n"
+        "    \"scheme\": \"HMAC\",\n"
+        "    \"details\": {\n"
+        "        \"hashAlg\": \"SHA256\"\n"
+        "    }\n"
+        "}";
+    const char *test_json_TPMT_KEYEDHASH_SCHEME_hmac_expt =
+        "{\n"
+        "    \"scheme\": \"HMAC\",\n"
+        "    \"details\": {\n"
+        "        \"hashAlg\": \"SHA256\"\n"
+        "    }\n"
+        "}";
+    CHECK_JSON(TPMT_KEYEDHASH_SCHEME, test_json_TPMT_KEYEDHASH_SCHEME_hmac_src, test_json_TPMT_KEYEDHASH_SCHEME_hmac_expt);
+
+    const char *test_json_TPMT_KEYEDHASH_SCHEME_xor_src =
+        "{\n"
+        "    \"scheme\": \"XOR\",\n"
+        "    \"details\": {\n"
+        "        \"hashAlg\": \"SHA256\",\n"
+        "        \"kdf\": \"MGF1\"\n"
+        "    }\n"
+        "}";
+    const char *test_json_TPMT_KEYEDHASH_SCHEME_xor_expt =
+        "{\n"
+        "    \"scheme\": \"XOR\",\n"
+        "    \"details\": {\n"
+        "        \"hashAlg\": \"SHA256\",\n"
+        "        \"kdf\": \"MGF1\"\n"
+        "    }\n"
+        "}";
+    CHECK_JSON(TPMT_KEYEDHASH_SCHEME, test_json_TPMT_KEYEDHASH_SCHEME_xor_src, test_json_TPMT_KEYEDHASH_SCHEME_xor_expt);
+
+}
+
+static void
+check_json_constants(void **state)
+{
+    CHECK_JSON_SIMPLE(TPMI_ALG_HASH, "\"sha1\"", "\"SHA1\"");
+    CHECK_JSON_SIMPLE(TPMI_ALG_HASH, "\"0x04\"", "\"SHA1\"");
+    CHECK_JSON_SIMPLE(TPMI_ALG_HASH, "4", "\"SHA1\"");
+}
+
+static void
+check_json_numbers(void **state)
+{
+    CHECK_JSON_SIMPLE(UINT16, "10", "10");
+    CHECK_JSON_SIMPLE(UINT16, "\"0x0a\"", "10");
+    CHECK_JSON_SIMPLE(UINT64, "10000000000000000","[2328306,1874919424]");
+}
+
+static void
+check_json_bits(void **state)
+{
+      const char *test_json_TPMA_NV_expected =\
+                    "{"
+                    "  \"PPWRITE\":0,"
+                    "  \"OWNERWRITE\":1,"
+                    "  \"AUTHWRITE\":1,"
+                    "  \"POLICYWRITE\":1,"
+                    "  \"POLICY_DELETE\":1,"
+                    "  \"WRITELOCKED\":0,"
+                    "  \"WRITEALL\":0,"
+                    "  \"WRITEDEFINE\":0,"
+                    "  \"WRITE_STCLEAR\":0,"
+                    "  \"GLOBALLOCK\":0,"
+                    "  \"PPREAD\":0,"
+                    "  \"OWNERREAD\":1,"
+                    "  \"AUTHREAD\":1,"
+                    "  \"POLICYREAD\":1,"
+                    "  \"NO_DA\":0,"
+                    "  \"ORDERLY\":1,"
+                    "  \"CLEAR_STCLEAR\":1,"
+                    "  \"READLOCKED\":1,"
+                    "  \"WRITTEN\":1,"
+                    "  \"PLATFORMCREATE\":0,"
+                    "  \"READ_STCLEAR\":0,"
+                    "  \"TPM2_NT\":\"COUNTER\""
+                    "}";
+
+    const char *test_json_TPMA_NV_src_array =\
+                    "["
+                    "  \"nv_ownerwrite\","
+                    "  \"nv_authwrite\","
+                    "  \"nv_policywrite\","
+                    "  \"nv_policy_delete\","
+                    "  \"nv_ownerread\","
+                    "  \"nv_authread\","
+                    "  \"nv_policyread\","
+                    "  \"nv_orderly\","
+                    "  \"nv_clear_stclear\","
+                    "  \"nv_readlocked\","
+                    "  \"nv_written\","
+                    "  {"
+                    "    \"TPM2_NT\": \"NT_COUNTER\""
+                    "  }"
+                    "]";
+
+       const char *test_json_TPMA_NV_src_struct =\
+                    "{"
+                    "  \"TPMA_NV_OWNERWRITE\":\"YES\","
+                    "  \"TPMA_NV_AUTHWRITE\":\"yes\","
+                    "  \"TPMA_NV_POLICYWRITE\":\"TPM2_YES\","
+                    "  \"TPMA_NV_POLICY_DELETE\":\"tpm2_yes\","
+                    "  \"TPMA_NV_OWNERREAD\":\"SET\","
+                    "  \"TPMA_NV_AUTHREAD\":\"set\","
+                    "  \"TPMA_NV_POLICYREAD\":1,"
+                    "  \"TPMA_NV_ORDERLY\":1,"
+                    "  \"TPMA_NV_CLEAR_STCLEAR\":1,"
+                    "  \"TPMA_NV_READLOCKED\":1,"
+                    "  \"TPMA_NV_WRITTEN\":1,"
+                    "  \"TPM2_NT\":1"
+                    "  }";
+
+    CHECK_JSON_SIMPLE(TPMA_NV, test_json_TPMA_NV_src_array, test_json_TPMA_NV_expected);
+    CHECK_JSON_SIMPLE(TPMA_NV, test_json_TPMA_NV_src_struct, test_json_TPMA_NV_expected);
+}
+
+static void
+check_json_policy(void **state)
+{
+     const char *test_json_policy_nv_src =       \
+        "{"
+        "  \"description\":\"Description pol_nv\","
+        "  \"policyDigests\":["
+        "  ],"
+        "  \"policyAuthorizations\":["
+        "  ],"
+        "    \"policy\":["
+        "        {"
+        "            \"type\": \"POLICYNV\","
+        "                   \"nvPath\": \"myNV\","
+        "                   \"operandB\": \"01030304\""
+        "      }"
+        "  ]"
+        "}";
+
+       const char *test_json_policy_nv_expected =       \
+        "{"
+        "  \"description\":\"Description pol_nv\","
+        "  \"policyDigests\":["
+        "  ],"
+        "  \"policyAuthorizations\":["
+        "  ],"
+        "    \"policy\":["
+        "        {"
+        "            \"type\": \"POLICYNV\","
+        "                   \"nvPath\": \"myNV\","
+        "                   \"operandB\": \"01030304\""
+        "     }"
+        "  ]"
+        "}";
+
+
+//    CHECK_JSON(TPMS_POLICY_HARNESS, test_json_policy_nv_src, test_json_policy_nv_expected);
+        {
+            TPMS_POLICY_HARNESS out;
+            TSS2_RC rc;
+            json_object *jso = json_tokener_parse(test_json_policy_nv_src);
+            if (!jso) fprintf(stderr, "JSON parsing failed\n");
+            assert_non_null(jso);
+            rc = ifapi_json_TPMS_POLICY_HARNESS_deserialize (jso, &out);
+            if (rc) fprintf(stderr, "Deserialization failed\n");
+            assert_int_equal (rc, TSS2_RC_SUCCESS);
+            json_object_put(jso);
+            jso = NULL;
+            rc = ifapi_json_TPMS_POLICY_HARNESS_serialize (&out, &jso);
+            assert_int_equal (rc, TSS2_RC_SUCCESS);
+            assert_non_null(jso);
+            const char *jso_string = json_object_to_json_string_ext(jso, JSON_C_TO_STRING_PRETTY);
+            assert_non_null(jso_string);
+            char *string1 = normalize(jso_string);
+            char *string2 =  normalize(test_json_policy_nv_expected);
+            assert_string_equal(string1, string2);
+            json_object_put(jso);
+            ifapi_cleanup_policy_harness(&out);
+            free(string1);
+            free(string2);
+        }
+
+    const char *test_json_policy_or_src =       \
+        "{"
+        "  \"description\":\"hareness description\","
+        "  \"policyDigests\":["
+        "    {"
+        "      \"hashAlg\":\"SHA256\","
+        "      \"digest\":\"59215cb6c21a60e26b2cc479334a021113611903795507c1227659e2aef23d16\""
+        "    }"
+        "  ],"
+        "  \"policy\":["
+        "    {"
+        "      \"type\":\"POLICYOR\","
+        "      \"policyDigests\":["
+        "        {"
+        "          \"hashAlg\":\"SHA256\","
+        "          \"digest\":\"59215cb6c21a60e26b2cc479334a021113611903795507c1227659e2aef23d16\""
+        "        }"
+        "      ],"
+        "        \"branches\":["
+        "          {"
+        "            \"name\":\"branch1\","
+        "            \"description\":\"description branch 1\","
+        "            \"policy\":["
+        "              {"
+        "                \"type\":\"POLICYPCR\","
+        "                \"policyDigests\":["
+        "                  {"
+        "                    \"hashAlg\":\"SHA256\","
+        "                    \"digest\":\"17d552f8e39ad882f6b3c09ae139af59616bf6a63f4093d6d20e9e1b9f7cdb6e\""
+        "                  }"
+        "                ],"
+        "                  \"pcrs\":["
+        "                    {"
+        "                      \"pcr\":16,"
+        "                      \"hashAlg\":\"SHA1\","
+        "                      \"digest\":\"0000000000000000000000000000000000000000\""
+        "                    }"
+        "                  ]"
+        "              }"
+        "            ],"
+        "            \"policyDigests\":["
+        "              {"
+        "                \"hashAlg\":\"SHA256\","
+        "                \"digest\":\"17d552f8e39ad882f6b3c09ae139af59616bf6a63f4093d6d20e9e1b9f7cdb6e\""
+        "              }"
+        "            ]"
+        "          },"
+        "          {"
+        "            \"name\":\"branch1\","
+        "            \"description\":\"description branch 1\","
+        "            \"policy\":["
+        "              {"
+        "                \"type\":\"POLICYPCR\","
+        "                \"policyDigests\":["
+        "                  {"
+        "                    \"hashAlg\":\"SHA256\","
+        "                    \"digest\":\"17d552f8e39ad882f6b3c09ae139af59616bf6a63f4093d6d20e9e1b9f7cdb6e\""
+        "                  }"
+        "                ],"
+        "                  \"pcrs\":["
+        "                    {"
+        "                      \"pcr\":16,"
+        "                      \"hashAlg\":\"SHA1\","
+        "                      \"digest\":\"0000000000000000000000000000000000000000\""
+        "                    }"
+        "                  ]"
+        "              }"
+        "            ],"
+        "            \"policyDigests\":["
+        "              {"
+        "                \"hashAlg\":\"SHA256\","
+        "                \"digest\":\"17d552f8e39ad882f6b3c09ae139af59616bf6a63f4093d6d20e9e1b9f7cdb6e\""
+        "              }"
+        "            ]"
+        "          }"
+        "        ]"
+        "    }"
+        "  ]"
+        "}";
+
+    char *test_json_policy_or_expected = strdup(test_json_policy_or_src);
+    if (test_json_policy_or_expected == NULL){
+        LOG_ERROR("%s", "Out of memory.");
+        return;
+    }
+//    CHECK_JSON(TPMS_POLICY_HARNESS, test_json_policy_or_src, test_json_policy_or_expected);
+        {
+            TPMS_POLICY_HARNESS out;
+            TSS2_RC rc;
+            json_object *jso = json_tokener_parse(test_json_policy_or_src);
+            if (!jso) fprintf(stderr, "JSON parsing failed\n");
+            assert_non_null(jso);
+            rc = ifapi_json_TPMS_POLICY_HARNESS_deserialize (jso, &out);
+            if (rc) fprintf(stderr, "Deserialization failed\n");
+            assert_int_equal (rc, TSS2_RC_SUCCESS);
+            json_object_put(jso);
+            jso = NULL;
+            rc = ifapi_json_TPMS_POLICY_HARNESS_serialize (&out, &jso);
+            assert_int_equal (rc, TSS2_RC_SUCCESS);
+            assert_non_null(jso);
+            const char *jso_string = json_object_to_json_string_ext(jso, JSON_C_TO_STRING_PRETTY);
+            assert_non_null(jso_string);
+            char *string1 = normalize(jso_string);
+            char *string2 =  normalize(test_json_policy_or_expected);
+            assert_string_equal(string1, string2);
+            json_object_put(jso);
+            ifapi_cleanup_policy_harness(&out);
+            free(string1);
+            free(string2);
+        }
+    free(test_json_policy_or_expected);
+}
+
+
+static void
+check_json_tpm2bs(void **state)
+{
+    CHECK_JSON(TPM2B_DIGEST, "\"0x0102\"", "\"0102\"");
+    CHECK_JSON(TPM2B_DIGEST, "\"0102\"", "\"0102\"");
+    CHECK_JSON(TPM2B_DIGEST, "\"caffee\"", "\"caffee\"");
+}
+
+static void
+check_error(void **state)
+{
+   /* Value is > then max value for UINT */
+    CHECK_ERROR(UINT16, "\"0x10000\"", TSS2_FAPI_RC_BAD_VALUE);
+    CHECK_ERROR(UINT32, "\"0x100000000\"", TSS2_FAPI_RC_BAD_VALUE);
+
+    /* Digest/list is too large*/
+    CHECK_ERROR(TPM2B_DIGEST, "\"0x0102222222222222222222222222222222222222222222222222222"
+                "22222222222222222222222222222222222222222222222222222222222222222222222222222\"",
+                TSS2_FAPI_RC_BAD_VALUE);
+
+    /* Illegal values */
+    CHECK_ERROR(TPMI_ALG_HASH, "\"SHA9999\"", TSS2_FAPI_RC_BAD_VALUE);
+    CHECK_ERROR(TPM2B_DIGEST, "\"xxxx\"", TSS2_FAPI_RC_BAD_VALUE);
+    CHECK_ERROR(TPM2B_DIGEST, "\"0x010x\"", TSS2_FAPI_RC_BAD_VALUE);
+}
+
+
+static void
+check_tpmjson_tofromtxt(void **state)
+{
+    const char *testcase_alg_id[] = { "\"TPM_ALG_ID_SHA1\"", "\"TPM2_ALG_ID_SHA1\"",
+                                      "\"ALG_ID_SHA1\"", "\"SHA1\"", "\"ALG_SHA1\"",
+                                      "\"tpm2_alg_id_sha1\"", "\"sha1\"", "\"0x0004\"" };
+    const char *expected_ald_id = { "\"SHA1\"" };
+    for (size_t i = 0; i < sizeof(testcase_alg_id) / sizeof(testcase_alg_id[0]); i++) {
+        CHECK_JSON_SIMPLE(TPM2_ALG_ID, testcase_alg_id[i], expected_ald_id);
+    }
+
+    const char *testcase_ecc_curve[] = { "\"TPM2_ECC_NIST_P256\"", "\"ECC_NIST_P256\"",
+                                         "\"NIST_P256\"", "\"0x0003\"", "\"nist_p256\"" };
+    const char *expected_ecc_curve = { "\"NIST_P256\"" };
+    for (size_t i = 0; i < sizeof(testcase_ecc_curve) / sizeof(testcase_ecc_curve[0]); i++) {
+        CHECK_JSON_SIMPLE(TPM2_ECC_CURVE, testcase_ecc_curve[i], expected_ecc_curve);
+    }
+
+    const char *testcase_cc[] = { "\"TPM2_CC_Startup\"", "\"CC_Startup\"",
+                                  "\"Startup\"", "\"0x00000144\"" };
+    const char *expected_cc = { "\"Startup\"" };
+    for (size_t i = 0; i < sizeof(testcase_cc) / sizeof(testcase_cc[0]); i++) {
+        CHECK_JSON_SIMPLE(TPM2_CC, testcase_cc[i], expected_cc);
+    }
+
+    const char *testcase_eo[] = { "\"TPM2_EO_EQ\"", "\"EO_EQ\"",
+                                  "\"EQ\"", "\"0x0000\"" };
+    const char *expected_eo = { "\"EQ\"" };
+    for (size_t i = 0; i < sizeof(testcase_eo) / sizeof(testcase_eo[0]); i++) {
+        CHECK_JSON_SIMPLE(TPM2_EO, testcase_eo[i], expected_eo);
+    }
+
+    const char *testcase_st[] = { "\"TPM2_ST_NO_SESSIONS\"", "\"ST_NO_SESSIONS\"",
+                                  "\"no_SESSIONS\"", "\"0x8001\"" };
+    const char *expected_st = { "\"NO_SESSIONS\"" };
+    for (size_t i = 0; i < sizeof(testcase_st) / sizeof(testcase_st[0]); i++) {
+        CHECK_JSON_SIMPLE(TPM2_ST, testcase_st[i], expected_st);
+    }
+
+    const char *testcase_pt_pcr[] = { "\"TPM2_PT_PCR_EXTEND_L0\"", "\"PT_PCR_EXTEND_L0\"",
+                                  "\"PCR_EXTEND_L0\"", "\"EXTEND_L0\"" };
+    const char *expected_pt_pcr = { "\"EXTEND_L0\"" };
+    for (size_t i = 0; i < sizeof(testcase_pt_pcr) / sizeof(testcase_pt_pcr[0]); i++) {
+        CHECK_JSON_SIMPLE(TPM2_PT_PCR, testcase_pt_pcr[i], expected_pt_pcr);
+    }
+
+    const char *testcase_alg_public[] = { "\"TPM2_ALG_RSA\"", "\"ALG_RSA\"",
+                                          "\"RSA\"", "\"0x0001\"" };
+    const char *expected_alg_public = { "\"RSA\"" };
+    for (size_t i = 0; i < sizeof(testcase_alg_public) / sizeof(testcase_alg_public[0]); i++) {
+        CHECK_JSON_SIMPLE(TPMI_ALG_PUBLIC, testcase_alg_public[i], expected_alg_public);
+    }
+}
+
+int
+main(int argc, char *argv[])
+{
+    const struct CMUnitTest tests[] = {
+        cmocka_unit_test(check_tpmjson_tofromtxt),
+        cmocka_unit_test(check_json_structs),
+        cmocka_unit_test(check_json_constants),
+        cmocka_unit_test(check_json_numbers),
+        cmocka_unit_test(check_json_bits),
+        cmocka_unit_test(check_json_tpm2bs),
+        cmocka_unit_test(check_json_to_bin),
+        cmocka_unit_test(check_bin),
+        cmocka_unit_test(check_policy_bin),
+        cmocka_unit_test(check_error),
+        cmocka_unit_test(check_json_policy),
+    };
+    return cmocka_run_group_tests(tests, NULL, NULL);
+}