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