diff --git a/.gitignore b/.gitignore index 8693e89b..7ae63b8d 100644 --- a/.gitignore +++ b/.gitignore @@ -65,12 +65,15 @@ examples/keygen/external_import examples/nvram/store examples/nvram/read examples/nvram/counter +examples/nvram/seal_policy_auth_nv +examples/nvram/seal_policy_auth_nv_external examples/gpio/gpio_config examples/gpio/gpio_set examples/gpio/gpio_read examples/gpio/gpio_nuvoton examples/seal/seal examples/seal/unseal +examples/seal/seal_policy_auth examples/attestation/make_credential examples/attestation/activate_credential examples/boot/secure_rot diff --git a/examples/README.md b/examples/README.md index 89556aaf..b1f96a13 100644 --- a/examples/README.md +++ b/examples/README.md @@ -453,6 +453,47 @@ After a successful unsealing, the data is stored into a new file. If no filename See [examples/boot/README.md](/examples/boot/README.md) +### Sealing data to the TPM with policy authorization + +Data can also be sealed to the TPM, either to NVM or regular, with policy authorization. ./examples/seal/seal\_policy\_auth.c shows an example of how to seal data to the TPM using the wolfTPM2\_SealWithAuthKey function and unseal with wolfTPM2\_UnsealWithAuthSig. These functions call wolfTPM2\_PolicyPCR to add the PCR values to the policyDigest and TPM2\_PolicyAuthorize to sign the digest with either an ecc or rsa key. ./examples/nvram/seal\_policy\_auth\_nv.c is similar but seals to the data to NVM and uses TPM2\_PolicyAuthorizeNV to keep the policyDigest in NVM so it persists in between boots. ./examples/nvram/seal\_policy\_auth\_nv\_external.c works the same way but it shows how to use a key generated from outside wolfTPM, currently only supports ecc256 keys + +``` +$ ./examples/seal/seal_policy_auth -ecc -aes 16 +Example for sealing data to the TPM with policy authorization + PCR Indicies:16 + Use Parameter Encryption: CFB +wolfTPM2_Init: success +TPM2_StartAuthSession: sessionHandle 0x3000000 +Loading SRK: Storage 0x81000200 (282 bytes) +ECC template +Loaded sealBlob to 0x80000002 +TPM2_StartAuthSession: sessionHandle 0x3000000 +Unsealed secret matches! + +$ ./examples/nvram/seal_policy_auth_nv -ecc -aes 16 +Example for sealing data to NV memory with policy authorization + PCR Indicies:16 + Use Parameter Encryption: CFB +wolfTPM2_Init: success +TPM2_StartAuthSession: sessionHandle 0x3000000 +Loading SRK: Storage 0x81000200 (282 bytes) +ECC template +TPM2_StartAuthSession: sessionHandle 0x3000000 +Unsealed secret matches! + +$ ./examples/nvram/seal_policy_auth_nv_external -ecc -aes 16 +Warning: Unrecognized option: -ecc +Example for sealing data to NV memory with policy authorization + PCR Indicies:16 + Use Parameter Encryption: CFB +wolfTPM2_Init: success +Loading SRK: Storage 0x81000200 (282 bytes) +TPM2_StartAuthSession: sessionHandle 0x3000000 +TPM2_StartAuthSession: sessionHandle 0x3000000 +Unsealed secret matches! +``` + + ## Secure Boot ### TPM based root of trust diff --git a/examples/nvram/include.am b/examples/nvram/include.am index 596bdd60..2d3da603 100644 --- a/examples/nvram/include.am +++ b/examples/nvram/include.am @@ -21,13 +21,28 @@ examples_nvram_counter_SOURCES = examples/nvram/counter.c \ examples/tpm_test_keys.c examples_nvram_counter_LDADD = src/libwolftpm.la $(LIB_STATIC_ADD) examples_nvram_counter_DEPENDENCIES = src/libwolftpm.la + +noinst_PROGRAMS += examples/nvram/seal_policy_auth_nv +examples_nvram_seal_policy_auth_nv_SOURCES = examples/nvram/seal_policy_auth_nv.c \ + examples/tpm_test_keys.c +examples_nvram_seal_policy_auth_nv_LDADD = src/libwolftpm.la $(LIB_STATIC_ADD) +examples_nvram_seal_policy_auth_nv_DEPENDENCIES = src/libwolftpm.la + +noinst_PROGRAMS += examples/nvram/seal_policy_auth_nv_external +examples_nvram_seal_policy_auth_nv_external_SOURCES = examples/nvram/seal_policy_auth_nv_external.c \ + examples/tpm_test_keys.c +examples_nvram_seal_policy_auth_nv_external_LDADD = src/libwolftpm.la $(LIB_STATIC_ADD) +examples_nvram_seal_policy_auth_nv_external_DEPENDENCIES = src/libwolftpm.la + endif example_nvramdir = $(exampledir)/nvram dist_example_nvram_DATA = \ examples/nvram/store.c \ examples/nvram/read.c \ - examples/nvram/counter.c + examples/nvram/counter.c \ + examples/nvram/seal_policy_auth_nv.c \ + examples/nvram/seal_policy_auth_nv_external.c DISTCLEANFILES+= examples/nvram/.libs/store DISTCLEANFILES+= examples/nvram/.libs/read diff --git a/examples/nvram/seal_policy_auth_nv.c b/examples/nvram/seal_policy_auth_nv.c new file mode 100644 index 00000000..0d3bebd9 --- /dev/null +++ b/examples/nvram/seal_policy_auth_nv.c @@ -0,0 +1,294 @@ +/* seal_policy_auth_nv.c + * + * Copyright (C) 2006-2023 wolfSSL Inc. + * + * This file is part of wolfTPM. + * + * wolfTPM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfTPM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* This is a helper tool for setting policies on a TPM 2.0 PCR */ + +#include + +#include + +#if !defined(WOLFTPM2_NO_WRAPPER) && !defined(WOLFTPM2_NO_WOLFCRYPT) + +#include +#include +#include +#include +#include + +/******************************************************************************/ +/* --- BEGIN TPM2.0 PCR Policy example tool -- */ +/******************************************************************************/ + +static void usage(void) +{ + printf("Expected usage:\n"); + printf("./examples/nvram/seal_policy_auth_nv [-aes/xor] [-rsa/ecc] [pcr]\n"); + printf("* -aes/xor: Use Parameter Encryption\n"); + printf("* -rsa/ecc: Pick sealing key type, (default rsa)\n"); + printf("* pcr: PCR index between 0-23 (default %d)\n", TPM2_DEMO_PCR_INDEX); +} + +static const word32 sealNvIndex = TPM2_DEMO_NV_TEST_INDEX; +static const word32 policyDigestNvIndex = TPM2_DEMO_NV_TEST_INDEX + 1; + +int TPM2_PCR_Seal_With_Policy_Auth_NV_Test(void* userCtx, int argc, char *argv[]) +{ + int i; + int rc = -1; + WOLFTPM2_NV nv; + WOLFTPM2_DEV dev; + WOLFTPM2_KEY storage; + WOLFTPM2_SESSION tpmSession; + WOLFTPM2_KEYBLOB authKey; + TPMT_PUBLIC authTemplate; + /* default to aes since parm encryption is required */ + TPM_ALG_ID paramEncAlg = TPM_ALG_CFB; + word32 pcrIndex = TPM2_DEMO_PCR_INDEX; + byte pcrArray[PCR_SELECT_MAX*2]; + word32 pcrArraySz = 0; + byte secret[16]; + byte secretOut[16]; + word32 secretOutSz = (word32)sizeof(secretOut); + byte policySignedSig[MAX_RSA_KEY_BYTES]; + word32 policySignedSigSz = MAX_RSA_KEY_BYTES; + TPM_ALG_ID alg = TPM_ALG_RSA; + + XMEMSET(&dev, 0, sizeof(WOLFTPM2_DEV)); + XMEMSET(&storage, 0, sizeof(WOLFTPM2_KEY)); + XMEMSET(&tpmSession, 0, sizeof(WOLFTPM2_SESSION)); + XMEMSET(&nv, 0, sizeof(nv)); + XMEMSET(&authTemplate, 0, sizeof(TPMT_PUBLIC)); + + /* set the secret */ + for (i = 0; i < (int)sizeof(secret); i++) { + secret[i] = i; + } + + if (argc >= 2) { + if (XSTRCMP(argv[1], "-?") == 0 || + XSTRCMP(argv[1], "-h") == 0 || + XSTRCMP(argv[1], "--help") == 0) { + usage(); + return 0; + } + } + while (argc > 1) { + if (XSTRCMP(argv[argc-1], "-aes") == 0) { + paramEncAlg = TPM_ALG_CFB; + } + else if (XSTRCMP(argv[argc-1], "-xor") == 0) { + paramEncAlg = TPM_ALG_XOR; + } + else if (XSTRCMP(argv[argc-1], "-rsa") == 0) { + alg = TPM_ALG_RSA; + } + else if (XSTRCMP(argv[argc-1], "-ecc") == 0) { + alg = TPM_ALG_ECC; + } + else if (argv[argc-1][0] != '-') { + /* TODO: Allow selection of multiple PCR's SHA-1 or SHA2-256 */ + pcrIndex = XATOI(argv[argc-1]); + if (pcrIndex > PCR_LAST) { + printf("PCR index is out of range (0-23)\n"); + usage(); + return 0; + } + pcrArray[pcrArraySz] = pcrIndex; + pcrArraySz++; + } + else { + printf("Warning: Unrecognized option: %s\n", argv[argc-1]); + } + argc--; + } + + if (pcrArraySz == 0) { + pcrArray[pcrArraySz] = pcrIndex; + pcrArraySz++; + } + + printf("Example for sealing data to NV memory with policy authorization\n"); + printf("\tPCR Indicies:"); + + for (i = 0; i < (int)pcrArraySz; i++) { + printf("%d ", pcrArray[i]); + } + + printf("\n"); + + printf("\tUse Parameter Encryption: %s\n", TPM2_GetAlgName(paramEncAlg)); + + rc = wolfTPM2_Init(&dev, TPM2_IoCb, userCtx); + if (rc != TPM_RC_SUCCESS) { + printf("wolfTPM2_Init failed 0x%x: %s\n", rc, TPM2_GetRCString(rc)); + goto exit; + } + printf("wolfTPM2_Init: success\n"); + + /* session is required for pcr authorization */ + /* Start an authenticated policy session (salted / unbound) */ + rc = wolfTPM2_StartSession(&dev, &tpmSession, NULL, NULL, + TPM_SE_POLICY, paramEncAlg); + if (rc != 0) goto exit; + printf("TPM2_StartAuthSession: sessionHandle 0x%x\n", + (word32)tpmSession.handle.hndl); + + /* set session for authorization of the storage key */ + rc = wolfTPM2_SetAuthSession(&dev, 0, &tpmSession, + (TPMA_SESSION_decrypt | TPMA_SESSION_encrypt | + TPMA_SESSION_continueSession)); + if (rc != 0) goto exit; + + /* get SRK */ + rc = getPrimaryStoragekey(&dev, &storage, TPM_ALG_RSA); + if (rc != 0) goto exit; + + /* create the auth key template */ + if (alg == TPM_ALG_RSA) { + printf("RSA template\n"); + rc = wolfTPM2_GetKeyTemplate_RSA(&authTemplate, + TPMA_OBJECT_sensitiveDataOrigin | TPMA_OBJECT_userWithAuth | + TPMA_OBJECT_decrypt | TPMA_OBJECT_sign | TPMA_OBJECT_noDA); + } + else if (alg == TPM_ALG_ECC) { + printf("ECC template\n"); + rc = wolfTPM2_GetKeyTemplate_ECC(&authTemplate, + TPMA_OBJECT_sensitiveDataOrigin | TPMA_OBJECT_userWithAuth | + TPMA_OBJECT_sign | TPMA_OBJECT_noDA, + TPM_ECC_NIST_P256, TPM_ALG_ECDSA); + } + if (rc != TPM_RC_SUCCESS) { + printf("create template failed failed\n"); + goto exit; + } + + /* generate the authorized key, this auth key can also generated and */ + /* loaded externally */ + rc = wolfTPM2_CreateKey(&dev, &authKey, &storage.handle, + &authTemplate, NULL, 0); + if (rc != TPM_RC_SUCCESS) { + printf("wolfTPM2_CreateKey failed\n"); + goto exit; + } + + rc = wolfTPM2_LoadKey(&dev, &authKey, &storage.handle); + if (rc != TPM_RC_SUCCESS) { + printf("wolfTPM2_LoadKey failed\n"); + goto exit; + } + + /* seal the secret */ + rc = wolfTPM2_SealWithAuthKeyNV(&dev, (WOLFTPM2_KEY*)&authKey, + &tpmSession, TPM_ALG_SHA256, TPM_ALG_SHA256, pcrArray, + pcrArraySz, secret, sizeof(secret), + NULL, 0, sealNvIndex, policyDigestNvIndex, policySignedSig, + &policySignedSigSz); + if (rc != TPM_RC_SUCCESS) { + printf("wolfTPM2_SealWithAuthPolicyNV failed 0x%x: %s\n", rc, + TPM2_GetRCString(rc)); + goto exit; + } + + /* reset our session */ + wolfTPM2_UnloadHandle(&dev, &tpmSession.handle); + XMEMSET(&tpmSession, 0, sizeof(WOLFTPM2_SESSION)); + + rc = wolfTPM2_StartSession(&dev, &tpmSession, NULL, NULL, + TPM_SE_POLICY, paramEncAlg); + if (rc != 0) goto exit; + printf("TPM2_StartAuthSession: sessionHandle 0x%x\n", + (word32)tpmSession.handle.hndl); + + /* set session for authorization of the storage key */ + rc = wolfTPM2_SetAuthSession(&dev, 0, &tpmSession, + (TPMA_SESSION_decrypt | TPMA_SESSION_encrypt | + TPMA_SESSION_continueSession)); + if (rc != 0) goto exit; + + nv.handle.hndl = sealNvIndex; + + /* try to unseal with the regular command, should fail */ + rc = wolfTPM2_NVReadAuth(&dev, &nv, sealNvIndex, + secretOut, &secretOutSz, 0); + if (rc == TPM_RC_SUCCESS) { + printf("wolfTPM2_NVReadAuth failed, it should not have allowed a read" + " without PolicyAuthorizeNV 0x%x: %s\n", rc, TPM2_GetRCString(rc)); + goto exit; + } + + /* unseal the secret */ + rc = wolfTPM2_UnsealWithAuthSigNV(&dev, (WOLFTPM2_KEY*)&authKey, + &tpmSession, TPM_ALG_SHA256, pcrArray, + pcrArraySz, NULL, 0, policySignedSig, policySignedSigSz, sealNvIndex, + policyDigestNvIndex, secretOut, &secretOutSz); + if (rc != TPM_RC_SUCCESS) { + printf("wolfTPM2_UnsealWithAuthSigNV failed 0x%x: %s\n", rc, + TPM2_GetRCString(rc)); + goto exit; + } + + if (XMEMCMP(secret, secretOut, sizeof(secret)) != 0) { + printf("Unsealed secret does not match\n"); + goto exit; + } + else { + printf("Unsealed secret matches!\n"); + } + +exit: + if (rc != 0) { + printf("Failure 0x%x: %s\n", rc, wolfTPM2_GetRCString(rc)); + } + + wolfTPM2_SetAuthPassword(&dev, 0, NULL); + + wolfTPM2_UnloadHandle(&dev, &authKey.handle); + wolfTPM2_UnloadHandle(&dev, &storage.handle); + wolfTPM2_UnloadHandle(&dev, &tpmSession.handle); + + wolfTPM2_Cleanup(&dev); + + return rc; +} + +/******************************************************************************/ +/* --- END TPM2.0 PCR Policy example tool -- */ +/******************************************************************************/ + +#endif /* !WOLFTPM2_NO_WRAPPER && !WOLFTPM2_NO_WOLFCRYPT */ + + +#ifndef NO_MAIN_DRIVER +int main(int argc, char *argv[]) +{ + int rc = -1; + +#if !defined(WOLFTPM2_NO_WRAPPER) && !defined(WOLFTPM2_NO_WOLFCRYPT) + rc = TPM2_PCR_Seal_With_Policy_Auth_NV_Test(NULL, argc, argv); +#else + printf("Wrapper code not compiled in\n"); + (void)argc; + (void)argv; +#endif /* !WOLFTPM2_NO_WRAPPER && !WOLFTPM2_NO_WOLFCRYPT */ + + return rc; +} +#endif diff --git a/examples/nvram/seal_policy_auth_nv_external.c b/examples/nvram/seal_policy_auth_nv_external.c new file mode 100644 index 00000000..c03d290f --- /dev/null +++ b/examples/nvram/seal_policy_auth_nv_external.c @@ -0,0 +1,343 @@ +/* seal_policy_auth_nv_external.c + * + * Copyright (C) 2006-2023 wolfSSL Inc. + * + * This file is part of wolfTPM. + * + * wolfTPM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfTPM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* This is a helper tool for setting policies on a TPM 2.0 PCR */ + +#include + +#include + +#if !defined(WOLFTPM2_NO_WRAPPER) && !defined(WOLFTPM2_NO_WOLFCRYPT) && \ + defined(WOLFSSL_PUBLIC_MP) && defined(HAVE_ECC) + +#include +#include +#include +#include + +#include +#include +#include +#include + +#define ECC_KEY_SIZE 32 + +/******************************************************************************/ +/* --- BEGIN TPM2.0 PCR Policy example tool -- */ +/******************************************************************************/ + +static void usage(void) +{ + printf("Expected usage:\n"); + printf("./examples/nvram/seal_policy_auth_nv_external [-aes/xor] [pcr]\n"); + printf("* -aes/xor: Use Parameter Encryption\n"); + printf("* pcr: PCR index between 0-23 (default %d)\n", TPM2_DEMO_PCR_INDEX); +} + +static const word32 sealNvIndex = TPM2_DEMO_NV_TEST_INDEX; +static const word32 policyDigestNvIndex = TPM2_DEMO_NV_TEST_INDEX + 1; + +/* currently only supports ecc256 */ +int TPM2_PCR_Seal_With_Policy_Auth_NV_External_Test(void* userCtx, int argc, char *argv[]) +{ + int i; + int rc = -1; + WOLFTPM2_NV nv; + WOLFTPM2_DEV dev; + WOLFTPM2_KEY storage; + WOLFTPM2_SESSION tpmSession; + WOLFTPM2_KEY authKey; + TPMT_PUBLIC authTemplate; + /* default to aes since parm encryption is required */ + TPM_ALG_ID paramEncAlg = TPM_ALG_CFB; + word32 pcrIndex = TPM2_DEMO_PCR_INDEX; + byte pcrArray[PCR_SELECT_MAX*2]; + word32 pcrArraySz = 0; + byte secret[16]; + byte secretOut[16]; + word32 secretOutSz = (word32)sizeof(secretOut); + wc_Sha256 sha; + byte zeroExpiry[4]; + byte hash[WC_SHA256_DIGEST_SIZE]; + ecc_key external_key; + WC_RNG rng; + byte sig[ECC_KEY_SIZE * 2]; + word32 sigSz = ECC_KEY_SIZE * 2; + byte qx[ECC_KEY_SIZE]; + word32 qxSz = ECC_KEY_SIZE; + byte qy[ECC_KEY_SIZE]; + word32 qySz = ECC_KEY_SIZE; + mp_int r, s; + + XMEMSET(&dev, 0, sizeof(WOLFTPM2_DEV)); + XMEMSET(&storage, 0, sizeof(WOLFTPM2_KEY)); + XMEMSET(&tpmSession, 0, sizeof(WOLFTPM2_SESSION)); + XMEMSET(&nv, 0, sizeof(nv)); + XMEMSET(&authKey, 0, sizeof(WOLFTPM2_KEY)); + XMEMSET(&authTemplate, 0, sizeof(TPMT_PUBLIC)); + XMEMSET(zeroExpiry, 0, sizeof(zeroExpiry)); + + /* set secret */ + for (i = 0; i < (int)sizeof(secret); i++) { + secret[i] = i; + } + + if (argc >= 2) { + if (XSTRCMP(argv[1], "-?") == 0 || + XSTRCMP(argv[1], "-h") == 0 || + XSTRCMP(argv[1], "--help") == 0) { + usage(); + return 0; + } + } + while (argc > 1) { + if (XSTRCMP(argv[argc-1], "-aes") == 0) { + paramEncAlg = TPM_ALG_CFB; + } + else if (XSTRCMP(argv[argc-1], "-xor") == 0) { + paramEncAlg = TPM_ALG_XOR; + } + else if (argv[argc-1][0] != '-') { + /* TODO: Allow selection of multiple PCR's SHA-1 or SHA2-256 */ + pcrIndex = XATOI(argv[argc-1]); + if (pcrIndex > PCR_LAST) { + printf("PCR index is out of range (0-23)\n"); + usage(); + return 0; + } + pcrArray[pcrArraySz] = pcrIndex; + pcrArraySz++; + } + else { + printf("Warning: Unrecognized option: %s\n", argv[argc-1]); + } + argc--; + } + + if (pcrArraySz == 0) { + pcrArray[pcrArraySz] = TPM2_DEMO_PCR_INDEX; + pcrArraySz++; + } + + printf("Example for sealing data to NV memory with policy authorization\n"); + printf("\tPCR Indicies:"); + + for (i = 0; i < (int)pcrArraySz; i++) { + printf("%d ", pcrArray[i]); + } + + printf("\n"); + + printf("\tUse Parameter Encryption: %s\n", TPM2_GetAlgName(paramEncAlg)); + + rc = wolfTPM2_Init(&dev, TPM2_IoCb, userCtx); + if (rc != TPM_RC_SUCCESS) { + printf("wolfTPM2_Init failed 0x%x: %s\n", rc, TPM2_GetRCString(rc)); + goto exit; + } + printf("wolfTPM2_Init: success\n"); + + /* get SRK */ + rc = getPrimaryStoragekey(&dev, &storage, TPM_ALG_RSA); + if (rc != 0) goto exit; + + /* session is required for pcr authorization */ + /* Start an authenticated policy session (salted / unbound) */ + rc = wolfTPM2_StartSession(&dev, &tpmSession, NULL, NULL, + TPM_SE_POLICY, paramEncAlg); + if (rc != 0) goto exit; + printf("TPM2_StartAuthSession: sessionHandle 0x%x\n", + (word32)tpmSession.handle.hndl); + + /* set session for authorization of the storage key */ + rc = wolfTPM2_SetAuthSession(&dev, 0, &tpmSession, + (TPMA_SESSION_decrypt | TPMA_SESSION_encrypt | + TPMA_SESSION_continueSession)); + if (rc != 0) goto exit; + + /* init rng */ + rc = wc_InitRng(&rng); + if (rc != 0) { + printf("wc_InitRng failed\n"); + goto exit; + } + + /* hash the zero expiry */ + rc = wc_InitSha256(&sha); + if (rc != 0) { + printf("wc_InitSha256 failed\n"); + goto exit; + } + + rc = wc_Sha256Update(&sha, zeroExpiry, sizeof(zeroExpiry)); + if (rc != 0) { + printf("wc_Sha256Update failed\n"); + goto exit; + } + + rc = wc_Sha256Final(&sha, hash); + if (rc != 0) { + printf("wc_Sha256Final failed\n"); + goto exit; + } + + /* create an external key */ + rc = wc_ecc_init(&external_key); + if (rc != 0) { + printf("wc_ecc_init failed\n"); + goto exit; + } + + /* make the key */ + rc = wc_ecc_make_key(&rng, ECC_KEY_SIZE, &external_key); + if (rc != 0) { + printf("wc_ecc_make_key failed\n"); + goto exit; + } + + mp_init(&r); + mp_init(&s); + + rc = wc_ecc_sign_hash_ex(hash, sizeof(hash), &rng, &external_key, + &r, &s); + + mp_to_unsigned_bin(&r, sig); + mp_to_unsigned_bin(&s, sig + ECC_KEY_SIZE); + + mp_clear(&r); + mp_clear(&s); + + if (rc != 0) { + printf("wc_ecc_sign_hash_ex failed %d\n", rc); + goto exit; + } + + sigSz = ECC_KEY_SIZE * 2; + + /* load the public part of the key into the tpm */ + rc = wc_ecc_export_public_raw(&external_key, qx, &qxSz, qy, &qySz); + if (rc != 0) { + printf("wc_ecc_export_public_raw failed\n"); + goto exit; + } + + rc = wolfTPM2_LoadEccPublicKey(&dev, (WOLFTPM2_KEY*)&authKey, + TPM_ECC_NIST_P256, qx, qxSz, qy, qySz); + if (rc != TPM_RC_SUCCESS) { + printf("wolfTPM2_LoadEccPublicKey failed\n"); + goto exit; + } + + /* seal the secret */ + rc = wolfTPM2_SealWithAuthSigNV(&dev, &authKey, &tpmSession, TPM_ALG_SHA256, + TPM_ALG_SHA256, pcrArray, pcrArraySz, secret, sizeof(secret), NULL, 0, + sig, sigSz, sealNvIndex, policyDigestNvIndex); + if (rc != TPM_RC_SUCCESS) { + printf("wolfTPM2_SealWithAuthPolicyNV failed 0x%x: %s\n", rc, + TPM2_GetRCString(rc)); + goto exit; + } + + /* reset our session */ + wolfTPM2_UnloadHandle(&dev, &tpmSession.handle); + XMEMSET(&tpmSession, 0, sizeof(WOLFTPM2_SESSION)); + + rc = wolfTPM2_StartSession(&dev, &tpmSession, NULL, NULL, + TPM_SE_POLICY, paramEncAlg); + if (rc != 0) goto exit; + printf("TPM2_StartAuthSession: sessionHandle 0x%x\n", + (word32)tpmSession.handle.hndl); + + /* set session for authorization of the storage key */ + rc = wolfTPM2_SetAuthSession(&dev, 0, &tpmSession, + (TPMA_SESSION_decrypt | TPMA_SESSION_encrypt | + TPMA_SESSION_continueSession)); + if (rc != 0) goto exit; + + nv.handle.hndl = sealNvIndex; + + /* try to unseal with the regular command, should fail */ + rc = wolfTPM2_NVReadAuth(&dev, &nv, sealNvIndex, + secretOut, &secretOutSz, 0); + if (rc == TPM_RC_SUCCESS) { + printf("wolfTPM2_NVReadAuth failed, it should not have allowed a read" + " without PolicyAuthorizeNV 0x%x: %s\n", rc, TPM2_GetRCString(rc)); + goto exit; + } + + /* unseal the secret */ + rc = wolfTPM2_UnsealWithAuthSigNV(&dev, &authKey, + &tpmSession, TPM_ALG_SHA256, pcrArray, + pcrArraySz, NULL, 0, sig, sigSz, sealNvIndex, + policyDigestNvIndex, secretOut, &secretOutSz); + if (rc != TPM_RC_SUCCESS) { + printf("wolfTPM2_UnsealWithAuthSigNV failed 0x%x: %s\n", rc, + TPM2_GetRCString(rc)); + goto exit; + } + + if (XMEMCMP(secret, secretOut, sizeof(secret)) != 0) { + printf("Unsealed secret does not match\n"); + goto exit; + } + else { + printf("Unsealed secret matches!\n"); + } + +exit: + if (rc != 0) { + printf("Failure 0x%x: %s\n", rc, wolfTPM2_GetRCString(rc)); + } + + wolfTPM2_SetAuthPassword(&dev, 0, NULL); + + wolfTPM2_UnloadHandle(&dev, &authKey.handle); + wolfTPM2_UnloadHandle(&dev, &storage.handle); + wolfTPM2_UnloadHandle(&dev, &tpmSession.handle); + + wolfTPM2_Cleanup(&dev); + + return rc; +} + +/******************************************************************************/ +/* --- END TPM2.0 PCR Policy example tool -- */ +/******************************************************************************/ + +#endif /* !WOLFTPM2_NO_WRAPPER && !WOLFTPM2_NO_WOLFCRYPT && WOLFSSL_PUBLIC_MP */ + +#ifndef NO_MAIN_DRIVER +int main(int argc, char *argv[]) +{ + int rc = -1; + +#if !defined(WOLFTPM2_NO_WRAPPER) && !defined(WOLFTPM2_NO_WOLFCRYPT) && \ + defined(WOLFSSL_PUBLIC_MP) && defined(HAVE_ECC) + rc = TPM2_PCR_Seal_With_Policy_Auth_NV_External_Test(NULL, argc, argv); +#else + printf("Wrapper or wolfcrypt or WOLFSSL_PUBLIC_MP code not compiled in\n"); + (void)argc; + (void)argv; +#endif /* !WOLFTPM2_NO_WRAPPER */ + + return rc; +} +#endif diff --git a/examples/seal/include.am b/examples/seal/include.am index 52bb2bd9..19a4e4f6 100644 --- a/examples/seal/include.am +++ b/examples/seal/include.am @@ -3,7 +3,8 @@ if BUILD_EXAMPLES noinst_PROGRAMS += examples/seal/seal \ - examples/seal/unseal + examples/seal/unseal \ + examples/seal/seal_policy_auth noinst_HEADERS += examples/seal/seal.h @@ -16,13 +17,21 @@ examples_seal_unseal_SOURCES = examples/seal/unseal.c \ examples/tpm_test_keys.c examples_seal_unseal_LDADD = src/libwolftpm.la $(LIB_STATIC_ADD) examples_seal_unseal_DEPENDENCIES = src/libwolftpm.la + + +examples_seal_seal_policy_auth_SOURCES = examples/seal/seal_policy_auth.c \ + examples/tpm_test_keys.c +examples_seal_seal_policy_auth_LDADD = src/libwolftpm.la $(LIB_STATIC_ADD) +examples_seal_seal_policy_auth_DEPENDENCIES = src/libwolftpm.la + endif example_sealdir = $(exampledir)/seal dist_example_seal_DATA = \ examples/seal/seal.c \ - examples/seal/unseal.c + examples/seal/unseal.c \ + examples/seal/seal_policy_auth.c DISTCLEANFILES+= examples/seal/.libs/seal DISTCLEANFILES+= examples/seal/.libs/unseal - +DISTCLEANFILES+= examples/seal/.libs/seal_policy_auth diff --git a/examples/seal/seal_policy_auth.c b/examples/seal/seal_policy_auth.c new file mode 100644 index 00000000..d1666715 --- /dev/null +++ b/examples/seal/seal_policy_auth.c @@ -0,0 +1,357 @@ +/* seal_policy_auth.c + * + * Copyright (C) 2006-2023 wolfSSL Inc. + * + * This file is part of wolfTPM. + * + * wolfTPM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfTPM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* This is a helper tool for setting policies on a TPM 2.0 PCR */ + +#include + +#include + +#if !defined(WOLFTPM2_NO_WRAPPER) && !defined(WOLFTPM2_NO_WOLFCRYPT) + +#include +#include +#include +#include + +#include + +/******************************************************************************/ +/* --- BEGIN TPM2.0 PCR Policy example tool -- */ +/******************************************************************************/ + +static void usage(void) +{ + printf("Expected usage:\n"); + printf("./examples/seal/seal_policy_auth [-aes/xor] [-rsa/ecc] [pcr]\n"); + printf("* -aes/xor: Use Parameter Encryption\n"); + printf("* -rsa/ecc: Pick sealing key type, (default rsa)\n"); + printf("* pcr: PCR index between 0-23 (default %d)\n", TPM2_DEMO_PCR_INDEX); +} + +int TPM2_PCR_Seal_With_Policy_Auth_Test(void* userCtx, int argc, char *argv[]) +{ + int i; + int rc = -1; + WOLFTPM2_DEV dev; + WOLFTPM2_KEY storage; + WOLFTPM2_SESSION tpmSession; + WOLFTPM2_KEYBLOB authKey; + WOLFTPM2_KEYBLOB sealBlob; + TPMT_PUBLIC authTemplate; + TPMT_PUBLIC sealTemplate; + /* default to aes since parm encryption is required */ + TPM_ALG_ID paramEncAlg = TPM_ALG_CFB; + TPM_ALG_ID alg = TPM_ALG_RSA; + word32 pcrIndex = TPM2_DEMO_PCR_INDEX; + byte policyDigest[TPM_MAX_DIGEST_SIZE]; + word32 policyDigestSz = (word32)sizeof(policyDigest); + byte policyDigestSig[MAX_RSA_KEY_BYTES]; + word32 policyDigestSigSz = (word32)sizeof(policyDigestSig); + byte badDigest[TPM_MAX_DIGEST_SIZE] = {0}; + byte badSig[TPM_MAX_DIGEST_SIZE] = {0}; + word32 badSigSz = (word32)TPM_MAX_DIGEST_SIZE; + byte pcrArray[PCR_SELECT_MAX*2]; + word32 pcrArraySz = 0; + byte nonce[16]; + byte secret[16]; + byte secretOut[16]; + word32 secretOutSz = (word32)sizeof(secretOut); + Unseal_In unsealIn[1]; + Unseal_Out unsealOut[1]; + + XMEMSET(&dev, 0, sizeof(WOLFTPM2_DEV)); + XMEMSET(&storage, 0, sizeof(WOLFTPM2_KEY)); + XMEMSET(&tpmSession, 0, sizeof(WOLFTPM2_SESSION)); + XMEMSET(&authKey, 0, sizeof(WOLFTPM2_KEYBLOB)); + XMEMSET(&sealBlob, 0, sizeof(WOLFTPM2_KEYBLOB)); + XMEMSET(&authTemplate, 0, sizeof(TPMT_PUBLIC)); + XMEMSET(&sealTemplate, 0, sizeof(TPMT_PUBLIC)); + XMEMSET(unsealIn, 0, sizeof(Unseal_In)); + XMEMSET(unsealOut, 0, sizeof(Unseal_Out)); + + /* set nonce and secret */ + for (i = 0; i < (int)sizeof(nonce); i++) { + nonce[i] = sizeof(nonce) - 1 - i; + secret[i] = i; + } + + if (argc >= 2) { + if (XSTRCMP(argv[1], "-?") == 0 || + XSTRCMP(argv[1], "-h") == 0 || + XSTRCMP(argv[1], "--help") == 0) { + usage(); + return 0; + } + } + while (argc > 1) { + if (XSTRCMP(argv[argc-1], "-aes") == 0) { + paramEncAlg = TPM_ALG_CFB; + } + else if (XSTRCMP(argv[argc-1], "-xor") == 0) { + paramEncAlg = TPM_ALG_XOR; + } + else if (XSTRCMP(argv[argc-1], "-rsa") == 0) { + alg = TPM_ALG_RSA; + } + else if (XSTRCMP(argv[argc-1], "-ecc") == 0) { + alg = TPM_ALG_ECC; + } + else if (argv[argc-1][0] != '-') { + /* TODO: Allow selection of multiple PCR's SHA-1 or SHA2-256 */ + pcrIndex = XATOI(argv[argc-1]); + if (pcrIndex > PCR_LAST) { + printf("PCR index is out of range (0-23)\n"); + usage(); + return 0; + } + pcrArray[pcrArraySz] = pcrIndex; + pcrArraySz++; + } + else { + printf("Warning: Unrecognized option: %s\n", argv[argc-1]); + } + argc--; + } + + if (pcrArraySz == 0) { + pcrArray[pcrArraySz] = pcrIndex; + pcrArraySz++; + } + + printf("Example for sealing data to the TPM with policy authorization\n"); + printf("\tPCR Indicies:"); + + for (i = 0; i < (int)pcrArraySz; i++) { + printf("%d ", pcrArray[i]); + } + + printf("\n"); + printf("\tUse Parameter Encryption: %s\n", TPM2_GetAlgName(paramEncAlg)); + + rc = wolfTPM2_Init(&dev, TPM2_IoCb, userCtx); + if (rc != TPM_RC_SUCCESS) { + printf("wolfTPM2_Init failed 0x%x: %s\n", rc, TPM2_GetRCString(rc)); + goto exit; + } + printf("wolfTPM2_Init: success\n"); + + /* session is required for pcr authorization */ + /* Start an authenticated policy session (salted / unbound) */ + rc = wolfTPM2_StartSession(&dev, &tpmSession, NULL, NULL, + TPM_SE_POLICY, paramEncAlg); + if (rc != 0) goto exit; + printf("TPM2_StartAuthSession: sessionHandle 0x%x\n", + (word32)tpmSession.handle.hndl); + + /* set session for authorization of the storage key */ + rc = wolfTPM2_SetAuthSession(&dev, 0, &tpmSession, + (TPMA_SESSION_decrypt | TPMA_SESSION_encrypt | + TPMA_SESSION_continueSession)); + if (rc != 0) goto exit; + + /* get SRK */ + rc = getPrimaryStoragekey(&dev, &storage, TPM_ALG_RSA); + if (rc != 0) goto exit; + + /* create the auth key template */ + if (alg == TPM_ALG_RSA) { + printf("RSA template\n"); + rc = wolfTPM2_GetKeyTemplate_RSA(&authTemplate, + TPMA_OBJECT_sensitiveDataOrigin | TPMA_OBJECT_userWithAuth | + TPMA_OBJECT_decrypt | TPMA_OBJECT_sign | TPMA_OBJECT_noDA); + } + else if (alg == TPM_ALG_ECC) { + printf("ECC template\n"); + rc = wolfTPM2_GetKeyTemplate_ECC(&authTemplate, + TPMA_OBJECT_sensitiveDataOrigin | TPMA_OBJECT_userWithAuth | + TPMA_OBJECT_sign | TPMA_OBJECT_noDA, + TPM_ECC_NIST_P256, TPM_ALG_ECDSA); + } + + if (rc != TPM_RC_SUCCESS) { + printf("key template generation failed\n"); + goto exit; + } + + /* generate the authorized key, this auth key can also generated and */ + /* loaded externally */ + rc = wolfTPM2_CreateKey(&dev, &authKey, &storage.handle, + &authTemplate, NULL, 0); + if (rc != TPM_RC_SUCCESS) { + printf("wolfTPM2_CreateKey failed\n"); + goto exit; + } + + rc = wolfTPM2_LoadKey(&dev, &authKey, &storage.handle); + if (rc != TPM_RC_SUCCESS) { + printf("wolfTPM2_LoadKey failed\n"); + goto exit; + } + + /* create the template */ + wolfTPM2_GetKeyTemplate_KeySeal(&sealTemplate, TPM_ALG_SHA256); + + /* seal the secret */ + rc = wolfTPM2_SealWithAuthKey(&dev, &authKey, &storage.handle, + &sealTemplate, &sealBlob, tpmSession.handle.hndl, + TPM_ALG_SHA256, pcrArray, pcrArraySz, + secret, sizeof(secret), nonce, sizeof(nonce), policyDigest, + &policyDigestSz, policyDigestSig, &policyDigestSigSz); + if (rc != TPM_RC_SUCCESS) { + printf("wolfTPM2_SealWithAuthKey failed 0x%x: %s\n", rc, + TPM2_GetRCString(rc)); + goto exit; + } + + /* load the seal blob */ + rc = wolfTPM2_LoadKey(&dev, &sealBlob, &storage.handle); + if (rc != TPM_RC_SUCCESS) { + printf("wolfTPM2_LoadKey failed\n"); + goto exit; + } + printf("Loaded sealBlob to 0x%x\n", + (word32)sealBlob.handle.hndl); + + /* reset our session */ + wolfTPM2_UnloadHandle(&dev, &tpmSession.handle); + + rc = wolfTPM2_StartSession(&dev, &tpmSession, NULL, NULL, + TPM_SE_POLICY, paramEncAlg); + if (rc != 0) goto exit; + printf("TPM2_StartAuthSession: sessionHandle 0x%x\n", + (word32)tpmSession.handle.hndl); + + /* set session for authorization of the storage key */ + rc = wolfTPM2_SetAuthSession(&dev, 0, &tpmSession, + (TPMA_SESSION_decrypt | TPMA_SESSION_encrypt | + TPMA_SESSION_continueSession)); + if (rc != 0) goto exit; + + /* try to unseal with the regular command, should fail */ + unsealIn->itemHandle = sealBlob.handle.hndl; + + rc = TPM2_Unseal(unsealIn, unsealOut); + + if (rc == TPM_RC_SUCCESS) { + printf("TPM2_Unseal failed, should not have allowed unauthorized" + "unseal 0x%x: %s\n", rc, + TPM2_GetRCString(rc)); + goto exit; + } + + /* unseal the secret */ + rc = wolfTPM2_UnsealWithAuthSig(&dev, &authKey, + tpmSession.handle.hndl, sealBlob.handle.hndl, TPM_ALG_SHA256, + pcrArray, pcrArraySz, policyDigest, + policyDigestSz, nonce, sizeof(nonce), policyDigestSig, + policyDigestSigSz, secretOut, &secretOutSz); + if (rc != TPM_RC_SUCCESS) { + printf("wolfTPM2_UnsealWithAuthSig failed 0x%x: %s\n", rc, + TPM2_GetRCString(rc)); + goto exit; + } + + if (XMEMCMP(secret, secretOut, sizeof(secret)) != 0) { + printf("Unsealed secret does not match\n"); + goto exit; + } + else { + printf("Unsealed secret matches!\n"); + } + + /* try to unseal with a bad signature, should fail */ + rc = wolfTPM2_UnsealWithAuthSig(&dev, &authKey, + tpmSession.handle.hndl, sealBlob.handle.hndl, TPM_ALG_SHA256, + pcrArray, pcrArraySz, policyDigest, + policyDigestSz, nonce, sizeof(nonce), badSig, policyDigestSigSz, + secretOut, &secretOutSz); + if (rc == TPM_RC_SUCCESS) { + printf("wolfTPM2_UnsealWithAuthorizedKey failed, should not have" + "allowed bad signature 0x%x: %s\n", rc, + TPM2_GetRCString(rc)); + goto exit; + } + + /* sign the bad digest, this is done for testing */ + rc = wolfTPM2_SignHash(&dev, (WOLFTPM2_KEY*)&authKey, badDigest, policyDigestSz, + badSig, (int*)&badSigSz); + if (rc != TPM_RC_SUCCESS) { + printf("wolfTPM2_SignHash failed 0x%x: %s\n", rc, + TPM2_GetRCString(rc)); + goto exit; + } + + /* try to unseal with a bad digest, but good signature, should fail */ + rc = wolfTPM2_UnsealWithAuthSig(&dev, &authKey, + tpmSession.handle.hndl, sealBlob.handle.hndl, TPM_ALG_SHA256, + pcrArray, pcrArraySz, badDigest, + policyDigestSz, nonce, sizeof(nonce), badSig, badSigSz, secretOut, + &secretOutSz); + if (rc == TPM_RC_SUCCESS) { + printf("wolfTPM2_UnsealWithAuthorizedKey failed, should not have" + "allowed bad digest 0x%x: %s\n", rc, + TPM2_GetRCString(rc)); + goto exit; + } + else { + rc = 0; + } + +exit: + if (rc != 0) { + printf("Failure 0x%x: %s\n", rc, wolfTPM2_GetRCString(rc)); + } + + wolfTPM2_SetAuthPassword(&dev, 0, NULL); + + wolfTPM2_UnloadHandle(&dev, &authKey.handle); + wolfTPM2_UnloadHandle(&dev, &sealBlob.handle); + wolfTPM2_UnloadHandle(&dev, &storage.handle); + wolfTPM2_UnloadHandle(&dev, &tpmSession.handle); + + wolfTPM2_Cleanup(&dev); + + return rc; +} + +/******************************************************************************/ +/* --- END TPM2.0 PCR Policy example tool -- */ +/******************************************************************************/ + +#endif /* !WOLFTPM2_NO_WRAPPER && !WOLFTPM2_NO_WOLFCRYPT */ + +#ifndef NO_MAIN_DRIVER +int main(int argc, char *argv[]) +{ + int rc = -1; + +#if !defined(WOLFTPM2_NO_WRAPPER) && !defined(WOLFTPM2_NO_WOLFCRYPT) + rc = TPM2_PCR_Seal_With_Policy_Auth_Test(NULL, argc, argv); +#else + printf("Wrapper code not compiled in\n"); + (void)argc; + (void)argv; +#endif /* !WOLFTPM2_NO_WRAPPER && !WOLFTPM2_NO_WOLFCRYPT */ + + return rc; +} +#endif diff --git a/src/tpm2_wrap.c b/src/tpm2_wrap.c index db818708..f1ef8da9 100644 --- a/src/tpm2_wrap.c +++ b/src/tpm2_wrap.c @@ -3351,9 +3351,9 @@ int wolfTPM2_NVDeleteKey(WOLFTPM2_DEV* dev, TPM_HANDLE primaryHandle, /* sigAlg: TPM_ALG_RSASSA, TPM_ALG_RSAPSS, TPM_ALG_ECDSA or TPM_ALG_ECDAA */ /* hashAlg: TPM_ALG_SHA1, TPM_ALG_SHA256, TPM_ALG_SHA384 or TPM_ALG_SHA512 */ -int wolfTPM2_SignHashScheme(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key, +int wolfTPM2_SignHashScheme_ex(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key, const byte* digest, int digestSz, byte* sig, int* sigSz, - TPMI_ALG_SIG_SCHEME sigAlg, TPMI_ALG_HASH hashAlg) + TPMI_ALG_SIG_SCHEME sigAlg, TPMI_ALG_HASH hashAlg, TPMT_SIGNATURE* sigOut) { int rc; Sign_In signIn; @@ -3375,8 +3375,10 @@ int wolfTPM2_SignHashScheme(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key, } } - /* set session auth for key */ - wolfTPM2_SetAuthHandle(dev, 0, &key->handle); + if (dev->ctx.session) { + /* set session auth for key */ + wolfTPM2_SetAuthHandle(dev, 0, &key->handle); + } XMEMSET(&signIn, 0, sizeof(signIn)); signIn.keyHandle = key->handle.hndl; @@ -3426,6 +3428,9 @@ int wolfTPM2_SignHashScheme(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key, } *sigSz = sigOutSz; + if (sigOut != NULL) + XMEMCPY(sigOut, &signOut.signature, sizeof(TPMT_SIGNATURE)); + #ifdef DEBUG_WOLFTPM printf("TPM2_Sign: %s %d\n", TPM2_GetAlgName(signIn.inScheme.scheme), *sigSz); @@ -3434,6 +3439,14 @@ int wolfTPM2_SignHashScheme(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key, return rc; } +int wolfTPM2_SignHashScheme(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key, + const byte* digest, int digestSz, byte* sig, int* sigSz, + TPMI_ALG_SIG_SCHEME sigAlg, TPMI_ALG_HASH hashAlg) +{ + return wolfTPM2_SignHashScheme_ex(dev, key, digest, digestSz, sig, sigSz, + sigAlg, hashAlg, NULL); +} + int wolfTPM2_SignHash(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key, const byte* digest, int digestSz, byte* sig, int* sigSz) { @@ -7350,6 +7363,1009 @@ int wolfTPM2_PolicyAuthorizeMake(TPM_ALG_ID pcrAlg, #endif return rc; } + + + + +/* use public authKey, must have digest, signature and nonce from external */ +int wolfTPM2_SealWithAuthSig(WOLFTPM2_DEV* dev, WOLFTPM2_KEYBLOB* authKey, + WOLFTPM2_HANDLE* parent, TPMT_PUBLIC* template, WOLFTPM2_KEYBLOB* sealBlob, + TPM_HANDLE sessionHandle, TPM_ALG_ID pcrAlg, byte* pcrArray, + word32 pcrArraySz, const byte* sealData, word32 sealSz, byte* policyDigest, + word32 policyDigestSz, const byte* nonce, word32 nonceSz, + const byte* policyDigestSig, word32 policyDigestSigSz) +{ + int rc; + byte checkDigest[TPM_MAX_DIGEST_SIZE]; + word32 checkDigestSz = TPM_MAX_DIGEST_SIZE; + PolicyAuthorize_In policyAuthIn[1]; + WOLFTPM2_HASH hash[1]; + TPM_ALG_ID sigAlg = TPM_ALG_NULL; + + if (dev == NULL || authKey == NULL || parent == NULL || template == NULL || + sealBlob == NULL || pcrArray == NULL || + sealData == NULL || policyDigest == NULL || policyDigestSig == NULL) { + return BAD_FUNC_ARG; + } + + XMEMSET(policyAuthIn, 0, sizeof(PolicyAuthorize_In)); + XMEMSET(hash, 0, sizeof(WOLFTPM2_HASH)); + + /* PolicyPCR should already have been added to the policy */ + /* start hash */ + rc = wolfTPM2_HashStart(dev, hash, pcrAlg, NULL, 0); + + /* hash the policyDigest */ + if (rc == 0) + rc = wolfTPM2_HashUpdate(dev, hash, policyDigest, policyDigestSz); + + /* hash the nonce */ + if (rc == 0 && nonce != NULL) + rc = wolfTPM2_HashUpdate(dev, hash, nonce, nonceSz); + + /* get the digest */ + if (rc == 0) + rc = wolfTPM2_HashFinish(dev, hash, checkDigest, &checkDigestSz); + + /* verify the signature, get the auth ticket, save it to policyAuthIn */ + if (rc == 0) { + if (authKey->pub.publicArea.type == TPM_ALG_ECC) { + sigAlg = authKey->pub.publicArea.parameters.eccDetail.scheme.scheme; + + if (sigAlg == TPM_ALG_NULL) + sigAlg = TPM_ALG_ECDSA; + } + else if (authKey->pub.publicArea.type == TPM_ALG_RSA) { + sigAlg = authKey->pub.publicArea.parameters.rsaDetail.scheme.scheme; + + if (sigAlg == TPM_ALG_NULL) + sigAlg = TPM_ALG_RSASSA; + } + + rc = wolfTPM2_VerifyHashTicket(dev, (WOLFTPM2_KEY*)authKey, + policyDigestSig, policyDigestSigSz, checkDigest, checkDigestSz, + sigAlg, WOLFTPM2_WRAP_DIGEST, &policyAuthIn->checkTicket); + } + + /* authorize the signing key by name to sign this policy */ + if (rc == 0) { + /* set session */ + policyAuthIn->policySession = sessionHandle; + + /* set authKey as the signer of this policy */ + XMEMCPY(&policyAuthIn->keySign, &authKey->handle.name, + sizeof(TPM2B_NAME)); + + /* set the approved policy digest */ + policyAuthIn->approvedPolicy.size = policyDigestSz; + XMEMCPY(policyAuthIn->approvedPolicy.buffer, policyDigest, + policyDigestSz); + + /* set the nonce */ + policyAuthIn->policyRef.size = nonceSz; + if (nonce != NULL) + XMEMCPY(policyAuthIn->policyRef.buffer, nonce, nonceSz); + + rc = TPM2_PolicyAuthorize(policyAuthIn); + } + + /* seal the object */ + if (rc == 0) { + rc = wolfTPM2_CreateKeySeal_ex(dev, sealBlob, parent, template, + NULL, 0, pcrAlg, pcrArray, pcrArraySz, sealData, sealSz); + } + + return rc; +} + +/* use private authKey */ +int wolfTPM2_SealWithAuthKey(WOLFTPM2_DEV* dev, WOLFTPM2_KEYBLOB* authKey, + WOLFTPM2_HANDLE* parent, TPMT_PUBLIC* template, WOLFTPM2_KEYBLOB* sealBlob, + TPM_HANDLE sessionHandle, TPM_ALG_ID pcrAlg, byte* pcrArray, + word32 pcrArraySz, const byte* sealData, word32 sealSz, const byte* nonce, + word32 nonceSz, byte* policyDigest, word32* policyDigestSz, + byte* policyDigestSig, word32* policyDigestSigSz) +{ + int rc = 0; + byte checkDigest[TPM_MAX_DIGEST_SIZE]; + word32 checkDigestSz = TPM_MAX_DIGEST_SIZE; + PolicyAuthorize_In policyAuthIn[1]; + WOLFTPM2_HASH hash[1]; + TPM_ALG_ID sigAlg = TPM_ALG_NULL; + + if (dev == NULL || authKey == NULL || parent == NULL || template == NULL || + sealBlob == NULL || pcrArray == NULL || sealData == NULL || + policyDigest == NULL || policyDigestSig == NULL) { + return BAD_FUNC_ARG; + } + + XMEMSET(policyAuthIn, 0, sizeof(PolicyAuthorize_In)); + XMEMSET(hash, 0, sizeof(WOLFTPM2_HASH)); + + /* add PolicyPCR to the policy */ + rc = wolfTPM2_PolicyPCR(dev, sessionHandle, pcrAlg, pcrArray, pcrArraySz); + + /* get the updated digest */ + if (rc == 0) { + rc = wolfTPM2_GetPolicyDigest(dev, sessionHandle, policyDigest, + policyDigestSz); + } + + /* start hash */ + if (rc == 0) + rc = wolfTPM2_HashStart(dev, hash, pcrAlg, NULL, 0); + + /* hash the policyDigest */ + if (rc == 0) + rc = wolfTPM2_HashUpdate(dev, hash, policyDigest, *policyDigestSz); + + /* hash the nonce */ + if (rc == 0 && nonce != NULL) + rc = wolfTPM2_HashUpdate(dev, hash, nonce, nonceSz); + + /* get the digest */ + if (rc == 0) + rc = wolfTPM2_HashFinish(dev, hash, checkDigest, &checkDigestSz); + + /* sign the hashed policyDigest so we can authorize it */ + if (rc == 0) { + if (authKey->pub.publicArea.type == TPM_ALG_ECC) { + sigAlg = authKey->pub.publicArea.parameters.eccDetail.scheme.scheme; + + if (sigAlg == TPM_ALG_NULL) + sigAlg = TPM_ALG_ECDSA; + } + else if (authKey->pub.publicArea.type == TPM_ALG_RSA) { + sigAlg = authKey->pub.publicArea.parameters.rsaDetail.scheme.scheme; + + if (sigAlg == TPM_ALG_NULL) + sigAlg = TPM_ALG_RSASSA; + } + + rc = wolfTPM2_SignHashScheme(dev, (WOLFTPM2_KEY*)authKey, checkDigest, + checkDigestSz, policyDigestSig, (int*)policyDigestSigSz, sigAlg, + WOLFTPM2_WRAP_DIGEST); + } + + /* verify the signature, get the auth ticket */ + if (rc == 0) { + rc = wolfTPM2_VerifyHashTicket(dev, (WOLFTPM2_KEY*)authKey, + policyDigestSig, *policyDigestSigSz, checkDigest, checkDigestSz, + sigAlg, WOLFTPM2_WRAP_DIGEST, &policyAuthIn->checkTicket); + } + + /* authorize the signing key by name to sign this policy */ + if (rc == 0) { + /* set session */ + policyAuthIn->policySession = sessionHandle; + + /* set authKey as the signer of this policy */ + XMEMCPY(&policyAuthIn->keySign, &authKey->handle.name, + sizeof(TPM2B_NAME)); + + /* set the approved policy digest */ + policyAuthIn->approvedPolicy.size = *policyDigestSz; + XMEMCPY(policyAuthIn->approvedPolicy.buffer, policyDigest, + *policyDigestSz); + + /* set the nonce */ + policyAuthIn->policyRef.size = nonceSz; + if (nonce != NULL) + XMEMCPY(policyAuthIn->policyRef.buffer, nonce, nonceSz); + + rc = TPM2_PolicyAuthorize(policyAuthIn); + } + + /* seal the object */ + if (rc == 0) { + rc = wolfTPM2_CreateKeySeal_ex(dev, sealBlob, parent, template, + NULL, 0, pcrAlg, pcrArray, pcrArraySz, sealData, sealSz); + } + + return rc; +} + +/* use public authKey */ +int wolfTPM2_UnsealWithAuthSig(WOLFTPM2_DEV* dev, WOLFTPM2_KEYBLOB* authKey, + TPM_HANDLE sessionHandle, TPM_HANDLE sealHandle, TPM_ALG_ID pcrAlg, + byte* pcrArray, word32 pcrArraySz, byte* policyDigest, + word32 policyDigestSz, const byte* nonce, word32 nonceSz, + const byte* policyDigestSig, word32 policyDigestSigSz, byte* out, + word32* outSz) +{ + int rc = 0; + PolicyAuthorize_In policyAuthIn[1]; + Unseal_In unsealIn[1]; + Unseal_Out unsealOut[1]; + byte checkDigest[TPM_MAX_DIGEST_SIZE]; + word32 checkDigestSz = TPM_MAX_DIGEST_SIZE; + WOLFTPM2_HASH hash[1]; + TPM_ALG_ID sigAlg = TPM_ALG_NULL; + + if (dev == NULL || authKey == NULL || pcrArray == NULL || + policyDigest == NULL || policyDigestSig == NULL) { + return BAD_FUNC_ARG; + } + + XMEMSET(policyAuthIn, 0, sizeof(PolicyAuthorize_In)); + XMEMSET(unsealIn, 0, sizeof(Unseal_In)); + XMEMSET(unsealOut, 0, sizeof(Unseal_Out)); + XMEMSET(hash, 0, sizeof(WOLFTPM2_HASH)); + + /* start hash */ + rc = wolfTPM2_HashStart(dev, hash, pcrAlg, NULL, 0); + + /* hash the policyDigest */ + if (rc == 0) + rc = wolfTPM2_HashUpdate(dev, hash, policyDigest, policyDigestSz); + + /* hash the nonce */ + if (rc == 0 && nonce != NULL) + rc = wolfTPM2_HashUpdate(dev, hash, nonce, nonceSz); + + /* get the digest */ + if (rc == 0) + rc = wolfTPM2_HashFinish(dev, hash, checkDigest, &checkDigestSz); + + /* verify the signature, get the auth ticket */ + if (rc == 0) { + if (authKey->pub.publicArea.type == TPM_ALG_ECC) { + sigAlg = authKey->pub.publicArea.parameters.eccDetail.scheme.scheme; + + if (sigAlg == TPM_ALG_NULL) + sigAlg = TPM_ALG_ECDSA; + } + else if (authKey->pub.publicArea.type == TPM_ALG_RSA) { + sigAlg = authKey->pub.publicArea.parameters.rsaDetail.scheme.scheme; + + if (sigAlg == TPM_ALG_NULL) + sigAlg = TPM_ALG_RSASSA; + } + + rc = wolfTPM2_VerifyHashTicket(dev, (WOLFTPM2_KEY*)authKey, + policyDigestSig, policyDigestSigSz, checkDigest, checkDigestSz, + sigAlg, WOLFTPM2_WRAP_DIGEST, &policyAuthIn->checkTicket); + } + + /* add PolicyPCR to the policy */ + if (rc == 0) { + rc = wolfTPM2_PolicyPCR(dev, sessionHandle, pcrAlg, pcrArray, pcrArraySz); + } + + /* authorize the policy with the auth ticket */ + if (rc == 0) { + /* set session */ + policyAuthIn->policySession = sessionHandle; + + /* set authKey as the signer of this policy */ + XMEMCPY(&policyAuthIn->keySign, &authKey->handle.name, + sizeof(TPM2B_NAME)); + + /* set the approved policy digest */ + policyAuthIn->approvedPolicy.size = policyDigestSz; + XMEMCPY(policyAuthIn->approvedPolicy.buffer, policyDigest, + policyDigestSz); + + /* set the nonce */ + policyAuthIn->policyRef.size = nonceSz; + if (nonce != NULL) + XMEMCPY(policyAuthIn->policyRef.buffer, nonce, nonceSz); + + rc = TPM2_PolicyAuthorize(policyAuthIn); + } + + /* unseal the buffer */ + if (rc == 0) { + unsealIn->itemHandle = sealHandle; + + rc = TPM2_Unseal(unsealIn, unsealOut); + } + + if (rc == 0) { + if (out == NULL) { + rc = LENGTH_ONLY_E; + } + else if (unsealOut->outData.size > *outSz) { + rc = INPUT_SIZE_E; + } + else { + XMEMCPY(out, unsealOut->outData.buffer, unsealOut->outData.size); + } + + *outSz = unsealOut->outData.size; + } + + return rc; +} + +int wolfTPM2_SealWithAuthSigNV(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* authKey, + WOLFTPM2_SESSION* session, TPM_ALG_ID policyHashAlg, TPM_ALG_ID pcrAlg, + byte* pcrArray, word32 pcrArraySz, const byte* sealData, word32 sealSz, + const byte* nonce, word32 nonceSz, const byte* policySignedSig, + word32 policySignedSigSz, word32 sealNvIndex, word32 policyDigestNvIndex) +{ + int rc = 0; + PolicySigned_In policySignedIn[1]; + PolicySigned_Out policySignedOut[1]; + PolicyAuthorizeNV_In policyAuthNVIn[1]; + WOLFTPM2_NV nv[1]; + WOLFTPM2_HANDLE parent[1]; + word32 nvAttributes; + byte policyDigest[TPM_MAX_DIGEST_SIZE]; + word32 policyDigestSz = TPM_MAX_DIGEST_SIZE; + word16 bigEnd; + + XMEMSET(policySignedIn, 0, sizeof(PolicySigned_In)); + XMEMSET(policySignedOut, 0, sizeof(PolicySigned_Out)); + XMEMSET(policyAuthNVIn, 0, sizeof(PolicyAuthorizeNV_In)); + XMEMSET(nv, 0, sizeof(WOLFTPM2_NV)); + XMEMSET(parent, 0, sizeof(WOLFTPM2_HANDLE)); + + if (dev == NULL || authKey == NULL || session == NULL || sealData == NULL || + policySignedSig == NULL || (nonceSz > 0 && nonce == NULL)) { + return BAD_FUNC_ARG; + } + + rc = wolfTPM2_SetAuthPassword(dev, 0, NULL); + + if (rc == 0) { + /* add PCR to the policy digest */ + rc = wolfTPM2_PolicyPCR(dev, session->handle.hndl, pcrAlg, pcrArray, + pcrArraySz); + } + + if (rc == 0) { + /* add PolicySigned to the policy */ + /* set the key handle */ + policySignedIn->authObject = authKey->handle.hndl; + + /* set the session */ + policySignedIn->policySession = session->handle.hndl; + + /* set nonce if it's non null */ + if (nonceSz > 0) { + policySignedIn->policyRef.size = nonceSz; + XMEMCPY(policySignedIn->policyRef.buffer, nonce, nonceSz); + } + + /* set auth sigAlg */ + if (authKey->pub.publicArea.type == TPM_ALG_ECC) { + policySignedIn->auth.sigAlg = + authKey->pub.publicArea.parameters.eccDetail.scheme.scheme; + + if (policySignedIn->auth.sigAlg == TPM_ALG_NULL) + policySignedIn->auth.sigAlg = TPM_ALG_ECDSA; + } + else if (authKey->pub.publicArea.type == TPM_ALG_RSA) { + policySignedIn->auth.sigAlg = + authKey->pub.publicArea.parameters.rsaDetail.scheme.scheme; + + if (policySignedIn->auth.sigAlg == TPM_ALG_NULL) + policySignedIn->auth.sigAlg = TPM_ALG_RSASSA; + } + + /* set hash alg */ + policySignedIn->auth.signature.any.hashAlg = pcrAlg; + + /* set auth signature */ + switch (authKey->pub.publicArea.type) { + case TPM_ALG_ECC: + policySignedIn->auth.signature.ecdsa.signatureR.size = + policySignedSigSz / 2; + XMEMCPY(policySignedIn->auth.signature.ecdsa.signatureR.buffer, + policySignedSig, + policySignedIn->auth.signature.ecdsa.signatureR.size); + + policySignedIn->auth.signature.ecdsa.signatureS.size = + policySignedSigSz / 2; + XMEMCPY(policySignedIn->auth.signature.ecdsa.signatureS.buffer, + policySignedSig + policySignedSigSz / 2, + policySignedIn->auth.signature.ecdsa.signatureS.size); + break; + case TPM_ALG_RSA: + policySignedIn->auth.signature.rsassa.sig.size = + policySignedSigSz; + XMEMCPY(policySignedIn->auth.signature.rsassa.sig.buffer, + policySignedSig, policySignedSigSz); + break; + default: + rc = BAD_FUNC_ARG; + break; + } + } + + if (rc == 0) { + rc = TPM2_PolicySigned(policySignedIn, policySignedOut); + } + + /* get the policyDigest */ + if (rc == 0) { + rc = wolfTPM2_GetPolicyDigest(dev, session->handle.hndl, policyDigest, + &policyDigestSz); + } + + /* get the nvAttributes */ + if (rc == 0) { + parent->hndl = TPM_RH_OWNER; + + rc = wolfTPM2_GetNvAttributesTemplate(parent->hndl, &nvAttributes); + } + + /* create the policy digest nv space */ + if (rc == 0) { + rc = wolfTPM2_NVCreateAuth(dev, parent, nv, policyDigestNvIndex, + nvAttributes, sizeof(TPM_ALG_ID) + policyDigestSz, NULL, 0); + + if (rc == TPM_RC_NV_DEFINED) + rc = 0; + } + + /* write the hash alg as the first two octects, big endian */ + if (rc == 0) { + bigEnd = XHTONS(policyHashAlg); + + rc = wolfTPM2_NVWriteAuth(dev, nv, policyDigestNvIndex, (byte*)&bigEnd, + sizeof(TPM_ALG_ID), 0); + } + + /* write the policy digest to the nv space */ + if (rc == 0) { + rc = wolfTPM2_NVWriteAuth(dev, nv, policyDigestNvIndex, policyDigest, + policyDigestSz, sizeof(TPM_ALG_ID)); + } + + /* authorize the policy */ + if (rc == 0) { + /* set session */ + policyAuthNVIn->policySession = session->handle.hndl; + + /* set nvIndex */ + policyAuthNVIn->nvIndex = policyDigestNvIndex; + + /* set authHandle */ + policyAuthNVIn->authHandle = parent->hndl; + + rc = TPM2_PolicyAuthorizeNV(policyAuthNVIn); + } + + /* create the sealData nv space */ + if (rc == 0) { + rc = wolfTPM2_NVCreateAuth(dev, parent, nv, sealNvIndex, nvAttributes, + sealSz + sizeof(word32), NULL, 0); + + if (rc == TPM_RC_NV_DEFINED) + rc = 0; + } + + /* seal the size */ + if (rc == 0) { + rc = wolfTPM2_NVWriteAuth(dev, nv, sealNvIndex, (byte*)&sealSz, + sizeof(word32), 0); + } + + /* seal the object */ + if (rc == 0) { + rc = wolfTPM2_NVWriteAuth(dev, nv, sealNvIndex, (byte*)sealData, sealSz, + sizeof(word32)); + } + + return rc; +} + +int wolfTPM2_SealWithAuthKeyNV(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* authKey, + WOLFTPM2_SESSION* session, TPM_ALG_ID policyHashAlg, TPM_ALG_ID pcrAlg, + byte* pcrArray, word32 pcrArraySz, const byte* sealData, word32 sealSz, + const byte* nonce, word32 nonceSz, word32 sealNvIndex, + word32 policyDigestNvIndex, byte* policySignedSig, + word32* policySignedSigSz) +{ + int rc = 0; + WOLFTPM2_HASH hash[1]; + PolicySigned_In policySignedIn[1]; + PolicySigned_Out policySignedOut[1]; + PolicyAuthorizeNV_In policyAuthNVIn[1]; + WOLFTPM2_NV nv[1]; + WOLFTPM2_HANDLE parent[1]; + word32 nvAttributes; + byte policyDigest[TPM_MAX_DIGEST_SIZE]; + word32 policyDigestSz = TPM_MAX_DIGEST_SIZE; + word16 bigEnd; + byte zeroExpiry[4]; + TPM_ALG_ID sigAlg = TPM_ALG_NULL; + byte aHash[TPM_MAX_DIGEST_SIZE]; + word32 aHashSz = TPM_MAX_DIGEST_SIZE; + + if (dev == NULL || pcrArray == NULL || sealData == NULL || + policySignedSig == NULL || (nonceSz > 0 && nonce == NULL)) { + return BAD_FUNC_ARG; + } + + XMEMSET(policySignedIn, 0, sizeof(PolicySigned_In)); + XMEMSET(policyAuthNVIn, 0, sizeof(PolicyAuthorizeNV_In)); + XMEMSET(hash, 0, sizeof(WOLFTPM2_HASH)); + XMEMSET(nv, 0, sizeof(WOLFTPM2_NV)); + XMEMSET(parent, 0, sizeof(WOLFTPM2_HANDLE)); + XMEMSET(zeroExpiry, 0, sizeof(zeroExpiry)); + + rc = wolfTPM2_SetAuthPassword(dev, 0, NULL); + + /* add PolicyPCR to the policy */ + if (rc == 0) + rc = wolfTPM2_PolicyPCR(dev, session->handle.hndl, pcrAlg, pcrArray, + pcrArraySz); + + /* start hash */ + if (rc == 0) + rc = wolfTPM2_HashStart(dev, hash, pcrAlg, NULL, 0); + + /* hash a zero expiration */ + if (rc == 0) + rc = wolfTPM2_HashUpdate(dev, hash, zeroExpiry, sizeof(zeroExpiry)); + + /* hash the nonce */ + if (rc == 0 && nonceSz > 0) + rc = wolfTPM2_HashUpdate(dev, hash, nonce, nonceSz); + + /* get the digest */ + if (rc == 0) + rc = wolfTPM2_HashFinish(dev, hash, aHash, &aHashSz); + + /* sign the digest */ + if (rc == 0) { + if (authKey->pub.publicArea.type == TPM_ALG_ECC) { + sigAlg = authKey->pub.publicArea.parameters.eccDetail.scheme.scheme; + + if (sigAlg == TPM_ALG_NULL) + sigAlg = TPM_ALG_ECDSA; + } + else if (authKey->pub.publicArea.type == TPM_ALG_RSA) { + sigAlg = authKey->pub.publicArea.parameters.rsaDetail.scheme.scheme; + + if (sigAlg == TPM_ALG_NULL) + sigAlg = TPM_ALG_RSASSA; + } + + rc = wolfTPM2_SignHashScheme_ex(dev, (WOLFTPM2_KEY*)authKey, aHash, + aHashSz, policySignedSig, (int*)policySignedSigSz, sigAlg, + policyHashAlg, &policySignedIn->auth); + } + + /* add PolicySigned to the policy */ + if (rc == 0) { + policySignedIn->authObject = authKey->handle.hndl; + + /* set the session */ + policySignedIn->policySession = session->handle.hndl; + + /* set nonce if it's non null */ + if (nonceSz > 0) { + policySignedIn->policyRef.size = nonceSz; + XMEMCPY(policySignedIn->policyRef.buffer, nonce, nonceSz); + } + + rc = TPM2_PolicySigned(policySignedIn, policySignedOut); + } + + /* get the policyDigest */ + if (rc == 0) { + rc = wolfTPM2_GetPolicyDigest(dev, session->handle.hndl, policyDigest, + &policyDigestSz); + } + + /* get the nvAttributes */ + if (rc == 0) { + parent->hndl = TPM_RH_OWNER; + + rc = wolfTPM2_GetNvAttributesTemplate(parent->hndl, &nvAttributes); + } + + /* create the policy digest nv space */ + if (rc == 0) { + rc = wolfTPM2_NVCreateAuth(dev, parent, nv, policyDigestNvIndex, + nvAttributes, sizeof(TPM_ALG_ID) + policyDigestSz, NULL, 0); + + if (rc == TPM_RC_NV_DEFINED) + rc = 0; + } + + /* write the hash alg as the first two octects, big endian */ + if (rc == 0) { + bigEnd = XHTONS(policyHashAlg); + + rc = wolfTPM2_NVWriteAuth(dev, nv, policyDigestNvIndex, (byte*)&bigEnd, + sizeof(TPM_ALG_ID), 0); + } + + /* write the policy digest to the nv space */ + if (rc == 0) { + rc = wolfTPM2_NVWriteAuth(dev, nv, policyDigestNvIndex, policyDigest, + policyDigestSz, sizeof(TPM_ALG_ID)); + } + + /* authorize the policy */ + if (rc == 0) { + /* set session */ + policyAuthNVIn->policySession = session->handle.hndl; + + /* set nvIndex */ + policyAuthNVIn->nvIndex = policyDigestNvIndex; + + /* set authHandle */ + policyAuthNVIn->authHandle = parent->hndl; + + rc = TPM2_PolicyAuthorizeNV(policyAuthNVIn); + } + + /* create the sealData nv space */ + if (rc == 0) { + rc = wolfTPM2_NVCreateAuth(dev, parent, nv, sealNvIndex, nvAttributes, + sealSz + sizeof(word32), NULL, 0); + + if (rc == TPM_RC_NV_DEFINED) + rc = 0; + } + + /* seal the size */ + if (rc == 0) { + rc = wolfTPM2_NVWriteAuth(dev, nv, sealNvIndex, (byte*)&sealSz, + sizeof(word32), 0); + } + + /* seal the object */ + if (rc == 0) { + rc = wolfTPM2_NVWriteAuth(dev, nv, sealNvIndex, (byte*)sealData, sealSz, + sizeof(word32)); + } + + return rc; +} + +int wolfTPM2_UnsealWithAuthSigNV(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* authKey, + WOLFTPM2_SESSION* session, TPM_ALG_ID pcrAlg, byte* pcrArray, + word32 pcrArraySz, const byte* nonce, word32 nonceSz, + const byte* policySignedSig, word32 policySignedSigSz, word32 sealNvIndex, + word32 policyDigestNvIndex, byte* out, word32* outSz) +{ + int rc = 0; + PolicySigned_In policySignedIn[1]; + PolicySigned_Out policySignedOut[1]; + word32 nvAttributes; + WOLFTPM2_NV nv[1]; + WOLFTPM2_HANDLE parent[1]; + PolicyAuthorizeNV_In policyAuthNVIn[1]; + word32 realSz; + word32 realSzSz = sizeof(word32); + + if (dev == NULL || authKey == NULL || pcrArray == NULL || + (nonceSz > 0 && nonce == NULL) || policySignedSig == NULL || out == NULL + || outSz == NULL) { + return BAD_FUNC_ARG; + } + + XMEMSET(policySignedIn, 0, sizeof(PolicySigned_In)); + XMEMSET(policySignedOut, 0, sizeof(PolicySigned_Out)); + XMEMSET(nv, 0, sizeof(WOLFTPM2_NV)); + XMEMSET(parent, 0, sizeof(WOLFTPM2_HANDLE)); + XMEMSET(policyAuthNVIn, 0, sizeof(PolicyAuthorizeNV_In)); + + rc = wolfTPM2_SetAuthPassword(dev, 0, NULL); + + /* add PolicyPCR to the policy */ + if (rc == 0) + rc = wolfTPM2_PolicyPCR(dev, session->handle.hndl, pcrAlg, pcrArray, + pcrArraySz); + + /* add PolicySigned to the policy */ + if (rc == 0) { + /* set the key handle */ + policySignedIn->authObject = authKey->handle.hndl; + + /* set the session */ + policySignedIn->policySession = session->handle.hndl; + + /* set nonce if it's non null */ + if (nonceSz > 0) { + policySignedIn->policyRef.size = nonceSz; + XMEMCPY(policySignedIn->policyRef.buffer, nonce, nonceSz); + } + + /* set auth sigAlg */ + if (authKey->pub.publicArea.type == TPM_ALG_ECC) { + policySignedIn->auth.sigAlg = + authKey->pub.publicArea.parameters.eccDetail.scheme.scheme; + + if (policySignedIn->auth.sigAlg == TPM_ALG_NULL) + policySignedIn->auth.sigAlg = TPM_ALG_ECDSA; + } + else if (authKey->pub.publicArea.type == TPM_ALG_RSA) { + policySignedIn->auth.sigAlg = + authKey->pub.publicArea.parameters.rsaDetail.scheme.scheme; + + if (policySignedIn->auth.sigAlg == TPM_ALG_NULL) + policySignedIn->auth.sigAlg = TPM_ALG_RSASSA; + } + + /* set hash alg */ + policySignedIn->auth.signature.any.hashAlg = pcrAlg; + + /* set auth signature */ + switch (authKey->pub.publicArea.type) { + case TPM_ALG_ECC: + policySignedIn->auth.signature.ecdsa.signatureR.size = + policySignedSigSz / 2; + XMEMCPY(policySignedIn->auth.signature.ecdsa.signatureR.buffer, + policySignedSig, + policySignedIn->auth.signature.ecdsa.signatureR.size); + + policySignedIn->auth.signature.ecdsa.signatureS.size = + policySignedSigSz / 2; + XMEMCPY(policySignedIn->auth.signature.ecdsa.signatureS.buffer, + policySignedSig + policySignedSigSz / 2, + policySignedIn->auth.signature.ecdsa.signatureS.size); + break; + case TPM_ALG_RSA: + policySignedIn->auth.signature.rsassa.sig.size = + policySignedSigSz; + XMEMCPY(policySignedIn->auth.signature.rsassa.sig.buffer, + policySignedSig, policySignedSigSz); + break; + default: + rc = BAD_FUNC_ARG; + break; + } + + if (rc == 0) { + rc = TPM2_PolicySigned(policySignedIn, policySignedOut); + } + } + + /* get the nvAttributes */ + if (rc == 0) { + parent->hndl = TPM_RH_OWNER; + + rc = wolfTPM2_GetNvAttributesTemplate(parent->hndl, &nvAttributes); + } + + /* create the policy digest nv space */ + if (rc == 0) { + rc = wolfTPM2_NVCreateAuth(dev, parent, nv, policyDigestNvIndex, + nvAttributes, sizeof(TPM_ALG_ID), NULL, 0); + + if (rc == TPM_RC_NV_DEFINED) + rc = 0; + } + + /* authorize the policy using the nv contents */ + if (rc == 0) { + /* set session */ + policyAuthNVIn->policySession = session->handle.hndl; + TPM2_SetSessionAuth(dev->session); + + /* set nvIndex */ + policyAuthNVIn->nvIndex = policyDigestNvIndex; + + /* set authHandle */ + policyAuthNVIn->authHandle = parent->hndl; + + rc = TPM2_PolicyAuthorizeNV(policyAuthNVIn); + } + + /* unseal the size */ + if (rc == 0) { + nv->handle.hndl = sealNvIndex; + + rc = wolfTPM2_NVReadAuth(dev, nv, sealNvIndex, + (byte*)&realSz, &realSzSz, 0); + } + + if (rc == 0) { + if (out == NULL) { + rc = LENGTH_ONLY_E; + } + else if (realSz > *outSz) { + rc = INPUT_SIZE_E; + } + + *outSz = realSz; + } + + /* unseal the buffer */ + if (rc == 0) { + rc = wolfTPM2_NVReadAuth(dev, nv, sealNvIndex, + out, outSz, realSzSz); + } + + return rc; +} + +int wolfTPM2_SealWithPCR_NV(WOLFTPM2_DEV* dev, WOLFTPM2_SESSION* session, + TPM_ALG_ID policyHashAlg, TPM_ALG_ID pcrAlg, byte* pcrArray, + word32 pcrArraySz, const byte* sealData, word32 sealSz, word32 sealNvIndex, + word32 policyDigestNvIndex) +{ + int rc = 0; + PolicyAuthorizeNV_In policyAuthNVIn[1]; + WOLFTPM2_NV nv[1]; + WOLFTPM2_HANDLE parent[1]; + word32 nvAttributes; + byte policyDigest[TPM_MAX_DIGEST_SIZE]; + word32 policyDigestSz = TPM_MAX_DIGEST_SIZE; + word16 bigEnd; + + if (dev == NULL || pcrArray == NULL || sealData == NULL) + return BAD_FUNC_ARG; + + XMEMSET(nv, 0, sizeof(WOLFTPM2_NV)); + XMEMSET(parent, 0, sizeof(WOLFTPM2_HANDLE)); + + rc = wolfTPM2_SetAuthPassword(dev, 0, NULL); + + /* add PolicyPCR to the policy */ + if (rc == 0) { + rc = wolfTPM2_PolicyPCR(dev, session->handle.hndl, pcrAlg, pcrArray, + pcrArraySz); + } + + /* get the policyDigest */ + if (rc == 0) { + rc = wolfTPM2_GetPolicyDigest(dev, session->handle.hndl, policyDigest, + &policyDigestSz); + } + + /* get the nvAttributes */ + if (rc == 0) { + parent->hndl = TPM_RH_OWNER; + + rc = wolfTPM2_GetNvAttributesTemplate(parent->hndl, &nvAttributes); + } + + /* create the policy digest nv space */ + if (rc == 0) { + rc = wolfTPM2_NVCreateAuth(dev, parent, nv, policyDigestNvIndex, + nvAttributes, sizeof(TPM_ALG_ID) + policyDigestSz, NULL, 0); + + if (rc == TPM_RC_NV_DEFINED) + rc = 0; + } + + /* write the hash alg as the first two octects, big endian */ + if (rc == 0) { + bigEnd = XHTONS(policyHashAlg); + + rc = wolfTPM2_NVWriteAuth(dev, nv, policyDigestNvIndex, (byte*)&bigEnd, + sizeof(TPM_ALG_ID), 0); + } + + /* write the policy digest to the nv space */ + if (rc == 0) { + rc = wolfTPM2_NVWriteAuth(dev, nv, policyDigestNvIndex, policyDigest, + policyDigestSz, sizeof(TPM_ALG_ID)); + } + + /* authorize the policy */ + if (rc == 0) { + /* set session */ + policyAuthNVIn->policySession = session->handle.hndl; + + /* set nvIndex */ + policyAuthNVIn->nvIndex = policyDigestNvIndex; + + /* set authHandle */ + policyAuthNVIn->authHandle = parent->hndl; + + rc = TPM2_PolicyAuthorizeNV(policyAuthNVIn); + } + + /* create the sealData nv space */ + if (rc == 0) { + rc = wolfTPM2_NVCreateAuth(dev, parent, nv, sealNvIndex, nvAttributes, + sealSz + sizeof(word32), NULL, 0); + + if (rc == TPM_RC_NV_DEFINED) + rc = 0; + } + + /* seal the size */ + if (rc == 0) { + rc = wolfTPM2_NVWriteAuth(dev, nv, sealNvIndex, (byte*)&sealSz, + sizeof(word32), 0); + } + + /* seal the object */ + if (rc == 0) { + rc = wolfTPM2_NVWriteAuth(dev, nv, sealNvIndex, (byte*)sealData, sealSz, + sizeof(word32)); + } + + return rc; +} + +int wolfTPM2_UnsealWithPCR_NV(WOLFTPM2_DEV* dev, WOLFTPM2_SESSION* session, + TPM_ALG_ID pcrAlg, byte* pcrArray, word32 pcrArraySz, word32 sealNvIndex, + word32 policyDigestNvIndex, byte* out, word32* outSz) +{ + int rc = 0; + word32 nvAttributes; + WOLFTPM2_NV nv[1]; + WOLFTPM2_HANDLE parent[1]; + PolicyAuthorizeNV_In policyAuthNVIn[1]; + word32 realSz; + word32 realSzSz = sizeof(word32); + + if (dev == NULL || pcrArray == NULL || out == NULL || outSz == NULL) + return BAD_FUNC_ARG; + + XMEMSET(nv, 0, sizeof(WOLFTPM2_NV)); + XMEMSET(parent, 0, sizeof(WOLFTPM2_HANDLE)); + XMEMSET(policyAuthNVIn, 0, sizeof(PolicyAuthorizeNV_In)); + + rc = wolfTPM2_SetAuthPassword(dev, 0, NULL); + + /* add PolicyPCR to the policy */ + if (rc == 0) { + rc = wolfTPM2_PolicyPCR(dev, session->handle.hndl, pcrAlg, pcrArray, + pcrArraySz); + } + + /* get the nvAttributes */ + if (rc == 0) { + parent->hndl = TPM_RH_OWNER; + + rc = wolfTPM2_GetNvAttributesTemplate(parent->hndl, &nvAttributes); + } + + /* create the policy digest nv space */ + if (rc == 0) { + rc = wolfTPM2_NVCreateAuth(dev, parent, nv, policyDigestNvIndex, + nvAttributes, sizeof(TPM_ALG_ID), NULL, 0); + + if (rc == TPM_RC_NV_DEFINED) + rc = 0; + } + + /* authorize the policy using the nv contents */ + if (rc == 0) { + /* set session */ + policyAuthNVIn->policySession = session->handle.hndl; + TPM2_SetSessionAuth(dev->session); + + /* set nvIndex */ + policyAuthNVIn->nvIndex = policyDigestNvIndex; + + /* set authHandle */ + policyAuthNVIn->authHandle = parent->hndl; + + rc = TPM2_PolicyAuthorizeNV(policyAuthNVIn); + } + + /* unseal the size */ + if (rc == 0) { + nv->handle.hndl = sealNvIndex; + + rc = wolfTPM2_NVReadAuth(dev, nv, sealNvIndex, + (byte*)&realSz, &realSzSz, 0); + } + + if (rc == 0) { + if (out == NULL) { + rc = LENGTH_ONLY_E; + } + else if (realSz > *outSz) { + rc = INPUT_SIZE_E; + } + + *outSz = realSz; + } + + /* unseal the buffer */ + if (rc == 0) { + rc = wolfTPM2_NVReadAuth(dev, nv, sealNvIndex, + out, outSz, realSzSz); + } + + return rc; +} + #endif /* !WOLFTPM2_NO_WOLFCRYPT */ /******************************************************************************/ diff --git a/wolftpm/tpm2.h b/wolftpm/tpm2.h index 5d6b6d38..6b195a74 100644 --- a/wolftpm/tpm2.h +++ b/wolftpm/tpm2.h @@ -3314,7 +3314,7 @@ WOLFTPM_API void TPM2_SetupPCRSel(TPML_PCR_SELECTION* pcr, TPM_ALG_ID alg, \param pcr pointer to a structure of type TPML_PCR_SELECTION \param alg value of type TPM_ALG_ID specifying the type of hash algorithm used \param pcrArray array of values between 0 and 23 specifying the PCR register for use - \param pcrArrayLen length of the pcrArray + \param pcrArraySz length of the pcrArray _Example_ \code @@ -3330,7 +3330,7 @@ WOLFTPM_API void TPM2_SetupPCRSel(TPML_PCR_SELECTION* pcr, TPM_ALG_ID alg, \sa TPM2_Quote */ WOLFTPM_API void TPM2_SetupPCRSelArray(TPML_PCR_SELECTION* pcr, TPM_ALG_ID alg, - byte* pcrArray, word32 pcrArrayLen); + byte* pcrArray, word32 pcrArraySz); /*! \ingroup TPM2_Proprietary diff --git a/wolftpm/tpm2_wrap.h b/wolftpm/tpm2_wrap.h index 2104f7de..859ec48e 100644 --- a/wolftpm/tpm2_wrap.h +++ b/wolftpm/tpm2_wrap.h @@ -1471,6 +1471,10 @@ WOLFTPM_API int wolfTPM2_SignHash(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key, \sa wolfTPM2_VerifyHash \sa wolfTPM2_VerifyHashScheme */ +WOLFTPM_API int wolfTPM2_SignHashScheme_ex(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key, + const byte* digest, int digestSz, byte* sig, int* sigSz, + TPMI_ALG_SIG_SCHEME sigAlg, TPMI_ALG_HASH hashAlg, TPMT_SIGNATURE* sigOut); + WOLFTPM_API int wolfTPM2_SignHashScheme(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key, const byte* digest, int digestSz, byte* sig, int* sigSz, TPMI_ALG_SIG_SCHEME sigAlg, TPMI_ALG_HASH hashAlg); @@ -3365,6 +3369,280 @@ WOLFTPM_API int wolfTPM2_PolicyAuthorizeMake(TPM_ALG_ID pcrAlg, const TPM2B_PUBLIC* pub, byte* digest, word32* digestSz, const byte* policyRef, word32 policyRefSz); + + + +/*! + \ingroup wolfTPM2_Wrappers + + \brief Seal a secret to the TPM with an externally signed policy digest and nonce. This + function will call policy authorize with the provided auth key and policy PCR with the PCR + indices that should apply to the secret. This seals the secret and ties it to the policy digest + value and nonce passed in. Can be unsealed using wolfTPM2_UnsealWithAuthSig. + + \return TPM_RC_SUCCESS: successful + \return INPUT_SIZE_E: policyDigestSz is too small to hold the returned digest + \return BAD_FUNC_ARG: check the provided arguments + + \param dev pointer to a populated structure of WOLFTPM2_DEV type + \param authKey pointer to a private key that will be used to sign and seal the secret + \param parent pointer to a struct of WOLFTPM2_HANDLE type, specifying a TPM 2.0 Primary Key to be used as the parent(Storage Key) + \param template to use for the seal key, can be generated using wolfTPM2_GetKeyTemplate_KeySeal + \param sealBlob the wolfTPM keyblob to keep the handle and public portion of the secret in + \param sessionHandle the handle of the current session, a session is required to use policy pcr + \param pcrAlg the hash algorithm to use with pcr policy + \param pcrArray array of pcr indices to use when creating the policy + \param pcrArraySz the number of indices in the pcrArray + \param sealData the data to seal into the tpm + \param sealSz the size of the seal data + \param policyDigest input digest of the policy, used to retrieve the secret later + \param policyDigestSz size of the policyDigest to be updated by this function + \param nonce a one time number to include in our policy + \param nonceSz size of nonce + \param policyDigestSig a signature of the policyDigest, signed by the authKey's private section + \param policyDigestSigSz size of policyDigestSig + + \sa wolfTPM2_UnsealWithAuthSig +*/ +WOLFTPM_API int wolfTPM2_SealWithAuthSig(WOLFTPM2_DEV* dev, + WOLFTPM2_KEYBLOB* authKey, WOLFTPM2_HANDLE* parent, TPMT_PUBLIC* template, + WOLFTPM2_KEYBLOB* sealBlob, TPM_HANDLE sessionHandle, TPM_ALG_ID pcrAlg, + byte* pcrArray, word32 pcrArraySz, const byte* sealData, word32 sealSz, + byte* policyDigest, word32 policyDigestSz, const byte* nonce, + word32 nonceSz, const byte* policyDigestSig, word32 policyDigestSigSz); + +/*! + \ingroup wolfTPM2_Wrappers + + \brief Seal a secret to the TPM after calling policy authorize with the provided auth key + and policy PCR with the PCR Indicesthat should apply to the secret. This seals the secret + and ties it to the policy digest value returned which can the be signed by the authKey passed + in to unseal the secret. Can be unsealed using wolfTPM2_UnsealWithAuthSig. + + \return TPM_RC_SUCCESS: successful + \return INPUT_SIZE_E: policyDigestSz is too small to hold the returned digest + \return BAD_FUNC_ARG: check the provided arguments + + \param dev pointer to a populated structure of WOLFTPM2_DEV type + \param authKey pointer to a private key that will be used to sign and seal the secret + \param parent pointer to a struct of WOLFTPM2_HANDLE type, specifying a TPM 2.0 Primary Key to be used as the parent(Storage Key) + \param template to use for the seal key, can be generated using wolfTPM2_GetKeyTemplate_KeySeal + \param sealBlob the wolfTPM keyblob to keep the handle and public portion of the secret in + \param sessionHandle the handle of the current session, a session is required to use policy pcr + \param pcrAlg the hash algorithm to use with pcr policy + \param pcrArray array of pcr indices to use when creating the policy + \param pcrArraySz the number of indices in the pcrArray + \param sealData the data to seal into the tpm + \param sealSz the size of the seal data + \param nonce a one time number to include in our policy + \param nonceSz size of nonce + \param policyDigest output digest of the policy, used to retrieve the secret later + \param policyDigestSz pointer to the size of the policyDigest to be updated by this function + + \sa wolfTPM2_UnsealWithAuthKey +*/ +WOLFTPM_API int wolfTPM2_SealWithAuthKey(WOLFTPM2_DEV* dev, + WOLFTPM2_KEYBLOB* authKey, WOLFTPM2_HANDLE* parent, TPMT_PUBLIC* template, + WOLFTPM2_KEYBLOB* sealBlob, TPM_HANDLE sessionHandle, TPM_ALG_ID pcrAlg, + byte* pcrArray, word32 pcrArraySz, const byte* sealData, word32 sealSz, + const byte* nonce, word32 nonceSz, byte* policyDigest, + word32* policyDigestSz, byte* policyDigestSig, word32* policyDigestSigSz); + +/*! + \ingroup wolfTPM2_Wrappers + + \brief Unseal a secret from the TPM after verifying the digest signature + was signed by the auth private key and checking the policy using policy + authorize and and policy pcr + + \return TPM_RC_SUCCESS: successful + \return INPUT_SIZE_E: policyDigestSz is too small to hold the returned digest + \return BAD_FUNC_ARG: check the provided arguments + + \param dev pointer to a populated structure of WOLFTPM2_DEV type + \param authKey pointer to a public key used to verify the policy digest signature + \param sessionHandle the handle of the current session, a session is required to use policy pcr + \param sealHandle the handle of the secret to be unsealed + \param pcrAlg the hashing algorithm to use for pcr values + \param pcrArray array of PCR indices to use with this policy + \param pcrArraySz length of pcrArray + \param policyDigest the digest of the policy that will be used to authorize the secret retrieval + \param policyDigestSz size of the policyDigest + \param nonce a one time number to include in our policy + \param nonceSz size of nonce + \param policyDigestSig a signature of the policyDigest, signed by the authKey's private section + \param policyDigestSigSz size of policyDigestSig + \param out the buffer that the retrieved secret will be written to + \param outSz pointer to the size of out + + \sa wolfTPM2_SealWithAuthKey + \sa wolfTPM2_SealWithAuthSig + \sa wolfTPM2_SealWithAuthSigNV +*/ +WOLFTPM_API int wolfTPM2_UnsealWithAuthSig(WOLFTPM2_DEV* dev, + WOLFTPM2_KEYBLOB* authKey, TPM_HANDLE sessionHandle, TPM_HANDLE sealHandle, + TPM_ALG_ID pcrAlg, byte* pcrArray, word32 pcrArraySz, byte* policyDigest, + word32 policyDigestSz, const byte* nonce, word32 nonceSz, + const byte* policyDigestSig, word32 policyDigestSigSz, byte* out, + word32* outSz); + +/*! + \ingroup wolfTPM2_Wrappers + + \brief Seal a secret to the TPM NVM after calling PolicyPCR with the passed + in pcrArray indices and verifying the PolicySigned signature was signed by + the auth private key along with the policyDigest of the session. + Can be unsealed using wolfTPM2_UnsealWithAuthSig. + + \return TPM_RC_SUCCESS: successful + \return INPUT_SIZE_E: policyDigestSz is too small to hold the returned digest + \return BAD_FUNC_ARG: check the provided arguments + + \param dev pointer to a populated structure of WOLFTPM2_DEV type + \param authKey pointer to a public key used to verify the policy digest signature + \param session the current session, a session is required to use policy pcr + \param policyHashAlg the hashing algorithm used to calculate policyDigest + \param pcrAlg the hashing algorithm to use for pcr values + \param pcrArray array of PCR indices to use with this policy + \param pcrArraySz length of pcrArray + \param sealData the data to seal into the tpm + \param sealSz the size of the seal data + \param nonce a one time number to include in our policy + \param nonceSz size of nonce + \param policySignedSig a signature of aHash as defined in the tpm2 documentation for PolicySigned + \param policySignedSigSz size of policySignedSig + \param sealNvIndex the NV index of the TPM to seal the secret to + \param policyDigestNvIndex the NV index of the TPM to seal the policyDigest to + + \sa wolfTPM2_UnsealWithAuthSig +*/ +WOLFTPM_API int wolfTPM2_SealWithAuthSigNV(WOLFTPM2_DEV* dev, + WOLFTPM2_KEY* authKey, WOLFTPM2_SESSION* session, TPM_ALG_ID policyHashAlg, + TPM_ALG_ID pcrAlg, byte* pcrArray, word32 pcrArraySz, + const byte* sealData, word32 sealSz, const byte* nonce, word32 nonceSz, + const byte* policySignedSig, word32 policySignedSigSz, word32 sealNvIndex, + word32 policyDigestNvIndex); + +/*! + \ingroup wolfTPM2_Wrappers + + \brief Seal a secret to the TPM's NVM after calling PolicyPCR and authorizing the current + policyDigest to later unseal the secret from NVM. + + \return TPM_RC_SUCCESS: successful + \return BAD_FUNC_ARG: check the provided arguments + + \param dev pointer to a populated structure of WOLFTPM2_DEV type + \param authKey authentication key + \param session the pointer to current session, a session is required to use policy pcr + \param policyHashAlg the hashing algorithm used to generate the policyDigest + \param pcrAlg the hashing algorithm to use for pcr values + \param pcrArray array of PCR indices to use with this policy + \param pcrArraySz length of pcrArray + \param sealData the secret to save to NVM + \param sealSz size of the secret buffer + \param nonce a one time number to include in our policy + \param nonceSz size of nonce + \param sealNvIndex nvIndex to write the secret to + \param policyDigestNvIndex nvIndex to write the policyDigest to + \param policySignedSig output signature of aHash as defined in the tpm2 documentation for PolicySigned + \param policySignedSigSz size of policySignedSig + + \sa wolfTPM2_SealWithAuthPolicyNV +*/ +WOLFTPM_API int wolfTPM2_SealWithAuthKeyNV(WOLFTPM2_DEV* dev, + WOLFTPM2_KEY* authKey, WOLFTPM2_SESSION* session, + TPM_ALG_ID policyHashAlg, TPM_ALG_ID pcrAlg, byte* pcrArray, + word32 pcrArraySz, const byte* sealData, word32 sealSz, + const byte* nonce, word32 nonceSz, word32 sealNvIndex, + word32 policyDigestNvIndex, byte* policySignedSig, + word32* policySignedSigSz); + +/*! + \ingroup wolfTPM2_Wrappers + + \brief Unseal a secret from the TPM's NVM after calling PolicyPCR and + authorizing the current policyDigest with PolicyAuthorizeNV and checking + the policySignedSig with PolicySigned + + \return TPM_RC_SUCCESS: successful + \return BAD_FUNC_ARG: check the provided arguments + + \param dev pointer to a populated structure of WOLFTPM2_DEV type + \param authKey authentication key + \param session the pointer to current session, a session is required to use policy pcr + \param pcrAlg the hashing algorithm to use for pcr values + \param pcrArray array of PCR indices to use with this policy + \param pcrArraySz length of pcrArray + \param nonce a one time number to include in our policy + \param nonceSz size of nonce + \param policySignedSig a signature of aHash as defined in the tpm2 documentation for PolicySigned + \param policySignedSigSz size of policySignedSig + \param sealNvIndex nvIndex to read the secret from + \param policyDigestNvIndex nvIndex to read the policyDigest from + \param out output buffer to read the unsealed secret + \param outSz pointer to the size of the output buffer + + \sa wolfTPM2_SealWithAuthKeyNV +*/ +WOLFTPM_API int wolfTPM2_UnsealWithAuthSigNV(WOLFTPM2_DEV* dev, + WOLFTPM2_KEY* authKey, WOLFTPM2_SESSION* session, TPM_ALG_ID pcrAlg, + byte* pcrArray, word32 pcrArraySz, const byte* nonce, word32 nonceSz, + const byte* policySignedSig, word32 policySignedSigSz, word32 sealNvIndex, + word32 policyDigestNvIndex, byte* out, word32* outSz); + +/*! + \ingroup wolfTPM2_Wrappers + + \brief Seal a secret to the TPM's NVM after calling PolicyPCR + + \return TPM_RC_SUCCESS: successful + \return BAD_FUNC_ARG: check the provided arguments + + \param dev pointer to a populated structure of WOLFTPM2_DEV type + \param session the pointer to current session, a session is required to use policy pcr + \param policyHashAlg the hashing algorithm used to generate the policyDigest + \param pcrAlg the hashing algorithm to use for pcr values + \param pcrArray array of PCR indices to use with this policy + \param pcrArraySz length of pcrArray + \param sealData the secret to save to NVM + \param sealSz size of the secret buffer + \param sealNvIndex nvIndex to write the secret to + \param policyDigestNvIndex nvIndex to write the policyDigest to + + \sa wolfTPM2_UnsealWithPCR_NV +*/ +WOLFTPM_API int wolfTPM2_SealWithPCR_NV(WOLFTPM2_DEV* dev, + WOLFTPM2_SESSION* session, TPM_ALG_ID policyHashAlg, TPM_ALG_ID pcrAlg, + byte* pcrArray, word32 pcrArraySz, const byte* sealData, word32 sealSz, + word32 sealNvIndex, word32 policyDigestNvIndex); + +/*! + \ingroup wolfTPM2_Wrappers + + \brief Unseal a secret from the TPM's NVM after calling PolicyPCR + + \return TPM_RC_SUCCESS: successful + \return BAD_FUNC_ARG: check the provided arguments + + \param dev pointer to a populated structure of WOLFTPM2_DEV type + \param session the pointer to current session, a session is required to use policy pcr + \param pcrAlg the hashing algorithm to use for pcr values + \param pcrArray array of PCR indices to use with this policy + \param pcrArraySz length of pcrArray + \param sealNvIndex nvIndex to write the secret to + \param policyDigestNvIndex nvIndex to write the policyDigest to + \param out output buffer to read the unsealed secret + \param outSz pointer to the size of the output buffer + + \sa wolfTPM2_SealWithPCR_NV +*/ +WOLFTPM_API int wolfTPM2_UnsealWithPCR_NV(WOLFTPM2_DEV* dev, + WOLFTPM2_SESSION* session, TPM_ALG_ID pcrAlg, byte* pcrArray, + word32 pcrArraySz, word32 sealNvIndex, word32 policyDigestNvIndex, + byte* out, word32* outSz); + + #ifdef __cplusplus } /* extern "C" */ #endif