Coverage Report

Created: 2022-08-24 06:30

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