129d062fc505fc60a5c3952e739bf0f8c9e4fc3e
[strongswan.git] / src / libpts / tcg / swid / tcg_swid_attr_tag_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_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 * | Unique Sequence ID Length |Unique Sequence ID (var length)|
42 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
43 * | Tag Length |
44 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
45 * | Tag (Variable) |
46 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
47 */
48
49 #define SWID_TAG_INV_SIZE 16
50 #define SWID_TAG_INV_RESERVED 0x00
51
52 /**
53 * Private data of an tcg_swid_attr_tag_inv_t object.
54 */
55 struct private_tcg_swid_attr_tag_inv_t {
56
57 /**
58 * Public members of tcg_swid_attr_tag_inv_t
59 */
60 tcg_swid_attr_tag_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 SWID Tags
94 */
95 linked_list_t *tag_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_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_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_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_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_inv_t *this)
129 {
130 bio_writer_t *writer;
131 swid_tag_t *tag;
132 enumerator_t *enumerator;
133
134 if (this->value.ptr)
135 {
136 return;
137 }
138
139 writer = bio_writer_create(SWID_TAG_INV_SIZE);
140 writer->write_uint8 (writer, SWID_TAG_INV_RESERVED);
141 writer->write_uint24(writer, this->tag_list->get_count(this->tag_list));
142 writer->write_uint32(writer, this->request_id);
143 writer->write_uint32(writer, this->eid_epoch);
144 writer->write_uint32(writer, this->last_eid);
145
146 enumerator = this->tag_list->create_enumerator(this->tag_list);
147 while (enumerator->enumerate(enumerator, &tag))
148 {
149 writer->write_data16(writer, tag->get_unique_seq_id(tag));
150 writer->write_data32(writer, tag->get_encoding(tag));
151 }
152 enumerator->destroy(enumerator);
153
154 this->value = writer->extract_buf(writer);
155 writer->destroy(writer);
156 }
157
158 METHOD(pa_tnc_attr_t, process, status_t,
159 private_tcg_swid_attr_tag_inv_t *this, u_int32_t *offset)
160 {
161 bio_reader_t *reader;
162 u_int32_t tag_count;
163 u_int8_t reserved;
164 chunk_t tag_encoding, unique_seq_id;
165 swid_tag_t *tag;
166
167 if (this->value.len < SWID_TAG_INV_SIZE)
168 {
169 DBG1(DBG_TNC, "insufficient data for SWID Tag Inventory");
170 *offset = 0;
171 return FAILED;
172 }
173
174 reader = bio_reader_create(this->value);
175 reader->read_uint8 (reader, &reserved);
176 reader->read_uint24(reader, &tag_count);
177 reader->read_uint32(reader, &this->request_id);
178 reader->read_uint32(reader, &this->eid_epoch);
179 reader->read_uint32(reader, &this->last_eid);
180 *offset = SWID_TAG_INV_SIZE;
181
182 while (tag_count--)
183 {
184 if (!reader->read_data16(reader, &unique_seq_id))
185 {
186 DBG1(DBG_TNC, "insufficient data for Unique Sequence ID");
187 return FAILED;
188 }
189 *offset += 2 + unique_seq_id.len;
190
191 if (!reader->read_data32(reader, &tag_encoding))
192 {
193 DBG1(DBG_TNC, "insufficient data for Tag");
194 return FAILED;
195 }
196 *offset += 4 + tag_encoding.len;
197
198 tag = swid_tag_create(tag_encoding, unique_seq_id);
199 this->tag_list->insert_last(this->tag_list, tag);
200 }
201 reader->destroy(reader);
202
203 return SUCCESS;
204 }
205
206 METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
207 private_tcg_swid_attr_tag_inv_t *this)
208 {
209 ref_get(&this->ref);
210 return &this->public.pa_tnc_attribute;
211 }
212
213 METHOD(pa_tnc_attr_t, destroy, void,
214 private_tcg_swid_attr_tag_inv_t *this)
215 {
216 if (ref_put(&this->ref))
217 {
218 this->tag_list->destroy_offset(this->tag_list,
219 offsetof(swid_tag_t, destroy));
220 free(this->value.ptr);
221 free(this);
222 }
223 }
224
225 METHOD(tcg_swid_attr_tag_inv_t, get_request_id, u_int32_t,
226 private_tcg_swid_attr_tag_inv_t *this)
227 {
228 return this->request_id;
229 }
230
231 METHOD(tcg_swid_attr_tag_inv_t, get_last_eid, u_int32_t,
232 private_tcg_swid_attr_tag_inv_t *this, u_int32_t *eid_epoch)
233 {
234 if (eid_epoch)
235 {
236 *eid_epoch = this->eid_epoch;
237 }
238 return this->last_eid;
239 }
240
241 METHOD(tcg_swid_attr_tag_inv_t, add_tag, void,
242 private_tcg_swid_attr_tag_inv_t *this, swid_tag_t *tag)
243 {
244 this->tag_list->insert_last(this->tag_list, tag);
245 }
246
247 METHOD(tcg_swid_attr_tag_inv_t, create_tag_enumerator, enumerator_t*,
248 private_tcg_swid_attr_tag_inv_t *this)
249 {
250 return this->tag_list->create_enumerator(this->tag_list);
251 }
252
253 /**
254 * Described in header.
255 */
256 pa_tnc_attr_t *tcg_swid_attr_tag_inv_create(u_int32_t request_id,
257 u_int32_t eid_epoch, u_int32_t eid)
258 {
259 private_tcg_swid_attr_tag_inv_t *this;
260
261 INIT(this,
262 .public = {
263 .pa_tnc_attribute = {
264 .get_type = _get_type,
265 .get_value = _get_value,
266 .get_noskip_flag = _get_noskip_flag,
267 .set_noskip_flag = _set_noskip_flag,
268 .build = _build,
269 .process = _process,
270 .get_ref = _get_ref,
271 .destroy = _destroy,
272 },
273 .get_request_id = _get_request_id,
274 .get_last_eid = _get_last_eid,
275 .add_tag = _add_tag,
276 .create_tag_enumerator = _create_tag_enumerator,
277 },
278 .type = { PEN_TCG, TCG_SWID_TAG_INVENTORY },
279 .request_id = request_id,
280 .eid_epoch = eid_epoch,
281 .last_eid = eid,
282 .tag_list = linked_list_create(),
283 .ref = 1,
284 );
285
286 return &this->public.pa_tnc_attribute;
287 }
288
289
290 /**
291 * Described in header.
292 */
293 pa_tnc_attr_t *tcg_swid_attr_tag_inv_create_from_data(chunk_t data)
294 {
295 private_tcg_swid_attr_tag_inv_t *this;
296
297 INIT(this,
298 .public = {
299 .pa_tnc_attribute = {
300 .get_type = _get_type,
301 .get_value = _get_value,
302 .get_noskip_flag = _get_noskip_flag,
303 .set_noskip_flag = _set_noskip_flag,
304 .build = _build,
305 .process = _process,
306 .get_ref = _get_ref,
307 .destroy = _destroy,
308 },
309 .get_request_id = _get_request_id,
310 .get_last_eid = _get_last_eid,
311 .add_tag = _add_tag,
312 .create_tag_enumerator = _create_tag_enumerator,
313 },
314 .type = { PEN_TCG, TCG_SWID_TAG_INVENTORY },
315 .value = chunk_clone(data),
316 .tag_list = linked_list_create(),
317 .ref = 1,
318 );
319
320 return &this->public.pa_tnc_attribute;
321 }