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