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