Moved TLS stack to its own library
[strongswan.git] / src / libtls / tls_writer.c
1 /*
2 * Copyright (C) 2010 Martin Willi
3 * Copyright (C) 2010 revosec AG
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 "tls_writer.h"
17
18 typedef struct private_tls_writer_t private_tls_writer_t;
19
20 /**
21 * Private data of an tls_writer_t object.
22 */
23 struct private_tls_writer_t {
24
25 /**
26 * Public tls_writer_t interface.
27 */
28 tls_writer_t public;
29
30 /**
31 * Allocated buffer
32 */
33 chunk_t buf;
34
35 /**
36 * Used bytes in buffer
37 */
38 size_t used;
39
40 /**
41 * Number of bytes to increase buffer size
42 */
43 size_t increase;
44 };
45
46 /**
47 * Increase buffer size
48 */
49 static void increase(private_tls_writer_t *this)
50 {
51 this->buf.len += this->increase;
52 this->buf.ptr = realloc(this->buf.ptr, this->buf.len);
53 }
54
55 METHOD(tls_writer_t, write_uint8, void,
56 private_tls_writer_t *this, u_int8_t value)
57 {
58 if (this->used + 1 > this->buf.len)
59 {
60 increase(this);
61 }
62 this->buf.ptr[this->used] = value;
63 this->used += 1;
64 }
65
66 METHOD(tls_writer_t, write_uint16, void,
67 private_tls_writer_t *this, u_int16_t value)
68 {
69 if (this->used + 2 > this->buf.len)
70 {
71 increase(this);
72 }
73 htoun16(this->buf.ptr + this->used, value);
74 this->used += 2;
75 }
76
77 METHOD(tls_writer_t, write_uint24, void,
78 private_tls_writer_t *this, u_int32_t value)
79 {
80 if (this->used + 3 > this->buf.len)
81 {
82 increase(this);
83 }
84 value = htonl(value);
85 memcpy(this->buf.ptr + this->used, ((char*)&value) + 1, 3);
86 this->used += 3;
87 }
88
89 METHOD(tls_writer_t, write_uint32, void,
90 private_tls_writer_t *this, u_int32_t value)
91 {
92 if (this->used + 4 > this->buf.len)
93 {
94 increase(this);
95 }
96 htoun32(this->buf.ptr + this->used, value);
97 this->used += 4;
98 }
99
100 METHOD(tls_writer_t, write_data, void,
101 private_tls_writer_t *this, chunk_t value)
102 {
103 while (this->used + value.len > this->buf.len)
104 {
105 increase(this);
106 }
107 memcpy(this->buf.ptr + this->used, value.ptr, value.len);
108 this->used += value.len;
109 }
110
111 METHOD(tls_writer_t, write_data8, void,
112 private_tls_writer_t *this, chunk_t value)
113 {
114 write_uint8(this, value.len);
115 write_data(this, value);
116 }
117
118 METHOD(tls_writer_t, write_data16, void,
119 private_tls_writer_t *this, chunk_t value)
120 {
121 write_uint16(this, value.len);
122 write_data(this, value);
123 }
124
125 METHOD(tls_writer_t, write_data24, void,
126 private_tls_writer_t *this, chunk_t value)
127 {
128 write_uint24(this, value.len);
129 write_data(this, value);
130 }
131
132 METHOD(tls_writer_t, write_data32, void,
133 private_tls_writer_t *this, chunk_t value)
134 {
135 write_uint32(this, value.len);
136 write_data(this, value);
137 }
138
139 METHOD(tls_writer_t, wrap8, void,
140 private_tls_writer_t *this)
141 {
142 if (this->used + 1 > this->buf.len)
143 {
144 increase(this);
145 }
146 memmove(this->buf.ptr + 1, this->buf.ptr, 1);
147 this->buf.ptr[0] = this->used;
148 this->used += 1;
149 }
150
151 METHOD(tls_writer_t, wrap16, void,
152 private_tls_writer_t *this)
153 {
154 if (this->used + 2 > this->buf.len)
155 {
156 increase(this);
157 }
158 memmove(this->buf.ptr + 2, this->buf.ptr, 2);
159 htoun16(this->buf.ptr, this->used);
160 this->used += 2;
161 }
162
163 METHOD(tls_writer_t, wrap24, void,
164 private_tls_writer_t *this)
165 {
166 u_int32_t len;
167
168 if (this->used + 3 > this->buf.len)
169 {
170 increase(this);
171 }
172 memmove(this->buf.ptr + 3, this->buf.ptr, 3);
173
174 len = htonl(this->used);
175 memcpy(this->buf.ptr, ((char*)&len) + 1, 3);
176 this->used += 3;
177 }
178
179 METHOD(tls_writer_t, wrap32, void,
180 private_tls_writer_t *this)
181 {
182 if (this->used + 4 > this->buf.len)
183 {
184 increase(this);
185 }
186 memmove(this->buf.ptr + 4, this->buf.ptr, 4);
187 htoun32(this->buf.ptr, this->used);
188 this->used += 4;
189 }
190
191 METHOD(tls_writer_t, get_buf, chunk_t,
192 private_tls_writer_t *this)
193 {
194 return chunk_create(this->buf.ptr, this->used);
195 }
196
197 METHOD(tls_writer_t, destroy, void,
198 private_tls_writer_t *this)
199 {
200 free(this->buf.ptr);
201 free(this);
202 }
203
204 /**
205 * See header
206 */
207 tls_writer_t *tls_writer_create(u_int32_t bufsize)
208 {
209 private_tls_writer_t *this;
210
211 INIT(this,
212 .public = {
213 .write_uint8 = _write_uint8,
214 .write_uint16 = _write_uint16,
215 .write_uint24 = _write_uint24,
216 .write_uint32 = _write_uint32,
217 .write_data = _write_data,
218 .write_data8 = _write_data8,
219 .write_data16 = _write_data16,
220 .write_data24 = _write_data24,
221 .write_data32 = _write_data32,
222 .wrap8 = _wrap8,
223 .wrap16 = _wrap16,
224 .wrap24 = _wrap24,
225 .wrap32 = _wrap32,
226 .get_buf = _get_buf,
227 .destroy = _destroy,
228 },
229 .increase = bufsize ?: 32,
230 );
231 if (bufsize)
232 {
233 this->buf = chunk_alloc(bufsize);
234 }
235
236 return &this->public;
237 }