summaryrefslogtreecommitdiff
path: root/src/lib/libssl/bs_cbb.c
diff options
context:
space:
mode:
authorcvs2svn <admin@example.com>2015-03-08 16:48:49 +0000
committercvs2svn <admin@example.com>2015-03-08 16:48:49 +0000
commitdecf84ba5550c1656a7fdb51b5b81969590c3f03 (patch)
tree44872802e872bdfd60730fa9cf01d9d5751251c1 /src/lib/libssl/bs_cbb.c
parent7a8f138352aa4eb7b65ac4b1a5fe7630fbee1427 (diff)
downloadopenbsd-libressl-v2.1.5.tar.gz
openbsd-libressl-v2.1.5.tar.bz2
openbsd-libressl-v2.1.5.zip
This commit was manufactured by cvs2git to create branch 'OPENBSD_5_7'.libressl-v2.1.5
Diffstat (limited to 'src/lib/libssl/bs_cbb.c')
-rw-r--r--src/lib/libssl/bs_cbb.c402
1 files changed, 0 insertions, 402 deletions
diff --git a/src/lib/libssl/bs_cbb.c b/src/lib/libssl/bs_cbb.c
deleted file mode 100644
index 5546fac97f..0000000000
--- a/src/lib/libssl/bs_cbb.c
+++ /dev/null
@@ -1,402 +0,0 @@
1/* $OpenBSD: bs_cbb.c,v 1.5 2015/02/07 06:10:32 doug Exp $ */
2/*
3 * Copyright (c) 2014, Google Inc.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
14 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
15 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
16
17#include <assert.h>
18#include <stdlib.h>
19#include <string.h>
20
21#include <openssl/opensslconf.h>
22
23#include "bytestring.h"
24
25static int
26cbb_init(CBB *cbb, uint8_t *buf, size_t cap)
27{
28 struct cbb_buffer_st *base;
29
30 base = malloc(sizeof(struct cbb_buffer_st));
31 if (base == NULL)
32 return 0;
33
34 base->buf = buf;
35 base->len = 0;
36 base->cap = cap;
37 base->can_resize = 1;
38
39 memset(cbb, 0, sizeof(CBB));
40 cbb->base = base;
41 cbb->is_top_level = 1;
42 return 1;
43}
44
45int
46CBB_init(CBB *cbb, size_t initial_capacity)
47{
48 uint8_t *buf;
49
50 buf = malloc(initial_capacity);
51 if (initial_capacity > 0 && buf == NULL)
52 return 0;
53
54 if (!cbb_init(cbb, buf, initial_capacity)) {
55 free(buf);
56 return 0;
57 }
58 return 1;
59}
60
61int
62CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len)
63{
64 if (!cbb_init(cbb, buf, len))
65 return 0;
66
67 cbb->base->can_resize = 0;
68 return 1;
69}
70
71void
72CBB_cleanup(CBB *cbb)
73{
74 if (cbb->base) {
75 if (cbb->base->buf && cbb->base->can_resize)
76 free(cbb->base->buf);
77
78 free(cbb->base);
79 }
80 cbb->base = NULL;
81}
82
83static int
84cbb_buffer_add(struct cbb_buffer_st *base, uint8_t **out, size_t len)
85{
86 size_t newlen;
87
88 if (base == NULL)
89 return 0;
90
91 newlen = base->len + len;
92 if (newlen < base->len)
93 /* Overflow */
94 return 0;
95
96 if (newlen > base->cap) {
97 size_t newcap = base->cap * 2;
98 uint8_t *newbuf;
99
100 if (!base->can_resize)
101 return 0;
102
103 if (newcap < base->cap || newcap < newlen)
104 newcap = newlen;
105
106 newbuf = realloc(base->buf, newcap);
107 if (newbuf == NULL)
108 return 0;
109
110 base->buf = newbuf;
111 base->cap = newcap;
112 }
113
114 if (out)
115 *out = base->buf + base->len;
116
117 base->len = newlen;
118 return 1;
119}
120
121static int
122cbb_buffer_add_u(struct cbb_buffer_st *base, uint32_t v, size_t len_len)
123{
124 uint8_t *buf;
125 size_t i;
126
127 if (len_len == 0)
128 return 1;
129
130 if (!cbb_buffer_add(base, &buf, len_len))
131 return 0;
132
133 for (i = len_len - 1; i < len_len; i--) {
134 buf[i] = v;
135 v >>= 8;
136 }
137 return 1;
138}
139
140int
141CBB_finish(CBB *cbb, uint8_t **out_data, size_t *out_len)
142{
143 if (!cbb->is_top_level)
144 return 0;
145
146 if (!CBB_flush(cbb))
147 return 0;
148
149 if (cbb->base->can_resize && (out_data == NULL || out_len == NULL))
150 /*
151 * |out_data| and |out_len| can only be NULL if the CBB is
152 * fixed.
153 */
154 return 0;
155
156 if (out_data != NULL)
157 *out_data = cbb->base->buf;
158
159 if (out_len != NULL)
160 *out_len = cbb->base->len;
161
162 cbb->base->buf = NULL;
163 CBB_cleanup(cbb);
164 return 1;
165}
166
167/*
168 * CBB_flush recurses and then writes out any pending length prefix. The current
169 * length of the underlying base is taken to be the length of the
170 * length-prefixed data.
171 */
172int
173CBB_flush(CBB *cbb)
174{
175 size_t child_start, i, len;
176
177 if (cbb->base == NULL)
178 return 0;
179
180 if (cbb->child == NULL || cbb->pending_len_len == 0)
181 return 1;
182
183 child_start = cbb->offset + cbb->pending_len_len;
184
185 if (!CBB_flush(cbb->child) || child_start < cbb->offset ||
186 cbb->base->len < child_start)
187 return 0;
188
189 len = cbb->base->len - child_start;
190
191 if (cbb->pending_is_asn1) {
192 /*
193 * For ASN.1 we assume that we'll only need a single byte for
194 * the length. If that turned out to be incorrect, we have to
195 * move the contents along in order to make space.
196 */
197 size_t len_len;
198 uint8_t initial_length_byte;
199
200 assert (cbb->pending_len_len == 1);
201
202 if (len > 0xfffffffe) {
203 /* Too large. */
204 return 0;
205 } else if (len > 0xffffff) {
206 len_len = 5;
207 initial_length_byte = 0x80 | 4;
208 } else if (len > 0xffff) {
209 len_len = 4;
210 initial_length_byte = 0x80 | 3;
211 } else if (len > 0xff) {
212 len_len = 3;
213 initial_length_byte = 0x80 | 2;
214 } else if (len > 0x7f) {
215 len_len = 2;
216 initial_length_byte = 0x80 | 1;
217 } else {
218 len_len = 1;
219 initial_length_byte = len;
220 len = 0;
221 }
222
223 if (len_len != 1) {
224 /*
225 * We need to move the contents along in order to make
226 * space.
227 */
228 size_t extra_bytes = len_len - 1;
229 if (!cbb_buffer_add(cbb->base, NULL, extra_bytes))
230 return 0;
231
232 memmove(cbb->base->buf + child_start + extra_bytes,
233 cbb->base->buf + child_start, len);
234 }
235 cbb->base->buf[cbb->offset++] = initial_length_byte;
236 cbb->pending_len_len = len_len - 1;
237 }
238
239 for (i = cbb->pending_len_len - 1; i < cbb->pending_len_len; i--) {
240 cbb->base->buf[cbb->offset + i] = len;
241 len >>= 8;
242 }
243 if (len != 0)
244 return 0;
245
246 cbb->child->base = NULL;
247 cbb->child = NULL;
248 cbb->pending_len_len = 0;
249 cbb->pending_is_asn1 = 0;
250 cbb->offset = 0;
251
252 return 1;
253}
254
255
256static int
257cbb_add_length_prefixed(CBB *cbb, CBB *out_contents, size_t len_len)
258{
259 uint8_t *prefix_bytes;
260
261 if (!CBB_flush(cbb))
262 return 0;
263
264 cbb->offset = cbb->base->len;
265 if (!cbb_buffer_add(cbb->base, &prefix_bytes, len_len))
266 return 0;
267
268 memset(prefix_bytes, 0, len_len);
269 memset(out_contents, 0, sizeof(CBB));
270 out_contents->base = cbb->base;
271 cbb->child = out_contents;
272 cbb->pending_len_len = len_len;
273 cbb->pending_is_asn1 = 0;
274
275 return 1;
276}
277
278int
279CBB_add_u8_length_prefixed(CBB *cbb, CBB *out_contents)
280{
281 return cbb_add_length_prefixed(cbb, out_contents, 1);
282}
283
284int
285CBB_add_u16_length_prefixed(CBB *cbb, CBB *out_contents)
286{
287 return cbb_add_length_prefixed(cbb, out_contents, 2);
288}
289
290int
291CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents)
292{
293 return cbb_add_length_prefixed(cbb, out_contents, 3);
294}
295
296int
297CBB_add_asn1(CBB *cbb, CBB *out_contents, uint8_t tag)
298{
299 /* Long form identifier octets are not supported. */
300 if ((tag & 0x1f) == 0x1f)
301 return 0;
302
303 if (!CBB_flush(cbb) || !CBB_add_u8(cbb, tag))
304 return 0;
305
306 cbb->offset = cbb->base->len;
307 if (!CBB_add_u8(cbb, 0))
308 return 0;
309
310 memset(out_contents, 0, sizeof(CBB));
311 out_contents->base = cbb->base;
312 cbb->child = out_contents;
313 cbb->pending_len_len = 1;
314 cbb->pending_is_asn1 = 1;
315
316 return 1;
317}
318
319int
320CBB_add_bytes(CBB *cbb, const uint8_t *data, size_t len)
321{
322 uint8_t *dest;
323
324 if (!CBB_flush(cbb) || !cbb_buffer_add(cbb->base, &dest, len))
325 return 0;
326
327 memcpy(dest, data, len);
328 return 1;
329}
330
331int
332CBB_add_space(CBB *cbb, uint8_t **out_data, size_t len)
333{
334 if (!CBB_flush(cbb) || !cbb_buffer_add(cbb->base, out_data, len))
335 return 0;
336
337 return 1;
338}
339
340int
341CBB_add_u8(CBB *cbb, uint8_t value)
342{
343 if (!CBB_flush(cbb))
344 return 0;
345
346 return cbb_buffer_add_u(cbb->base, value, 1);
347}
348
349int
350CBB_add_u16(CBB *cbb, uint16_t value)
351{
352 if (!CBB_flush(cbb))
353 return 0;
354
355 return cbb_buffer_add_u(cbb->base, value, 2);
356}
357
358int
359CBB_add_u24(CBB *cbb, uint32_t value)
360{
361 if (!CBB_flush(cbb))
362 return 0;
363
364 return cbb_buffer_add_u(cbb->base, value, 3);
365}
366
367int
368CBB_add_asn1_uint64(CBB *cbb, uint64_t value)
369{
370 CBB child;
371 size_t i;
372 int started = 0;
373
374 if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER))
375 return 0;
376
377 for (i = 0; i < 8; i++) {
378 uint8_t byte = (value >> 8*(7-i)) & 0xff;
379 if (!started) {
380 if (byte == 0)
381 /* Don't encode leading zeros. */
382 continue;
383
384 /*
385 * If the high bit is set, add a padding byte to make it
386 * unsigned.
387 */
388 if ((byte & 0x80) && !CBB_add_u8(&child, 0))
389 return 0;
390
391 started = 1;
392 }
393 if (!CBB_add_u8(&child, byte))
394 return 0;
395 }
396
397 /* 0 is encoded as a single 0, not the empty string. */
398 if (!started && !CBB_add_u8(&child, 0))
399 return 0;
400
401 return CBB_flush(cbb);
402}