log selected PTS measurement algorithm
[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 || !pts_meas_probe_algorithms(&supported_algorithms))
111 {
112 return TNC_RESULT_FATAL;
113 }
114 if (min_version > TNC_IFIMC_VERSION_1 || max_version < TNC_IFIMC_VERSION_1)
115 {
116 DBG1(DBG_IMC, "no common IF-IMC version");
117 return TNC_RESULT_NO_COMMON_VERSION;
118 }
119 return TNC_RESULT_SUCCESS;
120 }
121
122 /**
123 * see section 3.7.2 of TCG TNC IF-IMC Specification 1.2
124 */
125 TNC_Result TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id,
126 TNC_ConnectionID connection_id,
127 TNC_ConnectionState new_state)
128 {
129 imc_state_t *state;
130 /* TODO: Not used so far */
131 //imc_attestation_state_t *attestation_state;
132
133 if (!imc_attestation)
134 {
135 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
136 return TNC_RESULT_NOT_INITIALIZED;
137 }
138 switch (new_state)
139 {
140 case TNC_CONNECTION_STATE_CREATE:
141 state = imc_attestation_state_create(connection_id);
142 return imc_attestation->create_state(imc_attestation, state);
143 case TNC_CONNECTION_STATE_DELETE:
144 return imc_attestation->delete_state(imc_attestation, connection_id);
145 case TNC_CONNECTION_STATE_HANDSHAKE:
146 case TNC_CONNECTION_STATE_ACCESS_ISOLATED:
147 case TNC_CONNECTION_STATE_ACCESS_NONE:
148 default:
149 return imc_attestation->change_state(imc_attestation, connection_id,
150 new_state, NULL);
151 }
152 }
153
154 /**
155 * Get the TPM Version Information
156 */
157 static TSS_RESULT get_tpm_version_info(BYTE *tpm_version_info)
158 {
159 TSS_HCONTEXT hContext;
160 TSS_HTPM hTPM;
161 TSS_RESULT uiResult;
162 UINT32 uiResultLen;
163 /* TODO: Needed for parsing version info on IMV side */
164 //TPM_CAP_VERSION_INFO versionInfo;
165 //UINT64 offset = 0;
166
167 uiResult = Tspi_Context_Create(&hContext);
168 if (uiResult != TSS_SUCCESS) {
169 DBG1(DBG_IMC,"Error 0x%x on Tspi_Context_Create\n", uiResult);
170 return uiResult;
171 }
172 uiResult = Tspi_Context_Connect(hContext, NULL);
173 if (uiResult != TSS_SUCCESS) {
174 DBG1(DBG_IMC,"Error 0x%x on Tspi_Context_Connect\n", uiResult);
175 return uiResult;
176 }
177 uiResult = Tspi_Context_GetTpmObject (hContext, &hTPM);
178 if (uiResult != TSS_SUCCESS) {
179 DBG1(DBG_IMC,"Error 0x%x on Tspi_Context_GetTpmObject\n", uiResult);
180 return uiResult;
181 }
182
183 uiResult = Tspi_TPM_GetCapability(hTPM, TSS_TPMCAP_VERSION_VAL, 0, NULL, &uiResultLen,
184 &tpm_version_info);
185 if (uiResult != TSS_SUCCESS) {
186 DBG1(DBG_IMC,"Error 0x%x on Tspi_TPM_GetCapability\n", uiResult);
187 return uiResult;
188 }
189 }
190
191 /**
192 * Get Hash Measurement of a file
193 */
194 static TNC_Result hash_file(char *path, char *out)
195 {
196 BYTE buffer[IMC_ATTESTATION_BUF_SIZE];
197 FILE *file;
198 int bytes_read;
199 hasher_t *hasher;
200 hash_algorithm_t hash_alg;
201
202 /* Create a hasher */
203 hash_alg = pts_meas_to_hash_algorithm(selected_algorithm);
204 hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
205 if (!hasher)
206 {
207 DBG1(DBG_IMC, "hasher %N not available", hash_algorithm_names, hash_alg);
208 return TNC_RESULT_FATAL;
209 }
210
211 file = fopen(path, "rb");
212 if (!file)
213 {
214 DBG1(DBG_IMC,"file '%s' can not be opened", path);
215 hasher->destroy(hasher);
216 return TNC_RESULT_FATAL;
217 }
218 while (TRUE)
219 {
220 bytes_read = fread(buffer, 1, sizeof(buffer), file);
221 if (bytes_read > 0)
222 {
223 hasher->get_hash(hasher, chunk_create(buffer, bytes_read), NULL);
224 }
225 else
226 {
227 hasher->get_hash(hasher, chunk_empty, out);
228 break;
229 }
230 }
231 fclose(file);
232 hasher->destroy(hasher);
233
234 return TNC_RESULT_SUCCESS;
235 }
236
237 /**
238 * Get hash of all the files in a directory
239 */
240 static TNC_Result hash_directory(char *path)
241 {
242 DIR *dir;
243 struct dirent *ent;
244 linked_list_t *file_measurements;
245 file_meas_entry_t *entry;
246
247 file_measurements = linked_list_create();
248 entry = malloc_thing(file_meas_entry_t);
249
250 dir = opendir(path);
251 if (dir == NULL)
252 {
253 DBG1(DBG_IMC, "opening directory '%s' failed: %s", path, strerror(errno));
254 return TNC_RESULT_FATAL;
255 }
256 while ((ent = readdir(dir)))
257 {
258 char *file_hash;
259
260 if(hash_file(ent->d_name,file_hash) != TNC_RESULT_SUCCESS)
261 {
262 DBG1(DBG_IMC, "Hashing the given file has failed");
263 return TNC_RESULT_FATAL;
264 }
265
266 entry->measurement = chunk_create(file_hash,strlen(file_hash));
267 entry->file_name_len = strlen(ent->d_name);
268 entry->file_name = chunk_create(ent->d_name,strlen(ent->d_name));
269
270 file_measurements->insert_last(file_measurements,entry);
271 }
272 closedir(dir);
273
274 return TNC_RESULT_SUCCESS;
275 }
276
277 static TNC_Result send_message(TNC_ConnectionID connection_id)
278 {
279 pa_tnc_msg_t *msg;
280 pa_tnc_attr_t *attr;
281 imc_state_t *state;
282 imc_attestation_state_t *attestation_state;
283 imc_attestation_handshake_state_t handshake_state;
284 TNC_Result result;
285
286 if (!imc_attestation->get_state(imc_attestation, connection_id, &state))
287 {
288 return TNC_RESULT_FATAL;
289 }
290 attestation_state = (imc_attestation_state_t*)state;
291 handshake_state = attestation_state->get_handshake_state(attestation_state);
292
293 /* Switch on the attribute type IMC has received */
294 switch (handshake_state)
295 {
296 case IMC_ATTESTATION_STATE_REQ_PROTO_CAP:
297 {
298 pts_proto_caps_flag_t flags;
299 if(proto_caps & PTS_PROTO_CAPS_T)
300 {
301 flags = PTS_PROTO_CAPS_T;
302 }
303 if(proto_caps & PTS_PROTO_CAPS_V)
304 {
305 flags |= PTS_PROTO_CAPS_V;
306 }
307 attr = tcg_pts_attr_proto_caps_create(flags, FALSE);
308 break;
309 }
310 case IMC_ATTESTATION_STATE_REQ_MEAS_ALGO:
311 {
312 attr = tcg_pts_attr_meas_algo_create(selected_algorithm, TRUE);
313 break;
314 }
315 case IMC_ATTESTATION_STATE_GET_TPM_INFO:
316 {
317 TSS_RESULT uiResult;
318 BYTE *tpm_version_info;
319
320 uiResult = get_tpm_version_info(tpm_version_info);
321 if (uiResult != TSS_SUCCESS) {
322 DBG1(DBG_IMC,"Error 0x%x on get_tpm_version_info\n", uiResult);
323 return uiResult;
324 }
325
326 attr = tcg_pts_attr_tpm_version_info_create(
327 chunk_create((char *)tpm_version_info,
328 strlen(tpm_version_info)));
329 break;
330 }
331 case IMC_ATTESTATION_STATE_REQ_FILE_MEAS:
332 {
333 measurement_req_entry_t *entry;
334 enumerator_t *enumerator;
335 tcg_pts_attr_file_meas_t *attr_file_meas;
336 u_int16_t meas_len = HASH_SIZE_SHA1;
337
338 if (selected_algorithm & PTS_MEAS_ALGO_SHA384)
339 {
340 meas_len = HASH_SIZE_SHA384;
341 }
342 else if(selected_algorithm & PTS_MEAS_ALGO_SHA256)
343 {
344 meas_len = HASH_SIZE_SHA512;
345 }
346
347 msg = pa_tnc_msg_create();
348
349 /**
350 * Hash the files and add them as attribute
351 */
352 enumerator = enumerator_create_single(file_list, NULL);
353 while (enumerator->enumerate(enumerator, &entry))
354 {
355 char * file_hash;
356
357 attr = tcg_pts_attr_file_meas_create(1,
358 entry->request_id, meas_len);
359 attr->set_noskip_flag(attr, TRUE);
360 attr_file_meas = (tcg_pts_attr_file_meas_t*)attr;
361
362 if(hash_file(entry->path,file_hash) != TNC_RESULT_SUCCESS)
363 {
364 DBG1(DBG_IMC, "Hashing the given file has failed");
365 return TNC_RESULT_FATAL;
366 }
367 attr_file_meas->add_file_meas(attr_file_meas,
368 chunk_create(file_hash,strlen(file_hash)),
369 chunk_create(entry->path,strlen(entry->path)));
370
371 msg->add_attribute(msg, attr);
372 }
373
374 /**
375 * Hash the files in each directory and add them as attribute
376 */
377 enumerator = enumerator_create_single(directory_list, NULL);
378 while (enumerator->enumerate(enumerator, &entry))
379 {
380 enumerator_t *meas_enumerator;
381 file_meas_entry_t *meas_entry;
382 u_int64_t num_of_files = 0 ;
383
384 if(hash_directory(entry->path) != TNC_RESULT_SUCCESS)
385 {
386 DBG1(DBG_IMC, "Hashing the files in a given directory has failed");
387 return TNC_RESULT_FATAL;
388 }
389
390 attr = tcg_pts_attr_file_meas_create(0,
391 entry->request_id, meas_len);
392 attr->set_noskip_flag(attr, TRUE);
393 attr_file_meas = (tcg_pts_attr_file_meas_t*)attr;
394
395 meas_enumerator = enumerator_create_single(file_measurements, NULL);
396 while (meas_enumerator->enumerate(meas_enumerator, &meas_entry))
397 {
398 num_of_files++;
399 attr_file_meas->add_file_meas(attr_file_meas,
400 meas_entry->measurement,
401 meas_entry->file_name);
402 }
403
404 attr_file_meas->set_number_of_files(attr_file_meas,
405 num_of_files);
406 msg->add_attribute(msg, attr);
407 }
408 enumerator->destroy(enumerator);
409 goto end;
410 }
411 case IMC_ATTESTATION_STATE_GET_AIK:
412 /* TODO: Implement AIK retrieve */
413 case IMC_ATTESTATION_STATE_REQ_FUNCT_COMP_EVID:
414 case IMC_ATTESTATION_STATE_GEN_ATTEST_EVID:
415 case IMC_ATTESTATION_STATE_REQ_FILE_METADATA:
416 case IMC_ATTESTATION_STATE_REQ_IML:
417 case IMC_ATTESTATION_STATE_INIT:
418 DBG1(DBG_IMC, "Attestation IMC has nothing to send: \"%s\"", handshake_state);
419 return TNC_RESULT_FATAL;
420 default:
421 DBG1(DBG_IMC, "Attestation IMC is in unknown state: \"%s\"", handshake_state);
422 return TNC_RESULT_FATAL;
423 }
424
425
426 attr->set_noskip_flag(attr, TRUE);
427 msg = pa_tnc_msg_create();
428 msg->add_attribute(msg, attr);
429
430 end:
431 msg->build(msg);
432 result = imc_attestation->send_message(imc_attestation, connection_id,
433 msg->get_encoding(msg));
434 msg->destroy(msg);
435
436 return result;
437 }
438
439 /**
440 * see section 3.7.3 of TCG TNC IF-IMC Specification 1.2
441 */
442 TNC_Result TNC_IMC_BeginHandshake(TNC_IMCID imc_id,
443 TNC_ConnectionID connection_id)
444 {
445 if (!imc_attestation)
446 {
447 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
448 return TNC_RESULT_NOT_INITIALIZED;
449 }
450 return send_message(connection_id);
451 }
452
453 /**
454 * see section 3.7.4 of TCG TNC IF-IMC Specification 1.2
455 */
456 TNC_Result TNC_IMC_ReceiveMessage(TNC_IMCID imc_id,
457 TNC_ConnectionID connection_id,
458 TNC_BufferReference msg,
459 TNC_UInt32 msg_len,
460 TNC_MessageType msg_type)
461 {
462 pa_tnc_msg_t *pa_tnc_msg;
463 pa_tnc_attr_t *attr;
464 imc_state_t *state;
465 imc_attestation_state_t *attestation_state;
466 enumerator_t *enumerator;
467 TNC_Result result;
468 bool fatal_error = FALSE;
469
470 if (!imc_attestation)
471 {
472 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
473 return TNC_RESULT_NOT_INITIALIZED;
474 }
475
476 /* parse received PA-TNC message and automatically handle any errors */
477 result = imc_attestation->receive_message(imc_attestation, connection_id,
478 chunk_create(msg, msg_len), msg_type,
479 &pa_tnc_msg);
480
481 /* no parsed PA-TNC attributes available if an error occurred */
482 if (!pa_tnc_msg)
483 {
484 return result;
485 }
486
487 /* analyze PA-TNC attributes */
488 enumerator = pa_tnc_msg->create_attribute_enumerator(pa_tnc_msg);
489 while (enumerator->enumerate(enumerator, &attr))
490 {
491 if (attr->get_vendor_id(attr) == PEN_IETF &&
492 attr->get_type(attr) == IETF_ATTR_PA_TNC_ERROR)
493 {
494 ietf_attr_pa_tnc_error_t *error_attr;
495 pa_tnc_error_code_t error_code;
496 chunk_t msg_info, attr_info;
497 u_int32_t offset;
498
499 error_attr = (ietf_attr_pa_tnc_error_t*)attr;
500 error_code = error_attr->get_error_code(error_attr);
501 msg_info = error_attr->get_msg_info(error_attr);
502
503 DBG1(DBG_IMC, "received PA-TNC error '%N' concerning message %#B",
504 pa_tnc_error_code_names, error_code, &msg_info);
505 switch (error_code)
506 {
507 case PA_ERROR_INVALID_PARAMETER:
508 offset = error_attr->get_offset(error_attr);
509 DBG1(DBG_IMC, " occurred at offset of %u bytes", offset);
510 break;
511 case PA_ERROR_ATTR_TYPE_NOT_SUPPORTED:
512 attr_info = error_attr->get_attr_info(error_attr);
513 DBG1(DBG_IMC, " unsupported attribute %#B", &attr_info);
514 break;
515 default:
516 break;
517 }
518 fatal_error = TRUE;
519 }
520 else if (attr->get_vendor_id(attr) == PEN_TCG)
521 {
522 /**
523 * Handle TCG PTS attributes
524 */
525
526 /* get current IMC state */
527 if (!imc_attestation->get_state(imc_attestation, connection_id, &state))
528 {
529 return TNC_RESULT_FATAL;
530 }
531 attestation_state = (imc_attestation_state_t*)state;
532
533 switch(attr->get_type(attr))
534 {
535 case TCG_PTS_REQ_PROTO_CAPS:
536 {
537 tcg_pts_attr_proto_caps_t *attr_req_proto_caps;
538
539 attr_req_proto_caps = (tcg_pts_attr_proto_caps_t*)attr;
540 proto_caps = attr_req_proto_caps->get_flags(attr_req_proto_caps);
541
542 attestation_state->set_handshake_state(attestation_state,
543 IMC_ATTESTATION_STATE_REQ_PROTO_CAP);
544 break;
545 }
546 case TCG_PTS_MEAS_ALGO:
547 {
548 tcg_pts_attr_meas_algo_t *attr_meas_algo;
549
550 attr_meas_algo = (tcg_pts_attr_meas_algo_t*)attr;
551 selected_algorithm = attr_meas_algo->get_algorithms(attr_meas_algo);
552
553 if ((supported_algorithms & PTS_MEAS_ALGO_SHA384) &&
554 (selected_algorithm & PTS_MEAS_ALGO_SHA384))
555 {
556 selected_algorithm = PTS_MEAS_ALGO_SHA384;
557 }
558 else if (selected_algorithm & PTS_MEAS_ALGO_SHA256)
559 {
560 selected_algorithm = PTS_MEAS_ALGO_SHA256;
561 }
562 else if (selected_algorithm & PTS_MEAS_ALGO_SHA1)
563 {
564 selected_algorithm = PTS_MEAS_ALGO_SHA1;
565 }
566 else
567 {
568 /* TODO generate an error message */
569 selected_algorithm = PTS_MEAS_ALGO_SHA256;
570 }
571 DBG2(DBG_IMC, "selected PTS measurement algorithm is %N",
572 hash_algorithm_names,
573 pts_meas_to_hash_algorithm(selected_algorithm));
574
575 attestation_state->set_handshake_state(attestation_state,
576 IMC_ATTESTATION_STATE_REQ_MEAS_ALGO);
577 break;
578 }
579
580 case TCG_PTS_GET_TPM_VERSION_INFO:
581 {
582 attestation_state->set_handshake_state(attestation_state,
583 IMC_ATTESTATION_STATE_GET_TPM_INFO);
584 break;
585 }
586 case TCG_PTS_GET_AIK:
587 {
588 attestation_state->set_handshake_state(attestation_state,
589 IMC_ATTESTATION_STATE_GET_AIK);
590 break;
591 }
592
593 /* PTS-based Attestation Evidence */
594 case TCG_PTS_REQ_FUNCT_COMP_EVID:
595 break;
596 case TCG_PTS_GEN_ATTEST_EVID:
597 break;
598 case TCG_PTS_REQ_FILE_MEAS:
599 {
600 tcg_pts_attr_req_file_meas_t *attr_req_file_meas;
601 measurement_req_entry_t *entry;
602 u_int32_t delimiter;
603
604 attr_req_file_meas = (tcg_pts_attr_req_file_meas_t*)attr;
605 file_list = linked_list_create();
606 directory_list = linked_list_create();
607 delimiter = attr_req_file_meas->get_delimiter(attr_req_file_meas);
608 entry = malloc_thing(measurement_req_entry_t);
609 entry->request_id = attr_req_file_meas->get_request_id(attr_req_file_meas);
610 entry->path = attr_req_file_meas->get_file_path(attr_req_file_meas).ptr;
611
612 (attr_req_file_meas->get_directory_flag(attr_req_file_meas)) ?
613 directory_list->insert_last(directory_list, entry) :
614 file_list->insert_last(file_list, entry);
615
616 attestation_state->set_handshake_state(attestation_state,
617 IMC_ATTESTATION_STATE_REQ_FILE_MEAS);
618 break;
619 }
620
621 /* TODO: Not implemented yet */
622 case TCG_PTS_DH_NONCE_PARAMS_REQ:
623 case TCG_PTS_DH_NONCE_FINISH:
624 case TCG_PTS_REQ_FILE_META:
625 case TCG_PTS_REQ_INTEG_MEAS_LOG:
626 /* Attributes using XML */
627 case TCG_PTS_REQ_TEMPL_REF_MANI_SET_META:
628 case TCG_PTS_UPDATE_TEMPL_REF_MANI:
629 /* On Windows only*/
630 case TCG_PTS_REQ_REGISTRY_VALUE:
631 /* Received on IMV side only*/
632 case TCG_PTS_PROTO_CAPS:
633 case TCG_PTS_DH_NONCE_PARAMS_RESP:
634 case TCG_PTS_MEAS_ALGO_SELECTION:
635 case TCG_PTS_TPM_VERSION_INFO:
636 case TCG_PTS_TEMPL_REF_MANI_SET_META:
637 case TCG_PTS_AIK:
638 case TCG_PTS_SIMPLE_COMP_EVID:
639 case TCG_PTS_SIMPLE_EVID_FINAL:
640 case TCG_PTS_VERIFICATION_RESULT:
641 case TCG_PTS_INTEG_REPORT:
642 case TCG_PTS_UNIX_FILE_META:
643 case TCG_PTS_FILE_MEAS:
644 case TCG_PTS_INTEG_MEAS_LOG:
645 default:
646 DBG1(DBG_IMC, "received unsupported attribute '%N'",
647 tcg_attr_names, attr->get_type(attr));
648 break;
649 }
650
651
652 }
653 }
654 enumerator->destroy(enumerator);
655 pa_tnc_msg->destroy(pa_tnc_msg);
656
657 /* if no error occurred then always return the same response */
658 return fatal_error ? TNC_RESULT_FATAL : send_message(connection_id);
659 }
660
661 /**
662 * see section 3.7.5 of TCG TNC IF-IMC Specification 1.2
663 */
664 TNC_Result TNC_IMC_BatchEnding(TNC_IMCID imc_id,
665 TNC_ConnectionID connection_id)
666 {
667 if (!imc_attestation)
668 {
669 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
670 return TNC_RESULT_NOT_INITIALIZED;
671 }
672 return TNC_RESULT_SUCCESS;
673 }
674
675 /**
676 * see section 3.7.6 of TCG TNC IF-IMC Specification 1.2
677 */
678 TNC_Result TNC_IMC_Terminate(TNC_IMCID imc_id)
679 {
680 if (!imc_attestation)
681 {
682 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
683 return TNC_RESULT_NOT_INITIALIZED;
684 }
685 imc_attestation->destroy(imc_attestation);
686 imc_attestation = NULL;
687
688 return TNC_RESULT_SUCCESS;
689 }
690
691 /**
692 * see section 4.2.8.1 of TCG TNC IF-IMC Specification 1.2
693 */
694 TNC_Result TNC_IMC_ProvideBindFunction(TNC_IMCID imc_id,
695 TNC_TNCC_BindFunctionPointer bind_function)
696 {
697 if (!imc_attestation)
698 {
699 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
700 return TNC_RESULT_NOT_INITIALIZED;
701 }
702 return imc_attestation->bind_functions(imc_attestation, bind_function);
703 }