/* native_test.c * * Copyright (C) 2006-2018 wolfSSL Inc. * * This file is part of wolfSSL. (formerly known as CyaSSL) * * 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 example shows using the TPM2_ specification API's in TPM2_Native_Test() */ #include #include #include /******************************************************************************/ /* --- BEGIN TPM Native API Tests -- */ /******************************************************************************/ #define TPM_20_TPM_MFG_NV_SPACE ((TPM_HT_NV_INDEX << 24) | (0x00 << 22)) #define TPM_20_PLATFORM_MFG_NV_SPACE ((TPM_HT_NV_INDEX << 24) | (0x01 << 22)) #define TPM_20_OWNER_NV_SPACE ((TPM_HT_NV_INDEX << 24) | (0x02 << 22)) #define TPM_20_TCG_NV_SPACE ((TPM_HT_NV_INDEX << 24) | (0x03 << 22)) #define TPM_20_NV_INDEX_EK_CERTIFICATE (TPM_20_PLATFORM_MFG_NV_SPACE + 2) #define TPM_20_NV_INDEX_EK_NONCE (TPM_20_PLATFORM_MFG_NV_SPACE + 3) #define TPM_20_NV_INDEX_EK_TEMPLATE (TPM_20_PLATFORM_MFG_NV_SPACE + 4) typedef struct tpmKey { TPM_HANDLE handle; TPM2B_AUTH auth; TPMT_SYM_DEF_OBJECT symmetric; /* used for parameter encrypt/decrypt */ TPM2B_PRIVATE priv; TPM2B_PUBLIC pub; TPM2B_NAME name; } TpmKey; typedef TpmKey TpmRsaKey; typedef TpmKey TpmEccKey; typedef TpmKey TpmHmacKey; typedef struct tmpHandle { TPM_HANDLE handle; TPM2B_AUTH auth; } TpmHandle; int TPM2_Native_Test(void* userCtx) { int rc; TPM2_CTX tpm2Ctx; const BYTE TPM_20_EK_AUTH_POLICY[] = { 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, }; union { Startup_In startup; Shutdown_In shutdown; SelfTest_In selfTest; GetRandom_In getRand; StirRandom_In stirRand; GetCapability_In cap; IncrementalSelfTest_In incSelfTest; PCR_Read_In pcrRead; PCR_Extend_In pcrExtend; CreatePrimary_In createPri; Create_In create; EvictControl_In evict; ReadPublic_In readPub; StartAuthSession_In authSes; Load_In load; LoadExternal_In loadExt; FlushContext_In flushCtx; Unseal_In unseal; PolicyGetDigest_In policyGetDigest; PolicyPCR_In policyPCR; PolicyRestart_In policyRestart; PolicyCommandCode_In policyCC; Clear_In clear; HashSequenceStart_In hashSeqStart; SequenceUpdate_In seqUpdate; SequenceComplete_In seqComp; MakeCredential_In makeCred; ObjectChangeAuth_In objChgAuth; NV_ReadPublic_In nvReadPub; NV_DefineSpace_In nvDefine; NV_UndefineSpace_In nvUndefine; RSA_Encrypt_In rsaEnc; RSA_Decrypt_In rsaDec; Sign_In sign; VerifySignature_In verifySign; ECC_Parameters_In eccParam; ECDH_KeyGen_In ecdh; ECDH_ZGen_In ecdhZ; byte maxInput[MAX_COMMAND_SIZE]; } cmdIn; union { GetCapability_Out cap; GetRandom_Out getRand; GetTestResult_Out tr; IncrementalSelfTest_Out incSelfTest; PCR_Read_Out pcrRead; CreatePrimary_Out createPri; Create_Out create; ReadPublic_Out readPub; StartAuthSession_Out authSes; Load_Out load; LoadExternal_Out loadExt; Unseal_Out unseal; PolicyGetDigest_Out policyGetDigest; HashSequenceStart_Out hashSeqStart; SequenceComplete_Out seqComp; MakeCredential_Out makeCred; ObjectChangeAuth_Out objChgAuth; NV_ReadPublic_Out nvReadPub; RSA_Encrypt_Out rsaEnc; RSA_Decrypt_Out rsaDec; Sign_Out sign; VerifySignature_Out verifySign; ECC_Parameters_Out eccParam; ECDH_KeyGen_Out ecdh; ECDH_ZGen_Out ecdhZ; byte maxOutput[MAX_RESPONSE_SIZE]; } cmdOut; int pcrCount, pcrIndex, i; TPML_TAGGED_TPM_PROPERTY* tpmProp; TPM_HANDLE handle = TPM_RH_NULL; TPM_HANDLE sessionHandle = TPM_RH_NULL; TPMI_RH_NV_INDEX nvIndex; TPM2B_PUBLIC_KEY_RSA message; byte pcr[WC_SHA256_DIGEST_SIZE]; int pcr_len = WC_SHA256_DIGEST_SIZE; byte hash[WC_SHA256_DIGEST_SIZE]; int hash_len = WC_SHA256_DIGEST_SIZE; TpmRsaKey endorse; TpmRsaKey storage; TpmHmacKey hmacKey; TpmEccKey eccKey; TpmRsaKey rsaKey; const char storagePwd[] = "WolfTPMPassword"; const char usageAuth[] = "ThisIsASecretUsageAuth"; const char userKey[] = "ThisIsMyHmacKey"; const char label[] = "ThisIsMyLabel"; const char keyCreationNonce[] = "RandomServerPickedCreationNonce"; const char* hashTestData = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; const char* hashTestDig = "\x24\x8D\x6A\x61\xD2\x06\x38\xB8\xE5\xC0\x26\x93\x0C\x3E\x60" "\x39\xA3\x3C\xE4\x59\x64\xFF\x21\x67\xF6\xEC\xED\xD4\x19\xDB" "\x06\xC1"; TPMS_AUTH_COMMAND session[MAX_SESSION_NUM]; printf("TPM2 Demo using Native API's\n"); endorse.handle = TPM_RH_NULL; storage.handle = TPM_RH_NULL; hmacKey.handle = TPM_RH_NULL; eccKey.handle = TPM_RH_NULL; message.size = WC_SHA256_DIGEST_SIZE; XMEMSET(message.buffer, 0x11, message.size); rc = TPM2_Init(&tpm2Ctx, TPM2_IoCb, userCtx); if (rc != TPM_RC_SUCCESS) { printf("TPM2_Init failed 0x%x: %s\n", rc, TPM2_GetRCString(rc)); goto exit; } printf("TPM2: Caps 0x%08x, Did 0x%04x, Vid 0x%04x, Rid 0x%2x \n", tpm2Ctx.caps, tpm2Ctx.did_vid >> 16, tpm2Ctx.did_vid & 0xFFFF, tpm2Ctx.rid); /* define the default session auth */ XMEMSET(session, 0, sizeof(session)); session[0].sessionHandle = TPM_RS_PW; TPM2_SetSessionAuth(session); XMEMSET(&cmdIn.startup, 0, sizeof(cmdIn.startup)); cmdIn.startup.startupType = TPM_SU_CLEAR; rc = TPM2_Startup(&cmdIn.startup); if (rc != TPM_RC_SUCCESS && rc != TPM_RC_INITIALIZE /* TPM_RC_INITIALIZE = Already started */ ) { printf("TPM2_Startup failed 0x%x: %s\n", rc, TPM2_GetRCString(rc)); goto exit; } printf("TPM2_Startup pass\n"); /* Full self test */ XMEMSET(&cmdIn.selfTest, 0, sizeof(cmdIn.selfTest)); cmdIn.selfTest.fullTest = YES; rc = TPM2_SelfTest(&cmdIn.selfTest); if (rc != TPM_RC_SUCCESS) { printf("TPM2_SelfTest failed 0x%x: %s\n", rc, TPM2_GetRCString(rc)); goto exit; } printf("TPM2_SelfTest pass\n"); /* Get Test Result */ rc = TPM2_GetTestResult(&cmdOut.tr); if (rc != TPM_RC_SUCCESS) { printf("TPM2_GetTestResult failed 0x%x: %s\n", rc, TPM2_GetRCString(rc)); goto exit; } printf("TPM2_GetTestResult: Size %d, Rc 0x%x\n", cmdOut.tr.outData.size, cmdOut.tr.testResult); TPM2_PrintBin(cmdOut.tr.outData.buffer, cmdOut.tr.outData.size); /* Incremental Test */ XMEMSET(&cmdIn.incSelfTest, 0, sizeof(cmdIn.incSelfTest)); cmdIn.incSelfTest.toTest.count = 1; cmdIn.incSelfTest.toTest.algorithms[0] = TPM_ALG_RSA; rc = TPM2_IncrementalSelfTest(&cmdIn.incSelfTest, &cmdOut.incSelfTest); printf("TPM2_IncrementalSelfTest: Rc 0x%x, Alg 0x%x (Todo %d)\n", rc, cmdIn.incSelfTest.toTest.algorithms[0], (int)cmdOut.incSelfTest.toDoList.count); /* Get Capability for Property */ XMEMSET(&cmdIn.cap, 0, sizeof(cmdIn.cap)); cmdIn.cap.capability = TPM_CAP_TPM_PROPERTIES; cmdIn.cap.property = TPM_PT_FAMILY_INDICATOR; cmdIn.cap.propertyCount = 1; rc = TPM2_GetCapability(&cmdIn.cap, &cmdOut.cap); if (rc != TPM_RC_SUCCESS) { printf("TPM2_GetCapability failed 0x%x: %s\n", rc, TPM2_GetRCString(rc)); goto exit; } tpmProp = &cmdOut.cap.capabilityData.data.tpmProperties; printf("TPM2_GetCapability: Property FamilyIndicator 0x%08x\n", (unsigned int)tpmProp->tpmProperty[0].value); cmdIn.cap.capability = TPM_CAP_TPM_PROPERTIES; cmdIn.cap.property = TPM_PT_PCR_COUNT; cmdIn.cap.propertyCount = 1; rc = TPM2_GetCapability(&cmdIn.cap, &cmdOut.cap); if (rc != TPM_RC_SUCCESS) { printf("TPM2_GetCapability failed 0x%x: %s\n", rc, TPM2_GetRCString(rc)); goto exit; } tpmProp = &cmdOut.cap.capabilityData.data.tpmProperties; pcrCount = tpmProp->tpmProperty[0].value; printf("TPM2_GetCapability: Property PCR Count %d\n", pcrCount); /* Random */ XMEMSET(&cmdIn.getRand, 0, sizeof(cmdIn.getRand)); cmdIn.getRand.bytesRequested = WC_SHA256_DIGEST_SIZE; rc = TPM2_GetRandom(&cmdIn.getRand, &cmdOut.getRand); if (rc != TPM_RC_SUCCESS) { printf("TPM2_GetRandom failed 0x%x: %s\n", rc, TPM2_GetRCString(rc)); goto exit; } if (cmdOut.getRand.randomBytes.size != WC_SHA256_DIGEST_SIZE) { printf("TPM2_GetRandom length mismatch %d != %d\n", cmdOut.getRand.randomBytes.size, WC_SHA256_DIGEST_SIZE); goto exit; } printf("TPM2_GetRandom: Got %d bytes\n", cmdOut.getRand.randomBytes.size); TPM2_PrintBin(cmdOut.getRand.randomBytes.buffer, cmdOut.getRand.randomBytes.size); /* Stir Random */ XMEMSET(&cmdIn.stirRand, 0, sizeof(cmdIn.stirRand)); cmdIn.stirRand.inData.size = cmdOut.getRand.randomBytes.size; XMEMCPY(cmdIn.stirRand.inData.buffer, cmdOut.getRand.randomBytes.buffer, cmdIn.stirRand.inData.size); rc = TPM2_StirRandom(&cmdIn.stirRand); if (rc != TPM_RC_SUCCESS) { printf("TPM2_StirRandom failed 0x%x: %s\n", rc, TPM2_GetRCString(rc)); goto exit; } printf("TPM2_StirRandom: success\n"); /* PCR Read */ for (i=0; i 0) { printf("TPM2_NV_ReadPublic: Sz %d, Idx 0x%x, nameAlg %d, Attr 0x%x," " authPol %d, dataSz %d, name %d\n", cmdOut.nvReadPub.nvPublic.size, cmdOut.nvReadPub.nvPublic.nvPublic.nvIndex, cmdOut.nvReadPub.nvPublic.nvPublic.nameAlg, cmdOut.nvReadPub.nvPublic.nvPublic.attributes, cmdOut.nvReadPub.nvPublic.nvPublic.authPolicy.size, cmdOut.nvReadPub.nvPublic.nvPublic.dataSize, cmdOut.nvReadPub.nvName.size); } } /* Define new NV */ nvIndex = TPM_20_OWNER_NV_SPACE + 0x003FFFFF; /* Last owner Index */ XMEMSET(&cmdIn.nvDefine, 0, sizeof(cmdIn.nvDefine)); cmdIn.nvDefine.authHandle = storage.handle; cmdIn.nvDefine.auth.size = sizeof(usageAuth)-1; XMEMCPY(cmdIn.nvDefine.auth.buffer, usageAuth, cmdIn.nvDefine.auth.size); cmdIn.nvDefine.publicInfo.nvPublic.nvIndex = nvIndex; cmdIn.nvDefine.publicInfo.nvPublic.nameAlg = TPM_ALG_SHA256; cmdIn.nvDefine.publicInfo.nvPublic.attributes = ( TPMA_NV_OWNERWRITE | TPMA_NV_OWNERREAD | TPMA_NV_NO_DA | TPMA_NV_ORDERLY); cmdIn.nvDefine.publicInfo.nvPublic.dataSize = WC_SHA256_DIGEST_SIZE; rc = TPM2_NV_DefineSpace(&cmdIn.nvDefine); if (rc != TPM_RC_SUCCESS) { printf("TPM2_NV_DefineSpace failed 0x%x: %s\n", rc, TPM2_GetRCString(rc)); goto exit; } printf("TPM2_NV_DefineSpace: 0x%x\n", nvIndex); /* Read NV */ XMEMSET(&cmdIn.nvReadPub, 0, sizeof(cmdIn.nvReadPub)); cmdIn.nvReadPub.nvIndex = nvIndex; rc = TPM2_NV_ReadPublic(&cmdIn.nvReadPub, &cmdOut.nvReadPub); if (rc != TPM_RC_SUCCESS) { printf("TPM2_NV_ReadPublic failed 0x%x: %s\n", rc, TPM2_GetRCString(rc)); //goto exit; } printf("TPM2_NV_ReadPublic: Sz %d, Idx 0x%x, nameAlg %d, Attr 0x%x, " "authPol %d, dataSz %d, name %d\n", cmdOut.nvReadPub.nvPublic.size, cmdOut.nvReadPub.nvPublic.nvPublic.nvIndex, cmdOut.nvReadPub.nvPublic.nvPublic.nameAlg, cmdOut.nvReadPub.nvPublic.nvPublic.attributes, cmdOut.nvReadPub.nvPublic.nvPublic.authPolicy.size, cmdOut.nvReadPub.nvPublic.nvPublic.dataSize, cmdOut.nvReadPub.nvName.size); /* Undefine NV */ XMEMSET(&cmdIn.nvUndefine, 0, sizeof(cmdIn.nvUndefine)); cmdIn.nvUndefine.authHandle = storage.handle; cmdIn.nvUndefine.nvIndex = nvIndex; rc = TPM2_NV_UndefineSpace(&cmdIn.nvUndefine); if (rc != TPM_RC_SUCCESS) { printf("TPM2_NV_UndefineSpace failed 0x%x: %s\n", rc, TPM2_GetRCString(rc)); goto exit; } /* Clear auth buffer */ session[0].auth.size = 0; XMEMSET(session[0].auth.buffer, 0, sizeof(session[0].auth.buffer)); exit: /* Close session */ if (sessionHandle != TPM_RH_NULL) { cmdIn.flushCtx.flushHandle = sessionHandle; TPM2_FlushContext(&cmdIn.flushCtx); } /* Close object handle */ cmdIn.flushCtx.flushHandle = handle; TPM2_FlushContext(&cmdIn.flushCtx); cmdIn.flushCtx.flushHandle = eccKey.handle; TPM2_FlushContext(&cmdIn.flushCtx); cmdIn.flushCtx.flushHandle = hmacKey.handle; TPM2_FlushContext(&cmdIn.flushCtx); cmdIn.flushCtx.flushHandle = rsaKey.handle; TPM2_FlushContext(&cmdIn.flushCtx); /* Cleanup key handles */ cmdIn.flushCtx.flushHandle = endorse.handle; TPM2_FlushContext(&cmdIn.flushCtx); cmdIn.flushCtx.flushHandle = storage.handle; TPM2_FlushContext(&cmdIn.flushCtx); /* Shutdown */ cmdIn.shutdown.shutdownType = TPM_SU_CLEAR; rc = TPM2_Shutdown(&cmdIn.shutdown); if (rc != TPM_RC_SUCCESS) { printf("TPM2_Shutdown failed 0x%x: %s\n", rc, TPM2_GetRCString(rc)); goto exit; } TPM2_Cleanup(&tpm2Ctx); #ifdef TPM2_SPI_DEV /* close handle */ if (gSpiDev >= 0) close(gSpiDev); #endif return rc; } /******************************************************************************/ /* --- BEGIN TPM Native API Tests -- */ /******************************************************************************/ #ifndef NO_MAIN_DRIVER int main(void) { int rc; rc = TPM2_Native_Test(TPM2_IoGetUserCtx()); return rc; } #endif