Home | History | Annotate | Line # | Download | only in tcstp
      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
     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
     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
    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
    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
    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
    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
    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
    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
    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
    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