1fbde2c6dc86e03de55f3bb950eb7b0c9a705768
[strongswan.git] / src / libpts / plugins / imv_attestation / imv_attestation_build.c
1 /*
2 * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
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 "imv_attestation_build.h"
17 #include "imv_attestation_state.h"
18
19 #include <tcg/pts/tcg_pts_attr_proto_caps.h>
20 #include <tcg/pts/tcg_pts_attr_meas_algo.h>
21 #include <tcg/pts/tcg_pts_attr_dh_nonce_params_req.h>
22 #include <tcg/pts/tcg_pts_attr_dh_nonce_finish.h>
23 #include <tcg/pts/tcg_pts_attr_get_tpm_version_info.h>
24 #include <tcg/pts/tcg_pts_attr_get_aik.h>
25 #include <tcg/pts/tcg_pts_attr_req_func_comp_evid.h>
26 #include <tcg/pts/tcg_pts_attr_gen_attest_evid.h>
27
28 #include <utils/debug.h>
29
30 bool imv_attestation_build(imv_msg_t *out_msg,
31 imv_state_t *state,
32 pts_meas_algorithms_t supported_algorithms,
33 pts_dh_group_t supported_dh_groups,
34 pts_database_t *pts_db)
35 {
36 imv_attestation_state_t *attestation_state;
37 imv_attestation_handshake_state_t handshake_state;
38 pts_t *pts;
39 pa_tnc_attr_t *attr = NULL;
40
41 attestation_state = (imv_attestation_state_t*)state;
42 handshake_state = attestation_state->get_handshake_state(attestation_state);
43 pts = attestation_state->get_pts(attestation_state);
44
45 /**
46 * Received a response form the Attestation IMC so we can proceeed
47 */
48 if (handshake_state == IMV_ATTESTATION_STATE_DISCOVERY &&
49 (state->get_action_flags(state) & IMV_ATTESTATION_FLAG_ALGO))
50 {
51 handshake_state = IMV_ATTESTATION_STATE_NONCE_REQ;
52 }
53
54 /**
55 * Skip DH Nonce Parameters Request attribute when
56 * DH Nonce Exchange is not selected by PTS-IMC side
57 */
58 if (handshake_state == IMV_ATTESTATION_STATE_NONCE_REQ &&
59 !(pts->get_proto_caps(pts) & PTS_PROTO_CAPS_D))
60 {
61 DBG2(DBG_IMV, "PTS-IMC does not support DH Nonce negotiation");
62 handshake_state = IMV_ATTESTATION_STATE_TPM_INIT;
63 }
64
65 /**
66 * Skip TPM Version Info and AIK attributes when
67 * no TPM is available on the PTS-IMC side
68 */
69 if (handshake_state == IMV_ATTESTATION_STATE_TPM_INIT &&
70 !(pts->get_proto_caps(pts) & PTS_PROTO_CAPS_T))
71 {
72 DBG2(DBG_IMV, "PTS-IMC made no TPM available");
73 handshake_state = IMV_ATTESTATION_STATE_END;
74 }
75
76 switch (handshake_state)
77 {
78 case IMV_ATTESTATION_STATE_INIT:
79 {
80 pts_proto_caps_flag_t flags;
81
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 out_msg->add_attribute(out_msg, attr);
87
88 /* Send Measurement Algorithms attribute */
89 attr = tcg_pts_attr_meas_algo_create(supported_algorithms, FALSE);
90 attr->set_noskip_flag(attr, TRUE);
91 out_msg->add_attribute(out_msg, attr);
92
93 attestation_state->set_handshake_state(attestation_state,
94 IMV_ATTESTATION_STATE_DISCOVERY);
95 break;
96 }
97 case IMV_ATTESTATION_STATE_DISCOVERY:
98 break;
99 case IMV_ATTESTATION_STATE_NONCE_REQ:
100 {
101 int min_nonce_len;
102
103 /* Send DH nonce parameters request attribute */
104 min_nonce_len = lib->settings->get_int(lib->settings,
105 "libimcv.plugins.imv-attestation.min_nonce_len", 0);
106 attr = tcg_pts_attr_dh_nonce_params_req_create(min_nonce_len,
107 supported_dh_groups);
108 attr->set_noskip_flag(attr, TRUE);
109 out_msg->add_attribute(out_msg, attr);
110
111 attestation_state->set_handshake_state(attestation_state,
112 IMV_ATTESTATION_STATE_TPM_INIT);
113 break;
114 }
115 case IMV_ATTESTATION_STATE_TPM_INIT:
116 {
117 pts_meas_algorithms_t selected_algorithm;
118 chunk_t initiator_value, initiator_nonce;
119
120 if ((pts->get_proto_caps(pts) & PTS_PROTO_CAPS_D))
121 {
122 /* Send DH nonce finish attribute */
123 selected_algorithm = pts->get_meas_algorithm(pts);
124 pts->get_my_public_value(pts, &initiator_value, &initiator_nonce);
125 attr = tcg_pts_attr_dh_nonce_finish_create(selected_algorithm,
126 initiator_value, initiator_nonce);
127 attr->set_noskip_flag(attr, TRUE);
128 out_msg->add_attribute(out_msg, attr);
129 }
130
131 /* Send Get TPM Version attribute */
132 attr = tcg_pts_attr_get_tpm_version_info_create();
133 attr->set_noskip_flag(attr, TRUE);
134 out_msg->add_attribute(out_msg, attr);
135
136 /* Send Get AIK attribute */
137 attr = tcg_pts_attr_get_aik_create();
138 attr->set_noskip_flag(attr, TRUE);
139 out_msg->add_attribute(out_msg, attr);
140
141 attestation_state->set_handshake_state(attestation_state,
142 IMV_ATTESTATION_STATE_COMP_EVID);
143 break;
144 }
145 case IMV_ATTESTATION_STATE_COMP_EVID:
146 {
147 tcg_pts_attr_req_func_comp_evid_t *attr_cast;
148 enumerator_t *enumerator;
149 pts_component_t *comp;
150 pts_comp_func_name_t *comp_name;
151 chunk_t keyid;
152 int kid, vid, name, qualifier;
153 u_int8_t flags;
154 u_int32_t depth;
155 bool first = TRUE, first_component = TRUE;
156
157 attestation_state->set_handshake_state(attestation_state,
158 IMV_ATTESTATION_STATE_END);
159
160 if (!(pts->get_proto_caps(pts) & PTS_PROTO_CAPS_T) ||
161 !(pts->get_proto_caps(pts) & PTS_PROTO_CAPS_D))
162 {
163 DBG2(DBG_IMV, "PTS-IMC made no TPM available - "
164 "skipping Component Measurements");
165 break;
166 }
167 if (!pts->get_aik_keyid(pts, &keyid))
168 {
169 DBG1(DBG_IMV, "retrieval of AIK keyid failed");
170 return FALSE;
171 }
172 if (!pts_db)
173 {
174 DBG1(DBG_IMV, "pts database not available");
175 break;
176 }
177 if (pts_db->check_aik_keyid(pts_db, keyid, &kid) != SUCCESS)
178 {
179 return FALSE;
180 }
181 enumerator = pts_db->create_comp_evid_enumerator(pts_db, kid);
182 if (!enumerator)
183 {
184 break;
185 }
186 while (enumerator->enumerate(enumerator, &vid, &name,
187 &qualifier, &depth))
188 {
189 if (first)
190 {
191 DBG2(DBG_IMV, "evidence request by");
192 first = FALSE;
193 }
194 comp_name = pts_comp_func_name_create(vid, name, qualifier);
195 comp_name->log(comp_name, " ");
196
197 comp = attestation_state->create_component(attestation_state,
198 comp_name, depth, pts_db);
199 if (!comp)
200 {
201 DBG2(DBG_IMV, " not registered or duplicate"
202 " - removed from request");
203 comp_name->destroy(comp_name);
204 continue;
205 }
206 if (first_component)
207 {
208 attr = tcg_pts_attr_req_func_comp_evid_create();
209 attr->set_noskip_flag(attr, TRUE);
210 first_component = FALSE;
211 }
212 flags = comp->get_evidence_flags(comp);
213 /* TODO check flags against negotiated_caps */
214 attr_cast = (tcg_pts_attr_req_func_comp_evid_t *)attr;
215 attr_cast->add_component(attr_cast, flags, depth, comp_name);
216 }
217 enumerator->destroy(enumerator);
218
219 if (attr)
220 {
221 /* Send Request Functional Component Evidence attribute */
222 out_msg->add_attribute(out_msg, attr);
223
224 /* Send Generate Attestation Evidence attribute */
225 attr = tcg_pts_attr_gen_attest_evid_create();
226 attr->set_noskip_flag(attr, TRUE);
227 out_msg->add_attribute(out_msg, attr);
228
229 attestation_state->set_handshake_state(attestation_state,
230 IMV_ATTESTATION_STATE_EVID_FINAL);
231 }
232 break;
233 }
234 case IMV_ATTESTATION_STATE_EVID_FINAL:
235 if (attestation_state->components_finalized(attestation_state))
236 {
237 attestation_state->set_handshake_state(attestation_state,
238 IMV_ATTESTATION_STATE_END);
239 }
240 break;
241 case IMV_ATTESTATION_STATE_END:
242 attestation_state->set_handshake_state(attestation_state,
243 IMV_ATTESTATION_STATE_END);
244 break;
245 }
246 return TRUE;
247 }