summaryrefslogtreecommitdiff
path: root/src/tcs/tcsi_transport.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tcs/tcsi_transport.c')
-rw-r--r--src/tcs/tcsi_transport.c513
1 files changed, 513 insertions, 0 deletions
diff --git a/src/tcs/tcsi_transport.c b/src/tcs/tcsi_transport.c
new file mode 100644
index 0000000..38a3b32
--- /dev/null
+++ b/src/tcs/tcsi_transport.c
@@ -0,0 +1,513 @@
+
+/*
+ * Licensed Materials - Property of IBM
+ *
+ * trousers - An open source TCG Software Stack
+ *
+ * (C) Copyright International Business Machines Corp. 2007
+ *
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "trousers/tss.h"
+#include "trousers_types.h"
+#include "tcs_tsp.h"
+#include "tcs_utils.h"
+#include "tcs_int_literals.h"
+#include "capabilities.h"
+#include "tcslog.h"
+#include "tcsps.h"
+#include "req_mgr.h"
+
+
+TSS_RESULT
+TCSP_EstablishTransport_Internal(TCS_CONTEXT_HANDLE hContext,
+ UINT32 ulTransControlFlags,
+ TCS_KEY_HANDLE hEncKey,
+ UINT32 ulTransSessionInfoSize,
+ BYTE* rgbTransSessionInfo,
+ UINT32 ulSecretSize,
+ BYTE* rgbSecret,
+ TPM_AUTH* pEncKeyAuth,
+ TPM_MODIFIER_INDICATOR* pbLocality,
+ TCS_HANDLE* hTransSession,
+ UINT32* ulCurrentTicks,
+ BYTE** prgbCurrentTicks,
+ TPM_NONCE* pTransNonce)
+{
+ TSS_RESULT result;
+ UINT32 paramSize;
+ UINT64 offset;
+ TPM_KEY_HANDLE keySlot;
+ BYTE txBlob[TSS_TPM_TXBLOB_SIZE];
+
+ if ((result = ctx_verify_context(hContext)))
+ return result;
+
+ if (ulTransControlFlags == TSS_TCSATTRIB_TRANSPORT_EXCLUSIVE) {
+ if ((result = ctx_req_exclusive_transport(hContext)))
+ return result;
+ }
+
+ if (pEncKeyAuth) {
+ if ((result = auth_mgr_check(hContext, &pEncKeyAuth->AuthHandle)))
+ return result;
+ }
+
+ /* if hEncKey is set to TPM_KH_TRANSPORT, that's the signal to the TPM that this will be
+ * an unencrypted transport session, so we don't need to check that its loaded */
+ if (hEncKey != TPM_KH_TRANSPORT) {
+ if ((result = ensureKeyIsLoaded(hContext, hEncKey, &keySlot)))
+ return result;
+ }
+
+ offset = TSS_TPM_TXBLOB_HDR_LEN;
+ LoadBlob_UINT32(&offset, keySlot, txBlob);
+ LoadBlob(&offset, ulTransSessionInfoSize, txBlob, rgbTransSessionInfo);
+ LoadBlob_UINT32(&offset, ulSecretSize, txBlob);
+ LoadBlob(&offset, ulSecretSize, txBlob, rgbSecret);
+ if (pEncKeyAuth) {
+ LoadBlob_Auth(&offset, txBlob, pEncKeyAuth);
+ LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, offset, TPM_ORD_EstablishTransport,
+ txBlob);
+ } else
+ LoadBlob_Header(TPM_TAG_RQU_COMMAND, offset, TPM_ORD_EstablishTransport, txBlob);
+
+ if ((result = req_mgr_submit_req(txBlob)))
+ goto done;
+
+ if ((result = UnloadBlob_Header(txBlob, &paramSize))) {
+ LogDebugFn("UnloadBlob_Header failed: rc=0x%x", result);
+ goto done;
+ }
+
+ offset = TSS_TPM_TXBLOB_HDR_LEN;
+ UnloadBlob_UINT32(&offset, hTransSession, txBlob);
+ UnloadBlob_UINT32(&offset, pbLocality, txBlob);
+
+ *ulCurrentTicks = sizeof(TPM_STRUCTURE_TAG)
+ + sizeof(UINT64)
+ + sizeof(UINT16)
+ + sizeof(TPM_NONCE);
+
+ *prgbCurrentTicks = malloc(*ulCurrentTicks);
+ if (*prgbCurrentTicks == NULL) {
+ result = TCSERR(TSS_E_OUTOFMEMORY);
+ goto done;
+ }
+
+ UnloadBlob(&offset, *ulCurrentTicks, txBlob, *prgbCurrentTicks);
+ UnloadBlob(&offset, sizeof(TPM_NONCE), txBlob, (BYTE *)pTransNonce);
+ if (pEncKeyAuth)
+ UnloadBlob_Auth(&offset, txBlob, pEncKeyAuth);
+
+ ctx_set_transport_enabled(hContext, *hTransSession);
+done:
+ auth_mgr_release_auth(pEncKeyAuth, NULL, hContext);
+ return result;
+}
+
+TSS_RESULT
+TCSP_ExecuteTransport_Internal(TCS_CONTEXT_HANDLE hContext,
+ TPM_COMMAND_CODE unWrappedCommandOrdinal,
+ UINT32 ulWrappedCmdParamInSize,
+ BYTE* rgbWrappedCmdParamIn,
+ UINT32* pulHandleListSize, /* in, out */
+ TCS_HANDLE** rghHandles, /* in, out */
+ TPM_AUTH* pWrappedCmdAuth1, /* in, out */
+ TPM_AUTH* pWrappedCmdAuth2, /* in, out */
+ TPM_AUTH* pTransAuth, /* in, out */
+ UINT64* punCurrentTicks,
+ TPM_MODIFIER_INDICATOR* pbLocality,
+ TPM_RESULT* pulWrappedCmdReturnCode,
+ UINT32* ulWrappedCmdParamOutSize,
+ BYTE** rgbWrappedCmdParamOut)
+{
+ TSS_RESULT result;
+ UINT32 paramSize, wrappedSize, val1 = 0, val2 = 0, *pVal1 = NULL, *pVal2 = NULL;
+ TCS_HANDLE handle1 = 0, handle2 = 0;
+ UINT64 offset, wrappedOffset = 0;
+ BYTE txBlob[TSS_TPM_TXBLOB_SIZE];
+
+
+ if (*pulHandleListSize > 2) {
+ LogDebugFn("************ EXPAND KEYSLOT SIZE *********");
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+ }
+
+ if ((result = ctx_verify_context(hContext)))
+ return result;
+
+ if (pWrappedCmdAuth1)
+ if ((result = auth_mgr_check(hContext, &pWrappedCmdAuth1->AuthHandle)))
+ goto done;
+
+ if (pWrappedCmdAuth2)
+ if ((result = auth_mgr_check(hContext, &pWrappedCmdAuth2->AuthHandle)))
+ goto done;
+
+ switch (unWrappedCommandOrdinal) {
+ /* If the command is FlushSpecific, we get handle that needs to be freed, but we don't know
+ * what type it is. */
+ case TPM_ORD_FlushSpecific:
+ if (*pulHandleListSize == 0) { /* invalid */
+ result = TCSERR(TSS_E_BAD_PARAMETER);
+ goto done;
+ }
+
+ /* If this is a transport handle, remove the context's reference to the session */
+ ctx_set_transport_disabled(hContext, rghHandles[0]);
+
+ /* Is it a key? If so, jump to the get_slot_lite and key management calls below */
+ if (ctx_has_key_loaded(hContext, *rghHandles[0]))
+ goto map_key_handles;
+
+ /* fall through */
+ case TPM_ORD_Terminate_Handle:
+ if (!auth_mgr_check(hContext, rghHandles[0]))
+ auth_mgr_release_auth_handle(*rghHandles[0], hContext, FALSE);
+
+ /* If the handle is an auth handle or any other kind of handle, there's no
+ * mapping done in the TCS, so pass its value straight to the TPM and jump over
+ * the switch statement below where we assume FLushSpecific is being done on a
+ * key */
+ handle1 = val1 = *rghHandles[0];
+ pVal1 = &val1;
+
+ goto build_command;
+ default:
+ break;
+ }
+
+map_key_handles:
+ if (*pulHandleListSize == 2) {
+ handle2 = (*rghHandles)[1];
+
+ if ((result = get_slot_lite(hContext, handle2, &val2))) {
+ *pulHandleListSize = 0;
+ goto done;
+ }
+
+ pVal2 = &val2;
+ }
+
+ if (*pulHandleListSize >= 1) {
+ handle1 = *rghHandles[0];
+
+ *pulHandleListSize = 0;
+
+ if ((result = get_slot_lite(hContext, handle1, &val1)))
+ goto done;
+
+ pVal1 = &val1;
+ }
+
+ switch (unWrappedCommandOrdinal) {
+ case TPM_ORD_EvictKey:
+ case TPM_ORD_FlushSpecific:
+ {
+ if ((result = ctx_remove_key_loaded(hContext, handle1)))
+ goto done;
+
+ if ((result = key_mgr_dec_ref_count(handle1)))
+ goto done;
+
+ /* we can't call key_mgr_ref_cnt() here since it calls TPM_EvictKey directly */
+ mc_set_slot_by_handle(handle1, NULL_TPM_HANDLE);
+ break;
+ }
+ case TPM_ORD_OIAP:
+ {
+ /* are the maximum number of auth sessions open? */
+ if (auth_mgr_req_new(hContext) == FALSE) {
+ if ((result = auth_mgr_swap_out(hContext)))
+ goto done;
+ }
+
+ break;
+ }
+ case TPM_ORD_OSAP:
+ {
+ UINT16 entityType;
+ UINT32 entityValue, newEntValue;
+
+ /* are the maximum number of auth sessions open? */
+ if (auth_mgr_req_new(hContext) == FALSE) {
+ if ((result = auth_mgr_swap_out(hContext)))
+ goto done;
+ }
+
+ offset = 0;
+ UnloadBlob_UINT16(&offset, &entityType, rgbWrappedCmdParamIn);
+ UnloadBlob_UINT32(&offset, &entityValue, rgbWrappedCmdParamIn);
+
+ if (entityType == TCPA_ET_KEYHANDLE || entityType == TCPA_ET_KEY) {
+ if (ensureKeyIsLoaded(hContext, entityValue, &newEntValue))
+ return TCSERR(TSS_E_KEY_NOT_LOADED);
+
+ /* OSAP is never encrypted in a transport session, so changing
+ * rgbWrappedCmdParamIn is ok here */
+ offset = sizeof(UINT16);
+ LoadBlob_UINT32(&offset, newEntValue, rgbWrappedCmdParamIn);
+ }
+
+ break;
+ }
+ case TPM_ORD_DSAP:
+ {
+ UINT16 entityType;
+ UINT32 keyHandle, tpmKeyHandle;
+
+ /* are the maximum number of auth sessions open? */
+ if (auth_mgr_req_new(hContext) == FALSE) {
+ if ((result = auth_mgr_swap_out(hContext)))
+ goto done;
+ }
+
+ offset = 0;
+ UnloadBlob_UINT16(&offset, &entityType, rgbWrappedCmdParamIn);
+ UnloadBlob_UINT32(&offset, &keyHandle, rgbWrappedCmdParamIn);
+
+ if (ensureKeyIsLoaded(hContext, keyHandle, &tpmKeyHandle)) {
+ result = TCSERR(TSS_E_KEY_NOT_LOADED);
+ goto done;
+ }
+
+ /* DSAP's only encrypted paramter is entityValue, so replacing keyHandle inside
+ * rgbWrappedCmdParamIn is ok */
+ offset = sizeof(UINT16);
+ LoadBlob_UINT32(&offset, tpmKeyHandle, rgbWrappedCmdParamIn);
+ }
+ default:
+ break;
+ }
+
+build_command:
+ if ((result = tpm_rqu_build(TPM_ORD_ExecuteTransport, &wrappedOffset,
+ &txBlob[TSS_TXBLOB_WRAPPEDCMD_OFFSET], unWrappedCommandOrdinal,
+ pVal1, pVal2, ulWrappedCmdParamInSize, rgbWrappedCmdParamIn,
+ pWrappedCmdAuth1, pWrappedCmdAuth2)))
+ goto done;
+
+ /* The blob we'll load here looks like this:
+ *
+ * |TAGet|LENet|ORDet|wrappedCmdSize|wrappedCmd|AUTHet|
+ *
+ * wrappedCmd looks like this:
+ *
+ * |TAGw|LENw|ORDw|HANDLESw|DATAw|AUTH1w|AUTH2w|
+ *
+ * w = wrapped command info
+ * et = execute transport command info
+ *
+ * Note that the wrapped command was loaded into the blob by the tpm_rqu_build call
+ * above.
+ *
+ */
+ offset = TSS_TPM_TXBLOB_HDR_LEN;
+ /* Load wrapped command size: |wrappedCmdSize| */
+ LoadBlob_UINT32(&offset, wrappedOffset, txBlob);
+
+ /* offset + wrappedOffset is the position of the execute transport auth struct */
+ offset += wrappedOffset;
+
+ if (pTransAuth) {
+ /* Load the auth for the execute transport command: |AUTHet| */
+ LoadBlob_Auth(&offset, txBlob, pTransAuth);
+ /* Load the outer header: |TAGet|LENet|ORDet| */
+ LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, offset, TPM_ORD_ExecuteTransport,
+ txBlob);
+ } else {
+ /* Load the outer header: |TAGet|LENet|ORDet| */
+ LoadBlob_Header(TPM_TAG_RQU_COMMAND, offset, TPM_ORD_ExecuteTransport, txBlob);
+ }
+
+ if ((result = req_mgr_submit_req(txBlob)))
+ goto done;
+
+ /* Unload the Execute Transport (outer) header */
+ if ((result = UnloadBlob_Header(txBlob, &paramSize))) {
+ LogDebugFn("UnloadBlob_Header failed: rc=0x%x", result);
+ goto done;
+ }
+
+ /* The response from the TPM looks like this:
+ *
+ * |TAGet|LENet|RCet|currentTicks|locality|wrappedRspSize|wrappedRsp|AUTHet|
+ *
+ * and wrappedRsp looks like:
+ *
+ * |TAGw|LENw|RCw|HANDLESw|DATAw|AUTH1w|AUTH2w|
+ */
+
+ offset = TSS_TPM_TXBLOB_HDR_LEN;
+ UnloadBlob_UINT64(&offset, punCurrentTicks, txBlob);
+ UnloadBlob_UINT32(&offset, pbLocality, txBlob);
+
+ /* Unload the wrapped response size: |wrappedRspSize| */
+ UnloadBlob_UINT32(&offset, &wrappedSize, txBlob);
+
+ /* We've parsed right up to wrappedRsp, so save off this offset for later */
+ wrappedOffset = offset;
+
+ /* The current offset + the response size will be the offset of |AUTHet| */
+ offset += wrappedSize;
+ if (pTransAuth)
+ UnloadBlob_Auth(&offset, txBlob, pTransAuth);
+
+ /* Now parse through the returned response @ wrappedOffset */
+ if ((result = UnloadBlob_Header(&txBlob[wrappedOffset], &paramSize))) {
+ LogDebugFn("Wrapped command (Ordinal 0x%x) failed: rc=0x%x",
+ unWrappedCommandOrdinal, result);
+
+ /* This is the result of the wrapped command. If its not success, return its value
+ * in the pulWrappedCmdReturnCode variable and return indicating that the execute
+ * transport command was successful */
+ *pulWrappedCmdReturnCode = result;
+ *ulWrappedCmdParamOutSize = 0;
+ *rgbWrappedCmdParamOut = NULL;
+ auth_mgr_release_auth(pWrappedCmdAuth1, pWrappedCmdAuth2, hContext);
+
+ return TSS_SUCCESS;
+ }
+
+ *pulWrappedCmdReturnCode = TSS_SUCCESS;
+
+ pVal1 = pVal2 = NULL;
+ switch (unWrappedCommandOrdinal) {
+ /* The commands below have 1 outgoing handle */
+ case TPM_ORD_LoadKey2:
+ pVal1 = &val1;
+ break;
+ default:
+ break;
+ }
+
+ result = tpm_rsp_parse(TPM_ORD_ExecuteTransport, &txBlob[wrappedOffset], paramSize,
+ pVal1, pVal2, ulWrappedCmdParamOutSize, rgbWrappedCmdParamOut,
+ pWrappedCmdAuth1, pWrappedCmdAuth2);
+
+ offset = 0;
+ switch (unWrappedCommandOrdinal) {
+ case TPM_ORD_LoadKey2:
+ {
+ TCS_KEY_HANDLE tcs_handle = NULL_TCS_HANDLE;
+
+ if ((result = load_key_final(hContext, handle1, &tcs_handle, NULL, val1)))
+ goto done;
+
+ *rghHandles[0] = tcs_handle;
+ *pulHandleListSize = 1;
+ break;
+ }
+ case TPM_ORD_DSAP:
+ case TPM_ORD_OSAP:
+ case TPM_ORD_OIAP:
+ {
+ UINT32 handle;
+
+ UnloadBlob_UINT32(&offset, &handle, *rgbWrappedCmdParamOut);
+ result = auth_mgr_add(hContext, handle);
+ break;
+ }
+ default:
+ break;
+ }
+
+done:
+ auth_mgr_release_auth(pWrappedCmdAuth1, pWrappedCmdAuth2, hContext);
+ return result;
+}
+
+TSS_RESULT
+TCSP_ReleaseTransportSigned_Internal(TCS_CONTEXT_HANDLE hContext,
+ TCS_KEY_HANDLE hSignatureKey,
+ TPM_NONCE* AntiReplayNonce,
+ TPM_AUTH* pKeyAuth, /* in, out */
+ TPM_AUTH* pTransAuth, /* in, out */
+ TPM_MODIFIER_INDICATOR* pbLocality,
+ UINT32* pulCurrentTicksSize,
+ BYTE** prgbCurrentTicks,
+ UINT32* pulSignatureSize,
+ BYTE** prgbSignature)
+{
+ TSS_RESULT result;
+ UINT32 paramSize;
+ UINT64 offset;
+ TPM_KEY_HANDLE keySlot;
+ BYTE txBlob[TSS_TPM_TXBLOB_SIZE];
+
+ if ((result = ctx_verify_context(hContext)))
+ return result;
+
+ if (pKeyAuth) {
+ if ((result = auth_mgr_check(hContext, &pKeyAuth->AuthHandle)))
+ return result;
+ }
+
+ if ((result = ensureKeyIsLoaded(hContext, hSignatureKey, &keySlot)))
+ return result;
+
+ offset = TSS_TPM_TXBLOB_HDR_LEN;
+ LoadBlob_UINT32(&offset, keySlot, txBlob);
+ LoadBlob(&offset, sizeof(TPM_NONCE), txBlob, (BYTE *)AntiReplayNonce);
+ if (pKeyAuth) {
+ LoadBlob_Auth(&offset, txBlob, pKeyAuth);
+ LoadBlob_Auth(&offset, txBlob, pTransAuth);
+ LoadBlob_Header(TPM_TAG_RQU_AUTH2_COMMAND, offset, TPM_ORD_ReleaseTransportSigned,
+ txBlob);
+ } else {
+ LoadBlob_Auth(&offset, txBlob, pTransAuth);
+ LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, offset, TPM_ORD_ReleaseTransportSigned,
+ txBlob);
+ }
+
+ if ((result = req_mgr_submit_req(txBlob)))
+ goto done;
+
+ if ((result = UnloadBlob_Header(txBlob, &paramSize))) {
+ LogDebugFn("UnloadBlob_Header failed: rc=0x%x", result);
+ goto done;
+ }
+
+ /* unconditionally disable our accounting of the session */
+ ctx_set_transport_disabled(hContext, NULL);
+
+ offset = TSS_TPM_TXBLOB_HDR_LEN;
+ UnloadBlob_UINT32(&offset, pbLocality, txBlob);
+
+ *pulCurrentTicksSize = sizeof(TPM_STRUCTURE_TAG)
+ + sizeof(UINT64)
+ + sizeof(UINT16)
+ + sizeof(TPM_NONCE);
+
+ *prgbCurrentTicks = malloc(*pulCurrentTicksSize);
+ if (*prgbCurrentTicks == NULL) {
+ result = TCSERR(TSS_E_OUTOFMEMORY);
+ goto done;
+ }
+
+ UnloadBlob(&offset, *pulCurrentTicksSize, txBlob, *prgbCurrentTicks);
+ UnloadBlob_UINT32(&offset, pulSignatureSize, txBlob);
+
+ *prgbSignature = malloc(*pulSignatureSize);
+ if (*prgbSignature == NULL) {
+ free(*prgbCurrentTicks);
+ result = TCSERR(TSS_E_OUTOFMEMORY);
+ goto done;
+ }
+
+ UnloadBlob(&offset, *pulSignatureSize, txBlob, *prgbSignature);
+
+ if (pKeyAuth)
+ UnloadBlob_Auth(&offset, txBlob, pKeyAuth);
+ UnloadBlob_Auth(&offset, txBlob, pTransAuth);
+
+done:
+ auth_mgr_release_auth(pKeyAuth, NULL, hContext);
+ return result;
+}