1 /* Copyright (c) 2014, Google Inc.
2 *
3 * Permission to use, copy, modify, and/or distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14
15 #include <openssl/bytestring.h>
16
17 #include <assert.h>
18
19 #include <openssl/mem.h>
20
21
cbb_init(CBB * cbb,uint8_t * buf,size_t cap)22 static int cbb_init(CBB *cbb, uint8_t *buf, size_t cap) {
23 struct cbb_buffer_st *base;
24
25 base = OPENSSL_malloc(sizeof(struct cbb_buffer_st));
26 if (base == NULL) {
27 OPENSSL_free(buf);
28 return 0;
29 }
30
31 base->buf = buf;
32 base->len = 0;
33 base->cap = cap;
34 base->can_resize = 1;
35
36 memset(cbb, 0, sizeof(CBB));
37 cbb->base = base;
38 cbb->is_top_level = 1;
39 return 1;
40 }
41
CBB_init(CBB * cbb,size_t initial_capacity)42 int CBB_init(CBB *cbb, size_t initial_capacity) {
43 uint8_t *buf;
44
45 buf = OPENSSL_malloc(initial_capacity);
46 if (initial_capacity > 0 && buf == NULL) {
47 return 0;
48 }
49
50 return cbb_init(cbb, buf, initial_capacity);
51 }
52
CBB_init_fixed(CBB * cbb,uint8_t * buf,size_t len)53 int CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len) {
54 if (!cbb_init(cbb, buf, len)) {
55 return 0;
56 }
57
58 cbb->base->can_resize = 0;
59 return 1;
60 }
61
CBB_cleanup(CBB * cbb)62 void CBB_cleanup(CBB *cbb) {
63 if (cbb->base) {
64 if (cbb->base->buf && cbb->base->can_resize) {
65 OPENSSL_free(cbb->base->buf);
66 }
67 OPENSSL_free(cbb->base);
68 }
69 cbb->base = NULL;
70 }
71
cbb_buffer_add(struct cbb_buffer_st * base,uint8_t ** out,size_t len)72 static int cbb_buffer_add(struct cbb_buffer_st *base, uint8_t **out,
73 size_t len) {
74 size_t newlen;
75
76 if (base == NULL) {
77 return 0;
78 }
79
80 newlen = base->len + len;
81 if (newlen < base->len) {
82 /* Overflow */
83 return 0;
84 }
85
86 if (newlen > base->cap) {
87 size_t newcap = base->cap * 2;
88 uint8_t *newbuf;
89
90 if (!base->can_resize) {
91 return 0;
92 }
93
94 if (newcap < base->cap || newcap < newlen) {
95 newcap = newlen;
96 }
97 newbuf = OPENSSL_realloc(base->buf, newcap);
98 if (newbuf == NULL) {
99 return 0;
100 }
101
102 base->buf = newbuf;
103 base->cap = newcap;
104 }
105
106 if (out) {
107 *out = base->buf + base->len;
108 }
109 base->len = newlen;
110 return 1;
111 }
112
cbb_buffer_add_u(struct cbb_buffer_st * base,uint32_t v,size_t len_len)113 static int cbb_buffer_add_u(struct cbb_buffer_st *base, uint32_t v,
114 size_t len_len) {
115 uint8_t *buf;
116 size_t i;
117
118 if (len_len == 0) {
119 return 1;
120 }
121 if (!cbb_buffer_add(base, &buf, len_len)) {
122 return 0;
123 }
124
125 for (i = len_len - 1; i < len_len; i--) {
126 buf[i] = v;
127 v >>= 8;
128 }
129 return 1;
130 }
131
CBB_finish(CBB * cbb,uint8_t ** out_data,size_t * out_len)132 int CBB_finish(CBB *cbb, uint8_t **out_data, size_t *out_len) {
133 if (!cbb->is_top_level) {
134 return 0;
135 }
136
137 if (!CBB_flush(cbb)) {
138 return 0;
139 }
140
141 if (cbb->base->can_resize && (out_data == NULL || out_len == NULL)) {
142 /* |out_data| and |out_len| can only be NULL if the CBB is fixed. */
143 return 0;
144 }
145
146 if (out_data != NULL) {
147 *out_data = cbb->base->buf;
148 }
149 if (out_len != NULL) {
150 *out_len = cbb->base->len;
151 }
152 cbb->base->buf = NULL;
153 CBB_cleanup(cbb);
154 return 1;
155 }
156
157 /* CBB_flush recurses and then writes out any pending length prefix. The
158 * current length of the underlying base is taken to be the length of the
159 * length-prefixed data. */
CBB_flush(CBB * cbb)160 int CBB_flush(CBB *cbb) {
161 size_t child_start, i, len;
162
163 if (cbb->base == NULL) {
164 return 0;
165 }
166
167 if (cbb->child == NULL || cbb->pending_len_len == 0) {
168 return 1;
169 }
170
171 child_start = cbb->offset + cbb->pending_len_len;
172
173 if (!CBB_flush(cbb->child) ||
174 child_start < cbb->offset ||
175 cbb->base->len < child_start) {
176 return 0;
177 }
178
179 len = cbb->base->len - child_start;
180
181 if (cbb->pending_is_asn1) {
182 /* For ASN.1 we assume that we'll only need a single byte for the length.
183 * If that turned out to be incorrect, we have to move the contents along
184 * in order to make space. */
185 size_t len_len;
186 uint8_t initial_length_byte;
187
188 assert (cbb->pending_len_len == 1);
189
190 if (len > 0xfffffffe) {
191 /* Too large. */
192 return 0;
193 } else if (len > 0xffffff) {
194 len_len = 5;
195 initial_length_byte = 0x80 | 4;
196 } else if (len > 0xffff) {
197 len_len = 4;
198 initial_length_byte = 0x80 | 3;
199 } else if (len > 0xff) {
200 len_len = 3;
201 initial_length_byte = 0x80 | 2;
202 } else if (len > 0x7f) {
203 len_len = 2;
204 initial_length_byte = 0x80 | 1;
205 } else {
206 len_len = 1;
207 initial_length_byte = len;
208 len = 0;
209 }
210
211 if (len_len != 1) {
212 /* We need to move the contents along in order to make space. */
213 size_t extra_bytes = len_len - 1;
214 if (!cbb_buffer_add(cbb->base, NULL, extra_bytes)) {
215 return 0;
216 }
217 memmove(cbb->base->buf + child_start + extra_bytes,
218 cbb->base->buf + child_start, len);
219 }
220 cbb->base->buf[cbb->offset++] = initial_length_byte;
221 cbb->pending_len_len = len_len - 1;
222 }
223
224 for (i = cbb->pending_len_len - 1; i < cbb->pending_len_len; i--) {
225 cbb->base->buf[cbb->offset + i] = len;
226 len >>= 8;
227 }
228 if (len != 0) {
229 return 0;
230 }
231
232 cbb->child->base = NULL;
233 cbb->child = NULL;
234 cbb->pending_len_len = 0;
235 cbb->pending_is_asn1 = 0;
236 cbb->offset = 0;
237
238 return 1;
239 }
240
241
cbb_add_length_prefixed(CBB * cbb,CBB * out_contents,size_t len_len)242 static int cbb_add_length_prefixed(CBB *cbb, CBB *out_contents,
243 size_t len_len) {
244 uint8_t *prefix_bytes;
245
246 if (!CBB_flush(cbb)) {
247 return 0;
248 }
249
250 cbb->offset = cbb->base->len;
251 if (!cbb_buffer_add(cbb->base, &prefix_bytes, len_len)) {
252 return 0;
253 }
254
255 memset(prefix_bytes, 0, len_len);
256 memset(out_contents, 0, sizeof(CBB));
257 out_contents->base = cbb->base;
258 cbb->child = out_contents;
259 cbb->pending_len_len = len_len;
260 cbb->pending_is_asn1 = 0;
261
262 return 1;
263 }
264
CBB_add_u8_length_prefixed(CBB * cbb,CBB * out_contents)265 int CBB_add_u8_length_prefixed(CBB *cbb, CBB *out_contents) {
266 return cbb_add_length_prefixed(cbb, out_contents, 1);
267 }
268
CBB_add_u16_length_prefixed(CBB * cbb,CBB * out_contents)269 int CBB_add_u16_length_prefixed(CBB *cbb, CBB *out_contents) {
270 return cbb_add_length_prefixed(cbb, out_contents, 2);
271 }
272
CBB_add_u24_length_prefixed(CBB * cbb,CBB * out_contents)273 int CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents) {
274 return cbb_add_length_prefixed(cbb, out_contents, 3);
275 }
276
CBB_add_asn1(CBB * cbb,CBB * out_contents,uint8_t tag)277 int CBB_add_asn1(CBB *cbb, CBB *out_contents, uint8_t tag) {
278 if (!CBB_flush(cbb) ||
279 !CBB_add_u8(cbb, tag)) {
280 return 0;
281 }
282
283 cbb->offset = cbb->base->len;
284 if (!CBB_add_u8(cbb, 0)) {
285 return 0;
286 }
287
288 memset(out_contents, 0, sizeof(CBB));
289 out_contents->base = cbb->base;
290 cbb->child = out_contents;
291 cbb->pending_len_len = 1;
292 cbb->pending_is_asn1 = 1;
293
294 return 1;
295 }
296
CBB_add_bytes(CBB * cbb,const uint8_t * data,size_t len)297 int CBB_add_bytes(CBB *cbb, const uint8_t *data, size_t len) {
298 uint8_t *dest;
299
300 if (!CBB_flush(cbb) ||
301 !cbb_buffer_add(cbb->base, &dest, len)) {
302 return 0;
303 }
304 memcpy(dest, data, len);
305 return 1;
306 }
307
CBB_add_space(CBB * cbb,uint8_t ** out_data,size_t len)308 int CBB_add_space(CBB *cbb, uint8_t **out_data, size_t len) {
309 if (!CBB_flush(cbb) ||
310 !cbb_buffer_add(cbb->base, out_data, len)) {
311 return 0;
312 }
313 return 1;
314 }
315
CBB_add_u8(CBB * cbb,uint8_t value)316 int CBB_add_u8(CBB *cbb, uint8_t value) {
317 if (!CBB_flush(cbb)) {
318 return 0;
319 }
320
321 return cbb_buffer_add_u(cbb->base, value, 1);
322 }
323
CBB_add_u16(CBB * cbb,uint16_t value)324 int CBB_add_u16(CBB *cbb, uint16_t value) {
325 if (!CBB_flush(cbb)) {
326 return 0;
327 }
328
329 return cbb_buffer_add_u(cbb->base, value, 2);
330 }
331
CBB_add_u24(CBB * cbb,uint32_t value)332 int CBB_add_u24(CBB *cbb, uint32_t value) {
333 if (!CBB_flush(cbb)) {
334 return 0;
335 }
336
337 return cbb_buffer_add_u(cbb->base, value, 3);
338 }
339