diff options
Diffstat (limited to 'src/tspi/tspi_aik.c')
-rw-r--r-- | src/tspi/tspi_aik.c | 579 |
1 files changed, 579 insertions, 0 deletions
diff --git a/src/tspi/tspi_aik.c b/src/tspi/tspi_aik.c new file mode 100644 index 0000000..9476341 --- /dev/null +++ b/src/tspi/tspi_aik.c @@ -0,0 +1,579 @@ + +/* + * Licensed Materials - Property of IBM + * + * trousers - An open source TCG Software Stack + * + * (C) Copyright International Business Machines Corp. 2004-2006 + * + */ + +#include <limits.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <inttypes.h> +#include <limits.h> + +#include "trousers/tss.h" +#include "trousers/trousers.h" +#include "trousers_types.h" +#include "spi_utils.h" +#include "capabilities.h" +#include "tsplog.h" +#include "obj.h" +#include "authsess.h" + + +TSS_RESULT +Tspi_TPM_CollateIdentityRequest(TSS_HTPM hTPM, /* in */ + TSS_HKEY hKeySRK, /* in */ + TSS_HKEY hCAPubKey, /* in */ + UINT32 ulIdentityLabelLength, /* in */ + BYTE * rgbIdentityLabelData, /* in */ + TSS_HKEY hIdentityKey, /* in */ + TSS_ALGORITHM_ID algID, /* in */ + UINT32 * pulTcpaIdentityReqLength, /* out */ + BYTE ** prgbTcpaIdentityReq) /* out */ +{ +#ifdef TSS_BUILD_TRANSPORT + UINT32 transport; +#endif + TPM_AUTH srkAuth; + TCPA_RESULT result; + UINT64 offset; + BYTE hashblob[USHRT_MAX], idReqBlob[USHRT_MAX], testblob[USHRT_MAX]; + TCPA_DIGEST digest; + TSS_HPOLICY hSRKPolicy, hIDPolicy, hCAPolicy; + UINT32 caKeyBlobSize, idKeySize, idPubSize; + BYTE *caKeyBlob, *idKey, *newIdKey, *idPub; + TSS_KEY caKey; + TCPA_CHOSENID_HASH chosenIDHash = { { 0, } }; + UINT32 pcIdentityBindingSize; + BYTE *prgbIdentityBinding = NULL; + UINT32 pcEndorsementCredentialSize; + BYTE *prgbEndorsementCredential = NULL; + UINT32 pcPlatformCredentialSize; + BYTE *prgbPlatformCredential = NULL; + UINT32 pcConformanceCredentialSize; + BYTE *prgbConformanceCredential = NULL; +#define CHOSENID_BLOB_SIZE 2048 + BYTE chosenIDBlob[CHOSENID_BLOB_SIZE]; + TSS_HCONTEXT tspContext; + UINT32 encSymKeySize = 256, tmp; + BYTE encSymKey[256], *cb_var; + TSS_BOOL usesAuth; + TPM_AUTH *pSrkAuth = &srkAuth; + TCPA_IDENTITY_REQ rgbTcpaIdentityReq; + TCPA_KEY_PARMS symParms, asymParms; + TCPA_SYMMETRIC_KEY symKey; + int padding; + TSS_CALLBACK *cb; + Trspi_HashCtx hashCtx; + UINT32 tempCredSize; + BYTE *tempCred = NULL; + struct authsess *xsap = NULL; + + if (pulTcpaIdentityReqLength == NULL || prgbTcpaIdentityReq == NULL) + return TSPERR(TSS_E_BAD_PARAMETER); + + if ((result = obj_tpm_get_tsp_context(hTPM, &tspContext))) + return result; + + if ((result = obj_tpm_get_cb12(hTPM, TSS_TSPATTRIB_TPM_CALLBACK_COLLATEIDENTITY, &tmp, + &cb_var))) + return result; + + cb = (TSS_CALLBACK *)cb_var; + if (cb->callback == NULL) { + free_tspi(tspContext, cb); + cb = NULL; + } + + /* Get Policies */ + if ((result = obj_rsakey_get_policy(hKeySRK, TSS_POLICY_USAGE, &hSRKPolicy, &usesAuth))) + return result; + + if ((result = obj_rsakey_get_policy(hCAPubKey, TSS_POLICY_USAGE, + &hCAPolicy, NULL))) + return result; + + if ((result = obj_rsakey_get_policy(hIdentityKey, TSS_POLICY_USAGE, + &hIDPolicy, NULL))) + return result; + + /* setup the symmetric key's parms. */ + memset(&symParms, 0, sizeof(TCPA_KEY_PARMS)); + switch (algID) { + case TSS_ALG_AES: + symParms.algorithmID = TCPA_ALG_AES; + symKey.algId = TCPA_ALG_AES; + symKey.size = 128/8; + break; + case TSS_ALG_DES: + symParms.algorithmID = TCPA_ALG_DES; + symKey.algId = TCPA_ALG_DES; + symKey.size = 64/8; + break; + case TSS_ALG_3DES: + symParms.algorithmID = TCPA_ALG_3DES; + symKey.algId = TCPA_ALG_3DES; + symKey.size = 192/8; + break; + default: + result = TSPERR(TSS_E_BAD_PARAMETER); + goto error; + break; + } + + /* No symmetric key encryption schemes existed in the 1.1 time frame */ + symParms.encScheme = TCPA_ES_NONE; + + /* get the CA Pubkey's encryption scheme */ + if ((result = obj_rsakey_get_es(hCAPubKey, &tmp))) + return TSPERR(TSS_E_BAD_PARAMETER); + + switch (tmp) { + case TSS_ES_RSAESPKCSV15: + padding = TR_RSA_PKCS1_PADDING; + break; + case TSS_ES_RSAESOAEP_SHA1_MGF1: + padding = TR_RSA_PKCS1_OAEP_PADDING; + break; + case TSS_ES_NONE: + /* fall through */ + default: + padding = TR_RSA_NO_PADDING; + break; + } + + /* Get Key blobs */ + if ((result = obj_rsakey_get_blob(hIdentityKey, &idKeySize, &idKey))) + return result; + + if ((result = obj_rsakey_get_blob(hCAPubKey, &caKeyBlobSize, &caKeyBlob))) + return result; + + offset = 0; + memset(&caKey, 0, sizeof(TSS_KEY)); + if ((result = UnloadBlob_TSS_KEY(&offset, caKeyBlob, &caKey))) + return result; + + /* ChosenID hash = SHA1(label || TCPA_PUBKEY(CApub)) */ + offset = 0; + Trspi_LoadBlob(&offset, ulIdentityLabelLength, chosenIDBlob, rgbIdentityLabelData); + Trspi_LoadBlob_KEY_PARMS(&offset, chosenIDBlob, &caKey.algorithmParms); + Trspi_LoadBlob_STORE_PUBKEY(&offset, chosenIDBlob, &caKey.pubKey); + + if (offset > CHOSENID_BLOB_SIZE) + return TSPERR(TSS_E_INTERNAL_ERROR); + + if ((result = Trspi_Hash(TSS_HASH_SHA1, offset, chosenIDBlob, chosenIDHash.digest))) { + free_key_refs(&caKey); + return result; + } + + /* use chosenIDBlob temporarily */ + offset = 0; + Trspi_LoadBlob_KEY_PARMS(&offset, chosenIDBlob, &caKey.algorithmParms); + + offset = 0; + if ((result = Trspi_UnloadBlob_KEY_PARMS(&offset, chosenIDBlob, &asymParms))) + return result; + + if ((result = authsess_xsap_init(tspContext, hTPM, hIdentityKey, TSS_AUTH_POLICY_REQUIRED, + TPM_ORD_MakeIdentity, TPM_ET_OWNER, &xsap))) + return result; + + /* Hash the Auth data */ + result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); + result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_MakeIdentity); + result |= Trspi_Hash_ENCAUTH(&hashCtx, xsap->encAuthUse.authdata); + result |= Trspi_HashUpdate(&hashCtx, TCPA_SHA1_160_HASH_LEN, chosenIDHash.digest); + result |= Trspi_HashUpdate(&hashCtx, idKeySize, idKey); + if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) + goto error; + + /* Do the Auth's */ + if (usesAuth) { + if ((result = secret_PerformAuth_OIAP(hKeySRK, TPM_ORD_MakeIdentity, hSRKPolicy, + FALSE, &digest, &srkAuth))) + goto error; + pSrkAuth = &srkAuth; + } else { + pSrkAuth = NULL; + } + + if ((result = authsess_xsap_hmac(xsap, &digest))) + goto error; + +#ifdef TSS_BUILD_TRANSPORT + if ((result = obj_context_transport_get_control(tspContext, TSS_TSPATTRIB_ENABLE_TRANSPORT, + &transport))) + goto error; + + if (transport) { + if ((result = Transport_MakeIdentity2(tspContext, xsap->encAuthUse, chosenIDHash, + idKeySize, idKey, pSrkAuth, xsap->pAuth, + &idKeySize, &newIdKey, &pcIdentityBindingSize, + &prgbIdentityBinding))) + goto error; + } else { +#endif + if ((result = RPC_MakeIdentity(tspContext, xsap->encAuthUse, chosenIDHash, + idKeySize, idKey, pSrkAuth, xsap->pAuth, &idKeySize, + &newIdKey, &pcIdentityBindingSize, + &prgbIdentityBinding, &pcEndorsementCredentialSize, + &prgbEndorsementCredential, + &pcPlatformCredentialSize, &prgbPlatformCredential, + &pcConformanceCredentialSize, + &prgbConformanceCredential))) + goto error; +#ifdef TSS_BUILD_TRANSPORT + } +#endif + + result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); + result |= Trspi_Hash_UINT32(&hashCtx, result); + result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_MakeIdentity); + result |= Trspi_HashUpdate(&hashCtx, idKeySize, newIdKey); + result |= Trspi_Hash_UINT32(&hashCtx, pcIdentityBindingSize); + result |= Trspi_HashUpdate(&hashCtx, pcIdentityBindingSize, prgbIdentityBinding); + if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) { + free(newIdKey); + goto error; + } + + if ((result = authsess_xsap_verify(xsap, &digest))) { + free(newIdKey); + goto error; + } + + if (usesAuth == TRUE) { + if ((result = obj_policy_validate_auth_oiap(hSRKPolicy, &digest, &srkAuth))) { + free(newIdKey); + goto error; + } + } + + if ((result = obj_rsakey_set_tcpakey(hIdentityKey, idKeySize, newIdKey))) { + free(newIdKey); + goto error; + } + free(newIdKey); + if ((result = obj_rsakey_set_tcs_handle(hIdentityKey, 0))) + goto error; + + if ((result = obj_rsakey_get_pub_blob(hIdentityKey, &idPubSize, &idPub))) + goto error; + + if ((result = obj_tpm_get_cred(hTPM, TSS_TPMATTRIB_EKCERT, &tempCredSize, &tempCred))) + goto error; + + if (tempCred != NULL) { + free(prgbEndorsementCredential); + prgbEndorsementCredential = tempCred; + pcEndorsementCredentialSize = tempCredSize; + } + + if ((result = obj_tpm_get_cred(hTPM, TSS_TPMATTRIB_TPM_CC, &tempCredSize, &tempCred))) + goto error; + + if (tempCred != NULL) { + free(prgbConformanceCredential); + prgbConformanceCredential = tempCred; + pcConformanceCredentialSize = tempCredSize; + } + + if ((result = obj_tpm_get_cred(hTPM, TSS_TPMATTRIB_PLATFORMCERT, &tempCredSize, &tempCred))) + goto error; + + if (tempCred != NULL) { + free(prgbPlatformCredential); + prgbPlatformCredential = tempCred; + pcPlatformCredentialSize = tempCredSize; + } + + /* set up the TCPA_IDENTITY_PROOF structure */ + /* XXX This should be DER encoded first. TPM1.1b section 9.4 */ + /* XXX hash this incrementally using a Trspi_HashCtx */ + offset = 0; + Trspi_LoadBlob_TSS_VERSION(&offset, hashblob, VERSION_1_1); + Trspi_LoadBlob_UINT32(&offset, ulIdentityLabelLength, hashblob); + Trspi_LoadBlob_UINT32(&offset, pcIdentityBindingSize, hashblob); + Trspi_LoadBlob_UINT32(&offset, pcEndorsementCredentialSize, hashblob); + Trspi_LoadBlob_UINT32(&offset, pcPlatformCredentialSize, hashblob); + Trspi_LoadBlob_UINT32(&offset, pcConformanceCredentialSize, hashblob); + Trspi_LoadBlob(&offset, idPubSize, hashblob, idPub); + free_tspi(tspContext, idPub); + Trspi_LoadBlob(&offset, ulIdentityLabelLength, hashblob, rgbIdentityLabelData); + Trspi_LoadBlob(&offset, pcIdentityBindingSize, hashblob, prgbIdentityBinding); + Trspi_LoadBlob(&offset, pcEndorsementCredentialSize, hashblob, prgbEndorsementCredential); + Trspi_LoadBlob(&offset, pcPlatformCredentialSize, hashblob, prgbPlatformCredential); + Trspi_LoadBlob(&offset, pcConformanceCredentialSize, hashblob, prgbConformanceCredential); + + if (cb && cb->callback) { + /* Alloc the space for the callback to copy into. The additional 32 bytes will + * attempt to account for padding that the symmetric encryption will do. */ + rgbTcpaIdentityReq.asymBlob = calloc(1, (int)offset + 32); + rgbTcpaIdentityReq.symBlob = calloc(1, (int)offset + 32); + if (rgbTcpaIdentityReq.asymBlob == NULL || + rgbTcpaIdentityReq.symBlob == NULL) { + free(rgbTcpaIdentityReq.asymBlob); + free(rgbTcpaIdentityReq.symBlob); + LogError("malloc of %" PRIu64 " bytes failed", offset); + free_tspi(tspContext, cb); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto error; + } + rgbTcpaIdentityReq.asymSize = (UINT32)offset + 32; + rgbTcpaIdentityReq.symSize = (UINT32)offset + 32; + + if ((result = ((TSS_RESULT (*)(PVOID, UINT32, BYTE *, UINT32, UINT32 *, BYTE *, + UINT32 *, BYTE *))cb->callback)(cb->appData, (UINT32)offset, + hashblob, algID, + &rgbTcpaIdentityReq.asymSize, + rgbTcpaIdentityReq.asymBlob, + &rgbTcpaIdentityReq.symSize, + rgbTcpaIdentityReq.symBlob))) { + LogDebug("CollateIdentityRequest callback returned error 0x%x", result); + free_tspi(tspContext, cb); + goto error; + } + } else { + /* generate the symmetric key. */ + if ((result = get_local_random(tspContext, TRUE, symKey.size, &symKey.data))) + goto error; + + /* No symmetric key encryption schemes existed in the 1.1 time frame */ + symKey.encScheme = TCPA_ES_NONE; + + /* encrypt the proof */ + rgbTcpaIdentityReq.symSize = sizeof(testblob); + if ((result = Trspi_SymEncrypt(algID, TR_SYM_MODE_CBC, symKey.data, NULL, hashblob, + offset, testblob, &rgbTcpaIdentityReq.symSize))) + goto error; + + rgbTcpaIdentityReq.symBlob = testblob; + + /* XXX This should be DER encoded first. TPM1.1b section 9.4 */ + offset = 0; + Trspi_LoadBlob_SYMMETRIC_KEY(&offset, hashblob, &symKey); + + if ((result = Trspi_RSA_Public_Encrypt(hashblob, offset, encSymKey, &encSymKeySize, + caKey.pubKey.key, caKey.pubKey.keyLength, + 65537, padding))) + goto error; + + rgbTcpaIdentityReq.asymSize = encSymKeySize; + rgbTcpaIdentityReq.asymBlob = encSymKey; + } + + rgbTcpaIdentityReq.asymAlgorithm = asymParms; + rgbTcpaIdentityReq.symAlgorithm = symParms; + + /* XXX This should be DER encoded first. TPM1.1b section 9.4 */ + offset = 0; + Trspi_LoadBlob_IDENTITY_REQ(&offset, idReqBlob, &rgbTcpaIdentityReq); + + if (cb && cb->callback) { + free(rgbTcpaIdentityReq.symBlob); + free(rgbTcpaIdentityReq.asymBlob); + free_tspi(tspContext, cb); + } + + if ((*prgbTcpaIdentityReq = calloc_tspi(tspContext, offset)) == NULL) { + result = TSPERR(TSS_E_OUTOFMEMORY); + goto error; + } + + memcpy(*prgbTcpaIdentityReq, idReqBlob, offset); + *pulTcpaIdentityReqLength = offset; +error: + authsess_free(xsap); + free_key_refs(&caKey); + free(prgbIdentityBinding); + free(prgbEndorsementCredential); + free(prgbPlatformCredential); + free(prgbConformanceCredential); + + return result; +} + +TSS_RESULT +Tspi_TPM_ActivateIdentity(TSS_HTPM hTPM, /* in */ + TSS_HKEY hIdentKey, /* in */ + UINT32 ulAsymCAContentsBlobLength, /* in */ + BYTE * rgbAsymCAContentsBlob, /* in */ + UINT32 ulSymCAAttestationBlobLength, /* in */ + BYTE * rgbSymCAAttestationBlob, /* in */ + UINT32 * pulCredentialLength, /* out */ + BYTE ** prgbCredential) /* out */ +{ + TPM_AUTH idKeyAuth; + TPM_AUTH ownerAuth; + TSS_HCONTEXT tspContext; + TSS_HPOLICY hIDPolicy, hTPMPolicy; + UINT64 offset; + BYTE credBlob[0x1000]; + TCPA_DIGEST digest; + TSS_RESULT result; + TCS_KEY_HANDLE tcsKeyHandle; + TSS_BOOL usesAuth; + TPM_AUTH *pIDKeyAuth; + BYTE *symKeyBlob, *credCallback, *cb_var; + UINT32 symKeyBlobLen, credLen, tmp; + TCPA_SYMMETRIC_KEY symKey; + TSS_CALLBACK *cb; + Trspi_HashCtx hashCtx; + TPM_SYM_CA_ATTESTATION symCAAttestation; + + if (pulCredentialLength == NULL || prgbCredential == NULL) + return TSPERR(TSS_E_BAD_PARAMETER); + + if ((result = obj_tpm_get_tsp_context(hTPM, &tspContext))) + return result; + + if ((result = obj_tpm_get_cb12(hTPM, TSS_TSPATTRIB_TPM_CALLBACK_ACTIVATEIDENTITY, &tmp, + &cb_var))) + return result; + + cb = (TSS_CALLBACK *)cb_var; + if (cb->callback == NULL) { + free_tspi(tspContext, cb); + cb = NULL; + } + + if ((result = obj_rsakey_get_tcs_handle(hIdentKey, &tcsKeyHandle))) + return result; + + if ((result = obj_rsakey_get_policy(hIdentKey, TSS_POLICY_USAGE, + &hIDPolicy, &usesAuth))) + return result; + + if ((result = obj_tpm_get_policy(hTPM, TSS_POLICY_USAGE, &hTPMPolicy))) + return result; + + result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); + result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_ActivateIdentity); + result |= Trspi_Hash_UINT32(&hashCtx, ulAsymCAContentsBlobLength); + result |= Trspi_HashUpdate(&hashCtx, ulAsymCAContentsBlobLength, rgbAsymCAContentsBlob); + if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) + return result; + + if (usesAuth) { + if ((result = secret_PerformAuth_OIAP(hIDPolicy, TPM_ORD_ActivateIdentity, + hIDPolicy, FALSE, &digest, &idKeyAuth))) + return result; + pIDKeyAuth = &idKeyAuth; + } else { + pIDKeyAuth = NULL; + } + + if ((result = secret_PerformAuth_OIAP(hTPM, TPM_ORD_ActivateIdentity, hTPMPolicy, FALSE, + &digest, &ownerAuth))) + return result; + + if ((result = TCS_API(tspContext)->ActivateTPMIdentity(tspContext, tcsKeyHandle, + ulAsymCAContentsBlobLength, + rgbAsymCAContentsBlob, pIDKeyAuth, + &ownerAuth, &symKeyBlobLen, + &symKeyBlob))) + return result; + + result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); + result |= Trspi_Hash_UINT32(&hashCtx, result); + result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_ActivateIdentity); + result |= Trspi_HashUpdate(&hashCtx, symKeyBlobLen, symKeyBlob); + if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) + return result; + + if (usesAuth) { + if ((result = obj_policy_validate_auth_oiap(hIDPolicy, &digest, + &idKeyAuth))) { + LogDebugFn("Identity key auth validation of the symmetric key failed."); + return result; + } + } + + if ((result = obj_policy_validate_auth_oiap(hTPMPolicy, &digest, + &ownerAuth))) { + LogDebugFn("Owner auth validation of the symmetric key failed."); + return result; + } + + offset = 0; + if ((result = Trspi_UnloadBlob_SYM_CA_ATTESTATION(&offset, rgbSymCAAttestationBlob, + &symCAAttestation))) { + LogDebugFn("Error unloading CA's attestation blob."); + return result; + } + + if (cb && cb->callback) { + /* alloc the space for the callback to copy into */ + credCallback = calloc(1, ulSymCAAttestationBlobLength); + if (credCallback == NULL) { + LogDebug("malloc of %u bytes failed", ulSymCAAttestationBlobLength); + free(symKeyBlob); + free_tspi(tspContext, cb); + return TSPERR(TSS_E_INTERNAL_ERROR); + } + credLen = ulSymCAAttestationBlobLength; + + if ((result = ((TSS_RESULT (*)(PVOID, UINT32, BYTE *, UINT32, BYTE *, UINT32 *, + BYTE *))cb->callback)(cb->appData, symKeyBlobLen, symKeyBlob, + symCAAttestation.credSize, + symCAAttestation.credential, + &credLen, credCallback))) { + LogDebug("ActivateIdentity callback returned error 0x%x", result); + free(symCAAttestation.credential); + free(symKeyBlob); + free_tspi(tspContext, cb); + free(credCallback); + return TSPERR(TSS_E_INTERNAL_ERROR); + } + free(symCAAttestation.credential); + free_tspi(tspContext, cb); + free(symKeyBlob); + + if ((*prgbCredential = calloc_tspi(tspContext, credLen)) == NULL) { + free(credCallback); + return TSPERR(TSS_E_OUTOFMEMORY); + } + + memcpy(*prgbCredential, credCallback, credLen); + *pulCredentialLength = credLen; + free(credCallback); + + return TSS_SUCCESS; + } + + /* decrypt the symmetric blob using the recovered symmetric key */ + offset = 0; + if ((result = Trspi_UnloadBlob_SYMMETRIC_KEY(&offset, symKeyBlob, &symKey))) { + free(symCAAttestation.credential); + free(symKeyBlob); + return result; + } + free(symKeyBlob); + + if ((result = Trspi_SymDecrypt(symKey.algId, symKey.encScheme, symKey.data, NULL, + symCAAttestation.credential, symCAAttestation.credSize, + credBlob, &credLen))) { + free(symCAAttestation.credential); + free(symKey.data); + return result; + } + free(symCAAttestation.credential); + + if ((*prgbCredential = calloc_tspi(tspContext, credLen)) == NULL) { + free(symKey.data); + return TSPERR(TSS_E_OUTOFMEMORY); + } + + free(symKey.data); + memcpy(*prgbCredential, credBlob, credLen); + *pulCredentialLength = credLen; + + return TSS_SUCCESS; +} |