blob: 5280dc8f9c54509f090dd9043c7b63a863b646b2 [file] [log] [blame]
Adam Langley95c29f32014-06-20 12:00:00 -07001/* Copyright (c) 2014, Google Inc.
2 *
3 * Permission to use, copy, modify, and/or distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14
15#include <openssl/bytestring.h>
16
Adam Langley8e89e642014-08-06 16:01:44 -070017#include <assert.h>
David Benjamin47b8f002017-11-22 17:05:50 -050018#include <limits.h>
Adam Langley2b2d66d2015-01-30 17:08:37 -080019#include <string.h>
Adam Langley8e89e642014-08-06 16:01:44 -070020
Adam Langley95c29f32014-06-20 12:00:00 -070021#include <openssl/mem.h>
Bob Beckdcabfe22023-02-07 19:06:08 -070022#include <openssl/err.h>
Adam Langley95c29f32014-06-20 12:00:00 -070023
David Benjamin17cf2cb2016-12-13 01:07:13 -050024#include "../internal.h"
25
Adam Langley95c29f32014-06-20 12:00:00 -070026
David Benjamina8653202015-06-28 01:26:10 -040027void CBB_zero(CBB *cbb) {
David Benjamin17cf2cb2016-12-13 01:07:13 -050028 OPENSSL_memset(cbb, 0, sizeof(CBB));
David Benjamina8653202015-06-28 01:26:10 -040029}
30
David Benjamin15ba28f2022-06-24 16:51:13 -040031static void cbb_init(CBB *cbb, uint8_t *buf, size_t cap, int can_resize) {
David Benjaminad9eee12019-04-09 20:17:30 -050032 cbb->is_child = 0;
David Benjamin15ba28f2022-06-24 16:51:13 -040033 cbb->child = NULL;
34 cbb->u.base.buf = buf;
35 cbb->u.base.len = 0;
36 cbb->u.base.cap = cap;
37 cbb->u.base.can_resize = can_resize;
38 cbb->u.base.error = 0;
Adam Langley95c29f32014-06-20 12:00:00 -070039}
40
41int CBB_init(CBB *cbb, size_t initial_capacity) {
Adam Langleya33915d2015-11-16 12:04:32 -080042 CBB_zero(cbb);
Adam Langley95c29f32014-06-20 12:00:00 -070043
Adam Langleya33915d2015-11-16 12:04:32 -080044 uint8_t *buf = OPENSSL_malloc(initial_capacity);
Adam Langley95c29f32014-06-20 12:00:00 -070045 if (initial_capacity > 0 && buf == NULL) {
46 return 0;
47 }
48
David Benjamin15ba28f2022-06-24 16:51:13 -040049 cbb_init(cbb, buf, initial_capacity, /*can_resize=*/1);
Doug Hogana84f06f2015-02-01 19:46:09 -080050 return 1;
Adam Langley95c29f32014-06-20 12:00:00 -070051}
52
53int CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len) {
Adam Langleya33915d2015-11-16 12:04:32 -080054 CBB_zero(cbb);
David Benjamin15ba28f2022-06-24 16:51:13 -040055 cbb_init(cbb, buf, len, /*can_resize=*/0);
Adam Langley95c29f32014-06-20 12:00:00 -070056 return 1;
57}
58
59void CBB_cleanup(CBB *cbb) {
David Benjaminad9eee12019-04-09 20:17:30 -050060 // Child |CBB|s are non-owning. They are implicitly discarded and should not
61 // be used with |CBB_cleanup| or |ScopedCBB|.
62 assert(!cbb->is_child);
63 if (cbb->is_child) {
64 return;
65 }
David Benjamindbb03212015-09-24 13:49:03 -040066
David Benjamin15ba28f2022-06-24 16:51:13 -040067 if (cbb->u.base.can_resize) {
68 OPENSSL_free(cbb->u.base.buf);
Adam Langley95c29f32014-06-20 12:00:00 -070069 }
Adam Langley95c29f32014-06-20 12:00:00 -070070}
71
David Benjamin4cc671c2015-12-17 01:06:10 -050072static int cbb_buffer_reserve(struct cbb_buffer_st *base, uint8_t **out,
73 size_t len) {
Adam Langley95c29f32014-06-20 12:00:00 -070074 if (base == NULL) {
75 return 0;
76 }
77
David Benjamin15ba28f2022-06-24 16:51:13 -040078 size_t newlen = base->len + len;
Adam Langley95c29f32014-06-20 12:00:00 -070079 if (newlen < base->len) {
David Benjamin808f8322017-08-18 14:06:02 -040080 // Overflow
Bob Beckdcabfe22023-02-07 19:06:08 -070081 OPENSSL_PUT_ERROR(CRYPTO, ERR_R_OVERFLOW);
David Benjamin93a034a2016-07-19 07:08:24 +020082 goto err;
Adam Langley95c29f32014-06-20 12:00:00 -070083 }
84
85 if (newlen > base->cap) {
Adam Langley95c29f32014-06-20 12:00:00 -070086 if (!base->can_resize) {
Bob Beckdcabfe22023-02-07 19:06:08 -070087 OPENSSL_PUT_ERROR(CRYPTO, ERR_R_OVERFLOW);
David Benjamin93a034a2016-07-19 07:08:24 +020088 goto err;
Adam Langley95c29f32014-06-20 12:00:00 -070089 }
90
David Benjamin15ba28f2022-06-24 16:51:13 -040091 size_t newcap = base->cap * 2;
Adam Langley95c29f32014-06-20 12:00:00 -070092 if (newcap < base->cap || newcap < newlen) {
93 newcap = newlen;
94 }
David Benjamin15ba28f2022-06-24 16:51:13 -040095 uint8_t *newbuf = OPENSSL_realloc(base->buf, newcap);
Adam Langley95c29f32014-06-20 12:00:00 -070096 if (newbuf == NULL) {
David Benjamin93a034a2016-07-19 07:08:24 +020097 goto err;
Adam Langley95c29f32014-06-20 12:00:00 -070098 }
99
100 base->buf = newbuf;
101 base->cap = newcap;
102 }
103
104 if (out) {
105 *out = base->buf + base->len;
106 }
David Benjamin4cc671c2015-12-17 01:06:10 -0500107
108 return 1;
David Benjamin93a034a2016-07-19 07:08:24 +0200109
110err:
111 base->error = 1;
112 return 0;
David Benjamin4cc671c2015-12-17 01:06:10 -0500113}
114
115static int cbb_buffer_add(struct cbb_buffer_st *base, uint8_t **out,
116 size_t len) {
117 if (!cbb_buffer_reserve(base, out, len)) {
118 return 0;
119 }
David Benjamin808f8322017-08-18 14:06:02 -0400120 // This will not overflow or |cbb_buffer_reserve| would have failed.
David Benjamin4cc671c2015-12-17 01:06:10 -0500121 base->len += len;
Adam Langley95c29f32014-06-20 12:00:00 -0700122 return 1;
123}
124
Adam Langley95c29f32014-06-20 12:00:00 -0700125int CBB_finish(CBB *cbb, uint8_t **out_data, size_t *out_len) {
David Benjaminad9eee12019-04-09 20:17:30 -0500126 if (cbb->is_child) {
Bob Beckdcabfe22023-02-07 19:06:08 -0700127 OPENSSL_PUT_ERROR(CRYPTO, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
Adam Langley95c29f32014-06-20 12:00:00 -0700128 return 0;
129 }
130
131 if (!CBB_flush(cbb)) {
132 return 0;
133 }
134
David Benjamin15ba28f2022-06-24 16:51:13 -0400135 if (cbb->u.base.can_resize && (out_data == NULL || out_len == NULL)) {
David Benjamin808f8322017-08-18 14:06:02 -0400136 // |out_data| and |out_len| can only be NULL if the CBB is fixed.
David Benjamin98e882e2014-08-08 13:24:34 -0400137 return 0;
138 }
139
140 if (out_data != NULL) {
David Benjamin15ba28f2022-06-24 16:51:13 -0400141 *out_data = cbb->u.base.buf;
David Benjamin98e882e2014-08-08 13:24:34 -0400142 }
143 if (out_len != NULL) {
David Benjamin15ba28f2022-06-24 16:51:13 -0400144 *out_len = cbb->u.base.len;
David Benjamin98e882e2014-08-08 13:24:34 -0400145 }
David Benjamin15ba28f2022-06-24 16:51:13 -0400146 cbb->u.base.buf = NULL;
Adam Langley95c29f32014-06-20 12:00:00 -0700147 CBB_cleanup(cbb);
148 return 1;
149}
150
David Benjamin15ba28f2022-06-24 16:51:13 -0400151static struct cbb_buffer_st *cbb_get_base(CBB *cbb) {
152 if (cbb->is_child) {
153 return cbb->u.child.base;
154 }
155 return &cbb->u.base;
156}
157
David Benjamin808f8322017-08-18 14:06:02 -0400158// CBB_flush recurses and then writes out any pending length prefix. The
159// current length of the underlying base is taken to be the length of the
160// length-prefixed data.
Adam Langley95c29f32014-06-20 12:00:00 -0700161int CBB_flush(CBB *cbb) {
David Benjamin15ba28f2022-06-24 16:51:13 -0400162 // If |base| has hit an error, the buffer is in an undefined state, so
David Benjamin808f8322017-08-18 14:06:02 -0400163 // fail all following calls. In particular, |cbb->child| may point to invalid
164 // memory.
David Benjamin15ba28f2022-06-24 16:51:13 -0400165 struct cbb_buffer_st *base = cbb_get_base(cbb);
166 if (base == NULL || base->error) {
Adam Langley95c29f32014-06-20 12:00:00 -0700167 return 0;
168 }
169
David Benjamin15ba28f2022-06-24 16:51:13 -0400170 if (cbb->child == NULL) {
171 // Nothing to flush.
Adam Langley95c29f32014-06-20 12:00:00 -0700172 return 1;
173 }
174
David Benjamin15ba28f2022-06-24 16:51:13 -0400175 assert(cbb->child->is_child);
176 struct cbb_child_st *child = &cbb->child->u.child;
177 assert(child->base == base);
178 size_t child_start = child->offset + child->pending_len_len;
Adam Langley95c29f32014-06-20 12:00:00 -0700179
180 if (!CBB_flush(cbb->child) ||
David Benjamin15ba28f2022-06-24 16:51:13 -0400181 child_start < child->offset ||
182 base->len < child_start) {
David Benjamin93a034a2016-07-19 07:08:24 +0200183 goto err;
Adam Langley95c29f32014-06-20 12:00:00 -0700184 }
185
David Benjamin15ba28f2022-06-24 16:51:13 -0400186 size_t len = base->len - child_start;
Adam Langley95c29f32014-06-20 12:00:00 -0700187
David Benjamin15ba28f2022-06-24 16:51:13 -0400188 if (child->pending_is_asn1) {
David Benjamin808f8322017-08-18 14:06:02 -0400189 // For ASN.1 we assume that we'll only need a single byte for the length.
190 // If that turned out to be incorrect, we have to move the contents along
191 // in order to make space.
David Benjamin22edd872016-08-04 21:38:40 +0000192 uint8_t len_len;
Adam Langley95c29f32014-06-20 12:00:00 -0700193 uint8_t initial_length_byte;
194
David Benjamin15ba28f2022-06-24 16:51:13 -0400195 assert (child->pending_len_len == 1);
Adam Langley8e89e642014-08-06 16:01:44 -0700196
Adam Langley95c29f32014-06-20 12:00:00 -0700197 if (len > 0xfffffffe) {
Bob Beckdcabfe22023-02-07 19:06:08 -0700198 OPENSSL_PUT_ERROR(CRYPTO, ERR_R_OVERFLOW);
David Benjamin808f8322017-08-18 14:06:02 -0400199 // Too large.
David Benjamin93a034a2016-07-19 07:08:24 +0200200 goto err;
Adam Langley95c29f32014-06-20 12:00:00 -0700201 } else if (len > 0xffffff) {
202 len_len = 5;
203 initial_length_byte = 0x80 | 4;
204 } else if (len > 0xffff) {
205 len_len = 4;
206 initial_length_byte = 0x80 | 3;
207 } else if (len > 0xff) {
208 len_len = 3;
209 initial_length_byte = 0x80 | 2;
210 } else if (len > 0x7f) {
211 len_len = 2;
212 initial_length_byte = 0x80 | 1;
213 } else {
214 len_len = 1;
David Benjamin22edd872016-08-04 21:38:40 +0000215 initial_length_byte = (uint8_t)len;
Adam Langley95c29f32014-06-20 12:00:00 -0700216 len = 0;
217 }
218
219 if (len_len != 1) {
David Benjamin808f8322017-08-18 14:06:02 -0400220 // We need to move the contents along in order to make space.
Adam Langley95c29f32014-06-20 12:00:00 -0700221 size_t extra_bytes = len_len - 1;
David Benjamin15ba28f2022-06-24 16:51:13 -0400222 if (!cbb_buffer_add(base, NULL, extra_bytes)) {
David Benjamin93a034a2016-07-19 07:08:24 +0200223 goto err;
Adam Langley95c29f32014-06-20 12:00:00 -0700224 }
David Benjamin15ba28f2022-06-24 16:51:13 -0400225 OPENSSL_memmove(base->buf + child_start + extra_bytes,
226 base->buf + child_start, len);
Adam Langley95c29f32014-06-20 12:00:00 -0700227 }
David Benjamin15ba28f2022-06-24 16:51:13 -0400228 base->buf[child->offset++] = initial_length_byte;
229 child->pending_len_len = len_len - 1;
Adam Langley95c29f32014-06-20 12:00:00 -0700230 }
231
David Benjamin15ba28f2022-06-24 16:51:13 -0400232 for (size_t i = child->pending_len_len - 1; i < child->pending_len_len; i--) {
233 base->buf[child->offset + i] = (uint8_t)len;
Adam Langley95c29f32014-06-20 12:00:00 -0700234 len >>= 8;
235 }
236 if (len != 0) {
Bob Beckdcabfe22023-02-07 19:06:08 -0700237 OPENSSL_PUT_ERROR(CRYPTO, ERR_R_OVERFLOW);
David Benjamin93a034a2016-07-19 07:08:24 +0200238 goto err;
Adam Langley95c29f32014-06-20 12:00:00 -0700239 }
240
David Benjamin15ba28f2022-06-24 16:51:13 -0400241 child->base = NULL;
Adam Langley95c29f32014-06-20 12:00:00 -0700242 cbb->child = NULL;
Adam Langley95c29f32014-06-20 12:00:00 -0700243
244 return 1;
David Benjamin93a034a2016-07-19 07:08:24 +0200245
246err:
David Benjamin15ba28f2022-06-24 16:51:13 -0400247 base->error = 1;
David Benjamin93a034a2016-07-19 07:08:24 +0200248 return 0;
Adam Langley95c29f32014-06-20 12:00:00 -0700249}
250
David Benjamin2a0b3912015-12-18 01:01:21 -0500251const uint8_t *CBB_data(const CBB *cbb) {
252 assert(cbb->child == NULL);
David Benjamin15ba28f2022-06-24 16:51:13 -0400253 if (cbb->is_child) {
254 return cbb->u.child.base->buf + cbb->u.child.offset +
255 cbb->u.child.pending_len_len;
256 }
257 return cbb->u.base.buf;
David Benjamin2a0b3912015-12-18 01:01:21 -0500258}
259
Adam Langley614c66a2015-06-12 15:26:58 -0700260size_t CBB_len(const CBB *cbb) {
261 assert(cbb->child == NULL);
David Benjamin15ba28f2022-06-24 16:51:13 -0400262 if (cbb->is_child) {
263 assert(cbb->u.child.offset + cbb->u.child.pending_len_len <=
264 cbb->u.child.base->len);
265 return cbb->u.child.base->len - cbb->u.child.offset -
266 cbb->u.child.pending_len_len;
267 }
268 return cbb->u.base.len;
269}
Adam Langley614c66a2015-06-12 15:26:58 -0700270
David Benjamin15ba28f2022-06-24 16:51:13 -0400271static int cbb_add_child(CBB *cbb, CBB *out_child, uint8_t len_len,
272 int is_asn1) {
273 assert(cbb->child == NULL);
274 assert(!is_asn1 || len_len == 1);
275 struct cbb_buffer_st *base = cbb_get_base(cbb);
276 size_t offset = base->len;
277
278 // Reserve space for the length prefix.
279 uint8_t *prefix_bytes;
280 if (!cbb_buffer_add(base, &prefix_bytes, len_len)) {
281 return 0;
282 }
283 OPENSSL_memset(prefix_bytes, 0, len_len);
284
285 CBB_zero(out_child);
286 out_child->is_child = 1;
287 out_child->u.child.base = base;
288 out_child->u.child.offset = offset;
289 out_child->u.child.pending_len_len = len_len;
290 out_child->u.child.pending_is_asn1 = is_asn1;
291 cbb->child = out_child;
292 return 1;
Adam Langley614c66a2015-06-12 15:26:58 -0700293}
Adam Langley95c29f32014-06-20 12:00:00 -0700294
295static int cbb_add_length_prefixed(CBB *cbb, CBB *out_contents,
David Benjamin22edd872016-08-04 21:38:40 +0000296 uint8_t len_len) {
Adam Langley95c29f32014-06-20 12:00:00 -0700297 if (!CBB_flush(cbb)) {
298 return 0;
299 }
300
David Benjamin15ba28f2022-06-24 16:51:13 -0400301 return cbb_add_child(cbb, out_contents, len_len, /*is_asn1=*/0);
Adam Langley95c29f32014-06-20 12:00:00 -0700302}
303
304int CBB_add_u8_length_prefixed(CBB *cbb, CBB *out_contents) {
305 return cbb_add_length_prefixed(cbb, out_contents, 1);
306}
307
308int CBB_add_u16_length_prefixed(CBB *cbb, CBB *out_contents) {
309 return cbb_add_length_prefixed(cbb, out_contents, 2);
310}
311
312int CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents) {
313 return cbb_add_length_prefixed(cbb, out_contents, 3);
314}
315
David Benjamin47b8f002017-11-22 17:05:50 -0500316// add_base128_integer encodes |v| as a big-endian base-128 integer where the
317// high bit of each byte indicates where there is more data. This is the
318// encoding used in DER for both high tag number form and OID components.
David Benjamin095b6c92017-11-29 17:17:41 -0500319static int add_base128_integer(CBB *cbb, uint64_t v) {
David Benjamin47b8f002017-11-22 17:05:50 -0500320 unsigned len_len = 0;
David Benjamin095b6c92017-11-29 17:17:41 -0500321 uint64_t copy = v;
David Benjamin47b8f002017-11-22 17:05:50 -0500322 while (copy > 0) {
323 len_len++;
324 copy >>= 7;
325 }
326 if (len_len == 0) {
327 len_len = 1; // Zero is encoded with one byte.
328 }
329 for (unsigned i = len_len - 1; i < len_len; i--) {
330 uint8_t byte = (v >> (7 * i)) & 0x7f;
331 if (i != 0) {
332 // The high bit denotes whether there is more data.
333 byte |= 0x80;
334 }
335 if (!CBB_add_u8(cbb, byte)) {
336 return 0;
337 }
338 }
339 return 1;
340}
341
David Benjamina1dffbf2022-10-25 16:29:43 -0400342int CBB_add_asn1(CBB *cbb, CBB *out_contents, CBS_ASN1_TAG tag) {
David Benjamind9f49972017-12-21 23:11:23 -0500343 if (!CBB_flush(cbb)) {
Doug Hogan5ba30562015-02-02 00:40:21 -0800344 return 0;
345 }
346
David Benjamind9f49972017-12-21 23:11:23 -0500347 // Split the tag into leading bits and tag number.
348 uint8_t tag_bits = (tag >> CBS_ASN1_TAG_SHIFT) & 0xe0;
David Benjamina1dffbf2022-10-25 16:29:43 -0400349 CBS_ASN1_TAG tag_number = tag & CBS_ASN1_TAG_NUMBER_MASK;
David Benjamind9f49972017-12-21 23:11:23 -0500350 if (tag_number >= 0x1f) {
351 // Set all the bits in the tag number to signal high tag number form.
352 if (!CBB_add_u8(cbb, tag_bits | 0x1f) ||
353 !add_base128_integer(cbb, tag_number)) {
354 return 0;
355 }
356 } else if (!CBB_add_u8(cbb, tag_bits | tag_number)) {
Adam Langley95c29f32014-06-20 12:00:00 -0700357 return 0;
358 }
359
David Benjamin15ba28f2022-06-24 16:51:13 -0400360 // Reserve one byte of length prefix. |CBB_flush| will finish it later.
361 return cbb_add_child(cbb, out_contents, /*len_len=*/1, /*is_asn1=*/1);
Adam Langley95c29f32014-06-20 12:00:00 -0700362}
363
364int CBB_add_bytes(CBB *cbb, const uint8_t *data, size_t len) {
David Benjamin15ba28f2022-06-24 16:51:13 -0400365 uint8_t *out;
366 if (!CBB_add_space(cbb, &out, len)) {
Adam Langley95c29f32014-06-20 12:00:00 -0700367 return 0;
368 }
David Benjamin15ba28f2022-06-24 16:51:13 -0400369 OPENSSL_memcpy(out, data, len);
Adam Langley95c29f32014-06-20 12:00:00 -0700370 return 1;
371}
372
David Benjamin95450622021-07-16 18:24:02 -0400373int CBB_add_zeros(CBB *cbb, size_t len) {
374 uint8_t *out;
375 if (!CBB_add_space(cbb, &out, len)) {
376 return 0;
377 }
378 OPENSSL_memset(out, 0, len);
379 return 1;
380}
381
Adam Langleyeeb9f492014-08-06 16:29:56 -0700382int CBB_add_space(CBB *cbb, uint8_t **out_data, size_t len) {
383 if (!CBB_flush(cbb) ||
David Benjamin15ba28f2022-06-24 16:51:13 -0400384 !cbb_buffer_add(cbb_get_base(cbb), out_data, len)) {
Adam Langleyeeb9f492014-08-06 16:29:56 -0700385 return 0;
386 }
387 return 1;
388}
389
David Benjamin4cc671c2015-12-17 01:06:10 -0500390int CBB_reserve(CBB *cbb, uint8_t **out_data, size_t len) {
391 if (!CBB_flush(cbb) ||
David Benjamin15ba28f2022-06-24 16:51:13 -0400392 !cbb_buffer_reserve(cbb_get_base(cbb), out_data, len)) {
David Benjamin4cc671c2015-12-17 01:06:10 -0500393 return 0;
394 }
395 return 1;
396}
397
398int CBB_did_write(CBB *cbb, size_t len) {
David Benjamin15ba28f2022-06-24 16:51:13 -0400399 struct cbb_buffer_st *base = cbb_get_base(cbb);
400 size_t newlen = base->len + len;
David Benjamin4cc671c2015-12-17 01:06:10 -0500401 if (cbb->child != NULL ||
David Benjamin15ba28f2022-06-24 16:51:13 -0400402 newlen < base->len ||
403 newlen > base->cap) {
David Benjamin4cc671c2015-12-17 01:06:10 -0500404 return 0;
405 }
David Benjamin15ba28f2022-06-24 16:51:13 -0400406 base->len = newlen;
407 return 1;
408}
409
410static int cbb_add_u(CBB *cbb, uint64_t v, size_t len_len) {
411 uint8_t *buf;
412 if (!CBB_add_space(cbb, &buf, len_len)) {
413 return 0;
414 }
415
416 for (size_t i = len_len - 1; i < len_len; i--) {
417 buf[i] = v;
418 v >>= 8;
419 }
420
421 // |v| must fit in |len_len| bytes.
422 if (v != 0) {
423 cbb_get_base(cbb)->error = 1;
424 return 0;
425 }
426
David Benjamin4cc671c2015-12-17 01:06:10 -0500427 return 1;
428}
429
Adam Langley95c29f32014-06-20 12:00:00 -0700430int CBB_add_u8(CBB *cbb, uint8_t value) {
David Benjamin15ba28f2022-06-24 16:51:13 -0400431 return cbb_add_u(cbb, value, 1);
Adam Langley95c29f32014-06-20 12:00:00 -0700432}
433
434int CBB_add_u16(CBB *cbb, uint16_t value) {
David Benjamin15ba28f2022-06-24 16:51:13 -0400435 return cbb_add_u(cbb, value, 2);
Adam Langley95c29f32014-06-20 12:00:00 -0700436}
437
Adam Langleya965a252020-01-15 16:08:03 -0800438int CBB_add_u16le(CBB *cbb, uint16_t value) {
439 return CBB_add_u16(cbb, CRYPTO_bswap2(value));
440}
441
Adam Langley95c29f32014-06-20 12:00:00 -0700442int CBB_add_u24(CBB *cbb, uint32_t value) {
David Benjamin15ba28f2022-06-24 16:51:13 -0400443 return cbb_add_u(cbb, value, 3);
Adam Langley95c29f32014-06-20 12:00:00 -0700444}
David Benjaminb5b68542014-10-19 13:14:30 -0400445
David Benjaminbb076e32016-06-21 23:13:10 -0400446int CBB_add_u32(CBB *cbb, uint32_t value) {
David Benjamin15ba28f2022-06-24 16:51:13 -0400447 return cbb_add_u(cbb, value, 4);
David Benjaminbb076e32016-06-21 23:13:10 -0400448}
449
Adam Langleya965a252020-01-15 16:08:03 -0800450int CBB_add_u32le(CBB *cbb, uint32_t value) {
451 return CBB_add_u32(cbb, CRYPTO_bswap4(value));
452}
453
Kaustubha Govindc18353d2019-02-21 12:40:06 -0500454int CBB_add_u64(CBB *cbb, uint64_t value) {
David Benjamin15ba28f2022-06-24 16:51:13 -0400455 return cbb_add_u(cbb, value, 8);
Kaustubha Govindc18353d2019-02-21 12:40:06 -0500456}
457
Adam Langleya965a252020-01-15 16:08:03 -0800458int CBB_add_u64le(CBB *cbb, uint64_t value) {
459 return CBB_add_u64(cbb, CRYPTO_bswap8(value));
460}
461
David Benjamine8d53502015-10-10 14:13:23 -0400462void CBB_discard_child(CBB *cbb) {
463 if (cbb->child == NULL) {
464 return;
465 }
466
David Benjamin15ba28f2022-06-24 16:51:13 -0400467 struct cbb_buffer_st *base = cbb_get_base(cbb);
468 assert(cbb->child->is_child);
469 base->len = cbb->child->u.child.offset;
David Benjamine8d53502015-10-10 14:13:23 -0400470
David Benjamin15ba28f2022-06-24 16:51:13 -0400471 cbb->child->u.child.base = NULL;
David Benjamine8d53502015-10-10 14:13:23 -0400472 cbb->child = NULL;
David Benjamine8d53502015-10-10 14:13:23 -0400473}
474
David Benjaminb5b68542014-10-19 13:14:30 -0400475int CBB_add_asn1_uint64(CBB *cbb, uint64_t value) {
David Benjamin1ee71182022-10-06 15:07:20 -0400476 return CBB_add_asn1_uint64_with_tag(cbb, value, CBS_ASN1_INTEGER);
477}
David Benjaminb5b68542014-10-19 13:14:30 -0400478
David Benjamina1dffbf2022-10-25 16:29:43 -0400479int CBB_add_asn1_uint64_with_tag(CBB *cbb, uint64_t value, CBS_ASN1_TAG tag) {
David Benjamin1ee71182022-10-06 15:07:20 -0400480 CBB child;
481 if (!CBB_add_asn1(cbb, &child, tag)) {
David Benjaminb5b68542014-10-19 13:14:30 -0400482 return 0;
483 }
484
David Benjamin1ee71182022-10-06 15:07:20 -0400485 int started = 0;
David Benjamin54091232016-09-05 12:47:25 -0400486 for (size_t i = 0; i < 8; i++) {
David Benjaminb5b68542014-10-19 13:14:30 -0400487 uint8_t byte = (value >> 8*(7-i)) & 0xff;
488 if (!started) {
489 if (byte == 0) {
David Benjamin808f8322017-08-18 14:06:02 -0400490 // Don't encode leading zeros.
David Benjaminb5b68542014-10-19 13:14:30 -0400491 continue;
492 }
David Benjamin808f8322017-08-18 14:06:02 -0400493 // If the high bit is set, add a padding byte to make it
494 // unsigned.
David Benjaminb5b68542014-10-19 13:14:30 -0400495 if ((byte & 0x80) && !CBB_add_u8(&child, 0)) {
496 return 0;
497 }
498 started = 1;
499 }
500 if (!CBB_add_u8(&child, byte)) {
501 return 0;
502 }
503 }
504
David Benjamin808f8322017-08-18 14:06:02 -0400505 // 0 is encoded as a single 0, not the empty string.
David Benjaminb5b68542014-10-19 13:14:30 -0400506 if (!started && !CBB_add_u8(&child, 0)) {
507 return 0;
508 }
509
510 return CBB_flush(cbb);
511}
David Benjamin47b8f002017-11-22 17:05:50 -0500512
Matthew Braithwaite82dbb532019-12-10 12:18:42 -0800513int CBB_add_asn1_int64(CBB *cbb, int64_t value) {
David Benjamin1ee71182022-10-06 15:07:20 -0400514 return CBB_add_asn1_int64_with_tag(cbb, value, CBS_ASN1_INTEGER);
515}
516
David Benjamina1dffbf2022-10-25 16:29:43 -0400517int CBB_add_asn1_int64_with_tag(CBB *cbb, int64_t value, CBS_ASN1_TAG tag) {
Matthew Braithwaite82dbb532019-12-10 12:18:42 -0800518 if (value >= 0) {
David Benjamin1ee71182022-10-06 15:07:20 -0400519 return CBB_add_asn1_uint64_with_tag(cbb, (uint64_t)value, tag);
Matthew Braithwaite82dbb532019-12-10 12:18:42 -0800520 }
521
David Benjamin1e469e42022-05-13 17:06:56 -0400522 uint8_t bytes[sizeof(int64_t)];
523 memcpy(bytes, &value, sizeof(value));
Matthew Braithwaite82dbb532019-12-10 12:18:42 -0800524 int start = 7;
525 // Skip leading sign-extension bytes unless they are necessary.
David Benjamin1e469e42022-05-13 17:06:56 -0400526 while (start > 0 && (bytes[start] == 0xff && (bytes[start - 1] & 0x80))) {
Matthew Braithwaite82dbb532019-12-10 12:18:42 -0800527 start--;
528 }
529
530 CBB child;
David Benjamin1ee71182022-10-06 15:07:20 -0400531 if (!CBB_add_asn1(cbb, &child, tag)) {
Matthew Braithwaite82dbb532019-12-10 12:18:42 -0800532 return 0;
533 }
534 for (int i = start; i >= 0; i--) {
David Benjamin1e469e42022-05-13 17:06:56 -0400535 if (!CBB_add_u8(&child, bytes[i])) {
Matthew Braithwaite82dbb532019-12-10 12:18:42 -0800536 return 0;
537 }
538 }
539 return CBB_flush(cbb);
540}
541
Adam Langleyc61b5772018-01-25 15:37:46 -0800542int CBB_add_asn1_octet_string(CBB *cbb, const uint8_t *data, size_t data_len) {
543 CBB child;
544 if (!CBB_add_asn1(cbb, &child, CBS_ASN1_OCTETSTRING) ||
545 !CBB_add_bytes(&child, data, data_len) ||
546 !CBB_flush(cbb)) {
547 return 0;
548 }
549
550 return 1;
551}
552
553int CBB_add_asn1_bool(CBB *cbb, int value) {
554 CBB child;
555 if (!CBB_add_asn1(cbb, &child, CBS_ASN1_BOOLEAN) ||
556 !CBB_add_u8(&child, value != 0 ? 0xff : 0) ||
557 !CBB_flush(cbb)) {
558 return 0;
559 }
560
561 return 1;
562}
563
David Benjamin47b8f002017-11-22 17:05:50 -0500564// parse_dotted_decimal parses one decimal component from |cbs|, where |cbs| is
565// an OID literal, e.g., "1.2.840.113554.4.1.72585". It consumes both the
566// component and the dot, so |cbs| may be passed into the function again for the
567// next value.
David Benjamin095b6c92017-11-29 17:17:41 -0500568static int parse_dotted_decimal(CBS *cbs, uint64_t *out) {
David Benjamin50a5caf2022-12-28 18:33:18 -0500569 if (!CBS_get_u64_decimal(cbs, out)) {
570 return 0;
David Benjamin47b8f002017-11-22 17:05:50 -0500571 }
David Benjamin50a5caf2022-12-28 18:33:18 -0500572
573 // The integer must have either ended at the end of the string, or a
574 // non-terminal dot, which should be consumed. If the string ends with a dot,
575 // this is not a valid OID string.
576 uint8_t dot;
577 return !CBS_get_u8(cbs, &dot) || (dot == '.' && CBS_len(cbs) > 0);
David Benjamin47b8f002017-11-22 17:05:50 -0500578}
579
580int CBB_add_asn1_oid_from_text(CBB *cbb, const char *text, size_t len) {
581 if (!CBB_flush(cbb)) {
582 return 0;
583 }
584
585 CBS cbs;
586 CBS_init(&cbs, (const uint8_t *)text, len);
587
588 // OIDs must have at least two components.
David Benjamin095b6c92017-11-29 17:17:41 -0500589 uint64_t a, b;
David Benjamin47b8f002017-11-22 17:05:50 -0500590 if (!parse_dotted_decimal(&cbs, &a) ||
591 !parse_dotted_decimal(&cbs, &b)) {
592 return 0;
593 }
594
595 // The first component is encoded as 40 * |a| + |b|. This assumes that |a| is
596 // 0, 1, or 2 and that, when it is 0 or 1, |b| is at most 39.
597 if (a > 2 ||
598 (a < 2 && b > 39) ||
David Benjamin095b6c92017-11-29 17:17:41 -0500599 b > UINT64_MAX - 80 ||
600 !add_base128_integer(cbb, 40u * a + b)) {
David Benjamin47b8f002017-11-22 17:05:50 -0500601 return 0;
602 }
603
604 // The remaining components are encoded unmodified.
605 while (CBS_len(&cbs) > 0) {
606 if (!parse_dotted_decimal(&cbs, &a) ||
607 !add_base128_integer(cbb, a)) {
608 return 0;
609 }
610 }
611
612 return 1;
613}
David Benjamin92e33252017-12-22 00:12:27 -0500614
615static int compare_set_of_element(const void *a_ptr, const void *b_ptr) {
616 // See X.690, section 11.6 for the ordering. They are sorted in ascending
617 // order by their DER encoding.
618 const CBS *a = a_ptr, *b = b_ptr;
619 size_t a_len = CBS_len(a), b_len = CBS_len(b);
620 size_t min_len = a_len < b_len ? a_len : b_len;
621 int ret = OPENSSL_memcmp(CBS_data(a), CBS_data(b), min_len);
622 if (ret != 0) {
623 return ret;
624 }
625 if (a_len == b_len) {
626 return 0;
627 }
628 // If one is a prefix of the other, the shorter one sorts first. (This is not
629 // actually reachable. No DER encoding is a prefix of another DER encoding.)
630 return a_len < b_len ? -1 : 1;
631}
632
633int CBB_flush_asn1_set_of(CBB *cbb) {
634 if (!CBB_flush(cbb)) {
635 return 0;
636 }
637
638 CBS cbs;
639 size_t num_children = 0;
640 CBS_init(&cbs, CBB_data(cbb), CBB_len(cbb));
641 while (CBS_len(&cbs) != 0) {
642 if (!CBS_get_any_asn1_element(&cbs, NULL, NULL, NULL)) {
Bob Beckdcabfe22023-02-07 19:06:08 -0700643 OPENSSL_PUT_ERROR(CRYPTO, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
David Benjamin92e33252017-12-22 00:12:27 -0500644 return 0;
645 }
646 num_children++;
647 }
648
649 if (num_children < 2) {
650 return 1; // Nothing to do. This is the common case for X.509.
651 }
652 if (num_children > ((size_t)-1) / sizeof(CBS)) {
653 return 0; // Overflow.
654 }
655
656 // Parse out the children and sort. We alias them into a copy of so they
657 // remain valid as we rewrite |cbb|.
658 int ret = 0;
659 size_t buf_len = CBB_len(cbb);
David Benjamin3ba95862019-10-21 16:14:33 -0400660 uint8_t *buf = OPENSSL_memdup(CBB_data(cbb), buf_len);
David Benjamin92e33252017-12-22 00:12:27 -0500661 CBS *children = OPENSSL_malloc(num_children * sizeof(CBS));
662 if (buf == NULL || children == NULL) {
663 goto err;
664 }
665 CBS_init(&cbs, buf, buf_len);
666 for (size_t i = 0; i < num_children; i++) {
667 if (!CBS_get_any_asn1_element(&cbs, &children[i], NULL, NULL)) {
668 goto err;
669 }
670 }
671 qsort(children, num_children, sizeof(CBS), compare_set_of_element);
672
David Benjamin15ba28f2022-06-24 16:51:13 -0400673 // Write the contents back in the new order.
674 uint8_t *out = (uint8_t *)CBB_data(cbb);
675 size_t offset = 0;
David Benjamin92e33252017-12-22 00:12:27 -0500676 for (size_t i = 0; i < num_children; i++) {
David Benjamin15ba28f2022-06-24 16:51:13 -0400677 OPENSSL_memcpy(out + offset, CBS_data(&children[i]), CBS_len(&children[i]));
678 offset += CBS_len(&children[i]);
David Benjamin92e33252017-12-22 00:12:27 -0500679 }
David Benjamin15ba28f2022-06-24 16:51:13 -0400680 assert(offset == buf_len);
David Benjamin92e33252017-12-22 00:12:27 -0500681
682 ret = 1;
683
684err:
685 OPENSSL_free(buf);
686 OPENSSL_free(children);
687 return ret;
688}