summaryrefslogtreecommitdiff
path: root/src/lib/libssl/bs_cbs.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/lib/libssl/bs_cbs.c663
1 files changed, 356 insertions, 307 deletions
diff --git a/src/lib/libssl/bs_cbs.c b/src/lib/libssl/bs_cbs.c
index 7edfe65288..c3d3a8abf2 100644
--- a/src/lib/libssl/bs_cbs.c
+++ b/src/lib/libssl/bs_cbs.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: bs_cbs.c,v 1.1 2015/02/06 09:36:16 doug Exp $ */ 1/* $OpenBSD: bs_cbs.c,v 1.2 2015/02/06 22:22:33 doug Exp $ */
2/* 2/*
3 * Copyright (c) 2014, Google Inc. 3 * Copyright (c) 2014, Google Inc.
4 * 4 *
@@ -24,367 +24,416 @@
24 24
25#include "bytestring.h" 25#include "bytestring.h"
26 26
27void CBS_init(CBS *cbs, const uint8_t *data, size_t len) { 27void
28 cbs->data = data; 28CBS_init(CBS *cbs, const uint8_t *data, size_t len)
29 cbs->len = len; 29{
30 cbs->data = data;
31 cbs->len = len;
30} 32}
31 33
32static int cbs_get(CBS *cbs, const uint8_t **p, size_t n) { 34static int
33 if (cbs->len < n) { 35cbs_get(CBS *cbs, const uint8_t **p, size_t n)
34 return 0; 36{
35 } 37 if (cbs->len < n)
38 return 0;
36 39
37 *p = cbs->data; 40 *p = cbs->data;
38 cbs->data += n; 41 cbs->data += n;
39 cbs->len -= n; 42 cbs->len -= n;
40 return 1; 43 return 1;
41} 44}
42 45
43int CBS_skip(CBS *cbs, size_t len) { 46int
44 const uint8_t *dummy; 47CBS_skip(CBS *cbs, size_t len)
45 return cbs_get(cbs, &dummy, len); 48{
49 const uint8_t *dummy;
50 return cbs_get(cbs, &dummy, len);
46} 51}
47 52
48const uint8_t *CBS_data(const CBS *cbs) { 53const uint8_t *
49 return cbs->data; 54CBS_data(const CBS *cbs)
55{
56 return cbs->data;
50} 57}
51 58
52size_t CBS_len(const CBS *cbs) { 59size_t
53 return cbs->len; 60CBS_len(const CBS *cbs)
61{
62 return cbs->len;
54} 63}
55 64
56int CBS_stow(const CBS *cbs, uint8_t **out_ptr, size_t *out_len) { 65int
57 if (*out_ptr != NULL) { 66CBS_stow(const CBS *cbs, uint8_t **out_ptr, size_t *out_len)
58 free(*out_ptr); 67{
59 *out_ptr = NULL; 68 if (*out_ptr != NULL) {
60 } 69 free(*out_ptr);
61 *out_len = 0; 70 *out_ptr = NULL;
62 71 }
63 if (cbs->len == 0) { 72 *out_len = 0;
64 return 1; 73
65 } 74 if (cbs->len == 0)
66 *out_ptr = BUF_memdup(cbs->data, cbs->len); 75 return 1;
67 if (*out_ptr == NULL) { 76
68 return 0; 77 *out_ptr = BUF_memdup(cbs->data, cbs->len);
69 } 78 if (*out_ptr == NULL)
70 *out_len = cbs->len; 79 return 0;
71 return 1; 80
81 *out_len = cbs->len;
82 return 1;
72} 83}
73 84
74int CBS_strdup(const CBS *cbs, char **out_ptr) { 85int
75 if (*out_ptr != NULL) { 86CBS_strdup(const CBS *cbs, char **out_ptr)
76 free(*out_ptr); 87{
77 } 88 if (*out_ptr != NULL)
78 *out_ptr = strndup((const char*)cbs->data, cbs->len); 89 free(*out_ptr);
79 return (*out_ptr != NULL); 90
91 *out_ptr = strndup((const char*)cbs->data, cbs->len);
92 return (*out_ptr != NULL);
80} 93}
81 94
82int CBS_contains_zero_byte(const CBS *cbs) { 95int
83 return memchr(cbs->data, 0, cbs->len) != NULL; 96CBS_contains_zero_byte(const CBS *cbs)
97{
98 return memchr(cbs->data, 0, cbs->len) != NULL;
84} 99}
85 100
86int CBS_mem_equal(const CBS *cbs, const uint8_t *data, size_t len) { 101int
87 if (len != cbs->len) 102CBS_mem_equal(const CBS *cbs, const uint8_t *data, size_t len)
88 return 0; 103{
89 return CRYPTO_memcmp(cbs->data, data, len) == 0; 104 if (len != cbs->len)
105 return 0;
106
107 return CRYPTO_memcmp(cbs->data, data, len) == 0;
90} 108}
91 109
92static int cbs_get_u(CBS *cbs, uint32_t *out, size_t len) { 110static int
93 uint32_t result = 0; 111cbs_get_u(CBS *cbs, uint32_t *out, size_t len)
94 size_t i; 112{
95 const uint8_t *data; 113 uint32_t result = 0;
96 114 size_t i;
97 if (!cbs_get(cbs, &data, len)) { 115 const uint8_t *data;
98 return 0; 116
99 } 117 if (!cbs_get(cbs, &data, len))
100 for (i = 0; i < len; i++) { 118 return 0;
101 result <<= 8; 119
102 result |= data[i]; 120 for (i = 0; i < len; i++) {
103 } 121 result <<= 8;
104 *out = result; 122 result |= data[i];
105 return 1; 123 }
124 *out = result;
125 return 1;
106} 126}
107 127
108int CBS_get_u8(CBS *cbs, uint8_t *out) { 128int
109 const uint8_t *v; 129CBS_get_u8(CBS *cbs, uint8_t *out)
110 if (!cbs_get(cbs, &v, 1)) { 130{
111 return 0; 131 const uint8_t *v;
112 } 132
113 *out = *v; 133 if (!cbs_get(cbs, &v, 1))
114 return 1; 134 return 0;
135
136 *out = *v;
137 return 1;
115} 138}
116 139
117int CBS_get_u16(CBS *cbs, uint16_t *out) { 140int
118 uint32_t v; 141CBS_get_u16(CBS *cbs, uint16_t *out)
119 if (!cbs_get_u(cbs, &v, 2)) { 142{
120 return 0; 143 uint32_t v;
121 } 144
122 *out = v; 145 if (!cbs_get_u(cbs, &v, 2))
123 return 1; 146 return 0;
147
148 *out = v;
149 return 1;
124} 150}
125 151
126int CBS_get_u24(CBS *cbs, uint32_t *out) { 152int
127 return cbs_get_u(cbs, out, 3); 153CBS_get_u24(CBS *cbs, uint32_t *out)
154{
155 return cbs_get_u(cbs, out, 3);
128} 156}
129 157
130int CBS_get_u32(CBS *cbs, uint32_t *out) { 158int
131 return cbs_get_u(cbs, out, 4); 159CBS_get_u32(CBS *cbs, uint32_t *out)
160{
161 return cbs_get_u(cbs, out, 4);
132} 162}
133 163
134int CBS_get_bytes(CBS *cbs, CBS *out, size_t len) { 164int
135 const uint8_t *v; 165CBS_get_bytes(CBS *cbs, CBS *out, size_t len)
136 if (!cbs_get(cbs, &v, len)) { 166{
137 return 0; 167 const uint8_t *v;
138 } 168
139 CBS_init(out, v, len); 169 if (!cbs_get(cbs, &v, len))
140 return 1; 170 return 0;
171
172 CBS_init(out, v, len);
173 return 1;
141} 174}
142 175
143static int cbs_get_length_prefixed(CBS *cbs, CBS *out, size_t len_len) { 176static int
144 uint32_t len; 177cbs_get_length_prefixed(CBS *cbs, CBS *out, size_t len_len)
145 if (!cbs_get_u(cbs, &len, len_len)) { 178{
146 return 0; 179 uint32_t len;
147 } 180
148 return CBS_get_bytes(cbs, out, len); 181 if (!cbs_get_u(cbs, &len, len_len))
182 return 0;
183
184 return CBS_get_bytes(cbs, out, len);
149} 185}
150 186
151int CBS_get_u8_length_prefixed(CBS *cbs, CBS *out) { 187int
152 return cbs_get_length_prefixed(cbs, out, 1); 188CBS_get_u8_length_prefixed(CBS *cbs, CBS *out)
189{
190 return cbs_get_length_prefixed(cbs, out, 1);
153} 191}
154 192
155int CBS_get_u16_length_prefixed(CBS *cbs, CBS *out) { 193int
156 return cbs_get_length_prefixed(cbs, out, 2); 194CBS_get_u16_length_prefixed(CBS *cbs, CBS *out)
195{
196 return cbs_get_length_prefixed(cbs, out, 2);
157} 197}
158 198
159int CBS_get_u24_length_prefixed(CBS *cbs, CBS *out) { 199int
160 return cbs_get_length_prefixed(cbs, out, 3); 200CBS_get_u24_length_prefixed(CBS *cbs, CBS *out)
201{
202 return cbs_get_length_prefixed(cbs, out, 3);
161} 203}
162 204
163int CBS_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag, 205int
164 size_t *out_header_len) { 206CBS_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
165 uint8_t tag, length_byte; 207 size_t *out_header_len)
166 CBS header = *cbs; 208{
167 CBS throwaway; 209 uint8_t tag, length_byte;
168 210 CBS header = *cbs;
169 if (out == NULL) { 211 CBS throwaway;
170 out = &throwaway; 212
171 } 213 if (out == NULL)
172 214 out = &throwaway;
173 if (!CBS_get_u8(&header, &tag) || 215
174 !CBS_get_u8(&header, &length_byte)) { 216 if (!CBS_get_u8(&header, &tag) || !CBS_get_u8(&header, &length_byte))
175 return 0; 217 return 0;
176 } 218
177 219 if ((tag & 0x1f) == 0x1f)
178 if ((tag & 0x1f) == 0x1f) { 220 /* Long form tags are not supported. */
179 /* Long form tags are not supported. */ 221 return 0;
180 return 0; 222
181 } 223 if (out_tag != NULL)
182 224 *out_tag = tag;
183 if (out_tag != NULL) { 225
184 *out_tag = tag; 226 size_t len;
185 } 227 if ((length_byte & 0x80) == 0) {
186 228 /* Short form length. */
187 size_t len; 229 len = ((size_t) length_byte) + 2;
188 if ((length_byte & 0x80) == 0) { 230 if (out_header_len != NULL)
189 /* Short form length. */ 231 *out_header_len = 2;
190 len = ((size_t) length_byte) + 2; 232
191 if (out_header_len != NULL) { 233 } else {
192 *out_header_len = 2; 234 /* Long form length. */
193 } 235 const size_t num_bytes = length_byte & 0x7f;
194 } else { 236 uint32_t len32;
195 /* Long form length. */ 237
196 const size_t num_bytes = length_byte & 0x7f; 238 if ((tag & CBS_ASN1_CONSTRUCTED) != 0 && num_bytes == 0) {
197 uint32_t len32; 239 /* indefinite length */
198 240 *out_header_len = 2;
199 if ((tag & CBS_ASN1_CONSTRUCTED) != 0 && num_bytes == 0) { 241 return CBS_get_bytes(cbs, out, 2);
200 /* indefinite length */ 242 }
201 *out_header_len = 2; 243
202 return CBS_get_bytes(cbs, out, 2); 244 if (num_bytes == 0 || num_bytes > 4)
203 } 245 return 0;
204 246
205 if (num_bytes == 0 || num_bytes > 4) { 247 if (!cbs_get_u(&header, &len32, num_bytes))
206 return 0; 248 return 0;
207 } 249
208 if (!cbs_get_u(&header, &len32, num_bytes)) { 250 if (len32 < 128)
209 return 0; 251 /* Length should have used short-form encoding. */
210 } 252 return 0;
211 if (len32 < 128) { 253
212 /* Length should have used short-form encoding. */ 254 if ((len32 >> ((num_bytes-1)*8)) == 0)
213 return 0; 255 /* Length should have been at least one byte shorter. */
214 } 256 return 0;
215 if ((len32 >> ((num_bytes-1)*8)) == 0) { 257
216 /* Length should have been at least one byte shorter. */ 258 len = len32;
217 return 0; 259 if (len + 2 + num_bytes < len)
218 } 260 /* Overflow. */
219 len = len32; 261 return 0;
220 if (len + 2 + num_bytes < len) { 262
221 /* Overflow. */ 263 len += 2 + num_bytes;
222 return 0; 264 if (out_header_len != NULL)
223 } 265 *out_header_len = 2 + num_bytes;
224 len += 2 + num_bytes; 266 }
225 if (out_header_len != NULL) { 267
226 *out_header_len = 2 + num_bytes; 268 return CBS_get_bytes(cbs, out, len);
227 }
228 }
229
230 return CBS_get_bytes(cbs, out, len);
231} 269}
232 270
233static int cbs_get_asn1(CBS *cbs, CBS *out, unsigned tag_value, 271static int
234 int skip_header) { 272cbs_get_asn1(CBS *cbs, CBS *out, unsigned tag_value, int skip_header)
235 size_t header_len; 273{
236 unsigned tag; 274 size_t header_len;
237 CBS throwaway; 275 unsigned tag;
238 276 CBS throwaway;
239 if (out == NULL) { 277
240 out = &throwaway; 278 if (out == NULL)
241 } 279 out = &throwaway;
242 280
243 if (!CBS_get_any_asn1_element(cbs, out, &tag, &header_len) || 281 if (!CBS_get_any_asn1_element(cbs, out, &tag, &header_len) ||
244 tag != tag_value || 282 tag != tag_value || (header_len > 0 &&
245 (header_len > 0 && 283 /*
246 /* This ensures that the tag is either zero length or 284 * This ensures that the tag is either zero length or
247 * indefinite-length. */ 285 * indefinite-length.
248 CBS_len(out) == header_len && 286 */
249 CBS_data(out)[header_len - 1] == 0x80)) { 287 CBS_len(out) == header_len &&
250 return 0; 288 CBS_data(out)[header_len - 1] == 0x80))
251 } 289 return 0;
252 290
253 if (skip_header && !CBS_skip(out, header_len)) { 291 if (skip_header && !CBS_skip(out, header_len)) {
254 assert(0); 292 assert(0);
255 return 0; 293 return 0;
256 } 294 }
257 295
258 return 1; 296 return 1;
259} 297}
260 298
261int CBS_get_asn1(CBS *cbs, CBS *out, unsigned tag_value) { 299int
262 return cbs_get_asn1(cbs, out, tag_value, 1 /* skip header */); 300CBS_get_asn1(CBS *cbs, CBS *out, unsigned tag_value)
301{
302 return cbs_get_asn1(cbs, out, tag_value, 1 /* skip header */);
263} 303}
264 304
265int CBS_get_asn1_element(CBS *cbs, CBS *out, unsigned tag_value) { 305int
266 return cbs_get_asn1(cbs, out, tag_value, 0 /* include header */); 306CBS_get_asn1_element(CBS *cbs, CBS *out, unsigned tag_value)
307{
308 return cbs_get_asn1(cbs, out, tag_value, 0 /* include header */);
267} 309}
268 310
269int CBS_peek_asn1_tag(const CBS *cbs, unsigned tag_value) { 311int
270 if (CBS_len(cbs) < 1) { 312CBS_peek_asn1_tag(const CBS *cbs, unsigned tag_value)
271 return 0; 313{
272 } 314 if (CBS_len(cbs) < 1)
273 return CBS_data(cbs)[0] == tag_value; 315 return 0;
316
317 return CBS_data(cbs)[0] == tag_value;
274} 318}
275 319
276int CBS_get_asn1_uint64(CBS *cbs, uint64_t *out) { 320int
277 CBS bytes; 321CBS_get_asn1_uint64(CBS *cbs, uint64_t *out)
278 const uint8_t *data; 322{
279 size_t i, len; 323 CBS bytes;
280 324 const uint8_t *data;
281 if (!CBS_get_asn1(cbs, &bytes, CBS_ASN1_INTEGER)) { 325 size_t i, len;
282 return 0; 326
283 } 327 if (!CBS_get_asn1(cbs, &bytes, CBS_ASN1_INTEGER))
284 328 return 0;
285 *out = 0; 329
286 data = CBS_data(&bytes); 330 *out = 0;
287 len = CBS_len(&bytes); 331 data = CBS_data(&bytes);
288 332 len = CBS_len(&bytes);
289 if (len == 0) { 333
290 /* An INTEGER is encoded with at least one octet. */ 334 if (len == 0)
291 return 0; 335 /* An INTEGER is encoded with at least one octet. */
292 } 336 return 0;
293 337
294 if ((data[0] & 0x80) != 0) { 338 if ((data[0] & 0x80) != 0)
295 /* negative number */ 339 /* negative number */
296 return 0; 340 return 0;
297 } 341
298 342 for (i = 0; i < len; i++) {
299 for (i = 0; i < len; i++) { 343 if ((*out >> 56) != 0)
300 if ((*out >> 56) != 0) { 344 /* Too large to represent as a uint64_t. */
301 /* Too large to represent as a uint64_t. */ 345 return 0;
302 return 0; 346
303 } 347 *out <<= 8;
304 *out <<= 8; 348 *out |= data[i];
305 *out |= data[i]; 349 }
306 } 350
307 351 return 1;
308 return 1;
309} 352}
310 353
311int CBS_get_optional_asn1(CBS *cbs, CBS *out, int *out_present, unsigned tag) { 354int
312 if (CBS_peek_asn1_tag(cbs, tag)) { 355CBS_get_optional_asn1(CBS *cbs, CBS *out, int *out_present, unsigned tag)
313 if (!CBS_get_asn1(cbs, out, tag)) { 356{
314 return 0; 357 if (CBS_peek_asn1_tag(cbs, tag)) {
315 } 358 if (!CBS_get_asn1(cbs, out, tag))
316 *out_present = 1; 359 return 0;
317 } else { 360
318 *out_present = 0; 361 *out_present = 1;
319 } 362 } else {
320 return 1; 363 *out_present = 0;
364 }
365 return 1;
321} 366}
322 367
323int CBS_get_optional_asn1_octet_string(CBS *cbs, CBS *out, int *out_present, 368int
324 unsigned tag) { 369CBS_get_optional_asn1_octet_string(CBS *cbs, CBS *out, int *out_present,
325 CBS child; 370 unsigned tag)
326 int present; 371{
327 if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) { 372 CBS child;
328 return 0; 373 int present;
329 } 374
330 if (present) { 375 if (!CBS_get_optional_asn1(cbs, &child, &present, tag))
331 if (!CBS_get_asn1(&child, out, CBS_ASN1_OCTETSTRING) || 376 return 0;
332 CBS_len(&child) != 0) { 377
333 return 0; 378 if (present) {
334 } 379 if (!CBS_get_asn1(&child, out, CBS_ASN1_OCTETSTRING) ||
335 } else { 380 CBS_len(&child) != 0)
336 CBS_init(out, NULL, 0); 381 return 0;
337 } 382 } else {
338 if (out_present) { 383 CBS_init(out, NULL, 0);
339 *out_present = present; 384 }
340 } 385 if (out_present)
341 return 1; 386 *out_present = present;
387
388 return 1;
342} 389}
343 390
344int CBS_get_optional_asn1_uint64(CBS *cbs, uint64_t *out, unsigned tag, 391int
345 uint64_t default_value) { 392CBS_get_optional_asn1_uint64(CBS *cbs, uint64_t *out, unsigned tag,
346 CBS child; 393 uint64_t default_value)
347 int present; 394{
348 if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) { 395 CBS child;
349 return 0; 396 int present;
350 } 397
351 if (present) { 398 if (!CBS_get_optional_asn1(cbs, &child, &present, tag))
352 if (!CBS_get_asn1_uint64(&child, out) || 399 return 0;
353 CBS_len(&child) != 0) { 400
354 return 0; 401 if (present) {
355 } 402 if (!CBS_get_asn1_uint64(&child, out) ||
356 } else { 403 CBS_len(&child) != 0)
357 *out = default_value; 404 return 0;
358 } 405 } else {
359 return 1; 406 *out = default_value;
407 }
408 return 1;
360} 409}
361 410
362int CBS_get_optional_asn1_bool(CBS *cbs, int *out, unsigned tag, 411int
363 int default_value) { 412CBS_get_optional_asn1_bool(CBS *cbs, int *out, unsigned tag, int default_value)
364 CBS child, child2; 413{
365 int present; 414 CBS child, child2;
366 if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) { 415 int present;
367 return 0; 416
368 } 417 if (!CBS_get_optional_asn1(cbs, &child, &present, tag))
369 if (present) { 418 return 0;
370 uint8_t boolean; 419
371 420 if (present) {
372 if (!CBS_get_asn1(&child, &child2, CBS_ASN1_BOOLEAN) || 421 uint8_t boolean;
373 CBS_len(&child2) != 1 || 422
374 CBS_len(&child) != 0) { 423 if (!CBS_get_asn1(&child, &child2, CBS_ASN1_BOOLEAN) ||
375 return 0; 424 CBS_len(&child2) != 1 || CBS_len(&child) != 0)
376 } 425 return 0;
377 426
378 boolean = CBS_data(&child2)[0]; 427 boolean = CBS_data(&child2)[0];
379 if (boolean == 0) { 428 if (boolean == 0)
380 *out = 0; 429 *out = 0;
381 } else if (boolean == 0xff) { 430 else if (boolean == 0xff)
382 *out = 1; 431 *out = 1;
383 } else { 432 else
384 return 0; 433 return 0;
385 } 434
386 } else { 435 } else {
387 *out = default_value; 436 *out = default_value;
388 } 437 }
389 return 1; 438 return 1;
390} 439}