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 37void 38initData(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 50int 51loadData(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 109int 110setData(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 157UINT32 158getData(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 251TSS_RESULT 252sendTCSDPacket(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 298int 299recv_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 322int 323send_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 338TSS_RESULT 339send_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 398err_exit: 399 close(sd); 400 return result; 401} 402 403TSS_RESULT 404tcs_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 456err_exit: 457 return result; 458} 459 460/* TODO: Future work - remove socket creation/manipulation from RPC-specific file */ 461TSS_RESULT 462get_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 512exit: 513 if (res != NULL) 514 freeaddrinfo(res); 515 516 return result; 517} 518