2 * Copyright (C) 2011 Sansar Choinyambuu
3 * HSR Hochschule fuer Technik Rapperswil
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>.
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
16 #include "imv_attestation_build.h"
17 #include "imv_attestation_state.h"
20 #include <tcg/tcg_pts_attr_proto_caps.h>
21 #include <tcg/tcg_pts_attr_meas_algo.h>
22 #include <tcg/tcg_pts_attr_dh_nonce_params_req.h>
23 #include <tcg/tcg_pts_attr_dh_nonce_finish.h>
24 #include <tcg/tcg_pts_attr_get_tpm_version_info.h>
25 #include <tcg/tcg_pts_attr_get_aik.h>
26 #include <tcg/tcg_pts_attr_req_funct_comp_evid.h>
27 #include <tcg/tcg_pts_attr_gen_attest_evid.h>
28 #include <tcg/tcg_pts_attr_req_file_meas.h>
29 #include <tcg/tcg_pts_attr_req_file_meta.h>
33 bool imv_attestation_build(pa_tnc_msg_t
*msg
,
34 imv_attestation_state_t
*attestation_state
,
35 pts_meas_algorithms_t supported_algorithms
,
36 pts_dh_group_t supported_dh_groups
,
37 pts_database_t
*pts_db
)
39 imv_attestation_handshake_state_t handshake_state
;
43 handshake_state
= attestation_state
->get_handshake_state(attestation_state
);
44 pts
= attestation_state
->get_pts(attestation_state
);
46 /* D-H attributes are redundant */
47 /* when D-H Nonce Exchange is not selected on IMC side */
48 if (handshake_state
== IMV_ATTESTATION_STATE_NONCE_REQ
&&
49 !(pts
->get_proto_caps(pts
) & PTS_PROTO_CAPS_D
))
51 DBG1(DBG_IMV
, "PTS-IMC is not using Diffie-Hellman Nonce negotiation,"
52 "advancing to TPM Initialization phase");
53 handshake_state
= IMV_ATTESTATION_STATE_TPM_INIT
;
55 /* TPM Version Info, AIK attributes are redundant */
56 /* when TPM is not available on IMC side */
57 if (handshake_state
== IMV_ATTESTATION_STATE_TPM_INIT
&&
58 !(pts
->get_proto_caps(pts
) & PTS_PROTO_CAPS_T
))
60 DBG1(DBG_IMV
, "PTS-IMC has not got TPM available,"
61 "advancing to File Measurement phase");
62 handshake_state
= IMV_ATTESTATION_STATE_MEAS
;
64 /* Component Measurement cannot be done without D-H Nonce Exchange */
65 /* or TPM on IMC side */
66 if (handshake_state
== IMV_ATTESTATION_STATE_COMP_EVID
&&
67 (!(pts
->get_proto_caps(pts
) & PTS_PROTO_CAPS_T
) ||
68 !(pts
->get_proto_caps(pts
) & PTS_PROTO_CAPS_D
)) )
70 DBG1(DBG_IMV
, "PTS-IMC has not got TPM available,"
71 "skipping Component Measurement phase");
72 handshake_state
= IMV_ATTESTATION_STATE_END
;
75 /* Switch on the attribute type IMV has received */
76 switch (handshake_state
)
78 case IMV_ATTESTATION_STATE_INIT
:
80 pts_proto_caps_flag_t flags
;
82 /* Send Request Protocol Capabilities attribute */
83 flags
= pts
->get_proto_caps(pts
);
84 attr
= tcg_pts_attr_proto_caps_create(flags
, TRUE
);
85 attr
->set_noskip_flag(attr
, TRUE
);
86 msg
->add_attribute(msg
, attr
);
88 /* Send Measurement Algorithms attribute */
89 attr
= tcg_pts_attr_meas_algo_create(supported_algorithms
, FALSE
);
90 attr
->set_noskip_flag(attr
, TRUE
);
91 msg
->add_attribute(msg
, attr
);
93 attestation_state
->set_handshake_state(attestation_state
,
94 IMV_ATTESTATION_STATE_NONCE_REQ
);
97 case IMV_ATTESTATION_STATE_NONCE_REQ
:
101 /* Send DH nonce parameters request attribute */
102 min_nonce_len
= lib
->settings
->get_int(lib
->settings
,
103 "libimcv.plugins.imv-attestation.min_nonce_len", 0);
104 attr
= tcg_pts_attr_dh_nonce_params_req_create(min_nonce_len
,
105 supported_dh_groups
);
106 attr
->set_noskip_flag(attr
, TRUE
);
107 msg
->add_attribute(msg
, attr
);
109 attestation_state
->set_handshake_state(attestation_state
,
110 IMV_ATTESTATION_STATE_TPM_INIT
);
113 case IMV_ATTESTATION_STATE_TPM_INIT
:
115 pts_meas_algorithms_t selected_algorithm
;
116 chunk_t initiator_value
, initiator_nonce
;
118 if ((pts
->get_proto_caps(pts
) & PTS_PROTO_CAPS_D
))
120 /* Send DH nonce finish attribute */
121 selected_algorithm
= pts
->get_meas_algorithm(pts
);
122 pts
->get_my_public_value(pts
, &initiator_value
, &initiator_nonce
);
123 attr
= tcg_pts_attr_dh_nonce_finish_create(selected_algorithm
,
124 initiator_value
, initiator_nonce
);
125 attr
->set_noskip_flag(attr
, TRUE
);
126 msg
->add_attribute(msg
, attr
);
129 /* Send Get TPM Version attribute */
130 attr
= tcg_pts_attr_get_tpm_version_info_create();
131 attr
->set_noskip_flag(attr
, TRUE
);
132 msg
->add_attribute(msg
, attr
);
134 /* Send Get AIK attribute */
135 attr
= tcg_pts_attr_get_aik_create();
136 attr
->set_noskip_flag(attr
, TRUE
);
137 msg
->add_attribute(msg
, attr
);
139 attestation_state
->set_handshake_state(attestation_state
,
140 IMV_ATTESTATION_STATE_MEAS
);
143 case IMV_ATTESTATION_STATE_MEAS
:
145 enumerator_t
*enumerator
;
146 u_int32_t delimiter
= SOLIDUS_UTF
;
147 char *platform_info
, *pathname
;
148 u_int16_t request_id
;
152 attestation_state
->set_handshake_state(attestation_state
,
153 IMV_ATTESTATION_STATE_COMP_EVID
);
155 /* Get Platform and OS of the PTS-IMC */
156 platform_info
= pts
->get_platform_info(pts
);
158 if (!pts_db
|| !platform_info
)
160 DBG1(DBG_IMV
, "%s%s%s not available",
161 (pts_db
) ?
"" : "pts database",
162 (!pts_db
&& !platform_info
) ?
"and" : "",
163 (platform_info
) ?
"" : "platform info");
166 DBG1(DBG_IMV
, "platform is '%s'", platform_info
);
168 /* Send Request File Metadata attribute */
169 enumerator
= pts_db
->create_file_meta_enumerator(pts_db
,
175 while (enumerator
->enumerate(enumerator
, &type
, &pathname
))
177 is_dir
= (type
!= 0);
178 DBG2(DBG_IMV
, "metadata request for %s '%s'",
179 is_dir ?
"directory" : "file", pathname
);
180 attr
= tcg_pts_attr_req_file_meta_create(is_dir
, delimiter
,
182 attr
->set_noskip_flag(attr
, TRUE
);
183 msg
->add_attribute(msg
, attr
);
185 enumerator
->destroy(enumerator
);
187 /* Send Request File Measurement attribute */
188 enumerator
= pts_db
->create_file_meas_enumerator(pts_db
,
194 while (enumerator
->enumerate(enumerator
, &id
, &type
, &pathname
))
196 is_dir
= (type
!= 0);
197 request_id
= attestation_state
->add_file_meas_request(
198 attestation_state
, id
, is_dir
);
199 DBG2(DBG_IMV
, "measurement request %d for %s '%s'",
200 request_id
, is_dir ?
"directory" : "file", pathname
);
201 attr
= tcg_pts_attr_req_file_meas_create(is_dir
, request_id
,
202 delimiter
, pathname
);
203 attr
->set_noskip_flag(attr
, TRUE
);
204 msg
->add_attribute(msg
, attr
);
206 enumerator
->destroy(enumerator
);
209 case IMV_ATTESTATION_STATE_COMP_EVID
:
211 enumerator_t
*enumerator
;
214 pts_funct_comp_evid_req_t
*requests
= NULL
;
215 funct_comp_evid_req_entry_t
*entry
;
216 int vid
, name
, qualifier
, type
;
217 enum_name_t
*names
, *types
;
220 attestation_state
->set_handshake_state(attestation_state
,
221 IMV_ATTESTATION_STATE_END
);
223 /* Get Platform and OS of the PTS-IMC */
224 platform_info
= pts
->get_platform_info(pts
);
225 if (!pts_db
|| !platform_info
)
227 DBG1(DBG_IMV
, "%s%s%s not available",
228 (pts_db
) ?
"" : "pts database",
229 (!pts_db
&& !platform_info
) ?
"and" : "",
230 (platform_info
) ?
"" : "platform info");
233 DBG1(DBG_IMV
, "platform is '%s'", platform_info
);
236 enumerator
= pts_db
->create_comp_evid_enumerator(pts_db
, platform_info
);
241 while (enumerator
->enumerate(enumerator
, &vid
, &name
, &qualifier
))
243 entry
= malloc_thing(funct_comp_evid_req_entry_t
);
244 entry
->flags
= PTS_REQ_FUNC_COMP_FLAG_PCR
;
245 entry
->sub_comp_depth
= 0;
246 entry
->name
= pts_comp_func_name_create(vid
, name
, qualifier
);
248 names
= pts_components
->get_comp_func_names(pts_components
, vid
);
249 types
= pts_components
->get_qualifier_type_names(pts_components
, vid
);
252 type
= pts_components
->get_qualifier(pts_components
,
253 entry
->name
, &flags
);
254 DBG2(DBG_TNC
, "%N component evidence request '%N' [%s] '%N'",
255 pen_names
, vid
, names
, name
, flags
, types
, type
);
259 DBG2(DBG_TNC
, "0x%06x component evidence request 0x%08x 0x%02x",
260 vid
, name
, qualifier
);
264 /* Create a requests object */
265 requests
= pts_funct_comp_evid_req_create();
268 requests
->add(requests
, entry
);
269 attestation_state
->add_comp_evid_request(attestation_state
, entry
);
271 enumerator
->destroy(enumerator
);
273 /* Send Request Functional Component Evidence attribute */
274 attr
= tcg_pts_attr_req_funct_comp_evid_create(requests
);
275 attr
->set_noskip_flag(attr
, TRUE
);
276 msg
->add_attribute(msg
, attr
);
278 /* Send Generate Attestation Evidence attribute */
279 attr
= tcg_pts_attr_gen_attest_evid_create();
280 attr
->set_noskip_flag(attr
, TRUE
);
281 msg
->add_attribute(msg
, attr
);
286 DBG1(DBG_IMV
, "Attestation IMV is in unknown state: \"%s\"",