From 93a2493dbf623e39a833fb745f3f3af76a3d8dc3 Mon Sep 17 00:00:00 2001 From: David Garske Date: Fri, 29 Dec 2023 09:27:21 -0800 Subject: [PATCH] Fixes for attestation with endorsement key. Enable the broken endorsement tests. --- README.md | 5 +- examples/attestation/activate_credential.c | 47 +++++++++------ examples/attestation/make_credential.c | 70 ++++++++++------------ examples/keygen/keygen.c | 35 ++++++++--- examples/run_examples.sh | 56 +++++++++++++---- src/tpm2_packet.c | 6 ++ src/tpm2_wrap.c | 23 ++++--- wolftpm/tpm2.h | 2 +- 8 files changed, 158 insertions(+), 86 deletions(-) diff --git a/README.md b/README.md index 34902e5..3fbaaed 100644 --- a/README.md +++ b/README.md @@ -791,9 +791,10 @@ Connection: close ## Todo -* Key Generation and Attestation examples using endorsement hierarchy "-eh" are broken. -* Update to v1.59 of specification (adding CertifyX509) +* Add support for Endorsement certificates (EK Credential Profile). +* Update to v1.59 of specification (adding CertifyX509). * Inner wrap support for SensitiveToPrivate. +* Firmware upgrade support on TPM's. ## Support diff --git a/examples/attestation/activate_credential.c b/examples/attestation/activate_credential.c index 2752255..93b2bc4 100644 --- a/examples/attestation/activate_credential.c +++ b/examples/attestation/activate_credential.c @@ -44,6 +44,7 @@ static void usage(void) printf("Expected usage:\n"); printf("./examples/attestation/activate_credential [cred.blob] [-eh]\n"); printf("* cred.blob is a input file holding the generated credential.\n"); + printf("* -eh: Use the EK public key to encrypt the challenge\n"); printf("Demo usage without parameters, uses \"cred.blob\" filename.\n"); } @@ -64,14 +65,8 @@ int TPM2_ActivateCredential_Example(void* userCtx, int argc, char *argv[]) const char *input = "cred.blob"; const char *keyblob = "keyblob.bin"; - union { - ActivateCredential_In activCred; - byte maxInput[MAX_COMMAND_SIZE]; - } cmdIn; - union { - ActivateCredential_Out activCred; - byte maxOutput[MAX_RESPONSE_SIZE]; - } cmdOut; + ActivateCredential_In activCredIn; + ActivateCredential_Out activCredOut; if (argc == 1) { printf("Using default values\n"); @@ -157,9 +152,13 @@ int TPM2_ActivateCredential_Example(void* userCtx, int argc, char *argv[]) /* Set the created Policy Session for use in next operation */ rc = wolfTPM2_SetAuthSession(&dev, 1, &tpmSession, 0); if (rc != 0) goto exit; + /* Set the name for the endorsement handle */ + rc = wolfTPM2_SetAuthHandleName(&dev, 1, &endorse.handle); + if (rc != 0) goto exit; } else { - wolfTPM2_SetAuthHandle(&dev, 1, &storage.handle); + rc = wolfTPM2_SetAuthHandle(&dev, 1, &storage.handle); + if (rc != 0) goto exit; } /* Prepare the auth password for the Attestation Key */ @@ -169,19 +168,19 @@ int TPM2_ActivateCredential_Example(void* userCtx, int argc, char *argv[]) wolfTPM2_SetAuthHandle(&dev, 0, &akKey.handle); /* Prepare the Activate Credential command */ - XMEMSET(&cmdIn.activCred, 0, sizeof(cmdIn.activCred)); - XMEMSET(&cmdOut.activCred, 0, sizeof(cmdOut.activCred)); - cmdIn.activCred.activateHandle = akKey.handle.hndl; - cmdIn.activCred.keyHandle = primary->handle.hndl; + XMEMSET(&activCredIn, 0, sizeof(activCredIn)); + XMEMSET(&activCredOut, 0, sizeof(activCredOut)); + activCredIn.activateHandle = akKey.handle.hndl; + activCredIn.keyHandle = primary->handle.hndl; /* Read credential from the user file */ #if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES) fp = XFOPEN(input, "rb"); if (fp != XBADFILE) { - dataSize = (int)XFREAD((BYTE*)&cmdIn.activCred.credentialBlob, 1, - sizeof(cmdIn.activCred.credentialBlob), fp); + dataSize = (int)XFREAD((BYTE*)&activCredIn.credentialBlob, 1, + sizeof(activCredIn.credentialBlob), fp); if (dataSize > 0) { - dataSize += (int)XFREAD((BYTE*)&cmdIn.activCred.secret, 1, - sizeof(cmdIn.activCred.secret), fp); + dataSize += (int)XFREAD((BYTE*)&activCredIn.secret, 1, + sizeof(activCredIn.secret), fp); } XFCLOSE(fp); } @@ -192,18 +191,28 @@ int TPM2_ActivateCredential_Example(void* userCtx, int argc, char *argv[]) goto exit; #endif /* All required data to verify the credential is prepared */ - rc = TPM2_ActivateCredential(&cmdIn.activCred, &cmdOut.activCred); + rc = TPM2_ActivateCredential(&activCredIn, &activCredOut); if (rc != TPM_RC_SUCCESS) { - printf("TPM2_ActivateCredentials failed 0x%x: %s\n", rc, + printf("TPM2_ActivateCredential failed 0x%x: %s\n", rc, TPM2_GetRCString(rc)); goto exit; } printf("TPM2_ActivateCredential success\n"); + if (endorseKey) { + /* The policy session is closed after use. + * Reset handle, so we don't try and free it */ + tpmSession.handle.hndl = TPM_RH_NULL; + } + + printf("Secret: %d\n", activCredOut.certInfo.size); + TPM2_PrintBin(activCredOut.certInfo.buffer, + activCredOut.certInfo.size); exit: wolfTPM2_UnloadHandle(&dev, &primary->handle); wolfTPM2_UnloadHandle(&dev, &akKey.handle); + wolfTPM2_UnloadHandle(&dev, &tpmSession.handle); wolfTPM2_Cleanup(&dev); exit_badargs: diff --git a/examples/attestation/make_credential.c b/examples/attestation/make_credential.c index 8ebe922..b2b85f6 100644 --- a/examples/attestation/make_credential.c +++ b/examples/attestation/make_credential.c @@ -68,16 +68,10 @@ int TPM2_MakeCredential_Example(void* userCtx, int argc, char *argv[]) const char *srkPubFile = "srk.pub"; const char *pubFilename = NULL; - union { - MakeCredential_In makeCred; - LoadExternal_In loadExtIn; - byte maxInput[MAX_COMMAND_SIZE]; - } cmdIn; - union { - MakeCredential_Out makeCred; - LoadExternal_Out loadExtOut; - byte maxOutput[MAX_RESPONSE_SIZE]; - } cmdOut; + MakeCredential_In makeCredIn; + MakeCredential_Out makeCredOut; + LoadExternal_In loadExtIn; + LoadExternal_Out loadExtOut; if (argc == 1) { printf("Using public key from SRK to create the challenge\n"); @@ -100,12 +94,6 @@ int TPM2_MakeCredential_Example(void* userCtx, int argc, char *argv[]) goto exit_badargs; } - XMEMSET(&name, 0, sizeof(name)); - XMEMSET(&cmdIn.makeCred, 0, sizeof(cmdIn.makeCred)); - XMEMSET(&cmdOut.makeCred, 0, sizeof(cmdOut.makeCred)); - XMEMSET(&cmdIn.loadExtIn, 0, sizeof(cmdIn.loadExtIn)); - XMEMSET(&cmdOut.loadExtOut, 0, sizeof(cmdOut.loadExtOut)); - printf("Demo how to create a credential challenge for remote attestation\n"); printf("Credential will be stored in %s\n", output); @@ -125,24 +113,26 @@ int TPM2_MakeCredential_Example(void* userCtx, int argc, char *argv[]) } rc = readKeyBlob(pubFilename, &primary); if (rc != 0) { - printf("Failure to load %s\n", pubFilename); + printf("Failure to read %s\n", pubFilename); goto exit; } + /* Prepare the key for use by the TPM */ - XMEMCPY(&cmdIn.loadExtIn.inPublic, &primary.pub, - sizeof(cmdIn.loadExtIn.inPublic)); - cmdIn.loadExtIn.hierarchy = TPM_RH_NULL; - rc = TPM2_LoadExternal(&cmdIn.loadExtIn, &cmdOut.loadExtOut); + XMEMSET(&loadExtIn, 0, sizeof(loadExtIn)); + XMEMSET(&loadExtOut, 0, sizeof(loadExtOut)); + XMEMCPY(&loadExtIn.inPublic, &primary.pub, sizeof(loadExtIn.inPublic)); + loadExtIn.hierarchy = TPM_RH_NULL; + rc = TPM2_LoadExternal(&loadExtIn, &loadExtOut); if (rc != TPM_RC_SUCCESS) { printf("TPM2_LoadExternal: failed %d: %s\n", rc, wolfTPM2_GetRCString(rc)); return rc; } printf("Public key for encryption loaded\n"); - handle.hndl = cmdOut.loadExtOut.objectHandle; - + handle.hndl = loadExtOut.objectHandle; #if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES) /* Load AK Name digest */ + XMEMSET(&name, 0, sizeof(name)); fp = XFOPEN("ak.name", "rb"); if (fp != XBADFILE) { size_t nameReadSz = XFREAD((BYTE*)&name, 1, sizeof(name), fp); @@ -153,31 +143,37 @@ int TPM2_MakeCredential_Example(void* userCtx, int argc, char *argv[]) #endif /* Create secret for the attestation server */ - cmdIn.makeCred.credential.size = CRED_SECRET_SIZE; - wolfTPM2_GetRandom(&dev, cmdIn.makeCred.credential.buffer, - cmdIn.makeCred.credential.size); - /* Prepare the AK name */ - cmdIn.makeCred.objectName.size = name.size; - XMEMCPY(cmdIn.makeCred.objectName.name, name.name, - cmdIn.makeCred.objectName.size); + XMEMSET(&makeCredIn, 0, sizeof(makeCredIn)); + XMEMSET(&makeCredOut, 0, sizeof(makeCredOut)); + makeCredIn.credential.size = CRED_SECRET_SIZE; + wolfTPM2_GetRandom(&dev, makeCredIn.credential.buffer, + makeCredIn.credential.size); + /* Set the object name */ + makeCredIn.objectName.size = name.size; + XMEMCPY(makeCredIn.objectName.name, name.name, + makeCredIn.objectName.size); /* Set TPM key and execute */ - cmdIn.makeCred.handle = handle.hndl; - rc = TPM2_MakeCredential(&cmdIn.makeCred, &cmdOut.makeCred); + makeCredIn.handle = handle.hndl; + rc = TPM2_MakeCredential(&makeCredIn, &makeCredOut); if (rc != TPM_RC_SUCCESS) { - printf("TPM2_MakeCredentials failed 0x%x: %s\n", rc, + printf("TPM2_MakeCredential failed 0x%x: %s\n", rc, TPM2_GetRCString(rc)); goto exit; } printf("TPM2_MakeCredential success\n"); + printf("Secret: %d\n", makeCredIn.credential.size); + TPM2_PrintBin(makeCredIn.credential.buffer, + makeCredIn.credential.size); + #if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES) fp = XFOPEN(output, "wb"); if (fp != XBADFILE) { - dataSize = (int)XFWRITE((BYTE*)&cmdOut.makeCred.credentialBlob, 1, - sizeof(cmdOut.makeCred.credentialBlob), fp); + dataSize = (int)XFWRITE((BYTE*)&makeCredOut.credentialBlob, 1, + sizeof(makeCredOut.credentialBlob), fp); if (dataSize > 0) { - dataSize += (int)XFWRITE((BYTE*)&cmdOut.makeCred.secret, 1, - sizeof(cmdOut.makeCred.secret), fp); + dataSize += (int)XFWRITE((BYTE*)&makeCredOut.secret, 1, + sizeof(makeCredOut.secret), fp); } XFCLOSE(fp); } diff --git a/examples/keygen/keygen.c b/examples/keygen/keygen.c index cce27fb..7a7b6f5 100644 --- a/examples/keygen/keygen.c +++ b/examples/keygen/keygen.c @@ -141,7 +141,6 @@ int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[]) #if !defined(WOLFTPM2_NO_WOLFCRYPT) && !defined(NO_RSA) const char *pemFilename = NULL; #endif - FILE *fp; #endif size_t len = 0; char symMode[] = "aesctr"; @@ -251,20 +250,26 @@ int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[]) rc = wolfTPM2_StartSession(&dev, &tpmSession, primary, NULL, TPM_SE_HMAC, paramEncAlg); if (rc != 0) goto exit; - printf("TPM2_StartAuthSession: sessionHandle 0x%x\n", + printf("HMAC Session: Handle 0x%x\n", (word32)tpmSession.handle.hndl); /* set session for authorization of the primary key */ rc = wolfTPM2_SetAuthSession(&dev, 1, &tpmSession, - (TPMA_SESSION_decrypt | TPMA_SESSION_encrypt | TPMA_SESSION_continueSession)); + (TPMA_SESSION_decrypt | TPMA_SESSION_encrypt | + TPMA_SESSION_continueSession)); if (rc != 0) goto exit; } if (endorseKey) { /* Endorsement Key requires authorization with Policy */ - wolfTPM2_CreateAuthSession_EkPolicy(&dev, &tpmSession); + rc = wolfTPM2_CreateAuthSession_EkPolicy(&dev, &tpmSession); + if (rc != 0) goto exit; + printf("EK Policy Session: Handle 0x%x\n", + (word32)tpmSession.handle.hndl); + /* Set the created Policy Session for use in next operation */ - wolfTPM2_SetAuthSession(&dev, 0, &tpmSession, 0); + rc = wolfTPM2_SetAuthSession(&dev, 0, &tpmSession, 0); + if (rc != 0) goto exit; } /* Create new key */ @@ -285,6 +290,7 @@ int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[]) else { rc = BAD_FUNC_ARG; } + if (rc != 0) goto exit; /* set session for authorization key */ auth.size = (int)sizeof(gAiKeyAuth)-1; @@ -341,11 +347,25 @@ int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[]) printf("wolfTPM2_CreateKey failed\n"); goto exit; } + if (endorseKey) { + /* Endorsement policy session is closed after use, so start another */ + rc = wolfTPM2_CreateAuthSession_EkPolicy(&dev, &tpmSession); + if (rc == 0) { + rc = wolfTPM2_SetAuthSession(&dev, 0, &tpmSession, 0); + } + if (rc != 0) goto exit; + } rc = wolfTPM2_LoadKey(&dev, &newKeyBlob, &primary->handle); if (rc != TPM_RC_SUCCESS) { printf("wolfTPM2_LoadKey failed\n"); goto exit; } + if (endorseKey) { + /* The policy session is closed after use. + * Reset handle, so we don't try and free it */ + tpmSession.handle.hndl = TPM_RH_NULL; + } + printf("New key created and loaded (pub %d, priv %d bytes)\n", newKeyBlob.pub.size, newKeyBlob.priv.size); @@ -420,10 +440,7 @@ exit: /* Close handles */ wolfTPM2_UnloadHandle(&dev, &primary->handle); wolfTPM2_UnloadHandle(&dev, &newKeyBlob.handle); - /* EK policy is destroyed after use, flush parameter encryption session */ - if (paramEncAlg != TPM_ALG_NULL && !endorseKey) { - wolfTPM2_UnloadHandle(&dev, &tpmSession.handle); - } + wolfTPM2_UnloadHandle(&dev, &tpmSession.handle); wolfTPM2_Cleanup(&dev); return rc; diff --git a/examples/run_examples.sh b/examples/run_examples.sh index 693c40b..e6e3756 100755 --- a/examples/run_examples.sh +++ b/examples/run_examples.sh @@ -99,9 +99,22 @@ RESULT=$? rm -f keyedhashblob.bin [ $RESULT -ne 0 ] && echo -e "keygen keyed hash load failed! $RESULT" && exit 1 -# KeyGen Endorsement with Policy Secret -# TODO Fix: (TPM2_Create TPM_RC_AUTH_UNAVAILABLE) -#./examples/keygen/keygen rsakeyblobeh.bin -rsa -eh >> run.out +if [ $WOLFCRYPT_ENABLE -eq 1 ]; then + # KeyGen under Endorsement + ./examples/keygen/keygen rsakeyblobeh.bin -rsa -eh >> run.out + RESULT=$? + [ $RESULT -ne 0 ] && echo -e "keygen endorsement rsa failed! $RESULT" && exit 1 + ./examples/keygen/keyload rsakeyblobeh.bin -rsa -eh >> run.out + RESULT=$? + [ $RESULT -ne 0 ] && echo -e "keyload endorsement rsa failed! $RESULT" && exit 1 + + ./examples/keygen/keygen ecckeyblobeh.bin -ecc -eh >> run.out + RESULT=$? + [ $RESULT -ne 0 ] && echo -e "keygen endorsement rsa failed! $RESULT" && exit 1 + ./examples/keygen/keyload ecckeyblobeh.bin -ecc -eh >> run.out + RESULT=$? + [ $RESULT -ne 0 ] && echo -e "keygen endorsement rsa failed! $RESULT" && exit 1 +fi # NV Tests @@ -190,12 +203,14 @@ run_tpm_tls_client() { # Usage: run_tpm_tls_client [ecc/rsa] [tpmargs]] echo -e "TLS test (TPM as client) $1 $2" generate_port pushd $WOLFSSL_PATH >> run.out + echo -e "./examples/server/server -p $port -w -g -A ./certs/tpm-ca-$1-cert.pem" ./examples/server/server -p $port -w -g -A ./certs/tpm-ca-$1-cert.pem 2>&1 >> $PWD/run.out & RESULT=$? [ $RESULT -ne 0 ] && echo -e "tls server $1 $2 failed! $RESULT" && exit 1 popd >> run.out sleep 0.1 + echo -e "./examples/tls/tls_client -p=$port -$1 $2" ./examples/tls/tls_client -p=$port -$1 $2 2>&1 >> run.out RESULT=$? [ $RESULT -ne 0 ] && echo -e "tpm tls client $1 $2 failed! $RESULT" && exit 1 @@ -268,15 +283,33 @@ if [ $WOLFCRYPT_ENABLE -eq 1 ]; then [ $RESULT -ne 0 ] && echo -e "signed_timestamp ecc param enc failed! $RESULT" && exit 1 fi -./examples/attestation/make_credential >> run.out -RESULT=$? -[ $RESULT -ne 0 ] && echo -e "make_credential failed! $RESULT" && exit 1 -# TODO: Requires keygen -ek to be working -#./examples/attestation/make_credential -eh >> run.out -# TODO: Test broken (TPM2_ActivateCredentials TPM_RC_INTEGRITY) -#./examples/attestation/activate_credential >> run.out -#./examples/attestation/activate_credential -eh >> run.out +if [ $WOLFCRYPT_ENABLE -eq 1 ]; then + ./examples/keygen/keygen keyblob.bin -rsa >> run.out + RESULT=$? + [ $RESULT -ne 0 ] && echo -e "keygen rsa failed! $RESULT" && exit 1 + ./examples/attestation/make_credential >> run.out + RESULT=$? + [ $RESULT -ne 0 ] && echo -e "make_credential failed! $RESULT" && exit 1 + ./examples/attestation/activate_credential >> run.out + RESULT=$? + [ $RESULT -ne 0 ] && echo -e "activate_credential failed! $RESULT" && exit 1 + # Endorsement hierarchy + ./examples/keygen/keygen keyblob.bin -rsa -eh >> run.out + RESULT=$? + [ $RESULT -ne 0 ] && echo -e "keygen rsa endorsement failed! $RESULT" && exit 1 + ./examples/attestation/make_credential -eh >> run.out + RESULT=$? + [ $RESULT -ne 0 ] && echo -e "make_credential endorsement failed! $RESULT" && exit 1 + ./examples/attestation/activate_credential -eh >> run.out + RESULT=$? + [ $RESULT -ne 0 ] && echo -e "activate_credential endorsement failed! $RESULT" && exit 1 + + rm -f cred.blob + rm -f ek.pub + rm -f srk.pub + rm -f ak.name +fi # PCR Quote Tests echo -e "PCR Quote tests" @@ -457,6 +490,7 @@ if [ $WOLFCRYPT_ENABLE -eq 1 ]; then rm -f aaa.bin fi +rm -f keyblob.bin echo -e "Success!" exit 0 diff --git a/src/tpm2_packet.c b/src/tpm2_packet.c index 39eb74d..ac2a8cc 100644 --- a/src/tpm2_packet.c +++ b/src/tpm2_packet.c @@ -330,6 +330,12 @@ int TPM2_GetCmdAuthCount(TPM2_CTX* ctx, const CmdInfo_t* info) (sessionAttributes & TPMA_SESSION_audit)) authSessCount++; } + + /* Allow policy auth */ + else if (authReq && TPM2_IS_POLICY_SESSION(sessionHandle) && + sessionAttributes == 0) { + authSessCount++; + } else if (!authReq) { /* we cannot accept further authentications */ break; diff --git a/src/tpm2_wrap.c b/src/tpm2_wrap.c index c4e2ef5..d2257dd 100644 --- a/src/tpm2_wrap.c +++ b/src/tpm2_wrap.c @@ -822,11 +822,18 @@ int wolfTPM2_SetAuthHandle(WOLFTPM2_DEV* dev, int index, { const TPM2B_AUTH* auth = NULL; const TPM2B_NAME* name = NULL; - /* don't set auth for policy session */ - if (dev->ctx.session == NULL || handle->policyAuth) { - return 0; + if (dev == NULL || index >= MAX_SESSION_NUM) { + return BAD_FUNC_ARG; } + if (handle) { + /* don't set auth for policy session, just name */ + if (handle->policyAuth) { + TPM2_AUTH_SESSION* session = &dev->session[index]; + session->name.size = handle->name.size; + XMEMCPY(session->name.name, handle->name.name, handle->name.size); + return TPM_RC_SUCCESS; + } auth = &handle->auth; name = &handle->name; } @@ -892,12 +899,14 @@ int wolfTPM2_SetAuthSession(WOLFTPM2_DEV* dev, int index, XMEMCPY(session->nonceTPM.buffer, tpmSession->nonceTPM.buffer, session->nonceTPM.size); - /* Parameter Encryption session will have an hmac added later. + /* Parameter Encryption or Policy session will have an HMAC added later. * Reserve space, the same way it was done for nonceCaller above. */ - if (session->sessionHandle != TPM_RS_PW && - ((session->sessionAttributes & TPMA_SESSION_encrypt) || - (session->sessionAttributes & TPMA_SESSION_decrypt))) { + if ((session->sessionHandle != TPM_RS_PW && + ((session->sessionAttributes & TPMA_SESSION_encrypt) || + (session->sessionAttributes & TPMA_SESSION_decrypt))) + || TPM2_IS_POLICY_SESSION(session->sessionHandle)) + { session->auth.size = TPM2_GetHashDigestSize(session->authHash); } } diff --git a/wolftpm/tpm2.h b/wolftpm/tpm2.h index d386c6a..63288ae 100644 --- a/wolftpm/tpm2.h +++ b/wolftpm/tpm2.h @@ -1640,7 +1640,7 @@ typedef struct TPM2_AUTH_SESSION { #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) -/* Predetermined TPM 2.0 Endorsement policy auth template */ +/* Predetermined TPM 2.0 Endorsement policy auth template for SHA2-256 */ static 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,