2 * Copyright (C) 2013-2014 Andreas Steffen
3 * HSR Hochschule fuer Technik Rapperswil
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>.
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
16 #include "tcg_swid_attr_tag_inv.h"
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>
24 typedef struct private_tcg_swid_attr_tag_inv_t private_tcg_swid_attr_tag_inv_t
;
28 * see section 4.10 of TCG TNC SWID Message and Attributes for IF-M
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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
36 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
38 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
40 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
41 * | Instance ID Length | Instance ID (var. length) |
42 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
44 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
46 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
49 #define TCG_SWID_TAG_INV_RESERVED 0x00
52 * Private data of an tcg_swid_attr_tag_inv_t object.
54 struct private_tcg_swid_attr_tag_inv_t
{
57 * Public members of tcg_swid_attr_tag_inv_t
59 tcg_swid_attr_tag_inv_t
public;
62 * Vendor-specific attribute type
67 * Length of attribute value
72 * Offset up to which attribute value has been processed
77 * Current position of attribute value pointer
82 * Contains complete attribute or current segment
107 * Number of SWID Tags in attribute
114 swid_inventory_t
*inventory
;
122 METHOD(pa_tnc_attr_t
, get_type
, pen_type_t
,
123 private_tcg_swid_attr_tag_inv_t
*this)
128 METHOD(pa_tnc_attr_t
, get_value
, chunk_t
,
129 private_tcg_swid_attr_tag_inv_t
*this)
134 METHOD(pa_tnc_attr_t
, get_noskip_flag
, bool,
135 private_tcg_swid_attr_tag_inv_t
*this)
137 return this->noskip_flag
;
140 METHOD(pa_tnc_attr_t
, set_noskip_flag
,void,
141 private_tcg_swid_attr_tag_inv_t
*this, bool noskip
)
143 this->noskip_flag
= noskip
;
146 METHOD(pa_tnc_attr_t
, build
, void,
147 private_tcg_swid_attr_tag_inv_t
*this)
149 bio_writer_t
*writer
;
151 enumerator_t
*enumerator
;
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
);
165 enumerator
= this->inventory
->create_enumerator(this->inventory
);
166 while (enumerator
->enumerate(enumerator
, &tag
))
168 writer
->write_data16(writer
, tag
->get_instance_id(tag
));
169 writer
->write_data32(writer
, tag
->get_encoding(tag
));
171 enumerator
->destroy(enumerator
);
173 this->value
= writer
->extract_buf(writer
);
174 this->segment
= this->value
;
175 this->length
= this->value
.len
;
176 writer
->destroy(writer
);
179 METHOD(pa_tnc_attr_t
, process
, status_t
,
180 private_tcg_swid_attr_tag_inv_t
*this, uint32_t *offset
)
182 bio_reader_t
*reader
;
184 chunk_t tag_encoding
, instance_id
;
186 status_t status
= NEED_MORE
;
188 if (this->offset
== 0)
190 if (this->length
< TCG_SWID_TAG_INV_MIN_SIZE
)
192 DBG1(DBG_TNC
, "insufficient data for %N/%N", pen_names
, PEN_TCG
,
193 tcg_attr_names
, this->type
.type
);
194 *offset
= this->offset
;
197 if (this->value
.len
< TCG_SWID_TAG_INV_MIN_SIZE
)
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
);
212 reader
= bio_reader_create(this->value
);
214 while (this->tag_count
)
216 if (!reader
->read_data16(reader
, &instance_id
) ||
217 !reader
->read_data32(reader
, &tag_encoding
))
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
);
226 /* at least one tag was processed */
231 if (this->length
!= this->offset
)
233 DBG1(DBG_TNC
, "inconsistent length for %N/%N", pen_names
, PEN_TCG
,
234 tcg_attr_names
, this->type
.type
);
235 *offset
= this->offset
;
240 reader
->destroy(reader
);
244 METHOD(pa_tnc_attr_t
, add_segment
, void,
245 private_tcg_swid_attr_tag_inv_t
*this, chunk_t segment
)
247 this->value
= chunk_cat("cc", this->value
, segment
);
248 chunk_free(&this->segment
);
249 this->segment
= this->value
;
252 METHOD(pa_tnc_attr_t
, get_ref
, pa_tnc_attr_t
*,
253 private_tcg_swid_attr_tag_inv_t
*this)
256 return &this->public.pa_tnc_attribute
;
259 METHOD(pa_tnc_attr_t
, destroy
, void,
260 private_tcg_swid_attr_tag_inv_t
*this)
262 if (ref_put(&this->ref
))
264 this->inventory
->destroy(this->inventory
);
265 free(this->segment
.ptr
);
270 METHOD(tcg_swid_attr_tag_inv_t
, add
, void,
271 private_tcg_swid_attr_tag_inv_t
*this, swid_tag_t
*tag
)
273 this->inventory
->add(this->inventory
, tag
);
276 METHOD(tcg_swid_attr_tag_inv_t
, get_request_id
, uint32_t,
277 private_tcg_swid_attr_tag_inv_t
*this)
279 return this->request_id
;
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
)
287 *eid_epoch
= this->eid_epoch
;
289 return this->last_eid
;
292 METHOD(tcg_swid_attr_tag_inv_t
, get_tag_count
, uint32_t,
293 private_tcg_swid_attr_tag_inv_t
*this)
295 return this->tag_count
;
298 METHOD(tcg_swid_attr_tag_inv_t
, get_inventory
, swid_inventory_t
*,
299 private_tcg_swid_attr_tag_inv_t
*this)
301 return this->inventory
;
304 METHOD(tcg_swid_attr_tag_inv_t
, clear_inventory
, void,
305 private_tcg_swid_attr_tag_inv_t
*this)
307 this->inventory
->destroy(this->inventory
);
308 this->inventory
= swid_inventory_create(TRUE
);
312 * Described in header.
314 pa_tnc_attr_t
*tcg_swid_attr_tag_inv_create(uint32_t request_id
,
315 uint32_t eid_epoch
, uint32_t eid
)
317 private_tcg_swid_attr_tag_inv_t
*this;
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
,
328 .add_segment
= _add_segment
,
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
,
339 .type
= { PEN_TCG
, TCG_SWID_TAG_INVENTORY
},
340 .request_id
= request_id
,
341 .eid_epoch
= eid_epoch
,
343 .inventory
= swid_inventory_create(TRUE
),
347 return &this->public.pa_tnc_attribute
;
351 * Described in header.
353 pa_tnc_attr_t
*tcg_swid_attr_tag_inv_create_from_data(size_t length
,
356 private_tcg_swid_attr_tag_inv_t
*this;
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
,
367 .add_segment
= _add_segment
,
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
,
378 .type
= { PEN_TCG
, TCG_SWID_TAG_INVENTORY
},
380 .segment
= chunk_clone(data
),
381 .inventory
= swid_inventory_create(TRUE
),
385 /* received either complete attribute value or first segment */
386 this->value
= this->segment
;
388 return &this->public.pa_tnc_attribute
;