summaryrefslogtreecommitdiff
path: root/src/lib/libssl/bs_cbb.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/lib/libssl/bs_cbb.c611
1 files changed, 310 insertions, 301 deletions
diff --git a/src/lib/libssl/bs_cbb.c b/src/lib/libssl/bs_cbb.c
index 11688bcb7b..94ca54f43b 100644
--- a/src/lib/libssl/bs_cbb.c
+++ b/src/lib/libssl/bs_cbb.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: bs_cbb.c,v 1.2 2015/02/06 10:06:30 doug Exp $ */ 1/* $OpenBSD: bs_cbb.c,v 1.3 2015/02/06 22:22:33 doug Exp $ */
2/* 2/*
3 * Copyright (c) 2014, Google Inc. 3 * Copyright (c) 2014, Google Inc.
4 * 4 *
@@ -22,356 +22,365 @@
22 22
23#include "bytestring.h" 23#include "bytestring.h"
24 24
25static int cbb_init(CBB *cbb, uint8_t *buf, size_t cap) { 25static int
26 struct cbb_buffer_st *base; 26cbb_init(CBB *cbb, uint8_t *buf, size_t cap)
27{
28 struct cbb_buffer_st *base;
29
30 base = malloc(sizeof(struct cbb_buffer_st));
31 if (base == NULL) {
32 free(buf);
33 return 0;
34 }
35
36 base->buf = buf;
37 base->len = 0;
38 base->cap = cap;
39 base->can_resize = 1;
40
41 memset(cbb, 0, sizeof(CBB));
42 cbb->base = base;
43 cbb->is_top_level = 1;
44 return 1;
45}
27 46
28 base = malloc(sizeof(struct cbb_buffer_st)); 47int
29 if (base == NULL) { 48CBB_init(CBB *cbb, size_t initial_capacity)
30 free(buf); 49{
31 return 0; 50 uint8_t *buf;
32 }
33 51
34 base->buf = buf; 52 buf = malloc(initial_capacity);
35 base->len = 0; 53 if (initial_capacity > 0 && buf == NULL)
36 base->cap = cap; 54 return 0;
37 base->can_resize = 1;
38 55
39 memset(cbb, 0, sizeof(CBB)); 56 return cbb_init(cbb, buf, initial_capacity);
40 cbb->base = base;
41 cbb->is_top_level = 1;
42 return 1;
43} 57}
44 58
45int CBB_init(CBB *cbb, size_t initial_capacity) { 59int
46 uint8_t *buf; 60CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len)
47 61{
48 buf = malloc(initial_capacity); 62 if (!cbb_init(cbb, buf, len))
49 if (initial_capacity > 0 && buf == NULL) { 63 return 0;
50 return 0;
51 }
52 64
53 return cbb_init(cbb, buf, initial_capacity); 65 cbb->base->can_resize = 0;
66 return 1;
54} 67}
55 68
56int CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len) { 69void
57 if (!cbb_init(cbb, buf, len)) { 70CBB_cleanup(CBB *cbb)
58 return 0; 71{
59 } 72 if (cbb->base) {
73 if (cbb->base->buf && cbb->base->can_resize)
74 free(cbb->base->buf);
60 75
61 cbb->base->can_resize = 0; 76 free(cbb->base);
62 return 1; 77 }
78 cbb->base = NULL;
63} 79}
64 80
65void CBB_cleanup(CBB *cbb) { 81static int
66 if (cbb->base) { 82cbb_buffer_add(struct cbb_buffer_st *base, uint8_t **out, size_t len)
67 if (cbb->base->buf && cbb->base->can_resize) { 83{
68 free(cbb->base->buf); 84 size_t newlen;
69 } 85
70 free(cbb->base); 86 if (base == NULL)
71 } 87 return 0;
72 cbb->base = NULL; 88
73} 89 newlen = base->len + len;
90 if (newlen < base->len)
91 /* Overflow */
92 return 0;
93
94 if (newlen > base->cap) {
95 size_t newcap = base->cap * 2;
96 uint8_t *newbuf;
97
98 if (!base->can_resize)
99 return 0;
100
101 if (newcap < base->cap || newcap < newlen)
102 newcap = newlen;
103
104 newbuf = realloc(base->buf, newcap);
105 if (newbuf == NULL)
106 return 0;
107
108 base->buf = newbuf;
109 base->cap = newcap;
110 }
111
112 if (out)
113 *out = base->buf + base->len;
74 114
75static int cbb_buffer_add(struct cbb_buffer_st *base, uint8_t **out, 115 base->len = newlen;
76 size_t len) { 116 return 1;
77 size_t newlen;
78
79 if (base == NULL) {
80 return 0;
81 }
82
83 newlen = base->len + len;
84 if (newlen < base->len) {
85 /* Overflow */
86 return 0;
87 }
88
89 if (newlen > base->cap) {
90 size_t newcap = base->cap * 2;
91 uint8_t *newbuf;
92
93 if (!base->can_resize) {
94 return 0;
95 }
96
97 if (newcap < base->cap || newcap < newlen) {
98 newcap = newlen;
99 }
100 newbuf = realloc(base->buf, newcap);
101 if (newbuf == NULL) {
102 return 0;
103 }
104
105 base->buf = newbuf;
106 base->cap = newcap;
107 }
108
109 if (out) {
110 *out = base->buf + base->len;
111 }
112 base->len = newlen;
113 return 1;
114} 117}
115 118
116static int cbb_buffer_add_u(struct cbb_buffer_st *base, uint32_t v, 119static int
117 size_t len_len) { 120cbb_buffer_add_u(struct cbb_buffer_st *base, uint32_t v, size_t len_len)
118 uint8_t *buf; 121{
119 size_t i; 122 uint8_t *buf;
120 123 size_t i;
121 if (len_len == 0) { 124
122 return 1; 125 if (len_len == 0)
123 } 126 return 1;
124 if (!cbb_buffer_add(base, &buf, len_len)) { 127
125 return 0; 128 if (!cbb_buffer_add(base, &buf, len_len))
126 } 129 return 0;
127 130
128 for (i = len_len - 1; i < len_len; i--) { 131 for (i = len_len - 1; i < len_len; i--) {
129 buf[i] = v; 132 buf[i] = v;
130 v >>= 8; 133 v >>= 8;
131 } 134 }
132 return 1; 135 return 1;
133} 136}
134 137
135int CBB_finish(CBB *cbb, uint8_t **out_data, size_t *out_len) { 138int
136 if (!cbb->is_top_level) { 139CBB_finish(CBB *cbb, uint8_t **out_data, size_t *out_len)
137 return 0; 140{
138 } 141 if (!cbb->is_top_level)
139 142 return 0;
140 if (!CBB_flush(cbb)) { 143
141 return 0; 144 if (!CBB_flush(cbb))
142 } 145 return 0;
143 146
144 if (cbb->base->can_resize && (out_data == NULL || out_len == NULL)) { 147 if (cbb->base->can_resize && (out_data == NULL || out_len == NULL))
145 /* |out_data| and |out_len| can only be NULL if the CBB is fixed. */ 148 /* |out_data| and |out_len| can only be NULL if the CBB is fixed. */
146 return 0; 149 return 0;
147 } 150
148 151 if (out_data != NULL)
149 if (out_data != NULL) { 152 *out_data = cbb->base->buf;
150 *out_data = cbb->base->buf; 153
151 } 154 if (out_len != NULL)
152 if (out_len != NULL) { 155 *out_len = cbb->base->len;
153 *out_len = cbb->base->len; 156
154 } 157 cbb->base->buf = NULL;
155 cbb->base->buf = NULL; 158 CBB_cleanup(cbb);
156 CBB_cleanup(cbb); 159 return 1;
157 return 1;
158} 160}
159 161
160/* CBB_flush recurses and then writes out any pending length prefix. The 162/*
161 * current length of the underlying base is taken to be the length of the 163 * CBB_flush recurses and then writes out any pending length prefix. The current
162 * length-prefixed data. */ 164 * length of the underlying base is taken to be the length of the
163int CBB_flush(CBB *cbb) { 165 * length-prefixed data.
164 size_t child_start, i, len; 166 */
165 167int
166 if (cbb->base == NULL) { 168CBB_flush(CBB *cbb)
167 return 0; 169{
168 } 170 size_t child_start, i, len;
169 171
170 if (cbb->child == NULL || cbb->pending_len_len == 0) { 172 if (cbb->base == NULL)
171 return 1; 173 return 0;
172 } 174
173 175 if (cbb->child == NULL || cbb->pending_len_len == 0)
174 child_start = cbb->offset + cbb->pending_len_len; 176 return 1;
175 177
176 if (!CBB_flush(cbb->child) || 178 child_start = cbb->offset + cbb->pending_len_len;
177 child_start < cbb->offset || 179
178 cbb->base->len < child_start) { 180 if (!CBB_flush(cbb->child) || child_start < cbb->offset ||
179 return 0; 181 cbb->base->len < child_start)
180 } 182 return 0;
181 183
182 len = cbb->base->len - child_start; 184 len = cbb->base->len - child_start;
183 185
184 if (cbb->pending_is_asn1) { 186 if (cbb->pending_is_asn1) {
185 /* For ASN.1 we assume that we'll only need a single byte for the length. 187 /* For ASN.1 we assume that we'll only need a single byte for the length.
186 * If that turned out to be incorrect, we have to move the contents along 188 * If that turned out to be incorrect, we have to move the contents along
187 * in order to make space. */ 189 * in order to make space. */
188 size_t len_len; 190 size_t len_len;
189 uint8_t initial_length_byte; 191 uint8_t initial_length_byte;
190 192
191 assert (cbb->pending_len_len == 1); 193 assert (cbb->pending_len_len == 1);
192 194
193 if (len > 0xfffffffe) { 195 if (len > 0xfffffffe) {
194 /* Too large. */ 196 /* Too large. */
195 return 0; 197 return 0;
196 } else if (len > 0xffffff) { 198 } else if (len > 0xffffff) {
197 len_len = 5; 199 len_len = 5;
198 initial_length_byte = 0x80 | 4; 200 initial_length_byte = 0x80 | 4;
199 } else if (len > 0xffff) { 201 } else if (len > 0xffff) {
200 len_len = 4; 202 len_len = 4;
201 initial_length_byte = 0x80 | 3; 203 initial_length_byte = 0x80 | 3;
202 } else if (len > 0xff) { 204 } else if (len > 0xff) {
203 len_len = 3; 205 len_len = 3;
204 initial_length_byte = 0x80 | 2; 206 initial_length_byte = 0x80 | 2;
205 } else if (len > 0x7f) { 207 } else if (len > 0x7f) {
206 len_len = 2; 208 len_len = 2;
207 initial_length_byte = 0x80 | 1; 209 initial_length_byte = 0x80 | 1;
208 } else { 210 } else {
209 len_len = 1; 211 len_len = 1;
210 initial_length_byte = len; 212 initial_length_byte = len;
211 len = 0; 213 len = 0;
212 } 214 }
213 215
214 if (len_len != 1) { 216 if (len_len != 1) {
215 /* We need to move the contents along in order to make space. */ 217 /* We need to move the contents along in order to make space. */
216 size_t extra_bytes = len_len - 1; 218 size_t extra_bytes = len_len - 1;
217 if (!cbb_buffer_add(cbb->base, NULL, extra_bytes)) { 219 if (!cbb_buffer_add(cbb->base, NULL, extra_bytes))
218 return 0; 220 return 0;
219 } 221
220 memmove(cbb->base->buf + child_start + extra_bytes, 222 memmove(cbb->base->buf + child_start + extra_bytes,
221 cbb->base->buf + child_start, len); 223 cbb->base->buf + child_start, len);
222 } 224 }
223 cbb->base->buf[cbb->offset++] = initial_length_byte; 225 cbb->base->buf[cbb->offset++] = initial_length_byte;
224 cbb->pending_len_len = len_len - 1; 226 cbb->pending_len_len = len_len - 1;
225 } 227 }
226 228
227 for (i = cbb->pending_len_len - 1; i < cbb->pending_len_len; i--) { 229 for (i = cbb->pending_len_len - 1; i < cbb->pending_len_len; i--) {
228 cbb->base->buf[cbb->offset + i] = len; 230 cbb->base->buf[cbb->offset + i] = len;
229 len >>= 8; 231 len >>= 8;
230 } 232 }
231 if (len != 0) { 233 if (len != 0)
232 return 0; 234 return 0;
233 } 235
234 236 cbb->child->base = NULL;
235 cbb->child->base = NULL; 237 cbb->child = NULL;
236 cbb->child = NULL; 238 cbb->pending_len_len = 0;
237 cbb->pending_len_len = 0; 239 cbb->pending_is_asn1 = 0;
238 cbb->pending_is_asn1 = 0; 240 cbb->offset = 0;
239 cbb->offset = 0; 241
240 242 return 1;
241 return 1;
242} 243}
243 244
244 245
245static int cbb_add_length_prefixed(CBB *cbb, CBB *out_contents, 246static int
246 size_t len_len) { 247cbb_add_length_prefixed(CBB *cbb, CBB *out_contents, size_t len_len)
247 uint8_t *prefix_bytes; 248{
249 uint8_t *prefix_bytes;
248 250
249 if (!CBB_flush(cbb)) { 251 if (!CBB_flush(cbb))
250 return 0; 252 return 0;
251 }
252 253
253 cbb->offset = cbb->base->len; 254 cbb->offset = cbb->base->len;
254 if (!cbb_buffer_add(cbb->base, &prefix_bytes, len_len)) { 255 if (!cbb_buffer_add(cbb->base, &prefix_bytes, len_len))
255 return 0; 256 return 0;
256 }
257 257
258 memset(prefix_bytes, 0, len_len); 258 memset(prefix_bytes, 0, len_len);
259 memset(out_contents, 0, sizeof(CBB)); 259 memset(out_contents, 0, sizeof(CBB));
260 out_contents->base = cbb->base; 260 out_contents->base = cbb->base;
261 cbb->child = out_contents; 261 cbb->child = out_contents;
262 cbb->pending_len_len = len_len; 262 cbb->pending_len_len = len_len;
263 cbb->pending_is_asn1 = 0; 263 cbb->pending_is_asn1 = 0;
264 264
265 return 1; 265 return 1;
266} 266}
267 267
268int CBB_add_u8_length_prefixed(CBB *cbb, CBB *out_contents) { 268int
269 return cbb_add_length_prefixed(cbb, out_contents, 1); 269CBB_add_u8_length_prefixed(CBB *cbb, CBB *out_contents)
270{
271 return cbb_add_length_prefixed(cbb, out_contents, 1);
270} 272}
271 273
272int CBB_add_u16_length_prefixed(CBB *cbb, CBB *out_contents) { 274int
273 return cbb_add_length_prefixed(cbb, out_contents, 2); 275CBB_add_u16_length_prefixed(CBB *cbb, CBB *out_contents)
276{
277 return cbb_add_length_prefixed(cbb, out_contents, 2);
274} 278}
275 279
276int CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents) { 280int
277 return cbb_add_length_prefixed(cbb, out_contents, 3); 281CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents)
282{
283 return cbb_add_length_prefixed(cbb, out_contents, 3);
278} 284}
279 285
280int CBB_add_asn1(CBB *cbb, CBB *out_contents, uint8_t tag) { 286int
281 if (!CBB_flush(cbb) || 287CBB_add_asn1(CBB *cbb, CBB *out_contents, uint8_t tag)
282 !CBB_add_u8(cbb, tag)) { 288{
283 return 0; 289 if (!CBB_flush(cbb) || !CBB_add_u8(cbb, tag))
284 } 290 return 0;
285 291
286 cbb->offset = cbb->base->len; 292 cbb->offset = cbb->base->len;
287 if (!CBB_add_u8(cbb, 0)) { 293 if (!CBB_add_u8(cbb, 0))
288 return 0; 294 return 0;
289 }
290 295
291 memset(out_contents, 0, sizeof(CBB)); 296 memset(out_contents, 0, sizeof(CBB));
292 out_contents->base = cbb->base; 297 out_contents->base = cbb->base;
293 cbb->child = out_contents; 298 cbb->child = out_contents;
294 cbb->pending_len_len = 1; 299 cbb->pending_len_len = 1;
295 cbb->pending_is_asn1 = 1; 300 cbb->pending_is_asn1 = 1;
296 301
297 return 1; 302 return 1;
298} 303}
299 304
300int CBB_add_bytes(CBB *cbb, const uint8_t *data, size_t len) { 305int
301 uint8_t *dest; 306CBB_add_bytes(CBB *cbb, const uint8_t *data, size_t len)
307{
308 uint8_t *dest;
302 309
303 if (!CBB_flush(cbb) || 310 if (!CBB_flush(cbb) || !cbb_buffer_add(cbb->base, &dest, len))
304 !cbb_buffer_add(cbb->base, &dest, len)) { 311 return 0;
305 return 0; 312
306 } 313 memcpy(dest, data, len);
307 memcpy(dest, data, len); 314 return 1;
308 return 1;
309} 315}
310 316
311int CBB_add_space(CBB *cbb, uint8_t **out_data, size_t len) { 317int
312 if (!CBB_flush(cbb) || 318CBB_add_space(CBB *cbb, uint8_t **out_data, size_t len)
313 !cbb_buffer_add(cbb->base, out_data, len)) { 319{
314 return 0; 320 if (!CBB_flush(cbb) || !cbb_buffer_add(cbb->base, out_data, len))
315 } 321 return 0;
316 return 1; 322
323 return 1;
317} 324}
318 325
319int CBB_add_u8(CBB *cbb, uint8_t value) { 326int
320 if (!CBB_flush(cbb)) { 327CBB_add_u8(CBB *cbb, uint8_t value)
321 return 0; 328{
322 } 329 if (!CBB_flush(cbb))
330 return 0;
323 331
324 return cbb_buffer_add_u(cbb->base, value, 1); 332 return cbb_buffer_add_u(cbb->base, value, 1);
325} 333}
326 334
327int CBB_add_u16(CBB *cbb, uint16_t value) { 335int
328 if (!CBB_flush(cbb)) { 336CBB_add_u16(CBB *cbb, uint16_t value)
329 return 0; 337{
330 } 338 if (!CBB_flush(cbb))
339 return 0;
331 340
332 return cbb_buffer_add_u(cbb->base, value, 2); 341 return cbb_buffer_add_u(cbb->base, value, 2);
333} 342}
334 343
335int CBB_add_u24(CBB *cbb, uint32_t value) { 344int
336 if (!CBB_flush(cbb)) { 345CBB_add_u24(CBB *cbb, uint32_t value)
337 return 0; 346{
338 } 347 if (!CBB_flush(cbb))
348 return 0;
339 349
340 return cbb_buffer_add_u(cbb->base, value, 3); 350 return cbb_buffer_add_u(cbb->base, value, 3);
341} 351}
342 352
343int CBB_add_asn1_uint64(CBB *cbb, uint64_t value) { 353int
344 CBB child; 354CBB_add_asn1_uint64(CBB *cbb, uint64_t value)
345 size_t i; 355{
346 int started = 0; 356 CBB child;
347 357 size_t i;
348 if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER)) { 358 int started = 0;
349 return 0; 359
350 } 360 if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER))
351 361 return 0;
352 for (i = 0; i < 8; i++) { 362
353 uint8_t byte = (value >> 8*(7-i)) & 0xff; 363 for (i = 0; i < 8; i++) {
354 if (!started) { 364 uint8_t byte = (value >> 8*(7-i)) & 0xff;
355 if (byte == 0) { 365 if (!started) {
356 /* Don't encode leading zeros. */ 366 if (byte == 0)
357 continue; 367 /* Don't encode leading zeros. */
358 } 368 continue;
359 /* If the high bit is set, add a padding byte to make it 369
360 * unsigned. */ 370 /* If the high bit is set, add a padding byte to make it
361 if ((byte & 0x80) && !CBB_add_u8(&child, 0)) { 371 * unsigned. */
362 return 0; 372 if ((byte & 0x80) && !CBB_add_u8(&child, 0))
363 } 373 return 0;
364 started = 1; 374
365 } 375 started = 1;
366 if (!CBB_add_u8(&child, byte)) { 376 }
367 return 0; 377 if (!CBB_add_u8(&child, byte))
368 } 378 return 0;
369 } 379 }
370 380
371 /* 0 is encoded as a single 0, not the empty string. */ 381 /* 0 is encoded as a single 0, not the empty string. */
372 if (!started && !CBB_add_u8(&child, 0)) { 382 if (!started && !CBB_add_u8(&child, 0))
373 return 0; 383 return 0;
374 } 384
375 385 return CBB_flush(cbb);
376 return CBB_flush(cbb);
377} 386}