• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <string.h>
19 
20 #include <openssl/mem.h>
21 
22 #include "../internal.h"
23 
24 
CBB_zero(CBB * cbb)25 void CBB_zero(CBB *cbb) {
26   OPENSSL_memset(cbb, 0, sizeof(CBB));
27 }
28 
cbb_init(CBB * cbb,uint8_t * buf,size_t cap)29 static int cbb_init(CBB *cbb, uint8_t *buf, size_t cap) {
30   /* This assumes that |cbb| has already been zeroed. */
31   struct cbb_buffer_st *base;
32 
33   base = OPENSSL_malloc(sizeof(struct cbb_buffer_st));
34   if (base == NULL) {
35     return 0;
36   }
37 
38   base->buf = buf;
39   base->len = 0;
40   base->cap = cap;
41   base->can_resize = 1;
42   base->error = 0;
43 
44   cbb->base = base;
45   cbb->is_top_level = 1;
46   return 1;
47 }
48 
CBB_init(CBB * cbb,size_t initial_capacity)49 int CBB_init(CBB *cbb, size_t initial_capacity) {
50   CBB_zero(cbb);
51 
52   uint8_t *buf = OPENSSL_malloc(initial_capacity);
53   if (initial_capacity > 0 && buf == NULL) {
54     return 0;
55   }
56 
57   if (!cbb_init(cbb, buf, initial_capacity)) {
58     OPENSSL_free(buf);
59     return 0;
60   }
61 
62   return 1;
63 }
64 
CBB_init_fixed(CBB * cbb,uint8_t * buf,size_t len)65 int CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len) {
66   CBB_zero(cbb);
67 
68   if (!cbb_init(cbb, buf, len)) {
69     return 0;
70   }
71 
72   cbb->base->can_resize = 0;
73   return 1;
74 }
75 
CBB_cleanup(CBB * cbb)76 void CBB_cleanup(CBB *cbb) {
77   if (cbb->base) {
78     /* Only top-level |CBB|s are cleaned up. Child |CBB|s are non-owning. They
79      * are implicitly discarded when the parent is flushed or cleaned up. */
80     assert(cbb->is_top_level);
81 
82     if (cbb->base->can_resize) {
83       OPENSSL_free(cbb->base->buf);
84     }
85     OPENSSL_free(cbb->base);
86   }
87   cbb->base = NULL;
88 }
89 
cbb_buffer_reserve(struct cbb_buffer_st * base,uint8_t ** out,size_t len)90 static int cbb_buffer_reserve(struct cbb_buffer_st *base, uint8_t **out,
91                               size_t len) {
92   size_t newlen;
93 
94   if (base == NULL) {
95     return 0;
96   }
97 
98   newlen = base->len + len;
99   if (newlen < base->len) {
100     /* Overflow */
101     goto err;
102   }
103 
104   if (newlen > base->cap) {
105     size_t newcap = base->cap * 2;
106     uint8_t *newbuf;
107 
108     if (!base->can_resize) {
109       goto err;
110     }
111 
112     if (newcap < base->cap || newcap < newlen) {
113       newcap = newlen;
114     }
115     newbuf = OPENSSL_realloc(base->buf, newcap);
116     if (newbuf == NULL) {
117       goto err;
118     }
119 
120     base->buf = newbuf;
121     base->cap = newcap;
122   }
123 
124   if (out) {
125     *out = base->buf + base->len;
126   }
127 
128   return 1;
129 
130 err:
131   base->error = 1;
132   return 0;
133 }
134 
cbb_buffer_add(struct cbb_buffer_st * base,uint8_t ** out,size_t len)135 static int cbb_buffer_add(struct cbb_buffer_st *base, uint8_t **out,
136                           size_t len) {
137   if (!cbb_buffer_reserve(base, out, len)) {
138     return 0;
139   }
140   /* This will not overflow or |cbb_buffer_reserve| would have failed. */
141   base->len += len;
142   return 1;
143 }
144 
cbb_buffer_add_u(struct cbb_buffer_st * base,uint32_t v,size_t len_len)145 static int cbb_buffer_add_u(struct cbb_buffer_st *base, uint32_t v,
146                             size_t len_len) {
147   if (len_len == 0) {
148     return 1;
149   }
150 
151   uint8_t *buf;
152   if (!cbb_buffer_add(base, &buf, len_len)) {
153     return 0;
154   }
155 
156   for (size_t i = len_len - 1; i < len_len; i--) {
157     buf[i] = v;
158     v >>= 8;
159   }
160 
161   if (v != 0) {
162     base->error = 1;
163     return 0;
164   }
165 
166   return 1;
167 }
168 
CBB_finish(CBB * cbb,uint8_t ** out_data,size_t * out_len)169 int CBB_finish(CBB *cbb, uint8_t **out_data, size_t *out_len) {
170   if (!cbb->is_top_level) {
171     return 0;
172   }
173 
174   if (!CBB_flush(cbb)) {
175     return 0;
176   }
177 
178   if (cbb->base->can_resize && (out_data == NULL || out_len == NULL)) {
179     /* |out_data| and |out_len| can only be NULL if the CBB is fixed. */
180     return 0;
181   }
182 
183   if (out_data != NULL) {
184     *out_data = cbb->base->buf;
185   }
186   if (out_len != NULL) {
187     *out_len = cbb->base->len;
188   }
189   cbb->base->buf = NULL;
190   CBB_cleanup(cbb);
191   return 1;
192 }
193 
194 /* CBB_flush recurses and then writes out any pending length prefix. The
195  * current length of the underlying base is taken to be the length of the
196  * length-prefixed data. */
CBB_flush(CBB * cbb)197 int CBB_flush(CBB *cbb) {
198   size_t child_start, i, len;
199 
200   /* If |cbb->base| has hit an error, the buffer is in an undefined state, so
201    * fail all following calls. In particular, |cbb->child| may point to invalid
202    * memory. */
203   if (cbb->base == NULL || cbb->base->error) {
204     return 0;
205   }
206 
207   if (cbb->child == NULL || cbb->child->pending_len_len == 0) {
208     return 1;
209   }
210 
211   child_start = cbb->child->offset + cbb->child->pending_len_len;
212 
213   if (!CBB_flush(cbb->child) ||
214       child_start < cbb->child->offset ||
215       cbb->base->len < child_start) {
216     goto err;
217   }
218 
219   len = cbb->base->len - child_start;
220 
221   if (cbb->child->pending_is_asn1) {
222     /* For ASN.1 we assume that we'll only need a single byte for the length.
223      * If that turned out to be incorrect, we have to move the contents along
224      * in order to make space. */
225     uint8_t len_len;
226     uint8_t initial_length_byte;
227 
228     assert (cbb->child->pending_len_len == 1);
229 
230     if (len > 0xfffffffe) {
231       /* Too large. */
232       goto err;
233     } else if (len > 0xffffff) {
234       len_len = 5;
235       initial_length_byte = 0x80 | 4;
236     } else if (len > 0xffff) {
237       len_len = 4;
238       initial_length_byte = 0x80 | 3;
239     } else if (len > 0xff) {
240       len_len = 3;
241       initial_length_byte = 0x80 | 2;
242     } else if (len > 0x7f) {
243       len_len = 2;
244       initial_length_byte = 0x80 | 1;
245     } else {
246       len_len = 1;
247       initial_length_byte = (uint8_t)len;
248       len = 0;
249     }
250 
251     if (len_len != 1) {
252       /* We need to move the contents along in order to make space. */
253       size_t extra_bytes = len_len - 1;
254       if (!cbb_buffer_add(cbb->base, NULL, extra_bytes)) {
255         goto err;
256       }
257       OPENSSL_memmove(cbb->base->buf + child_start + extra_bytes,
258                       cbb->base->buf + child_start, len);
259     }
260     cbb->base->buf[cbb->child->offset++] = initial_length_byte;
261     cbb->child->pending_len_len = len_len - 1;
262   }
263 
264   for (i = cbb->child->pending_len_len - 1; i < cbb->child->pending_len_len;
265        i--) {
266     cbb->base->buf[cbb->child->offset + i] = (uint8_t)len;
267     len >>= 8;
268   }
269   if (len != 0) {
270     goto err;
271   }
272 
273   cbb->child->base = NULL;
274   cbb->child = NULL;
275 
276   return 1;
277 
278 err:
279   cbb->base->error = 1;
280   return 0;
281 }
282 
CBB_data(const CBB * cbb)283 const uint8_t *CBB_data(const CBB *cbb) {
284   assert(cbb->child == NULL);
285   return cbb->base->buf + cbb->offset + cbb->pending_len_len;
286 }
287 
CBB_len(const CBB * cbb)288 size_t CBB_len(const CBB *cbb) {
289   assert(cbb->child == NULL);
290   assert(cbb->offset + cbb->pending_len_len <= cbb->base->len);
291 
292   return cbb->base->len - cbb->offset - cbb->pending_len_len;
293 }
294 
cbb_add_length_prefixed(CBB * cbb,CBB * out_contents,uint8_t len_len)295 static int cbb_add_length_prefixed(CBB *cbb, CBB *out_contents,
296                                    uint8_t len_len) {
297   uint8_t *prefix_bytes;
298 
299   if (!CBB_flush(cbb)) {
300     return 0;
301   }
302 
303   size_t offset = cbb->base->len;
304   if (!cbb_buffer_add(cbb->base, &prefix_bytes, len_len)) {
305     return 0;
306   }
307 
308   OPENSSL_memset(prefix_bytes, 0, len_len);
309   OPENSSL_memset(out_contents, 0, sizeof(CBB));
310   out_contents->base = cbb->base;
311   cbb->child = out_contents;
312   cbb->child->offset = offset;
313   cbb->child->pending_len_len = len_len;
314   cbb->child->pending_is_asn1 = 0;
315 
316   return 1;
317 }
318 
CBB_add_u8_length_prefixed(CBB * cbb,CBB * out_contents)319 int CBB_add_u8_length_prefixed(CBB *cbb, CBB *out_contents) {
320   return cbb_add_length_prefixed(cbb, out_contents, 1);
321 }
322 
CBB_add_u16_length_prefixed(CBB * cbb,CBB * out_contents)323 int CBB_add_u16_length_prefixed(CBB *cbb, CBB *out_contents) {
324   return cbb_add_length_prefixed(cbb, out_contents, 2);
325 }
326 
CBB_add_u24_length_prefixed(CBB * cbb,CBB * out_contents)327 int CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents) {
328   return cbb_add_length_prefixed(cbb, out_contents, 3);
329 }
330 
CBB_add_asn1(CBB * cbb,CBB * out_contents,unsigned tag)331 int CBB_add_asn1(CBB *cbb, CBB *out_contents, unsigned tag) {
332   if (tag > 0xff ||
333       (tag & 0x1f) == 0x1f) {
334     /* Long form identifier octets are not supported. Further, all current valid
335      * tag serializations are 8 bits. */
336     cbb->base->error = 1;
337     return 0;
338   }
339 
340   if (!CBB_flush(cbb) ||
341       /* |tag|'s representation matches the DER encoding. */
342       !CBB_add_u8(cbb, (uint8_t)tag)) {
343     return 0;
344   }
345 
346   size_t offset = cbb->base->len;
347   if (!CBB_add_u8(cbb, 0)) {
348     return 0;
349   }
350 
351   OPENSSL_memset(out_contents, 0, sizeof(CBB));
352   out_contents->base = cbb->base;
353   cbb->child = out_contents;
354   cbb->child->offset = offset;
355   cbb->child->pending_len_len = 1;
356   cbb->child->pending_is_asn1 = 1;
357 
358   return 1;
359 }
360 
CBB_add_bytes(CBB * cbb,const uint8_t * data,size_t len)361 int CBB_add_bytes(CBB *cbb, const uint8_t *data, size_t len) {
362   uint8_t *dest;
363 
364   if (!CBB_flush(cbb) ||
365       !cbb_buffer_add(cbb->base, &dest, len)) {
366     return 0;
367   }
368   OPENSSL_memcpy(dest, data, len);
369   return 1;
370 }
371 
CBB_add_space(CBB * cbb,uint8_t ** out_data,size_t len)372 int CBB_add_space(CBB *cbb, uint8_t **out_data, size_t len) {
373   if (!CBB_flush(cbb) ||
374       !cbb_buffer_add(cbb->base, out_data, len)) {
375     return 0;
376   }
377   return 1;
378 }
379 
CBB_reserve(CBB * cbb,uint8_t ** out_data,size_t len)380 int CBB_reserve(CBB *cbb, uint8_t **out_data, size_t len) {
381   if (!CBB_flush(cbb) ||
382       !cbb_buffer_reserve(cbb->base, out_data, len)) {
383     return 0;
384   }
385   return 1;
386 }
387 
CBB_did_write(CBB * cbb,size_t len)388 int CBB_did_write(CBB *cbb, size_t len) {
389   size_t newlen = cbb->base->len + len;
390   if (cbb->child != NULL ||
391       newlen < cbb->base->len ||
392       newlen > cbb->base->cap) {
393     return 0;
394   }
395   cbb->base->len = newlen;
396   return 1;
397 }
398 
CBB_add_u8(CBB * cbb,uint8_t value)399 int CBB_add_u8(CBB *cbb, uint8_t value) {
400   if (!CBB_flush(cbb)) {
401     return 0;
402   }
403 
404   return cbb_buffer_add_u(cbb->base, value, 1);
405 }
406 
CBB_add_u16(CBB * cbb,uint16_t value)407 int CBB_add_u16(CBB *cbb, uint16_t value) {
408   if (!CBB_flush(cbb)) {
409     return 0;
410   }
411 
412   return cbb_buffer_add_u(cbb->base, value, 2);
413 }
414 
CBB_add_u24(CBB * cbb,uint32_t value)415 int CBB_add_u24(CBB *cbb, uint32_t value) {
416   if (!CBB_flush(cbb)) {
417     return 0;
418   }
419 
420   return cbb_buffer_add_u(cbb->base, value, 3);
421 }
422 
CBB_add_u32(CBB * cbb,uint32_t value)423 int CBB_add_u32(CBB *cbb, uint32_t value) {
424   if (!CBB_flush(cbb)) {
425     return 0;
426   }
427 
428   return cbb_buffer_add_u(cbb->base, value, 4);
429 }
430 
CBB_discard_child(CBB * cbb)431 void CBB_discard_child(CBB *cbb) {
432   if (cbb->child == NULL) {
433     return;
434   }
435 
436   cbb->base->len = cbb->child->offset;
437 
438   cbb->child->base = NULL;
439   cbb->child = NULL;
440 }
441 
CBB_add_asn1_uint64(CBB * cbb,uint64_t value)442 int CBB_add_asn1_uint64(CBB *cbb, uint64_t value) {
443   CBB child;
444   int started = 0;
445 
446   if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER)) {
447     return 0;
448   }
449 
450   for (size_t i = 0; i < 8; i++) {
451     uint8_t byte = (value >> 8*(7-i)) & 0xff;
452     if (!started) {
453       if (byte == 0) {
454         /* Don't encode leading zeros. */
455         continue;
456       }
457       /* If the high bit is set, add a padding byte to make it
458        * unsigned. */
459       if ((byte & 0x80) && !CBB_add_u8(&child, 0)) {
460         return 0;
461       }
462       started = 1;
463     }
464     if (!CBB_add_u8(&child, byte)) {
465       return 0;
466     }
467   }
468 
469   /* 0 is encoded as a single 0, not the empty string. */
470   if (!started && !CBB_add_u8(&child, 0)) {
471     return 0;
472   }
473 
474   return CBB_flush(cbb);
475 }
476