Home | History | Annotate | Line # | Download | only in tcs
      1 
      2 /*
      3  * Licensed Materials - Property of IBM
      4  *
      5  * trousers - An open source TCG Software Stack
      6  *
      7  * (C) Copyright International Business Machines Corp. 2007
      8  *
      9  */
     10 
     11 
     12 #include <stdlib.h>
     13 #include <stdio.h>
     14 #include <string.h>
     15 
     16 #include "trousers/tss.h"
     17 #include "trousers_types.h"
     18 #include "tcs_tsp.h"
     19 #include "tcs_utils.h"
     20 #include "tcs_int_literals.h"
     21 #include "capabilities.h"
     22 #include "tcslog.h"
     23 #include "tcsps.h"
     24 #include "req_mgr.h"
     25 
     26 
     27 TSS_RESULT
     28 TCSP_EstablishTransport_Internal(TCS_CONTEXT_HANDLE      hContext,
     29 				 UINT32                  ulTransControlFlags,
     30 				 TCS_KEY_HANDLE          hEncKey,
     31 				 UINT32                  ulTransSessionInfoSize,
     32 				 BYTE*                   rgbTransSessionInfo,
     33 				 UINT32                  ulSecretSize,
     34 				 BYTE*                   rgbSecret,
     35 				 TPM_AUTH*               pEncKeyAuth,
     36 				 TPM_MODIFIER_INDICATOR* pbLocality,
     37 				 TCS_HANDLE*             hTransSession,
     38 				 UINT32*                 ulCurrentTicks,
     39 				 BYTE**                  prgbCurrentTicks,
     40 				 TPM_NONCE*              pTransNonce)
     41 {
     42 	TSS_RESULT result;
     43 	UINT32 paramSize;
     44 	UINT64 offset;
     45 	TPM_KEY_HANDLE keySlot = TPM_KH_TRANSPORT;
     46 	BYTE txBlob[TSS_TPM_TXBLOB_SIZE];
     47 
     48 	if ((result = ctx_verify_context(hContext)))
     49 		return result;
     50 
     51 	if (ulTransControlFlags == TSS_TCSATTRIB_TRANSPORT_EXCLUSIVE) {
     52 		if ((result = ctx_req_exclusive_transport(hContext)))
     53 			return result;
     54 	}
     55 
     56 	if (pEncKeyAuth) {
     57 		if ((result = auth_mgr_check(hContext, &pEncKeyAuth->AuthHandle)))
     58 			return result;
     59 	}
     60 
     61 	/* if hEncKey is set to TPM_KH_TRANSPORT, that's the signal to the TPM that this will be
     62 	 * an unencrypted transport session, so we don't need to check that its loaded */
     63 	if (hEncKey != TPM_KH_TRANSPORT) {
     64 		if ((result = ensureKeyIsLoaded(hContext, hEncKey, &keySlot)))
     65 			return result;
     66 	}
     67 
     68 	offset = TSS_TPM_TXBLOB_HDR_LEN;
     69 	LoadBlob_UINT32(&offset, keySlot, txBlob);
     70 	LoadBlob(&offset, ulTransSessionInfoSize, txBlob, rgbTransSessionInfo);
     71 	LoadBlob_UINT32(&offset, ulSecretSize, txBlob);
     72 	LoadBlob(&offset, ulSecretSize, txBlob, rgbSecret);
     73 	if (pEncKeyAuth) {
     74 		LoadBlob_Auth(&offset, txBlob, pEncKeyAuth);
     75 		LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, offset, TPM_ORD_EstablishTransport,
     76 				txBlob);
     77 	} else
     78 		LoadBlob_Header(TPM_TAG_RQU_COMMAND, offset, TPM_ORD_EstablishTransport, txBlob);
     79 
     80 	if ((result = req_mgr_submit_req(txBlob)))
     81 		goto done;
     82 
     83 	if ((result = UnloadBlob_Header(txBlob, &paramSize))) {
     84 		LogDebugFn("UnloadBlob_Header failed: rc=0x%x", result);
     85 		goto done;
     86 	}
     87 
     88 	offset = TSS_TPM_TXBLOB_HDR_LEN;
     89 	UnloadBlob_UINT32(&offset, hTransSession, txBlob);
     90 	UnloadBlob_UINT32(&offset, pbLocality, txBlob);
     91 
     92 	*ulCurrentTicks = sizeof(TPM_STRUCTURE_TAG)
     93 			  + sizeof(UINT64)
     94 			  + sizeof(UINT16)
     95 			  + sizeof(TPM_NONCE);
     96 
     97 	*prgbCurrentTicks = malloc(*ulCurrentTicks);
     98 	if (*prgbCurrentTicks == NULL) {
     99 		result = TCSERR(TSS_E_OUTOFMEMORY);
    100 		goto done;
    101 	}
    102 
    103 	UnloadBlob(&offset, *ulCurrentTicks, txBlob, *prgbCurrentTicks);
    104 	UnloadBlob(&offset, sizeof(TPM_NONCE), txBlob, (BYTE *)pTransNonce);
    105 	if (pEncKeyAuth)
    106 		UnloadBlob_Auth(&offset, txBlob, pEncKeyAuth);
    107 
    108 	ctx_set_transport_enabled(hContext, *hTransSession);
    109 done:
    110 	auth_mgr_release_auth(pEncKeyAuth, NULL, hContext);
    111 	return result;
    112 }
    113 
    114 TSS_RESULT
    115 TCSP_ExecuteTransport_Internal(TCS_CONTEXT_HANDLE      hContext,
    116 			       TPM_COMMAND_CODE        unWrappedCommandOrdinal,
    117 			       UINT32                  ulWrappedCmdParamInSize,
    118 			       BYTE*                   rgbWrappedCmdParamIn,
    119 			       UINT32*                 pulHandleListSize,	/* in, out */
    120 			       TCS_HANDLE**            rghHandles,		/* in, out */
    121 			       TPM_AUTH*               pWrappedCmdAuth1,	/* in, out */
    122 			       TPM_AUTH*               pWrappedCmdAuth2,	/* in, out */
    123 			       TPM_AUTH*               pTransAuth,		/* in, out */
    124 			       UINT64*                 punCurrentTicks,
    125 			       TPM_MODIFIER_INDICATOR* pbLocality,
    126 			       TPM_RESULT*             pulWrappedCmdReturnCode,
    127 			       UINT32*                 ulWrappedCmdParamOutSize,
    128 			       BYTE**                  rgbWrappedCmdParamOut)
    129 {
    130 	TSS_RESULT result;
    131 	UINT32 paramSize, wrappedSize, val1 = 0, val2 = 0, *pVal1 = NULL, *pVal2 = NULL;
    132 	TCS_HANDLE handle1 = 0, handle2 = 0;
    133 	UINT64 offset, wrappedOffset = 0;
    134 	BYTE txBlob[TSS_TPM_TXBLOB_SIZE];
    135 
    136 
    137 	if (*pulHandleListSize > 2) {
    138 		LogDebugFn("************ EXPAND KEYSLOT SIZE *********");
    139 		return TCSERR(TSS_E_INTERNAL_ERROR);
    140 	}
    141 
    142 	if ((result = ctx_verify_context(hContext)))
    143 		return result;
    144 
    145 	if (pWrappedCmdAuth1)
    146 		if ((result = auth_mgr_check(hContext, &pWrappedCmdAuth1->AuthHandle)))
    147 			goto done;
    148 
    149 	if (pWrappedCmdAuth2)
    150 		if ((result = auth_mgr_check(hContext, &pWrappedCmdAuth2->AuthHandle)))
    151 			goto done;
    152 
    153 	switch (unWrappedCommandOrdinal) {
    154 	/* If the command is FlushSpecific, we get handle that needs to be freed, but we don't know
    155 	 * what type it is. */
    156 	case TPM_ORD_FlushSpecific:
    157 		if (*pulHandleListSize == 0) { /* invalid */
    158 			result = TCSERR(TSS_E_BAD_PARAMETER);
    159 			goto done;
    160 		}
    161 
    162 		/* If this is a transport handle, remove the context's reference to the session */
    163 		ctx_set_transport_disabled(hContext, rghHandles[0]);
    164 
    165 		/* Is it a key? If so, jump to the get_slot_lite and key management calls below */
    166 		if (ctx_has_key_loaded(hContext, *rghHandles[0]))
    167 			goto map_key_handles;
    168 
    169 		/* fall through */
    170 	case TPM_ORD_Terminate_Handle:
    171 		if (!auth_mgr_check(hContext, rghHandles[0]))
    172 			auth_mgr_release_auth_handle(*rghHandles[0], hContext, FALSE);
    173 
    174 		/* If the handle is an auth handle or any other kind of handle, there's no
    175 		 * mapping done in the TCS, so pass its value straight to the TPM and jump over
    176 		 * the switch statement below where we assume FLushSpecific is being done on a
    177 		 * key */
    178 		handle1 = val1 = *rghHandles[0];
    179 		pVal1 = &val1;
    180 
    181 		goto build_command;
    182 	default:
    183 		break;
    184 	}
    185 
    186 map_key_handles:
    187 	if (*pulHandleListSize == 2) {
    188 		handle2 = (*rghHandles)[1];
    189 
    190 		if ((result = get_slot_lite(hContext, handle2, &val2))) {
    191 			*pulHandleListSize = 0;
    192 			goto done;
    193 		}
    194 
    195 		pVal2 = &val2;
    196 	}
    197 
    198 	if (*pulHandleListSize >= 1) {
    199 		handle1 = *rghHandles[0];
    200 
    201 		*pulHandleListSize = 0;
    202 
    203 		if ((result = get_slot_lite(hContext, handle1, &val1)))
    204 			goto done;
    205 
    206 		pVal1 = &val1;
    207 	}
    208 
    209 	switch (unWrappedCommandOrdinal) {
    210 	case TPM_ORD_EvictKey:
    211 	case TPM_ORD_FlushSpecific:
    212 	{
    213 		if ((result = ctx_remove_key_loaded(hContext, handle1)))
    214 			goto done;
    215 
    216 		if ((result = key_mgr_dec_ref_count(handle1)))
    217 			goto done;
    218 
    219 		/* we can't call key_mgr_ref_cnt() here since it calls TPM_EvictKey directly */
    220 		mc_set_slot_by_handle(handle1, NULL_TPM_HANDLE);
    221 		break;
    222 	}
    223 	case TPM_ORD_OIAP:
    224 	{
    225 		/* are the maximum number of auth sessions open? */
    226 		if (auth_mgr_req_new(hContext) == FALSE) {
    227 			if ((result = auth_mgr_swap_out(hContext)))
    228 				goto done;
    229 		}
    230 
    231 		break;
    232 	}
    233 	case TPM_ORD_OSAP:
    234 	{
    235 		UINT16 entityType;
    236 		UINT32 entityValue, newEntValue;
    237 
    238 		/* are the maximum number of auth sessions open? */
    239 		if (auth_mgr_req_new(hContext) == FALSE) {
    240 			if ((result = auth_mgr_swap_out(hContext)))
    241 				goto done;
    242 		}
    243 
    244 		offset = 0;
    245 		UnloadBlob_UINT16(&offset, &entityType, rgbWrappedCmdParamIn);
    246 		UnloadBlob_UINT32(&offset, &entityValue, rgbWrappedCmdParamIn);
    247 
    248 		if (entityType == TCPA_ET_KEYHANDLE || entityType == TCPA_ET_KEY) {
    249 			if (ensureKeyIsLoaded(hContext, entityValue, &newEntValue))
    250 				return TCSERR(TSS_E_KEY_NOT_LOADED);
    251 
    252 			/* OSAP is never encrypted in a transport session, so changing
    253 			 * rgbWrappedCmdParamIn is ok here */
    254 			offset = sizeof(UINT16);
    255 			LoadBlob_UINT32(&offset, newEntValue, rgbWrappedCmdParamIn);
    256 		}
    257 
    258 		break;
    259 	}
    260 	case TPM_ORD_DSAP:
    261 	{
    262 		UINT16 entityType;
    263 		UINT32 keyHandle, tpmKeyHandle;
    264 
    265 		/* are the maximum number of auth sessions open? */
    266 		if (auth_mgr_req_new(hContext) == FALSE) {
    267 			if ((result = auth_mgr_swap_out(hContext)))
    268 				goto done;
    269 		}
    270 
    271 		offset = 0;
    272 		UnloadBlob_UINT16(&offset, &entityType, rgbWrappedCmdParamIn);
    273 		UnloadBlob_UINT32(&offset, &keyHandle, rgbWrappedCmdParamIn);
    274 
    275 		if (ensureKeyIsLoaded(hContext, keyHandle, &tpmKeyHandle)) {
    276 			result = TCSERR(TSS_E_KEY_NOT_LOADED);
    277 			goto done;
    278 		}
    279 
    280 		/* DSAP's only encrypted paramter is entityValue, so replacing keyHandle inside
    281 		 * rgbWrappedCmdParamIn is ok */
    282 		offset = sizeof(UINT16);
    283 		LoadBlob_UINT32(&offset, tpmKeyHandle, rgbWrappedCmdParamIn);
    284 	}
    285 	default:
    286 		break;
    287 	}
    288 
    289 build_command:
    290 	if ((result = tpm_rqu_build(TPM_ORD_ExecuteTransport, &wrappedOffset,
    291 				    &txBlob[TSS_TXBLOB_WRAPPEDCMD_OFFSET], unWrappedCommandOrdinal,
    292 				    pVal1, pVal2, ulWrappedCmdParamInSize, rgbWrappedCmdParamIn,
    293 				    pWrappedCmdAuth1, pWrappedCmdAuth2)))
    294 		goto done;
    295 
    296 	/* The blob we'll load here looks like this:
    297 	 *
    298 	 * |TAGet|LENet|ORDet|wrappedCmdSize|wrappedCmd|AUTHet|
    299 	 *
    300 	 * wrappedCmd looks like this:
    301 	 *
    302 	 * |TAGw|LENw|ORDw|HANDLESw|DATAw|AUTH1w|AUTH2w|
    303 	 *
    304 	 * w = wrapped command info
    305 	 * et = execute transport command info
    306 	 *
    307 	 * Note that the wrapped command was loaded into the blob by the tpm_rqu_build call
    308 	 * above.
    309 	 *
    310 	 */
    311 	offset = TSS_TPM_TXBLOB_HDR_LEN;
    312 	/* Load wrapped command size: |wrappedCmdSize| */
    313 	LoadBlob_UINT32(&offset, wrappedOffset, txBlob);
    314 
    315 	/* offset + wrappedOffset is the position of the execute transport auth struct */
    316 	offset += wrappedOffset;
    317 
    318 	if (pTransAuth) {
    319 		/* Load the auth for the execute transport command: |AUTHet| */
    320 		LoadBlob_Auth(&offset, txBlob, pTransAuth);
    321 		/* Load the outer header: |TAGet|LENet|ORDet| */
    322 		LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, offset, TPM_ORD_ExecuteTransport,
    323 				txBlob);
    324 	} else {
    325 		/* Load the outer header: |TAGet|LENet|ORDet| */
    326 		LoadBlob_Header(TPM_TAG_RQU_COMMAND, offset, TPM_ORD_ExecuteTransport, txBlob);
    327 	}
    328 
    329 	if ((result = req_mgr_submit_req(txBlob)))
    330 		goto done;
    331 
    332 	/* Unload the Execute Transport (outer) header */
    333 	if ((result = UnloadBlob_Header(txBlob, &paramSize))) {
    334 		LogDebugFn("UnloadBlob_Header failed: rc=0x%x", result);
    335 		goto done;
    336 	}
    337 
    338 	/* The response from the TPM looks like this:
    339 	 *
    340 	 * |TAGet|LENet|RCet|currentTicks|locality|wrappedRspSize|wrappedRsp|AUTHet|
    341 	 *
    342 	 * and wrappedRsp looks like:
    343 	 *
    344 	 * |TAGw|LENw|RCw|HANDLESw|DATAw|AUTH1w|AUTH2w|
    345 	 */
    346 
    347 	offset = TSS_TPM_TXBLOB_HDR_LEN;
    348 	UnloadBlob_UINT64(&offset, punCurrentTicks, txBlob);
    349 	UnloadBlob_UINT32(&offset, pbLocality, txBlob);
    350 
    351 	/* Unload the wrapped response size: |wrappedRspSize| */
    352 	UnloadBlob_UINT32(&offset, &wrappedSize, txBlob);
    353 
    354 	/* We've parsed right up to wrappedRsp, so save off this offset for later */
    355 	wrappedOffset = offset;
    356 
    357 	/* The current offset + the response size will be the offset of |AUTHet| */
    358 	offset += wrappedSize;
    359 	if (pTransAuth)
    360 		UnloadBlob_Auth(&offset, txBlob, pTransAuth);
    361 
    362 	/* Now parse through the returned response @ wrappedOffset */
    363 	if ((result = UnloadBlob_Header(&txBlob[wrappedOffset], &paramSize))) {
    364 		LogDebugFn("Wrapped command (Ordinal 0x%x) failed: rc=0x%x",
    365 			   unWrappedCommandOrdinal, result);
    366 
    367 		/* This is the result of the wrapped command. If its not success, return its value
    368 		 * in the pulWrappedCmdReturnCode variable and return indicating that the execute
    369 		 * transport command was successful */
    370 		*pulWrappedCmdReturnCode = result;
    371 		*ulWrappedCmdParamOutSize = 0;
    372 		*rgbWrappedCmdParamOut = NULL;
    373 		auth_mgr_release_auth(pWrappedCmdAuth1, pWrappedCmdAuth2, hContext);
    374 
    375 		return TSS_SUCCESS;
    376 	}
    377 
    378 	*pulWrappedCmdReturnCode = TSS_SUCCESS;
    379 
    380 	pVal1 = pVal2 = NULL;
    381 	switch (unWrappedCommandOrdinal) {
    382 		/* The commands below have 1 outgoing handle */
    383 		case TPM_ORD_LoadKey2:
    384 			pVal1 = &val1;
    385 			break;
    386 		default:
    387 			break;
    388 	}
    389 
    390 	result = tpm_rsp_parse(TPM_ORD_ExecuteTransport, &txBlob[wrappedOffset], paramSize,
    391 			       pVal1, pVal2, ulWrappedCmdParamOutSize, rgbWrappedCmdParamOut,
    392 			       pWrappedCmdAuth1, pWrappedCmdAuth2);
    393 
    394 	offset = 0;
    395 	switch (unWrappedCommandOrdinal) {
    396 	case TPM_ORD_LoadKey2:
    397 	{
    398 		TCS_KEY_HANDLE tcs_handle = NULL_TCS_HANDLE;
    399 
    400 		if ((result = load_key_final(hContext, handle1, &tcs_handle, NULL, val1)))
    401 			goto done;
    402 
    403 		*rghHandles[0] = tcs_handle;
    404 		*pulHandleListSize = 1;
    405 		break;
    406 	}
    407 	case TPM_ORD_DSAP:
    408 	case TPM_ORD_OSAP:
    409 	case TPM_ORD_OIAP:
    410 	{
    411 		UINT32 handle;
    412 
    413 		UnloadBlob_UINT32(&offset, &handle, *rgbWrappedCmdParamOut);
    414 		result = auth_mgr_add(hContext, handle);
    415 		break;
    416 	}
    417 	default:
    418 		break;
    419 	}
    420 
    421 done:
    422 	auth_mgr_release_auth(pWrappedCmdAuth1, pWrappedCmdAuth2, hContext);
    423 	return result;
    424 }
    425 
    426 TSS_RESULT
    427 TCSP_ReleaseTransportSigned_Internal(TCS_CONTEXT_HANDLE      hContext,
    428 				     TCS_KEY_HANDLE          hSignatureKey,
    429 				     TPM_NONCE*              AntiReplayNonce,
    430 				     TPM_AUTH*               pKeyAuth,		/* in, out */
    431 				     TPM_AUTH*               pTransAuth,	/* in, out */
    432 				     TPM_MODIFIER_INDICATOR* pbLocality,
    433 				     UINT32*                 pulCurrentTicksSize,
    434 				     BYTE**                  prgbCurrentTicks,
    435 				     UINT32*                 pulSignatureSize,
    436 				     BYTE**                  prgbSignature)
    437 {
    438 	TSS_RESULT result;
    439 	UINT32 paramSize;
    440 	UINT64 offset;
    441 	TPM_KEY_HANDLE keySlot;
    442 	BYTE txBlob[TSS_TPM_TXBLOB_SIZE];
    443 
    444 	if ((result = ctx_verify_context(hContext)))
    445 		return result;
    446 
    447 	if (pKeyAuth) {
    448 		if ((result = auth_mgr_check(hContext, &pKeyAuth->AuthHandle)))
    449 			return result;
    450 	}
    451 
    452 	if ((result = ensureKeyIsLoaded(hContext, hSignatureKey, &keySlot)))
    453 		return result;
    454 
    455 	offset = TSS_TPM_TXBLOB_HDR_LEN;
    456 	LoadBlob_UINT32(&offset, keySlot, txBlob);
    457 	LoadBlob(&offset, sizeof(TPM_NONCE), txBlob, (BYTE *)AntiReplayNonce);
    458 	if (pKeyAuth) {
    459 		LoadBlob_Auth(&offset, txBlob, pKeyAuth);
    460 		LoadBlob_Auth(&offset, txBlob, pTransAuth);
    461 		LoadBlob_Header(TPM_TAG_RQU_AUTH2_COMMAND, offset, TPM_ORD_ReleaseTransportSigned,
    462 				txBlob);
    463 	} else {
    464 		LoadBlob_Auth(&offset, txBlob, pTransAuth);
    465 		LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, offset, TPM_ORD_ReleaseTransportSigned,
    466 				txBlob);
    467 	}
    468 
    469 	if ((result = req_mgr_submit_req(txBlob)))
    470 		goto done;
    471 
    472 	if ((result = UnloadBlob_Header(txBlob, &paramSize))) {
    473 		LogDebugFn("UnloadBlob_Header failed: rc=0x%x", result);
    474 		goto done;
    475 	}
    476 
    477 	/* unconditionally disable our accounting of the session */
    478 	ctx_set_transport_disabled(hContext, NULL);
    479 
    480 	offset = TSS_TPM_TXBLOB_HDR_LEN;
    481 	UnloadBlob_UINT32(&offset, pbLocality, txBlob);
    482 
    483 	*pulCurrentTicksSize = sizeof(TPM_STRUCTURE_TAG)
    484 			       + sizeof(UINT64)
    485 			       + sizeof(UINT16)
    486 			       + sizeof(TPM_NONCE);
    487 
    488 	*prgbCurrentTicks = malloc(*pulCurrentTicksSize);
    489 	if (*prgbCurrentTicks == NULL) {
    490 		result = TCSERR(TSS_E_OUTOFMEMORY);
    491 		goto done;
    492 	}
    493 
    494 	UnloadBlob(&offset, *pulCurrentTicksSize, txBlob, *prgbCurrentTicks);
    495 	UnloadBlob_UINT32(&offset, pulSignatureSize, txBlob);
    496 
    497 	*prgbSignature = malloc(*pulSignatureSize);
    498 	if (*prgbSignature == NULL) {
    499 		free(*prgbCurrentTicks);
    500 		result = TCSERR(TSS_E_OUTOFMEMORY);
    501 		goto done;
    502 	}
    503 
    504 	UnloadBlob(&offset, *pulSignatureSize, txBlob, *prgbSignature);
    505 
    506 	if (pKeyAuth)
    507 		UnloadBlob_Auth(&offset, txBlob, pKeyAuth);
    508 	UnloadBlob_Auth(&offset, txBlob, pTransAuth);
    509 
    510 done:
    511 	auth_mgr_release_auth(pKeyAuth, NULL, hContext);
    512 	return result;
    513 }
    514