xref: /openbsd-src/lib/libssl/bs_cbs.c (revision d0fc3bb68efd6c434b4053cd7adb29023cbec341)
1 /*	$OpenBSD: bs_cbs.c,v 1.20 2021/05/16 10:58:27 jsing Exp $	*/
2 /*
3  * Copyright (c) 2014, Google Inc.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
14  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
15  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <stdlib.h>
19 #include <string.h>
20 
21 #include "bytestring.h"
22 
23 void
24 CBS_init(CBS *cbs, const uint8_t *data, size_t len)
25 {
26 	cbs->data = data;
27 	cbs->initial_len = len;
28 	cbs->len = len;
29 }
30 
31 void
32 CBS_dup(const CBS *cbs, CBS *out)
33 {
34 	CBS_init(out, CBS_data(cbs), CBS_len(cbs));
35 	out->initial_len = cbs->initial_len;
36 }
37 
38 static int
39 cbs_get(CBS *cbs, const uint8_t **p, size_t n)
40 {
41 	if (cbs->len < n)
42 		return 0;
43 
44 	*p = cbs->data;
45 	cbs->data += n;
46 	cbs->len -= n;
47 	return 1;
48 }
49 
50 size_t
51 CBS_offset(const CBS *cbs)
52 {
53 	return cbs->initial_len - cbs->len;
54 }
55 
56 int
57 CBS_skip(CBS *cbs, size_t len)
58 {
59 	const uint8_t *dummy;
60 	return cbs_get(cbs, &dummy, len);
61 }
62 
63 const uint8_t *
64 CBS_data(const CBS *cbs)
65 {
66 	return cbs->data;
67 }
68 
69 size_t
70 CBS_len(const CBS *cbs)
71 {
72 	return cbs->len;
73 }
74 
75 int
76 CBS_stow(const CBS *cbs, uint8_t **out_ptr, size_t *out_len)
77 {
78 	free(*out_ptr);
79 	*out_ptr = NULL;
80 	*out_len = 0;
81 
82 	if (cbs->len == 0)
83 		return 1;
84 
85 	if ((*out_ptr = malloc(cbs->len)) == NULL)
86 		return 0;
87 
88 	memcpy(*out_ptr, cbs->data, cbs->len);
89 
90 	*out_len = cbs->len;
91 	return 1;
92 }
93 
94 int
95 CBS_strdup(const CBS *cbs, char **out_ptr)
96 {
97 	free(*out_ptr);
98 	*out_ptr = strndup((const char *)cbs->data, cbs->len);
99 	return (*out_ptr != NULL);
100 }
101 
102 int
103 CBS_write_bytes(const CBS *cbs, uint8_t *dst, size_t dst_len, size_t *copied)
104 {
105 	if (dst_len < cbs->len)
106 		return 0;
107 
108 	memmove(dst, cbs->data, cbs->len);
109 
110 	if (copied != NULL)
111 		*copied = cbs->len;
112 
113 	return 1;
114 }
115 
116 int
117 CBS_contains_zero_byte(const CBS *cbs)
118 {
119 	return memchr(cbs->data, 0, cbs->len) != NULL;
120 }
121 
122 int
123 CBS_mem_equal(const CBS *cbs, const uint8_t *data, size_t len)
124 {
125 	if (len != cbs->len)
126 		return 0;
127 
128 	return timingsafe_memcmp(cbs->data, data, len) == 0;
129 }
130 
131 static int
132 cbs_get_u(CBS *cbs, uint32_t *out, size_t len)
133 {
134 	uint32_t result = 0;
135 	size_t i;
136 	const uint8_t *data;
137 
138 	if (len < 1 || len > 4)
139 		return 0;
140 
141 	if (!cbs_get(cbs, &data, len))
142 		return 0;
143 
144 	for (i = 0; i < len; i++) {
145 		result <<= 8;
146 		result |= data[i];
147 	}
148 	*out = result;
149 	return 1;
150 }
151 
152 int
153 CBS_get_u8(CBS *cbs, uint8_t *out)
154 {
155 	const uint8_t *v;
156 
157 	if (!cbs_get(cbs, &v, 1))
158 		return 0;
159 
160 	*out = *v;
161 	return 1;
162 }
163 
164 int
165 CBS_get_u16(CBS *cbs, uint16_t *out)
166 {
167 	uint32_t v;
168 
169 	if (!cbs_get_u(cbs, &v, 2))
170 		return 0;
171 
172 	*out = v;
173 	return 1;
174 }
175 
176 int
177 CBS_get_u24(CBS *cbs, uint32_t *out)
178 {
179 	return cbs_get_u(cbs, out, 3);
180 }
181 
182 int
183 CBS_get_u32(CBS *cbs, uint32_t *out)
184 {
185 	return cbs_get_u(cbs, out, 4);
186 }
187 
188 int
189 CBS_get_bytes(CBS *cbs, CBS *out, size_t len)
190 {
191 	const uint8_t *v;
192 
193 	if (!cbs_get(cbs, &v, len))
194 		return 0;
195 
196 	CBS_init(out, v, len);
197 	return 1;
198 }
199 
200 static int
201 cbs_get_length_prefixed(CBS *cbs, CBS *out, size_t len_len)
202 {
203 	uint32_t len;
204 
205 	if (!cbs_get_u(cbs, &len, len_len))
206 		return 0;
207 
208 	return CBS_get_bytes(cbs, out, len);
209 }
210 
211 int
212 CBS_get_u8_length_prefixed(CBS *cbs, CBS *out)
213 {
214 	return cbs_get_length_prefixed(cbs, out, 1);
215 }
216 
217 int
218 CBS_get_u16_length_prefixed(CBS *cbs, CBS *out)
219 {
220 	return cbs_get_length_prefixed(cbs, out, 2);
221 }
222 
223 int
224 CBS_get_u24_length_prefixed(CBS *cbs, CBS *out)
225 {
226 	return cbs_get_length_prefixed(cbs, out, 3);
227 }
228 
229 int
230 CBS_get_any_asn1_element(CBS *cbs, CBS *out, unsigned int *out_tag,
231     size_t *out_header_len)
232 {
233 	return cbs_get_any_asn1_element_internal(cbs, out, out_tag,
234 	    out_header_len, 1);
235 }
236 
237 /*
238  * Review X.690 for details on ASN.1 DER encoding.
239  *
240  * If non-strict mode is enabled, then DER rules are relaxed
241  * for indefinite constructs (violates DER but a little closer to BER).
242  * Non-strict mode should only be used by bs_ber.c
243  *
244  * Sections 8, 10 and 11 for DER encoding
245  */
246 int
247 cbs_get_any_asn1_element_internal(CBS *cbs, CBS *out, unsigned int *out_tag,
248     size_t *out_header_len, int strict)
249 {
250 	uint8_t tag, length_byte;
251 	CBS header = *cbs;
252 	CBS throwaway;
253 	size_t len;
254 
255 	if (out == NULL)
256 		out = &throwaway;
257 
258 	/*
259 	 * Get identifier octet and length octet.  Only 1 octet for each
260 	 * is a CBS limitation.
261 	 */
262 	if (!CBS_get_u8(&header, &tag) || !CBS_get_u8(&header, &length_byte))
263 		return 0;
264 
265 	/* CBS limitation: long form tags are not supported. */
266 	if ((tag & 0x1f) == 0x1f)
267 		return 0;
268 
269 	if (out_tag != NULL)
270 		*out_tag = tag;
271 
272 	if ((length_byte & 0x80) == 0) {
273 		/* Short form length. */
274 		len = ((size_t) length_byte) + 2;
275 		if (out_header_len != NULL)
276 			*out_header_len = 2;
277 
278 	} else {
279 		/* Long form length. */
280 		const size_t num_bytes = length_byte & 0x7f;
281 		uint32_t len32;
282 
283 		/* ASN.1 reserved value for future extensions */
284 		if (num_bytes == 0x7f)
285 			return 0;
286 
287 		/* Handle indefinite form length */
288 		if (num_bytes == 0) {
289 			/* DER encoding doesn't allow for indefinite form. */
290 			if (strict)
291 				return 0;
292 
293 			/* Primitive cannot use indefinite in BER or DER. */
294 			if ((tag & CBS_ASN1_CONSTRUCTED) == 0)
295 				return 0;
296 
297 			/* Constructed, indefinite length allowed in BER. */
298 			if (out_header_len != NULL)
299 				*out_header_len = 2;
300 			return CBS_get_bytes(cbs, out, 2);
301 		}
302 
303 		/* CBS limitation. */
304 		if (num_bytes > 4)
305 			return 0;
306 
307 		if (!cbs_get_u(&header, &len32, num_bytes))
308 			return 0;
309 
310 		/* DER has a minimum length octet requirement. */
311 		if (len32 < 128)
312 			/* Should have used short form instead */
313 			return 0;
314 
315 		if ((len32 >> ((num_bytes - 1) * 8)) == 0)
316 			/* Length should have been at least one byte shorter. */
317 			return 0;
318 
319 		len = len32;
320 		if (len + 2 + num_bytes < len)
321 			/* Overflow. */
322 			return 0;
323 
324 		len += 2 + num_bytes;
325 		if (out_header_len != NULL)
326 			*out_header_len = 2 + num_bytes;
327 	}
328 
329 	return CBS_get_bytes(cbs, out, len);
330 }
331 
332 static int
333 cbs_get_asn1(CBS *cbs, CBS *out, unsigned int tag_value, int skip_header)
334 {
335 	size_t header_len;
336 	unsigned int tag;
337 	CBS throwaway;
338 
339 	if (out == NULL)
340 		out = &throwaway;
341 
342 	if (!CBS_get_any_asn1_element(cbs, out, &tag, &header_len) ||
343 	    tag != tag_value)
344 		return 0;
345 
346 	if (skip_header && !CBS_skip(out, header_len))
347 		return 0;
348 
349 	return 1;
350 }
351 
352 int
353 CBS_get_asn1(CBS *cbs, CBS *out, unsigned int tag_value)
354 {
355 	return cbs_get_asn1(cbs, out, tag_value, 1 /* skip header */);
356 }
357 
358 int
359 CBS_get_asn1_element(CBS *cbs, CBS *out, unsigned int tag_value)
360 {
361 	return cbs_get_asn1(cbs, out, tag_value, 0 /* include header */);
362 }
363 
364 int
365 CBS_peek_asn1_tag(const CBS *cbs, unsigned int tag_value)
366 {
367 	if (CBS_len(cbs) < 1)
368 		return 0;
369 
370 	/*
371 	 * Tag number 31 indicates the start of a long form number.
372 	 * This is valid in ASN.1, but CBS only supports short form.
373 	 */
374 	if ((tag_value & 0x1f) == 0x1f)
375 		return 0;
376 
377 	return CBS_data(cbs)[0] == tag_value;
378 }
379 
380 /* Encoding details are in ASN.1: X.690 section 8.3 */
381 int
382 CBS_get_asn1_uint64(CBS *cbs, uint64_t *out)
383 {
384 	CBS bytes;
385 	const uint8_t *data;
386 	size_t i, len;
387 
388 	if (!CBS_get_asn1(cbs, &bytes, CBS_ASN1_INTEGER))
389 		return 0;
390 
391 	*out = 0;
392 	data = CBS_data(&bytes);
393 	len = CBS_len(&bytes);
394 
395 	if (len == 0)
396 		/* An INTEGER is encoded with at least one content octet. */
397 		return 0;
398 
399 	if ((data[0] & 0x80) != 0)
400 		/* Negative number. */
401 		return 0;
402 
403 	if (data[0] == 0 && len > 1 && (data[1] & 0x80) == 0)
404 		/* Violates smallest encoding rule: excessive leading zeros. */
405 		return 0;
406 
407 	for (i = 0; i < len; i++) {
408 		if ((*out >> 56) != 0)
409 			/* Too large to represent as a uint64_t. */
410 			return 0;
411 
412 		*out <<= 8;
413 		*out |= data[i];
414 	}
415 
416 	return 1;
417 }
418 
419 int
420 CBS_get_optional_asn1(CBS *cbs, CBS *out, int *out_present, unsigned int tag)
421 {
422 	if (CBS_peek_asn1_tag(cbs, tag)) {
423 		if (!CBS_get_asn1(cbs, out, tag))
424 			return 0;
425 
426 		*out_present = 1;
427 	} else {
428 		*out_present = 0;
429 	}
430 	return 1;
431 }
432 
433 int
434 CBS_get_optional_asn1_octet_string(CBS *cbs, CBS *out, int *out_present,
435     unsigned int tag)
436 {
437 	CBS child;
438 	int present;
439 
440 	if (!CBS_get_optional_asn1(cbs, &child, &present, tag))
441 		return 0;
442 
443 	if (present) {
444 		if (!CBS_get_asn1(&child, out, CBS_ASN1_OCTETSTRING) ||
445 		    CBS_len(&child) != 0)
446 			return 0;
447 	} else {
448 		CBS_init(out, NULL, 0);
449 	}
450 	if (out_present)
451 		*out_present = present;
452 
453 	return 1;
454 }
455 
456 int
457 CBS_get_optional_asn1_uint64(CBS *cbs, uint64_t *out, unsigned int tag,
458     uint64_t default_value)
459 {
460 	CBS child;
461 	int present;
462 
463 	if (!CBS_get_optional_asn1(cbs, &child, &present, tag))
464 		return 0;
465 
466 	if (present) {
467 		if (!CBS_get_asn1_uint64(&child, out) ||
468 		    CBS_len(&child) != 0)
469 			return 0;
470 	} else {
471 		*out = default_value;
472 	}
473 	return 1;
474 }
475 
476 int
477 CBS_get_optional_asn1_bool(CBS *cbs, int *out, unsigned int tag,
478     int default_value)
479 {
480 	CBS child, child2;
481 	int present;
482 
483 	if (!CBS_get_optional_asn1(cbs, &child, &present, tag))
484 		return 0;
485 
486 	if (present) {
487 		uint8_t boolean;
488 
489 		if (!CBS_get_asn1(&child, &child2, CBS_ASN1_BOOLEAN) ||
490 		    CBS_len(&child2) != 1 || CBS_len(&child) != 0)
491 			return 0;
492 
493 		boolean = CBS_data(&child2)[0];
494 		if (boolean == 0)
495 			*out = 0;
496 		else if (boolean == 0xff)
497 			*out = 1;
498 		else
499 			return 0;
500 
501 	} else {
502 		*out = default_value;
503 	}
504 	return 1;
505 }
506