blob: c5f0464421c84277efa84fc63a33303d541b611e [file] [log] [blame]
Adam Langley95c29f32014-06-20 12:00:00 -07001/* 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
Bob Beck652464e2022-06-16 10:49:00 -060015#include <openssl/asn1.h>
Adam Langley95c29f32014-06-20 12:00:00 -070016#include <openssl/bytestring.h>
Bob Beck652464e2022-06-16 10:49:00 -060017#include <openssl/mem.h>
Adam Langley95c29f32014-06-20 12:00:00 -070018
19#include <assert.h>
Bob Beck652464e2022-06-16 10:49:00 -060020#include <ctype.h>
David Benjamin095b6c92017-11-29 17:17:41 -050021#include <inttypes.h>
David Benjamined439582014-07-14 19:13:02 -040022#include <string.h>
Adam Langley95c29f32014-06-20 12:00:00 -070023
Bob Beck652464e2022-06-16 10:49:00 -060024#include "../asn1/internal.h"
David Benjamin17cf2cb2016-12-13 01:07:13 -050025#include "../internal.h"
Bob Beck652464e2022-06-16 10:49:00 -060026#include "internal.h"
Adam Langley9c01e002014-08-21 10:54:06 -070027
Adam Langley95c29f32014-06-20 12:00:00 -070028
Adam Langley95c29f32014-06-20 12:00:00 -070029static int cbs_get(CBS *cbs, const uint8_t **p, size_t n) {
30 if (cbs->len < n) {
31 return 0;
32 }
33
34 *p = cbs->data;
35 cbs->data += n;
36 cbs->len -= n;
37 return 1;
38}
39
40int CBS_skip(CBS *cbs, size_t len) {
41 const uint8_t *dummy;
42 return cbs_get(cbs, &dummy, len);
43}
44
David Benjamin03973092014-06-24 23:27:17 -040045int CBS_stow(const CBS *cbs, uint8_t **out_ptr, size_t *out_len) {
David Benjamin22ccc2d2015-04-22 13:50:28 -040046 OPENSSL_free(*out_ptr);
47 *out_ptr = NULL;
David Benjamin03973092014-06-24 23:27:17 -040048 *out_len = 0;
49
50 if (cbs->len == 0) {
51 return 1;
52 }
David Benjamin3ba95862019-10-21 16:14:33 -040053 *out_ptr = OPENSSL_memdup(cbs->data, cbs->len);
David Benjamin03973092014-06-24 23:27:17 -040054 if (*out_ptr == NULL) {
55 return 0;
56 }
57 *out_len = cbs->len;
58 return 1;
59}
60
David Benjamined439582014-07-14 19:13:02 -040061int CBS_strdup(const CBS *cbs, char **out_ptr) {
62 if (*out_ptr != NULL) {
63 OPENSSL_free(*out_ptr);
64 }
David Benjamin3ba95862019-10-21 16:14:33 -040065 *out_ptr = OPENSSL_strndup((const char*)cbs->data, cbs->len);
David Benjamined439582014-07-14 19:13:02 -040066 return (*out_ptr != NULL);
67}
68
69int CBS_contains_zero_byte(const CBS *cbs) {
David Benjamin17cf2cb2016-12-13 01:07:13 -050070 return OPENSSL_memchr(cbs->data, 0, cbs->len) != NULL;
David Benjamin03973092014-06-24 23:27:17 -040071}
72
David Benjamin22f9bcc2014-07-13 12:29:21 -040073int CBS_mem_equal(const CBS *cbs, const uint8_t *data, size_t len) {
David Benjaminc9a202f2015-02-11 01:16:26 -050074 if (len != cbs->len) {
David Benjamin22f9bcc2014-07-13 12:29:21 -040075 return 0;
David Benjaminc9a202f2015-02-11 01:16:26 -050076 }
David Benjamin22f9bcc2014-07-13 12:29:21 -040077 return CRYPTO_memcmp(cbs->data, data, len) == 0;
78}
79
Kaustubha Govindc18353d2019-02-21 12:40:06 -050080static int cbs_get_u(CBS *cbs, uint64_t *out, size_t len) {
81 uint64_t result = 0;
Adam Langley95c29f32014-06-20 12:00:00 -070082 const uint8_t *data;
83
84 if (!cbs_get(cbs, &data, len)) {
85 return 0;
86 }
David Benjamin54091232016-09-05 12:47:25 -040087 for (size_t i = 0; i < len; i++) {
Adam Langley95c29f32014-06-20 12:00:00 -070088 result <<= 8;
89 result |= data[i];
90 }
91 *out = result;
92 return 1;
93}
94
95int CBS_get_u8(CBS *cbs, uint8_t *out) {
96 const uint8_t *v;
97 if (!cbs_get(cbs, &v, 1)) {
98 return 0;
99 }
100 *out = *v;
101 return 1;
102}
103
104int CBS_get_u16(CBS *cbs, uint16_t *out) {
Kaustubha Govindc18353d2019-02-21 12:40:06 -0500105 uint64_t v;
Adam Langley95c29f32014-06-20 12:00:00 -0700106 if (!cbs_get_u(cbs, &v, 2)) {
107 return 0;
108 }
109 *out = v;
110 return 1;
111}
112
Adam Langleya965a252020-01-15 16:08:03 -0800113int CBS_get_u16le(CBS *cbs, uint16_t *out) {
114 if (!CBS_get_u16(cbs, out)) {
115 return 0;
116 }
117 *out = CRYPTO_bswap2(*out);
118 return 1;
119}
120
Adam Langley95c29f32014-06-20 12:00:00 -0700121int CBS_get_u24(CBS *cbs, uint32_t *out) {
Kaustubha Govindc18353d2019-02-21 12:40:06 -0500122 uint64_t v;
123 if (!cbs_get_u(cbs, &v, 3)) {
124 return 0;
125 }
David Benjamin7ac94aa2022-10-24 15:44:37 -0400126 *out = (uint32_t)v;
Kaustubha Govindc18353d2019-02-21 12:40:06 -0500127 return 1;
Adam Langley95c29f32014-06-20 12:00:00 -0700128}
129
130int CBS_get_u32(CBS *cbs, uint32_t *out) {
Kaustubha Govindc18353d2019-02-21 12:40:06 -0500131 uint64_t v;
132 if (!cbs_get_u(cbs, &v, 4)) {
133 return 0;
134 }
David Benjamin7ac94aa2022-10-24 15:44:37 -0400135 *out = (uint32_t)v;
Kaustubha Govindc18353d2019-02-21 12:40:06 -0500136 return 1;
137}
138
Adam Langleya965a252020-01-15 16:08:03 -0800139int CBS_get_u32le(CBS *cbs, uint32_t *out) {
140 if (!CBS_get_u32(cbs, out)) {
141 return 0;
142 }
143 *out = CRYPTO_bswap4(*out);
144 return 1;
145}
146
Kaustubha Govindc18353d2019-02-21 12:40:06 -0500147int CBS_get_u64(CBS *cbs, uint64_t *out) {
148 return cbs_get_u(cbs, out, 8);
Adam Langley95c29f32014-06-20 12:00:00 -0700149}
150
Adam Langleya965a252020-01-15 16:08:03 -0800151int CBS_get_u64le(CBS *cbs, uint64_t *out) {
152 if (!cbs_get_u(cbs, out, 8)) {
153 return 0;
154 }
155 *out = CRYPTO_bswap8(*out);
156 return 1;
157}
158
David Benjamina7810c12016-06-06 18:54:51 -0400159int CBS_get_last_u8(CBS *cbs, uint8_t *out) {
160 if (cbs->len == 0) {
161 return 0;
162 }
163 *out = cbs->data[cbs->len - 1];
164 cbs->len--;
165 return 1;
166}
167
Adam Langley95c29f32014-06-20 12:00:00 -0700168int CBS_get_bytes(CBS *cbs, CBS *out, size_t len) {
169 const uint8_t *v;
170 if (!cbs_get(cbs, &v, len)) {
171 return 0;
172 }
173 CBS_init(out, v, len);
174 return 1;
175}
176
David Benjaminb8d28cf2015-07-28 21:34:45 -0400177int CBS_copy_bytes(CBS *cbs, uint8_t *out, size_t len) {
178 const uint8_t *v;
179 if (!cbs_get(cbs, &v, len)) {
180 return 0;
181 }
David Benjamin17cf2cb2016-12-13 01:07:13 -0500182 OPENSSL_memcpy(out, v, len);
David Benjaminb8d28cf2015-07-28 21:34:45 -0400183 return 1;
184}
185
Adam Langley95c29f32014-06-20 12:00:00 -0700186static int cbs_get_length_prefixed(CBS *cbs, CBS *out, size_t len_len) {
Kaustubha Govindc18353d2019-02-21 12:40:06 -0500187 uint64_t len;
Adam Langley95c29f32014-06-20 12:00:00 -0700188 if (!cbs_get_u(cbs, &len, len_len)) {
189 return 0;
190 }
Kaustubha Govindc18353d2019-02-21 12:40:06 -0500191 // If |len_len| <= 3 then we know that |len| will fit into a |size_t|, even on
192 // 32-bit systems.
193 assert(len_len <= 3);
Adam Langley95c29f32014-06-20 12:00:00 -0700194 return CBS_get_bytes(cbs, out, len);
195}
196
197int CBS_get_u8_length_prefixed(CBS *cbs, CBS *out) {
198 return cbs_get_length_prefixed(cbs, out, 1);
199}
200
201int CBS_get_u16_length_prefixed(CBS *cbs, CBS *out) {
202 return cbs_get_length_prefixed(cbs, out, 2);
203}
204
205int CBS_get_u24_length_prefixed(CBS *cbs, CBS *out) {
206 return cbs_get_length_prefixed(cbs, out, 3);
207}
208
David Benjaminb27438e2021-08-24 14:24:38 -0400209int CBS_get_until_first(CBS *cbs, CBS *out, uint8_t c) {
210 const uint8_t *split = OPENSSL_memchr(CBS_data(cbs), c, CBS_len(cbs));
211 if (split == NULL) {
212 return 0;
213 }
214 return CBS_get_bytes(cbs, out, split - CBS_data(cbs));
215}
216
David Benjamin50a5caf2022-12-28 18:33:18 -0500217int CBS_get_u64_decimal(CBS *cbs, uint64_t *out) {
218 uint64_t v = 0;
219 int seen_digit = 0;
220 while (CBS_len(cbs) != 0) {
221 uint8_t c = CBS_data(cbs)[0];
Bob Beckf86a63c2023-01-30 12:17:39 -0700222 if (!OPENSSL_isdigit(c)) {
David Benjamin50a5caf2022-12-28 18:33:18 -0500223 break;
224 }
225 CBS_skip(cbs, 1);
226 if (// Forbid stray leading zeros.
227 (v == 0 && seen_digit) ||
228 // Check for overflow.
229 v > UINT64_MAX / 10 || //
230 v * 10 > UINT64_MAX - (c - '0')) {
231 return 0;
232 }
233 v = v * 10 + (c - '0');
234 seen_digit = 1;
235 }
236
237 *out = v;
238 return seen_digit;
239}
240
David Benjamin095b6c92017-11-29 17:17:41 -0500241// parse_base128_integer reads a big-endian base-128 integer from |cbs| and sets
242// |*out| to the result. This is the encoding used in DER for both high tag
243// number form and OID components.
244static int parse_base128_integer(CBS *cbs, uint64_t *out) {
245 uint64_t v = 0;
246 uint8_t b;
247 do {
248 if (!CBS_get_u8(cbs, &b)) {
249 return 0;
250 }
251 if ((v >> (64 - 7)) != 0) {
252 // The value is too large.
253 return 0;
254 }
255 if (v == 0 && b == 0x80) {
256 // The value must be minimally encoded.
257 return 0;
258 }
259 v = (v << 7) | (b & 0x7f);
260
261 // Values end at an octet with the high bit cleared.
262 } while (b & 0x80);
263
264 *out = v;
265 return 1;
266}
267
David Benjamina1dffbf2022-10-25 16:29:43 -0400268static int parse_asn1_tag(CBS *cbs, CBS_ASN1_TAG *out) {
David Benjamind9f49972017-12-21 23:11:23 -0500269 uint8_t tag_byte;
270 if (!CBS_get_u8(cbs, &tag_byte)) {
Adam Langley95c29f32014-06-20 12:00:00 -0700271 return 0;
272 }
273
David Benjamin808f8322017-08-18 14:06:02 -0400274 // ITU-T X.690 section 8.1.2.3 specifies the format for identifiers with a tag
275 // number no greater than 30.
276 //
277 // If the number portion is 31 (0x1f, the largest value that fits in the
278 // allotted bits), then the tag is more than one byte long and the
Adam Langleye56dfcf2020-12-16 15:11:27 -0800279 // continuation bytes contain the tag number.
David Benjamina1dffbf2022-10-25 16:29:43 -0400280 CBS_ASN1_TAG tag = ((CBS_ASN1_TAG)tag_byte & 0xe0) << CBS_ASN1_TAG_SHIFT;
281 CBS_ASN1_TAG tag_number = tag_byte & 0x1f;
David Benjamind9f49972017-12-21 23:11:23 -0500282 if (tag_number == 0x1f) {
283 uint64_t v;
284 if (!parse_base128_integer(cbs, &v) ||
285 // Check the tag number is within our supported bounds.
286 v > CBS_ASN1_TAG_NUMBER_MASK ||
Adam Langleye56dfcf2020-12-16 15:11:27 -0800287 // Small tag numbers should have used low tag number form, even in BER.
David Benjamind9f49972017-12-21 23:11:23 -0500288 v < 0x1f) {
289 return 0;
290 }
David Benjamina1dffbf2022-10-25 16:29:43 -0400291 tag_number = (CBS_ASN1_TAG)v;
David Benjamin66801fe2017-11-21 16:25:12 -0500292 }
David Benjamin2fc4f362017-11-30 16:41:24 -0500293
David Benjamind9f49972017-12-21 23:11:23 -0500294 tag |= tag_number;
295
David Benjaminedbdc242021-11-02 11:37:22 -0400296 // Tag [UNIVERSAL 0] is reserved for use by the encoding. Reject it here to
297 // avoid some ambiguity around ANY values and BER indefinite-length EOCs. See
298 // https://crbug.com/boringssl/455.
299 if ((tag & ~CBS_ASN1_CONSTRUCTED) == 0) {
300 return 0;
301 }
302
David Benjamind9f49972017-12-21 23:11:23 -0500303 *out = tag;
304 return 1;
305}
306
David Benjamina1dffbf2022-10-25 16:29:43 -0400307static int cbs_get_any_asn1_element(CBS *cbs, CBS *out, CBS_ASN1_TAG *out_tag,
Adam Langleye56dfcf2020-12-16 15:11:27 -0800308 size_t *out_header_len, int *out_ber_found,
David Benjamin7fac3862021-10-30 12:37:44 -0400309 int *out_indefinite, int ber_ok) {
David Benjamind9f49972017-12-21 23:11:23 -0500310 CBS header = *cbs;
311 CBS throwaway;
312
313 if (out == NULL) {
314 out = &throwaway;
315 }
Adam Langleye56dfcf2020-12-16 15:11:27 -0800316 if (ber_ok) {
317 *out_ber_found = 0;
David Benjamin7fac3862021-10-30 12:37:44 -0400318 *out_indefinite = 0;
319 } else {
320 assert(out_ber_found == NULL);
321 assert(out_indefinite == NULL);
Adam Langleye56dfcf2020-12-16 15:11:27 -0800322 }
David Benjamind9f49972017-12-21 23:11:23 -0500323
David Benjamina1dffbf2022-10-25 16:29:43 -0400324 CBS_ASN1_TAG tag;
David Benjamind9f49972017-12-21 23:11:23 -0500325 if (!parse_asn1_tag(&header, &tag)) {
326 return 0;
327 }
David Benjamin9b04d652014-08-27 20:19:50 -0400328 if (out_tag != NULL) {
329 *out_tag = tag;
330 }
Adam Langley95c29f32014-06-20 12:00:00 -0700331
David Benjamind9f49972017-12-21 23:11:23 -0500332 uint8_t length_byte;
333 if (!CBS_get_u8(&header, &length_byte)) {
334 return 0;
335 }
336
337 size_t header_len = CBS_len(cbs) - CBS_len(&header);
338
Adam Langley95c29f32014-06-20 12:00:00 -0700339 size_t len;
David Benjamin808f8322017-08-18 14:06:02 -0400340 // The format for the length encoding is specified in ITU-T X.690 section
341 // 8.1.3.
Adam Langley95c29f32014-06-20 12:00:00 -0700342 if ((length_byte & 0x80) == 0) {
David Benjamin808f8322017-08-18 14:06:02 -0400343 // Short form length.
David Benjamind9f49972017-12-21 23:11:23 -0500344 len = ((size_t) length_byte) + header_len;
David Benjamin9b04d652014-08-27 20:19:50 -0400345 if (out_header_len != NULL) {
David Benjamind9f49972017-12-21 23:11:23 -0500346 *out_header_len = header_len;
David Benjamin9b04d652014-08-27 20:19:50 -0400347 }
Adam Langley95c29f32014-06-20 12:00:00 -0700348 } else {
David Benjamin808f8322017-08-18 14:06:02 -0400349 // The high bit indicate that this is the long form, while the next 7 bits
350 // encode the number of subsequent octets used to encode the length (ITU-T
351 // X.690 clause 8.1.3.5.b).
Adam Langley95c29f32014-06-20 12:00:00 -0700352 const size_t num_bytes = length_byte & 0x7f;
Kaustubha Govindc18353d2019-02-21 12:40:06 -0500353 uint64_t len64;
Adam Langley95c29f32014-06-20 12:00:00 -0700354
Adam Langleycc1e3df2015-06-02 15:49:48 -0700355 if (ber_ok && (tag & CBS_ASN1_CONSTRUCTED) != 0 && num_bytes == 0) {
David Benjamin808f8322017-08-18 14:06:02 -0400356 // indefinite length
Adam Langley09760962015-06-02 15:48:37 -0700357 if (out_header_len != NULL) {
David Benjamind9f49972017-12-21 23:11:23 -0500358 *out_header_len = header_len;
Adam Langley09760962015-06-02 15:48:37 -0700359 }
Adam Langleye56dfcf2020-12-16 15:11:27 -0800360 *out_ber_found = 1;
David Benjamin7fac3862021-10-30 12:37:44 -0400361 *out_indefinite = 1;
David Benjamind9f49972017-12-21 23:11:23 -0500362 return CBS_get_bytes(cbs, out, header_len);
Adam Langley95c29f32014-06-20 12:00:00 -0700363 }
364
David Benjamin808f8322017-08-18 14:06:02 -0400365 // ITU-T X.690 clause 8.1.3.5.c specifies that the value 0xff shall not be
366 // used as the first byte of the length. If this parser encounters that
Adam Langleye56dfcf2020-12-16 15:11:27 -0800367 // value, num_bytes will be parsed as 127, which will fail this check.
Adam Langley95c29f32014-06-20 12:00:00 -0700368 if (num_bytes == 0 || num_bytes > 4) {
369 return 0;
370 }
Kaustubha Govindc18353d2019-02-21 12:40:06 -0500371 if (!cbs_get_u(&header, &len64, num_bytes)) {
Adam Langley95c29f32014-06-20 12:00:00 -0700372 return 0;
373 }
Adam Langleye56dfcf2020-12-16 15:11:27 -0800374 // ITU-T X.690 section 10.1 (DER length forms) requires encoding the
375 // length with the minimum number of octets. BER could, technically, have
376 // 125 superfluous zero bytes. We do not attempt to handle that and still
377 // require that the length fit in a |uint32_t| for BER.
Kaustubha Govindc18353d2019-02-21 12:40:06 -0500378 if (len64 < 128) {
David Benjamin808f8322017-08-18 14:06:02 -0400379 // Length should have used short-form encoding.
Adam Langleye56dfcf2020-12-16 15:11:27 -0800380 if (ber_ok) {
381 *out_ber_found = 1;
382 } else {
383 return 0;
384 }
Adam Langley95c29f32014-06-20 12:00:00 -0700385 }
Adam Langleye56dfcf2020-12-16 15:11:27 -0800386 if ((len64 >> ((num_bytes - 1) * 8)) == 0) {
David Benjamin808f8322017-08-18 14:06:02 -0400387 // Length should have been at least one byte shorter.
Adam Langleye56dfcf2020-12-16 15:11:27 -0800388 if (ber_ok) {
389 *out_ber_found = 1;
390 } else {
391 return 0;
392 }
Adam Langley95c29f32014-06-20 12:00:00 -0700393 }
Kaustubha Govindc18353d2019-02-21 12:40:06 -0500394 len = len64;
David Benjamind9f49972017-12-21 23:11:23 -0500395 if (len + header_len + num_bytes < len) {
David Benjamin808f8322017-08-18 14:06:02 -0400396 // Overflow.
Adam Langley95c29f32014-06-20 12:00:00 -0700397 return 0;
398 }
David Benjamind9f49972017-12-21 23:11:23 -0500399 len += header_len + num_bytes;
David Benjamin9b04d652014-08-27 20:19:50 -0400400 if (out_header_len != NULL) {
David Benjamind9f49972017-12-21 23:11:23 -0500401 *out_header_len = header_len + num_bytes;
David Benjamin9b04d652014-08-27 20:19:50 -0400402 }
Adam Langley95c29f32014-06-20 12:00:00 -0700403 }
404
405 return CBS_get_bytes(cbs, out, len);
406}
407
David Benjamina1dffbf2022-10-25 16:29:43 -0400408int CBS_get_any_asn1(CBS *cbs, CBS *out, CBS_ASN1_TAG *out_tag) {
David Benjamin455919d2016-09-30 15:05:32 -0400409 size_t header_len;
410 if (!CBS_get_any_asn1_element(cbs, out, out_tag, &header_len)) {
411 return 0;
412 }
413
414 if (!CBS_skip(out, header_len)) {
415 assert(0);
416 return 0;
417 }
418
419 return 1;
420}
421
David Benjamina1dffbf2022-10-25 16:29:43 -0400422int CBS_get_any_asn1_element(CBS *cbs, CBS *out, CBS_ASN1_TAG *out_tag,
Adam Langleycc1e3df2015-06-02 15:49:48 -0700423 size_t *out_header_len) {
David Benjamin7fac3862021-10-30 12:37:44 -0400424 return cbs_get_any_asn1_element(cbs, out, out_tag, out_header_len, NULL, NULL,
425 /*ber_ok=*/0);
Adam Langleycc1e3df2015-06-02 15:49:48 -0700426}
427
David Benjamina1dffbf2022-10-25 16:29:43 -0400428int CBS_get_any_ber_asn1_element(CBS *cbs, CBS *out, CBS_ASN1_TAG *out_tag,
David Benjamin7fac3862021-10-30 12:37:44 -0400429 size_t *out_header_len, int *out_ber_found,
430 int *out_indefinite) {
Adam Langleye56dfcf2020-12-16 15:11:27 -0800431 int ber_found_temp;
432 return cbs_get_any_asn1_element(
433 cbs, out, out_tag, out_header_len,
David Benjamin7fac3862021-10-30 12:37:44 -0400434 out_ber_found ? out_ber_found : &ber_found_temp, out_indefinite,
435 /*ber_ok=*/1);
Adam Langleycc1e3df2015-06-02 15:49:48 -0700436}
437
David Benjamina1dffbf2022-10-25 16:29:43 -0400438static int cbs_get_asn1(CBS *cbs, CBS *out, CBS_ASN1_TAG tag_value,
Adam Langley95c29f32014-06-20 12:00:00 -0700439 int skip_header) {
440 size_t header_len;
David Benjamina1dffbf2022-10-25 16:29:43 -0400441 CBS_ASN1_TAG tag;
Adam Langley95c29f32014-06-20 12:00:00 -0700442 CBS throwaway;
443
444 if (out == NULL) {
445 out = &throwaway;
446 }
447
Adam Langley9c01e002014-08-21 10:54:06 -0700448 if (!CBS_get_any_asn1_element(cbs, out, &tag, &header_len) ||
Adam Langleycc1e3df2015-06-02 15:49:48 -0700449 tag != tag_value) {
Adam Langley95c29f32014-06-20 12:00:00 -0700450 return 0;
451 }
452
453 if (skip_header && !CBS_skip(out, header_len)) {
454 assert(0);
455 return 0;
456 }
457
458 return 1;
459}
460
David Benjamina1dffbf2022-10-25 16:29:43 -0400461int CBS_get_asn1(CBS *cbs, CBS *out, CBS_ASN1_TAG tag_value) {
Adam Langley9c01e002014-08-21 10:54:06 -0700462 return cbs_get_asn1(cbs, out, tag_value, 1 /* skip header */);
Adam Langley95c29f32014-06-20 12:00:00 -0700463}
464
David Benjamina1dffbf2022-10-25 16:29:43 -0400465int CBS_get_asn1_element(CBS *cbs, CBS *out, CBS_ASN1_TAG tag_value) {
Adam Langley9c01e002014-08-21 10:54:06 -0700466 return cbs_get_asn1(cbs, out, tag_value, 0 /* include header */);
467}
468
David Benjamina1dffbf2022-10-25 16:29:43 -0400469int CBS_peek_asn1_tag(const CBS *cbs, CBS_ASN1_TAG tag_value) {
David Benjamind9f49972017-12-21 23:11:23 -0500470 CBS copy = *cbs;
David Benjamina1dffbf2022-10-25 16:29:43 -0400471 CBS_ASN1_TAG actual_tag;
David Benjamind9f49972017-12-21 23:11:23 -0500472 return parse_asn1_tag(&copy, &actual_tag) && tag_value == actual_tag;
David Benjaminb6986172014-10-09 19:39:15 -0400473}
474
Adam Langley9c01e002014-08-21 10:54:06 -0700475int CBS_get_asn1_uint64(CBS *cbs, uint64_t *out) {
476 CBS bytes;
David Benjamin354e1e92020-09-04 19:01:50 -0400477 if (!CBS_get_asn1(cbs, &bytes, CBS_ASN1_INTEGER) ||
478 !CBS_is_unsigned_asn1_integer(&bytes)) {
Adam Langley9c01e002014-08-21 10:54:06 -0700479 return 0;
480 }
481
482 *out = 0;
David Benjamin76dd1802017-04-17 10:04:39 -0400483 const uint8_t *data = CBS_data(&bytes);
484 size_t len = CBS_len(&bytes);
David Benjamin76dd1802017-04-17 10:04:39 -0400485 for (size_t i = 0; i < len; i++) {
Adam Langley9c01e002014-08-21 10:54:06 -0700486 if ((*out >> 56) != 0) {
David Benjamin808f8322017-08-18 14:06:02 -0400487 // Too large to represent as a uint64_t.
Adam Langley9c01e002014-08-21 10:54:06 -0700488 return 0;
489 }
490 *out <<= 8;
491 *out |= data[i];
492 }
493
494 return 1;
Adam Langley95c29f32014-06-20 12:00:00 -0700495}
David Benjamin83fd6b62014-10-19 04:33:38 -0400496
Matthew Braithwaite82dbb532019-12-10 12:18:42 -0800497int CBS_get_asn1_int64(CBS *cbs, int64_t *out) {
David Benjamin354e1e92020-09-04 19:01:50 -0400498 int is_negative;
Matthew Braithwaite82dbb532019-12-10 12:18:42 -0800499 CBS bytes;
David Benjamin354e1e92020-09-04 19:01:50 -0400500 if (!CBS_get_asn1(cbs, &bytes, CBS_ASN1_INTEGER) ||
501 !CBS_is_valid_asn1_integer(&bytes, &is_negative)) {
Matthew Braithwaite82dbb532019-12-10 12:18:42 -0800502 return 0;
503 }
504 const uint8_t *data = CBS_data(&bytes);
505 const size_t len = CBS_len(&bytes);
David Benjamin354e1e92020-09-04 19:01:50 -0400506 if (len > sizeof(int64_t)) {
Matthew Braithwaite82dbb532019-12-10 12:18:42 -0800507 return 0;
508 }
David Benjamin1e469e42022-05-13 17:06:56 -0400509 uint8_t sign_extend[sizeof(int64_t)];
David Benjamin45b24642024-06-21 17:00:31 -0400510 OPENSSL_memset(sign_extend, is_negative ? 0xff : 0, sizeof(sign_extend));
511 OPENSSL_memcpy(sign_extend + sizeof(int64_t) - len, data, len);
512 *out = CRYPTO_load_u64_be(sign_extend);
Matthew Braithwaite82dbb532019-12-10 12:18:42 -0800513 return 1;
514}
515
Adam Langleyc61b5772018-01-25 15:37:46 -0800516int CBS_get_asn1_bool(CBS *cbs, int *out) {
517 CBS bytes;
518 if (!CBS_get_asn1(cbs, &bytes, CBS_ASN1_BOOLEAN) ||
519 CBS_len(&bytes) != 1) {
520 return 0;
521 }
522
523 const uint8_t value = *CBS_data(&bytes);
524 if (value != 0 && value != 0xff) {
525 return 0;
526 }
527
528 *out = !!value;
529 return 1;
530}
531
David Benjamina1dffbf2022-10-25 16:29:43 -0400532int CBS_get_optional_asn1(CBS *cbs, CBS *out, int *out_present, CBS_ASN1_TAG tag) {
Paul Lietar23b185a2015-09-03 14:40:21 +0100533 int present = 0;
534
David Benjamin83fd6b62014-10-19 04:33:38 -0400535 if (CBS_peek_asn1_tag(cbs, tag)) {
536 if (!CBS_get_asn1(cbs, out, tag)) {
537 return 0;
538 }
Paul Lietar23b185a2015-09-03 14:40:21 +0100539 present = 1;
David Benjamin83fd6b62014-10-19 04:33:38 -0400540 }
Paul Lietar23b185a2015-09-03 14:40:21 +0100541
542 if (out_present != NULL) {
543 *out_present = present;
544 }
545
David Benjamin83fd6b62014-10-19 04:33:38 -0400546 return 1;
547}
548
549int CBS_get_optional_asn1_octet_string(CBS *cbs, CBS *out, int *out_present,
David Benjamina1dffbf2022-10-25 16:29:43 -0400550 CBS_ASN1_TAG tag) {
David Benjamin83fd6b62014-10-19 04:33:38 -0400551 CBS child;
552 int present;
553 if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) {
554 return 0;
555 }
556 if (present) {
Adam Langleyd096c062018-03-15 13:54:33 -0700557 assert(out);
David Benjamin83fd6b62014-10-19 04:33:38 -0400558 if (!CBS_get_asn1(&child, out, CBS_ASN1_OCTETSTRING) ||
559 CBS_len(&child) != 0) {
560 return 0;
561 }
562 } else {
563 CBS_init(out, NULL, 0);
564 }
565 if (out_present) {
566 *out_present = present;
567 }
568 return 1;
569}
570
David Benjamina1dffbf2022-10-25 16:29:43 -0400571int CBS_get_optional_asn1_uint64(CBS *cbs, uint64_t *out, CBS_ASN1_TAG tag,
David Benjamin83fd6b62014-10-19 04:33:38 -0400572 uint64_t default_value) {
573 CBS child;
574 int present;
575 if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) {
576 return 0;
577 }
578 if (present) {
579 if (!CBS_get_asn1_uint64(&child, out) ||
580 CBS_len(&child) != 0) {
581 return 0;
582 }
583 } else {
584 *out = default_value;
585 }
586 return 1;
587}
Adam Langley75712922014-10-10 16:23:43 -0700588
David Benjamina1dffbf2022-10-25 16:29:43 -0400589int CBS_get_optional_asn1_bool(CBS *cbs, int *out, CBS_ASN1_TAG tag,
Adam Langley75712922014-10-10 16:23:43 -0700590 int default_value) {
591 CBS child, child2;
592 int present;
593 if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) {
594 return 0;
595 }
596 if (present) {
597 uint8_t boolean;
598
599 if (!CBS_get_asn1(&child, &child2, CBS_ASN1_BOOLEAN) ||
600 CBS_len(&child2) != 1 ||
601 CBS_len(&child) != 0) {
602 return 0;
603 }
604
605 boolean = CBS_data(&child2)[0];
606 if (boolean == 0) {
607 *out = 0;
608 } else if (boolean == 0xff) {
609 *out = 1;
610 } else {
611 return 0;
612 }
613 } else {
614 *out = default_value;
615 }
616 return 1;
617}
David Benjaminfcd714d2016-12-13 20:48:19 -0500618
619int CBS_is_valid_asn1_bitstring(const CBS *cbs) {
620 CBS in = *cbs;
621 uint8_t num_unused_bits;
622 if (!CBS_get_u8(&in, &num_unused_bits) ||
623 num_unused_bits > 7) {
624 return 0;
625 }
626
627 if (num_unused_bits == 0) {
628 return 1;
629 }
630
David Benjamin808f8322017-08-18 14:06:02 -0400631 // All num_unused_bits bits must exist and be zeros.
David Benjaminfcd714d2016-12-13 20:48:19 -0500632 uint8_t last;
633 if (!CBS_get_last_u8(&in, &last) ||
634 (last & ((1 << num_unused_bits) - 1)) != 0) {
635 return 0;
636 }
637
638 return 1;
639}
640
641int CBS_asn1_bitstring_has_bit(const CBS *cbs, unsigned bit) {
642 if (!CBS_is_valid_asn1_bitstring(cbs)) {
643 return 0;
644 }
645
646 const unsigned byte_num = (bit >> 3) + 1;
647 const unsigned bit_num = 7 - (bit & 7);
648
David Benjamin808f8322017-08-18 14:06:02 -0400649 // Unused bits are zero, and this function does not distinguish between
650 // missing and unset bits. Thus it is sufficient to do a byte-level length
651 // check.
David Benjaminfcd714d2016-12-13 20:48:19 -0500652 return byte_num < CBS_len(cbs) &&
653 (CBS_data(cbs)[byte_num] & (1 << bit_num)) != 0;
654}
David Benjamin095b6c92017-11-29 17:17:41 -0500655
David Benjamin354e1e92020-09-04 19:01:50 -0400656int CBS_is_valid_asn1_integer(const CBS *cbs, int *out_is_negative) {
657 CBS copy = *cbs;
658 uint8_t first_byte, second_byte;
659 if (!CBS_get_u8(&copy, &first_byte)) {
660 return 0; // INTEGERs may not be empty.
661 }
662 if (out_is_negative != NULL) {
663 *out_is_negative = (first_byte & 0x80) != 0;
664 }
665 if (!CBS_get_u8(&copy, &second_byte)) {
666 return 1; // One byte INTEGERs are always minimal.
667 }
668 if ((first_byte == 0x00 && (second_byte & 0x80) == 0) ||
669 (first_byte == 0xff && (second_byte & 0x80) != 0)) {
670 return 0; // The value is minimal iff the first 9 bits are not all equal.
671 }
672 return 1;
673}
674
675int CBS_is_unsigned_asn1_integer(const CBS *cbs) {
676 int is_negative;
677 return CBS_is_valid_asn1_integer(cbs, &is_negative) && !is_negative;
678}
679
David Benjamin095b6c92017-11-29 17:17:41 -0500680static int add_decimal(CBB *out, uint64_t v) {
681 char buf[DECIMAL_SIZE(uint64_t) + 1];
David Benjamin23d6e4c2023-07-15 02:44:54 -0400682 snprintf(buf, sizeof(buf), "%" PRIu64, v);
David Benjamin095b6c92017-11-29 17:17:41 -0500683 return CBB_add_bytes(out, (const uint8_t *)buf, strlen(buf));
684}
685
David Benjamin898de8d2023-03-11 12:26:37 -0500686int CBS_is_valid_asn1_oid(const CBS *cbs) {
687 if (CBS_len(cbs) == 0) {
688 return 0; // OID encodings cannot be empty.
689 }
690
691 CBS copy = *cbs;
692 uint8_t v, prev = 0;
693 while (CBS_get_u8(&copy, &v)) {
694 // OID encodings are a sequence of minimally-encoded base-128 integers (see
695 // |parse_base128_integer|). If |prev|'s MSB was clear, it was the last byte
696 // of an integer (or |v| is the first byte). |v| is then the first byte of
697 // the next integer. If first byte of an integer is 0x80, it is not
698 // minimally-encoded.
699 if ((prev & 0x80) == 0 && v == 0x80) {
700 return 0;
701 }
702 prev = v;
703 }
704
705 // The last byte should must end an integer encoding.
706 return (prev & 0x80) == 0;
707}
708
David Benjamin095b6c92017-11-29 17:17:41 -0500709char *CBS_asn1_oid_to_text(const CBS *cbs) {
710 CBB cbb;
711 if (!CBB_init(&cbb, 32)) {
712 goto err;
713 }
714
715 CBS copy = *cbs;
716 // The first component is 40 * value1 + value2, where value1 is 0, 1, or 2.
717 uint64_t v;
718 if (!parse_base128_integer(&copy, &v)) {
719 goto err;
720 }
721
722 if (v >= 80) {
723 if (!CBB_add_bytes(&cbb, (const uint8_t *)"2.", 2) ||
724 !add_decimal(&cbb, v - 80)) {
725 goto err;
726 }
727 } else if (!add_decimal(&cbb, v / 40) ||
728 !CBB_add_u8(&cbb, '.') ||
729 !add_decimal(&cbb, v % 40)) {
730 goto err;
731 }
732
733 while (CBS_len(&copy) != 0) {
734 if (!parse_base128_integer(&copy, &v) ||
735 !CBB_add_u8(&cbb, '.') ||
736 !add_decimal(&cbb, v)) {
737 goto err;
738 }
739 }
740
741 uint8_t *txt;
742 size_t txt_len;
743 if (!CBB_add_u8(&cbb, '\0') ||
744 !CBB_finish(&cbb, &txt, &txt_len)) {
745 goto err;
746 }
747
748 return (char *)txt;
749
750err:
751 CBB_cleanup(&cbb);
752 return NULL;
753}
Bob Beck652464e2022-06-16 10:49:00 -0600754
755static int cbs_get_two_digits(CBS *cbs, int *out) {
756 uint8_t first_digit, second_digit;
757 if (!CBS_get_u8(cbs, &first_digit)) {
758 return 0;
759 }
Bob Beckf86a63c2023-01-30 12:17:39 -0700760 if (!OPENSSL_isdigit(first_digit)) {
Bob Beck652464e2022-06-16 10:49:00 -0600761 return 0;
762 }
763 if (!CBS_get_u8(cbs, &second_digit)) {
764 return 0;
765 }
Bob Beckf86a63c2023-01-30 12:17:39 -0700766 if (!OPENSSL_isdigit(second_digit)) {
Bob Beck652464e2022-06-16 10:49:00 -0600767 return 0;
768 }
769 *out = (first_digit - '0') * 10 + (second_digit - '0');
770 return 1;
771}
772
773static int is_valid_day(int year, int month, int day) {
774 if (day < 1) {
775 return 0;
776 }
777 switch (month) {
778 case 1:
779 case 3:
780 case 5:
781 case 7:
782 case 8:
783 case 10:
784 case 12:
785 return day <= 31;
786 case 4:
787 case 6:
788 case 9:
789 case 11:
790 return day <= 30;
791 case 2:
792 if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
793 return day <= 29;
794 } else {
795 return day <= 28;
796 }
797 default:
798 return 0;
799 }
800}
801
802static int CBS_parse_rfc5280_time_internal(const CBS *cbs, int is_gentime,
803 int allow_timezone_offset,
804 struct tm *out_tm) {
805 int year, month, day, hour, min, sec, tmp;
806 CBS copy = *cbs;
807 uint8_t tz;
808
809 if (is_gentime) {
810 if (!cbs_get_two_digits(&copy, &tmp)) {
811 return 0;
812 }
813 year = tmp * 100;
814 if (!cbs_get_two_digits(&copy, &tmp)) {
815 return 0;
816 }
817 year += tmp;
818 } else {
819 year = 1900;
820 if (!cbs_get_two_digits(&copy, &tmp)) {
821 return 0;
822 }
823 year += tmp;
824 if (year < 1950) {
825 year += 100;
826 }
827 if (year >= 2050) {
828 return 0; // A Generalized time must be used.
829 }
830 }
831 if (!cbs_get_two_digits(&copy, &month) || month < 1 ||
832 month > 12 || // Reject invalid months.
833 !cbs_get_two_digits(&copy, &day) ||
834 !is_valid_day(year, month, day) || // Reject invalid days.
835 !cbs_get_two_digits(&copy, &hour) ||
836 hour > 23 || // Reject invalid hours.
837 !cbs_get_two_digits(&copy, &min) ||
838 min > 59 || // Reject invalid minutes.
839 !cbs_get_two_digits(&copy, &sec) || sec > 59 || !CBS_get_u8(&copy, &tz)) {
840 return 0;
841 }
842
843 int offset_sign = 0;
844 switch (tz) {
845 case 'Z':
846 break; // We correctly have 'Z' on the end as per spec.
847 case '+':
848 offset_sign = 1;
849 break; // Should not be allowed per RFC 5280.
850 case '-':
851 offset_sign = -1;
852 break; // Should not be allowed per RFC 5280.
853 default:
854 return 0; // Reject anything else after the time.
855 }
856
857 // If allow_timezone_offset is non-zero, allow for a four digit timezone
858 // offset to be specified even though this is not allowed by RFC 5280. We are
859 // permissive of this for UTCTimes due to the unfortunate existence of
860 // artisinally rolled long lived certificates that were baked into places that
861 // are now difficult to change. These certificates were generated with the
862 // 'openssl' command that permissively allowed the creation of certificates
863 // with notBefore and notAfter times specified as strings for direct
864 // certificate inclusion on the command line. For context see cl/237068815.
865 //
866 // TODO(bbe): This has been expunged from public web-pki as the ecosystem has
867 // managed to encourage CA compliance with standards. We should find a way to
868 // get rid of this or make it off by default.
869 int offset_seconds = 0;
870 if (offset_sign != 0) {
871 if (!allow_timezone_offset) {
872 return 0;
873 }
874 int offset_hours, offset_minutes;
875 if (!cbs_get_two_digits(&copy, &offset_hours) ||
876 offset_hours > 23 || // Reject invalid hours.
877 !cbs_get_two_digits(&copy, &offset_minutes) ||
878 offset_minutes > 59) { // Reject invalid minutes.
879 return 0;
880 }
881 offset_seconds = offset_sign * (offset_hours * 3600 + offset_minutes * 60);
882 }
883
884 if (CBS_len(&copy) != 0) {
885 return 0; // Reject invalid lengths.
886 }
887
888 if (out_tm != NULL) {
889 // Fill in the tm fields corresponding to what we validated.
890 out_tm->tm_year = year - 1900;
891 out_tm->tm_mon = month - 1;
892 out_tm->tm_mday = day;
893 out_tm->tm_hour = hour;
894 out_tm->tm_min = min;
895 out_tm->tm_sec = sec;
896 if (offset_seconds && !OPENSSL_gmtime_adj(out_tm, 0, offset_seconds)) {
897 return 0;
898 }
899 }
900 return 1;
901}
902
903int CBS_parse_generalized_time(const CBS *cbs, struct tm *out_tm,
904 int allow_timezone_offset) {
905 return CBS_parse_rfc5280_time_internal(cbs, 1, allow_timezone_offset, out_tm);
906}
907
908int CBS_parse_utc_time(const CBS *cbs, struct tm *out_tm,
909 int allow_timezone_offset) {
910 return CBS_parse_rfc5280_time_internal(cbs, 0, allow_timezone_offset, out_tm);
911}