summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lib/libssl/bs_ber.c220
-rw-r--r--src/lib/libssl/bs_cbb.c387
-rw-r--r--src/lib/libssl/bs_cbs.c390
-rw-r--r--src/lib/libssl/bytestring.h346
-rw-r--r--src/lib/libssl/src/ssl/bs_ber.c220
-rw-r--r--src/lib/libssl/src/ssl/bs_cbb.c387
-rw-r--r--src/lib/libssl/src/ssl/bs_cbs.c390
-rw-r--r--src/lib/libssl/src/ssl/bytestring.h346
-rw-r--r--src/lib/libssl/ssl/Makefile3
-rw-r--r--src/regress/lib/libssl/Makefile3
-rw-r--r--src/regress/lib/libssl/bytestring/Makefile14
-rw-r--r--src/regress/lib/libssl/bytestring/bytestringtest.c655
12 files changed, 3359 insertions, 2 deletions
diff --git a/src/lib/libssl/bs_ber.c b/src/lib/libssl/bs_ber.c
new file mode 100644
index 0000000000..b94b63e37e
--- /dev/null
+++ b/src/lib/libssl/bs_ber.c
@@ -0,0 +1,220 @@
1/* $OpenBSD: bs_ber.c,v 1.1 2015/02/06 09:36:16 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 <string.h>
18
19#include <openssl/opensslconf.h>
20
21#include "bytestring.h"
22
23/* kMaxDepth is a just a sanity limit. The code should be such that the length
24 * of the input being processes always decreases. None the less, a very large
25 * input could otherwise cause the stack to overflow. */
26static const unsigned kMaxDepth = 2048;
27
28/* cbs_find_ber walks an ASN.1 structure in |orig_in| and sets |*ber_found|
29 * depending on whether an indefinite length element was found. The value of
30 * |in| is not changed. It returns one on success (i.e. |*ber_found| was set)
31 * and zero on error. */
32static int cbs_find_ber(CBS *orig_in, char *ber_found, unsigned depth) {
33 CBS in;
34
35 if (depth > kMaxDepth) {
36 return 0;
37 }
38
39 CBS_init(&in, CBS_data(orig_in), CBS_len(orig_in));
40 *ber_found = 0;
41
42 while (CBS_len(&in) > 0) {
43 CBS contents;
44 unsigned tag;
45 size_t header_len;
46
47 if (!CBS_get_any_asn1_element(&in, &contents, &tag, &header_len)) {
48 return 0;
49 }
50 if (CBS_len(&contents) == header_len &&
51 header_len > 0 &&
52 CBS_data(&contents)[header_len-1] == 0x80) {
53 *ber_found = 1;
54 return 1;
55 }
56 if (tag & CBS_ASN1_CONSTRUCTED) {
57 if (!CBS_skip(&contents, header_len) ||
58 !cbs_find_ber(&contents, ber_found, depth + 1)) {
59 return 0;
60 }
61 }
62 }
63
64 return 1;
65}
66
67/* is_primitive_type returns true if |tag| likely a primitive type. Normally
68 * one can just test the "constructed" bit in the tag but, in BER, even
69 * primitive tags can have the constructed bit if they have indefinite
70 * length. */
71static char is_primitive_type(unsigned tag) {
72 return (tag & 0xc0) == 0 &&
73 (tag & 0x1f) != (CBS_ASN1_SEQUENCE & 0x1f) &&
74 (tag & 0x1f) != (CBS_ASN1_SET & 0x1f);
75}
76
77/* is_eoc returns true if |header_len| and |contents|, as returned by
78 * |CBS_get_any_asn1_element|, indicate an "end of contents" (EOC) value. */
79static char is_eoc(size_t header_len, CBS *contents) {
80 return header_len == 2 && CBS_len(contents) == 2 &&
81 memcmp(CBS_data(contents), "\x00\x00", 2) == 0;
82}
83
84/* cbs_convert_ber reads BER data from |in| and writes DER data to |out|. If
85 * |squash_header| is set then the top-level of elements from |in| will not
86 * have their headers written. This is used when concatenating the fragments of
87 * an indefinite length, primitive value. If |looking_for_eoc| is set then any
88 * EOC elements found will cause the function to return after consuming it.
89 * It returns one on success and zero on error. */
90static int cbs_convert_ber(CBS *in, CBB *out, char squash_header,
91 char looking_for_eoc, unsigned depth) {
92 if (depth > kMaxDepth) {
93 return 0;
94 }
95
96 while (CBS_len(in) > 0) {
97 CBS contents;
98 unsigned tag;
99 size_t header_len;
100 CBB *out_contents, out_contents_storage;
101
102 if (!CBS_get_any_asn1_element(in, &contents, &tag, &header_len)) {
103 return 0;
104 }
105 out_contents = out;
106
107 if (CBS_len(&contents) == header_len) {
108 if (is_eoc(header_len, &contents)) {
109 return looking_for_eoc;
110 }
111
112 if (header_len > 0 && CBS_data(&contents)[header_len - 1] == 0x80) {
113 /* This is an indefinite length element. If it's a SEQUENCE or SET then
114 * we just need to write the out the contents as normal, but with a
115 * concrete length prefix.
116 *
117 * If it's a something else then the contents will be a series of BER
118 * elements of the same type which need to be concatenated. */
119 const char context_specific = (tag & 0xc0) == 0x80;
120 char squash_child_headers = is_primitive_type(tag);
121
122 /* This is a hack, but it sufficies to handle NSS's output. If we find
123 * an indefinite length, context-specific tag with a definite, primtive
124 * tag inside it, then we assume that the context-specific tag is
125 * implicit and the tags within are fragments of a primitive type that
126 * need to be concatenated. */
127 if (context_specific && (tag & CBS_ASN1_CONSTRUCTED)) {
128 CBS in_copy, inner_contents;
129 unsigned inner_tag;
130 size_t inner_header_len;
131
132 CBS_init(&in_copy, CBS_data(in), CBS_len(in));
133 if (!CBS_get_any_asn1_element(&in_copy, &inner_contents, &inner_tag,
134 &inner_header_len)) {
135 return 0;
136 }
137 if (CBS_len(&inner_contents) > inner_header_len &&
138 is_primitive_type(inner_tag)) {
139 squash_child_headers = 1;
140 }
141 }
142
143 if (!squash_header) {
144 unsigned out_tag = tag;
145 if (squash_child_headers) {
146 out_tag &= ~CBS_ASN1_CONSTRUCTED;
147 }
148 if (!CBB_add_asn1(out, &out_contents_storage, out_tag)) {
149 return 0;
150 }
151 out_contents = &out_contents_storage;
152 }
153
154 if (!cbs_convert_ber(in, out_contents,
155 squash_child_headers,
156 1 /* looking for eoc */, depth + 1)) {
157 return 0;
158 }
159 if (out_contents != out && !CBB_flush(out)) {
160 return 0;
161 }
162 continue;
163 }
164 }
165
166 if (!squash_header) {
167 if (!CBB_add_asn1(out, &out_contents_storage, tag)) {
168 return 0;
169 }
170 out_contents = &out_contents_storage;
171 }
172
173 if (!CBS_skip(&contents, header_len)) {
174 return 0;
175 }
176
177 if (tag & CBS_ASN1_CONSTRUCTED) {
178 if (!cbs_convert_ber(&contents, out_contents, 0 /* don't squash header */,
179 0 /* not looking for eoc */, depth + 1)) {
180 return 0;
181 }
182 } else {
183 if (!CBB_add_bytes(out_contents, CBS_data(&contents),
184 CBS_len(&contents))) {
185 return 0;
186 }
187 }
188
189 if (out_contents != out && !CBB_flush(out)) {
190 return 0;
191 }
192 }
193
194 return looking_for_eoc == 0;
195}
196
197int CBS_asn1_ber_to_der(CBS *in, uint8_t **out, size_t *out_len) {
198 CBB cbb;
199
200 /* First, do a quick walk to find any indefinite-length elements. Most of the
201 * time we hope that there aren't any and thus we can quickly return. */
202 char conversion_needed;
203 if (!cbs_find_ber(in, &conversion_needed, 0)) {
204 return 0;
205 }
206
207 if (!conversion_needed) {
208 *out = NULL;
209 *out_len = 0;
210 return 1;
211 }
212
213 CBB_init(&cbb, CBS_len(in));
214 if (!cbs_convert_ber(in, &cbb, 0, 0, 0)) {
215 CBB_cleanup(&cbb);
216 return 0;
217 }
218
219 return CBB_finish(&cbb, out, out_len);
220}
diff --git a/src/lib/libssl/bs_cbb.c b/src/lib/libssl/bs_cbb.c
new file mode 100644
index 0000000000..668231c1c7
--- /dev/null
+++ b/src/lib/libssl/bs_cbb.c
@@ -0,0 +1,387 @@
1/* $OpenBSD: bs_cbb.c,v 1.1 2015/02/06 09:36:16 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 cbb_init(CBB *cbb, uint8_t *buf, size_t cap) {
26 struct cbb_buffer_st *base;
27
28 base = malloc(sizeof(struct cbb_buffer_st));
29 if (base == NULL) {
30 free(buf);
31 return 0;
32 }
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 CBB_init(CBB *cbb, size_t initial_capacity) {
46 uint8_t *buf;
47
48 buf = malloc(initial_capacity);
49 if (initial_capacity > 0 && buf == NULL) {
50 return 0;
51 }
52
53 return cbb_init(cbb, buf, initial_capacity);
54}
55
56int CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len) {
57 if (!cbb_init(cbb, buf, len)) {
58 return 0;
59 }
60
61 cbb->base->can_resize = 0;
62 return 1;
63}
64
65void CBB_cleanup(CBB *cbb) {
66 if (cbb->base) {
67 if (cbb->base->buf && cbb->base->can_resize) {
68 free(cbb->base->buf);
69 }
70 free(cbb->base);
71 }
72 cbb->base = NULL;
73}
74
75static int cbb_buffer_add(struct cbb_buffer_st *base, uint8_t **out,
76 size_t len) {
77 size_t newlen;
78
79 if (base == NULL) {
80 return 0;
81 }
82
83#if 0
84 // XXX Added for boringssl patch testing
85 if (len == 0) {
86 if (out) {
87 *out = NULL;
88 }
89 return 1;
90 }
91#endif
92
93 newlen = base->len + len;
94 if (newlen < base->len) {
95 /* Overflow */
96 return 0;
97 }
98
99 if (newlen > base->cap) {
100 size_t newcap = base->cap * 2;
101 uint8_t *newbuf;
102
103 if (!base->can_resize) {
104 return 0;
105 }
106
107 if (newcap < base->cap || newcap < newlen) {
108 newcap = newlen;
109 }
110 newbuf = realloc(base->buf, newcap);
111 if (newbuf == NULL) {
112 return 0;
113 }
114
115 base->buf = newbuf;
116 base->cap = newcap;
117 }
118
119 if (out) {
120 *out = base->buf + base->len;
121 }
122 base->len = newlen;
123 return 1;
124}
125
126static int cbb_buffer_add_u(struct cbb_buffer_st *base, uint32_t v,
127 size_t len_len) {
128 uint8_t *buf;
129 size_t i;
130
131 if (len_len == 0) {
132 return 1;
133 }
134 if (!cbb_buffer_add(base, &buf, len_len)) {
135 return 0;
136 }
137
138 for (i = len_len - 1; i < len_len; i--) {
139 buf[i] = v;
140 v >>= 8;
141 }
142 return 1;
143}
144
145int CBB_finish(CBB *cbb, uint8_t **out_data, size_t *out_len) {
146 if (!cbb->is_top_level) {
147 return 0;
148 }
149
150 if (!CBB_flush(cbb)) {
151 return 0;
152 }
153
154 if (cbb->base->can_resize && (out_data == NULL || out_len == NULL)) {
155 /* |out_data| and |out_len| can only be NULL if the CBB is fixed. */
156 return 0;
157 }
158
159 if (out_data != NULL) {
160 *out_data = cbb->base->buf;
161 }
162 if (out_len != NULL) {
163 *out_len = cbb->base->len;
164 }
165 cbb->base->buf = NULL;
166 CBB_cleanup(cbb);
167 return 1;
168}
169
170/* CBB_flush recurses and then writes out any pending length prefix. The
171 * current length of the underlying base is taken to be the length of the
172 * length-prefixed data. */
173int CBB_flush(CBB *cbb) {
174 size_t child_start, i, len;
175
176 if (cbb->base == NULL) {
177 return 0;
178 }
179
180 if (cbb->child == NULL || cbb->pending_len_len == 0) {
181 return 1;
182 }
183
184 child_start = cbb->offset + cbb->pending_len_len;
185
186 if (!CBB_flush(cbb->child) ||
187 child_start < cbb->offset ||
188 cbb->base->len < child_start) {
189 return 0;
190 }
191
192 len = cbb->base->len - child_start;
193
194 if (cbb->pending_is_asn1) {
195 /* For ASN.1 we assume that we'll only need a single byte for the length.
196 * If that turned out to be incorrect, we have to move the contents along
197 * in order to make space. */
198 size_t len_len;
199 uint8_t initial_length_byte;
200
201 assert (cbb->pending_len_len == 1);
202
203 if (len > 0xfffffffe) {
204 /* Too large. */
205 return 0;
206 } else if (len > 0xffffff) {
207 len_len = 5;
208 initial_length_byte = 0x80 | 4;
209 } else if (len > 0xffff) {
210 len_len = 4;
211 initial_length_byte = 0x80 | 3;
212 } else if (len > 0xff) {
213 len_len = 3;
214 initial_length_byte = 0x80 | 2;
215 } else if (len > 0x7f) {
216 len_len = 2;
217 initial_length_byte = 0x80 | 1;
218 } else {
219 len_len = 1;
220 initial_length_byte = len;
221 len = 0;
222 }
223
224 if (len_len != 1) {
225 /* We need to move the contents along in order to make space. */
226 size_t extra_bytes = len_len - 1;
227 if (!cbb_buffer_add(cbb->base, NULL, extra_bytes)) {
228 return 0;
229 }
230 memmove(cbb->base->buf + child_start + extra_bytes,
231 cbb->base->buf + child_start, len);
232 }
233 cbb->base->buf[cbb->offset++] = initial_length_byte;
234 cbb->pending_len_len = len_len - 1;
235 }
236
237 for (i = cbb->pending_len_len - 1; i < cbb->pending_len_len; i--) {
238 cbb->base->buf[cbb->offset + i] = len;
239 len >>= 8;
240 }
241 if (len != 0) {
242 return 0;
243 }
244
245 cbb->child->base = NULL;
246 cbb->child = NULL;
247 cbb->pending_len_len = 0;
248 cbb->pending_is_asn1 = 0;
249 cbb->offset = 0;
250
251 return 1;
252}
253
254
255static int cbb_add_length_prefixed(CBB *cbb, CBB *out_contents,
256 size_t len_len) {
257 uint8_t *prefix_bytes;
258
259 if (!CBB_flush(cbb)) {
260 return 0;
261 }
262
263 cbb->offset = cbb->base->len;
264 if (!cbb_buffer_add(cbb->base, &prefix_bytes, len_len)) {
265 return 0;
266 }
267
268 memset(prefix_bytes, 0, len_len);
269 memset(out_contents, 0, sizeof(CBB));
270 out_contents->base = cbb->base;
271 cbb->child = out_contents;
272 cbb->pending_len_len = len_len;
273 cbb->pending_is_asn1 = 0;
274
275 return 1;
276}
277
278int CBB_add_u8_length_prefixed(CBB *cbb, CBB *out_contents) {
279 return cbb_add_length_prefixed(cbb, out_contents, 1);
280}
281
282int CBB_add_u16_length_prefixed(CBB *cbb, CBB *out_contents) {
283 return cbb_add_length_prefixed(cbb, out_contents, 2);
284}
285
286int CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents) {
287 return cbb_add_length_prefixed(cbb, out_contents, 3);
288}
289
290int CBB_add_asn1(CBB *cbb, CBB *out_contents, uint8_t tag) {
291 if (!CBB_flush(cbb) ||
292 !CBB_add_u8(cbb, tag)) {
293 return 0;
294 }
295
296 cbb->offset = cbb->base->len;
297 if (!CBB_add_u8(cbb, 0)) {
298 return 0;
299 }
300
301 memset(out_contents, 0, sizeof(CBB));
302 out_contents->base = cbb->base;
303 cbb->child = out_contents;
304 cbb->pending_len_len = 1;
305 cbb->pending_is_asn1 = 1;
306
307 return 1;
308}
309
310int CBB_add_bytes(CBB *cbb, const uint8_t *data, size_t len) {
311 uint8_t *dest;
312
313 if (!CBB_flush(cbb) ||
314 !cbb_buffer_add(cbb->base, &dest, len)) {
315 return 0;
316 }
317 memcpy(dest, data, len);
318 return 1;
319}
320
321int CBB_add_space(CBB *cbb, uint8_t **out_data, size_t len) {
322 if (!CBB_flush(cbb) ||
323 !cbb_buffer_add(cbb->base, out_data, len)) {
324 return 0;
325 }
326 return 1;
327}
328
329int CBB_add_u8(CBB *cbb, uint8_t value) {
330 if (!CBB_flush(cbb)) {
331 return 0;
332 }
333
334 return cbb_buffer_add_u(cbb->base, value, 1);
335}
336
337int CBB_add_u16(CBB *cbb, uint16_t value) {
338 if (!CBB_flush(cbb)) {
339 return 0;
340 }
341
342 return cbb_buffer_add_u(cbb->base, value, 2);
343}
344
345int CBB_add_u24(CBB *cbb, uint32_t value) {
346 if (!CBB_flush(cbb)) {
347 return 0;
348 }
349
350 return cbb_buffer_add_u(cbb->base, value, 3);
351}
352
353int CBB_add_asn1_uint64(CBB *cbb, uint64_t value) {
354 CBB child;
355 size_t i;
356 int started = 0;
357
358 if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER)) {
359 return 0;
360 }
361
362 for (i = 0; i < 8; i++) {
363 uint8_t byte = (value >> 8*(7-i)) & 0xff;
364 if (!started) {
365 if (byte == 0) {
366 /* Don't encode leading zeros. */
367 continue;
368 }
369 /* If the high bit is set, add a padding byte to make it
370 * unsigned. */
371 if ((byte & 0x80) && !CBB_add_u8(&child, 0)) {
372 return 0;
373 }
374 started = 1;
375 }
376 if (!CBB_add_u8(&child, byte)) {
377 return 0;
378 }
379 }
380
381 /* 0 is encoded as a single 0, not the empty string. */
382 if (!started && !CBB_add_u8(&child, 0)) {
383 return 0;
384 }
385
386 return CBB_flush(cbb);
387}
diff --git a/src/lib/libssl/bs_cbs.c b/src/lib/libssl/bs_cbs.c
new file mode 100644
index 0000000000..7edfe65288
--- /dev/null
+++ b/src/lib/libssl/bs_cbs.c
@@ -0,0 +1,390 @@
1/* $OpenBSD: bs_cbs.c,v 1.1 2015/02/06 09:36:16 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#include <openssl/buffer.h>
23#include <openssl/crypto.h>
24
25#include "bytestring.h"
26
27void CBS_init(CBS *cbs, const uint8_t *data, size_t len) {
28 cbs->data = data;
29 cbs->len = len;
30}
31
32static int cbs_get(CBS *cbs, const uint8_t **p, size_t n) {
33 if (cbs->len < n) {
34 return 0;
35 }
36
37 *p = cbs->data;
38 cbs->data += n;
39 cbs->len -= n;
40 return 1;
41}
42
43int CBS_skip(CBS *cbs, size_t len) {
44 const uint8_t *dummy;
45 return cbs_get(cbs, &dummy, len);
46}
47
48const uint8_t *CBS_data(const CBS *cbs) {
49 return cbs->data;
50}
51
52size_t CBS_len(const CBS *cbs) {
53 return cbs->len;
54}
55
56int CBS_stow(const CBS *cbs, uint8_t **out_ptr, size_t *out_len) {
57 if (*out_ptr != NULL) {
58 free(*out_ptr);
59 *out_ptr = NULL;
60 }
61 *out_len = 0;
62
63 if (cbs->len == 0) {
64 return 1;
65 }
66 *out_ptr = BUF_memdup(cbs->data, cbs->len);
67 if (*out_ptr == NULL) {
68 return 0;
69 }
70 *out_len = cbs->len;
71 return 1;
72}
73
74int CBS_strdup(const CBS *cbs, char **out_ptr) {
75 if (*out_ptr != NULL) {
76 free(*out_ptr);
77 }
78 *out_ptr = strndup((const char*)cbs->data, cbs->len);
79 return (*out_ptr != NULL);
80}
81
82int CBS_contains_zero_byte(const CBS *cbs) {
83 return memchr(cbs->data, 0, cbs->len) != NULL;
84}
85
86int CBS_mem_equal(const CBS *cbs, const uint8_t *data, size_t len) {
87 if (len != cbs->len)
88 return 0;
89 return CRYPTO_memcmp(cbs->data, data, len) == 0;
90}
91
92static int cbs_get_u(CBS *cbs, uint32_t *out, size_t len) {
93 uint32_t result = 0;
94 size_t i;
95 const uint8_t *data;
96
97 if (!cbs_get(cbs, &data, len)) {
98 return 0;
99 }
100 for (i = 0; i < len; i++) {
101 result <<= 8;
102 result |= data[i];
103 }
104 *out = result;
105 return 1;
106}
107
108int CBS_get_u8(CBS *cbs, uint8_t *out) {
109 const uint8_t *v;
110 if (!cbs_get(cbs, &v, 1)) {
111 return 0;
112 }
113 *out = *v;
114 return 1;
115}
116
117int CBS_get_u16(CBS *cbs, uint16_t *out) {
118 uint32_t v;
119 if (!cbs_get_u(cbs, &v, 2)) {
120 return 0;
121 }
122 *out = v;
123 return 1;
124}
125
126int CBS_get_u24(CBS *cbs, uint32_t *out) {
127 return cbs_get_u(cbs, out, 3);
128}
129
130int CBS_get_u32(CBS *cbs, uint32_t *out) {
131 return cbs_get_u(cbs, out, 4);
132}
133
134int CBS_get_bytes(CBS *cbs, CBS *out, size_t len) {
135 const uint8_t *v;
136 if (!cbs_get(cbs, &v, len)) {
137 return 0;
138 }
139 CBS_init(out, v, len);
140 return 1;
141}
142
143static int cbs_get_length_prefixed(CBS *cbs, CBS *out, size_t len_len) {
144 uint32_t len;
145 if (!cbs_get_u(cbs, &len, len_len)) {
146 return 0;
147 }
148 return CBS_get_bytes(cbs, out, len);
149}
150
151int CBS_get_u8_length_prefixed(CBS *cbs, CBS *out) {
152 return cbs_get_length_prefixed(cbs, out, 1);
153}
154
155int CBS_get_u16_length_prefixed(CBS *cbs, CBS *out) {
156 return cbs_get_length_prefixed(cbs, out, 2);
157}
158
159int CBS_get_u24_length_prefixed(CBS *cbs, CBS *out) {
160 return cbs_get_length_prefixed(cbs, out, 3);
161}
162
163int CBS_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
164 size_t *out_header_len) {
165 uint8_t tag, length_byte;
166 CBS header = *cbs;
167 CBS throwaway;
168
169 if (out == NULL) {
170 out = &throwaway;
171 }
172
173 if (!CBS_get_u8(&header, &tag) ||
174 !CBS_get_u8(&header, &length_byte)) {
175 return 0;
176 }
177
178 if ((tag & 0x1f) == 0x1f) {
179 /* Long form tags are not supported. */
180 return 0;
181 }
182
183 if (out_tag != NULL) {
184 *out_tag = tag;
185 }
186
187 size_t len;
188 if ((length_byte & 0x80) == 0) {
189 /* Short form length. */
190 len = ((size_t) length_byte) + 2;
191 if (out_header_len != NULL) {
192 *out_header_len = 2;
193 }
194 } else {
195 /* Long form length. */
196 const size_t num_bytes = length_byte & 0x7f;
197 uint32_t len32;
198
199 if ((tag & CBS_ASN1_CONSTRUCTED) != 0 && num_bytes == 0) {
200 /* indefinite length */
201 *out_header_len = 2;
202 return CBS_get_bytes(cbs, out, 2);
203 }
204
205 if (num_bytes == 0 || num_bytes > 4) {
206 return 0;
207 }
208 if (!cbs_get_u(&header, &len32, num_bytes)) {
209 return 0;
210 }
211 if (len32 < 128) {
212 /* Length should have used short-form encoding. */
213 return 0;
214 }
215 if ((len32 >> ((num_bytes-1)*8)) == 0) {
216 /* Length should have been at least one byte shorter. */
217 return 0;
218 }
219 len = len32;
220 if (len + 2 + num_bytes < len) {
221 /* Overflow. */
222 return 0;
223 }
224 len += 2 + num_bytes;
225 if (out_header_len != NULL) {
226 *out_header_len = 2 + num_bytes;
227 }
228 }
229
230 return CBS_get_bytes(cbs, out, len);
231}
232
233static int cbs_get_asn1(CBS *cbs, CBS *out, unsigned tag_value,
234 int skip_header) {
235 size_t header_len;
236 unsigned tag;
237 CBS throwaway;
238
239 if (out == NULL) {
240 out = &throwaway;
241 }
242
243 if (!CBS_get_any_asn1_element(cbs, out, &tag, &header_len) ||
244 tag != tag_value ||
245 (header_len > 0 &&
246 /* This ensures that the tag is either zero length or
247 * indefinite-length. */
248 CBS_len(out) == header_len &&
249 CBS_data(out)[header_len - 1] == 0x80)) {
250 return 0;
251 }
252
253 if (skip_header && !CBS_skip(out, header_len)) {
254 assert(0);
255 return 0;
256 }
257
258 return 1;
259}
260
261int CBS_get_asn1(CBS *cbs, CBS *out, unsigned tag_value) {
262 return cbs_get_asn1(cbs, out, tag_value, 1 /* skip header */);
263}
264
265int CBS_get_asn1_element(CBS *cbs, CBS *out, unsigned tag_value) {
266 return cbs_get_asn1(cbs, out, tag_value, 0 /* include header */);
267}
268
269int CBS_peek_asn1_tag(const CBS *cbs, unsigned tag_value) {
270 if (CBS_len(cbs) < 1) {
271 return 0;
272 }
273 return CBS_data(cbs)[0] == tag_value;
274}
275
276int CBS_get_asn1_uint64(CBS *cbs, uint64_t *out) {
277 CBS bytes;
278 const uint8_t *data;
279 size_t i, len;
280
281 if (!CBS_get_asn1(cbs, &bytes, CBS_ASN1_INTEGER)) {
282 return 0;
283 }
284
285 *out = 0;
286 data = CBS_data(&bytes);
287 len = CBS_len(&bytes);
288
289 if (len == 0) {
290 /* An INTEGER is encoded with at least one octet. */
291 return 0;
292 }
293
294 if ((data[0] & 0x80) != 0) {
295 /* negative number */
296 return 0;
297 }
298
299 for (i = 0; i < len; i++) {
300 if ((*out >> 56) != 0) {
301 /* Too large to represent as a uint64_t. */
302 return 0;
303 }
304 *out <<= 8;
305 *out |= data[i];
306 }
307
308 return 1;
309}
310
311int CBS_get_optional_asn1(CBS *cbs, CBS *out, int *out_present, unsigned tag) {
312 if (CBS_peek_asn1_tag(cbs, tag)) {
313 if (!CBS_get_asn1(cbs, out, tag)) {
314 return 0;
315 }
316 *out_present = 1;
317 } else {
318 *out_present = 0;
319 }
320 return 1;
321}
322
323int CBS_get_optional_asn1_octet_string(CBS *cbs, CBS *out, int *out_present,
324 unsigned tag) {
325 CBS child;
326 int present;
327 if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) {
328 return 0;
329 }
330 if (present) {
331 if (!CBS_get_asn1(&child, out, CBS_ASN1_OCTETSTRING) ||
332 CBS_len(&child) != 0) {
333 return 0;
334 }
335 } else {
336 CBS_init(out, NULL, 0);
337 }
338 if (out_present) {
339 *out_present = present;
340 }
341 return 1;
342}
343
344int CBS_get_optional_asn1_uint64(CBS *cbs, uint64_t *out, unsigned tag,
345 uint64_t default_value) {
346 CBS child;
347 int present;
348 if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) {
349 return 0;
350 }
351 if (present) {
352 if (!CBS_get_asn1_uint64(&child, out) ||
353 CBS_len(&child) != 0) {
354 return 0;
355 }
356 } else {
357 *out = default_value;
358 }
359 return 1;
360}
361
362int CBS_get_optional_asn1_bool(CBS *cbs, int *out, unsigned tag,
363 int default_value) {
364 CBS child, child2;
365 int present;
366 if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) {
367 return 0;
368 }
369 if (present) {
370 uint8_t boolean;
371
372 if (!CBS_get_asn1(&child, &child2, CBS_ASN1_BOOLEAN) ||
373 CBS_len(&child2) != 1 ||
374 CBS_len(&child) != 0) {
375 return 0;
376 }
377
378 boolean = CBS_data(&child2)[0];
379 if (boolean == 0) {
380 *out = 0;
381 } else if (boolean == 0xff) {
382 *out = 1;
383 } else {
384 return 0;
385 }
386 } else {
387 *out = default_value;
388 }
389 return 1;
390}
diff --git a/src/lib/libssl/bytestring.h b/src/lib/libssl/bytestring.h
new file mode 100644
index 0000000000..3c4e8eaaf3
--- /dev/null
+++ b/src/lib/libssl/bytestring.h
@@ -0,0 +1,346 @@
1/* $OpenBSD: bytestring.h,v 1.1 2015/02/06 09:36:16 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#ifndef OPENSSL_HEADER_BYTESTRING_H
18#define OPENSSL_HEADER_BYTESTRING_H
19
20#if defined(__cplusplus)
21extern "C" {
22#endif
23
24#include <sys/types.h>
25#include <stdint.h>
26
27#include <openssl/opensslconf.h>
28
29/* Bytestrings are used for parsing and building TLS and ASN.1 messages.
30 *
31 * A "CBS" (CRYPTO ByteString) represents a string of bytes in memory and
32 * provides utility functions for safely parsing length-prefixed structures
33 * like TLS and ASN.1 from it.
34 *
35 * A "CBB" (CRYPTO ByteBuilder) is a memory buffer that grows as needed and
36 * provides utility functions for building length-prefixed messages. */
37
38
39/* CRYPTO ByteString */
40
41typedef struct cbs_st {
42 const uint8_t *data;
43 size_t len;
44} CBS;
45
46/* CBS_init sets |cbs| to point to |data|. It does not take ownership of
47 * |data|. */
48void CBS_init(CBS *cbs, const uint8_t *data, size_t len);
49
50/* CBS_skip advances |cbs| by |len| bytes. It returns one on success and zero
51 * otherwise. */
52int CBS_skip(CBS *cbs, size_t len);
53
54/* CBS_data returns a pointer to the contains of |cbs|. */
55const uint8_t *CBS_data(const CBS *cbs);
56
57/* CBS_len returns the number of bytes remaining in |cbs|. */
58size_t CBS_len(const CBS *cbs);
59
60/* CBS_stow copies the current contents of |cbs| into |*out_ptr| and
61 * |*out_len|. If |*out_ptr| is not NULL, the contents are freed with
62 * OPENSSL_free. It returns one on success and zero on allocation failure. On
63 * success, |*out_ptr| should be freed with OPENSSL_free. If |cbs| is empty,
64 * |*out_ptr| will be NULL. */
65int CBS_stow(const CBS *cbs, uint8_t **out_ptr, size_t *out_len);
66
67/* CBS_strdup copies the current contents of |cbs| into |*out_ptr| as a
68 * NUL-terminated C string. If |*out_ptr| is not NULL, the contents are freed
69 * with OPENSSL_free. It returns one on success and zero on allocation
70 * failure. On success, |*out_ptr| should be freed with OPENSSL_free.
71 *
72 * NOTE: If |cbs| contains NUL bytes, the string will be truncated. Call
73 * |CBS_contains_zero_byte(cbs)| to check for NUL bytes. */
74int CBS_strdup(const CBS *cbs, char **out_ptr);
75
76/* CBS_contains_zero_byte returns one if the current contents of |cbs| contains
77 * a NUL byte and zero otherwise. */
78int CBS_contains_zero_byte(const CBS *cbs);
79
80/* CBS_mem_equal compares the current contents of |cbs| with the |len| bytes
81 * starting at |data|. If they're equal, it returns one, otherwise zero. If the
82 * lengths match, it uses a constant-time comparison. */
83int CBS_mem_equal(const CBS *cbs, const uint8_t *data,
84 size_t len);
85
86/* CBS_get_u8 sets |*out| to the next uint8_t from |cbs| and advances |cbs|. It
87 * returns one on success and zero on error. */
88int CBS_get_u8(CBS *cbs, uint8_t *out);
89
90/* CBS_get_u16 sets |*out| to the next, big-endian uint16_t from |cbs| and
91 * advances |cbs|. It returns one on success and zero on error. */
92int CBS_get_u16(CBS *cbs, uint16_t *out);
93
94/* CBS_get_u24 sets |*out| to the next, big-endian 24-bit value from |cbs| and
95 * advances |cbs|. It returns one on success and zero on error. */
96int CBS_get_u24(CBS *cbs, uint32_t *out);
97
98/* CBS_get_u32 sets |*out| to the next, big-endian uint32_t value from |cbs|
99 * and advances |cbs|. It returns one on success and zero on error. */
100int CBS_get_u32(CBS *cbs, uint32_t *out);
101
102/* CBS_get_bytes sets |*out| to the next |len| bytes from |cbs| and advances
103 * |cbs|. It returns one on success and zero on error. */
104int CBS_get_bytes(CBS *cbs, CBS *out, size_t len);
105
106/* CBS_get_u8_length_prefixed sets |*out| to the contents of an 8-bit,
107 * length-prefixed value from |cbs| and advances |cbs| over it. It returns one
108 * on success and zero on error. */
109int CBS_get_u8_length_prefixed(CBS *cbs, CBS *out);
110
111/* CBS_get_u16_length_prefixed sets |*out| to the contents of a 16-bit,
112 * big-endian, length-prefixed value from |cbs| and advances |cbs| over it. It
113 * returns one on success and zero on error. */
114int CBS_get_u16_length_prefixed(CBS *cbs, CBS *out);
115
116/* CBS_get_u24_length_prefixed sets |*out| to the contents of a 24-bit,
117 * big-endian, length-prefixed value from |cbs| and advances |cbs| over it. It
118 * returns one on success and zero on error. */
119int CBS_get_u24_length_prefixed(CBS *cbs, CBS *out);
120
121
122/* Parsing ASN.1 */
123
124#define CBS_ASN1_BOOLEAN 0x1
125#define CBS_ASN1_INTEGER 0x2
126#define CBS_ASN1_BITSTRING 0x3
127#define CBS_ASN1_OCTETSTRING 0x4
128#define CBS_ASN1_OBJECT 0x6
129#define CBS_ASN1_ENUMERATED 0xa
130#define CBS_ASN1_SEQUENCE (0x10 | CBS_ASN1_CONSTRUCTED)
131#define CBS_ASN1_SET (0x11 | CBS_ASN1_CONSTRUCTED)
132
133#define CBS_ASN1_CONSTRUCTED 0x20
134#define CBS_ASN1_CONTEXT_SPECIFIC 0x80
135
136/* CBS_get_asn1 sets |*out| to the contents of DER-encoded, ASN.1 element (not
137 * including tag and length bytes) and advances |cbs| over it. The ASN.1
138 * element must match |tag_value|. It returns one on success and zero
139 * on error.
140 *
141 * Tag numbers greater than 31 are not supported. */
142int CBS_get_asn1(CBS *cbs, CBS *out, unsigned tag_value);
143
144/* CBS_get_asn1_element acts like |CBS_get_asn1| but |out| will include the
145 * ASN.1 header bytes too. */
146int CBS_get_asn1_element(CBS *cbs, CBS *out, unsigned tag_value);
147
148/* CBS_peek_asn1_tag looks ahead at the next ASN.1 tag and returns one
149 * if the next ASN.1 element on |cbs| would have tag |tag_value|. If
150 * |cbs| is empty or the tag does not match, it returns zero. Note: if
151 * it returns one, CBS_get_asn1 may still fail if the rest of the
152 * element is malformed. */
153int CBS_peek_asn1_tag(const CBS *cbs, unsigned tag_value);
154
155/* CBS_get_any_asn1_element sets |*out| to contain the next ASN.1 element from
156 * |*cbs| (including header bytes) and advances |*cbs|. It sets |*out_tag| to
157 * the tag number and |*out_header_len| to the length of the ASN.1 header. If
158 * the element has indefinite length then |*out| will only contain the
159 * header. Each of |out|, |out_tag|, and |out_header_len| may be NULL to ignore
160 * the value.
161 *
162 * Tag numbers greater than 31 are not supported. */
163int CBS_get_any_asn1_element(CBS *cbs, CBS *out,
164 unsigned *out_tag,
165 size_t *out_header_len);
166
167/* CBS_get_asn1_uint64 gets an ASN.1 INTEGER from |cbs| using |CBS_get_asn1|
168 * and sets |*out| to its value. It returns one on success and zero on error,
169 * where error includes the integer being negative, or too large to represent
170 * in 64 bits. */
171int CBS_get_asn1_uint64(CBS *cbs, uint64_t *out);
172
173/* CBS_get_optional_asn1 gets an optional explicitly-tagged element
174 * from |cbs| tagged with |tag| and sets |*out| to its contents. If
175 * present, it sets |*out_present| to one, otherwise zero. It returns
176 * one on success, whether or not the element was present, and zero on
177 * decode failure. */
178int CBS_get_optional_asn1(CBS *cbs, CBS *out, int *out_present,
179 unsigned tag);
180
181/* CBS_get_optional_asn1_octet_string gets an optional
182 * explicitly-tagged OCTET STRING from |cbs|. If present, it sets
183 * |*out| to the string and |*out_present| to one. Otherwise, it sets
184 * |*out| to empty and |*out_present| to zero. |out_present| may be
185 * NULL. It returns one on success, whether or not the element was
186 * present, and zero on decode failure. */
187int CBS_get_optional_asn1_octet_string(CBS *cbs, CBS *out,
188 int *out_present,
189 unsigned tag);
190
191/* CBS_get_optional_asn1_uint64 gets an optional explicitly-tagged
192 * INTEGER from |cbs|. If present, it sets |*out| to the
193 * value. Otherwise, it sets |*out| to |default_value|. It returns one
194 * on success, whether or not the element was present, and zero on
195 * decode failure. */
196int CBS_get_optional_asn1_uint64(CBS *cbs, uint64_t *out,
197 unsigned tag,
198 uint64_t default_value);
199
200/* CBS_get_optional_asn1_bool gets an optional, explicitly-tagged BOOLEAN from
201 * |cbs|. If present, it sets |*out| to either zero or one, based on the
202 * boolean. Otherwise, it sets |*out| to |default_value|. It returns one on
203 * success, whether or not the element was present, and zero on decode
204 * failure. */
205int CBS_get_optional_asn1_bool(CBS *cbs, int *out, unsigned tag,
206 int default_value);
207
208
209/* CRYPTO ByteBuilder.
210 *
211 * |CBB| objects allow one to build length-prefixed serialisations. A |CBB|
212 * object is associated with a buffer and new buffers are created with
213 * |CBB_init|. Several |CBB| objects can point at the same buffer when a
214 * length-prefix is pending, however only a single |CBB| can be 'current' at
215 * any one time. For example, if one calls |CBB_add_u8_length_prefixed| then
216 * the new |CBB| points at the same buffer as the original. But if the original
217 * |CBB| is used then the length prefix is written out and the new |CBB| must
218 * not be used again.
219 *
220 * If one needs to force a length prefix to be written out because a |CBB| is
221 * going out of scope, use |CBB_flush|. */
222
223struct cbb_buffer_st {
224 uint8_t *buf;
225 size_t len; /* The number of valid bytes. */
226 size_t cap; /* The size of buf. */
227 char can_resize; /* One iff |buf| is owned by this object. If not then |buf|
228 cannot be resized. */
229};
230
231typedef struct cbb_st {
232 struct cbb_buffer_st *base;
233 /* offset is the offset from the start of |base->buf| to the position of any
234 * pending length-prefix. */
235 size_t offset;
236 /* child points to a child CBB if a length-prefix is pending. */
237 struct cbb_st *child;
238 /* pending_len_len contains the number of bytes in a pending length-prefix,
239 * or zero if no length-prefix is pending. */
240 uint8_t pending_len_len;
241 char pending_is_asn1;
242 /* is_top_level is true iff this is a top-level |CBB| (as opposed to a child
243 * |CBB|). Top-level objects are valid arguments for |CBB_finish|. */
244 char is_top_level;
245} CBB;
246
247/* CBB_init initialises |cbb| with |initial_capacity|. Since a |CBB| grows as
248 * needed, the |initial_capacity| is just a hint. It returns one on success or
249 * zero on error. */
250int CBB_init(CBB *cbb, size_t initial_capacity);
251
252/* CBB_init_fixed initialises |cbb| to write to |len| bytes at |buf|. Since
253 * |buf| cannot grow, trying to write more than |len| bytes will cause CBB
254 * functions to fail. It returns one on success or zero on error. */
255int CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len);
256
257/* CBB_cleanup frees all resources owned by |cbb| and other |CBB| objects
258 * writing to the same buffer. This should be used in an error case where a
259 * serialisation is abandoned. */
260void CBB_cleanup(CBB *cbb);
261
262/* CBB_finish completes any pending length prefix and sets |*out_data| to a
263 * malloced buffer and |*out_len| to the length of that buffer. The caller
264 * takes ownership of the buffer and, unless the buffer was fixed with
265 * |CBB_init_fixed|, must call |OPENSSL_free| when done.
266 *
267 * It can only be called on a "top level" |CBB|, i.e. one initialised with
268 * |CBB_init| or |CBB_init_fixed|. It returns one on success and zero on
269 * error. */
270int CBB_finish(CBB *cbb, uint8_t **out_data, size_t *out_len);
271
272/* CBB_flush causes any pending length prefixes to be written out and any child
273 * |CBB| objects of |cbb| to be invalidated. It returns one on success or zero
274 * on error. */
275int CBB_flush(CBB *cbb);
276
277/* CBB_add_u8_length_prefixed sets |*out_contents| to a new child of |cbb|. The
278 * data written to |*out_contents| will be prefixed in |cbb| with an 8-bit
279 * length. It returns one on success or zero on error. */
280int CBB_add_u8_length_prefixed(CBB *cbb, CBB *out_contents);
281
282/* CBB_add_u16_length_prefixed sets |*out_contents| to a new child of |cbb|.
283 * The data written to |*out_contents| will be prefixed in |cbb| with a 16-bit,
284 * big-endian length. It returns one on success or zero on error. */
285int CBB_add_u16_length_prefixed(CBB *cbb, CBB *out_contents);
286
287/* CBB_add_u24_length_prefixed sets |*out_contents| to a new child of |cbb|.
288 * The data written to |*out_contents| will be prefixed in |cbb| with a 24-bit,
289 * big-endian length. It returns one on success or zero on error. */
290int CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents);
291
292/* CBB_add_asn sets |*out_contents| to a |CBB| into which the contents of an
293 * ASN.1 object can be written. The |tag| argument will be used as the tag for
294 * the object. It returns one on success or zero on error. */
295int CBB_add_asn1(CBB *cbb, CBB *out_contents, uint8_t tag);
296
297/* CBB_add_bytes appends |len| bytes from |data| to |cbb|. It returns one on
298 * success and zero otherwise. */
299int CBB_add_bytes(CBB *cbb, const uint8_t *data, size_t len);
300
301/* CBB_add_space appends |len| bytes to |cbb| and sets |*out_data| to point to
302 * the beginning of that space. The caller must then write |len| bytes of
303 * actual contents to |*out_data|. It returns one on success and zero
304 * otherwise. */
305int CBB_add_space(CBB *cbb, uint8_t **out_data, size_t len);
306
307/* CBB_add_u8 appends an 8-bit number from |value| to |cbb|. It returns one on
308 * success and zero otherwise. */
309int CBB_add_u8(CBB *cbb, uint8_t value);
310
311/* CBB_add_u8 appends a 16-bit, big-endian number from |value| to |cbb|. It
312 * returns one on success and zero otherwise. */
313int CBB_add_u16(CBB *cbb, uint16_t value);
314
315/* CBB_add_u24 appends a 24-bit, big-endian number from |value| to |cbb|. It
316 * returns one on success and zero otherwise. */
317int CBB_add_u24(CBB *cbb, uint32_t value);
318
319/* CBB_add_asn1_uint64 writes an ASN.1 INTEGER into |cbb| using |CBB_add_asn1|
320 * and writes |value| in its contents. It returns one on success and zero on
321 * error. */
322int CBB_add_asn1_uint64(CBB *cbb, uint64_t value);
323
324#ifdef LIBRESSL_INTERNAL
325/* CBS_asn1_ber_to_der reads an ASN.1 structure from |in|. If it finds
326 * indefinite-length elements then it attempts to convert the BER data to DER
327 * and sets |*out| and |*out_length| to describe a malloced buffer containing
328 * the DER data. Additionally, |*in| will be advanced over the ASN.1 data.
329 *
330 * If it doesn't find any indefinite-length elements then it sets |*out| to
331 * NULL and |*in| is unmodified.
332 *
333 * A sufficiently complex ASN.1 structure will break this function because it's
334 * not possible to generically convert BER to DER without knowledge of the
335 * structure itself. However, this sufficies to handle the PKCS#7 and #12 output
336 * from NSS.
337 *
338 * It returns one on success and zero otherwise. */
339int CBS_asn1_ber_to_der(CBS *in, uint8_t **out, size_t *out_len);
340#endif /* LIBRESSL_INTERNAL */
341
342#if defined(__cplusplus)
343} /* extern C */
344#endif
345
346#endif /* OPENSSL_HEADER_BYTESTRING_H */
diff --git a/src/lib/libssl/src/ssl/bs_ber.c b/src/lib/libssl/src/ssl/bs_ber.c
new file mode 100644
index 0000000000..b94b63e37e
--- /dev/null
+++ b/src/lib/libssl/src/ssl/bs_ber.c
@@ -0,0 +1,220 @@
1/* $OpenBSD: bs_ber.c,v 1.1 2015/02/06 09:36:16 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 <string.h>
18
19#include <openssl/opensslconf.h>
20
21#include "bytestring.h"
22
23/* kMaxDepth is a just a sanity limit. The code should be such that the length
24 * of the input being processes always decreases. None the less, a very large
25 * input could otherwise cause the stack to overflow. */
26static const unsigned kMaxDepth = 2048;
27
28/* cbs_find_ber walks an ASN.1 structure in |orig_in| and sets |*ber_found|
29 * depending on whether an indefinite length element was found. The value of
30 * |in| is not changed. It returns one on success (i.e. |*ber_found| was set)
31 * and zero on error. */
32static int cbs_find_ber(CBS *orig_in, char *ber_found, unsigned depth) {
33 CBS in;
34
35 if (depth > kMaxDepth) {
36 return 0;
37 }
38
39 CBS_init(&in, CBS_data(orig_in), CBS_len(orig_in));
40 *ber_found = 0;
41
42 while (CBS_len(&in) > 0) {
43 CBS contents;
44 unsigned tag;
45 size_t header_len;
46
47 if (!CBS_get_any_asn1_element(&in, &contents, &tag, &header_len)) {
48 return 0;
49 }
50 if (CBS_len(&contents) == header_len &&
51 header_len > 0 &&
52 CBS_data(&contents)[header_len-1] == 0x80) {
53 *ber_found = 1;
54 return 1;
55 }
56 if (tag & CBS_ASN1_CONSTRUCTED) {
57 if (!CBS_skip(&contents, header_len) ||
58 !cbs_find_ber(&contents, ber_found, depth + 1)) {
59 return 0;
60 }
61 }
62 }
63
64 return 1;
65}
66
67/* is_primitive_type returns true if |tag| likely a primitive type. Normally
68 * one can just test the "constructed" bit in the tag but, in BER, even
69 * primitive tags can have the constructed bit if they have indefinite
70 * length. */
71static char is_primitive_type(unsigned tag) {
72 return (tag & 0xc0) == 0 &&
73 (tag & 0x1f) != (CBS_ASN1_SEQUENCE & 0x1f) &&
74 (tag & 0x1f) != (CBS_ASN1_SET & 0x1f);
75}
76
77/* is_eoc returns true if |header_len| and |contents|, as returned by
78 * |CBS_get_any_asn1_element|, indicate an "end of contents" (EOC) value. */
79static char is_eoc(size_t header_len, CBS *contents) {
80 return header_len == 2 && CBS_len(contents) == 2 &&
81 memcmp(CBS_data(contents), "\x00\x00", 2) == 0;
82}
83
84/* cbs_convert_ber reads BER data from |in| and writes DER data to |out|. If
85 * |squash_header| is set then the top-level of elements from |in| will not
86 * have their headers written. This is used when concatenating the fragments of
87 * an indefinite length, primitive value. If |looking_for_eoc| is set then any
88 * EOC elements found will cause the function to return after consuming it.
89 * It returns one on success and zero on error. */
90static int cbs_convert_ber(CBS *in, CBB *out, char squash_header,
91 char looking_for_eoc, unsigned depth) {
92 if (depth > kMaxDepth) {
93 return 0;
94 }
95
96 while (CBS_len(in) > 0) {
97 CBS contents;
98 unsigned tag;
99 size_t header_len;
100 CBB *out_contents, out_contents_storage;
101
102 if (!CBS_get_any_asn1_element(in, &contents, &tag, &header_len)) {
103 return 0;
104 }
105 out_contents = out;
106
107 if (CBS_len(&contents) == header_len) {
108 if (is_eoc(header_len, &contents)) {
109 return looking_for_eoc;
110 }
111
112 if (header_len > 0 && CBS_data(&contents)[header_len - 1] == 0x80) {
113 /* This is an indefinite length element. If it's a SEQUENCE or SET then
114 * we just need to write the out the contents as normal, but with a
115 * concrete length prefix.
116 *
117 * If it's a something else then the contents will be a series of BER
118 * elements of the same type which need to be concatenated. */
119 const char context_specific = (tag & 0xc0) == 0x80;
120 char squash_child_headers = is_primitive_type(tag);
121
122 /* This is a hack, but it sufficies to handle NSS's output. If we find
123 * an indefinite length, context-specific tag with a definite, primtive
124 * tag inside it, then we assume that the context-specific tag is
125 * implicit and the tags within are fragments of a primitive type that
126 * need to be concatenated. */
127 if (context_specific && (tag & CBS_ASN1_CONSTRUCTED)) {
128 CBS in_copy, inner_contents;
129 unsigned inner_tag;
130 size_t inner_header_len;
131
132 CBS_init(&in_copy, CBS_data(in), CBS_len(in));
133 if (!CBS_get_any_asn1_element(&in_copy, &inner_contents, &inner_tag,
134 &inner_header_len)) {
135 return 0;
136 }
137 if (CBS_len(&inner_contents) > inner_header_len &&
138 is_primitive_type(inner_tag)) {
139 squash_child_headers = 1;
140 }
141 }
142
143 if (!squash_header) {
144 unsigned out_tag = tag;
145 if (squash_child_headers) {
146 out_tag &= ~CBS_ASN1_CONSTRUCTED;
147 }
148 if (!CBB_add_asn1(out, &out_contents_storage, out_tag)) {
149 return 0;
150 }
151 out_contents = &out_contents_storage;
152 }
153
154 if (!cbs_convert_ber(in, out_contents,
155 squash_child_headers,
156 1 /* looking for eoc */, depth + 1)) {
157 return 0;
158 }
159 if (out_contents != out && !CBB_flush(out)) {
160 return 0;
161 }
162 continue;
163 }
164 }
165
166 if (!squash_header) {
167 if (!CBB_add_asn1(out, &out_contents_storage, tag)) {
168 return 0;
169 }
170 out_contents = &out_contents_storage;
171 }
172
173 if (!CBS_skip(&contents, header_len)) {
174 return 0;
175 }
176
177 if (tag & CBS_ASN1_CONSTRUCTED) {
178 if (!cbs_convert_ber(&contents, out_contents, 0 /* don't squash header */,
179 0 /* not looking for eoc */, depth + 1)) {
180 return 0;
181 }
182 } else {
183 if (!CBB_add_bytes(out_contents, CBS_data(&contents),
184 CBS_len(&contents))) {
185 return 0;
186 }
187 }
188
189 if (out_contents != out && !CBB_flush(out)) {
190 return 0;
191 }
192 }
193
194 return looking_for_eoc == 0;
195}
196
197int CBS_asn1_ber_to_der(CBS *in, uint8_t **out, size_t *out_len) {
198 CBB cbb;
199
200 /* First, do a quick walk to find any indefinite-length elements. Most of the
201 * time we hope that there aren't any and thus we can quickly return. */
202 char conversion_needed;
203 if (!cbs_find_ber(in, &conversion_needed, 0)) {
204 return 0;
205 }
206
207 if (!conversion_needed) {
208 *out = NULL;
209 *out_len = 0;
210 return 1;
211 }
212
213 CBB_init(&cbb, CBS_len(in));
214 if (!cbs_convert_ber(in, &cbb, 0, 0, 0)) {
215 CBB_cleanup(&cbb);
216 return 0;
217 }
218
219 return CBB_finish(&cbb, out, out_len);
220}
diff --git a/src/lib/libssl/src/ssl/bs_cbb.c b/src/lib/libssl/src/ssl/bs_cbb.c
new file mode 100644
index 0000000000..668231c1c7
--- /dev/null
+++ b/src/lib/libssl/src/ssl/bs_cbb.c
@@ -0,0 +1,387 @@
1/* $OpenBSD: bs_cbb.c,v 1.1 2015/02/06 09:36:16 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 cbb_init(CBB *cbb, uint8_t *buf, size_t cap) {
26 struct cbb_buffer_st *base;
27
28 base = malloc(sizeof(struct cbb_buffer_st));
29 if (base == NULL) {
30 free(buf);
31 return 0;
32 }
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 CBB_init(CBB *cbb, size_t initial_capacity) {
46 uint8_t *buf;
47
48 buf = malloc(initial_capacity);
49 if (initial_capacity > 0 && buf == NULL) {
50 return 0;
51 }
52
53 return cbb_init(cbb, buf, initial_capacity);
54}
55
56int CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len) {
57 if (!cbb_init(cbb, buf, len)) {
58 return 0;
59 }
60
61 cbb->base->can_resize = 0;
62 return 1;
63}
64
65void CBB_cleanup(CBB *cbb) {
66 if (cbb->base) {
67 if (cbb->base->buf && cbb->base->can_resize) {
68 free(cbb->base->buf);
69 }
70 free(cbb->base);
71 }
72 cbb->base = NULL;
73}
74
75static int cbb_buffer_add(struct cbb_buffer_st *base, uint8_t **out,
76 size_t len) {
77 size_t newlen;
78
79 if (base == NULL) {
80 return 0;
81 }
82
83#if 0
84 // XXX Added for boringssl patch testing
85 if (len == 0) {
86 if (out) {
87 *out = NULL;
88 }
89 return 1;
90 }
91#endif
92
93 newlen = base->len + len;
94 if (newlen < base->len) {
95 /* Overflow */
96 return 0;
97 }
98
99 if (newlen > base->cap) {
100 size_t newcap = base->cap * 2;
101 uint8_t *newbuf;
102
103 if (!base->can_resize) {
104 return 0;
105 }
106
107 if (newcap < base->cap || newcap < newlen) {
108 newcap = newlen;
109 }
110 newbuf = realloc(base->buf, newcap);
111 if (newbuf == NULL) {
112 return 0;
113 }
114
115 base->buf = newbuf;
116 base->cap = newcap;
117 }
118
119 if (out) {
120 *out = base->buf + base->len;
121 }
122 base->len = newlen;
123 return 1;
124}
125
126static int cbb_buffer_add_u(struct cbb_buffer_st *base, uint32_t v,
127 size_t len_len) {
128 uint8_t *buf;
129 size_t i;
130
131 if (len_len == 0) {
132 return 1;
133 }
134 if (!cbb_buffer_add(base, &buf, len_len)) {
135 return 0;
136 }
137
138 for (i = len_len - 1; i < len_len; i--) {
139 buf[i] = v;
140 v >>= 8;
141 }
142 return 1;
143}
144
145int CBB_finish(CBB *cbb, uint8_t **out_data, size_t *out_len) {
146 if (!cbb->is_top_level) {
147 return 0;
148 }
149
150 if (!CBB_flush(cbb)) {
151 return 0;
152 }
153
154 if (cbb->base->can_resize && (out_data == NULL || out_len == NULL)) {
155 /* |out_data| and |out_len| can only be NULL if the CBB is fixed. */
156 return 0;
157 }
158
159 if (out_data != NULL) {
160 *out_data = cbb->base->buf;
161 }
162 if (out_len != NULL) {
163 *out_len = cbb->base->len;
164 }
165 cbb->base->buf = NULL;
166 CBB_cleanup(cbb);
167 return 1;
168}
169
170/* CBB_flush recurses and then writes out any pending length prefix. The
171 * current length of the underlying base is taken to be the length of the
172 * length-prefixed data. */
173int CBB_flush(CBB *cbb) {
174 size_t child_start, i, len;
175
176 if (cbb->base == NULL) {
177 return 0;
178 }
179
180 if (cbb->child == NULL || cbb->pending_len_len == 0) {
181 return 1;
182 }
183
184 child_start = cbb->offset + cbb->pending_len_len;
185
186 if (!CBB_flush(cbb->child) ||
187 child_start < cbb->offset ||
188 cbb->base->len < child_start) {
189 return 0;
190 }
191
192 len = cbb->base->len - child_start;
193
194 if (cbb->pending_is_asn1) {
195 /* For ASN.1 we assume that we'll only need a single byte for the length.
196 * If that turned out to be incorrect, we have to move the contents along
197 * in order to make space. */
198 size_t len_len;
199 uint8_t initial_length_byte;
200
201 assert (cbb->pending_len_len == 1);
202
203 if (len > 0xfffffffe) {
204 /* Too large. */
205 return 0;
206 } else if (len > 0xffffff) {
207 len_len = 5;
208 initial_length_byte = 0x80 | 4;
209 } else if (len > 0xffff) {
210 len_len = 4;
211 initial_length_byte = 0x80 | 3;
212 } else if (len > 0xff) {
213 len_len = 3;
214 initial_length_byte = 0x80 | 2;
215 } else if (len > 0x7f) {
216 len_len = 2;
217 initial_length_byte = 0x80 | 1;
218 } else {
219 len_len = 1;
220 initial_length_byte = len;
221 len = 0;
222 }
223
224 if (len_len != 1) {
225 /* We need to move the contents along in order to make space. */
226 size_t extra_bytes = len_len - 1;
227 if (!cbb_buffer_add(cbb->base, NULL, extra_bytes)) {
228 return 0;
229 }
230 memmove(cbb->base->buf + child_start + extra_bytes,
231 cbb->base->buf + child_start, len);
232 }
233 cbb->base->buf[cbb->offset++] = initial_length_byte;
234 cbb->pending_len_len = len_len - 1;
235 }
236
237 for (i = cbb->pending_len_len - 1; i < cbb->pending_len_len; i--) {
238 cbb->base->buf[cbb->offset + i] = len;
239 len >>= 8;
240 }
241 if (len != 0) {
242 return 0;
243 }
244
245 cbb->child->base = NULL;
246 cbb->child = NULL;
247 cbb->pending_len_len = 0;
248 cbb->pending_is_asn1 = 0;
249 cbb->offset = 0;
250
251 return 1;
252}
253
254
255static int cbb_add_length_prefixed(CBB *cbb, CBB *out_contents,
256 size_t len_len) {
257 uint8_t *prefix_bytes;
258
259 if (!CBB_flush(cbb)) {
260 return 0;
261 }
262
263 cbb->offset = cbb->base->len;
264 if (!cbb_buffer_add(cbb->base, &prefix_bytes, len_len)) {
265 return 0;
266 }
267
268 memset(prefix_bytes, 0, len_len);
269 memset(out_contents, 0, sizeof(CBB));
270 out_contents->base = cbb->base;
271 cbb->child = out_contents;
272 cbb->pending_len_len = len_len;
273 cbb->pending_is_asn1 = 0;
274
275 return 1;
276}
277
278int CBB_add_u8_length_prefixed(CBB *cbb, CBB *out_contents) {
279 return cbb_add_length_prefixed(cbb, out_contents, 1);
280}
281
282int CBB_add_u16_length_prefixed(CBB *cbb, CBB *out_contents) {
283 return cbb_add_length_prefixed(cbb, out_contents, 2);
284}
285
286int CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents) {
287 return cbb_add_length_prefixed(cbb, out_contents, 3);
288}
289
290int CBB_add_asn1(CBB *cbb, CBB *out_contents, uint8_t tag) {
291 if (!CBB_flush(cbb) ||
292 !CBB_add_u8(cbb, tag)) {
293 return 0;
294 }
295
296 cbb->offset = cbb->base->len;
297 if (!CBB_add_u8(cbb, 0)) {
298 return 0;
299 }
300
301 memset(out_contents, 0, sizeof(CBB));
302 out_contents->base = cbb->base;
303 cbb->child = out_contents;
304 cbb->pending_len_len = 1;
305 cbb->pending_is_asn1 = 1;
306
307 return 1;
308}
309
310int CBB_add_bytes(CBB *cbb, const uint8_t *data, size_t len) {
311 uint8_t *dest;
312
313 if (!CBB_flush(cbb) ||
314 !cbb_buffer_add(cbb->base, &dest, len)) {
315 return 0;
316 }
317 memcpy(dest, data, len);
318 return 1;
319}
320
321int CBB_add_space(CBB *cbb, uint8_t **out_data, size_t len) {
322 if (!CBB_flush(cbb) ||
323 !cbb_buffer_add(cbb->base, out_data, len)) {
324 return 0;
325 }
326 return 1;
327}
328
329int CBB_add_u8(CBB *cbb, uint8_t value) {
330 if (!CBB_flush(cbb)) {
331 return 0;
332 }
333
334 return cbb_buffer_add_u(cbb->base, value, 1);
335}
336
337int CBB_add_u16(CBB *cbb, uint16_t value) {
338 if (!CBB_flush(cbb)) {
339 return 0;
340 }
341
342 return cbb_buffer_add_u(cbb->base, value, 2);
343}
344
345int CBB_add_u24(CBB *cbb, uint32_t value) {
346 if (!CBB_flush(cbb)) {
347 return 0;
348 }
349
350 return cbb_buffer_add_u(cbb->base, value, 3);
351}
352
353int CBB_add_asn1_uint64(CBB *cbb, uint64_t value) {
354 CBB child;
355 size_t i;
356 int started = 0;
357
358 if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER)) {
359 return 0;
360 }
361
362 for (i = 0; i < 8; i++) {
363 uint8_t byte = (value >> 8*(7-i)) & 0xff;
364 if (!started) {
365 if (byte == 0) {
366 /* Don't encode leading zeros. */
367 continue;
368 }
369 /* If the high bit is set, add a padding byte to make it
370 * unsigned. */
371 if ((byte & 0x80) && !CBB_add_u8(&child, 0)) {
372 return 0;
373 }
374 started = 1;
375 }
376 if (!CBB_add_u8(&child, byte)) {
377 return 0;
378 }
379 }
380
381 /* 0 is encoded as a single 0, not the empty string. */
382 if (!started && !CBB_add_u8(&child, 0)) {
383 return 0;
384 }
385
386 return CBB_flush(cbb);
387}
diff --git a/src/lib/libssl/src/ssl/bs_cbs.c b/src/lib/libssl/src/ssl/bs_cbs.c
new file mode 100644
index 0000000000..7edfe65288
--- /dev/null
+++ b/src/lib/libssl/src/ssl/bs_cbs.c
@@ -0,0 +1,390 @@
1/* $OpenBSD: bs_cbs.c,v 1.1 2015/02/06 09:36:16 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#include <openssl/buffer.h>
23#include <openssl/crypto.h>
24
25#include "bytestring.h"
26
27void CBS_init(CBS *cbs, const uint8_t *data, size_t len) {
28 cbs->data = data;
29 cbs->len = len;
30}
31
32static int cbs_get(CBS *cbs, const uint8_t **p, size_t n) {
33 if (cbs->len < n) {
34 return 0;
35 }
36
37 *p = cbs->data;
38 cbs->data += n;
39 cbs->len -= n;
40 return 1;
41}
42
43int CBS_skip(CBS *cbs, size_t len) {
44 const uint8_t *dummy;
45 return cbs_get(cbs, &dummy, len);
46}
47
48const uint8_t *CBS_data(const CBS *cbs) {
49 return cbs->data;
50}
51
52size_t CBS_len(const CBS *cbs) {
53 return cbs->len;
54}
55
56int CBS_stow(const CBS *cbs, uint8_t **out_ptr, size_t *out_len) {
57 if (*out_ptr != NULL) {
58 free(*out_ptr);
59 *out_ptr = NULL;
60 }
61 *out_len = 0;
62
63 if (cbs->len == 0) {
64 return 1;
65 }
66 *out_ptr = BUF_memdup(cbs->data, cbs->len);
67 if (*out_ptr == NULL) {
68 return 0;
69 }
70 *out_len = cbs->len;
71 return 1;
72}
73
74int CBS_strdup(const CBS *cbs, char **out_ptr) {
75 if (*out_ptr != NULL) {
76 free(*out_ptr);
77 }
78 *out_ptr = strndup((const char*)cbs->data, cbs->len);
79 return (*out_ptr != NULL);
80}
81
82int CBS_contains_zero_byte(const CBS *cbs) {
83 return memchr(cbs->data, 0, cbs->len) != NULL;
84}
85
86int CBS_mem_equal(const CBS *cbs, const uint8_t *data, size_t len) {
87 if (len != cbs->len)
88 return 0;
89 return CRYPTO_memcmp(cbs->data, data, len) == 0;
90}
91
92static int cbs_get_u(CBS *cbs, uint32_t *out, size_t len) {
93 uint32_t result = 0;
94 size_t i;
95 const uint8_t *data;
96
97 if (!cbs_get(cbs, &data, len)) {
98 return 0;
99 }
100 for (i = 0; i < len; i++) {
101 result <<= 8;
102 result |= data[i];
103 }
104 *out = result;
105 return 1;
106}
107
108int CBS_get_u8(CBS *cbs, uint8_t *out) {
109 const uint8_t *v;
110 if (!cbs_get(cbs, &v, 1)) {
111 return 0;
112 }
113 *out = *v;
114 return 1;
115}
116
117int CBS_get_u16(CBS *cbs, uint16_t *out) {
118 uint32_t v;
119 if (!cbs_get_u(cbs, &v, 2)) {
120 return 0;
121 }
122 *out = v;
123 return 1;
124}
125
126int CBS_get_u24(CBS *cbs, uint32_t *out) {
127 return cbs_get_u(cbs, out, 3);
128}
129
130int CBS_get_u32(CBS *cbs, uint32_t *out) {
131 return cbs_get_u(cbs, out, 4);
132}
133
134int CBS_get_bytes(CBS *cbs, CBS *out, size_t len) {
135 const uint8_t *v;
136 if (!cbs_get(cbs, &v, len)) {
137 return 0;
138 }
139 CBS_init(out, v, len);
140 return 1;
141}
142
143static int cbs_get_length_prefixed(CBS *cbs, CBS *out, size_t len_len) {
144 uint32_t len;
145 if (!cbs_get_u(cbs, &len, len_len)) {
146 return 0;
147 }
148 return CBS_get_bytes(cbs, out, len);
149}
150
151int CBS_get_u8_length_prefixed(CBS *cbs, CBS *out) {
152 return cbs_get_length_prefixed(cbs, out, 1);
153}
154
155int CBS_get_u16_length_prefixed(CBS *cbs, CBS *out) {
156 return cbs_get_length_prefixed(cbs, out, 2);
157}
158
159int CBS_get_u24_length_prefixed(CBS *cbs, CBS *out) {
160 return cbs_get_length_prefixed(cbs, out, 3);
161}
162
163int CBS_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
164 size_t *out_header_len) {
165 uint8_t tag, length_byte;
166 CBS header = *cbs;
167 CBS throwaway;
168
169 if (out == NULL) {
170 out = &throwaway;
171 }
172
173 if (!CBS_get_u8(&header, &tag) ||
174 !CBS_get_u8(&header, &length_byte)) {
175 return 0;
176 }
177
178 if ((tag & 0x1f) == 0x1f) {
179 /* Long form tags are not supported. */
180 return 0;
181 }
182
183 if (out_tag != NULL) {
184 *out_tag = tag;
185 }
186
187 size_t len;
188 if ((length_byte & 0x80) == 0) {
189 /* Short form length. */
190 len = ((size_t) length_byte) + 2;
191 if (out_header_len != NULL) {
192 *out_header_len = 2;
193 }
194 } else {
195 /* Long form length. */
196 const size_t num_bytes = length_byte & 0x7f;
197 uint32_t len32;
198
199 if ((tag & CBS_ASN1_CONSTRUCTED) != 0 && num_bytes == 0) {
200 /* indefinite length */
201 *out_header_len = 2;
202 return CBS_get_bytes(cbs, out, 2);
203 }
204
205 if (num_bytes == 0 || num_bytes > 4) {
206 return 0;
207 }
208 if (!cbs_get_u(&header, &len32, num_bytes)) {
209 return 0;
210 }
211 if (len32 < 128) {
212 /* Length should have used short-form encoding. */
213 return 0;
214 }
215 if ((len32 >> ((num_bytes-1)*8)) == 0) {
216 /* Length should have been at least one byte shorter. */
217 return 0;
218 }
219 len = len32;
220 if (len + 2 + num_bytes < len) {
221 /* Overflow. */
222 return 0;
223 }
224 len += 2 + num_bytes;
225 if (out_header_len != NULL) {
226 *out_header_len = 2 + num_bytes;
227 }
228 }
229
230 return CBS_get_bytes(cbs, out, len);
231}
232
233static int cbs_get_asn1(CBS *cbs, CBS *out, unsigned tag_value,
234 int skip_header) {
235 size_t header_len;
236 unsigned tag;
237 CBS throwaway;
238
239 if (out == NULL) {
240 out = &throwaway;
241 }
242
243 if (!CBS_get_any_asn1_element(cbs, out, &tag, &header_len) ||
244 tag != tag_value ||
245 (header_len > 0 &&
246 /* This ensures that the tag is either zero length or
247 * indefinite-length. */
248 CBS_len(out) == header_len &&
249 CBS_data(out)[header_len - 1] == 0x80)) {
250 return 0;
251 }
252
253 if (skip_header && !CBS_skip(out, header_len)) {
254 assert(0);
255 return 0;
256 }
257
258 return 1;
259}
260
261int CBS_get_asn1(CBS *cbs, CBS *out, unsigned tag_value) {
262 return cbs_get_asn1(cbs, out, tag_value, 1 /* skip header */);
263}
264
265int CBS_get_asn1_element(CBS *cbs, CBS *out, unsigned tag_value) {
266 return cbs_get_asn1(cbs, out, tag_value, 0 /* include header */);
267}
268
269int CBS_peek_asn1_tag(const CBS *cbs, unsigned tag_value) {
270 if (CBS_len(cbs) < 1) {
271 return 0;
272 }
273 return CBS_data(cbs)[0] == tag_value;
274}
275
276int CBS_get_asn1_uint64(CBS *cbs, uint64_t *out) {
277 CBS bytes;
278 const uint8_t *data;
279 size_t i, len;
280
281 if (!CBS_get_asn1(cbs, &bytes, CBS_ASN1_INTEGER)) {
282 return 0;
283 }
284
285 *out = 0;
286 data = CBS_data(&bytes);
287 len = CBS_len(&bytes);
288
289 if (len == 0) {
290 /* An INTEGER is encoded with at least one octet. */
291 return 0;
292 }
293
294 if ((data[0] & 0x80) != 0) {
295 /* negative number */
296 return 0;
297 }
298
299 for (i = 0; i < len; i++) {
300 if ((*out >> 56) != 0) {
301 /* Too large to represent as a uint64_t. */
302 return 0;
303 }
304 *out <<= 8;
305 *out |= data[i];
306 }
307
308 return 1;
309}
310
311int CBS_get_optional_asn1(CBS *cbs, CBS *out, int *out_present, unsigned tag) {
312 if (CBS_peek_asn1_tag(cbs, tag)) {
313 if (!CBS_get_asn1(cbs, out, tag)) {
314 return 0;
315 }
316 *out_present = 1;
317 } else {
318 *out_present = 0;
319 }
320 return 1;
321}
322
323int CBS_get_optional_asn1_octet_string(CBS *cbs, CBS *out, int *out_present,
324 unsigned tag) {
325 CBS child;
326 int present;
327 if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) {
328 return 0;
329 }
330 if (present) {
331 if (!CBS_get_asn1(&child, out, CBS_ASN1_OCTETSTRING) ||
332 CBS_len(&child) != 0) {
333 return 0;
334 }
335 } else {
336 CBS_init(out, NULL, 0);
337 }
338 if (out_present) {
339 *out_present = present;
340 }
341 return 1;
342}
343
344int CBS_get_optional_asn1_uint64(CBS *cbs, uint64_t *out, unsigned tag,
345 uint64_t default_value) {
346 CBS child;
347 int present;
348 if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) {
349 return 0;
350 }
351 if (present) {
352 if (!CBS_get_asn1_uint64(&child, out) ||
353 CBS_len(&child) != 0) {
354 return 0;
355 }
356 } else {
357 *out = default_value;
358 }
359 return 1;
360}
361
362int CBS_get_optional_asn1_bool(CBS *cbs, int *out, unsigned tag,
363 int default_value) {
364 CBS child, child2;
365 int present;
366 if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) {
367 return 0;
368 }
369 if (present) {
370 uint8_t boolean;
371
372 if (!CBS_get_asn1(&child, &child2, CBS_ASN1_BOOLEAN) ||
373 CBS_len(&child2) != 1 ||
374 CBS_len(&child) != 0) {
375 return 0;
376 }
377
378 boolean = CBS_data(&child2)[0];
379 if (boolean == 0) {
380 *out = 0;
381 } else if (boolean == 0xff) {
382 *out = 1;
383 } else {
384 return 0;
385 }
386 } else {
387 *out = default_value;
388 }
389 return 1;
390}
diff --git a/src/lib/libssl/src/ssl/bytestring.h b/src/lib/libssl/src/ssl/bytestring.h
new file mode 100644
index 0000000000..3c4e8eaaf3
--- /dev/null
+++ b/src/lib/libssl/src/ssl/bytestring.h
@@ -0,0 +1,346 @@
1/* $OpenBSD: bytestring.h,v 1.1 2015/02/06 09:36:16 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#ifndef OPENSSL_HEADER_BYTESTRING_H
18#define OPENSSL_HEADER_BYTESTRING_H
19
20#if defined(__cplusplus)
21extern "C" {
22#endif
23
24#include <sys/types.h>
25#include <stdint.h>
26
27#include <openssl/opensslconf.h>
28
29/* Bytestrings are used for parsing and building TLS and ASN.1 messages.
30 *
31 * A "CBS" (CRYPTO ByteString) represents a string of bytes in memory and
32 * provides utility functions for safely parsing length-prefixed structures
33 * like TLS and ASN.1 from it.
34 *
35 * A "CBB" (CRYPTO ByteBuilder) is a memory buffer that grows as needed and
36 * provides utility functions for building length-prefixed messages. */
37
38
39/* CRYPTO ByteString */
40
41typedef struct cbs_st {
42 const uint8_t *data;
43 size_t len;
44} CBS;
45
46/* CBS_init sets |cbs| to point to |data|. It does not take ownership of
47 * |data|. */
48void CBS_init(CBS *cbs, const uint8_t *data, size_t len);
49
50/* CBS_skip advances |cbs| by |len| bytes. It returns one on success and zero
51 * otherwise. */
52int CBS_skip(CBS *cbs, size_t len);
53
54/* CBS_data returns a pointer to the contains of |cbs|. */
55const uint8_t *CBS_data(const CBS *cbs);
56
57/* CBS_len returns the number of bytes remaining in |cbs|. */
58size_t CBS_len(const CBS *cbs);
59
60/* CBS_stow copies the current contents of |cbs| into |*out_ptr| and
61 * |*out_len|. If |*out_ptr| is not NULL, the contents are freed with
62 * OPENSSL_free. It returns one on success and zero on allocation failure. On
63 * success, |*out_ptr| should be freed with OPENSSL_free. If |cbs| is empty,
64 * |*out_ptr| will be NULL. */
65int CBS_stow(const CBS *cbs, uint8_t **out_ptr, size_t *out_len);
66
67/* CBS_strdup copies the current contents of |cbs| into |*out_ptr| as a
68 * NUL-terminated C string. If |*out_ptr| is not NULL, the contents are freed
69 * with OPENSSL_free. It returns one on success and zero on allocation
70 * failure. On success, |*out_ptr| should be freed with OPENSSL_free.
71 *
72 * NOTE: If |cbs| contains NUL bytes, the string will be truncated. Call
73 * |CBS_contains_zero_byte(cbs)| to check for NUL bytes. */
74int CBS_strdup(const CBS *cbs, char **out_ptr);
75
76/* CBS_contains_zero_byte returns one if the current contents of |cbs| contains
77 * a NUL byte and zero otherwise. */
78int CBS_contains_zero_byte(const CBS *cbs);
79
80/* CBS_mem_equal compares the current contents of |cbs| with the |len| bytes
81 * starting at |data|. If they're equal, it returns one, otherwise zero. If the
82 * lengths match, it uses a constant-time comparison. */
83int CBS_mem_equal(const CBS *cbs, const uint8_t *data,
84 size_t len);
85
86/* CBS_get_u8 sets |*out| to the next uint8_t from |cbs| and advances |cbs|. It
87 * returns one on success and zero on error. */
88int CBS_get_u8(CBS *cbs, uint8_t *out);
89
90/* CBS_get_u16 sets |*out| to the next, big-endian uint16_t from |cbs| and
91 * advances |cbs|. It returns one on success and zero on error. */
92int CBS_get_u16(CBS *cbs, uint16_t *out);
93
94/* CBS_get_u24 sets |*out| to the next, big-endian 24-bit value from |cbs| and
95 * advances |cbs|. It returns one on success and zero on error. */
96int CBS_get_u24(CBS *cbs, uint32_t *out);
97
98/* CBS_get_u32 sets |*out| to the next, big-endian uint32_t value from |cbs|
99 * and advances |cbs|. It returns one on success and zero on error. */
100int CBS_get_u32(CBS *cbs, uint32_t *out);
101
102/* CBS_get_bytes sets |*out| to the next |len| bytes from |cbs| and advances
103 * |cbs|. It returns one on success and zero on error. */
104int CBS_get_bytes(CBS *cbs, CBS *out, size_t len);
105
106/* CBS_get_u8_length_prefixed sets |*out| to the contents of an 8-bit,
107 * length-prefixed value from |cbs| and advances |cbs| over it. It returns one
108 * on success and zero on error. */
109int CBS_get_u8_length_prefixed(CBS *cbs, CBS *out);
110
111/* CBS_get_u16_length_prefixed sets |*out| to the contents of a 16-bit,
112 * big-endian, length-prefixed value from |cbs| and advances |cbs| over it. It
113 * returns one on success and zero on error. */
114int CBS_get_u16_length_prefixed(CBS *cbs, CBS *out);
115
116/* CBS_get_u24_length_prefixed sets |*out| to the contents of a 24-bit,
117 * big-endian, length-prefixed value from |cbs| and advances |cbs| over it. It
118 * returns one on success and zero on error. */
119int CBS_get_u24_length_prefixed(CBS *cbs, CBS *out);
120
121
122/* Parsing ASN.1 */
123
124#define CBS_ASN1_BOOLEAN 0x1
125#define CBS_ASN1_INTEGER 0x2
126#define CBS_ASN1_BITSTRING 0x3
127#define CBS_ASN1_OCTETSTRING 0x4
128#define CBS_ASN1_OBJECT 0x6
129#define CBS_ASN1_ENUMERATED 0xa
130#define CBS_ASN1_SEQUENCE (0x10 | CBS_ASN1_CONSTRUCTED)
131#define CBS_ASN1_SET (0x11 | CBS_ASN1_CONSTRUCTED)
132
133#define CBS_ASN1_CONSTRUCTED 0x20
134#define CBS_ASN1_CONTEXT_SPECIFIC 0x80
135
136/* CBS_get_asn1 sets |*out| to the contents of DER-encoded, ASN.1 element (not
137 * including tag and length bytes) and advances |cbs| over it. The ASN.1
138 * element must match |tag_value|. It returns one on success and zero
139 * on error.
140 *
141 * Tag numbers greater than 31 are not supported. */
142int CBS_get_asn1(CBS *cbs, CBS *out, unsigned tag_value);
143
144/* CBS_get_asn1_element acts like |CBS_get_asn1| but |out| will include the
145 * ASN.1 header bytes too. */
146int CBS_get_asn1_element(CBS *cbs, CBS *out, unsigned tag_value);
147
148/* CBS_peek_asn1_tag looks ahead at the next ASN.1 tag and returns one
149 * if the next ASN.1 element on |cbs| would have tag |tag_value|. If
150 * |cbs| is empty or the tag does not match, it returns zero. Note: if
151 * it returns one, CBS_get_asn1 may still fail if the rest of the
152 * element is malformed. */
153int CBS_peek_asn1_tag(const CBS *cbs, unsigned tag_value);
154
155/* CBS_get_any_asn1_element sets |*out| to contain the next ASN.1 element from
156 * |*cbs| (including header bytes) and advances |*cbs|. It sets |*out_tag| to
157 * the tag number and |*out_header_len| to the length of the ASN.1 header. If
158 * the element has indefinite length then |*out| will only contain the
159 * header. Each of |out|, |out_tag|, and |out_header_len| may be NULL to ignore
160 * the value.
161 *
162 * Tag numbers greater than 31 are not supported. */
163int CBS_get_any_asn1_element(CBS *cbs, CBS *out,
164 unsigned *out_tag,
165 size_t *out_header_len);
166
167/* CBS_get_asn1_uint64 gets an ASN.1 INTEGER from |cbs| using |CBS_get_asn1|
168 * and sets |*out| to its value. It returns one on success and zero on error,
169 * where error includes the integer being negative, or too large to represent
170 * in 64 bits. */
171int CBS_get_asn1_uint64(CBS *cbs, uint64_t *out);
172
173/* CBS_get_optional_asn1 gets an optional explicitly-tagged element
174 * from |cbs| tagged with |tag| and sets |*out| to its contents. If
175 * present, it sets |*out_present| to one, otherwise zero. It returns
176 * one on success, whether or not the element was present, and zero on
177 * decode failure. */
178int CBS_get_optional_asn1(CBS *cbs, CBS *out, int *out_present,
179 unsigned tag);
180
181/* CBS_get_optional_asn1_octet_string gets an optional
182 * explicitly-tagged OCTET STRING from |cbs|. If present, it sets
183 * |*out| to the string and |*out_present| to one. Otherwise, it sets
184 * |*out| to empty and |*out_present| to zero. |out_present| may be
185 * NULL. It returns one on success, whether or not the element was
186 * present, and zero on decode failure. */
187int CBS_get_optional_asn1_octet_string(CBS *cbs, CBS *out,
188 int *out_present,
189 unsigned tag);
190
191/* CBS_get_optional_asn1_uint64 gets an optional explicitly-tagged
192 * INTEGER from |cbs|. If present, it sets |*out| to the
193 * value. Otherwise, it sets |*out| to |default_value|. It returns one
194 * on success, whether or not the element was present, and zero on
195 * decode failure. */
196int CBS_get_optional_asn1_uint64(CBS *cbs, uint64_t *out,
197 unsigned tag,
198 uint64_t default_value);
199
200/* CBS_get_optional_asn1_bool gets an optional, explicitly-tagged BOOLEAN from
201 * |cbs|. If present, it sets |*out| to either zero or one, based on the
202 * boolean. Otherwise, it sets |*out| to |default_value|. It returns one on
203 * success, whether or not the element was present, and zero on decode
204 * failure. */
205int CBS_get_optional_asn1_bool(CBS *cbs, int *out, unsigned tag,
206 int default_value);
207
208
209/* CRYPTO ByteBuilder.
210 *
211 * |CBB| objects allow one to build length-prefixed serialisations. A |CBB|
212 * object is associated with a buffer and new buffers are created with
213 * |CBB_init|. Several |CBB| objects can point at the same buffer when a
214 * length-prefix is pending, however only a single |CBB| can be 'current' at
215 * any one time. For example, if one calls |CBB_add_u8_length_prefixed| then
216 * the new |CBB| points at the same buffer as the original. But if the original
217 * |CBB| is used then the length prefix is written out and the new |CBB| must
218 * not be used again.
219 *
220 * If one needs to force a length prefix to be written out because a |CBB| is
221 * going out of scope, use |CBB_flush|. */
222
223struct cbb_buffer_st {
224 uint8_t *buf;
225 size_t len; /* The number of valid bytes. */
226 size_t cap; /* The size of buf. */
227 char can_resize; /* One iff |buf| is owned by this object. If not then |buf|
228 cannot be resized. */
229};
230
231typedef struct cbb_st {
232 struct cbb_buffer_st *base;
233 /* offset is the offset from the start of |base->buf| to the position of any
234 * pending length-prefix. */
235 size_t offset;
236 /* child points to a child CBB if a length-prefix is pending. */
237 struct cbb_st *child;
238 /* pending_len_len contains the number of bytes in a pending length-prefix,
239 * or zero if no length-prefix is pending. */
240 uint8_t pending_len_len;
241 char pending_is_asn1;
242 /* is_top_level is true iff this is a top-level |CBB| (as opposed to a child
243 * |CBB|). Top-level objects are valid arguments for |CBB_finish|. */
244 char is_top_level;
245} CBB;
246
247/* CBB_init initialises |cbb| with |initial_capacity|. Since a |CBB| grows as
248 * needed, the |initial_capacity| is just a hint. It returns one on success or
249 * zero on error. */
250int CBB_init(CBB *cbb, size_t initial_capacity);
251
252/* CBB_init_fixed initialises |cbb| to write to |len| bytes at |buf|. Since
253 * |buf| cannot grow, trying to write more than |len| bytes will cause CBB
254 * functions to fail. It returns one on success or zero on error. */
255int CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len);
256
257/* CBB_cleanup frees all resources owned by |cbb| and other |CBB| objects
258 * writing to the same buffer. This should be used in an error case where a
259 * serialisation is abandoned. */
260void CBB_cleanup(CBB *cbb);
261
262/* CBB_finish completes any pending length prefix and sets |*out_data| to a
263 * malloced buffer and |*out_len| to the length of that buffer. The caller
264 * takes ownership of the buffer and, unless the buffer was fixed with
265 * |CBB_init_fixed|, must call |OPENSSL_free| when done.
266 *
267 * It can only be called on a "top level" |CBB|, i.e. one initialised with
268 * |CBB_init| or |CBB_init_fixed|. It returns one on success and zero on
269 * error. */
270int CBB_finish(CBB *cbb, uint8_t **out_data, size_t *out_len);
271
272/* CBB_flush causes any pending length prefixes to be written out and any child
273 * |CBB| objects of |cbb| to be invalidated. It returns one on success or zero
274 * on error. */
275int CBB_flush(CBB *cbb);
276
277/* CBB_add_u8_length_prefixed sets |*out_contents| to a new child of |cbb|. The
278 * data written to |*out_contents| will be prefixed in |cbb| with an 8-bit
279 * length. It returns one on success or zero on error. */
280int CBB_add_u8_length_prefixed(CBB *cbb, CBB *out_contents);
281
282/* CBB_add_u16_length_prefixed sets |*out_contents| to a new child of |cbb|.
283 * The data written to |*out_contents| will be prefixed in |cbb| with a 16-bit,
284 * big-endian length. It returns one on success or zero on error. */
285int CBB_add_u16_length_prefixed(CBB *cbb, CBB *out_contents);
286
287/* CBB_add_u24_length_prefixed sets |*out_contents| to a new child of |cbb|.
288 * The data written to |*out_contents| will be prefixed in |cbb| with a 24-bit,
289 * big-endian length. It returns one on success or zero on error. */
290int CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents);
291
292/* CBB_add_asn sets |*out_contents| to a |CBB| into which the contents of an
293 * ASN.1 object can be written. The |tag| argument will be used as the tag for
294 * the object. It returns one on success or zero on error. */
295int CBB_add_asn1(CBB *cbb, CBB *out_contents, uint8_t tag);
296
297/* CBB_add_bytes appends |len| bytes from |data| to |cbb|. It returns one on
298 * success and zero otherwise. */
299int CBB_add_bytes(CBB *cbb, const uint8_t *data, size_t len);
300
301/* CBB_add_space appends |len| bytes to |cbb| and sets |*out_data| to point to
302 * the beginning of that space. The caller must then write |len| bytes of
303 * actual contents to |*out_data|. It returns one on success and zero
304 * otherwise. */
305int CBB_add_space(CBB *cbb, uint8_t **out_data, size_t len);
306
307/* CBB_add_u8 appends an 8-bit number from |value| to |cbb|. It returns one on
308 * success and zero otherwise. */
309int CBB_add_u8(CBB *cbb, uint8_t value);
310
311/* CBB_add_u8 appends a 16-bit, big-endian number from |value| to |cbb|. It
312 * returns one on success and zero otherwise. */
313int CBB_add_u16(CBB *cbb, uint16_t value);
314
315/* CBB_add_u24 appends a 24-bit, big-endian number from |value| to |cbb|. It
316 * returns one on success and zero otherwise. */
317int CBB_add_u24(CBB *cbb, uint32_t value);
318
319/* CBB_add_asn1_uint64 writes an ASN.1 INTEGER into |cbb| using |CBB_add_asn1|
320 * and writes |value| in its contents. It returns one on success and zero on
321 * error. */
322int CBB_add_asn1_uint64(CBB *cbb, uint64_t value);
323
324#ifdef LIBRESSL_INTERNAL
325/* CBS_asn1_ber_to_der reads an ASN.1 structure from |in|. If it finds
326 * indefinite-length elements then it attempts to convert the BER data to DER
327 * and sets |*out| and |*out_length| to describe a malloced buffer containing
328 * the DER data. Additionally, |*in| will be advanced over the ASN.1 data.
329 *
330 * If it doesn't find any indefinite-length elements then it sets |*out| to
331 * NULL and |*in| is unmodified.
332 *
333 * A sufficiently complex ASN.1 structure will break this function because it's
334 * not possible to generically convert BER to DER without knowledge of the
335 * structure itself. However, this sufficies to handle the PKCS#7 and #12 output
336 * from NSS.
337 *
338 * It returns one on success and zero otherwise. */
339int CBS_asn1_ber_to_der(CBS *in, uint8_t **out, size_t *out_len);
340#endif /* LIBRESSL_INTERNAL */
341
342#if defined(__cplusplus)
343} /* extern C */
344#endif
345
346#endif /* OPENSSL_HEADER_BYTESTRING_H */
diff --git a/src/lib/libssl/ssl/Makefile b/src/lib/libssl/ssl/Makefile
index 226ba681b6..c8f954d43e 100644
--- a/src/lib/libssl/ssl/Makefile
+++ b/src/lib/libssl/ssl/Makefile
@@ -1,4 +1,4 @@
1# $OpenBSD: Makefile,v 1.47 2014/07/12 03:27:23 deraadt Exp $ 1# $OpenBSD: Makefile,v 1.48 2015/02/06 09:36:16 doug Exp $
2 2
3LIB= ssl 3LIB= ssl
4 4
@@ -27,6 +27,7 @@ SRCS=\
27 bio_ssl.c ssl_err.c t1_reneg.c \ 27 bio_ssl.c ssl_err.c t1_reneg.c \
28 pqueue.c 28 pqueue.c
29SRCS+= s3_cbc.c 29SRCS+= s3_cbc.c
30SRCS+= bs_ber.c bs_cbb.c bs_cbs.c
30 31
31HDRS= srtp.h ssl.h ssl2.h ssl3.h ssl23.h tls1.h dtls1.h 32HDRS= srtp.h ssl.h ssl2.h ssl3.h ssl23.h tls1.h dtls1.h
32 33
diff --git a/src/regress/lib/libssl/Makefile b/src/regress/lib/libssl/Makefile
index f13ebf0b47..4d64dc3966 100644
--- a/src/regress/lib/libssl/Makefile
+++ b/src/regress/lib/libssl/Makefile
@@ -1,7 +1,8 @@
1# $OpenBSD: Makefile,v 1.20 2015/02/06 08:48:39 jsing Exp $ 1# $OpenBSD: Makefile,v 1.21 2015/02/06 09:36:16 doug Exp $
2 2
3SUBDIR= \ 3SUBDIR= \
4 asn1 \ 4 asn1 \
5 bytestring \
5 ciphers \ 6 ciphers \
6 ssl 7 ssl
7 8
diff --git a/src/regress/lib/libssl/bytestring/Makefile b/src/regress/lib/libssl/bytestring/Makefile
new file mode 100644
index 0000000000..439bf1cf8d
--- /dev/null
+++ b/src/regress/lib/libssl/bytestring/Makefile
@@ -0,0 +1,14 @@
1# $OpenBSD: Makefile,v 1.1 2015/02/06 09:36:16 doug Exp $
2
3PROG= bytestringtest
4LDADD= -lcrypto -lssl
5DPADD= ${LIBCRYPTO} ${LIBSSL}
6WARNINGS= Yes
7CFLAGS+= -DLIBRESSL_INTERNAL -Werror -I/usr/src/lib/libssl/src/ssl
8
9REGRESS_TARGETS=regress-bytestringtest
10
11regress-bytestringtest: ${PROG}
12 ./${PROG}
13
14.include <bsd.regress.mk>
diff --git a/src/regress/lib/libssl/bytestring/bytestringtest.c b/src/regress/lib/libssl/bytestring/bytestringtest.c
new file mode 100644
index 0000000000..92e33c02e7
--- /dev/null
+++ b/src/regress/lib/libssl/bytestring/bytestringtest.c
@@ -0,0 +1,655 @@
1/* $OpenBSD: bytestringtest.c,v 1.1 2015/02/06 09:36:16 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 <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20
21#include <openssl/crypto.h>
22
23#include "bytestring.h"
24
25/* This is from <openssl/base.h> in boringssl */
26#define OPENSSL_U64(x) x##ULL
27
28static int test_skip(void) {
29 static const uint8_t kData[] = {1, 2, 3};
30 CBS data;
31
32 CBS_init(&data, kData, sizeof(kData));
33 return CBS_len(&data) == 3 &&
34 CBS_skip(&data, 1) &&
35 CBS_len(&data) == 2 &&
36 CBS_skip(&data, 2) &&
37 CBS_len(&data) == 0 &&
38 !CBS_skip(&data, 1);
39}
40
41static int test_get_u(void) {
42 static const uint8_t kData[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
43 uint8_t u8;
44 uint16_t u16;
45 uint32_t u32;
46 CBS data;
47
48 CBS_init(&data, kData, sizeof(kData));
49 return CBS_get_u8(&data, &u8) &&
50 u8 == 1 &&
51 CBS_get_u16(&data, &u16) &&
52 u16 == 0x203 &&
53 CBS_get_u24(&data, &u32) &&
54 u32 == 0x40506 &&
55 CBS_get_u32(&data, &u32) &&
56 u32 == 0x708090a &&
57 !CBS_get_u8(&data, &u8);
58}
59
60static int test_get_prefixed(void) {
61 static const uint8_t kData[] = {1, 2, 0, 2, 3, 4, 0, 0, 3, 3, 2, 1};
62 uint8_t u8;
63 uint16_t u16;
64 uint32_t u32;
65 CBS data, prefixed;
66
67 CBS_init(&data, kData, sizeof(kData));
68 return CBS_get_u8_length_prefixed(&data, &prefixed) &&
69 CBS_len(&prefixed) == 1 &&
70 CBS_get_u8(&prefixed, &u8) &&
71 u8 == 2 &&
72 CBS_get_u16_length_prefixed(&data, &prefixed) &&
73 CBS_len(&prefixed) == 2 &&
74 CBS_get_u16(&prefixed, &u16) &&
75 u16 == 0x304 &&
76 CBS_get_u24_length_prefixed(&data, &prefixed) &&
77 CBS_len(&prefixed) == 3 &&
78 CBS_get_u24(&prefixed, &u32) &&
79 u32 == 0x30201;
80}
81
82static int test_get_prefixed_bad(void) {
83 static const uint8_t kData1[] = {2, 1};
84 static const uint8_t kData2[] = {0, 2, 1};
85 static const uint8_t kData3[] = {0, 0, 2, 1};
86 CBS data, prefixed;
87
88 CBS_init(&data, kData1, sizeof(kData1));
89 if (CBS_get_u8_length_prefixed(&data, &prefixed)) {
90 return 0;
91 }
92
93 CBS_init(&data, kData2, sizeof(kData2));
94 if (CBS_get_u16_length_prefixed(&data, &prefixed)) {
95 return 0;
96 }
97
98 CBS_init(&data, kData3, sizeof(kData3));
99 if (CBS_get_u24_length_prefixed(&data, &prefixed)) {
100 return 0;
101 }
102
103 return 1;
104}
105
106static int test_get_asn1(void) {
107 static const uint8_t kData1[] = {0x30, 2, 1, 2};
108 static const uint8_t kData2[] = {0x30, 3, 1, 2};
109 static const uint8_t kData3[] = {0x30, 0x80};
110 static const uint8_t kData4[] = {0x30, 0x81, 1, 1};
111 static const uint8_t kData5[] = {0x30, 0x82, 0, 1, 1};
112 static const uint8_t kData6[] = {0xa1, 3, 0x4, 1, 1};
113 static const uint8_t kData7[] = {0xa1, 3, 0x4, 2, 1};
114 static const uint8_t kData8[] = {0xa1, 3, 0x2, 1, 1};
115 static const uint8_t kData9[] = {0xa1, 3, 0x2, 1, 0xff};
116
117 CBS data, contents;
118 int present;
119 uint64_t value;
120
121 CBS_init(&data, kData1, sizeof(kData1));
122 if (CBS_peek_asn1_tag(&data, 0x1) ||
123 !CBS_peek_asn1_tag(&data, 0x30)) {
124 return 0;
125 }
126 if (!CBS_get_asn1(&data, &contents, 0x30) ||
127 CBS_len(&contents) != 2 ||
128 memcmp(CBS_data(&contents), "\x01\x02", 2) != 0) {
129 return 0;
130 }
131
132 CBS_init(&data, kData2, sizeof(kData2));
133 /* data is truncated */
134 if (CBS_get_asn1(&data, &contents, 0x30)) {
135 return 0;
136 }
137
138 CBS_init(&data, kData3, sizeof(kData3));
139 /* zero byte length of length */
140 if (CBS_get_asn1(&data, &contents, 0x30)) {
141 return 0;
142 }
143
144 CBS_init(&data, kData4, sizeof(kData4));
145 /* long form mistakenly used. */
146 if (CBS_get_asn1(&data, &contents, 0x30)) {
147 return 0;
148 }
149
150 CBS_init(&data, kData5, sizeof(kData5));
151 /* length takes too many bytes. */
152 if (CBS_get_asn1(&data, &contents, 0x30)) {
153 return 0;
154 }
155
156 CBS_init(&data, kData1, sizeof(kData1));
157 /* wrong tag. */
158 if (CBS_get_asn1(&data, &contents, 0x31)) {
159 return 0;
160 }
161
162 CBS_init(&data, NULL, 0);
163 /* peek at empty data. */
164 if (CBS_peek_asn1_tag(&data, 0x30)) {
165 return 0;
166 }
167
168 CBS_init(&data, NULL, 0);
169 /* optional elements at empty data. */
170 if (!CBS_get_optional_asn1(&data, &contents, &present, 0xa0) ||
171 present ||
172 !CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa0) ||
173 present ||
174 CBS_len(&contents) != 0 ||
175 !CBS_get_optional_asn1_octet_string(&data, &contents, NULL, 0xa0) ||
176 CBS_len(&contents) != 0 ||
177 !CBS_get_optional_asn1_uint64(&data, &value, 0xa0, 42) ||
178 value != 42) {
179 return 0;
180 }
181
182 CBS_init(&data, kData6, sizeof(kData6));
183 /* optional element. */
184 if (!CBS_get_optional_asn1(&data, &contents, &present, 0xa0) ||
185 present ||
186 !CBS_get_optional_asn1(&data, &contents, &present, 0xa1) ||
187 !present ||
188 CBS_len(&contents) != 3 ||
189 memcmp(CBS_data(&contents), "\x04\x01\x01", 3) != 0) {
190 return 0;
191 }
192
193 CBS_init(&data, kData6, sizeof(kData6));
194 /* optional octet string. */
195 if (!CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa0) ||
196 present ||
197 CBS_len(&contents) != 0 ||
198 !CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa1) ||
199 !present ||
200 CBS_len(&contents) != 1 ||
201 CBS_data(&contents)[0] != 1) {
202 return 0;
203 }
204
205 CBS_init(&data, kData7, sizeof(kData7));
206 /* invalid optional octet string. */
207 if (CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa1)) {
208 return 0;
209 }
210
211 CBS_init(&data, kData8, sizeof(kData8));
212 /* optional octet string. */
213 if (!CBS_get_optional_asn1_uint64(&data, &value, 0xa0, 42) ||
214 value != 42 ||
215 !CBS_get_optional_asn1_uint64(&data, &value, 0xa1, 42) ||
216 value != 1) {
217 return 0;
218 }
219
220 CBS_init(&data, kData9, sizeof(kData9));
221 /* invalid optional integer. */
222 if (CBS_get_optional_asn1_uint64(&data, &value, 0xa1, 42)) {
223 return 0;
224 }
225
226 return 1;
227}
228
229static int test_get_optional_asn1_bool(void) {
230 CBS data;
231 int val;
232
233 static const uint8_t kTrue[] = {0x0a, 3, CBS_ASN1_BOOLEAN, 1, 0xff};
234 static const uint8_t kFalse[] = {0x0a, 3, CBS_ASN1_BOOLEAN, 1, 0x00};
235 static const uint8_t kInvalid[] = {0x0a, 3, CBS_ASN1_BOOLEAN, 1, 0x01};
236
237 CBS_init(&data, NULL, 0);
238 val = 2;
239 if (!CBS_get_optional_asn1_bool(&data, &val, 0x0a, 0) ||
240 val != 0) {
241 return 0;
242 }
243
244 CBS_init(&data, kTrue, sizeof(kTrue));
245 val = 2;
246 if (!CBS_get_optional_asn1_bool(&data, &val, 0x0a, 0) ||
247 val != 1) {
248 return 0;
249 }
250
251 CBS_init(&data, kFalse, sizeof(kFalse));
252 val = 2;
253 if (!CBS_get_optional_asn1_bool(&data, &val, 0x0a, 1) ||
254 val != 0) {
255 return 0;
256 }
257
258 CBS_init(&data, kInvalid, sizeof(kInvalid));
259 if (CBS_get_optional_asn1_bool(&data, &val, 0x0a, 1)) {
260 return 0;
261 }
262
263 return 1;
264}
265
266static int test_cbb_basic(void) {
267 static const uint8_t kExpected[] = {1, 2, 3, 4, 5, 6, 7, 8};
268 uint8_t *buf;
269 size_t buf_len;
270 int ok;
271 CBB cbb;
272
273 if (!CBB_init(&cbb, 100)) {
274 return 0;
275 }
276 CBB_cleanup(&cbb);
277
278 if (!CBB_init(&cbb, 0) ||
279 !CBB_add_u8(&cbb, 1) ||
280 !CBB_add_u16(&cbb, 0x203) ||
281 !CBB_add_u24(&cbb, 0x40506) ||
282 !CBB_add_bytes(&cbb, (const uint8_t*) "\x07\x08", 2) ||
283 !CBB_finish(&cbb, &buf, &buf_len)) {
284 return 0;
285 }
286
287 ok = buf_len == sizeof(kExpected) && memcmp(buf, kExpected, buf_len) == 0;
288 free(buf);
289 return ok;
290}
291
292static int test_cbb_fixed(void) {
293 CBB cbb;
294 uint8_t buf[1];
295 uint8_t *out_buf;
296 size_t out_size;
297
298 if (!CBB_init_fixed(&cbb, NULL, 0) ||
299 CBB_add_u8(&cbb, 1) ||
300 !CBB_finish(&cbb, &out_buf, &out_size) ||
301 out_buf != NULL ||
302 out_size != 0) {
303 return 0;
304 }
305
306 if (!CBB_init_fixed(&cbb, buf, 1) ||
307 !CBB_add_u8(&cbb, 1) ||
308 CBB_add_u8(&cbb, 2) ||
309 !CBB_finish(&cbb, &out_buf, &out_size) ||
310 out_buf != buf ||
311 out_size != 1 ||
312 buf[0] != 1) {
313 return 0;
314 }
315
316 return 1;
317}
318
319static int test_cbb_finish_child(void) {
320 CBB cbb, child;
321 uint8_t *out_buf;
322 size_t out_size;
323
324 if (!CBB_init(&cbb, 16) ||
325 !CBB_add_u8_length_prefixed(&cbb, &child) ||
326 CBB_finish(&child, &out_buf, &out_size) ||
327 !CBB_finish(&cbb, &out_buf, &out_size) ||
328 out_size != 1 ||
329 out_buf[0] != 0) {
330 return 0;
331 }
332
333 free(out_buf);
334 return 1;
335}
336
337static int test_cbb_prefixed(void) {
338 static const uint8_t kExpected[] = {0, 1, 1, 0, 2, 2, 3, 0, 0, 3,
339 4, 5, 6, 5, 4, 1, 0, 1, 2};
340 uint8_t *buf;
341 size_t buf_len;
342 CBB cbb, contents, inner_contents, inner_inner_contents;
343 int ok;
344
345 if (!CBB_init(&cbb, 0) ||
346 !CBB_add_u8_length_prefixed(&cbb, &contents) ||
347 !CBB_add_u8_length_prefixed(&cbb, &contents) ||
348 !CBB_add_u8(&contents, 1) ||
349 !CBB_add_u16_length_prefixed(&cbb, &contents) ||
350 !CBB_add_u16(&contents, 0x203) ||
351 !CBB_add_u24_length_prefixed(&cbb, &contents) ||
352 !CBB_add_u24(&contents, 0x40506) ||
353 !CBB_add_u8_length_prefixed(&cbb, &contents) ||
354 !CBB_add_u8_length_prefixed(&contents, &inner_contents) ||
355 !CBB_add_u8(&inner_contents, 1) ||
356 !CBB_add_u16_length_prefixed(&inner_contents, &inner_inner_contents) ||
357 !CBB_add_u8(&inner_inner_contents, 2) ||
358 !CBB_finish(&cbb, &buf, &buf_len)) {
359 return 0;
360 }
361
362 ok = buf_len == sizeof(kExpected) && memcmp(buf, kExpected, buf_len) == 0;
363 free(buf);
364 return ok;
365}
366
367static int test_cbb_misuse(void) {
368 CBB cbb, child, contents;
369 uint8_t *buf;
370 size_t buf_len;
371
372 if (!CBB_init(&cbb, 0) ||
373 !CBB_add_u8_length_prefixed(&cbb, &child) ||
374 !CBB_add_u8(&child, 1) ||
375 !CBB_add_u8(&cbb, 2)) {
376 return 0;
377 }
378
379 /* Since we wrote to |cbb|, |child| is now invalid and attempts to write to
380 * it should fail. */
381 if (CBB_add_u8(&child, 1) ||
382 CBB_add_u16(&child, 1) ||
383 CBB_add_u24(&child, 1) ||
384 CBB_add_u8_length_prefixed(&child, &contents) ||
385 CBB_add_u16_length_prefixed(&child, &contents) ||
386 CBB_add_asn1(&child, &contents, 1) ||
387 CBB_add_bytes(&child, (const uint8_t*) "a", 1)) {
388 fprintf(stderr, "CBB operation on invalid CBB did not fail.\n");
389 return 0;
390 }
391
392 if (!CBB_finish(&cbb, &buf, &buf_len) ||
393 buf_len != 3 ||
394 memcmp(buf, "\x01\x01\x02", 3) != 0) {
395 return 0;
396 }
397
398 free(buf);
399
400 return 1;
401}
402
403static int test_cbb_asn1(void) {
404 static const uint8_t kExpected[] = {0x30, 3, 1, 2, 3};
405 uint8_t *buf, *test_data;
406 size_t buf_len;
407 CBB cbb, contents, inner_contents;
408
409 if (!CBB_init(&cbb, 0) ||
410 !CBB_add_asn1(&cbb, &contents, 0x30) ||
411 !CBB_add_bytes(&contents, (const uint8_t*) "\x01\x02\x03", 3) ||
412 !CBB_finish(&cbb, &buf, &buf_len)) {
413 return 0;
414 }
415
416 if (buf_len != sizeof(kExpected) || memcmp(buf, kExpected, buf_len) != 0) {
417 return 0;
418 }
419 free(buf);
420
421 test_data = malloc(100000);
422 memset(test_data, 0x42, 100000);
423
424 if (!CBB_init(&cbb, 0) ||
425 !CBB_add_asn1(&cbb, &contents, 0x30) ||
426 !CBB_add_bytes(&contents, test_data, 130) ||
427 !CBB_finish(&cbb, &buf, &buf_len)) {
428 return 0;
429 }
430
431 if (buf_len != 3 + 130 ||
432 memcmp(buf, "\x30\x81\x82", 3) != 0 ||
433 memcmp(buf + 3, test_data, 130) != 0) {
434 return 0;
435 }
436 free(buf);
437
438 if (!CBB_init(&cbb, 0) ||
439 !CBB_add_asn1(&cbb, &contents, 0x30) ||
440 !CBB_add_bytes(&contents, test_data, 1000) ||
441 !CBB_finish(&cbb, &buf, &buf_len)) {
442 return 0;
443 }
444
445 if (buf_len != 4 + 1000 ||
446 memcmp(buf, "\x30\x82\x03\xe8", 4) != 0 ||
447 memcmp(buf + 4, test_data, 1000)) {
448 return 0;
449 }
450 free(buf);
451
452 if (!CBB_init(&cbb, 0) ||
453 !CBB_add_asn1(&cbb, &contents, 0x30) ||
454 !CBB_add_asn1(&contents, &inner_contents, 0x30) ||
455 !CBB_add_bytes(&inner_contents, test_data, 100000) ||
456 !CBB_finish(&cbb, &buf, &buf_len)) {
457 return 0;
458 }
459
460 if (buf_len != 5 + 5 + 100000 ||
461 memcmp(buf, "\x30\x83\x01\x86\xa5\x30\x83\x01\x86\xa0", 10) != 0 ||
462 memcmp(buf + 10, test_data, 100000)) {
463 return 0;
464 }
465 free(buf);
466
467 free(test_data);
468 return 1;
469}
470
471static int do_ber_convert(const char *name,
472 const uint8_t *der_expected, size_t der_len,
473 const uint8_t *ber, size_t ber_len) {
474 CBS in;
475 uint8_t *out;
476 size_t out_len;
477
478 CBS_init(&in, ber, ber_len);
479 if (!CBS_asn1_ber_to_der(&in, &out, &out_len)) {
480 fprintf(stderr, "%s: CBS_asn1_ber_to_der failed.\n", name);
481 return 0;
482 }
483
484 if (out == NULL) {
485 if (ber_len != der_len ||
486 memcmp(der_expected, ber, ber_len) != 0) {
487 fprintf(stderr, "%s: incorrect unconverted result.\n", name);
488 return 0;
489 }
490
491 return 1;
492 }
493
494 if (out_len != der_len ||
495 memcmp(out, der_expected, der_len) != 0) {
496 fprintf(stderr, "%s: incorrect converted result.\n", name);
497 return 0;
498 }
499
500 free(out);
501 return 1;
502}
503
504static int test_ber_convert(void) {
505 static const uint8_t kSimpleBER[] = {0x01, 0x01, 0x00};
506
507 /* kIndefBER contains a SEQUENCE with an indefinite length. */
508 static const uint8_t kIndefBER[] = {0x30, 0x80, 0x01, 0x01, 0x02, 0x00, 0x00};
509 static const uint8_t kIndefDER[] = {0x30, 0x03, 0x01, 0x01, 0x02};
510
511 /* kOctetStringBER contains an indefinite length OCTETSTRING with two parts.
512 * These parts need to be concatenated in DER form. */
513 static const uint8_t kOctetStringBER[] = {0x24, 0x80, 0x04, 0x02, 0, 1,
514 0x04, 0x02, 2, 3, 0x00, 0x00};
515 static const uint8_t kOctetStringDER[] = {0x04, 0x04, 0, 1, 2, 3};
516
517 /* kNSSBER is part of a PKCS#12 message generated by NSS that uses indefinite
518 * length elements extensively. */
519 static const uint8_t kNSSBER[] = {
520 0x30, 0x80, 0x02, 0x01, 0x03, 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48,
521 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x80, 0x24, 0x80, 0x04, 0x04,
522 0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x39,
523 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05,
524 0x00, 0x04, 0x14, 0x84, 0x98, 0xfc, 0x66, 0x33, 0xee, 0xba, 0xe7, 0x90,
525 0xc1, 0xb6, 0xe8, 0x8f, 0xfe, 0x1d, 0xc5, 0xa5, 0x97, 0x93, 0x3e, 0x04,
526 0x10, 0x38, 0x62, 0xc6, 0x44, 0x12, 0xd5, 0x30, 0x00, 0xf8, 0xf2, 0x1b,
527 0xf0, 0x6e, 0x10, 0x9b, 0xb8, 0x02, 0x02, 0x07, 0xd0, 0x00, 0x00,
528 };
529
530 static const uint8_t kNSSDER[] = {
531 0x30, 0x53, 0x02, 0x01, 0x03, 0x30, 0x13, 0x06, 0x09, 0x2a, 0x86,
532 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x06, 0x04, 0x04,
533 0x01, 0x02, 0x03, 0x04, 0x30, 0x39, 0x30, 0x21, 0x30, 0x09, 0x06,
534 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14, 0x84,
535 0x98, 0xfc, 0x66, 0x33, 0xee, 0xba, 0xe7, 0x90, 0xc1, 0xb6, 0xe8,
536 0x8f, 0xfe, 0x1d, 0xc5, 0xa5, 0x97, 0x93, 0x3e, 0x04, 0x10, 0x38,
537 0x62, 0xc6, 0x44, 0x12, 0xd5, 0x30, 0x00, 0xf8, 0xf2, 0x1b, 0xf0,
538 0x6e, 0x10, 0x9b, 0xb8, 0x02, 0x02, 0x07, 0xd0,
539 };
540
541 return do_ber_convert("kSimpleBER", kSimpleBER, sizeof(kSimpleBER),
542 kSimpleBER, sizeof(kSimpleBER)) &&
543 do_ber_convert("kIndefBER", kIndefDER, sizeof(kIndefDER), kIndefBER,
544 sizeof(kIndefBER)) &&
545 do_ber_convert("kOctetStringBER", kOctetStringDER,
546 sizeof(kOctetStringDER), kOctetStringBER,
547 sizeof(kOctetStringBER)) &&
548 do_ber_convert("kNSSBER", kNSSDER, sizeof(kNSSDER), kNSSBER,
549 sizeof(kNSSBER));
550}
551
552typedef struct {
553 uint64_t value;
554 const char *encoding;
555 size_t encoding_len;
556} ASN1_UINT64_TEST;
557
558static const ASN1_UINT64_TEST kAsn1Uint64Tests[] = {
559 {0, "\x02\x01\x00", 3},
560 {1, "\x02\x01\x01", 3},
561 {127, "\x02\x01\x7f", 3},
562 {128, "\x02\x02\x00\x80", 4},
563 {0xdeadbeef, "\x02\x05\x00\xde\xad\xbe\xef", 7},
564 {OPENSSL_U64(0x0102030405060708),
565 "\x02\x08\x01\x02\x03\x04\x05\x06\x07\x08", 10},
566 {OPENSSL_U64(0xffffffffffffffff),
567 "\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xff", 11},
568};
569
570typedef struct {
571 const char *encoding;
572 size_t encoding_len;
573} ASN1_INVALID_UINT64_TEST;
574
575static const ASN1_INVALID_UINT64_TEST kAsn1InvalidUint64Tests[] = {
576 /* Bad tag. */
577 {"\x03\x01\x00", 3},
578 /* Empty contents. */
579 {"\x02\x00", 2},
580 /* Negative number. */
581 {"\x02\x01\x80", 3},
582 /* Overflow */
583 {"\x02\x09\x01\x00\x00\x00\x00\x00\x00\x00\x00", 11},
584};
585
586static int test_asn1_uint64(void) {
587 size_t i;
588
589 for (i = 0; i < sizeof(kAsn1Uint64Tests) / sizeof(kAsn1Uint64Tests[0]); i++) {
590 const ASN1_UINT64_TEST *test = &kAsn1Uint64Tests[i];
591 CBS cbs;
592 uint64_t value;
593 CBB cbb;
594 uint8_t *out;
595 size_t len;
596
597 CBS_init(&cbs, (const uint8_t *)test->encoding, test->encoding_len);
598 if (!CBS_get_asn1_uint64(&cbs, &value) ||
599 CBS_len(&cbs) != 0 ||
600 value != test->value) {
601 return 0;
602 }
603
604 if (!CBB_init(&cbb, 0)) {
605 return 0;
606 }
607 if (!CBB_add_asn1_uint64(&cbb, test->value) ||
608 !CBB_finish(&cbb, &out, &len)) {
609 CBB_cleanup(&cbb);
610 return 0;
611 }
612 if (len != test->encoding_len || memcmp(out, test->encoding, len) != 0) {
613 free(out);
614 return 0;
615 }
616 free(out);
617 }
618
619 for (i = 0;
620 i < sizeof(kAsn1InvalidUint64Tests) / sizeof(kAsn1InvalidUint64Tests[0]);
621 i++) {
622 const ASN1_INVALID_UINT64_TEST *test = &kAsn1InvalidUint64Tests[i];
623 CBS cbs;
624 uint64_t value;
625
626 CBS_init(&cbs, (const uint8_t *)test->encoding, test->encoding_len);
627 if (CBS_get_asn1_uint64(&cbs, &value)) {
628 return 0;
629 }
630 }
631
632 return 1;
633}
634
635int main(void) {
636 if (!test_skip() ||
637 !test_get_u() ||
638 !test_get_prefixed() ||
639 !test_get_prefixed_bad() ||
640 !test_get_asn1() ||
641 !test_cbb_basic() ||
642 !test_cbb_fixed() ||
643 !test_cbb_finish_child() ||
644 !test_cbb_misuse() ||
645 !test_cbb_prefixed() ||
646 !test_cbb_asn1() ||
647 !test_ber_convert() ||
648 !test_asn1_uint64() ||
649 !test_get_optional_asn1_bool()) {
650 return 1;
651 }
652
653 printf("PASS\n");
654 return 0;
655}