xref: /netbsd-src/crypto/external/cpl/trousers/dist/src/tspi/rpc/tcstp/rpc.c (revision 9ac63422b666fbe53a067de74d8af2aa4e45a08b)
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-2006
8  *
9  */
10 
11 #include <unistd.h>
12 #include <errno.h>
13 #include <string.h>
14 #include <sys/socket.h>
15 #include <sys/types.h>
16 #include <netinet/in.h>
17 #include <arpa/inet.h>
18 #include <netdb.h>
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <assert.h>
22 #include <limits.h>
23 
24 #include "trousers/tss.h"
25 #include "trousers/trousers.h"
26 #include "trousers_types.h"
27 #include "spi_utils.h"
28 #include "capabilities.h"
29 #include "tsplog.h"
30 #include "hosttable.h"
31 #include "tcsd_wrap.h"
32 #include "obj.h"
33 #include "rpc_tcstp_tsp.h"
34 
35 
36 void
37 initData(struct tcsd_comm_data *comm, int parm_count)
38 {
39 	/* min packet size should be the size of the header */
40 	memset(&comm->hdr, 0, sizeof(struct tcsd_packet_hdr));
41 	comm->hdr.packet_size = sizeof(struct tcsd_packet_hdr);
42 	if (parm_count > 0) {
43 		comm->hdr.type_offset = sizeof(struct tcsd_packet_hdr);
44 		comm->hdr.parm_offset = comm->hdr.type_offset +
45 					(sizeof(TCSD_PACKET_TYPE) * parm_count);
46 		comm->hdr.packet_size = comm->hdr.parm_offset;
47 	}
48 
49 	memset(comm->buf, 0, comm->buf_size);
50 }
51 
52 int
53 loadData(UINT64 *offset, TCSD_PACKET_TYPE data_type, void *data, int data_size, BYTE *blob)
54 {
55 	switch (data_type) {
56 		case TCSD_PACKET_TYPE_BYTE:
57 			Trspi_LoadBlob_BYTE(offset, *((BYTE *) (data)), blob);
58 			break;
59 		case TCSD_PACKET_TYPE_BOOL:
60 			Trspi_LoadBlob_BOOL(offset, *((TSS_BOOL *) (data)), blob);
61 			break;
62 		case TCSD_PACKET_TYPE_UINT16:
63 			Trspi_LoadBlob_UINT16(offset, *((UINT16 *) (data)), blob);
64 			break;
65 		case TCSD_PACKET_TYPE_UINT32:
66 			Trspi_LoadBlob_UINT32(offset, *((UINT32 *) (data)), blob);
67 			break;
68 		case TCSD_PACKET_TYPE_PBYTE:
69 			Trspi_LoadBlob(offset, data_size, blob, (BYTE *)data);
70 			break;
71 		case TCSD_PACKET_TYPE_NONCE:
72 			Trspi_LoadBlob(offset, 20, blob, ((TCPA_NONCE *)data)->nonce);
73 			break;
74 		case TCSD_PACKET_TYPE_DIGEST:
75 			Trspi_LoadBlob(offset, 20, blob, ((TCPA_DIGEST *)data)->digest);
76 			break;
77 		case TCSD_PACKET_TYPE_AUTH:
78 			LoadBlob_AUTH(offset, blob, ((TPM_AUTH *)data));
79 			break;
80 		case TCSD_PACKET_TYPE_UUID:
81 			Trspi_LoadBlob_UUID(offset, blob, *((TSS_UUID *)data));
82 			break;
83 		case TCSD_PACKET_TYPE_ENCAUTH:
84 			Trspi_LoadBlob(offset, 20, blob, ((TCPA_ENCAUTH *)data)->authdata);
85 			break;
86 		case TCSD_PACKET_TYPE_VERSION:
87 			Trspi_LoadBlob_TCPA_VERSION(offset, blob, *((TCPA_VERSION *)data));
88 			break;
89 #ifdef TSS_BUILD_PS
90 		case TCSD_PACKET_TYPE_LOADKEY_INFO:
91 			LoadBlob_LOADKEY_INFO(offset, blob, ((TCS_LOADKEY_INFO *)data));
92 			break;
93 #endif
94 		case TCSD_PACKET_TYPE_PCR_EVENT:
95 			Trspi_LoadBlob_PCR_EVENT(offset, blob, ((TSS_PCR_EVENT *)data));
96 			break;
97 		case TCSD_PACKET_TYPE_COUNTER_VALUE:
98 			Trspi_LoadBlob_COUNTER_VALUE(offset, blob, ((TPM_COUNTER_VALUE *)data));
99 			break;
100 		case TCSD_PACKET_TYPE_SECRET:
101 			Trspi_LoadBlob(offset, 20, blob, ((TCPA_SECRET *)data)->authdata);
102 			break;
103 		default:
104 			LogError("TCSD packet type unknown! (0x%x)", data_type & 0xff);
105 			return TSPERR(TSS_E_INTERNAL_ERROR);
106 	}
107 
108 	return TSS_SUCCESS;
109 }
110 
111 int
112 setData(TCSD_PACKET_TYPE dataType,
113 	int index,
114 	void *theData,
115 	int theDataSize,
116 	struct tcsd_comm_data *comm)
117 {
118         UINT64 old_offset, offset;
119         TSS_RESULT result;
120         TCSD_PACKET_TYPE *type;
121 
122         /* Calculate the size of the area needed (use NULL for blob address) */
123         offset = 0;
124         if ((result = loadData(&offset, dataType, theData, theDataSize, NULL)))
125                 return result;
126         if (((int)comm->hdr.packet_size + (int)offset) < 0) {
127                 LogError("Too much data to be transmitted!");
128                 return TSPERR(TSS_E_INTERNAL_ERROR);
129         }
130         if (((int)comm->hdr.packet_size + (int)offset) > comm->buf_size) {
131                 /* reallocate the buffer */
132                 BYTE *buffer;
133                 int buffer_size = comm->hdr.packet_size + offset;
134 
135                 LogDebug("Increasing communication buffer to %d bytes.", buffer_size);
136                 buffer = realloc(comm->buf, buffer_size);
137                 if (buffer == NULL) {
138                         LogError("realloc of %d bytes failed.", buffer_size);
139                         return TSPERR(TSS_E_INTERNAL_ERROR);
140                 }
141                 comm->buf_size = buffer_size;
142                 comm->buf = buffer;
143         }
144 
145         offset = old_offset = comm->hdr.parm_offset + comm->hdr.parm_size;
146         if ((result = loadData(&offset, dataType, theData, theDataSize, comm->buf)))
147                 return result;
148         type = (TCSD_PACKET_TYPE *)(comm->buf + comm->hdr.type_offset) + index;
149         *type = dataType;
150         comm->hdr.type_size += sizeof(TCSD_PACKET_TYPE);
151         comm->hdr.parm_size += (offset - old_offset);
152 
153         comm->hdr.packet_size = offset;
154         comm->hdr.num_parms++;
155 
156         return TSS_SUCCESS;
157 }
158 
159 UINT32
160 getData(TCSD_PACKET_TYPE dataType,
161 	int index,
162 	void *theData,
163 	int theDataSize,
164 	struct tcsd_comm_data *comm)
165 {
166 	TSS_RESULT result;
167 	UINT64 old_offset, offset;
168 	TCSD_PACKET_TYPE *type = (TCSD_PACKET_TYPE *)(comm->buf + comm->hdr.type_offset) + index;
169 
170 	if ((UINT32)index >= comm->hdr.num_parms || dataType != *type) {
171 		LogDebug("Data type of TCS packet element %d doesn't match.", index);
172 		return TSS_TCP_RPC_BAD_PACKET_TYPE;
173 	}
174 	old_offset = offset = comm->hdr.parm_offset;
175 	switch (dataType) {
176 		case TCSD_PACKET_TYPE_BYTE:
177 			Trspi_UnloadBlob_BYTE(&offset, (BYTE *)theData, comm->buf);
178 			break;
179 		case TCSD_PACKET_TYPE_BOOL:
180 			Trspi_UnloadBlob_BOOL(&offset, (TSS_BOOL *)theData, comm->buf);
181 			break;
182 		case TCSD_PACKET_TYPE_UINT16:
183 			Trspi_UnloadBlob_UINT16(&offset, (UINT16 *)theData, comm->buf);
184 			break;
185 		case TCSD_PACKET_TYPE_UINT32:
186 			Trspi_UnloadBlob_UINT32(&offset, (UINT32 *)theData, comm->buf);
187 			break;
188 		case TCSD_PACKET_TYPE_UINT64:
189 			Trspi_UnloadBlob_UINT64(&offset, (UINT64 *)theData, comm->buf);
190 			break;
191 		case TCSD_PACKET_TYPE_PBYTE:
192 			Trspi_UnloadBlob(&offset, theDataSize, comm->buf, (BYTE *)theData);
193 			break;
194 		case TCSD_PACKET_TYPE_NONCE:
195 			Trspi_UnloadBlob_NONCE(&offset, comm->buf, (TPM_NONCE *)theData);
196 			break;
197 		case TCSD_PACKET_TYPE_DIGEST:
198 			Trspi_UnloadBlob(&offset, sizeof(TCPA_DIGEST), comm->buf,
199 					 ((TCPA_DIGEST *)theData)->digest);
200 			break;
201 		case TCSD_PACKET_TYPE_AUTH:
202 			UnloadBlob_AUTH(&offset, comm->buf, ((TPM_AUTH *)theData));
203 			break;
204 		case TCSD_PACKET_TYPE_UUID:
205 			Trspi_UnloadBlob_UUID(&offset, comm->buf, ((TSS_UUID *)theData));
206 			break;
207 		case TCSD_PACKET_TYPE_ENCAUTH:
208 			Trspi_UnloadBlob(&offset, sizeof(TCPA_ENCAUTH), comm->buf,
209 					 ((TCPA_ENCAUTH *)theData)->authdata);
210 			break;
211 		case TCSD_PACKET_TYPE_VERSION:
212 			Trspi_UnloadBlob_TCPA_VERSION(&offset, comm->buf,
213 						      ((TCPA_VERSION *)theData));
214 			break;
215 		case TCSD_PACKET_TYPE_KM_KEYINFO:
216 			if ((result = Trspi_UnloadBlob_KM_KEYINFO(&offset, comm->buf,
217 								  ((TSS_KM_KEYINFO *)theData))))
218 				return result;
219 			break;
220 		case TCSD_PACKET_TYPE_KM_KEYINFO2:
221 			if ((result = Trspi_UnloadBlob_KM_KEYINFO2(&offset, comm->buf,
222 								   ((TSS_KM_KEYINFO2 *)theData))))
223 				return result;
224 			break;
225 #ifdef TSS_BUILD_PS
226 		case TCSD_PACKET_TYPE_LOADKEY_INFO:
227 			UnloadBlob_LOADKEY_INFO(&offset, comm->buf, ((TCS_LOADKEY_INFO *)theData));
228 			break;
229 #endif
230 		case TCSD_PACKET_TYPE_PCR_EVENT:
231 			if ((result = Trspi_UnloadBlob_PCR_EVENT(&offset, comm->buf,
232 								 ((TSS_PCR_EVENT *)theData))))
233 				return result;
234 			break;
235 		case TCSD_PACKET_TYPE_COUNTER_VALUE:
236 			Trspi_UnloadBlob_COUNTER_VALUE(&offset, comm->buf,
237 						       ((TPM_COUNTER_VALUE *)theData));
238 			break;
239 		case TCSD_PACKET_TYPE_SECRET:
240 			Trspi_UnloadBlob(&offset, sizeof(TCPA_SECRET), comm->buf,
241 					 ((TCPA_SECRET *)theData)->authdata);
242 			break;
243 		default:
244 			LogError("unknown data type (%d) in TCSD packet!", dataType);
245 			return -1;
246 	}
247 	comm->hdr.parm_offset = offset;
248 	comm->hdr.parm_size -= (offset - old_offset);
249 
250 	return TSS_SUCCESS;
251 }
252 
253 TSS_RESULT
254 sendTCSDPacket(struct host_table_entry *hte)
255 {
256 	TSS_RESULT rc;
257 	UINT64 offset = 0;
258 
259 	Trspi_LoadBlob_UINT32(&offset, hte->comm.hdr.packet_size, hte->comm.buf);
260 	Trspi_LoadBlob_UINT32(&offset, hte->comm.hdr.u.ordinal, hte->comm.buf);
261 	Trspi_LoadBlob_UINT32(&offset, hte->comm.hdr.num_parms, hte->comm.buf);
262 	Trspi_LoadBlob_UINT32(&offset, hte->comm.hdr.type_size, hte->comm.buf);
263 	Trspi_LoadBlob_UINT32(&offset, hte->comm.hdr.type_offset, hte->comm.buf);
264 	Trspi_LoadBlob_UINT32(&offset, hte->comm.hdr.parm_size, hte->comm.buf);
265 	Trspi_LoadBlob_UINT32(&offset, hte->comm.hdr.parm_offset, hte->comm.buf);
266 
267 #if 0
268 	/* ---  Send it */
269 	printBuffer(hte->comm.buf, hte->comm.hdr.packet_size);
270 	LogInfo("Sending Packet with TCSD ordinal 0x%X", hte->comm.hdr.u.ordinal);
271 #endif
272 	/* if the ordinal is open context, there are some host table entry
273 	 * manipulations that must be done, so call _init
274 	 */
275 	if (hte->comm.hdr.u.ordinal == TCSD_ORD_OPENCONTEXT) {
276 		if ((rc = send_init(hte))) {
277 			LogError("Failed to send packet");
278 			return rc;
279 		}
280 	} else {
281 		if ((rc = tcs_sendit(hte))) {
282 			LogError("Failed to send packet");
283 			return rc;
284 		}
285 	}
286 
287 	/* create a platform version of the tcsd header */
288 	offset = 0;
289 	Trspi_UnloadBlob_UINT32(&offset, &hte->comm.hdr.packet_size, hte->comm.buf);
290 	Trspi_UnloadBlob_UINT32(&offset, &hte->comm.hdr.u.result, hte->comm.buf);
291 	Trspi_UnloadBlob_UINT32(&offset, &hte->comm.hdr.num_parms, hte->comm.buf);
292 	Trspi_UnloadBlob_UINT32(&offset, &hte->comm.hdr.type_size, hte->comm.buf);
293 	Trspi_UnloadBlob_UINT32(&offset, &hte->comm.hdr.type_offset, hte->comm.buf);
294 	Trspi_UnloadBlob_UINT32(&offset, &hte->comm.hdr.parm_size, hte->comm.buf);
295 	Trspi_UnloadBlob_UINT32(&offset, &hte->comm.hdr.parm_offset, hte->comm.buf);
296 
297 	return TSS_SUCCESS;
298 }
299 
300 int
301 recv_from_socket(int sock, void *buffer, int size)
302 {
303 	int recv_size = 0, recv_total = 0;
304 
305 	while (recv_total < size) {
306 		errno = 0;
307 		if ((recv_size = recv(sock, buffer+recv_total, size-recv_total, 0)) <= 0) {
308 			if (recv_size < 0) {
309 				if (errno == EINTR)
310 					continue;
311 				LogError("Socket receive connection error: %s.", strerror(errno));
312 			} else {
313 				LogDebug("Socket connection closed.");
314 			}
315 
316 			return -1;
317 		}
318 		recv_total += recv_size;
319 	}
320 
321 	return recv_total;
322 }
323 
324 int
325 send_to_socket(int sock, void *buffer, int size)
326 {
327 	int send_size = 0, send_total = 0;
328 
329 	while (send_total < size) {
330 		if ((send_size = send(sock, buffer+send_total, size-send_total, 0)) < 0) {
331 			LogError("Socket send connection error: %s.", strerror(errno));
332 			return -1;
333 		}
334 		send_total += send_size;
335 	}
336 
337 	return send_total;
338 }
339 
340 TSS_RESULT
341 send_init(struct host_table_entry *hte)
342 {
343 	int sd;
344 	int recv_size;
345 	BYTE *buffer;
346 	TSS_RESULT result;
347 
348 	struct sockaddr_in addr;
349 	struct hostent *hEnt = NULL;
350 
351 	sd = socket(PF_INET, SOCK_STREAM, 0);
352 	if (sd == -1) {
353 		LogError("socket: %s", strerror(errno));
354 		result = TSPERR(TSS_E_COMM_FAILURE);
355 		goto err_exit;
356 	}
357 
358 	memset(&addr, 0, sizeof(addr));
359 	addr.sin_family = AF_INET;
360 	addr.sin_port = htons(get_port());
361 
362 	LogDebug("Sending TSP packet to host %s.", hte->hostname);
363 
364 	/* try to resolve by hostname first */
365 	hEnt = gethostbyname((char *)hte->hostname);
366 	if (hEnt == NULL) {
367 		/* if by hostname fails, try by dot notation */
368 		if (inet_aton((char *)hte->hostname, &addr.sin_addr) == 0) {
369 			LogError("hostname %s does not resolve to a valid address.", hte->hostname);
370 			result = TSPERR(TSS_E_CONNECTION_FAILED);
371 			goto err_exit;
372 		}
373 	} else {
374 		memcpy(&addr.sin_addr, hEnt->h_addr_list[0], 4);
375 	}
376 
377 	LogDebug("Connecting to %s", inet_ntoa(addr.sin_addr));
378 
379 	if (connect(sd, (struct sockaddr *) &addr, sizeof (addr))) {
380 		LogError("connect: %s", strerror(errno));
381 		result = TSPERR(TSS_E_COMM_FAILURE);
382 		goto err_exit;
383 	}
384 
385 	if (send_to_socket(sd, hte->comm.buf, hte->comm.hdr.packet_size) < 0) {
386 		result = TSPERR(TSS_E_COMM_FAILURE);
387 		goto err_exit;
388 	}
389 
390 	buffer = hte->comm.buf;
391 	recv_size = sizeof(struct tcsd_packet_hdr);
392 	if ((recv_size = recv_from_socket(sd, buffer, recv_size)) < 0) {
393 		result = TSPERR(TSS_E_COMM_FAILURE);
394 		goto err_exit;
395 	}
396 	buffer += sizeof(struct tcsd_packet_hdr);       /* increment the receive buffer pointer */
397 
398 	/* check the packet size */
399 	recv_size = Decode_UINT32(hte->comm.buf);
400 	if (recv_size < (int)sizeof(struct tcsd_packet_hdr)) {
401 		LogError("Packet to receive from socket %d is too small (%d bytes)",
402 				sd, recv_size);
403 		result = TSPERR(TSS_E_COMM_FAILURE);
404 		goto err_exit;
405 	}
406 
407 	if (recv_size > hte->comm.buf_size ) {
408 		BYTE *new_buffer;
409 
410 		LogDebug("Increasing communication buffer to %d bytes.", recv_size);
411 		new_buffer = realloc(hte->comm.buf, recv_size);
412 		if (new_buffer == NULL) {
413 			LogError("realloc of %d bytes failed.", recv_size);
414 			result = TSPERR(TSS_E_OUTOFMEMORY);
415 			goto err_exit;
416 		}
417 		buffer = new_buffer + sizeof(struct tcsd_packet_hdr);
418 		hte->comm.buf_size = recv_size;
419 		hte->comm.buf = new_buffer;
420 	}
421 
422 	/* get the rest of the packet */
423 	recv_size -= sizeof(struct tcsd_packet_hdr);    /* already received the header */
424 	if ((recv_size = recv_from_socket(sd, buffer, recv_size)) < 0) {
425 		result = TSPERR(TSS_E_COMM_FAILURE);
426 		goto err_exit;
427 	}
428 
429 	hte->socket = sd;
430 
431 	return TSS_SUCCESS;
432 
433 err_exit:
434 	close(sd);
435 	return result;
436 }
437 
438 TSS_RESULT
439 tcs_sendit(struct host_table_entry *hte)
440 {
441 	int recv_size;
442 	BYTE *buffer;
443 	TSS_RESULT result;
444 
445 	if (send_to_socket(hte->socket, hte->comm.buf, hte->comm.hdr.packet_size) < 0) {
446 		result = TSPERR(TSS_E_COMM_FAILURE);
447 		goto err_exit;
448 	}
449 
450 	buffer = hte->comm.buf;
451 	recv_size = sizeof(struct tcsd_packet_hdr);
452 	if ((recv_size = recv_from_socket(hte->socket, buffer, recv_size)) < 0) {
453 		result = TSPERR(TSS_E_COMM_FAILURE);
454 		goto err_exit;
455 	}
456 	buffer += recv_size;            /* increment the receive buffer pointer */
457 
458 	/* check the packet size */
459 	recv_size = Decode_UINT32(hte->comm.buf);
460 	if (recv_size < (int)sizeof(struct tcsd_packet_hdr)) {
461 		LogError("Packet to receive from socket %d is too small (%d bytes)",
462 				hte->socket, recv_size);
463 		result = TSPERR(TSS_E_COMM_FAILURE);
464 		goto err_exit;
465 	}
466 
467 	if (recv_size > hte->comm.buf_size ) {
468 		BYTE *new_buffer;
469 
470 		LogDebug("Increasing communication buffer to %d bytes.", recv_size);
471 		new_buffer = realloc(hte->comm.buf, recv_size);
472 		if (new_buffer == NULL) {
473 			LogError("realloc of %d bytes failed.", recv_size);
474 			result = TSPERR(TSS_E_OUTOFMEMORY);
475 			goto err_exit;
476 		}
477 		buffer = new_buffer + sizeof(struct tcsd_packet_hdr);
478 		hte->comm.buf_size = recv_size;
479 		hte->comm.buf = new_buffer;
480 	}
481 
482 	/* get the rest of the packet */
483 	recv_size -= sizeof(struct tcsd_packet_hdr);    /* already received the header */
484 	if ((recv_size = recv_from_socket(hte->socket, buffer, recv_size)) < 0) {
485 		result = TSPERR(TSS_E_COMM_FAILURE);
486 		goto err_exit;
487 	}
488 
489 	return TSS_SUCCESS;
490 
491 err_exit:
492 	return result;
493 }
494 
495 /* XXX this should be moved out of an RPC-specific file */
496 short
497 get_port(void)
498 {
499 	char *env_port;
500 	int port = 0;
501 
502 	env_port = getenv("TSS_TCSD_PORT");
503 
504 	if (env_port == NULL)
505 		return TCSD_DEFAULT_PORT;
506 
507 	port = atoi(env_port);
508 
509 	if (port == 0 || port > 65535)
510 		return TCSD_DEFAULT_PORT;
511 
512 	return (short)port;
513 }
514 
515