Home | History | Annotate | Line # | Download | only in tspi
      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. 2004-2007
      8  *
      9  */
     10 
     11 
     12 #include <stdlib.h>
     13 #include <stdio.h>
     14 #include <string.h>
     15 #include <time.h>
     16 #include <errno.h>
     17 #include <assert.h>
     18 
     19 #include "trousers/tss.h"
     20 #include "trousers/trousers.h"
     21 #include "trousers_types.h"
     22 #include "tcs_tsp.h"
     23 #include "spi_utils.h"
     24 #include "capabilities.h"
     25 #include "tsplog.h"
     26 #include "obj.h"
     27 #include "authsess.h"
     28 
     29 
     30 TSS_RESULT
     31 secret_PerformAuth_OIAP(TSS_HOBJECT hAuthorizedObject,
     32 			UINT32 ulPendingFn,
     33 			TSS_HPOLICY hPolicy,
     34 			TSS_BOOL cas, /* continue auth session */
     35 			TCPA_DIGEST *hashDigest,
     36 			TPM_AUTH *auth)
     37 {
     38 	TSS_RESULT result;
     39 	TSS_BOOL bExpired;
     40 	UINT32 mode;
     41 	TCPA_SECRET secret;
     42 	TSS_HCONTEXT tspContext;
     43 	TSS_RESULT (*OIAP)(TSS_HCONTEXT, TCS_AUTHHANDLE *, TPM_NONCE *); // XXX hack
     44 	TSS_RESULT (*TerminateHandle)(TSS_HCONTEXT, TCS_HANDLE); // XXX hack
     45 
     46 	/* This validates that the secret can be used */
     47 	if ((result = obj_policy_has_expired(hPolicy, &bExpired)))
     48 		return result;
     49 
     50 	if (bExpired == TRUE)
     51 		return TSPERR(TSS_E_INVALID_OBJ_ACCESS);
     52 
     53 	if ((result = obj_policy_get_tsp_context(hPolicy, &tspContext)))
     54 		return result;
     55 
     56 	if ((result = obj_policy_get_mode(hPolicy, &mode)))
     57 		return result;
     58 
     59 	if ((result = Init_AuthNonce(tspContext, cas, auth)))
     60 		return result;
     61 
     62 	/* XXX hack for opening a transport session */
     63 	if (cas) {
     64 		OIAP = RPC_OIAP;
     65 		TerminateHandle = RPC_TerminateHandle;
     66 	} else {
     67 		OIAP = TCS_API(tspContext)->OIAP;
     68 		TerminateHandle = TCS_API(tspContext)->TerminateHandle;
     69 	}
     70 
     71 	/* added retry logic */
     72 	if ((result = OIAP(tspContext, &auth->AuthHandle, &auth->NonceEven))) {
     73 		if (result == TCPA_E_RESOURCES) {
     74 			int retry = 0;
     75 			do {
     76 				/* POSIX sleep time, { secs, nanosecs } */
     77 				struct timespec t = { 0, AUTH_RETRY_NANOSECS };
     78 
     79 				nanosleep(&t, NULL);
     80 
     81 				result = OIAP(tspContext, &auth->AuthHandle, &auth->NonceEven);
     82 			} while (result == TCPA_E_RESOURCES && ++retry < AUTH_RETRY_COUNT);
     83 		}
     84 
     85 		if (result)
     86 			return result;
     87 	}
     88 
     89 	switch (mode) {
     90 		case TSS_SECRET_MODE_CALLBACK:
     91 			result = obj_policy_do_hmac(hPolicy, hAuthorizedObject,
     92 						    TRUE, ulPendingFn,
     93 						    auth->fContinueAuthSession,
     94 						    20,
     95 						    auth->NonceEven.nonce,
     96 						    auth->NonceOdd.nonce,
     97 						    NULL, NULL, 20,
     98 						    hashDigest->digest,
     99 						    (BYTE *)&auth->HMAC);
    100 			break;
    101 		case TSS_SECRET_MODE_SHA1:
    102 		case TSS_SECRET_MODE_PLAIN:
    103 		case TSS_SECRET_MODE_POPUP:
    104 			if ((result = obj_policy_get_secret(hPolicy, TR_SECRET_CTX_NOT_NEW,
    105 							    &secret)))
    106 				break;
    107 
    108 			HMAC_Auth(secret.authdata, hashDigest->digest, auth);
    109 			break;
    110 		case TSS_SECRET_MODE_NONE:
    111 			/* fall through */
    112 		default:
    113 			result = TSPERR(TSS_E_POLICY_NO_SECRET);
    114 			break;
    115 	}
    116 
    117 	if (result) {
    118 		TerminateHandle(tspContext, auth->AuthHandle);
    119 		return result;
    120 	}
    121 
    122 	return obj_policy_dec_counter(hPolicy);
    123 }
    124 #if 0
    125 TSS_RESULT
    126 secret_PerformXOR_OSAP(TSS_HPOLICY hPolicy, TSS_HPOLICY hUsagePolicy,
    127 		       TSS_HPOLICY hMigrationPolicy, TSS_HOBJECT hOSAPObject,
    128 		       UINT16 osapType, UINT32 osapData,
    129 		       TCPA_ENCAUTH * encAuthUsage, TCPA_ENCAUTH * encAuthMig,
    130 		       BYTE *sharedSecret, TPM_AUTH * auth, TCPA_NONCE * nonceEvenOSAP)
    131 {
    132 	TSS_BOOL bExpired;
    133 	TCPA_SECRET keySecret;
    134 	TCPA_SECRET usageSecret;
    135 	TCPA_SECRET migSecret = { { 0, } };
    136 	UINT32 keyMode, usageMode, migMode = 0;
    137 	TSS_RESULT result;
    138 	TSS_HCONTEXT tspContext;
    139 
    140 
    141 	if ((result = obj_policy_has_expired(hPolicy, &bExpired)))
    142 		return result;
    143 
    144 	if (bExpired == TRUE)
    145 		return TSPERR(TSS_E_INVALID_OBJ_ACCESS);
    146 
    147 	if ((result = obj_policy_has_expired(hUsagePolicy, &bExpired)))
    148 		return result;
    149 
    150 	if (bExpired == TRUE)
    151 		return TSPERR(TSS_E_INVALID_OBJ_ACCESS);
    152 
    153 	if (hMigrationPolicy) {
    154 		if ((result = obj_policy_has_expired(hMigrationPolicy, &bExpired)))
    155 			return result;
    156 
    157 		if (bExpired == TRUE)
    158 			return TSPERR(TSS_E_INVALID_OBJ_ACCESS);
    159 
    160 		if ((result = obj_policy_get_mode(hMigrationPolicy, &migMode)))
    161 			return result;
    162 	}
    163 
    164 	if ((result = obj_policy_get_tsp_context(hPolicy, &tspContext)))
    165 		return result;
    166 
    167 	if ((result = obj_policy_get_mode(hPolicy, &keyMode)))
    168 		return result;
    169 
    170 	if ((result = obj_policy_get_mode(hUsagePolicy, &usageMode)))
    171 		return result;
    172 
    173 	if (keyMode == TSS_SECRET_MODE_CALLBACK ||
    174 	    usageMode == TSS_SECRET_MODE_CALLBACK ||
    175 	    (hMigrationPolicy && migMode == TSS_SECRET_MODE_CALLBACK)) {
    176 		if (keyMode != TSS_SECRET_MODE_CALLBACK ||
    177 		    usageMode != TSS_SECRET_MODE_CALLBACK ||
    178 		    (hMigrationPolicy && migMode != TSS_SECRET_MODE_CALLBACK))
    179 			return TSPERR(TSS_E_BAD_PARAMETER);
    180 	}
    181 
    182 	if (keyMode != TSS_SECRET_MODE_CALLBACK) {
    183 		if ((result = obj_policy_get_secret(hPolicy, TR_SECRET_CTX_NOT_NEW, &keySecret)))
    184 			return result;
    185 
    186 		if ((result = obj_policy_get_secret(hUsagePolicy, TR_SECRET_CTX_NEW, &usageSecret)))
    187 			return result;
    188 
    189 		if (hMigrationPolicy) {
    190 			if ((result = obj_policy_get_secret(hMigrationPolicy, TR_SECRET_CTX_NEW,
    191 							&migSecret)))
    192 				return result;
    193 		}
    194 
    195 		if ((result = OSAP_Calc(tspContext, osapType, osapData,
    196 					keySecret.authdata, usageSecret.authdata,
    197 					migSecret.authdata, encAuthUsage,
    198 					encAuthMig, sharedSecret, auth)))
    199 			return result;
    200 	} else {
    201 		/* If the secret mode is NONE here, we don't return an error. This is
    202 		 * because there are commands such as CreateKey, which require an auth
    203 		 * session even when creating no-auth keys. A secret of all 0's will be
    204 		 * used in this case. */
    205 		if ((result = TCS_API(tspContext)->OSAP(tspContext, osapType, osapData,
    206 							&auth->NonceOdd, &auth->AuthHandle,
    207 							&auth->NonceEven, nonceEvenOSAP)))
    208 			return result;
    209 
    210 		if ((result = obj_policy_do_xor(hPolicy, hOSAPObject,
    211 						hPolicy, TRUE, 20,
    212 						auth->NonceEven.nonce, NULL,
    213 						nonceEvenOSAP->nonce,
    214 						auth->NonceOdd.nonce, 20,
    215 						encAuthUsage->authdata,
    216 						encAuthMig->authdata))) {
    217 			TCS_API(tspContext)->TerminateHandle(tspContext, auth->AuthHandle);
    218 			return result;
    219 		}
    220 	}
    221 
    222 	return TSS_SUCCESS;
    223 }
    224 
    225 TSS_RESULT
    226 secret_PerformAuth_OSAP(TSS_HOBJECT hAuthorizedObject, UINT32 ulPendingFn,
    227 			TSS_HPOLICY hPolicy, TSS_HPOLICY hUsagePolicy,
    228 			TSS_HPOLICY hMigPolicy, BYTE sharedSecret[20],
    229 			TPM_AUTH *auth, BYTE *hashDigest,
    230 			TCPA_NONCE *nonceEvenOSAP)
    231 {
    232 	TSS_RESULT result;
    233 	UINT32 keyMode, usageMode, migMode = 0;
    234 
    235 	if ((result = obj_policy_get_mode(hPolicy, &keyMode)))
    236 		return result;
    237 
    238 	if ((result = obj_policy_get_mode(hUsagePolicy, &usageMode)))
    239 		return result;
    240 
    241 	if (hMigPolicy) {
    242 		if ((result = obj_policy_get_mode(hMigPolicy, &migMode)))
    243 			return result;
    244 	}
    245 
    246 	/* ---  If any of them is a callback */
    247 	if (keyMode == TSS_SECRET_MODE_CALLBACK ||
    248 	    usageMode == TSS_SECRET_MODE_CALLBACK ||
    249 	    (hMigPolicy && migMode == TSS_SECRET_MODE_CALLBACK)) {
    250 		/* ---  And they're not all callback */
    251 		if (keyMode != TSS_SECRET_MODE_CALLBACK ||
    252 		    usageMode != TSS_SECRET_MODE_CALLBACK ||
    253 		    (hMigPolicy && migMode != TSS_SECRET_MODE_CALLBACK))
    254 			return TSPERR(TSS_E_BAD_PARAMETER);
    255 	}
    256 
    257 	if (keyMode == TSS_SECRET_MODE_CALLBACK) {
    258 		if ((result = obj_policy_do_hmac(hPolicy, hAuthorizedObject,
    259 						 TRUE, ulPendingFn,
    260 						 auth->fContinueAuthSession,
    261 						 20,
    262 						 auth->NonceEven.nonce,
    263 						 NULL,
    264 						 nonceEvenOSAP->nonce,
    265 						 auth->NonceOdd.nonce, 20,
    266 						 hashDigest,
    267 						 (BYTE *)&auth->HMAC)))
    268 			return result;
    269 	} else {
    270 		HMAC_Auth(sharedSecret, hashDigest, auth);
    271 	}
    272 
    273 	if ((result = obj_policy_dec_counter(hPolicy)))
    274 		return result;
    275 
    276 	if ((result = obj_policy_dec_counter(hUsagePolicy)))
    277 		return result;
    278 
    279 	if (hMigPolicy) {
    280 		if ((result = obj_policy_dec_counter(hMigPolicy)))
    281 			return result;
    282 	}
    283 
    284 	return TSS_SUCCESS;
    285 }
    286 
    287 TSS_RESULT
    288 secret_ValidateAuth_OSAP(TSS_HOBJECT hAuthorizedObject, UINT32 ulPendingFn,
    289 			 TSS_HPOLICY hPolicy, TSS_HPOLICY hUsagePolicy,
    290 			 TSS_HPOLICY hMigPolicy, BYTE sharedSecret[20],
    291 			 TPM_AUTH *auth, BYTE *hashDigest,
    292 			 TCPA_NONCE *nonceEvenOSAP)
    293 {
    294 	TSS_RESULT result;
    295 	UINT32 keyMode, usageMode, migMode = 0;
    296 
    297 	if ((result = obj_policy_get_mode(hPolicy, &keyMode)))
    298 		return result;
    299 
    300 	if ((result = obj_policy_get_mode(hUsagePolicy, &usageMode)))
    301 		return result;
    302 
    303 	if (hMigPolicy) {
    304 		if ((result = obj_policy_get_mode(hMigPolicy, &migMode)))
    305 			return result;
    306 	}
    307 
    308 	/* ---  If any of them is a callback */
    309 	if (keyMode == TSS_SECRET_MODE_CALLBACK ||
    310 	    usageMode == TSS_SECRET_MODE_CALLBACK ||
    311 	    (hMigPolicy && migMode == TSS_SECRET_MODE_CALLBACK)) {
    312 		/* ---  And they're not all callback */
    313 		if (keyMode != TSS_SECRET_MODE_CALLBACK ||
    314 		    usageMode != TSS_SECRET_MODE_CALLBACK ||
    315 		    (hMigPolicy && migMode != TSS_SECRET_MODE_CALLBACK))
    316 			return TSPERR(TSS_E_BAD_PARAMETER);
    317 	}
    318 
    319 	if (keyMode != TSS_SECRET_MODE_CALLBACK) {
    320 		if (validateReturnAuth(sharedSecret, hashDigest, auth))
    321 			return TSPERR(TSS_E_TSP_AUTHFAIL);
    322 	} else {
    323 		if ((result = obj_policy_do_hmac(hPolicy, hAuthorizedObject,
    324 						 FALSE, ulPendingFn,
    325 						 auth->fContinueAuthSession,
    326 						 20,
    327 						 auth->NonceEven.nonce,
    328 						 NULL,
    329 						 nonceEvenOSAP->nonce,
    330 						 auth->NonceOdd.nonce, 20,
    331 						 hashDigest,
    332 						 (BYTE *)&auth->HMAC)))
    333 			return result;
    334 	}
    335 
    336 	return TSS_SUCCESS;
    337 }
    338 #endif
    339 TSS_RESULT
    340 Init_AuthNonce(TSS_HCONTEXT tspContext, TSS_BOOL cas, TPM_AUTH * auth)
    341 {
    342 	TSS_RESULT result;
    343 
    344 	auth->fContinueAuthSession = cas;
    345 	if ((result = get_local_random(tspContext, FALSE, sizeof(TPM_NONCE),
    346 				       (BYTE **)auth->NonceOdd.nonce))) {
    347 		LogError("Failed creating random nonce");
    348 		return TSPERR(TSS_E_INTERNAL_ERROR);
    349 	}
    350 
    351 	return TSS_SUCCESS;
    352 }
    353 
    354 TSS_BOOL
    355 validateReturnAuth(BYTE *secret, BYTE *hash, TPM_AUTH *auth)
    356 {
    357 	BYTE digest[20];
    358 	/* auth is expected to have both nonces and the digest from the TPM */
    359 	memcpy(digest, &auth->HMAC, 20);
    360 	HMAC_Auth(secret, hash, auth);
    361 
    362 	return ((TSS_BOOL) (memcmp(digest, &auth->HMAC, 20) != 0));
    363 }
    364 
    365 void
    366 HMAC_Auth(BYTE * secret, BYTE * Digest, TPM_AUTH * auth)
    367 {
    368 	UINT64 offset;
    369 	BYTE Blob[61];
    370 
    371 	offset = 0;
    372 	Trspi_LoadBlob(&offset, 20, Blob, Digest);
    373 	Trspi_LoadBlob(&offset, 20, Blob, auth->NonceEven.nonce);
    374 	Trspi_LoadBlob(&offset, 20, Blob, auth->NonceOdd.nonce);
    375 	Blob[offset++] = auth->fContinueAuthSession;
    376 
    377 	Trspi_HMAC(TSS_HASH_SHA1, 20, secret, offset, Blob, (BYTE *)&auth->HMAC);
    378 }
    379 
    380 TSS_RESULT
    381 OSAP_Calc(TSS_HCONTEXT tspContext, UINT16 EntityType, UINT32 EntityValue,
    382 	  BYTE * authSecret, BYTE * usageSecret, BYTE * migSecret,
    383 	  TCPA_ENCAUTH * encAuthUsage, TCPA_ENCAUTH * encAuthMig,
    384 	  BYTE * sharedSecret, TPM_AUTH * auth)
    385 {
    386 	TSS_RESULT rc;
    387 	TCPA_NONCE nonceEvenOSAP;
    388 	UINT64 offset;
    389 	BYTE hmacBlob[0x200];
    390 	BYTE hashBlob[0x200];
    391 	BYTE xorUsageAuth[20];
    392 	BYTE xorMigAuth[20];
    393 	UINT32 i;
    394 
    395 	if ((rc = get_local_random(tspContext, FALSE, sizeof(TPM_NONCE),
    396 				   (BYTE **)auth->NonceOdd.nonce))) {
    397 		LogError("Failed creating random nonce");
    398 		return TSPERR(TSS_E_INTERNAL_ERROR);
    399 	}
    400 	auth->fContinueAuthSession = 0x00;
    401 
    402 	if ((rc = TCS_API(tspContext)->OSAP(tspContext, EntityType, EntityValue, &auth->NonceOdd,
    403 					    &auth->AuthHandle, &auth->NonceEven, &nonceEvenOSAP))) {
    404 		if (rc == TCPA_E_RESOURCES) {
    405 			int retry = 0;
    406 			do {
    407 				/* POSIX sleep time, { secs, nanosecs } */
    408 				struct timespec t = { 0, AUTH_RETRY_NANOSECS };
    409 
    410 				nanosleep(&t, NULL);
    411 
    412 				rc = TCS_API(tspContext)->OSAP(tspContext, EntityType, EntityValue,
    413 							       &auth->NonceOdd, &auth->AuthHandle,
    414 							       &auth->NonceEven, &nonceEvenOSAP);
    415 			} while (rc == TCPA_E_RESOURCES && ++retry < AUTH_RETRY_COUNT);
    416 		}
    417 
    418 		if (rc)
    419 			return rc;
    420 	}
    421 
    422 	offset = 0;
    423 	Trspi_LoadBlob(&offset, 20, hmacBlob, nonceEvenOSAP.nonce);
    424 	Trspi_LoadBlob(&offset, 20, hmacBlob, auth->NonceOdd.nonce);
    425 
    426 	Trspi_HMAC(TSS_HASH_SHA1, 20, authSecret, offset, hmacBlob, sharedSecret);
    427 
    428 	offset = 0;
    429 	Trspi_LoadBlob(&offset, 20, hashBlob, sharedSecret);
    430 	Trspi_LoadBlob(&offset, 20, hashBlob, auth->NonceEven.nonce);
    431 
    432 	if ((rc = Trspi_Hash(TSS_HASH_SHA1, offset, hashBlob, xorUsageAuth)))
    433 		return rc;
    434 
    435 	offset = 0;
    436 	Trspi_LoadBlob(&offset, 20, hashBlob, sharedSecret);
    437 	Trspi_LoadBlob(&offset, 20, hashBlob, auth->NonceOdd.nonce);
    438 	if ((rc = Trspi_Hash(TSS_HASH_SHA1, offset, hashBlob, xorMigAuth)))
    439 		return rc;
    440 
    441 	for (i = 0; i < sizeof(TCPA_ENCAUTH); i++)
    442 		encAuthUsage->authdata[i] = usageSecret[i] ^ xorUsageAuth[i];
    443 	for (i = 0; i < sizeof(TCPA_ENCAUTH); i++)
    444 		encAuthMig->authdata[i] = migSecret[i] ^ xorMigAuth[i];
    445 
    446 	return TSS_SUCCESS;
    447 }
    448 
    449 TSS_RESULT
    450 obj_policy_validate_auth_oiap(TSS_HPOLICY hPolicy, TCPA_DIGEST *hashDigest, TPM_AUTH *auth)
    451 {
    452 	TSS_RESULT result = TSS_SUCCESS;
    453 	struct tsp_object *obj;
    454 	struct tr_policy_obj *policy;
    455 	BYTE wellKnown[TCPA_SHA1_160_HASH_LEN] = TSS_WELL_KNOWN_SECRET;
    456 
    457 	if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL)
    458 		return TSPERR(TSS_E_INVALID_HANDLE);
    459 
    460 	policy = (struct tr_policy_obj *)obj->data;
    461 
    462 	switch (policy->SecretMode) {
    463 		case TSS_SECRET_MODE_CALLBACK:
    464 			result = policy->Tspicb_CallbackHMACAuth(
    465 					policy->hmacAppData,
    466 					hPolicy,
    467 					0,
    468 					auth->fContinueAuthSession,
    469 					FALSE,
    470 					20,
    471 					auth->NonceEven.nonce,
    472 					auth->NonceOdd.nonce,
    473 					NULL, NULL, 20,
    474 					hashDigest->digest,
    475 					(BYTE *)&auth->HMAC);
    476 			break;
    477 		case TSS_SECRET_MODE_SHA1:
    478 		case TSS_SECRET_MODE_PLAIN:
    479 		case TSS_SECRET_MODE_POPUP:
    480 			if (validateReturnAuth(policy->Secret, hashDigest->digest, auth))
    481 				result = TSPERR(TSS_E_TSP_AUTHFAIL);
    482 			break;
    483 		case TSS_SECRET_MODE_NONE:
    484 			if (validateReturnAuth(wellKnown, hashDigest->digest, auth))
    485 				result = TSPERR(TSS_E_TSP_AUTHFAIL);
    486 			break;
    487 		default:
    488 			result = TSPERR(TSS_E_POLICY_NO_SECRET);
    489 			break;
    490 	}
    491 
    492 	obj_list_put(&policy_list);
    493 
    494 	return result;
    495 }
    496 
    497 #if 0
    498 TSS_RESULT
    499 authsess_oiap_get(TSS_HOBJECT obj, TPM_COMMAND_CODE ord, TPM_DIGEST *digest, TPM_AUTH *auth)
    500 {
    501 	TSS_RESULT result = TSS_SUCCESS;
    502 	TSS_BOOL bExpired;
    503 	UINT32 mode;
    504 	TPM_SECRET secret;
    505 	TSS_HCONTEXT tspContext;
    506 	TSS_RESULT (*OIAP)(TSS_HCONTEXT, TCS_AUTHHANDLE *, TPM_NONCE *); // XXX hack
    507 	TSS_RESULT (*TerminateHandle)(TSS_HCONTEXT, TCS_HANDLE); // XXX hack
    508 
    509 
    510 	if (obj_is_tpm(obj))
    511 		result = obj_tpm_get_tsp_context(obj, hContext);
    512 	else if (obj_is_rsakey(obj))
    513 		result = obj_rsakey_get_tsp_context(obj, hContext);
    514 	else if (obj_is_encdata(obj))
    515 		result = obj_encdata_get_tsp_context(obj, hContext);
    516 	else if (obj_is_nvstore(obj))
    517 		result = obj_nvstore_get_tsp_context(obj, hContext);
    518 	else
    519 		result = TSPERR(TSS_E_INVALID_HANDLE);
    520 
    521 #if 0
    522 	/* This validates that the secret can be used */
    523 	if ((result = obj_policy_has_expired(hPolicy, &bExpired)))
    524 		return result;
    525 
    526 	if (bExpired == TRUE)
    527 		return TSPERR(TSS_E_INVALID_OBJ_ACCESS);
    528 
    529 	if ((result = obj_policy_get_tsp_context(hPolicy, &tspContext)))
    530 		return result;
    531 
    532 	if ((result = obj_policy_get_mode(hPolicy, &mode)))
    533 		return result;
    534 #else
    535 	if ((result = obj_policy_get_authsess_params()))
    536 		return result;
    537 #endif
    538 	if ((result = Init_AuthNonce(tspContext, cas, auth)))
    539 		return result;
    540 
    541 	/* XXX hack for opening a transport session */
    542 	if (cas) {
    543 		OIAP = RPC_OIAP;
    544 		TerminateHandle = RPC_TerminateHandle;
    545 	} else {
    546 		OIAP = TCS_API(tspContext)->OIAP;
    547 		TerminateHandle = TCS_API(tspContext)->TerminateHandle;
    548 	}
    549 
    550 	/* added retry logic */
    551 	if ((result = OIAP(tspContext, &auth->AuthHandle, &auth->NonceEven))) {
    552 		if (result == TCPA_E_RESOURCES) {
    553 			int retry = 0;
    554 			do {
    555 				/* POSIX sleep time, { secs, nanosecs } */
    556 				struct timespec t = { 0, AUTH_RETRY_NANOSECS };
    557 
    558 				nanosleep(&t, NULL);
    559 
    560 				result = OIAP(tspContext, &auth->AuthHandle, &auth->NonceEven);
    561 			} while (result == TCPA_E_RESOURCES && ++retry < AUTH_RETRY_COUNT);
    562 		}
    563 
    564 		if (result)
    565 			return result;
    566 	}
    567 
    568 	switch (mode) {
    569 		case TSS_SECRET_MODE_CALLBACK:
    570 			result = obj_policy_do_hmac(hPolicy, hAuthorizedObject,
    571 						    TRUE, ulPendingFn,
    572 						    auth->fContinueAuthSession,
    573 						    20,
    574 						    auth->NonceEven.nonce,
    575 						    auth->NonceOdd.nonce,
    576 						    NULL, NULL, 20,
    577 						    hashDigest->digest,
    578 						    (BYTE *)&auth->HMAC);
    579 			break;
    580 		case TSS_SECRET_MODE_SHA1:
    581 		case TSS_SECRET_MODE_PLAIN:
    582 		case TSS_SECRET_MODE_POPUP:
    583 			if ((result = obj_policy_get_secret(hPolicy, TR_SECRET_CTX_NOT_NEW,
    584 							    &secret)))
    585 				break;
    586 
    587 			HMAC_Auth(secret.authdata, hashDigest->digest, auth);
    588 			break;
    589 		case TSS_SECRET_MODE_NONE:
    590 			/* fall through */
    591 		default:
    592 			result = TSPERR(TSS_E_POLICY_NO_SECRET);
    593 			break;
    594 	}
    595 
    596 	if (result) {
    597 		TerminateHandle(tspContext, auth->AuthHandle);
    598 		return result;
    599 	}
    600 
    601 	return obj_policy_dec_counter(hPolicy);
    602 }
    603 
    604 TSS_RESULT
    605 authsess_oiap_put(TPM_AUTH *auth)
    606 {
    607 }
    608 #endif
    609 
    610 #ifdef TSS_BUILD_DELEGATION
    611 TSS_RESULT
    612 authsess_do_dsap(struct authsess *sess)
    613 {
    614 	TSS_RESULT result;
    615 
    616 	if ((result = TCS_API(sess->tspContext)->DSAP(sess->tspContext, sess->entity_type,
    617 						      sess->obj_parent, &sess->nonceOddxSAP,
    618 						      sess->entityValueSize, sess->entityValue,
    619 						      &sess->pAuth->AuthHandle,
    620 						      &sess->pAuth->NonceEven,
    621 						      &sess->nonceEvenxSAP))) {
    622 		if (result == TCPA_E_RESOURCES) {
    623 			int retry = 0;
    624 			do {
    625 				/* POSIX sleep time, { secs, nanosecs } */
    626 				struct timespec t = { 0, AUTH_RETRY_NANOSECS };
    627 
    628 				nanosleep(&t, NULL);
    629 
    630 				result = TCS_API(sess->tspContext)->DSAP(sess->tspContext,
    631 									 sess->entity_type,
    632 									 sess->obj_parent,
    633 									 &sess->nonceOddxSAP,
    634 									 sess->entityValueSize,
    635 									 sess->entityValue,
    636 									 &sess->pAuth->AuthHandle,
    637 									 &sess->pAuth->NonceEven,
    638 									 &sess->nonceEvenxSAP);
    639 			} while (result == TCPA_E_RESOURCES && ++retry < AUTH_RETRY_COUNT);
    640 		}
    641 	}
    642 
    643 	return result;
    644 }
    645 #endif
    646 
    647 TSS_RESULT
    648 authsess_do_osap(struct authsess *sess)
    649 {
    650 	TSS_RESULT result;
    651 
    652 	if ((result = TCS_API(sess->tspContext)->OSAP(sess->tspContext, sess->entity_type,
    653 						      sess->obj_parent, &sess->nonceOddxSAP,
    654 						      &sess->pAuth->AuthHandle,
    655 						      &sess->pAuth->NonceEven,
    656 						      &sess->nonceEvenxSAP))) {
    657 		if (result == TCPA_E_RESOURCES) {
    658 			int retry = 0;
    659 			do {
    660 				/* POSIX sleep time, { secs, nanosecs } */
    661 				struct timespec t = { 0, AUTH_RETRY_NANOSECS };
    662 
    663 				nanosleep(&t, NULL);
    664 
    665 				result = TCS_API(sess->tspContext)->OSAP(sess->tspContext,
    666 									 sess->entity_type,
    667 									 sess->obj_parent,
    668 									 &sess->nonceOddxSAP,
    669 									 &sess->pAuth->AuthHandle,
    670 									 &sess->pAuth->NonceEven,
    671 									 &sess->nonceEvenxSAP);
    672 			} while (result == TCPA_E_RESOURCES && ++retry < AUTH_RETRY_COUNT);
    673 		}
    674 	}
    675 
    676 	return result;
    677 }
    678 
    679 TSS_RESULT
    680 authsess_callback_xor(PVOID lpAppData,
    681 		      TSS_HOBJECT hOSAPObject,
    682 		      TSS_HOBJECT hObject,
    683 		      TSS_FLAG PurposeSecret,
    684 		      UINT32 ulSizeNonces,
    685 		      BYTE *rgbNonceEven,
    686 		      BYTE *rgbNonceOdd,
    687 		      BYTE *rgbNonceEvenOSAP,
    688 		      BYTE *rgbNonceOddOSAP,
    689 		      UINT32 ulSizeEncAuth,
    690 		      BYTE *rgbEncAuthUsage,
    691 		      BYTE *rgbEncAuthMigration)
    692 {
    693 	TSS_RESULT result;
    694 	BYTE xorUseAuth[sizeof(TPM_DIGEST)];
    695 	BYTE xorMigAuth[sizeof(TPM_DIGEST)];
    696 	Trspi_HashCtx hashCtx;
    697 	UINT32 i;
    698 	struct authsess *sess = (struct authsess *)lpAppData;
    699 
    700 	/* sess->sharedSecret was calculated in authsess_xsap_init */
    701 
    702 	result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
    703 	result |= Trspi_Hash_SECRET(&hashCtx, sess->sharedSecret.digest);
    704 	result |= Trspi_Hash_NONCE(&hashCtx, rgbNonceEven);
    705 	if ((result |= Trspi_HashFinal(&hashCtx, xorUseAuth)))
    706 		return result;
    707 
    708 	for (i = 0; i < ulSizeEncAuth; i++)
    709 		rgbEncAuthUsage[i] ^= xorUseAuth[i];
    710 
    711 	result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
    712 	result |= Trspi_Hash_SECRET(&hashCtx, sess->sharedSecret.digest);
    713 	result |= Trspi_Hash_NONCE(&hashCtx, rgbNonceOdd);
    714 	if ((result |= Trspi_HashFinal(&hashCtx, xorMigAuth)))
    715 		return result;
    716 
    717 	for (i = 0; i < ulSizeEncAuth; i++)
    718 		rgbEncAuthMigration[i] ^= xorMigAuth[i];
    719 
    720 	return TSS_SUCCESS;
    721 }
    722 
    723 TSS_RESULT
    724 authsess_callback_hmac(PVOID lpAppData,
    725 		       TSS_HOBJECT hAuthorizedObject,
    726 		       TSS_BOOL ReturnOrVerify,
    727 		       UINT32 ulPendingFunction,
    728 		       TSS_BOOL ContinueUse,
    729 		       UINT32 ulSizeNonces,
    730 		       BYTE *rgbNonceEven,
    731 		       BYTE *rgbNonceOdd,
    732 		       BYTE *rgbNonceEvenOSAP,
    733 		       BYTE *rgbNonceOddOSAP,
    734 		       UINT32 ulSizeDigestHmac,
    735 		       BYTE *rgbParamDigest,
    736 		       BYTE *rgbHmacData)
    737 {
    738 	struct authsess *sess = (struct authsess *)lpAppData;
    739 	TSS_RESULT result = TSS_SUCCESS;
    740 	UINT64 offset;
    741 	BYTE Blob[61];
    742 
    743 	offset = 0;
    744 	Trspi_LoadBlob(&offset, ulSizeDigestHmac, Blob, rgbParamDigest);
    745 	Trspi_LoadBlob(&offset, ulSizeNonces, Blob, rgbNonceEven);
    746 	Trspi_LoadBlob(&offset, ulSizeNonces, Blob, rgbNonceOdd);
    747 	Blob[offset++] = ContinueUse;
    748 
    749 	if (ReturnOrVerify) {
    750 		Trspi_HMAC(TSS_HASH_SHA1, ulSizeDigestHmac, sess->sharedSecret.digest, offset, Blob,
    751 			   rgbHmacData);
    752 	} else {
    753 		TPM_HMAC hmacVerify;
    754 
    755 		Trspi_HMAC(TSS_HASH_SHA1, ulSizeDigestHmac, sess->sharedSecret.digest, offset, Blob,
    756 			   hmacVerify.digest);
    757 		result = memcmp(rgbHmacData, hmacVerify.digest, ulSizeDigestHmac);
    758 		if (result)
    759 			result = TPM_E_AUTHFAIL;
    760 	}
    761 
    762 	return result;
    763 }
    764 
    765 /* Create an OSAP session. @requirements is used in different ways depending on the command to
    766  * indicate whether we should require a policy or auth value */
    767 TSS_RESULT
    768 authsess_xsap_init(TSS_HCONTEXT     tspContext,
    769 		   TSS_HOBJECT	    obj_parent,
    770 		   TSS_HOBJECT      obj_child,
    771 		   TSS_BOOL	    requirements,
    772 		   TPM_COMMAND_CODE command,
    773 		   TPM_ENTITY_TYPE  entity_type,
    774 		   struct authsess  **xsess)
    775 {
    776 	TSS_RESULT result;
    777 	TSS_BOOL authdatausage = FALSE, req_auth = TRUE, get_child_auth = TRUE, secret_set = FALSE;
    778 	BYTE hmacBlob[2 * sizeof(TPM_DIGEST)];
    779 	UINT64 offset;
    780 	TSS_BOOL new_secret = TR_SECRET_CTX_NOT_NEW;
    781 	struct authsess *sess;
    782 
    783 	if ((sess = calloc(1, sizeof(struct authsess))) == NULL) {
    784 		LogError("malloc of %zd bytes failed", sizeof(struct authsess));
    785 		return TSPERR(TSS_E_OUTOFMEMORY);
    786 	}
    787 
    788 	switch (command) {
    789 	/* Parent is Key for the cases below */
    790 	case TPM_ORD_Delegate_CreateKeyDelegation:
    791 	case TPM_ORD_CreateWrapKey:
    792 	case TPM_ORD_CMK_CreateKey:
    793 	case TPM_ORD_Seal:
    794 	case TPM_ORD_Sealx:
    795 	case TPM_ORD_Unseal:
    796 	case TPM_ORD_ChangeAuth:
    797 		if ((result = obj_rsakey_get_policy(obj_parent, TSS_POLICY_USAGE,
    798 						    &sess->hUsageParent, NULL)))
    799 			goto error;
    800 		break;
    801 	/* Parent is TPM for the cases below */
    802 	case TPM_ORD_Delegate_CreateOwnerDelegation:
    803 		req_auth = FALSE;
    804 		/* fall through */
    805 	case TPM_ORD_MakeIdentity:
    806 	case TPM_ORD_NV_DefineSpace:
    807 		if ((result = obj_tpm_get_policy(obj_parent, TSS_POLICY_USAGE,
    808 						 &sess->hUsageParent)))
    809 			goto error;
    810 		break;
    811 	case TPM_ORD_ChangeAuthOwner:
    812 		/* Special case, ChangeAuthOwner is used to change Owner and SRK auth */
    813 		if (obj_is_rsakey(obj_parent)) {
    814 			if ((result = obj_rsakey_get_policy(obj_parent, TSS_POLICY_USAGE,
    815 							    &sess->hUsageParent, NULL)))
    816 				goto error;
    817 		} else {
    818 			if ((result = obj_tpm_get_policy(obj_parent, TSS_POLICY_USAGE,
    819 							 &sess->hUsageParent)))
    820 				goto error;
    821 		}
    822 		break;
    823 	default:
    824 		result = TSPERR(TSS_E_INTERNAL_ERROR);
    825 		goto error;
    826 	}
    827 
    828 	if (requirements && !sess->hUsageParent) {
    829 		result = TSPERR(TSS_E_TSP_AUTHREQUIRED);
    830 		goto error;
    831 	}
    832 
    833 	if (sess->hUsageParent) {
    834 		/* These are trousers callback functions which will be used to process the auth
    835 		 * session. If the policy type is callback for hUsageParent, they will be
    836 		 * overwritten by the application defined callback functions in the policy */
    837 		sess->cb_xor.callback = authsess_callback_xor;
    838 		sess->cb_xor.appData = (PVOID)sess;
    839 		sess->cb_hmac.callback = authsess_callback_hmac;
    840 		sess->cb_hmac.appData = (PVOID)sess;
    841 
    842 		/* XXX the parent object doesn't always hold the callbacks */
    843 		if ((result = obj_policy_get_xsap_params(sess->hUsageParent, command,
    844 							 &sess->entity_type, &sess->entityValueSize,
    845 							 &sess->entityValue,
    846 							 sess->parentSecret.authdata, &sess->cb_xor,
    847 							 &sess->cb_hmac, NULL, &sess->parentMode,
    848 							 new_secret)))
    849 			goto error;
    850 	} else
    851 		sess->parentMode = TSS_SECRET_MODE_NONE;
    852 
    853 	switch (command) {
    854 	/* Child is a Key object */
    855 	case TPM_ORD_CreateWrapKey:
    856 	case TPM_ORD_CMK_CreateKey:
    857 		if ((result = obj_rsakey_get_policies(obj_child, &sess->hUsageChild,
    858 						      &sess->hMigChild, &authdatausage)))
    859 			goto error;
    860 
    861 		if (authdatausage && !sess->hUsageChild) {
    862 			result = TSPERR(TSS_E_TSP_AUTHREQUIRED);
    863 			goto error;
    864 		}
    865 
    866 		if (obj_rsakey_is_migratable(obj_child)) {
    867 			if (!sess->hMigChild) {
    868 				result = TSPERR(TSS_E_KEY_NO_MIGRATION_POLICY);
    869 				goto error;
    870 			}
    871 
    872 			if ((result = obj_policy_get_xsap_params(sess->hMigChild, 0, NULL, NULL,
    873 								 NULL, sess->encAuthMig.authdata,
    874 								 NULL, NULL, NULL, &sess->mMode,
    875 								 new_secret)))
    876 				goto error;
    877 		}
    878 
    879 		if ((result = obj_rsakey_get_tcs_handle(obj_parent, &sess->obj_parent)))
    880 			goto error;
    881 		break;
    882 	/* Child is an Encdata object */
    883 	case TPM_ORD_Unseal:
    884 #ifdef TSS_BUILD_SEALX
    885 	case TPM_ORD_Sealx:
    886 		/* These may be overwritten down below, when obj_policy_get_xsap_params is called
    887 		 * on the child usage policy */
    888 		sess->cb_sealx.callback = sealx_mask_cb;
    889 		sess->cb_sealx.appData = (PVOID)sess;
    890 		/* fall through */
    891 #endif
    892 	case TPM_ORD_Seal:
    893 		if ((result = obj_encdata_get_policy(obj_child, TSS_POLICY_USAGE,
    894 						     &sess->hUsageChild)))
    895 			goto error;
    896 
    897 		if ((result = obj_rsakey_get_tcs_handle(obj_parent, &sess->obj_parent)))
    898 			goto error;
    899 		break;
    900 #ifdef TSS_BUILD_NV
    901 	/* Child is an NV object */
    902 	case TPM_ORD_NV_DefineSpace:
    903 		/* The requirements variable tells us whether nv object auth is required */
    904 		req_auth = requirements;
    905 
    906 		if (req_auth) {
    907 			if (sess->parentMode == TSS_SECRET_MODE_NONE) {
    908 				result = TSPERR(TSS_E_TSP_AUTHREQUIRED);
    909 				goto error;
    910 			}
    911 
    912 			if ((result = obj_nvstore_get_policy(obj_child, TSS_POLICY_USAGE,
    913 							     &sess->hUsageChild)))
    914 				goto error;
    915 
    916 			/* According to the spec, we must fall back on the TSP context's policy for
    917 			 * auth if none is set in the NV object */
    918 			if (!sess->hUsageChild) {
    919 				if ((result = obj_context_get_policy(tspContext, TSS_POLICY_USAGE,
    920 								     &sess->hUsageChild)))
    921 					goto error;
    922 			}
    923 
    924 			if ((result = obj_policy_is_secret_set(sess->hUsageChild, &secret_set)))
    925 				goto error;
    926 
    927 			if (!secret_set) {
    928 				result = TSPERR(TSS_E_TSP_AUTHREQUIRED);
    929 				goto error;
    930 			}
    931 		} else {
    932 			/* In this case, the TPM is owned, but we're creating a no-auth NV area */
    933 			get_child_auth = FALSE;
    934 		}
    935 
    936 		break;
    937 #endif
    938 	/* Child is a Key object */
    939 	case TPM_ORD_MakeIdentity:
    940 		if ((result = obj_rsakey_get_policy(obj_child, TSS_POLICY_USAGE,
    941 						    &sess->hUsageChild, NULL)))
    942 			goto error;
    943 		break;
    944 	/* Child is a Policy object */
    945 	case TPM_ORD_Delegate_CreateKeyDelegation:
    946 	case TPM_ORD_ChangeAuth:
    947 		if ((result = obj_rsakey_get_tcs_handle(obj_parent, &sess->obj_parent)))
    948 			goto error;
    949 		/* fall through */
    950 	case TPM_ORD_Delegate_CreateOwnerDelegation:
    951 	case TPM_ORD_ChangeAuthOwner:
    952 		sess->hUsageChild = obj_child;
    953 		new_secret = TR_SECRET_CTX_NEW;
    954 		break;
    955 	default:
    956 		result = TSPERR(TSS_E_INTERNAL_ERROR);
    957 		goto error;
    958 	}
    959 
    960 	/* If req_auth is FALSE here, we don't actually need to set up an auth session, so returning
    961 	 * is OK.  At this point, authsess->pAuth is NULL, so the TCS API will not get any
    962 	 * authdata. */
    963 	if (req_auth == FALSE && sess->parentMode == TSS_SECRET_MODE_NONE)
    964 		goto done;
    965 
    966 	if (get_child_auth) {
    967 		if ((result = obj_policy_get_xsap_params(sess->hUsageChild, 0, 0, NULL, NULL,
    968 							 sess->encAuthUse.authdata, NULL, NULL,
    969 							 &sess->cb_sealx, &sess->uMode,
    970 							 new_secret)))
    971 			goto error;
    972 	}
    973 
    974 	if ((result = get_local_random(tspContext, FALSE, sizeof(TPM_NONCE),
    975 				       (BYTE **)sess->nonceOddxSAP.nonce)))
    976 		goto error;
    977 
    978 	sess->obj_child = obj_child;
    979 	sess->tspContext = tspContext;
    980 	sess->pAuth = &sess->auth;
    981 	sess->command = command;
    982 
    983 #ifdef TSS_BUILD_DELEGATION
    984 	/* if entityValue is set, we have a custom entity, i.e. delegation blob or row */
    985 	if (sess->entityValue) {
    986 		/* DSAP's entity type was pulled from the policy in the authsess_xsap_init call
    987 		 * above */
    988 		if ((result = authsess_do_dsap(sess)))
    989 			goto error;
    990 	}
    991 #endif
    992 	if (!sess->entityValue) {
    993 		sess->entity_type = entity_type;
    994 		if ((result = authsess_do_osap(sess)))
    995 			goto error;
    996 	}
    997 
    998 	if ((result = get_local_random(tspContext, FALSE, sizeof(TPM_NONCE),
    999 				       (BYTE **)sess->auth.NonceOdd.nonce)))
   1000 		goto error;
   1001 
   1002 	/* We have both OSAP nonces, so calculate the shared secret if we're responsible for it */
   1003 	if (sess->parentMode != TSS_SECRET_MODE_CALLBACK) {
   1004 		offset = 0;
   1005 		Trspi_LoadBlob(&offset, sizeof(TPM_NONCE), hmacBlob, sess->nonceEvenxSAP.nonce);
   1006 		Trspi_LoadBlob(&offset, sizeof(TPM_NONCE), hmacBlob, sess->nonceOddxSAP.nonce);
   1007 
   1008 		if ((result = Trspi_HMAC(TSS_HASH_SHA1, sizeof(TPM_ENCAUTH),
   1009 					 sess->parentSecret.authdata, offset, hmacBlob,
   1010 					 sess->sharedSecret.digest)))
   1011 			goto error;
   1012 	}
   1013 
   1014 	/* XXX What does a PurposeSecret of TRUE mean here? */
   1015 	if ((result =
   1016 	     ((TSS_RESULT (*)(PVOID, TSS_HOBJECT, TSS_HOBJECT, TSS_FLAG,
   1017 	       UINT32, BYTE *, BYTE *, BYTE *, BYTE *, UINT32, BYTE *,
   1018 	       BYTE *))sess->cb_xor.callback)(sess->cb_xor.appData, sess->hUsageParent,
   1019 					      sess->hUsageChild, TRUE, sizeof(TPM_DIGEST),
   1020 					      sess->auth.NonceEven.nonce, sess->auth.NonceOdd.nonce,
   1021 					      sess->nonceEvenxSAP.nonce, sess->nonceOddxSAP.nonce,
   1022 					      sizeof(TPM_ENCAUTH), sess->encAuthUse.authdata,
   1023 					      sess->encAuthMig.authdata)))
   1024 		return result;
   1025 
   1026 done:
   1027 	*xsess = sess;
   1028 
   1029 	return TSS_SUCCESS;
   1030 error:
   1031 	free(sess);
   1032 	return result;
   1033 }
   1034 
   1035 TSS_RESULT
   1036 authsess_xsap_hmac(struct authsess *sess, TPM_DIGEST *digest)
   1037 {
   1038 	TSS_RESULT result;
   1039 
   1040 	/* If no auth session was established using this authsess object, return success */
   1041 	if (!sess->pAuth)
   1042 		return TSS_SUCCESS;
   1043 
   1044 	/* XXX Placeholder for future continueAuthSession support:
   1045 	 *      conditionally bump NonceOdd if continueAuthSession == TRUE here
   1046 	 */
   1047 
   1048 	if ((result =
   1049 	    ((TSS_RESULT (*)(PVOID, TSS_HOBJECT, TSS_BOOL,
   1050 	      UINT32, TSS_BOOL, UINT32, BYTE *, BYTE *,
   1051 	      BYTE *, BYTE *, UINT32, BYTE *,
   1052 	      BYTE *))sess->cb_hmac.callback)(sess->cb_hmac.appData,
   1053 					      sess->hUsageParent, TRUE, sess->command,
   1054 					      sess->auth.fContinueAuthSession, sizeof(TPM_NONCE),
   1055 					      sess->auth.NonceEven.nonce,
   1056 					      sess->auth.NonceOdd.nonce,
   1057 					      sess->nonceEvenxSAP.nonce,
   1058 					      sess->nonceOddxSAP.nonce, sizeof(TPM_DIGEST),
   1059 					      digest->digest, sess->auth.HMAC.authdata)))
   1060 		return result;
   1061 
   1062 	if (sess->hUsageParent)
   1063 		obj_policy_dec_counter(sess->hUsageParent);
   1064 
   1065 	if (sess->hUsageChild)
   1066 		obj_policy_dec_counter(sess->hUsageChild);
   1067 
   1068 	if (sess->hMigChild)
   1069 		obj_policy_dec_counter(sess->hMigChild);
   1070 
   1071 	return TSS_SUCCESS;
   1072 }
   1073 
   1074 TSS_RESULT
   1075 authsess_xsap_verify(struct authsess *sess, TPM_DIGEST *digest)
   1076 {
   1077 	/* If no auth session was established using this authsess object, return success */
   1078 	if (!sess->pAuth)
   1079 		return TSS_SUCCESS;
   1080 
   1081 	return ((TSS_RESULT (*)(PVOID, TSS_HOBJECT, TSS_BOOL,
   1082 		 UINT32, TSS_BOOL, UINT32, BYTE *, BYTE *,
   1083 		 BYTE *, BYTE *, UINT32, BYTE *,
   1084 		 BYTE *))sess->cb_hmac.callback)(sess->cb_hmac.appData,
   1085 						 sess->hUsageParent, FALSE, sess->command,
   1086 						 sess->auth.fContinueAuthSession, sizeof(TPM_NONCE),
   1087 						 sess->auth.NonceEven.nonce,
   1088 						 sess->auth.NonceOdd.nonce,
   1089 						 sess->nonceEvenxSAP.nonce,
   1090 						 sess->nonceOddxSAP.nonce, sizeof(TPM_DIGEST),
   1091 						 digest->digest, sess->auth.HMAC.authdata);
   1092 }
   1093 
   1094 TSS_RESULT
   1095 __tspi_free_resource(TSS_HCONTEXT tspContext, UINT32 handle, UINT32 resourceType)
   1096 {
   1097 	TSS_RESULT result = TSS_SUCCESS;
   1098 #ifdef TSS_BUILD_TSS12
   1099 	UINT32 version = 0;
   1100 
   1101 	if ((result = obj_context_get_tpm_version(tspContext, &version)))
   1102 		return result;
   1103 
   1104 	if (version == 2) {
   1105 		return TCS_API(tspContext)->FlushSpecific(tspContext, handle, resourceType);
   1106 	}
   1107 #endif
   1108 
   1109 	switch (resourceType) {
   1110 		case TPM_RT_KEY:
   1111 			result = TCS_API(tspContext)->EvictKey(tspContext, handle);
   1112 			break;
   1113 		case TPM_RT_AUTH:
   1114 			result = TCS_API(tspContext)->TerminateHandle(tspContext, handle);
   1115 			break;
   1116 		default:
   1117 			LogDebugFn("Trying to free TPM 1.2 resource type 0x%x on 1.1 TPM!",
   1118 				   resourceType);
   1119 			result = TSPERR(TSS_E_INTERNAL_ERROR);
   1120 			break;
   1121 	}
   1122 
   1123 	return result;
   1124 }
   1125 
   1126 void
   1127 authsess_free(struct authsess *xsap)
   1128 {
   1129 	if (xsap) {
   1130 		if (xsap->auth.AuthHandle && xsap->auth.fContinueAuthSession)
   1131 			(void)__tspi_free_resource(xsap->tspContext, xsap->auth.AuthHandle, TPM_RT_AUTH);
   1132 
   1133 		free(xsap->entityValue);
   1134 		free(xsap);
   1135 		xsap = NULL;
   1136 	}
   1137 }
   1138 
   1139 #ifdef TSS_BUILD_TRANSPORT
   1140 TSS_RESULT
   1141 Transport_OIAP(TSS_HCONTEXT    tspContext,   /* in */
   1142 	       TCS_AUTHHANDLE* authHandle,   /* out */
   1143 	       TPM_NONCE*      nonce0)       /* out */
   1144 {
   1145 	TSS_RESULT result;
   1146 	UINT32 decLen = 0;
   1147 	BYTE *dec = NULL;
   1148 	UINT64 offset;
   1149 	TCS_HANDLE handlesLen = 0;
   1150 
   1151 	if ((result = obj_context_transport_init(tspContext)))
   1152 		return result;
   1153 
   1154 	LogDebugFn("Executing in a transport session");
   1155 
   1156 	if ((result = obj_context_transport_execute(tspContext, TPM_ORD_OIAP, 0, NULL, NULL,
   1157 						    &handlesLen, NULL, NULL, NULL, &decLen, &dec)))
   1158 		return result;
   1159 
   1160 	if (decLen != sizeof(TCS_AUTHHANDLE) + sizeof(TPM_NONCE))
   1161 		return TSPERR(TSS_E_INTERNAL_ERROR);
   1162 
   1163 	offset = 0;
   1164 	Trspi_UnloadBlob_UINT32(&offset, authHandle, dec);
   1165 	Trspi_UnloadBlob_NONCE(&offset, dec, nonce0);
   1166 
   1167 	return result;
   1168 }
   1169 
   1170 TSS_RESULT
   1171 Transport_OSAP(TSS_HCONTEXT    tspContext,	/* in */
   1172 	       TPM_ENTITY_TYPE entityType,	/* in */
   1173 	       UINT32          entityValue,	/* in */
   1174 	       TPM_NONCE*      nonceOddOSAP,	/* in */
   1175 	       TCS_AUTHHANDLE* authHandle,	/* out */
   1176 	       TPM_NONCE*      nonceEven,	/* out */
   1177 	       TPM_NONCE*      nonceEvenOSAP)	/* out */
   1178 {
   1179 	TSS_RESULT result;
   1180 	UINT32 decLen = 0;
   1181 	BYTE *dec = NULL;
   1182 	UINT64 offset;
   1183 	TCS_HANDLE handlesLen = 0;
   1184 	BYTE data[sizeof(UINT16) + sizeof(UINT32) + sizeof(TPM_NONCE)];
   1185 
   1186 	if ((result = obj_context_transport_init(tspContext)))
   1187 		return result;
   1188 
   1189 	LogDebugFn("Executing in a transport session");
   1190 
   1191 	offset = 0;
   1192 	Trspi_LoadBlob_UINT16(&offset, entityType, data);
   1193 	Trspi_LoadBlob_UINT32(&offset, entityValue, data);
   1194 	Trspi_LoadBlob_NONCE(&offset, data, nonceOddOSAP);
   1195 
   1196 	if ((result = obj_context_transport_execute(tspContext, TPM_ORD_OSAP, sizeof(data), data,
   1197 						    NULL, &handlesLen, NULL, NULL, NULL, &decLen,
   1198 						    &dec)))
   1199 		return result;
   1200 
   1201 	offset = 0;
   1202 	Trspi_UnloadBlob_UINT32(&offset, authHandle, dec);
   1203 	Trspi_UnloadBlob_NONCE(&offset, dec, nonceEven);
   1204 	Trspi_UnloadBlob_NONCE(&offset, dec, nonceEvenOSAP);
   1205 
   1206 	return TSS_SUCCESS;
   1207 }
   1208 
   1209 TSS_RESULT
   1210 Transport_TerminateHandle(TSS_HCONTEXT tspContext, /* in */
   1211 			  TCS_AUTHHANDLE handle)   /* in */
   1212 {
   1213 	TSS_RESULT result;
   1214 	TCS_HANDLE handlesLen = 0, *handles, *handles_track;
   1215 
   1216 	/* Call ExecuteTransport */
   1217 	handlesLen = 1;
   1218 	if ((handles = malloc(sizeof(TCS_HANDLE))) == NULL) {
   1219 		LogError("malloc of %zd bytes failed", sizeof(TCS_HANDLE));
   1220 		return TSPERR(TSS_E_OUTOFMEMORY);
   1221 	}
   1222 
   1223 	*handles = handle;
   1224     handles_track = handles;
   1225 
   1226     // Since the call tree of this function can possibly alloc memory
   1227     // (check RPC_ExecuteTransport_TP function), its better to keep track of
   1228     // the handle.
   1229 	result = obj_context_transport_execute(tspContext, TPM_ORD_Terminate_Handle, 0, NULL,
   1230 					       NULL, &handlesLen, &handles, NULL, NULL, NULL, NULL);
   1231 
   1232 	free(handles);
   1233     handles = NULL;
   1234     free(handles_track);
   1235 
   1236 	return result;
   1237 }
   1238 #endif
   1239