c403d06f92fe0847b598d1c725c10f973c208e80
[strongswan.git] / src / libimcv / tcg / swid / tcg_swid_attr_req.c
1 /*
2 * Copyright (C) 2013 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 "tcg_swid_attr_req.h"
17
18 #include "swid/swid_tag_id.h"
19
20 #include <pa_tnc/pa_tnc_msg.h>
21 #include <bio/bio_writer.h>
22 #include <bio/bio_reader.h>
23 #include <utils/debug.h>
24 #include <collections/linked_list.h>
25
26 typedef struct private_tcg_swid_attr_req_t private_tcg_swid_attr_req_t;
27
28 /**
29 * SWID Request
30 * see section 4.7 of TCG TNC SWID Message and Attributes for IF-M
31 *
32 * 1 2 3
33 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
34 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
35 * |Reserved |C|S|R| Tag ID Count |
36 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
37 * | Request ID |
38 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
39 * | Earliest EID |
40 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
41 * | Tag Creator Length | Tag Creator (variable length) |
42 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
43 * | Unique Software ID Length |Unique Software ID (var length)|
44 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
45 */
46
47 #define SWID_REQ_RESERVED_MASK 0x03
48
49 /**
50 * Private data of an tcg_swid_attr_req_t object.
51 */
52 struct private_tcg_swid_attr_req_t {
53
54 /**
55 * Public members of tcg_swid_attr_req_t
56 */
57 tcg_swid_attr_req_t public;
58
59 /**
60 * Vendor-specific attribute type
61 */
62 pen_type_t type;
63
64 /**
65 * Attribute value
66 */
67 chunk_t value;
68
69 /**
70 * Noskip flag
71 */
72 bool noskip_flag;
73
74 /**
75 * SWID request flags
76 */
77 u_int8_t flags;
78
79 /**
80 * Request ID
81 */
82 u_int32_t request_id;
83
84 /**
85 * Earliest EID
86 */
87 u_int32_t earliest_eid;
88
89 /**
90 * List of Target Tag Identifiers
91 */
92 swid_inventory_t *targets;
93
94 /**
95 * Reference count
96 */
97 refcount_t ref;
98 };
99
100 METHOD(pa_tnc_attr_t, get_type, pen_type_t,
101 private_tcg_swid_attr_req_t *this)
102 {
103 return this->type;
104 }
105
106 METHOD(pa_tnc_attr_t, get_value, chunk_t,
107 private_tcg_swid_attr_req_t *this)
108 {
109 return this->value;
110 }
111
112 METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
113 private_tcg_swid_attr_req_t *this)
114 {
115 return this->noskip_flag;
116 }
117
118 METHOD(pa_tnc_attr_t, set_noskip_flag,void,
119 private_tcg_swid_attr_req_t *this, bool noskip)
120 {
121 this->noskip_flag = noskip;
122 }
123
124 METHOD(pa_tnc_attr_t, build, void,
125 private_tcg_swid_attr_req_t *this)
126 {
127 bio_writer_t *writer;
128 chunk_t tag_creator, unique_sw_id;
129 swid_tag_id_t *tag_id;
130 enumerator_t *enumerator;
131
132 if (this->value.ptr)
133 {
134 return;
135 }
136
137 writer = bio_writer_create(TCG_SWID_REQ_MIN_SIZE);
138 writer->write_uint8 (writer, this->flags);
139 writer->write_uint24(writer, this->targets->get_count(this->targets));
140 writer->write_uint32(writer, this->request_id);
141 writer->write_uint32(writer, this->earliest_eid);
142
143 enumerator = this->targets->create_enumerator(this->targets);
144 while (enumerator->enumerate(enumerator, &tag_id))
145 {
146 tag_creator = tag_id->get_tag_creator(tag_id);
147 unique_sw_id = tag_id->get_unique_sw_id(tag_id, NULL);
148 writer->write_data16(writer, tag_creator);
149 writer->write_data16(writer, unique_sw_id);
150 }
151 enumerator->destroy(enumerator);
152
153 this->value = writer->extract_buf(writer);
154 writer->destroy(writer);
155 }
156
157 METHOD(pa_tnc_attr_t, process, status_t,
158 private_tcg_swid_attr_req_t *this, u_int32_t *offset)
159 {
160 bio_reader_t *reader;
161 u_int32_t tag_id_count;
162 chunk_t tag_creator, unique_sw_id;
163 swid_tag_id_t *tag_id;
164
165 if (this->value.len < TCG_SWID_REQ_MIN_SIZE)
166 {
167 DBG1(DBG_TNC, "insufficient data for SWID Request");
168 *offset = 0;
169 return FAILED;
170 }
171
172 reader = bio_reader_create(this->value);
173 reader->read_uint8 (reader, &this->flags);
174 reader->read_uint24(reader, &tag_id_count);
175 reader->read_uint32(reader, &this->request_id);
176 reader->read_uint32(reader, &this->earliest_eid);
177
178 if (this->request_id == 0)
179 {
180 *offset = 4;
181 return FAILED;
182 }
183 *offset = TCG_SWID_REQ_MIN_SIZE;
184
185 this->flags &= SWID_REQ_RESERVED_MASK;
186
187 while (tag_id_count--)
188 {
189 if (!reader->read_data16(reader, &tag_creator))
190 {
191 DBG1(DBG_TNC, "insufficient data for Tag Creator field");
192 return FAILED;
193 }
194 *offset += 2 + tag_creator.len;
195
196 if (!reader->read_data16(reader, &unique_sw_id))
197 {
198 DBG1(DBG_TNC, "insufficient data for Unique Software ID");
199 return FAILED;
200 }
201 *offset += 2 + unique_sw_id.len;
202
203 tag_id = swid_tag_id_create(tag_creator, unique_sw_id, chunk_empty);
204 this->targets->add(this->targets, tag_id);
205 }
206 reader->destroy(reader);
207
208 return SUCCESS;
209 }
210
211 METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
212 private_tcg_swid_attr_req_t *this)
213 {
214 ref_get(&this->ref);
215 return &this->public.pa_tnc_attribute;
216 }
217
218 METHOD(pa_tnc_attr_t, destroy, void,
219 private_tcg_swid_attr_req_t *this)
220 {
221 if (ref_put(&this->ref))
222 {
223 this->targets->destroy(this->targets);
224 free(this->value.ptr);
225 free(this);
226 }
227 }
228
229 METHOD(tcg_swid_attr_req_t, get_flags, u_int8_t,
230 private_tcg_swid_attr_req_t *this)
231 {
232 return this->flags;
233 }
234
235 METHOD(tcg_swid_attr_req_t, get_request_id, u_int32_t,
236 private_tcg_swid_attr_req_t *this)
237 {
238 return this->request_id;
239 }
240
241 METHOD(tcg_swid_attr_req_t, get_earliest_eid, u_int32_t,
242 private_tcg_swid_attr_req_t *this)
243 {
244 return this->earliest_eid;
245 }
246
247 METHOD(tcg_swid_attr_req_t, add_target, void,
248 private_tcg_swid_attr_req_t *this, swid_tag_id_t *tag_id)
249 {
250 this->targets->add(this->targets, tag_id);
251 }
252
253 METHOD(tcg_swid_attr_req_t, get_targets, swid_inventory_t*,
254 private_tcg_swid_attr_req_t *this)
255 {
256 return this->targets;
257 }
258
259 /**
260 * Described in header.
261 */
262 pa_tnc_attr_t *tcg_swid_attr_req_create(u_int8_t flags, u_int32_t request_id,
263 u_int32_t eid)
264 {
265 private_tcg_swid_attr_req_t *this;
266
267 INIT(this,
268 .public = {
269 .pa_tnc_attribute = {
270 .get_type = _get_type,
271 .get_value = _get_value,
272 .get_noskip_flag = _get_noskip_flag,
273 .set_noskip_flag = _set_noskip_flag,
274 .build = _build,
275 .process = _process,
276 .get_ref = _get_ref,
277 .destroy = _destroy,
278 },
279 .get_flags = _get_flags,
280 .get_request_id = _get_request_id,
281 .get_earliest_eid = _get_earliest_eid,
282 .add_target = _add_target,
283 .get_targets = _get_targets,
284 },
285 .type = { PEN_TCG, TCG_SWID_REQUEST },
286 .flags = flags & SWID_REQ_RESERVED_MASK,
287 .request_id = request_id,
288 .earliest_eid = eid,
289 .targets = swid_inventory_create(FALSE),
290 .ref = 1,
291 );
292
293 return &this->public.pa_tnc_attribute;
294 }
295
296 /**
297 * Described in header.
298 */
299 pa_tnc_attr_t *tcg_swid_attr_req_create_from_data(chunk_t data)
300 {
301 private_tcg_swid_attr_req_t *this;
302
303 INIT(this,
304 .public = {
305 .pa_tnc_attribute = {
306 .get_type = _get_type,
307 .get_value = _get_value,
308 .get_noskip_flag = _get_noskip_flag,
309 .set_noskip_flag = _set_noskip_flag,
310 .build = _build,
311 .process = _process,
312 .get_ref = _get_ref,
313 .destroy = _destroy,
314 },
315 .get_flags = _get_flags,
316 .get_request_id = _get_request_id,
317 .get_earliest_eid = _get_earliest_eid,
318 .add_target = _add_target,
319 .get_targets = _get_targets,
320 },
321 .type = { PEN_TCG, TCG_SWID_REQUEST },
322 .value = chunk_clone(data),
323 .targets = swid_inventory_create(FALSE),
324 .ref = 1,
325 );
326
327 return &this->public.pa_tnc_attribute;
328 }