bdb2e6ad51a40de27074e43cac4d0b4128922973
[strongswan.git] / src / libpts / tcg / swid / tcg_swid_attr_tag_id_inv.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_tag_id_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_id_inv_t private_tcg_swid_attr_tag_id_inv_t;
25
26 /**
27 * SWID Tag Identifier Inventory
28 * see section 4.8 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 * | Tag Creator Length | Tag Creator (variable length) |
42 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
43 * | Unique Software ID Length |Unique Software ID (var length)|
44 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
45 * | Unique Sequence ID Length |Unique Sequence ID (var length)|
46 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
47 */
48
49 #define SWID_TAG_ID_INV_SIZE 16
50 #define SWID_TAG_ID_INV_RESERVED 0x00
51
52 /**
53 * Private data of an tcg_swid_attr_tag_id_inv_t object.
54 */
55 struct private_tcg_swid_attr_tag_id_inv_t {
56
57 /**
58 * Public members of tcg_swid_attr_tag_id_inv_t
59 */
60 tcg_swid_attr_tag_id_inv_t public;
61
62 /**
63 * Vendor-specific attribute type
64 */
65 pen_type_t type;
66
67 /**
68 * Attribute value
69 */
70 chunk_t value;
71
72 /**
73 * Noskip flag
74 */
75 bool noskip_flag;
76
77 /**
78 * Request ID
79 */
80 u_int32_t request_id;
81
82 /**
83 * Event ID Epoch
84 */
85 u_int32_t eid_epoch;
86
87 /**
88 * Last Event ID
89 */
90 u_int32_t last_eid;
91
92 /**
93 * List of Tag Identifiers
94 */
95 linked_list_t *tag_id_list;
96
97 /**
98 * Reference count
99 */
100 refcount_t ref;
101 };
102
103 METHOD(pa_tnc_attr_t, get_type, pen_type_t,
104 private_tcg_swid_attr_tag_id_inv_t *this)
105 {
106 return this->type;
107 }
108
109 METHOD(pa_tnc_attr_t, get_value, chunk_t,
110 private_tcg_swid_attr_tag_id_inv_t *this)
111 {
112 return this->value;
113 }
114
115 METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
116 private_tcg_swid_attr_tag_id_inv_t *this)
117 {
118 return this->noskip_flag;
119 }
120
121 METHOD(pa_tnc_attr_t, set_noskip_flag,void,
122 private_tcg_swid_attr_tag_id_inv_t *this, bool noskip)
123 {
124 this->noskip_flag = noskip;
125 }
126
127 METHOD(pa_tnc_attr_t, build, void,
128 private_tcg_swid_attr_tag_id_inv_t *this)
129 {
130 bio_writer_t *writer;
131 swid_tag_id_t *tag_id;
132 chunk_t tag_creator, unique_sw_id, unique_seq_id;
133 enumerator_t *enumerator;
134
135 if (this->value.ptr)
136 {
137 return;
138 }
139
140 writer = bio_writer_create(SWID_TAG_ID_INV_SIZE);
141 writer->write_uint8 (writer, SWID_TAG_ID_INV_RESERVED);
142 writer->write_uint24(writer, this->tag_id_list->get_count(this->tag_id_list));
143 writer->write_uint32(writer, this->request_id);
144 writer->write_uint32(writer, this->eid_epoch);
145 writer->write_uint32(writer, this->last_eid);
146
147 enumerator = this->tag_id_list->create_enumerator(this->tag_id_list);
148 while (enumerator->enumerate(enumerator, &tag_id))
149 {
150 tag_creator = tag_id->get_tag_creator(tag_id);
151 unique_sw_id = tag_id->get_unique_sw_id(tag_id, &unique_seq_id);
152 writer->write_data16(writer, tag_creator);
153 writer->write_data16(writer, unique_sw_id);
154 writer->write_data16(writer, unique_seq_id);
155 }
156 enumerator->destroy(enumerator);
157
158 this->value = writer->extract_buf(writer);
159 writer->destroy(writer);
160 }
161
162 METHOD(pa_tnc_attr_t, process, status_t,
163 private_tcg_swid_attr_tag_id_inv_t *this, u_int32_t *offset)
164 {
165 bio_reader_t *reader;
166 u_int32_t tag_id_count;
167 u_int8_t reserved;
168 chunk_t tag_creator, unique_sw_id, unique_seq_id;
169 swid_tag_id_t *tag_id;
170
171 if (this->value.len < SWID_TAG_ID_INV_SIZE)
172 {
173 DBG1(DBG_TNC, "insufficient data for SWID Tag Identifier Inventory");
174 *offset = 0;
175 return FAILED;
176 }
177
178 reader = bio_reader_create(this->value);
179 reader->read_uint8 (reader, &reserved);
180 reader->read_uint24(reader, &tag_id_count);
181 reader->read_uint32(reader, &this->request_id);
182 reader->read_uint32(reader, &this->eid_epoch);
183 reader->read_uint32(reader, &this->last_eid);
184 *offset = SWID_TAG_ID_INV_SIZE;
185
186 while (tag_id_count--)
187 {
188 if (!reader->read_data16(reader, &tag_creator))
189 {
190 DBG1(DBG_TNC, "insufficient data for Tag Creator field");
191 return FAILED;
192 }
193 *offset += 2 + tag_creator.len;
194
195 if (!reader->read_data16(reader, &unique_sw_id))
196 {
197 DBG1(DBG_TNC, "insufficient data for Unique Software ID");
198 return FAILED;
199 }
200 *offset += 2 + unique_sw_id.len;
201
202 if (!reader->read_data16(reader, &unique_seq_id))
203 {
204 DBG1(DBG_TNC, "insufficient data for Unique Sequence ID");
205 return FAILED;
206 }
207 *offset += 2 + unique_seq_id.len;
208
209 tag_id = swid_tag_id_create(tag_creator, unique_sw_id, unique_seq_id);
210 this->tag_id_list->insert_last(this->tag_id_list, tag_id);
211 }
212 reader->destroy(reader);
213
214 return SUCCESS;
215 }
216
217 METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
218 private_tcg_swid_attr_tag_id_inv_t *this)
219 {
220 ref_get(&this->ref);
221 return &this->public.pa_tnc_attribute;
222 }
223
224 METHOD(pa_tnc_attr_t, destroy, void,
225 private_tcg_swid_attr_tag_id_inv_t *this)
226 {
227 if (ref_put(&this->ref))
228 {
229 this->tag_id_list->destroy_offset(this->tag_id_list,
230 offsetof(swid_tag_id_t, destroy));
231 free(this->value.ptr);
232 free(this);
233 }
234 }
235
236 METHOD(tcg_swid_attr_tag_id_inv_t, get_request_id, u_int32_t,
237 private_tcg_swid_attr_tag_id_inv_t *this)
238 {
239 return this->request_id;
240 }
241
242 METHOD(tcg_swid_attr_tag_id_inv_t, get_last_eid, u_int32_t,
243 private_tcg_swid_attr_tag_id_inv_t *this, u_int32_t *eid_epoch)
244 {
245 if (eid_epoch)
246 {
247 *eid_epoch = this->eid_epoch;
248 }
249 return this->last_eid;
250 }
251
252 METHOD(tcg_swid_attr_tag_id_inv_t, add_tag_id, void,
253 private_tcg_swid_attr_tag_id_inv_t *this, swid_tag_id_t *tag_id)
254 {
255 this->tag_id_list->insert_last(this->tag_id_list, tag_id);
256 }
257
258 METHOD(tcg_swid_attr_tag_id_inv_t, create_tag_id_enumerator, enumerator_t*,
259 private_tcg_swid_attr_tag_id_inv_t *this)
260 {
261 return this->tag_id_list->create_enumerator(this->tag_id_list);
262 }
263
264 /**
265 * Described in header.
266 */
267 pa_tnc_attr_t *tcg_swid_attr_tag_id_inv_create(u_int32_t request_id,
268 u_int32_t eid_epoch,
269 u_int32_t eid)
270 {
271 private_tcg_swid_attr_tag_id_inv_t *this;
272
273 INIT(this,
274 .public = {
275 .pa_tnc_attribute = {
276 .get_type = _get_type,
277 .get_value = _get_value,
278 .get_noskip_flag = _get_noskip_flag,
279 .set_noskip_flag = _set_noskip_flag,
280 .build = _build,
281 .process = _process,
282 .get_ref = _get_ref,
283 .destroy = _destroy,
284 },
285 .get_request_id = _get_request_id,
286 .get_last_eid = _get_last_eid,
287 .add_tag_id = _add_tag_id,
288 .create_tag_id_enumerator = _create_tag_id_enumerator,
289 },
290 .type = { PEN_TCG, TCG_SWID_TAG_ID_INVENTORY },
291 .request_id = request_id,
292 .eid_epoch = eid_epoch,
293 .last_eid = eid,
294 .tag_id_list = linked_list_create(),
295 .ref = 1,
296 );
297
298 return &this->public.pa_tnc_attribute;
299 }
300
301
302 /**
303 * Described in header.
304 */
305 pa_tnc_attr_t *tcg_swid_attr_tag_id_inv_create_from_data(chunk_t data)
306 {
307 private_tcg_swid_attr_tag_id_inv_t *this;
308
309 INIT(this,
310 .public = {
311 .pa_tnc_attribute = {
312 .get_type = _get_type,
313 .get_value = _get_value,
314 .get_noskip_flag = _get_noskip_flag,
315 .set_noskip_flag = _set_noskip_flag,
316 .build = _build,
317 .process = _process,
318 .get_ref = _get_ref,
319 .destroy = _destroy,
320 },
321 .get_request_id = _get_request_id,
322 .get_last_eid = _get_last_eid,
323 .add_tag_id = _add_tag_id,
324 .create_tag_id_enumerator = _create_tag_id_enumerator,
325 },
326 .type = { PEN_TCG, TCG_SWID_TAG_ID_INVENTORY },
327 .value = chunk_clone(data),
328 .tag_id_list = linked_list_create(),
329 .ref = 1,
330 );
331
332 return &this->public.pa_tnc_attribute;
333 }