Added add_segment() method to TCG/SEG attributes
[strongswan.git] / src / libimcv / tcg / seg / tcg_seg_attr_next_seg.c
1 /*
2 * Copyright (C) 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_seg_attr_next_seg.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 typedef struct private_tcg_seg_attr_next_seg_t private_tcg_seg_attr_next_seg_t;
24
25 typedef enum {
26 NEXT_SEG_FLAG_NONE = 0,
27 NEXT_SEG_FLAG_CANCEL = 1
28 } next_seg_flags_t;
29
30 /**
31 * Next Segment
32 * see TCG IF-M Segmentation Specification
33 *
34 * 1 2 3
35 * 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
36 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
37 * |C| Reserved | Base Attribute ID |
38 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
39 */
40
41 /**
42 * Private data of an tcg_seg_attr_next_seg_t object.
43 */
44 struct private_tcg_seg_attr_next_seg_t {
45
46 /**
47 * Public members of tcg_seg_attr_next_seg_t
48 */
49 tcg_seg_attr_next_seg_t public;
50
51 /**
52 * Vendor-specific attribute type
53 */
54 pen_type_t type;
55
56 /**
57 * Length of attribute value
58 */
59 size_t length;
60
61 /**
62 * Attribute value or segment
63 */
64 chunk_t value;
65
66 /**
67 * Noskip flag
68 */
69 bool noskip_flag;
70
71 /**
72 * Cancel flag
73 */
74 bool cancel_flag;
75
76 /**
77 * Base Attribute ID
78 */
79 uint32_t base_attr_id;
80
81 /**
82 * Reference count
83 */
84 refcount_t ref;
85 };
86
87 METHOD(pa_tnc_attr_t, get_type, pen_type_t,
88 private_tcg_seg_attr_next_seg_t *this)
89 {
90 return this->type;
91 }
92
93 METHOD(pa_tnc_attr_t, get_value, chunk_t,
94 private_tcg_seg_attr_next_seg_t *this)
95 {
96 return this->value;
97 }
98
99 METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
100 private_tcg_seg_attr_next_seg_t *this)
101 {
102 return this->noskip_flag;
103 }
104
105 METHOD(pa_tnc_attr_t, set_noskip_flag,void,
106 private_tcg_seg_attr_next_seg_t *this, bool noskip)
107 {
108 this->noskip_flag = noskip;
109 }
110
111 METHOD(pa_tnc_attr_t, build, void,
112 private_tcg_seg_attr_next_seg_t *this)
113 {
114 bio_writer_t *writer;
115
116 if (this->value.ptr)
117 {
118 return;
119 }
120 writer = bio_writer_create(TCG_SEG_ATTR_NEXT_SEG_SIZE);
121 writer->write_uint8 (writer, this->cancel_flag ? NEXT_SEG_FLAG_CANCEL :
122 NEXT_SEG_FLAG_NONE);
123 writer->write_uint24(writer, this->base_attr_id);
124
125 this->value = writer->extract_buf(writer);
126 this->length = this->value.len;
127 writer->destroy(writer);
128 }
129
130 METHOD(pa_tnc_attr_t, process, status_t,
131 private_tcg_seg_attr_next_seg_t *this, u_int32_t *offset)
132 {
133 bio_reader_t *reader;
134 uint8_t flags;
135
136 *offset = 0;
137
138 if (this->value.len < this->length)
139 {
140 DBG1(DBG_TNC, "segmentation not allowed for %N", tcg_attr_names,
141 this->type.type);
142 return FAILED;
143 }
144 if (this->value.len < TCG_SEG_ATTR_NEXT_SEG_SIZE)
145 {
146 DBG1(DBG_TNC, "insufficient data for %N", tcg_attr_names,
147 this->type.type);
148 return FAILED;
149 }
150 reader = bio_reader_create(this->value);
151 reader->read_uint8 (reader, &flags);
152 reader->read_uint24(reader, &this->base_attr_id);
153 reader->destroy(reader);
154
155 this->cancel_flag = (flags & NEXT_SEG_FLAG_CANCEL);
156
157 return SUCCESS;
158 }
159
160 METHOD(pa_tnc_attr_t, add_segment, void,
161 private_tcg_seg_attr_next_seg_t *this, chunk_t segment)
162 {
163 this->value = chunk_cat("mc", this->value, segment);
164 }
165
166 METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
167 private_tcg_seg_attr_next_seg_t *this)
168 {
169 ref_get(&this->ref);
170 return &this->public.pa_tnc_attribute;
171 }
172
173 METHOD(pa_tnc_attr_t, destroy, void,
174 private_tcg_seg_attr_next_seg_t *this)
175 {
176 if (ref_put(&this->ref))
177 {
178 free(this->value.ptr);
179 free(this);
180 }
181 }
182
183 METHOD(tcg_seg_attr_next_seg_t, get_base_attr_id, uint32_t,
184 private_tcg_seg_attr_next_seg_t *this)
185 {
186 return this->base_attr_id;
187 }
188
189 METHOD(tcg_seg_attr_next_seg_t, get_cancel_flag, bool,
190 private_tcg_seg_attr_next_seg_t *this)
191 {
192 return this->cancel_flag;
193 }
194
195 /**
196 * Described in header.
197 */
198 pa_tnc_attr_t* tcg_seg_attr_next_seg_create(uint32_t base_attr_id, bool cancel)
199 {
200 private_tcg_seg_attr_next_seg_t *this;
201
202 INIT(this,
203 .public = {
204 .pa_tnc_attribute = {
205 .get_type = _get_type,
206 .get_value = _get_value,
207 .get_noskip_flag = _get_noskip_flag,
208 .set_noskip_flag = _set_noskip_flag,
209 .build = _build,
210 .process = _process,
211 .add_segment = _add_segment,
212 .get_ref = _get_ref,
213 .destroy = _destroy,
214 },
215 .get_base_attr_id = _get_base_attr_id,
216 .get_cancel_flag = _get_cancel_flag,
217 },
218 .type = { PEN_TCG, TCG_SEG_NEXT_SEG_REQ },
219 .base_attr_id = base_attr_id,
220 .cancel_flag = cancel,
221 .ref = 1,
222 );
223
224 return &this->public.pa_tnc_attribute;
225 }
226
227 /**
228 * Described in header.
229 */
230 pa_tnc_attr_t *tcg_seg_attr_next_seg_create_from_data(size_t length,
231 chunk_t data)
232 {
233 private_tcg_seg_attr_next_seg_t *this;
234
235 INIT(this,
236 .public = {
237 .pa_tnc_attribute = {
238 .get_type = _get_type,
239 .get_value = _get_value,
240 .get_noskip_flag = _get_noskip_flag,
241 .set_noskip_flag = _set_noskip_flag,
242 .build = _build,
243 .process = _process,
244 .add_segment = _add_segment,
245 .get_ref = _get_ref,
246 .destroy = _destroy,
247 },
248 .get_base_attr_id = _get_base_attr_id,
249 .get_cancel_flag = _get_cancel_flag,
250 },
251 .type = { PEN_TCG, TCG_SEG_NEXT_SEG_REQ },
252 .length = length,
253 .value = chunk_clone(data),
254 .ref = 1,
255 );
256
257 return &this->public.pa_tnc_attribute;
258 }