diff options
Diffstat (limited to 'src/tspi/tspi_seal.c')
-rw-r--r-- | src/tspi/tspi_seal.c | 327 |
1 files changed, 327 insertions, 0 deletions
diff --git a/src/tspi/tspi_seal.c b/src/tspi/tspi_seal.c new file mode 100644 index 0000000..95250c6 --- /dev/null +++ b/src/tspi/tspi_seal.c @@ -0,0 +1,327 @@ + +/* + * Licensed Materials - Property of IBM + * + * trousers - An open source TCG Software Stack + * + * (C) Copyright International Business Machines Corp. 2004-2007 + * + */ + + +#include <stdlib.h> +#include <stdio.h> +#include <string.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_Data_Seal(TSS_HENCDATA hEncData, /* in */ + TSS_HKEY hEncKey, /* in */ + UINT32 ulDataLength, /* in */ + BYTE * rgbDataToSeal, /* in */ + TSS_HPCRS hPcrComposite) /* in */ +{ + TPM_DIGEST digest; + TSS_RESULT result; + TSS_HPOLICY hPolicy, hEncPolicy; + BYTE *encData = NULL; + BYTE *pcrData = NULL; + UINT32 encDataSize; + UINT32 pcrDataSize; + UINT32 pcrInfoType = TSS_PCRS_STRUCT_DEFAULT; + UINT32 sealOrdinal = TPM_ORD_Seal; + TCS_KEY_HANDLE tcsKeyHandle; + TSS_HCONTEXT tspContext; + Trspi_HashCtx hashCtx; + BYTE *sealData = NULL; + struct authsess *xsap = NULL; +#ifdef TSS_BUILD_SEALX + UINT32 protectMode; +#endif + + if (rgbDataToSeal == NULL) + return TSPERR(TSS_E_BAD_PARAMETER); + + if ((result = obj_encdata_get_tsp_context(hEncData, &tspContext))) + return result; + + if ((result = obj_rsakey_get_policy(hEncKey, TSS_POLICY_USAGE, + &hPolicy, NULL))) + return result; + + if ((result = obj_encdata_get_policy(hEncData, TSS_POLICY_USAGE, + &hEncPolicy))) + return result; + + if ((result = obj_rsakey_get_tcs_handle(hEncKey, &tcsKeyHandle))) + return result; + +#ifdef TSS_BUILD_SEALX + /* Get the TSS_TSPATTRIB_ENCDATASEAL_PROTECT_MODE attribute + to determine the seal function to invoke */ + if ((result = obj_encdata_get_seal_protect_mode(hEncData, &protectMode))) + return result; + + if (protectMode == TSS_TSPATTRIB_ENCDATASEAL_NO_PROTECT) { + sealOrdinal = TPM_ORD_Seal; + pcrInfoType = 0; + } else if (protectMode == TSS_TSPATTRIB_ENCDATASEAL_PROTECT) { + sealOrdinal = TPM_ORD_Sealx; + pcrInfoType = TSS_PCRS_STRUCT_INFO_LONG; + } else + return TSPERR(TSS_E_INTERNAL_ERROR); +#endif + + /* If PCR's are of interest */ + pcrDataSize = 0; + if (hPcrComposite) { + if ((result = obj_pcrs_create_info_type(hPcrComposite, &pcrInfoType, &pcrDataSize, + &pcrData))) + return result; + } + + if ((result = authsess_xsap_init(tspContext, hEncKey, hEncData, TSS_AUTH_POLICY_REQUIRED, + sealOrdinal, TPM_ET_KEYHANDLE, &xsap))) + goto error; + +#ifdef TSS_BUILD_SEALX + if (sealOrdinal == TPM_ORD_Seal) + sealData = rgbDataToSeal; + else { + if ((sealData = (BYTE *)calloc(1, ulDataLength)) == NULL) { + LogError("malloc of %u bytes failed", ulDataLength); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto error; + } + + if ((result = + ((TSS_RESULT (*)(PVOID, TSS_HKEY, TSS_HENCDATA, TSS_ALGORITHM_ID, + UINT32, BYTE *, BYTE *, BYTE *, BYTE *, UINT32, BYTE *, + BYTE *))xsap->cb_sealx.callback)(xsap->cb_sealx.appData, hEncKey, hEncData, + xsap->cb_sealx.alg, sizeof(TPM_NONCE), + xsap->auth.NonceEven.nonce, + xsap->auth.NonceOdd.nonce, + xsap->nonceEvenxSAP.nonce, + xsap->nonceOddxSAP.nonce, ulDataLength, + rgbDataToSeal, sealData))) + goto error; + } +#else + sealData = rgbDataToSeal; +#endif + + result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); + result |= Trspi_Hash_UINT32(&hashCtx, sealOrdinal); + result |= Trspi_Hash_ENCAUTH(&hashCtx, xsap->encAuthUse.authdata); + result |= Trspi_Hash_UINT32(&hashCtx, pcrDataSize); + result |= Trspi_HashUpdate(&hashCtx, pcrDataSize, pcrData); + result |= Trspi_Hash_UINT32(&hashCtx, ulDataLength); + result |= Trspi_HashUpdate(&hashCtx, ulDataLength, sealData); + if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) { + goto error; + } + + if ((result = authsess_xsap_hmac(xsap, &digest))) + goto error; + +#ifdef TSS_BUILD_SEALX + if (sealOrdinal == TPM_ORD_Seal) { + if ((result = TCS_API(tspContext)->Seal(tspContext, tcsKeyHandle, &xsap->encAuthUse, + pcrDataSize, pcrData, ulDataLength, + sealData, xsap->pAuth, &encDataSize, + &encData))) { + goto error; + } + } else if (sealOrdinal == TPM_ORD_Sealx) { + if ((result = TCS_API(tspContext)->Sealx(tspContext, tcsKeyHandle, &xsap->encAuthUse, + pcrDataSize, pcrData, ulDataLength, sealData, + xsap->pAuth, &encDataSize, &encData))) { + goto error; + } + } else { + result = TSPERR(TSS_E_INTERNAL_ERROR); + goto error; + } +#else + if ((result = TCS_API(tspContext)->Seal(tspContext, tcsKeyHandle, &xsap->encAuthUse, + pcrDataSize, pcrData, ulDataLength, sealData, + xsap->pAuth, &encDataSize, &encData))) + goto error; +#endif + + result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); + result |= Trspi_Hash_UINT32(&hashCtx, result); + result |= Trspi_Hash_UINT32(&hashCtx, sealOrdinal); + result |= Trspi_HashUpdate(&hashCtx, encDataSize, encData); + if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) + goto error; + + if ((result = authsess_xsap_verify(xsap, &digest))) + goto error; + + /* Need to set the object with the blob and the pcr's */ + if ((result = obj_encdata_set_data(hEncData, encDataSize, encData))) + goto error; + + if (pcrDataSize) + result = obj_encdata_set_pcr_info(hEncData, pcrInfoType, pcrData); + +error: + authsess_free(xsap); + free(encData); + free(pcrData); + if (sealData != rgbDataToSeal) + free(sealData); + return result; +} + +TSS_RESULT +Tspi_Data_Unseal(TSS_HENCDATA hEncData, /* in */ + TSS_HKEY hKey, /* in */ + UINT32 * pulUnsealedDataLength,/* out */ + BYTE ** prgbUnsealedData) /* out */ +{ + UINT64 offset; + TPM_AUTH privAuth2; + TPM_DIGEST digest; + TPM_NONCE authLastNonceEven; + TSS_RESULT result; + TSS_HPOLICY hPolicy, hEncPolicy; + TCS_KEY_HANDLE tcsKeyHandle; + TSS_HCONTEXT tspContext; + UINT32 ulDataLen, unSealedDataLen; + BYTE *data = NULL, *unSealedData = NULL, *maskedData; + UINT16 mask; + Trspi_HashCtx hashCtx; + struct authsess *xsap = NULL; + + if (pulUnsealedDataLength == NULL || prgbUnsealedData == NULL) + return TSPERR(TSS_E_BAD_PARAMETER); + + if ((result = obj_encdata_get_tsp_context(hEncData, &tspContext))) + return result; + + if ((result = obj_rsakey_get_policy(hKey, TSS_POLICY_USAGE, &hPolicy, NULL))) + return result; + + if ((result = obj_encdata_get_policy(hEncData, TSS_POLICY_USAGE, &hEncPolicy))) + return result; + + if ((result = obj_encdata_get_data(hEncData, &ulDataLen, &data))) + return result == (TSS_E_INVALID_OBJ_ACCESS | TSS_LAYER_TSP) ? + TSPERR(TSS_E_ENC_NO_DATA) : + result; + + offset = 0; + Trspi_UnloadBlob_UINT16(&offset, &mask, data); + if (mask == TPM_TAG_STORED_DATA12) { + /* The second UINT16 in a TPM_STORED_DATA12 is the entity type. If its non-zero + * then we must unmask the unsealed data after it returns from the TCS */ + Trspi_UnloadBlob_UINT16(&offset, &mask, data); + } else + mask = 0; + + if ((result = obj_rsakey_get_tcs_handle(hKey, &tcsKeyHandle))) + goto error; + + if ((result = authsess_xsap_init(tspContext, hKey, hEncData, TSS_AUTH_POLICY_REQUIRED, + TPM_ORD_Unseal, TPM_ET_KEYHANDLE, &xsap))) + goto error; + + result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); + result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_Unseal); + result |= Trspi_HashUpdate(&hashCtx, ulDataLen, data); + if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) + goto error; + + if ((result = authsess_xsap_hmac(xsap, &digest))) + goto error; + + if ((result = secret_PerformAuth_OIAP(hEncData, TPM_ORD_Unseal, hEncPolicy, FALSE, &digest, + &privAuth2))) + goto error; + + if (mask) { + /* save off last nonce even to pass to sealx callback */ + memcpy(authLastNonceEven.nonce, xsap->auth.NonceEven.nonce, sizeof(TPM_NONCE)); + } + + if ((result = TCS_API(tspContext)->Unseal(tspContext, tcsKeyHandle, ulDataLen, data, + xsap->pAuth, &privAuth2, &unSealedDataLen, + &unSealedData))) + goto error; + + result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); + result |= Trspi_Hash_UINT32(&hashCtx, TSS_SUCCESS); + result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_Unseal); + result |= Trspi_Hash_UINT32(&hashCtx, unSealedDataLen); + result |= Trspi_HashUpdate(&hashCtx, unSealedDataLen, unSealedData); + if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) { + free(unSealedData); + goto error; + } + + if ((result = authsess_xsap_verify(xsap, &digest))) { + free(unSealedData); + goto error; + } + + if ((result = obj_policy_validate_auth_oiap(hEncPolicy, &digest, &privAuth2))) { + free(unSealedData); + goto error; + } + + /* If the data is masked, use the callback set up in authsess_xsap_init */ + if (mask) { + maskedData = unSealedData; + + if ((unSealedData = calloc_tspi(tspContext, unSealedDataLen)) == NULL) { + free(maskedData); + LogError("malloc of %u bytes failed", unSealedDataLen); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto error; + } + + /* XXX pass in out saved-off authLastNonceEven. This conflicts with the + * description of the rgbNonceEven parameter in the spec, but without it, its not + * possible to compute the MGF1 key */ + if ((result = + ((TSS_RESULT (*)(PVOID, TSS_HKEY, TSS_HENCDATA, TSS_ALGORITHM_ID, + UINT32, BYTE *, BYTE *, BYTE *, BYTE *, UINT32, BYTE *, + BYTE *))xsap->cb_sealx.callback)(xsap->cb_sealx.appData, hKey, hEncData, + xsap->cb_sealx.alg, sizeof(TPM_NONCE), + authLastNonceEven.nonce, + xsap->auth.NonceOdd.nonce, + xsap->nonceEvenxSAP.nonce, + xsap->nonceOddxSAP.nonce, + unSealedDataLen, maskedData, + unSealedData))) { + free(maskedData); + goto error; + } + + free(maskedData); + } else { + if ((result = __tspi_add_mem_entry(tspContext, unSealedData))) + goto error; + } + + *pulUnsealedDataLength = unSealedDataLen; + *prgbUnsealedData = unSealedData; + +error: + authsess_free(xsap); + if (data) + free_tspi(tspContext, data); + + return result; +} |