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 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 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 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 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 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 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 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. */ 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 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 265 int CBB_add_u8_length_prefixed(CBB *cbb, CBB *out_contents) { 266 return cbb_add_length_prefixed(cbb, out_contents, 1); 267 } 268 269 int CBB_add_u16_length_prefixed(CBB *cbb, CBB *out_contents) { 270 return cbb_add_length_prefixed(cbb, out_contents, 2); 271 } 272 273 int CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents) { 274 return cbb_add_length_prefixed(cbb, out_contents, 3); 275 } 276 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 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 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 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 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 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