summaryrefslogtreecommitdiff
path: root/src/lib/libssl/bs_cbb.c
diff options
context:
space:
mode:
authorcvs2svn <admin@example.com>2021-08-18 16:06:57 +0000
committercvs2svn <admin@example.com>2021-08-18 16:06:57 +0000
commitd56c8fa8260d226f98b26f017b45b9c2b135f38d (patch)
tree348178b41617813cc93787187984a734ef8379ca /src/lib/libssl/bs_cbb.c
parent18b9c1bcab7c37d8c5bd05b8e0d14d0c59d96650 (diff)
downloadopenbsd-tb_20210818.tar.gz
openbsd-tb_20210818.tar.bz2
openbsd-tb_20210818.zip
This commit was manufactured by cvs2git to create tag 'tb_20210818'.tb_20210818
Diffstat (limited to 'src/lib/libssl/bs_cbb.c')
-rw-r--r--src/lib/libssl/bs_cbb.c467
1 files changed, 0 insertions, 467 deletions
diff --git a/src/lib/libssl/bs_cbb.c b/src/lib/libssl/bs_cbb.c
deleted file mode 100644
index e17c57edd6..0000000000
--- a/src/lib/libssl/bs_cbb.c
+++ /dev/null
@@ -1,467 +0,0 @@
1/* $OpenBSD: bs_cbb.c,v 1.26 2021/05/16 10:58:27 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
18#include <stdlib.h>
19#include <string.h>
20
21#include "bytestring.h"
22
23#define CBB_INITIAL_SIZE 64
24
25static int
26cbb_init(CBB *cbb, uint8_t *buf, size_t cap)
27{
28 struct cbb_buffer_st *base;
29
30 if ((base = calloc(1, sizeof(struct cbb_buffer_st))) == NULL)
31 return 0;
32
33 base->buf = buf;
34 base->len = 0;
35 base->cap = cap;
36 base->can_resize = 1;
37
38 cbb->base = base;
39 cbb->is_top_level = 1;
40
41 return 1;
42}
43
44int
45CBB_init(CBB *cbb, size_t initial_capacity)
46{
47 uint8_t *buf = NULL;
48
49 memset(cbb, 0, sizeof(*cbb));
50
51 if (initial_capacity == 0)
52 initial_capacity = CBB_INITIAL_SIZE;
53
54 if ((buf = calloc(1, initial_capacity)) == NULL)
55 return 0;
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 freezero(cbb->base->buf, cbb->base->cap);
84 free(cbb->base);
85 }
86 cbb->base = NULL;
87 cbb->child = 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 = recallocarray(base->buf, base->cap, newcap, 1);
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 if (cbb->pending_len_len != 1)
215 return 0;
216
217 /* Check for long form */
218 if (len > 0xfffffffe)
219 return 0; /* 0xffffffff is reserved */
220 else if (len > 0xffffff)
221 len_len = 5;
222 else if (len > 0xffff)
223 len_len = 4;
224 else if (len > 0xff)
225 len_len = 3;
226 else if (len > 0x7f)
227 len_len = 2;
228
229 if (len_len == 1) {
230 /* For short form, the initial byte is the length. */
231 initial_length_byte = len;
232 len = 0;
233
234 } else {
235 /*
236 * For long form, the initial byte is the number of
237 * subsequent length octets (plus bit 8 set).
238 */
239 initial_length_byte = 0x80 | (len_len - 1);
240
241 /*
242 * We need to move the contents along in order to make
243 * space for the long form length octets.
244 */
245 size_t extra_bytes = len_len - 1;
246 if (!cbb_buffer_add(cbb->base, NULL, extra_bytes))
247 return 0;
248
249 memmove(cbb->base->buf + child_start + extra_bytes,
250 cbb->base->buf + child_start, len);
251 }
252 cbb->base->buf[cbb->offset++] = initial_length_byte;
253 cbb->pending_len_len = len_len - 1;
254 }
255
256 for (i = cbb->pending_len_len - 1; i < cbb->pending_len_len; i--) {
257 cbb->base->buf[cbb->offset + i] = len;
258 len >>= 8;
259 }
260 if (len != 0)
261 return 0;
262
263 cbb->child->base = NULL;
264 cbb->child = NULL;
265 cbb->pending_len_len = 0;
266 cbb->pending_is_asn1 = 0;
267 cbb->offset = 0;
268
269 return 1;
270}
271
272void
273CBB_discard_child(CBB *cbb)
274{
275 if (cbb->child == NULL)
276 return;
277
278 cbb->base->len = cbb->offset;
279
280 cbb->child->base = NULL;
281 cbb->child = NULL;
282 cbb->pending_len_len = 0;
283 cbb->pending_is_asn1 = 0;
284 cbb->offset = 0;
285}
286
287static int
288cbb_add_length_prefixed(CBB *cbb, CBB *out_contents, size_t len_len)
289{
290 uint8_t *prefix_bytes;
291
292 if (!CBB_flush(cbb))
293 return 0;
294
295 cbb->offset = cbb->base->len;
296 if (!cbb_buffer_add(cbb->base, &prefix_bytes, len_len))
297 return 0;
298
299 memset(prefix_bytes, 0, len_len);
300 memset(out_contents, 0, sizeof(CBB));
301 out_contents->base = cbb->base;
302 cbb->child = out_contents;
303 cbb->pending_len_len = len_len;
304 cbb->pending_is_asn1 = 0;
305
306 return 1;
307}
308
309int
310CBB_add_u8_length_prefixed(CBB *cbb, CBB *out_contents)
311{
312 return cbb_add_length_prefixed(cbb, out_contents, 1);
313}
314
315int
316CBB_add_u16_length_prefixed(CBB *cbb, CBB *out_contents)
317{
318 return cbb_add_length_prefixed(cbb, out_contents, 2);
319}
320
321int
322CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents)
323{
324 return cbb_add_length_prefixed(cbb, out_contents, 3);
325}
326
327int
328CBB_add_asn1(CBB *cbb, CBB *out_contents, unsigned int tag)
329{
330 if (tag > UINT8_MAX)
331 return 0;
332
333 /* Long form identifier octets are not supported. */
334 if ((tag & 0x1f) == 0x1f)
335 return 0;
336
337 /* Short-form identifier octet only needs a single byte */
338 if (!CBB_flush(cbb) || !CBB_add_u8(cbb, tag))
339 return 0;
340
341 /*
342 * Add 1 byte to cover the short-form length octet case. If it turns
343 * out we need long-form, it will be extended later.
344 */
345 cbb->offset = cbb->base->len;
346 if (!CBB_add_u8(cbb, 0))
347 return 0;
348
349 memset(out_contents, 0, sizeof(CBB));
350 out_contents->base = cbb->base;
351 cbb->child = out_contents;
352 cbb->pending_len_len = 1;
353 cbb->pending_is_asn1 = 1;
354
355 return 1;
356}
357
358int
359CBB_add_bytes(CBB *cbb, const uint8_t *data, size_t len)
360{
361 uint8_t *dest;
362
363 if (!CBB_flush(cbb) || !cbb_buffer_add(cbb->base, &dest, len))
364 return 0;
365
366 memcpy(dest, data, len);
367 return 1;
368}
369
370int
371CBB_add_space(CBB *cbb, uint8_t **out_data, size_t len)
372{
373 if (!CBB_flush(cbb) || !cbb_buffer_add(cbb->base, out_data, len))
374 return 0;
375
376 memset(*out_data, 0, len);
377 return 1;
378}
379
380int
381CBB_add_u8(CBB *cbb, size_t value)
382{
383 if (value > UINT8_MAX)
384 return 0;
385
386 return cbb_add_u(cbb, (uint32_t)value, 1);
387}
388
389int
390CBB_add_u16(CBB *cbb, size_t value)
391{
392 if (value > UINT16_MAX)
393 return 0;
394
395 return cbb_add_u(cbb, (uint32_t)value, 2);
396}
397
398int
399CBB_add_u24(CBB *cbb, size_t value)
400{
401 if (value > 0xffffffUL)
402 return 0;
403
404 return cbb_add_u(cbb, (uint32_t)value, 3);
405}
406
407int
408CBB_add_u32(CBB *cbb, size_t value)
409{
410 if (value > 0xffffffffUL)
411 return 0;
412
413 return cbb_add_u(cbb, (uint32_t)value, 4);
414}
415
416int
417CBB_add_asn1_uint64(CBB *cbb, uint64_t value)
418{
419 CBB child;
420 size_t i;
421 int started = 0;
422
423 if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER))
424 return 0;
425
426 for (i = 0; i < 8; i++) {
427 uint8_t byte = (value >> 8 * (7 - i)) & 0xff;
428
429 /*
430 * ASN.1 restriction: first 9 bits cannot be all zeroes or
431 * all ones. Since this function only encodes unsigned
432 * integers, the only concerns are not encoding leading
433 * zeros and adding a padding byte if necessary.
434 *
435 * In practice, this means:
436 * 1) Skip leading octets of all zero bits in the value
437 * 2) After skipping the leading zero octets, if the next 9
438 * bits are all ones, add an all zero prefix octet (and
439 * set the high bit of the prefix octet if negative).
440 *
441 * Additionally, for an unsigned value, add an all zero
442 * prefix if the high bit of the first octet would be one.
443 */
444 if (!started) {
445 if (byte == 0)
446 /* Don't encode leading zeros. */
447 continue;
448
449 /*
450 * If the high bit is set, add a padding byte to make it
451 * unsigned.
452 */
453 if ((byte & 0x80) && !CBB_add_u8(&child, 0))
454 return 0;
455
456 started = 1;
457 }
458 if (!CBB_add_u8(&child, byte))
459 return 0;
460 }
461
462 /* 0 is encoded as a single 0, not the empty string. */
463 if (!started && !CBB_add_u8(&child, 0))
464 return 0;
465
466 return CBB_flush(cbb);
467}