Implemented the ReceiveMessage function on imc/v
[strongswan.git] / src / libimcv / plugins / imc_attestation / imc_attestation.c
1 /*
2 * Copyright (C) 2011 Sansar Choinyambuu
3 * HSR Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include "imc_attestation_state.h"
17
18 #include <imc/imc_agent.h>
19 #include <pa_tnc/pa_tnc_msg.h>
20 #include <ietf/ietf_attr.h>
21 #include <ietf/ietf_attr_pa_tnc_error.h>
22
23 #include <tcg/tcg_pts_attr_proto_caps.h>
24 #include <tcg/tcg_pts_attr_meas_algo.h>
25 #include <tcg/tcg_pts_attr_get_tpm_version_info.h>
26 #include <tcg/tcg_pts_attr_tpm_version_info.h>
27 #include <tcg/tcg_pts_attr_get_aik.h>
28 #include <tcg/tcg_pts_attr_aik.h>
29 #include <tcg/tcg_pts_attr_req_funct_comp_evid.h>
30 #include <tcg/tcg_pts_attr_gen_attest_evid.h>
31 #include <tcg/tcg_pts_attr_simple_comp_evid.h>
32 #include <tcg/tcg_pts_attr_simple_evid_final.h>
33 #include <tcg/tcg_pts_attr_req_file_meas.h>
34 #include <tcg/tcg_pts_attr_file_meas.h>
35
36 #include <tncif_pa_subtypes.h>
37
38 #include <pen/pen.h>
39 #include <debug.h>
40 #include <utils/linked_list.h>
41 #include <crypto/hashers/hasher.h>
42 #include <dirent.h>
43 #include <errno.h>
44
45 #include <trousers/tss.h>
46 #include <trousers/trousers.h>
47
48
49 /* IMC definitions */
50
51 static const char imc_name[] = "Attestation";
52
53 #define IMC_VENDOR_ID PEN_TCG
54 #define IMC_SUBTYPE PA_SUBTYPE_TCG_PTS
55 #define IMC_ATTESTATION_BUF_SIZE 32768
56
57 static imc_agent_t *imc_attestation;
58
59 /**
60 * Supported PTS measurement algorithms
61 */
62 static pts_meas_algorithms_t supported_algorithms = 0;
63
64 /**
65 * PTS Protocol capabilities
66 */
67 static pts_proto_caps_flag_t proto_caps;
68
69 /**
70 * Selected PTS measurement algorithm after attribute exchange
71 */
72 static pts_meas_algorithms_t selected_algorithm = PTS_MEAS_ALGO_SHA256;
73
74 /**
75 * List of files and directories to measure
76 */
77 static linked_list_t *file_list, *directory_list;
78
79 /**
80 * List of file measurements
81 */
82 static linked_list_t *file_measurements;
83
84 /* TODO: Move the struct to some header file? Duplicate with imv_attestation*/
85 /**
86 * Struct to hold file or directory name with the request ID for Request File Measurement attribute
87 */
88 typedef struct measurement_req_entry_t measurement_req_entry_t;
89
90 struct measurement_req_entry_t {
91 char *path;
92 u_int16_t request_id;
93 };
94
95 /**
96 * see section 3.7.1 of TCG TNC IF-IMC Specification 1.2
97 */
98 TNC_Result TNC_IMC_Initialize(TNC_IMCID imc_id,
99 TNC_Version min_version,
100 TNC_Version max_version,
101 TNC_Version *actual_version)
102 {
103 if (imc_attestation)
104 {
105 DBG1(DBG_IMC, "IMC \"%s\" has already been initialized", imc_name);
106 return TNC_RESULT_ALREADY_INITIALIZED;
107 }
108 imc_attestation = imc_agent_create(imc_name, IMC_VENDOR_ID, IMC_SUBTYPE,
109 imc_id, actual_version);
110 if (!imc_attestation ||
111 !tcg_pts_probe_meas_algorithms(&supported_algorithms))
112 {
113 return TNC_RESULT_FATAL;
114 }
115 if (min_version > TNC_IFIMC_VERSION_1 || max_version < TNC_IFIMC_VERSION_1)
116 {
117 DBG1(DBG_IMC, "no common IF-IMC version");
118 return TNC_RESULT_NO_COMMON_VERSION;
119 }
120 return TNC_RESULT_SUCCESS;
121 }
122
123 /**
124 * see section 3.7.2 of TCG TNC IF-IMC Specification 1.2
125 */
126 TNC_Result TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id,
127 TNC_ConnectionID connection_id,
128 TNC_ConnectionState new_state)
129 {
130 imc_state_t *state;
131 /* TODO: Not used so far */
132 //imc_attestation_state_t *attestation_state;
133
134 if (!imc_attestation)
135 {
136 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
137 return TNC_RESULT_NOT_INITIALIZED;
138 }
139 switch (new_state)
140 {
141 case TNC_CONNECTION_STATE_CREATE:
142 state = imc_attestation_state_create(connection_id);
143 return imc_attestation->create_state(imc_attestation, state);
144 case TNC_CONNECTION_STATE_DELETE:
145 return imc_attestation->delete_state(imc_attestation, connection_id);
146 case TNC_CONNECTION_STATE_HANDSHAKE:
147 case TNC_CONNECTION_STATE_ACCESS_ISOLATED:
148 case TNC_CONNECTION_STATE_ACCESS_NONE:
149 default:
150 return imc_attestation->change_state(imc_attestation, connection_id,
151 new_state, NULL);
152 }
153 }
154
155 /**
156 * Get the TPM Version Information
157 */
158 static TSS_RESULT get_tpm_version_info(BYTE *tpm_version_info)
159 {
160 TSS_HCONTEXT hContext;
161 TSS_HTPM hTPM;
162 TSS_RESULT uiResult;
163 UINT32 uiResultLen;
164 /* TODO: Needed for parsing version info on IMV side */
165 //TPM_CAP_VERSION_INFO versionInfo;
166 //UINT64 offset = 0;
167
168 uiResult = Tspi_Context_Create(&hContext);
169 if (uiResult != TSS_SUCCESS) {
170 DBG1(DBG_IMC,"Error 0x%x on Tspi_Context_Create\n", uiResult);
171 return uiResult;
172 }
173 uiResult = Tspi_Context_Connect(hContext, NULL);
174 if (uiResult != TSS_SUCCESS) {
175 DBG1(DBG_IMC,"Error 0x%x on Tspi_Context_Connect\n", uiResult);
176 return uiResult;
177 }
178 uiResult = Tspi_Context_GetTpmObject (hContext, &hTPM);
179 if (uiResult != TSS_SUCCESS) {
180 DBG1(DBG_IMC,"Error 0x%x on Tspi_Context_GetTpmObject\n", uiResult);
181 return uiResult;
182 }
183
184 uiResult = Tspi_TPM_GetCapability(hTPM, TSS_TPMCAP_VERSION_VAL, 0, NULL, &uiResultLen,
185 &tpm_version_info);
186 if (uiResult != TSS_SUCCESS) {
187 DBG1(DBG_IMC,"Error 0x%x on Tspi_TPM_GetCapability\n", uiResult);
188 return uiResult;
189 }
190 }
191
192 /**
193 * Get Hash Measurement of a file
194 */
195 static TNC_Result hash_file(char *path, char *out)
196 {
197 BYTE buffer[IMC_ATTESTATION_BUF_SIZE];
198 FILE *file;
199 int bytes_read;
200 hasher_t *hasher;
201 hash_algorithm_t hash_alg;
202
203 /* Create a hasher */
204 hash_alg = tcg_pts_meas_to_hash_algorithm(selected_algorithm);
205 hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
206 if (!hasher)
207 {
208 DBG1(DBG_IMC, "hasher %N not available", hash_algorithm_names, hash_alg);
209 return TNC_RESULT_FATAL;
210 }
211
212 file = fopen(path, "rb");
213 if (!file)
214 {
215 DBG1(DBG_IMC,"file '%s' can not be opened", path);
216 hasher->destroy(hasher);
217 return TNC_RESULT_FATAL;
218 }
219 while (TRUE)
220 {
221 bytes_read = fread(buffer, 1, sizeof(buffer), file);
222 if (bytes_read > 0)
223 {
224 hasher->get_hash(hasher, chunk_create(buffer, bytes_read), NULL);
225 }
226 else
227 {
228 hasher->get_hash(hasher, chunk_empty, out);
229 break;
230 }
231 }
232 fclose(file);
233 hasher->destroy(hasher);
234
235 return TNC_RESULT_SUCCESS;
236 }
237
238 /**
239 * Get hash of all the files in a directory
240 */
241 static TNC_Result hash_directory(char *path)
242 {
243 DIR *dir;
244 struct dirent *ent;
245 linked_list_t *file_measurements;
246 file_meas_entry_t *entry;
247
248 file_measurements = linked_list_create();
249 entry = malloc_thing(file_meas_entry_t);
250
251 dir = opendir(path);
252 if (dir == NULL)
253 {
254 DBG1(DBG_IMC, "opening directory '%s' failed: %s", path, strerror(errno));
255 return TNC_RESULT_FATAL;
256 }
257 while ((ent = readdir(dir)))
258 {
259 char *file_hash;
260
261 if(hash_file(ent->d_name,file_hash) != TNC_RESULT_SUCCESS)
262 {
263 DBG1(DBG_IMC, "Hashing the given file has failed");
264 return TNC_RESULT_FATAL;
265 }
266
267 entry->measurement = chunk_create(file_hash,strlen(file_hash));
268 entry->file_name_len = strlen(ent->d_name);
269 entry->file_name = chunk_create(ent->d_name,strlen(ent->d_name));
270
271 file_measurements->insert_last(file_measurements,entry);
272 }
273 closedir(dir);
274
275 return TNC_RESULT_SUCCESS;
276 }
277
278 static TNC_Result send_message(TNC_ConnectionID connection_id)
279 {
280 pa_tnc_msg_t *msg;
281 pa_tnc_attr_t *attr;
282 imc_state_t *state;
283 imc_attestation_state_t *attestation_state;
284 imc_attestation_handshake_state_t handshake_state;
285 TNC_Result result;
286
287 if (!imc_attestation->get_state(imc_attestation, connection_id, &state))
288 {
289 return TNC_RESULT_FATAL;
290 }
291 attestation_state = (imc_attestation_state_t*)state;
292 handshake_state = attestation_state->get_handshake_state(attestation_state);
293
294 /* Switch on the attribute type IMC has received */
295 switch (handshake_state)
296 {
297 case IMC_ATTESTATION_STATE_REQ_PROTO_CAP:
298 {
299 pts_proto_caps_flag_t flags;
300 if(proto_caps & PTS_PROTO_CAPS_T)
301 {
302 flags = PTS_PROTO_CAPS_T;
303 }
304 if(proto_caps & PTS_PROTO_CAPS_V)
305 {
306 flags |= PTS_PROTO_CAPS_V;
307 }
308 attr = tcg_pts_attr_proto_caps_create(flags, FALSE);
309 break;
310 }
311 case IMC_ATTESTATION_STATE_REQ_MEAS_ALGO:
312 {
313 attr = tcg_pts_attr_meas_algo_create(selected_algorithm, TRUE);
314 break;
315 }
316 case IMC_ATTESTATION_STATE_GET_TPM_INFO:
317 {
318 TSS_RESULT uiResult;
319 BYTE *tpm_version_info;
320
321 uiResult = get_tpm_version_info(tpm_version_info);
322 if (uiResult != TSS_SUCCESS) {
323 DBG1(DBG_IMC,"Error 0x%x on get_tpm_version_info\n", uiResult);
324 return uiResult;
325 }
326
327 attr = tcg_pts_attr_tpm_version_info_create(
328 chunk_create((char *)tpm_version_info,
329 strlen(tpm_version_info)));
330 break;
331 }
332 case IMC_ATTESTATION_STATE_REQ_FILE_MEAS:
333 {
334 measurement_req_entry_t *entry;
335 enumerator_t *enumerator;
336 tcg_pts_attr_file_meas_t *attr_file_meas;
337 u_int16_t meas_len = HASH_SIZE_SHA1;
338
339 if (selected_algorithm & PTS_MEAS_ALGO_SHA384)
340 {
341 meas_len = HASH_SIZE_SHA384;
342 }
343 else if(selected_algorithm & PTS_MEAS_ALGO_SHA256)
344 {
345 meas_len = HASH_SIZE_SHA512;
346 }
347
348 msg = pa_tnc_msg_create();
349
350 /**
351 * Hash the files and add them as attribute
352 */
353 enumerator = enumerator_create_single(file_list, NULL);
354 while (enumerator->enumerate(enumerator, &entry))
355 {
356 char * file_hash;
357
358 attr = tcg_pts_attr_file_meas_create(1,
359 entry->request_id, meas_len);
360 attr->set_noskip_flag(attr, TRUE);
361 attr_file_meas = (tcg_pts_attr_file_meas_t*)attr;
362
363 if(hash_file(entry->path,file_hash) != TNC_RESULT_SUCCESS)
364 {
365 DBG1(DBG_IMC, "Hashing the given file has failed");
366 return TNC_RESULT_FATAL;
367 }
368 attr_file_meas->add_file_meas(attr_file_meas,
369 chunk_create(file_hash,strlen(file_hash)),
370 chunk_create(entry->path,strlen(entry->path)));
371
372 msg->add_attribute(msg, attr);
373 }
374
375 /**
376 * Hash the files in each directory and add them as attribute
377 */
378 enumerator = enumerator_create_single(directory_list, NULL);
379 while (enumerator->enumerate(enumerator, &entry))
380 {
381 enumerator_t *meas_enumerator;
382 file_meas_entry_t *meas_entry;
383 u_int64_t num_of_files = 0 ;
384
385 if(hash_directory(entry->path) != TNC_RESULT_SUCCESS)
386 {
387 DBG1(DBG_IMC, "Hashing the files in a given directory has failed");
388 return TNC_RESULT_FATAL;
389 }
390
391 attr = tcg_pts_attr_file_meas_create(0,
392 entry->request_id, meas_len);
393 attr->set_noskip_flag(attr, TRUE);
394 attr_file_meas = (tcg_pts_attr_file_meas_t*)attr;
395
396 meas_enumerator = enumerator_create_single(file_measurements, NULL);
397 while (meas_enumerator->enumerate(meas_enumerator, &meas_entry))
398 {
399 num_of_files++;
400 attr_file_meas->add_file_meas(attr_file_meas,
401 meas_entry->measurement,
402 meas_entry->file_name);
403 }
404
405 attr_file_meas->set_number_of_files(attr_file_meas,
406 num_of_files);
407 msg->add_attribute(msg, attr);
408 }
409 enumerator->destroy(enumerator);
410 goto end;
411 }
412 case IMC_ATTESTATION_STATE_GET_AIK:
413 /* TODO: Implement AIK retrieve */
414 case IMC_ATTESTATION_STATE_REQ_FUNCT_COMP_EVID:
415 case IMC_ATTESTATION_STATE_GEN_ATTEST_EVID:
416 case IMC_ATTESTATION_STATE_REQ_FILE_METADATA:
417 case IMC_ATTESTATION_STATE_REQ_IML:
418 case IMC_ATTESTATION_STATE_INIT:
419 DBG1(DBG_IMC, "Attestation IMC has nothing to send: \"%s\"", handshake_state);
420 return TNC_RESULT_FATAL;
421 default:
422 DBG1(DBG_IMC, "Attestation IMC is in unknown state: \"%s\"", handshake_state);
423 return TNC_RESULT_FATAL;
424 }
425
426
427 attr->set_noskip_flag(attr, TRUE);
428 msg = pa_tnc_msg_create();
429 msg->add_attribute(msg, attr);
430
431 end:
432 msg->build(msg);
433 result = imc_attestation->send_message(imc_attestation, connection_id,
434 msg->get_encoding(msg));
435 msg->destroy(msg);
436
437 return result;
438 }
439
440 /**
441 * see section 3.7.3 of TCG TNC IF-IMC Specification 1.2
442 */
443 TNC_Result TNC_IMC_BeginHandshake(TNC_IMCID imc_id,
444 TNC_ConnectionID connection_id)
445 {
446 if (!imc_attestation)
447 {
448 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
449 return TNC_RESULT_NOT_INITIALIZED;
450 }
451 return send_message(connection_id);
452 }
453
454 /**
455 * see section 3.7.4 of TCG TNC IF-IMC Specification 1.2
456 */
457 TNC_Result TNC_IMC_ReceiveMessage(TNC_IMCID imc_id,
458 TNC_ConnectionID connection_id,
459 TNC_BufferReference msg,
460 TNC_UInt32 msg_len,
461 TNC_MessageType msg_type)
462 {
463 pa_tnc_msg_t *pa_tnc_msg;
464 pa_tnc_attr_t *attr;
465 imc_state_t *state;
466 imc_attestation_state_t *attestation_state;
467 imc_attestation_handshake_state_t handshake_state;
468 enumerator_t *enumerator;
469 TNC_Result result;
470 bool fatal_error = FALSE;
471
472 if (!imc_attestation)
473 {
474 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
475 return TNC_RESULT_NOT_INITIALIZED;
476 }
477
478 /* parse received PA-TNC message and automatically handle any errors */
479 result = imc_attestation->receive_message(imc_attestation, connection_id,
480 chunk_create(msg, msg_len), msg_type,
481 &pa_tnc_msg);
482
483 /* no parsed PA-TNC attributes available if an error occurred */
484 if (!pa_tnc_msg)
485 {
486 return result;
487 }
488
489 /* analyze PA-TNC attributes */
490 enumerator = pa_tnc_msg->create_attribute_enumerator(pa_tnc_msg);
491 while (enumerator->enumerate(enumerator, &attr))
492 {
493 if (attr->get_vendor_id(attr) == PEN_IETF &&
494 attr->get_type(attr) == IETF_ATTR_PA_TNC_ERROR)
495 {
496 ietf_attr_pa_tnc_error_t *error_attr;
497 pa_tnc_error_code_t error_code;
498 chunk_t msg_info, attr_info;
499 u_int32_t offset;
500
501 error_attr = (ietf_attr_pa_tnc_error_t*)attr;
502 error_code = error_attr->get_error_code(error_attr);
503 msg_info = error_attr->get_msg_info(error_attr);
504
505 DBG1(DBG_IMC, "received PA-TNC error '%N' concerning message %#B",
506 pa_tnc_error_code_names, error_code, &msg_info);
507 switch (error_code)
508 {
509 case PA_ERROR_INVALID_PARAMETER:
510 offset = error_attr->get_offset(error_attr);
511 DBG1(DBG_IMC, " occurred at offset of %u bytes", offset);
512 break;
513 case PA_ERROR_ATTR_TYPE_NOT_SUPPORTED:
514 attr_info = error_attr->get_attr_info(error_attr);
515 DBG1(DBG_IMC, " unsupported attribute %#B", &attr_info);
516 break;
517 default:
518 break;
519 }
520 fatal_error = TRUE;
521 }
522 else if (attr->get_vendor_id(attr) == PEN_TCG)
523 {
524 /**
525 * Handle TCG PTS attributes
526 */
527
528 /* get current IMC state */
529 if (!imc_attestation->get_state(imc_attestation, connection_id, &state))
530 {
531 return TNC_RESULT_FATAL;
532 }
533 attestation_state = (imc_attestation_state_t*)state;
534
535 switch(attr->get_type(attr))
536 {
537 case TCG_PTS_REQ_PROTO_CAPS:
538 {
539 tcg_pts_attr_proto_caps_t *attr_req_proto_caps;
540
541 attr_req_proto_caps = (tcg_pts_attr_proto_caps_t*)attr;
542 proto_caps = attr_req_proto_caps->get_flags(attr_req_proto_caps);
543
544 handshake_state = IMC_ATTESTATION_STATE_REQ_PROTO_CAP;
545 attestation_state->set_handshake_state(attestation_state,
546 handshake_state);
547 break;
548 }
549 case TCG_PTS_MEAS_ALGO:
550 {
551 tcg_pts_attr_meas_algo_t *attr_meas_algo;
552
553 attr_meas_algo = (tcg_pts_attr_meas_algo_t*)attr;
554 selected_algorithm = attr_meas_algo->get_algorithms(attr_meas_algo);
555 if((supported_algorithms & PTS_MEAS_ALGO_SHA384) &&
556 (selected_algorithm & PTS_MEAS_ALGO_SHA384))
557 {
558 selected_algorithm = PTS_MEAS_ALGO_SHA384;
559 }
560 else if((supported_algorithms & PTS_MEAS_ALGO_SHA256) &&
561 (selected_algorithm & PTS_MEAS_ALGO_SHA256))
562 {
563 selected_algorithm = PTS_MEAS_ALGO_SHA256;
564 }
565 else
566 {
567 selected_algorithm = PTS_MEAS_ALGO_SHA1;
568 }
569
570 handshake_state = IMC_ATTESTATION_STATE_REQ_MEAS_ALGO;
571 attestation_state->set_handshake_state(attestation_state,
572 handshake_state);
573 break;
574 }
575
576 case TCG_PTS_GET_TPM_VERSION_INFO:
577 {
578 handshake_state = IMC_ATTESTATION_STATE_GET_TPM_INFO;
579 attestation_state->set_handshake_state(attestation_state,
580 handshake_state);
581 break;
582 }
583 case TCG_PTS_GET_AIK:
584 {
585 handshake_state = IMC_ATTESTATION_STATE_GET_AIK;
586 attestation_state->set_handshake_state(attestation_state,
587 handshake_state);
588 break;
589 }
590
591 /* PTS-based Attestation Evidence */
592 case TCG_PTS_REQ_FUNCT_COMP_EVID:
593 break;
594 case TCG_PTS_GEN_ATTEST_EVID:
595 break;
596 case TCG_PTS_REQ_FILE_MEAS:
597 {
598 tcg_pts_attr_req_file_meas_t *attr_req_file_meas;
599 measurement_req_entry_t *entry;
600 u_int32_t delimiter;
601
602 attr_req_file_meas = (tcg_pts_attr_req_file_meas_t*)attr;
603 file_list = linked_list_create();
604 directory_list = linked_list_create();
605 delimiter = attr_req_file_meas->get_delimiter(attr_req_file_meas);
606 entry = malloc_thing(measurement_req_entry_t);
607 entry->request_id = attr_req_file_meas->get_request_id(attr_req_file_meas);
608 entry->path = attr_req_file_meas->get_file_path(attr_req_file_meas).ptr;
609
610 (attr_req_file_meas->get_directory_flag(attr_req_file_meas)) ?
611 directory_list->insert_last(directory_list, entry) :
612 file_list->insert_last(file_list, entry);
613
614 handshake_state = IMC_ATTESTATION_STATE_REQ_FILE_MEAS;
615 attestation_state->set_handshake_state(attestation_state,
616 handshake_state);
617 break;
618 }
619
620 /* TODO: Not implemented yet */
621 case TCG_PTS_DH_NONCE_PARAMS_REQ:
622 case TCG_PTS_DH_NONCE_FINISH:
623 case TCG_PTS_REQ_FILE_META:
624 case TCG_PTS_REQ_INTEG_MEAS_LOG:
625 /* Attributes using XML */
626 case TCG_PTS_REQ_TEMPL_REF_MANI_SET_META:
627 case TCG_PTS_UPDATE_TEMPL_REF_MANI:
628 /* On Windows only*/
629 case TCG_PTS_REQ_REGISTRY_VALUE:
630 /* Received on IMV side only*/
631 case TCG_PTS_PROTO_CAPS:
632 case TCG_PTS_DH_NONCE_PARAMS_RESP:
633 case TCG_PTS_MEAS_ALGO_SELECTION:
634 case TCG_PTS_TPM_VERSION_INFO:
635 case TCG_PTS_TEMPL_REF_MANI_SET_META:
636 case TCG_PTS_AIK:
637 case TCG_PTS_SIMPLE_COMP_EVID:
638 case TCG_PTS_SIMPLE_EVID_FINAL:
639 case TCG_PTS_VERIFICATION_RESULT:
640 case TCG_PTS_INTEG_REPORT:
641 case TCG_PTS_UNIX_FILE_META:
642 case TCG_PTS_FILE_MEAS:
643 case TCG_PTS_INTEG_MEAS_LOG:
644 default:
645 DBG1(DBG_IMC, "received unsupported attribute '%N'",
646 tcg_attr_names, attr->get_type(attr));
647 break;
648 }
649
650
651 }
652 }
653 enumerator->destroy(enumerator);
654 pa_tnc_msg->destroy(pa_tnc_msg);
655
656 /* if no error occurred then always return the same response */
657 return fatal_error ? TNC_RESULT_FATAL : send_message(connection_id);
658 }
659
660 /**
661 * see section 3.7.5 of TCG TNC IF-IMC Specification 1.2
662 */
663 TNC_Result TNC_IMC_BatchEnding(TNC_IMCID imc_id,
664 TNC_ConnectionID connection_id)
665 {
666 if (!imc_attestation)
667 {
668 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
669 return TNC_RESULT_NOT_INITIALIZED;
670 }
671 return TNC_RESULT_SUCCESS;
672 }
673
674 /**
675 * see section 3.7.6 of TCG TNC IF-IMC Specification 1.2
676 */
677 TNC_Result TNC_IMC_Terminate(TNC_IMCID imc_id)
678 {
679 if (!imc_attestation)
680 {
681 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
682 return TNC_RESULT_NOT_INITIALIZED;
683 }
684 imc_attestation->destroy(imc_attestation);
685 imc_attestation = NULL;
686
687 return TNC_RESULT_SUCCESS;
688 }
689
690 /**
691 * see section 4.2.8.1 of TCG TNC IF-IMC Specification 1.2
692 */
693 TNC_Result TNC_IMC_ProvideBindFunction(TNC_IMCID imc_id,
694 TNC_TNCC_BindFunctionPointer bind_function)
695 {
696 if (!imc_attestation)
697 {
698 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
699 return TNC_RESULT_NOT_INITIALIZED;
700 }
701 return imc_attestation->bind_functions(imc_attestation, bind_function);
702 }