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#include <stdlib.h>
12#include <stdio.h>
13#include <syslog.h>
14#include <string.h>
15#include <netdb.h>
16#if (defined (__OpenBSD__) || defined (__FreeBSD__) || defined(__NetBSD__))
17#include <sys/types.h>
18#include <sys/socket.h>
19#endif
20#include <errno.h>
21
22#include "trousers/tss.h"
23#include "trousers_types.h"
24#include "tcs_tsp.h"
25#include "tcs_utils.h"
26#include "tcs_int_literals.h"
27#include "capabilities.h"
28#include "tcslog.h"
29#include "tcsd_wrap.h"
30#include "tcsd.h"
31#include "rpc_tcstp_tcs.h"
32
33
34/* Lock is not static because we need to reference it in the auth manager */
35MUTEX_DECLARE_INIT(tcsp_lock);
36
37
38void
39LoadBlob_Auth_Special(UINT64 *offset, BYTE *blob, TPM_AUTH *auth)
40{
41	LoadBlob(offset, TCPA_SHA1BASED_NONCE_LEN, blob, auth->NonceEven.nonce);
42	LoadBlob_BOOL(offset, auth->fContinueAuthSession, blob);
43	LoadBlob(offset, TCPA_SHA1BASED_NONCE_LEN, blob, (BYTE *)&auth->HMAC);
44}
45
46void
47UnloadBlob_Auth_Special(UINT64 *offset, BYTE *blob, TPM_AUTH *auth)
48{
49	UnloadBlob_UINT32(offset, &auth->AuthHandle, blob);
50	UnloadBlob(offset, TCPA_SHA1BASED_NONCE_LEN, blob, auth->NonceOdd.nonce);
51	UnloadBlob_BOOL(offset, &auth->fContinueAuthSession, blob);
52	UnloadBlob(offset, TCPA_SHA1BASED_NONCE_LEN, blob, (BYTE *)&auth->HMAC);
53}
54
55int
56recv_from_socket(int sock, void *buffer, int size)
57{
58        int recv_size = 0, recv_total = 0;
59
60	while (recv_total < size) {
61		errno = 0;
62		if ((recv_size = recv(sock, buffer+recv_total, size-recv_total, 0)) <= 0) {
63			if (recv_size < 0) {
64				if (errno == EINTR)
65					continue;
66				LogError("Socket receive connection error: %s.", strerror(errno));
67			} else {
68				LogDebug("Socket connection closed.");
69			}
70
71			return -1;
72		}
73		recv_total += recv_size;
74	}
75
76	return recv_total;
77}
78
79int
80send_to_socket(int sock, void *buffer, int size)
81{
82	int send_size = 0, send_total = 0;
83
84	while (send_total < size) {
85		if ((send_size = send(sock, buffer+send_total, size-send_total, 0)) < 0) {
86			LogError("Socket send connection error: %s.", strerror(errno));
87			return -1;
88		}
89		send_total += send_size;
90	}
91
92	return send_total;
93}
94
95
96void
97initData(struct tcsd_comm_data *comm, int parm_count)
98{
99	/* min packet size should be the size of the header */
100	memset(&comm->hdr, 0, sizeof(struct tcsd_packet_hdr));
101	comm->hdr.packet_size = sizeof(struct tcsd_packet_hdr);
102	if (parm_count > 0) {
103		comm->hdr.type_offset = sizeof(struct tcsd_packet_hdr);
104		comm->hdr.parm_offset = comm->hdr.type_offset +
105			(sizeof(TCSD_PACKET_TYPE) * parm_count);
106		comm->hdr.packet_size = comm->hdr.parm_offset;
107	}
108
109	memset(comm->buf, 0, comm->buf_size);
110}
111
112int
113loadData(UINT64 *offset, TCSD_PACKET_TYPE data_type, void *data, int data_size, BYTE *blob)
114{
115	switch (data_type) {
116		case TCSD_PACKET_TYPE_BYTE:
117			LoadBlob_BYTE(offset, *((BYTE *) (data)), blob);
118			break;
119		case TCSD_PACKET_TYPE_BOOL:
120			LoadBlob_BOOL(offset, *((TSS_BOOL *) (data)), blob);
121			break;
122		case TCSD_PACKET_TYPE_UINT16:
123			LoadBlob_UINT16(offset, *((UINT16 *) (data)), blob);
124			break;
125		case TCSD_PACKET_TYPE_UINT32:
126			LoadBlob_UINT32(offset, *((UINT32 *) (data)), blob);
127			break;
128		case TCSD_PACKET_TYPE_UINT64:
129			LoadBlob_UINT64(offset, *((UINT64 *) (data)), blob);
130			break;
131		case TCSD_PACKET_TYPE_PBYTE:
132			LoadBlob(offset, data_size, blob, data);
133			break;
134		case TCSD_PACKET_TYPE_NONCE:
135			LoadBlob(offset, sizeof(TCPA_NONCE), blob, ((TCPA_NONCE *)data)->nonce);
136			break;
137		case TCSD_PACKET_TYPE_DIGEST:
138			LoadBlob(offset, sizeof(TCPA_DIGEST), blob, ((TCPA_DIGEST *)data)->digest);
139			break;
140		case TCSD_PACKET_TYPE_AUTH:
141			LoadBlob_Auth_Special(offset, blob, ((TPM_AUTH *)data));
142			break;
143#ifdef TSS_BUILD_PS
144		case TCSD_PACKET_TYPE_UUID:
145			LoadBlob_UUID(offset, blob, *((TSS_UUID *)data));
146			break;
147		case TCSD_PACKET_TYPE_KM_KEYINFO:
148			LoadBlob_KM_KEYINFO(offset, blob, ((TSS_KM_KEYINFO *)data));
149			break;
150		case TCSD_PACKET_TYPE_KM_KEYINFO2:
151			LoadBlob_KM_KEYINFO2(offset, blob, ((TSS_KM_KEYINFO2 *)data));
152			break;
153		case TCSD_PACKET_TYPE_LOADKEY_INFO:
154			LoadBlob_LOADKEY_INFO(offset, blob, ((TCS_LOADKEY_INFO *)data));
155			break;
156#endif
157		case TCSD_PACKET_TYPE_ENCAUTH:
158			LoadBlob(offset, sizeof(TCPA_ENCAUTH), blob,
159				 ((TCPA_ENCAUTH *)data)->authdata);
160			break;
161		case TCSD_PACKET_TYPE_VERSION:
162			LoadBlob_VERSION(offset, blob, ((TPM_VERSION *)data));
163			break;
164#ifdef TSS_BUILD_PCR_EVENTS
165		case TCSD_PACKET_TYPE_PCR_EVENT:
166			LoadBlob_PCR_EVENT(offset, blob, ((TSS_PCR_EVENT *)data));
167			break;
168#endif
169		case TCSD_PACKET_TYPE_SECRET:
170			LoadBlob(offset, sizeof(TCPA_SECRET), blob,
171				 ((TCPA_SECRET *)data)->authdata);
172			break;
173		default:
174			LogError("TCSD packet type unknown! (0x%x)", data_type & 0xff);
175			return TCSERR(TSS_E_INTERNAL_ERROR);
176	}
177
178	return TSS_SUCCESS;
179}
180
181
182int
183setData(TCSD_PACKET_TYPE dataType,
184	int index,
185	void *theData,
186	int theDataSize,
187	struct tcsd_comm_data *comm)
188{
189	UINT64 old_offset, offset;
190	TSS_RESULT result;
191	TCSD_PACKET_TYPE *type;
192
193	/* Calculate the size of the area needed (use NULL for blob address) */
194	offset = 0;
195	if ((result = loadData(&offset, dataType, theData, theDataSize, NULL)) != TSS_SUCCESS)
196		return result;
197	if (((int)comm->hdr.packet_size + (int)offset) < 0) {
198		LogError("Too much data to be transmitted!");
199		return TCSERR(TSS_E_INTERNAL_ERROR);
200	}
201	if (((int)comm->hdr.packet_size + (int)offset) > comm->buf_size) {
202		/* reallocate the buffer */
203		BYTE *buffer;
204		int buffer_size = comm->hdr.packet_size + offset;
205
206		LogDebug("Increasing communication buffer to %d bytes.", buffer_size);
207		buffer = realloc(comm->buf, buffer_size);
208		if (buffer == NULL) {
209			LogError("realloc of %d bytes failed.", buffer_size);
210			return TCSERR(TSS_E_INTERNAL_ERROR);
211		}
212		comm->buf_size = buffer_size;
213		comm->buf = buffer;
214	}
215
216	offset = old_offset = comm->hdr.parm_offset + comm->hdr.parm_size;
217	if ((result = loadData(&offset, dataType, theData, theDataSize, comm->buf)) != TSS_SUCCESS)
218		return result;
219	type = (TCSD_PACKET_TYPE *)(comm->buf + comm->hdr.type_offset) + index;
220	*type = dataType;
221	comm->hdr.type_size += sizeof(TCSD_PACKET_TYPE);
222	comm->hdr.parm_size += (offset - old_offset);
223
224	comm->hdr.packet_size = offset;
225	comm->hdr.num_parms++;
226
227	return TSS_SUCCESS;
228}
229
230UINT32
231getData(TCSD_PACKET_TYPE dataType,
232	int index,
233	void *theData,
234	int theDataSize,
235	struct tcsd_comm_data *comm)
236{
237	UINT64 old_offset, offset;
238	TCSD_PACKET_TYPE *type = (TCSD_PACKET_TYPE *)(comm->buf + comm->hdr.type_offset) + index;
239
240	if ((UINT32)index >= comm->hdr.num_parms || dataType != *type) {
241		LogDebug("Data type of TCS packet element %d doesn't match.", index);
242		return TSS_TCP_RPC_BAD_PACKET_TYPE;
243	}
244	old_offset = offset = comm->hdr.parm_offset;
245	switch (dataType) {
246		case TCSD_PACKET_TYPE_BYTE:
247			if (old_offset + sizeof(BYTE) > comm->hdr.packet_size)
248				return TCSERR(TSS_E_INTERNAL_ERROR);
249
250			UnloadBlob_BYTE(&offset, (BYTE *) (theData), comm->buf);
251			break;
252		case TCSD_PACKET_TYPE_BOOL:
253			if (old_offset + sizeof(TSS_BOOL) > comm->hdr.packet_size)
254				return TCSERR(TSS_E_INTERNAL_ERROR);
255
256			UnloadBlob_BOOL(&offset, (TSS_BOOL *) (theData), comm->buf);
257			break;
258		case TCSD_PACKET_TYPE_UINT16:
259			if (old_offset + sizeof(UINT16) > comm->hdr.packet_size)
260				return TCSERR(TSS_E_INTERNAL_ERROR);
261
262			UnloadBlob_UINT16(&offset, (UINT16 *) (theData), comm->buf);
263			break;
264		case TCSD_PACKET_TYPE_UINT32:
265			if (old_offset + sizeof(UINT32) > comm->hdr.packet_size)
266				return TCSERR(TSS_E_INTERNAL_ERROR);
267
268			UnloadBlob_UINT32(&offset, (UINT32 *) (theData), comm->buf);
269			break;
270		case TCSD_PACKET_TYPE_PBYTE:
271			if (old_offset + theDataSize > comm->hdr.packet_size)
272				return TCSERR(TSS_E_INTERNAL_ERROR);
273
274			UnloadBlob(&offset, theDataSize, comm->buf, theData);
275			break;
276		case TCSD_PACKET_TYPE_NONCE:
277			if (old_offset + sizeof(TPM_NONCE) > comm->hdr.packet_size)
278				return TCSERR(TSS_E_INTERNAL_ERROR);
279
280			UnloadBlob(&offset, sizeof(TCPA_NONCE), comm->buf,
281					((TCPA_NONCE *) (theData))->nonce);
282			break;
283		case TCSD_PACKET_TYPE_DIGEST:
284			if (old_offset + sizeof(TPM_DIGEST) > comm->hdr.packet_size)
285				return TCSERR(TSS_E_INTERNAL_ERROR);
286
287			UnloadBlob(&offset, sizeof(TCPA_DIGEST), comm->buf,
288					((TCPA_DIGEST *) (theData))->digest);
289			break;
290		case TCSD_PACKET_TYPE_AUTH:
291			if ((old_offset + sizeof(TCS_AUTHHANDLE)
292					+ sizeof(TPM_BOOL)
293					+ (2 * sizeof(TPM_NONCE))) > comm->hdr.packet_size)
294				return TCSERR(TSS_E_INTERNAL_ERROR);
295
296			UnloadBlob_Auth_Special(&offset, comm->buf, ((TPM_AUTH *) theData));
297			break;
298		case TCSD_PACKET_TYPE_ENCAUTH:
299			if (old_offset + sizeof(TPM_ENCAUTH) > comm->hdr.packet_size)
300				return TCSERR(TSS_E_INTERNAL_ERROR);
301
302			UnloadBlob(&offset, sizeof(TCPA_ENCAUTH), comm->buf,
303					((TCPA_ENCAUTH *) theData)->authdata);
304			break;
305		case TCSD_PACKET_TYPE_VERSION:
306			if (old_offset + sizeof(TPM_VERSION) > comm->hdr.packet_size)
307				return TCSERR(TSS_E_INTERNAL_ERROR);
308
309			UnloadBlob_VERSION(&offset, comm->buf, ((TPM_VERSION *) theData));
310			break;
311#ifdef TSS_BUILD_PS
312		case TCSD_PACKET_TYPE_KM_KEYINFO:
313			UnloadBlob_KM_KEYINFO(&old_offset, comm->buf, NULL);
314
315			if (old_offset > comm->hdr.packet_size)
316				return TCSERR(TSS_E_INTERNAL_ERROR);
317
318			old_offset = offset;
319			UnloadBlob_KM_KEYINFO(&offset, comm->buf, ((TSS_KM_KEYINFO *)theData));
320			break;
321		case TCSD_PACKET_TYPE_LOADKEY_INFO:
322			UnloadBlob_LOADKEY_INFO(&old_offset, comm->buf, NULL);
323
324			if (old_offset > comm->hdr.packet_size)
325				return TCSERR(TSS_E_INTERNAL_ERROR);
326
327			old_offset = offset;
328			UnloadBlob_LOADKEY_INFO(&offset, comm->buf, ((TCS_LOADKEY_INFO *)theData));
329			break;
330		case TCSD_PACKET_TYPE_UUID:
331			if (old_offset + sizeof(TSS_UUID) > comm->hdr.packet_size)
332				return TCSERR(TSS_E_INTERNAL_ERROR);
333
334			UnloadBlob_UUID(&offset, comm->buf, (TSS_UUID *) theData);
335			break;
336#endif
337#ifdef TSS_BUILD_PCR_EVENTS
338		case TCSD_PACKET_TYPE_PCR_EVENT:
339		{
340			TSS_RESULT result;
341
342			(void)UnloadBlob_PCR_EVENT(&old_offset, comm->buf, NULL);
343
344			if (old_offset > comm->hdr.packet_size)
345				return TCSERR(TSS_E_INTERNAL_ERROR);
346
347			old_offset = offset;
348			if ((result = UnloadBlob_PCR_EVENT(&offset, comm->buf,
349							   ((TSS_PCR_EVENT *)theData))))
350				return result;
351			break;
352		}
353#endif
354		case TCSD_PACKET_TYPE_SECRET:
355			if (old_offset + sizeof(TPM_SECRET) > comm->hdr.packet_size)
356				return TCSERR(TSS_E_INTERNAL_ERROR);
357
358			UnloadBlob(&offset, sizeof(TCPA_SECRET), comm->buf,
359					((TCPA_SECRET *) theData)->authdata);
360			break;
361		default:
362			LogError("TCSD packet type unknown! (0x%x)", dataType & 0xff);
363			return TCSERR(TSS_E_INTERNAL_ERROR);
364	}
365	comm->hdr.parm_offset = offset;
366	comm->hdr.parm_size -= (offset - old_offset);
367
368	return TSS_SUCCESS;
369}
370
371TSS_RESULT
372tcs_wrap_Error(struct tcsd_thread_data *data)
373{
374	LogError("%s reached.", __FUNCTION__);
375
376	initData(&data->comm, 0);
377
378	data->comm.hdr.u.result = TCSERR(TSS_E_FAIL);
379
380	return TSS_SUCCESS;
381
382}
383
384/* Dispatch */
385typedef struct tdDispatchTable {
386	TSS_RESULT (*Func) (struct tcsd_thread_data *);
387	const char *name;
388} DispatchTable;
389
390DispatchTable tcs_func_table[TCSD_MAX_NUM_ORDS] = {
391	{tcs_wrap_Error,"Error"},   /* 0 */
392	{tcs_wrap_OpenContext,"OpenContext"},
393	{tcs_wrap_CloseContext,"CloseContext"},
394	{tcs_wrap_Error,"Error"},
395	{tcs_wrap_TCSGetCapability,"TCSGetCapability"},
396	{tcs_wrap_RegisterKey,"RegisterKey"}, /* 5 */
397	{tcs_wrap_UnregisterKey,"UnregisterKey"},
398	{tcs_wrap_EnumRegisteredKeys,"EnumRegisteredKeys"},
399	{tcs_wrap_Error,"Error"},
400	{tcs_wrap_GetRegisteredKeyBlob,"GetRegisteredKeyBlob"},
401	{tcs_wrap_GetRegisteredKeyByPublicInfo,"GetRegisteredKeyByPublicInfo"}, /* 10 */
402	{tcs_wrap_LoadKeyByBlob,"LoadKeyByBlob"},
403	{tcs_wrap_LoadKeyByUUID,"LoadKeyByUUID"},
404	{tcs_wrap_EvictKey,"EvictKey"},
405	{tcs_wrap_CreateWrapKey,"CreateWrapKey"},
406	{tcs_wrap_GetPubkey,"GetPubkey"}, /* 15 */
407	{tcs_wrap_MakeIdentity,"MakeIdentity"},
408	{tcs_wrap_LogPcrEvent,"LogPcrEvent"},
409	{tcs_wrap_GetPcrEvent,"GetPcrEvent"},
410	{tcs_wrap_GetPcrEventsByPcr,"GetPcrEventsByPcr"},
411	{tcs_wrap_GetPcrEventLog,"GetPcrEventLog"}, /* 20 */
412	{tcs_wrap_SetOwnerInstall,"SetOwnerInstall"},
413	{tcs_wrap_TakeOwnership,"TakeOwnership"},
414	{tcs_wrap_OIAP,"OIAP"},
415	{tcs_wrap_OSAP,"OSAP"},
416	{tcs_wrap_ChangeAuth,"ChangeAuth"}, /* 25 */
417	{tcs_wrap_ChangeAuthOwner,"ChangeAuthOwner"},
418	{tcs_wrap_Error,"Error"},
419	{tcs_wrap_Error,"Error"},
420	{tcs_wrap_TerminateHandle,"TerminateHandle"},
421	{tcs_wrap_ActivateIdentity,"ActivateIdentity"}, /* 30 */
422	{tcs_wrap_Extend,"Extend"},
423	{tcs_wrap_PcrRead,"PcrRead"},
424	{tcs_wrap_Quote,"Quote"},
425	{tcs_wrap_DirWriteAuth,"DirWriteAuth"},
426	{tcs_wrap_DirRead,"DirRead"}, /* 35 */
427	{tcs_wrap_Seal,"Seal"},
428	{tcs_wrap_UnSeal,"UnSeal"},
429	{tcs_wrap_UnBind,"UnBind"},
430	{tcs_wrap_CreateMigrationBlob,"CreateMigrationBlob"},
431	{tcs_wrap_ConvertMigrationBlob,"ConvertMigrationBlob"}, /* 40 */
432	{tcs_wrap_AuthorizeMigrationKey,"AuthorizeMigrationKey"},
433	{tcs_wrap_CertifyKey,"CertifyKey"},
434	{tcs_wrap_Sign,"Sign"},
435	{tcs_wrap_GetRandom,"GetRandom"},
436	{tcs_wrap_StirRandom,"StirRandom"}, /* 45 */
437	{tcs_wrap_GetCapability,"GetCapability"},
438	{tcs_wrap_Error,"Error"},
439	{tcs_wrap_GetCapabilityOwner,"GetCapabilityOwner"},
440	{tcs_wrap_CreateEndorsementKeyPair,"CreateEndorsementKeyPair"},
441	{tcs_wrap_ReadPubek,"ReadPubek"}, /* 50 */
442	{tcs_wrap_DisablePubekRead,"DisablePubekRead"},
443	{tcs_wrap_OwnerReadPubek,"OwnerReadPubek"},
444	{tcs_wrap_SelfTestFull,"SelfTestFull"},
445	{tcs_wrap_CertifySelfTest,"CertifySelfTest"},
446	{tcs_wrap_Error,"Error"}, /* 55 */
447	{tcs_wrap_GetTestResult,"GetTestResult"},
448	{tcs_wrap_OwnerSetDisable,"OwnerSetDisable"},
449	{tcs_wrap_OwnerClear,"OwnerClear"},
450	{tcs_wrap_DisableOwnerClear,"DisableOwnerClear"},
451	{tcs_wrap_ForceClear,"ForceClear"}, /* 60 */
452	{tcs_wrap_DisableForceClear,"DisableForceClear"},
453	{tcs_wrap_PhysicalDisable,"PhysicalDisable"},
454	{tcs_wrap_PhysicalEnable,"PhysicalEnable"},
455	{tcs_wrap_PhysicalSetDeactivated,"PhysicalSetDeactivated"},
456	{tcs_wrap_SetTempDeactivated,"SetTempDeactivated"}, /* 65 */
457	{tcs_wrap_PhysicalPresence,"PhysicalPresence"},
458	{tcs_wrap_Error,"Error"},
459	{tcs_wrap_Error,"Error"},
460	{tcs_wrap_CreateMaintenanceArchive,"CreateMaintenanceArchive"},
461	{tcs_wrap_LoadMaintenanceArchive,"LoadMaintenanceArchive"}, /* 70 */
462	{tcs_wrap_KillMaintenanceFeature,"KillMaintenanceFeature"},
463	{tcs_wrap_LoadManuMaintPub,"LoadManuMaintPub"},
464	{tcs_wrap_ReadManuMaintPub,"ReadManuMaintPub"},
465	{tcs_wrap_DaaJoin,"DaaJoin"},
466	{tcs_wrap_DaaSign,"DaaSign"}, /* 75 */
467	{tcs_wrap_SetCapability,"SetCapability"},
468	{tcs_wrap_ResetLockValue,"ResetLockValue"},
469	{tcs_wrap_PcrReset,"PcrReset"},
470	{tcs_wrap_ReadCounter,"ReadCounter"},
471	{tcs_wrap_CreateCounter,"CreateCounter"}, /* 80 */
472	{tcs_wrap_IncrementCounter,"IncrementCounter"},
473	{tcs_wrap_ReleaseCounter,"ReleaseCounter"},
474	{tcs_wrap_ReleaseCounterOwner,"ReleaseCounterOwner"},
475	{tcs_wrap_ReadCurrentTicks,"ReadCurrentTicks"},
476	{tcs_wrap_TickStampBlob,"TicksStampBlob"}, /* 85 */
477	{tcs_wrap_GetCredential,"GetCredential"},
478	{tcs_wrap_NV_DefineOrReleaseSpace,"NVDefineOrReleaseSpace"},
479	{tcs_wrap_NV_WriteValue,"NVWriteValue"},
480	{tcs_wrap_NV_WriteValueAuth,"NVWriteValueAuth"},
481	{tcs_wrap_NV_ReadValue,"NVReadValue"}, /* 90 */
482	{tcs_wrap_NV_ReadValueAuth,"NVReadValueAuth"},
483	{tcs_wrap_EstablishTransport,"EstablishTransport"},
484	{tcs_wrap_ExecuteTransport,"ExecuteTransport"},
485	{tcs_wrap_ReleaseTransportSigned,"ReleaseTransportSigned"},
486	{tcs_wrap_SetOrdinalAuditStatus,"SetOrdinalAuditStatus"}, /* 95 */
487	{tcs_wrap_GetAuditDigest,"GetAuditDigest"},
488	{tcs_wrap_GetAuditDigestSigned,"GetAuditDigestSigned"},
489	{tcs_wrap_Sealx,"Sealx"},
490	{tcs_wrap_SetOperatorAuth,"SetOperatorAuth"},
491	{tcs_wrap_OwnerReadInternalPub,"OwnerReadInternalPub"}, /* 100 */
492	{tcs_wrap_EnumRegisteredKeys2,"EnumRegisteredKeys2"},
493	{tcs_wrap_SetTempDeactivated2,"SetTempDeactivated2"},
494	{tcs_wrap_Delegate_Manage,"Delegate_Manage"},
495	{tcs_wrap_Delegate_CreateKeyDelegation,"Delegate_CreateKeyDelegation"},
496	{tcs_wrap_Delegate_CreateOwnerDelegation,"Delegate_CreateOwnerDelegation"}, /* 105 */
497	{tcs_wrap_Delegate_LoadOwnerDelegation,"Delegate_LoadOwnerDelegation"},
498	{tcs_wrap_Delegate_ReadTable,"Delegate_ReadTable"},
499	{tcs_wrap_Delegate_UpdateVerificationCount,"Delegate_UpdateVerificationCount"},
500	{tcs_wrap_Delegate_VerifyDelegation,"Delegate_VerifyDelegation"},
501	{tcs_wrap_CreateRevocableEndorsementKeyPair,"CreateRevocableEndorsementKeyPair"}, /* 110 */
502	{tcs_wrap_RevokeEndorsementKeyPair,"RevokeEndorsementKeyPair"},
503	{tcs_wrap_Error,"Error - was MakeIdentity2"},
504	{tcs_wrap_Quote2,"Quote2"},
505	{tcs_wrap_CMK_SetRestrictions,"CMK_SetRestrictions"},
506	{tcs_wrap_CMK_ApproveMA,"CMK_ApproveMA"}, /* 115 */
507	{tcs_wrap_CMK_CreateKey,"CMK_CreateKey"},
508	{tcs_wrap_CMK_CreateTicket,"CMK_CreateTicket"},
509	{tcs_wrap_CMK_CreateBlob,"CMK_CreateBlob"},
510	{tcs_wrap_CMK_ConvertMigration,"CMK_ConvertMigration"},
511	{tcs_wrap_FlushSpecific,"FlushSpecific"}, /* 120 */
512	{tcs_wrap_KeyControlOwner, "KeyControlOwner"},
513	{tcs_wrap_DSAP, "DSAP"}
514};
515
516int
517access_control(struct tcsd_thread_data *thread_data)
518{
519	int i = 0;
520	struct hostent *local_hostent = NULL;
521	static char *localhostname = NULL;
522	static int localhostname_len = 0;
523
524	if (!localhostname) {
525		if ((local_hostent = gethostbyname("localhost")) == NULL) {
526			LogError("Error resolving localhost: %s", hstrerror(h_errno));
527			return 1;
528		}
529
530		LogDebugFn("Cached local hostent:");
531		LogDebugFn("h_name: %s", local_hostent->h_name);
532		for (i = 0; local_hostent->h_aliases[i]; i++) {
533			LogDebugFn("h_aliases[%d]: %s", i, local_hostent->h_aliases[i]);
534		}
535		LogDebugFn("h_addrtype: %s",
536			   (local_hostent->h_addrtype == AF_INET6 ? "AF_INET6" : "AF_INET"));
537
538		localhostname_len = strlen(local_hostent->h_name);
539		if ((localhostname = strdup(local_hostent->h_name)) == NULL) {
540			LogError("malloc of %d bytes failed.", localhostname_len);
541			return TCSERR(TSS_E_OUTOFMEMORY);
542		}
543	}
544
545	/* if the request comes from localhost, or is in the accepted ops list,
546	 * approve it */
547	if (!strncmp(thread_data->hostname, localhostname,
548		     MIN((size_t)localhostname_len, strlen(thread_data->hostname)))) {
549		return 0;
550	} else {
551		while (tcsd_options.remote_ops[i]) {
552			if ((UINT32)tcsd_options.remote_ops[i] == thread_data->comm.hdr.u.ordinal) {
553				LogInfo("Accepted %s operation from %s",
554					tcs_func_table[thread_data->comm.hdr.u.ordinal].name,
555					thread_data->hostname);
556				return 0;
557			}
558			i++;
559		}
560	}
561
562	return 1;
563}
564
565TSS_RESULT
566dispatchCommand(struct tcsd_thread_data *data)
567{
568	UINT64 offset;
569	TSS_RESULT result;
570
571	/* First, check the ordinal bounds */
572	if (data->comm.hdr.u.ordinal >= TCSD_MAX_NUM_ORDS) {
573		LogError("Illegal TCSD Ordinal");
574		return TCSERR(TSS_E_FAIL);
575	}
576
577	LogDebug("Dispatching ordinal %u", data->comm.hdr.u.ordinal);
578	/* We only need to check access_control if there are remote operations that are defined
579	 * in the config file, which means we allow remote connections */
580	if (tcsd_options.remote_ops[0] && access_control(data)) {
581		LogWarn("Denied %s operation from %s",
582			tcs_func_table[data->comm.hdr.u.ordinal].name, data->hostname);
583
584		/* set platform header */
585		memset(&data->comm.hdr, 0, sizeof(data->comm.hdr));
586		data->comm.hdr.packet_size = sizeof(struct tcsd_packet_hdr);
587		data->comm.hdr.u.result = TCSERR(TSS_E_FAIL);
588
589		/* set the comm buffer */
590		memset(data->comm.buf, 0, data->comm.buf_size);
591		offset = 0;
592		LoadBlob_UINT32(&offset, data->comm.hdr.packet_size, data->comm.buf);
593		LoadBlob_UINT32(&offset, data->comm.hdr.u.result, data->comm.buf);
594
595		return TSS_SUCCESS;
596	}
597
598	/* Now, dispatch */
599	if ((result = tcs_func_table[data->comm.hdr.u.ordinal].Func(data)) == TSS_SUCCESS) {
600		/* set the comm buffer */
601		offset = 0;
602		LoadBlob_UINT32(&offset, data->comm.hdr.packet_size, data->comm.buf);
603		LoadBlob_UINT32(&offset, data->comm.hdr.u.result, data->comm.buf);
604		LoadBlob_UINT32(&offset, data->comm.hdr.num_parms, data->comm.buf);
605		LoadBlob_UINT32(&offset, data->comm.hdr.type_size, data->comm.buf);
606		LoadBlob_UINT32(&offset, data->comm.hdr.type_offset, data->comm.buf);
607		LoadBlob_UINT32(&offset, data->comm.hdr.parm_size, data->comm.buf);
608		LoadBlob_UINT32(&offset, data->comm.hdr.parm_offset, data->comm.buf);
609	}
610
611	return result;
612
613}
614
615TSS_RESULT
616getTCSDPacket(struct tcsd_thread_data *data)
617{
618        /* make sure the all the data is present */
619	if (data->comm.hdr.num_parms > 0 &&
620	    data->comm.hdr.packet_size !=
621		(UINT32)(data->comm.hdr.parm_offset + data->comm.hdr.parm_size))
622		return TCSERR(TSS_E_INTERNAL_ERROR);
623
624	/* dispatch the command to the TCS */
625	return dispatchCommand(data);
626}
627