summaryrefslogtreecommitdiff
path: root/src/lib/libssl/bs_cbb.c
diff options
context:
space:
mode:
authorcvs2svn <admin@example.com>2015-08-02 21:54:22 +0000
committercvs2svn <admin@example.com>2015-08-02 21:54:22 +0000
commited3760bf4be4a96a89233fb8f8b84a0d44725862 (patch)
tree5609c82060f75c53af0a7641d9b33a88574876cd /src/lib/libssl/bs_cbb.c
parentf8b563fb5ba1524c821d37308f4e6abfc866bc3f (diff)
downloadopenbsd-OPENBSD_5_8_BASE.tar.gz
openbsd-OPENBSD_5_8_BASE.tar.bz2
openbsd-OPENBSD_5_8_BASE.zip
This commit was manufactured by cvs2git to create tag 'OPENBSD_5_8_BASE'.OPENBSD_5_8_BASE
Diffstat (limited to 'src/lib/libssl/bs_cbb.c')
-rw-r--r--src/lib/libssl/bs_cbb.c436
1 files changed, 0 insertions, 436 deletions
diff --git a/src/lib/libssl/bs_cbb.c b/src/lib/libssl/bs_cbb.c
deleted file mode 100644
index 441141734b..0000000000
--- a/src/lib/libssl/bs_cbb.c
+++ /dev/null
@@ -1,436 +0,0 @@
1/* $OpenBSD: bs_cbb.c,v 1.12 2015/06/18 23:25:07 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 = NULL;
49
50 if (initial_capacity > 0) {
51 if ((buf = malloc(initial_capacity)) == NULL)
52 return 0;
53 }
54
55 if (!cbb_init(cbb, buf, initial_capacity)) {
56 free(buf);
57 return 0;
58 }
59 return 1;
60}
61
62int
63CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len)
64{
65 if (!cbb_init(cbb, buf, len))
66 return 0;
67
68 cbb->base->can_resize = 0;
69 return 1;
70}
71
72void
73CBB_cleanup(CBB *cbb)
74{
75 if (cbb->base) {
76 if (cbb->base->can_resize)
77 free(cbb->base->buf);
78
79 free(cbb->base);
80 }
81 cbb->base = NULL;
82}
83
84static int
85cbb_buffer_add(struct cbb_buffer_st *base, uint8_t **out, size_t len)
86{
87 size_t newlen;
88
89 if (base == NULL)
90 return 0;
91
92 newlen = base->len + len;
93 if (newlen < base->len)
94 /* Overflow */
95 return 0;
96
97 if (newlen > base->cap) {
98 size_t newcap = base->cap * 2;
99 uint8_t *newbuf;
100
101 if (!base->can_resize)
102 return 0;
103
104 if (newcap < base->cap || newcap < newlen)
105 newcap = newlen;
106
107 newbuf = realloc(base->buf, newcap);
108 if (newbuf == NULL)
109 return 0;
110
111 base->buf = newbuf;
112 base->cap = newcap;
113 }
114
115 if (out)
116 *out = base->buf + base->len;
117
118 base->len = newlen;
119 return 1;
120}
121
122static int
123cbb_add_u(CBB *cbb, uint32_t v, size_t len_len)
124{
125 uint8_t *buf;
126 size_t i;
127
128 if (len_len == 0)
129 return 1;
130
131 if (len_len > 4)
132 return 0;
133
134 if (!CBB_flush(cbb) || !cbb_buffer_add(cbb->base, &buf, len_len))
135 return 0;
136
137 for (i = len_len - 1; i < len_len; i--) {
138 buf[i] = v;
139 v >>= 8;
140 }
141 return 1;
142}
143
144int
145CBB_finish(CBB *cbb, uint8_t **out_data, size_t *out_len)
146{
147 if (!cbb->is_top_level)
148 return 0;
149
150 if (!CBB_flush(cbb))
151 return 0;
152
153 if (cbb->base->can_resize && (out_data == NULL || out_len == NULL))
154 /*
155 * |out_data| and |out_len| can only be NULL if the CBB is
156 * fixed.
157 */
158 return 0;
159
160 if (out_data != NULL)
161 *out_data = cbb->base->buf;
162
163 if (out_len != NULL)
164 *out_len = cbb->base->len;
165
166 cbb->base->buf = NULL;
167 CBB_cleanup(cbb);
168 return 1;
169}
170
171/*
172 * CBB_flush recurses and then writes out any pending length prefix. The current
173 * length of the underlying base is taken to be the length of the
174 * length-prefixed data.
175 */
176int
177CBB_flush(CBB *cbb)
178{
179 size_t child_start, i, len;
180
181 if (cbb->base == NULL)
182 return 0;
183
184 if (cbb->child == NULL || cbb->pending_len_len == 0)
185 return 1;
186
187 child_start = cbb->offset + cbb->pending_len_len;
188
189 if (!CBB_flush(cbb->child) || child_start < cbb->offset ||
190 cbb->base->len < child_start)
191 return 0;
192
193 len = cbb->base->len - child_start;
194
195 if (cbb->pending_is_asn1) {
196 /*
197 * For ASN.1, we assumed that we were using short form which
198 * only requires a single byte for the length octet.
199 *
200 * If it turns out that we need long form, we have to move
201 * the contents along in order to make space for more length
202 * octets.
203 */
204 size_t len_len = 1; /* total number of length octets */
205 uint8_t initial_length_byte;
206
207 /* We already wrote 1 byte for the length. */
208 assert (cbb->pending_len_len == 1);
209
210 /* Check for long form */
211 if (len > 0xfffffffe)
212 return 0; /* 0xffffffff is reserved */
213 else if (len > 0xffffff)
214 len_len = 5;
215 else if (len > 0xffff)
216 len_len = 4;
217 else if (len > 0xff)
218 len_len = 3;
219 else if (len > 0x7f)
220 len_len = 2;
221
222 if (len_len == 1) {
223 /* For short form, the initial byte is the length. */
224 initial_length_byte = len;
225 len = 0;
226
227 } else {
228 /*
229 * For long form, the initial byte is the number of
230 * subsequent length octets (plus bit 8 set).
231 */
232 initial_length_byte = 0x80 | (len_len - 1);
233
234 /*
235 * We need to move the contents along in order to make
236 * space for the long form length octets.
237 */
238 size_t extra_bytes = len_len - 1;
239 if (!cbb_buffer_add(cbb->base, NULL, extra_bytes))
240 return 0;
241
242 memmove(cbb->base->buf + child_start + extra_bytes,
243 cbb->base->buf + child_start, len);
244 }
245 cbb->base->buf[cbb->offset++] = initial_length_byte;
246 cbb->pending_len_len = len_len - 1;
247 }
248
249 for (i = cbb->pending_len_len - 1; i < cbb->pending_len_len; i--) {
250 cbb->base->buf[cbb->offset + i] = len;
251 len >>= 8;
252 }
253 if (len != 0)
254 return 0;
255
256 cbb->child->base = NULL;
257 cbb->child = NULL;
258 cbb->pending_len_len = 0;
259 cbb->pending_is_asn1 = 0;
260 cbb->offset = 0;
261
262 return 1;
263}
264
265
266static int
267cbb_add_length_prefixed(CBB *cbb, CBB *out_contents, size_t len_len)
268{
269 uint8_t *prefix_bytes;
270
271 if (!CBB_flush(cbb))
272 return 0;
273
274 cbb->offset = cbb->base->len;
275 if (!cbb_buffer_add(cbb->base, &prefix_bytes, len_len))
276 return 0;
277
278 memset(prefix_bytes, 0, len_len);
279 memset(out_contents, 0, sizeof(CBB));
280 out_contents->base = cbb->base;
281 cbb->child = out_contents;
282 cbb->pending_len_len = len_len;
283 cbb->pending_is_asn1 = 0;
284
285 return 1;
286}
287
288int
289CBB_add_u8_length_prefixed(CBB *cbb, CBB *out_contents)
290{
291 return cbb_add_length_prefixed(cbb, out_contents, 1);
292}
293
294int
295CBB_add_u16_length_prefixed(CBB *cbb, CBB *out_contents)
296{
297 return cbb_add_length_prefixed(cbb, out_contents, 2);
298}
299
300int
301CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents)
302{
303 return cbb_add_length_prefixed(cbb, out_contents, 3);
304}
305
306int
307CBB_add_asn1(CBB *cbb, CBB *out_contents, unsigned int tag)
308{
309 if (tag > UINT8_MAX)
310 return 0;
311
312 /* Long form identifier octets are not supported. */
313 if ((tag & 0x1f) == 0x1f)
314 return 0;
315
316 /* Short-form identifier octet only needs a single byte */
317 if (!CBB_flush(cbb) || !CBB_add_u8(cbb, tag))
318 return 0;
319
320 /*
321 * Add 1 byte to cover the short-form length octet case. If it turns
322 * out we need long-form, it will be extended later.
323 */
324 cbb->offset = cbb->base->len;
325 if (!CBB_add_u8(cbb, 0))
326 return 0;
327
328 memset(out_contents, 0, sizeof(CBB));
329 out_contents->base = cbb->base;
330 cbb->child = out_contents;
331 cbb->pending_len_len = 1;
332 cbb->pending_is_asn1 = 1;
333
334 return 1;
335}
336
337int
338CBB_add_bytes(CBB *cbb, const uint8_t *data, size_t len)
339{
340 uint8_t *dest;
341
342 if (!CBB_add_space(cbb, &dest, len))
343 return 0;
344
345 memcpy(dest, data, len);
346 return 1;
347}
348
349int
350CBB_add_space(CBB *cbb, uint8_t **out_data, size_t len)
351{
352 if (!CBB_flush(cbb) || !cbb_buffer_add(cbb->base, out_data, len))
353 return 0;
354
355 return 1;
356}
357
358int
359CBB_add_u8(CBB *cbb, size_t value)
360{
361 if (value > UINT8_MAX)
362 return 0;
363
364 return cbb_add_u(cbb, (uint32_t)value, 1);
365}
366
367int
368CBB_add_u16(CBB *cbb, size_t value)
369{
370 if (value > UINT16_MAX)
371 return 0;
372
373 return cbb_add_u(cbb, (uint32_t)value, 2);
374}
375
376int
377CBB_add_u24(CBB *cbb, size_t value)
378{
379 if (value > 0xffffffUL)
380 return 0;
381
382 return cbb_add_u(cbb, (uint32_t)value, 3);
383}
384
385int
386CBB_add_asn1_uint64(CBB *cbb, uint64_t value)
387{
388 CBB child;
389 size_t i;
390 int started = 0;
391
392 if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER))
393 return 0;
394
395 for (i = 0; i < 8; i++) {
396 uint8_t byte = (value >> 8 * (7 - i)) & 0xff;
397
398 /*
399 * ASN.1 restriction: first 9 bits cannot be all zeroes or
400 * all ones. Since this function only encodes unsigned
401 * integers, the only concerns are not encoding leading
402 * zeros and adding a padding byte if necessary.
403 *
404 * In practice, this means:
405 * 1) Skip leading octets of all zero bits in the value
406 * 2) After skipping the leading zero octets, if the next 9
407 * bits are all ones, add an all zero prefix octet (and
408 * set the high bit of the prefix octet if negative).
409 *
410 * Additionally, for an unsigned value, add an all zero
411 * prefix if the high bit of the first octet would be one.
412 */
413 if (!started) {
414 if (byte == 0)
415 /* Don't encode leading zeros. */
416 continue;
417
418 /*
419 * If the high bit is set, add a padding byte to make it
420 * unsigned.
421 */
422 if ((byte & 0x80) && !CBB_add_u8(&child, 0))
423 return 0;
424
425 started = 1;
426 }
427 if (!CBB_add_u8(&child, byte))
428 return 0;
429 }
430
431 /* 0 is encoded as a single 0, not the empty string. */
432 if (!started && !CBB_add_u8(&child, 0))
433 return 0;
434
435 return CBB_flush(cbb);
436}