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