]> git.ipfire.org Git - thirdparty/strongswan.git/blob - src/libimcv/tcg/swid/tcg_swid_attr_tag_inv.c
013482441679fe413a82df327b0096c9555419ff
[thirdparty/strongswan.git] / src / libimcv / tcg / swid / tcg_swid_attr_tag_inv.c
1 /*
2 * Copyright (C) 2013-2014 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_tag_inv.h"
17
18 #include <pa_tnc/pa_tnc_msg.h>
19 #include <bio/bio_writer.h>
20 #include <bio/bio_reader.h>
21 #include <utils/debug.h>
22
23
24 typedef struct private_tcg_swid_attr_tag_inv_t private_tcg_swid_attr_tag_inv_t;
25
26 /**
27 * SWID Tag Inventory
28 * see section 4.10 of TCG TNC SWID Message and Attributes for IF-M
29 *
30 * 1 2 3
31 * 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
32 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
33 * | Reserved | Tag ID Count |
34 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
35 * | Request ID Copy |
36 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
37 * | EID Epoch |
38 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
39 * | Last EID |
40 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
41 * | Instance ID Length | Instance ID (var. length) |
42 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
43 * | Tag Length |
44 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
45 * | Tag (Variable) |
46 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
47 */
48
49 #define TCG_SWID_TAG_INV_RESERVED 0x00
50
51 /**
52 * Private data of an tcg_swid_attr_tag_inv_t object.
53 */
54 struct private_tcg_swid_attr_tag_inv_t {
55
56 /**
57 * Public members of tcg_swid_attr_tag_inv_t
58 */
59 tcg_swid_attr_tag_inv_t public;
60
61 /**
62 * Vendor-specific attribute type
63 */
64 pen_type_t type;
65
66 /**
67 * Length of attribute value
68 */
69 size_t length;
70
71 /**
72 * Offset up to which attribute value has been processed
73 */
74 size_t offset;
75
76 /**
77 * Current position of attribute value pointer
78 */
79 chunk_t value;
80
81 /**
82 * Contains complete attribute or current segment
83 */
84 chunk_t segment;
85
86 /**
87 * Noskip flag
88 */
89 bool noskip_flag;
90
91 /**
92 * Request ID
93 */
94 uint32_t request_id;
95
96 /**
97 * Event ID Epoch
98 */
99 uint32_t eid_epoch;
100
101 /**
102 * Last Event ID
103 */
104 uint32_t last_eid;
105
106 /**
107 * Number of SWID Tags in attribute
108 */
109 uint32_t tag_count;
110
111 /**
112 * SWID Tag Inventory
113 */
114 swid_inventory_t *inventory;
115
116 /**
117 * Reference count
118 */
119 refcount_t ref;
120 };
121
122 METHOD(pa_tnc_attr_t, get_type, pen_type_t,
123 private_tcg_swid_attr_tag_inv_t *this)
124 {
125 return this->type;
126 }
127
128 METHOD(pa_tnc_attr_t, get_value, chunk_t,
129 private_tcg_swid_attr_tag_inv_t *this)
130 {
131 return this->value;
132 }
133
134 METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
135 private_tcg_swid_attr_tag_inv_t *this)
136 {
137 return this->noskip_flag;
138 }
139
140 METHOD(pa_tnc_attr_t, set_noskip_flag,void,
141 private_tcg_swid_attr_tag_inv_t *this, bool noskip)
142 {
143 this->noskip_flag = noskip;
144 }
145
146 METHOD(pa_tnc_attr_t, build, void,
147 private_tcg_swid_attr_tag_inv_t *this)
148 {
149 bio_writer_t *writer;
150 swid_tag_t *tag;
151 enumerator_t *enumerator;
152
153 if (this->value.ptr)
154 {
155 return;
156 }
157
158 writer = bio_writer_create(TCG_SWID_TAG_INV_MIN_SIZE);
159 writer->write_uint8 (writer, TCG_SWID_TAG_INV_RESERVED);
160 writer->write_uint24(writer, this->inventory->get_count(this->inventory));
161 writer->write_uint32(writer, this->request_id);
162 writer->write_uint32(writer, this->eid_epoch);
163 writer->write_uint32(writer, this->last_eid);
164
165 enumerator = this->inventory->create_enumerator(this->inventory);
166 while (enumerator->enumerate(enumerator, &tag))
167 {
168 writer->write_data16(writer, tag->get_instance_id(tag));
169 writer->write_data32(writer, tag->get_encoding(tag));
170 }
171 enumerator->destroy(enumerator);
172
173 this->value = writer->extract_buf(writer);
174 this->segment = this->value;
175 this->length = this->value.len;
176 writer->destroy(writer);
177 }
178
179 METHOD(pa_tnc_attr_t, process, status_t,
180 private_tcg_swid_attr_tag_inv_t *this, uint32_t *offset)
181 {
182 bio_reader_t *reader;
183 uint8_t reserved;
184 chunk_t tag_encoding, instance_id;
185 swid_tag_t *tag;
186 status_t status = NEED_MORE;
187
188 if (this->offset == 0)
189 {
190 if (this->length < TCG_SWID_TAG_INV_MIN_SIZE)
191 {
192 DBG1(DBG_TNC, "insufficient data for %N/%N", pen_names, PEN_TCG,
193 tcg_attr_names, this->type.type);
194 *offset = this->offset;
195 return FAILED;
196 }
197 if (this->value.len < TCG_SWID_TAG_INV_MIN_SIZE)
198 {
199 return NEED_MORE;
200 }
201 reader = bio_reader_create(this->value);
202 reader->read_uint8 (reader, &reserved);
203 reader->read_uint24(reader, &this->tag_count);
204 reader->read_uint32(reader, &this->request_id);
205 reader->read_uint32(reader, &this->eid_epoch);
206 reader->read_uint32(reader, &this->last_eid);
207 this->offset = TCG_SWID_TAG_INV_MIN_SIZE;
208 this->value = reader->peek(reader);
209 reader->destroy(reader);
210 }
211
212 reader = bio_reader_create(this->value);
213
214 while (this->tag_count)
215 {
216 if (!reader->read_data16(reader, &instance_id) ||
217 !reader->read_data32(reader, &tag_encoding))
218 {
219 goto end;
220 }
221 tag = swid_tag_create(tag_encoding, instance_id);
222 this->inventory->add(this->inventory, tag);
223 this->offset += this->value.len - reader->remaining(reader);
224 this->value = reader->peek(reader);
225
226 /* at least one tag was processed */
227 status = SUCCESS;
228 this->tag_count--;
229 }
230
231 if (this->length != this->offset)
232 {
233 DBG1(DBG_TNC, "inconsistent length for %N/%N", pen_names, PEN_TCG,
234 tcg_attr_names, this->type.type);
235 *offset = this->offset;
236 status = FAILED;
237 }
238
239 end:
240 reader->destroy(reader);
241 return status;
242 }
243
244 METHOD(pa_tnc_attr_t, add_segment, void,
245 private_tcg_swid_attr_tag_inv_t *this, chunk_t segment)
246 {
247 this->value = chunk_cat("cc", this->value, segment);
248 chunk_free(&this->segment);
249 this->segment = this->value;
250 }
251
252 METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
253 private_tcg_swid_attr_tag_inv_t *this)
254 {
255 ref_get(&this->ref);
256 return &this->public.pa_tnc_attribute;
257 }
258
259 METHOD(pa_tnc_attr_t, destroy, void,
260 private_tcg_swid_attr_tag_inv_t *this)
261 {
262 if (ref_put(&this->ref))
263 {
264 this->inventory->destroy(this->inventory);
265 free(this->segment.ptr);
266 free(this);
267 }
268 }
269
270 METHOD(tcg_swid_attr_tag_inv_t, add, void,
271 private_tcg_swid_attr_tag_inv_t *this, swid_tag_t *tag)
272 {
273 this->inventory->add(this->inventory, tag);
274 }
275
276 METHOD(tcg_swid_attr_tag_inv_t, get_request_id, uint32_t,
277 private_tcg_swid_attr_tag_inv_t *this)
278 {
279 return this->request_id;
280 }
281
282 METHOD(tcg_swid_attr_tag_inv_t, get_last_eid, uint32_t,
283 private_tcg_swid_attr_tag_inv_t *this, uint32_t *eid_epoch)
284 {
285 if (eid_epoch)
286 {
287 *eid_epoch = this->eid_epoch;
288 }
289 return this->last_eid;
290 }
291
292 METHOD(tcg_swid_attr_tag_inv_t, get_tag_count, uint32_t,
293 private_tcg_swid_attr_tag_inv_t *this)
294 {
295 return this->tag_count;
296 }
297
298 METHOD(tcg_swid_attr_tag_inv_t, get_inventory, swid_inventory_t*,
299 private_tcg_swid_attr_tag_inv_t *this)
300 {
301 return this->inventory;
302 }
303
304 METHOD(tcg_swid_attr_tag_inv_t, clear_inventory, void,
305 private_tcg_swid_attr_tag_inv_t *this)
306 {
307 this->inventory->destroy(this->inventory);
308 this->inventory = swid_inventory_create(TRUE);
309 }
310
311 /**
312 * Described in header.
313 */
314 pa_tnc_attr_t *tcg_swid_attr_tag_inv_create(uint32_t request_id,
315 uint32_t eid_epoch, uint32_t eid)
316 {
317 private_tcg_swid_attr_tag_inv_t *this;
318
319 INIT(this,
320 .public = {
321 .pa_tnc_attribute = {
322 .get_type = _get_type,
323 .get_value = _get_value,
324 .get_noskip_flag = _get_noskip_flag,
325 .set_noskip_flag = _set_noskip_flag,
326 .build = _build,
327 .process = _process,
328 .add_segment = _add_segment,
329 .get_ref = _get_ref,
330 .destroy = _destroy,
331 },
332 .add = _add,
333 .get_request_id = _get_request_id,
334 .get_last_eid = _get_last_eid,
335 .get_tag_count = _get_tag_count,
336 .get_inventory = _get_inventory,
337 .clear_inventory = _clear_inventory,
338 },
339 .type = { PEN_TCG, TCG_SWID_TAG_INVENTORY },
340 .request_id = request_id,
341 .eid_epoch = eid_epoch,
342 .last_eid = eid,
343 .inventory = swid_inventory_create(TRUE),
344 .ref = 1,
345 );
346
347 return &this->public.pa_tnc_attribute;
348 }
349
350 /**
351 * Described in header.
352 */
353 pa_tnc_attr_t *tcg_swid_attr_tag_inv_create_from_data(size_t length,
354 chunk_t data)
355 {
356 private_tcg_swid_attr_tag_inv_t *this;
357
358 INIT(this,
359 .public = {
360 .pa_tnc_attribute = {
361 .get_type = _get_type,
362 .get_value = _get_value,
363 .get_noskip_flag = _get_noskip_flag,
364 .set_noskip_flag = _set_noskip_flag,
365 .build = _build,
366 .process = _process,
367 .add_segment = _add_segment,
368 .get_ref = _get_ref,
369 .destroy = _destroy,
370 },
371 .add = _add,
372 .get_request_id = _get_request_id,
373 .get_last_eid = _get_last_eid,
374 .get_tag_count = _get_tag_count,
375 .get_inventory = _get_inventory,
376 .clear_inventory = _clear_inventory,
377 },
378 .type = { PEN_TCG, TCG_SWID_TAG_INVENTORY },
379 .length = length,
380 .segment = chunk_clone(data),
381 .inventory = swid_inventory_create(TRUE),
382 .ref = 1,
383 );
384
385 /* received either complete attribute value or first segment */
386 this->value = this->segment;
387
388 return &this->public.pa_tnc_attribute;
389 }