/src/boringssl/crypto/bytestring/cbs.cc
Line | Count | Source |
1 | | // Copyright 2014 The BoringSSL Authors |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of the License at |
6 | | // |
7 | | // https://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software |
10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
14 | | |
15 | | #include <openssl/asn1.h> |
16 | | #include <openssl/bytestring.h> |
17 | | #include <openssl/mem.h> |
18 | | |
19 | | #include <assert.h> |
20 | | #include <ctype.h> |
21 | | #include <string.h> |
22 | | |
23 | | #include "../asn1/internal.h" |
24 | | #include "../internal.h" |
25 | | #include "internal.h" |
26 | | |
27 | | |
28 | | using namespace bssl; |
29 | | |
30 | 1.57G | static int cbs_get(CBS *cbs, const uint8_t **p, size_t n) { |
31 | 1.57G | if (cbs->len < n) { |
32 | 8.07M | return 0; |
33 | 8.07M | } |
34 | | |
35 | 1.56G | *p = cbs->data; |
36 | 1.56G | cbs->data += n; |
37 | 1.56G | cbs->len -= n; |
38 | 1.56G | return 1; |
39 | 1.57G | } |
40 | | |
41 | 25.4M | int CBS_skip(CBS *cbs, size_t len) { |
42 | 25.4M | const uint8_t *dummy; |
43 | 25.4M | return cbs_get(cbs, &dummy, len); |
44 | 25.4M | } |
45 | | |
46 | 0 | int CBS_stow(const CBS *cbs, uint8_t **out_ptr, size_t *out_len) { |
47 | 0 | OPENSSL_free(*out_ptr); |
48 | 0 | *out_ptr = nullptr; |
49 | 0 | *out_len = 0; |
50 | |
|
51 | 0 | if (cbs->len == 0) { |
52 | 0 | return 1; |
53 | 0 | } |
54 | 0 | *out_ptr = reinterpret_cast<uint8_t *>(OPENSSL_memdup(cbs->data, cbs->len)); |
55 | 0 | if (*out_ptr == nullptr) { |
56 | 0 | return 0; |
57 | 0 | } |
58 | 0 | *out_len = cbs->len; |
59 | 0 | return 1; |
60 | 0 | } |
61 | | |
62 | 14.6k | int CBS_strdup(const CBS *cbs, char **out_ptr) { |
63 | 14.6k | if (*out_ptr != nullptr) { |
64 | 0 | OPENSSL_free(*out_ptr); |
65 | 0 | } |
66 | 14.6k | *out_ptr = OPENSSL_strndup((const char *)cbs->data, cbs->len); |
67 | 14.6k | return (*out_ptr != nullptr); |
68 | 14.6k | } |
69 | | |
70 | 14.6k | int CBS_contains_zero_byte(const CBS *cbs) { |
71 | 14.6k | return OPENSSL_memchr(cbs->data, 0, cbs->len) != nullptr; |
72 | 14.6k | } |
73 | | |
74 | 78.0k | int CBS_mem_equal(const CBS *cbs, const uint8_t *data, size_t len) { |
75 | 78.0k | if (len != cbs->len) { |
76 | 1.25k | return 0; |
77 | 1.25k | } |
78 | 76.7k | return CRYPTO_memcmp(cbs->data, data, len) == 0; |
79 | 78.0k | } |
80 | | |
81 | 61.2M | static int cbs_get_u(CBS *cbs, uint64_t *out, size_t len) { |
82 | 61.2M | uint64_t result = 0; |
83 | 61.2M | const uint8_t *data; |
84 | | |
85 | 61.2M | if (!cbs_get(cbs, &data, len)) { |
86 | 50.5k | return 0; |
87 | 50.5k | } |
88 | 185M | for (size_t i = 0; i < len; i++) { |
89 | 124M | result <<= 8; |
90 | 124M | result |= data[i]; |
91 | 124M | } |
92 | 61.2M | *out = result; |
93 | 61.2M | return 1; |
94 | 61.2M | } |
95 | | |
96 | 1.44G | int CBS_get_u8(CBS *cbs, uint8_t *out) { |
97 | 1.44G | const uint8_t *v; |
98 | 1.44G | if (!cbs_get(cbs, &v, 1)) { |
99 | 6.60M | return 0; |
100 | 6.60M | } |
101 | 1.44G | *out = *v; |
102 | 1.44G | return 1; |
103 | 1.44G | } |
104 | | |
105 | 50.2M | int CBS_get_u16(CBS *cbs, uint16_t *out) { |
106 | 50.2M | uint64_t v; |
107 | 50.2M | if (!cbs_get_u(cbs, &v, 2)) { |
108 | 21.7k | return 0; |
109 | 21.7k | } |
110 | 50.2M | *out = v; |
111 | 50.2M | return 1; |
112 | 50.2M | } |
113 | | |
114 | 0 | int CBS_get_u16le(CBS *cbs, uint16_t *out) { |
115 | 0 | if (!CBS_get_u16(cbs, out)) { |
116 | 0 | return 0; |
117 | 0 | } |
118 | 0 | *out = CRYPTO_bswap2(*out); |
119 | 0 | return 1; |
120 | 0 | } |
121 | | |
122 | 2.14M | int CBS_get_u24(CBS *cbs, uint32_t *out) { |
123 | 2.14M | uint64_t v; |
124 | 2.14M | if (!cbs_get_u(cbs, &v, 3)) { |
125 | 15.1k | return 0; |
126 | 15.1k | } |
127 | 2.12M | *out = (uint32_t)v; |
128 | 2.12M | return 1; |
129 | 2.14M | } |
130 | | |
131 | 262k | int CBS_get_u32(CBS *cbs, uint32_t *out) { |
132 | 262k | uint64_t v; |
133 | 262k | if (!cbs_get_u(cbs, &v, 4)) { |
134 | 370 | return 0; |
135 | 370 | } |
136 | 261k | *out = (uint32_t)v; |
137 | 261k | return 1; |
138 | 262k | } |
139 | | |
140 | 0 | int CBS_get_u32le(CBS *cbs, uint32_t *out) { |
141 | 0 | if (!CBS_get_u32(cbs, out)) { |
142 | 0 | return 0; |
143 | 0 | } |
144 | 0 | *out = CRYPTO_bswap4(*out); |
145 | 0 | return 1; |
146 | 0 | } |
147 | | |
148 | 0 | int CBS_get_u48(CBS *cbs, uint64_t *out) { return cbs_get_u(cbs, out, 6); } |
149 | | |
150 | 83.5k | int CBS_get_u64(CBS *cbs, uint64_t *out) { return cbs_get_u(cbs, out, 8); } |
151 | | |
152 | 0 | int CBS_get_u64le(CBS *cbs, uint64_t *out) { |
153 | 0 | if (!cbs_get_u(cbs, out, 8)) { |
154 | 0 | return 0; |
155 | 0 | } |
156 | 0 | *out = CRYPTO_bswap8(*out); |
157 | 0 | return 1; |
158 | 0 | } |
159 | | |
160 | 387k | int CBS_get_last_u8(CBS *cbs, uint8_t *out) { |
161 | 387k | if (cbs->len == 0) { |
162 | 139 | return 0; |
163 | 139 | } |
164 | 387k | *out = cbs->data[cbs->len - 1]; |
165 | 387k | cbs->len--; |
166 | 387k | return 1; |
167 | 387k | } |
168 | | |
169 | 35.5M | int CBS_get_bytes(CBS *cbs, CBS *out, size_t len) { |
170 | 35.5M | const uint8_t *v; |
171 | 35.5M | if (!cbs_get(cbs, &v, len)) { |
172 | 1.42M | return 0; |
173 | 1.42M | } |
174 | 34.1M | CBS_init(out, v, len); |
175 | 34.1M | return 1; |
176 | 35.5M | } |
177 | | |
178 | 791 | int CBS_copy_bytes(CBS *cbs, uint8_t *out, size_t len) { |
179 | 791 | const uint8_t *v; |
180 | 791 | if (!cbs_get(cbs, &v, len)) { |
181 | 15 | return 0; |
182 | 15 | } |
183 | 776 | OPENSSL_memcpy(out, v, len); |
184 | 776 | return 1; |
185 | 791 | } |
186 | | |
187 | 4.52M | static int cbs_get_length_prefixed(CBS *cbs, CBS *out, size_t len_len) { |
188 | 4.52M | uint64_t len; |
189 | 4.52M | if (!cbs_get_u(cbs, &len, len_len)) { |
190 | 9.59k | return 0; |
191 | 9.59k | } |
192 | | // If `len_len` <= 3 then we know that `len` will fit into a `size_t`, even on |
193 | | // 32-bit systems. |
194 | 4.52M | assert(len_len <= 3); |
195 | 4.51M | return CBS_get_bytes(cbs, out, len); |
196 | 4.51M | } |
197 | | |
198 | 443k | int CBS_get_u8_length_prefixed(CBS *cbs, CBS *out) { |
199 | 443k | return cbs_get_length_prefixed(cbs, out, 1); |
200 | 443k | } |
201 | | |
202 | 3.55M | int CBS_get_u16_length_prefixed(CBS *cbs, CBS *out) { |
203 | 3.55M | return cbs_get_length_prefixed(cbs, out, 2); |
204 | 3.55M | } |
205 | | |
206 | 523k | int CBS_get_u24_length_prefixed(CBS *cbs, CBS *out) { |
207 | 523k | return cbs_get_length_prefixed(cbs, out, 3); |
208 | 523k | } |
209 | | |
210 | 361k | int CBS_get_until_first(CBS *cbs, CBS *out, uint8_t c) { |
211 | 361k | const uint8_t *split = reinterpret_cast<const uint8_t *>( |
212 | 361k | OPENSSL_memchr(CBS_data(cbs), c, CBS_len(cbs))); |
213 | 361k | if (split == nullptr) { |
214 | 3.31k | return 0; |
215 | 3.31k | } |
216 | 358k | return CBS_get_bytes(cbs, out, split - CBS_data(cbs)); |
217 | 361k | } |
218 | | |
219 | 0 | int CBS_get_until_first_of(CBS *cbs, CBS *out, const char *chars) { |
220 | 0 | size_t pos = 0; |
221 | 0 | while (pos < CBS_len(cbs)) { |
222 | 0 | uint8_t c = CBS_data(cbs)[pos]; |
223 | | // Special-case for \0 characters. We don't want to match on a null byte, |
224 | | // even though strchr will happily return the \0 at the end of `chars`. |
225 | 0 | if (!c || !strchr(chars, c)) { |
226 | 0 | pos++; |
227 | 0 | } else { |
228 | 0 | break; |
229 | 0 | } |
230 | 0 | } |
231 | 0 | if (pos == CBS_len(cbs)) { |
232 | 0 | return 0; |
233 | 0 | } |
234 | 0 | return CBS_get_bytes(cbs, out, pos); |
235 | 0 | } |
236 | | |
237 | 0 | int CBS_get_until_first_not_of(CBS *cbs, CBS *out, const char *chars) { |
238 | 0 | size_t pos = 0; |
239 | 0 | while (pos < CBS_len(cbs)) { |
240 | 0 | uint8_t c = CBS_data(cbs)[pos]; |
241 | | // Special-case for \0 characters. We don't want to match on a null byte, |
242 | | // even though strchr will happily return the \0 at the end of `chars`. |
243 | 0 | if (c && strchr(chars, c)) { |
244 | 0 | pos++; |
245 | 0 | } else { |
246 | 0 | break; |
247 | 0 | } |
248 | 0 | } |
249 | 0 | if (pos == CBS_len(cbs)) { |
250 | 0 | return 0; |
251 | 0 | } |
252 | 0 | return CBS_get_bytes(cbs, out, pos); |
253 | 0 | } |
254 | | |
255 | 63.7k | int CBS_get_u64_decimal(CBS *cbs, uint64_t *out) { |
256 | 63.7k | uint64_t v = 0; |
257 | 63.7k | int seen_digit = 0; |
258 | 213k | while (CBS_len(cbs) != 0) { |
259 | 188k | uint8_t c = CBS_data(cbs)[0]; |
260 | 188k | if (!OPENSSL_isdigit(c)) { |
261 | 39.0k | break; |
262 | 39.0k | } |
263 | 149k | CBS_skip(cbs, 1); |
264 | 149k | if (/* Forbid stray leading zeros */ |
265 | 149k | (v == 0 && seen_digit) || |
266 | | // Check for overflow. |
267 | 149k | v > UINT64_MAX / 10 || // |
268 | 149k | v * 10 > UINT64_MAX - (c - '0')) { |
269 | 172 | return 0; |
270 | 172 | } |
271 | 149k | v = v * 10 + (c - '0'); |
272 | 149k | seen_digit = 1; |
273 | 149k | } |
274 | | |
275 | 63.6k | *out = v; |
276 | 63.6k | return seen_digit; |
277 | 63.7k | } |
278 | | |
279 | 314k | int CBS_get_asn1_oid_component(CBS *cbs, uint64_t *out) { |
280 | 314k | uint64_t v = 0; |
281 | 314k | uint8_t b; |
282 | 798k | do { |
283 | 798k | if (!CBS_get_u8(cbs, &b)) { |
284 | 27.6k | return 0; |
285 | 27.6k | } |
286 | 770k | if ((v >> (64 - 7)) != 0) { |
287 | | // The value is too large. |
288 | 1.68k | return 0; |
289 | 1.68k | } |
290 | 768k | if (v == 0 && b == 0x80) { |
291 | | // The value must be minimally encoded. |
292 | 2.58k | return 0; |
293 | 2.58k | } |
294 | 766k | v = (v << 7) | (b & 0x7f); |
295 | | |
296 | | // Values end at an octet with the high bit cleared. |
297 | 766k | } while (b & 0x80); |
298 | | |
299 | 282k | *out = v; |
300 | 282k | return 1; |
301 | 314k | } |
302 | | |
303 | 34.5M | static int parse_asn1_tag(CBS *cbs, CBS_ASN1_TAG *out) { |
304 | 34.5M | uint8_t tag_byte; |
305 | 34.5M | if (!CBS_get_u8(cbs, &tag_byte)) { |
306 | 1.90M | return 0; |
307 | 1.90M | } |
308 | | |
309 | | // ITU-T X.690 section 8.1.2.3 specifies the format for identifiers with a tag |
310 | | // number no greater than 30. |
311 | | // |
312 | | // If the number portion is 31 (0x1f, the largest value that fits in the |
313 | | // allotted bits), then the tag is more than one byte long and the |
314 | | // continuation bytes contain the tag number. |
315 | 32.6M | CBS_ASN1_TAG tag = ((CBS_ASN1_TAG)tag_byte & 0xe0) << CBS_ASN1_TAG_SHIFT; |
316 | 32.6M | CBS_ASN1_TAG tag_number = tag_byte & 0x1f; |
317 | 32.6M | if (tag_number == 0x1f) { |
318 | | // High tag numbers are encoded in the same format as OID components. |
319 | 186k | uint64_t v; |
320 | 186k | if (!CBS_get_asn1_oid_component(cbs, &v) || |
321 | | // Check the tag number is within our supported bounds. |
322 | 154k | v > CBS_ASN1_TAG_NUMBER_MASK || |
323 | | // Small tag numbers should have used low tag number form, even in BER. |
324 | 132k | v < 0x1f) { |
325 | 61.2k | return 0; |
326 | 61.2k | } |
327 | 124k | tag_number = (CBS_ASN1_TAG)v; |
328 | 124k | } |
329 | | |
330 | 32.5M | tag |= tag_number; |
331 | | |
332 | | // Tag [UNIVERSAL 0] is reserved for use by the encoding. Reject it here to |
333 | | // avoid some ambiguity around ANY values and BER indefinite-length EOCs. See |
334 | | // https://crbug.com/boringssl/455. |
335 | 32.5M | if ((tag & ~CBS_ASN1_CONSTRUCTED) == 0) { |
336 | 25.7k | return 0; |
337 | 25.7k | } |
338 | | |
339 | 32.5M | *out = tag; |
340 | 32.5M | return 1; |
341 | 32.5M | } |
342 | | |
343 | | static int cbs_get_any_asn1_element(CBS *cbs, CBS *out, CBS_ASN1_TAG *out_tag, |
344 | | size_t *out_header_len, int *out_ber_found, |
345 | 27.1M | int *out_indefinite, int ber_ok) { |
346 | 27.1M | CBS header = *cbs; |
347 | 27.1M | CBS throwaway; |
348 | | |
349 | 27.1M | if (out == nullptr) { |
350 | 3.53M | out = &throwaway; |
351 | 3.53M | } |
352 | 27.1M | if (ber_ok) { |
353 | 1.87M | *out_ber_found = 0; |
354 | 1.87M | *out_indefinite = 0; |
355 | 25.3M | } else { |
356 | 25.3M | assert(out_ber_found == nullptr); |
357 | 25.3M | assert(out_indefinite == nullptr); |
358 | 25.3M | } |
359 | | |
360 | 27.1M | CBS_ASN1_TAG tag; |
361 | 27.1M | if (!parse_asn1_tag(&header, &tag)) { |
362 | 38.1k | return 0; |
363 | 38.1k | } |
364 | 27.1M | if (out_tag != nullptr) { |
365 | 21.8M | *out_tag = tag; |
366 | 21.8M | } |
367 | | |
368 | 27.1M | uint8_t length_byte; |
369 | 27.1M | if (!CBS_get_u8(&header, &length_byte)) { |
370 | 13.6k | return 0; |
371 | 13.6k | } |
372 | | |
373 | 27.1M | size_t header_len = CBS_len(cbs) - CBS_len(&header); |
374 | | |
375 | 27.1M | size_t len; |
376 | | // The format for the length encoding is specified in ITU-T X.690 section |
377 | | // 8.1.3. |
378 | 27.1M | if ((length_byte & 0x80) == 0) { |
379 | | // Short form length. |
380 | 23.1M | len = ((size_t)length_byte) + header_len; |
381 | 23.1M | if (out_header_len != nullptr) { |
382 | 19.4M | *out_header_len = header_len; |
383 | 19.4M | } |
384 | 23.1M | } else { |
385 | | // The high bit indicate that this is the long form, while the next 7 bits |
386 | | // encode the number of subsequent octets used to encode the length (ITU-T |
387 | | // X.690 clause 8.1.3.5.b). |
388 | 4.02M | const size_t num_bytes = length_byte & 0x7f; |
389 | 4.02M | uint64_t len64; |
390 | | |
391 | 4.02M | if (ber_ok && (tag & CBS_ASN1_CONSTRUCTED) != 0 && num_bytes == 0) { |
392 | | // indefinite length |
393 | 23.6k | if (out_header_len != nullptr) { |
394 | 23.6k | *out_header_len = header_len; |
395 | 23.6k | } |
396 | 23.6k | *out_ber_found = 1; |
397 | 23.6k | *out_indefinite = 1; |
398 | 23.6k | return CBS_get_bytes(cbs, out, header_len); |
399 | 23.6k | } |
400 | | |
401 | | // ITU-T X.690 clause 8.1.3.5.c specifies that the value 0xff shall not be |
402 | | // used as the first byte of the length. If this parser encounters that |
403 | | // value, num_bytes will be parsed as 127, which will fail this check. |
404 | 4.00M | if (num_bytes == 0 || num_bytes > 4) { |
405 | 9.98k | return 0; |
406 | 9.98k | } |
407 | 3.99M | if (!cbs_get_u(&header, &len64, num_bytes)) { |
408 | 1.26k | return 0; |
409 | 1.26k | } |
410 | | // ITU-T X.690 section 10.1 (DER length forms) requires encoding the |
411 | | // length with the minimum number of octets. BER could, technically, have |
412 | | // 125 superfluous zero bytes. We do not attempt to handle that and still |
413 | | // require that the length fit in a `uint32_t` for BER. |
414 | 3.98M | if (len64 < 128) { |
415 | | // Length should have used short-form encoding. |
416 | 4.74k | if (ber_ok) { |
417 | 2.21k | *out_ber_found = 1; |
418 | 2.53k | } else { |
419 | 2.53k | return 0; |
420 | 2.53k | } |
421 | 4.74k | } |
422 | 3.98M | if ((len64 >> ((num_bytes - 1) * 8)) == 0) { |
423 | | // Length should have been at least one byte shorter. |
424 | 3.55k | if (ber_ok) { |
425 | 1.42k | *out_ber_found = 1; |
426 | 2.12k | } else { |
427 | 2.12k | return 0; |
428 | 2.12k | } |
429 | 3.55k | } |
430 | 3.98M | len = len64; |
431 | 3.98M | if (len + header_len + num_bytes < len) { |
432 | | // Overflow. |
433 | 0 | return 0; |
434 | 0 | } |
435 | 3.98M | len += header_len + num_bytes; |
436 | 3.98M | if (out_header_len != nullptr) { |
437 | 2.34M | *out_header_len = header_len + num_bytes; |
438 | 2.34M | } |
439 | 3.98M | } |
440 | | |
441 | 27.1M | return CBS_get_bytes(cbs, out, len); |
442 | 27.1M | } |
443 | | |
444 | 1.19k | int CBS_get_any_asn1(CBS *cbs, CBS *out, CBS_ASN1_TAG *out_tag) { |
445 | 1.19k | size_t header_len; |
446 | 1.19k | if (!CBS_get_any_asn1_element(cbs, out, out_tag, &header_len)) { |
447 | 448 | return 0; |
448 | 448 | } |
449 | | |
450 | 746 | if (out && !CBS_skip(out, header_len)) { |
451 | 0 | assert(0); |
452 | 0 | return 0; |
453 | 0 | } |
454 | | |
455 | 746 | return 1; |
456 | 746 | } |
457 | | |
458 | | int CBS_get_any_asn1_element(CBS *cbs, CBS *out, CBS_ASN1_TAG *out_tag, |
459 | 25.3M | size_t *out_header_len) { |
460 | 25.3M | return cbs_get_any_asn1_element(cbs, out, out_tag, out_header_len, nullptr, |
461 | 25.3M | nullptr, |
462 | 25.3M | /*ber_ok=*/0); |
463 | 25.3M | } |
464 | | |
465 | | int CBS_get_any_ber_asn1_element(CBS *cbs, CBS *out, CBS_ASN1_TAG *out_tag, |
466 | | size_t *out_header_len, int *out_ber_found, |
467 | 1.87M | int *out_indefinite) { |
468 | 1.87M | int ber_found_temp; |
469 | 1.87M | return cbs_get_any_asn1_element( |
470 | 1.87M | cbs, out, out_tag, out_header_len, |
471 | 1.87M | out_ber_found ? out_ber_found : &ber_found_temp, out_indefinite, |
472 | 1.87M | /*ber_ok=*/1); |
473 | 1.87M | } |
474 | | |
475 | | static int cbs_get_asn1(CBS *cbs, CBS *out, CBS_ASN1_TAG tag_value, |
476 | 15.8M | int skip_header) { |
477 | 15.8M | size_t header_len; |
478 | 15.8M | CBS_ASN1_TAG tag; |
479 | 15.8M | CBS throwaway; |
480 | | |
481 | 15.8M | if (out == nullptr) { |
482 | 724k | out = &throwaway; |
483 | 724k | } |
484 | | |
485 | 15.8M | if (!CBS_get_any_asn1_element(cbs, out, &tag, &header_len) || |
486 | 15.8M | tag != tag_value) { |
487 | 116k | return 0; |
488 | 116k | } |
489 | | |
490 | 15.7M | if (skip_header && !CBS_skip(out, header_len)) { |
491 | 0 | assert(0); |
492 | 0 | return 0; |
493 | 0 | } |
494 | | |
495 | 15.7M | return 1; |
496 | 15.7M | } |
497 | | |
498 | 15.7M | int CBS_get_asn1(CBS *cbs, CBS *out, CBS_ASN1_TAG tag_value) { |
499 | 15.7M | return cbs_get_asn1(cbs, out, tag_value, 1 /* skip header */); |
500 | 15.7M | } |
501 | | |
502 | 136k | int CBS_get_asn1_element(CBS *cbs, CBS *out, CBS_ASN1_TAG tag_value) { |
503 | 136k | return cbs_get_asn1(cbs, out, tag_value, 0 /* include header */); |
504 | 136k | } |
505 | | |
506 | 7.34M | CBS_ASN1_TAG CBS_peek_any_asn1_tag(const CBS *cbs) { |
507 | 7.34M | CBS copy = *cbs; |
508 | 7.34M | CBS_ASN1_TAG tag; |
509 | 7.34M | if (!parse_asn1_tag(©, &tag)) { |
510 | 1.95M | return 0; |
511 | 1.95M | } |
512 | 5.38M | return tag; |
513 | 7.34M | } |
514 | | |
515 | 7.33M | int CBS_peek_asn1_tag(const CBS *cbs, CBS_ASN1_TAG tag_value) { |
516 | 7.33M | CBS_ASN1_TAG actual_tag = CBS_peek_any_asn1_tag(cbs); |
517 | | // The caller should never pass zero as |tag_value|, but return zero if they |
518 | | // did. |
519 | 7.33M | return actual_tag != 0 && actual_tag == tag_value; |
520 | 7.33M | } |
521 | | |
522 | 1.03M | int CBS_get_asn1_uint64(CBS *cbs, uint64_t *out) { |
523 | 1.03M | return CBS_get_asn1_uint64_with_tag(cbs, out, CBS_ASN1_INTEGER); |
524 | 1.03M | } |
525 | | |
526 | 1.03M | int CBS_get_asn1_uint64_with_tag(CBS *cbs, uint64_t *out, CBS_ASN1_TAG tag) { |
527 | 1.03M | CBS bytes; |
528 | 1.03M | if (!CBS_get_asn1(cbs, &bytes, tag) || |
529 | 1.02M | !CBS_is_unsigned_asn1_integer(&bytes)) { |
530 | 11.6k | return 0; |
531 | 11.6k | } |
532 | | |
533 | 1.02M | *out = 0; |
534 | 1.02M | const uint8_t *data = CBS_data(&bytes); |
535 | 1.02M | size_t len = CBS_len(&bytes); |
536 | 2.73M | for (size_t i = 0; i < len; i++) { |
537 | 1.71M | if ((*out >> 56) != 0) { |
538 | | // Too large to represent as a uint64_t. |
539 | 1.38k | return 0; |
540 | 1.38k | } |
541 | 1.71M | *out <<= 8; |
542 | 1.71M | *out |= data[i]; |
543 | 1.71M | } |
544 | | |
545 | 1.02M | return 1; |
546 | 1.02M | } |
547 | | |
548 | 0 | int CBS_get_asn1_int64(CBS *cbs, int64_t *out) { |
549 | 0 | return CBS_get_asn1_int64_with_tag(cbs, out, CBS_ASN1_INTEGER); |
550 | 0 | } |
551 | | |
552 | 0 | int CBS_get_asn1_int64_with_tag(CBS *cbs, int64_t *out, CBS_ASN1_TAG tag) { |
553 | 0 | int is_negative; |
554 | 0 | CBS bytes; |
555 | 0 | if (!CBS_get_asn1(cbs, &bytes, tag) || |
556 | 0 | !CBS_is_valid_asn1_integer(&bytes, &is_negative)) { |
557 | 0 | return 0; |
558 | 0 | } |
559 | 0 | const uint8_t *data = CBS_data(&bytes); |
560 | 0 | const size_t len = CBS_len(&bytes); |
561 | 0 | if (len > sizeof(int64_t)) { |
562 | 0 | return 0; |
563 | 0 | } |
564 | 0 | uint8_t sign_extend[sizeof(int64_t)]; |
565 | 0 | OPENSSL_memset(sign_extend, is_negative ? 0xff : 0, sizeof(sign_extend)); |
566 | 0 | OPENSSL_memcpy(sign_extend + sizeof(int64_t) - len, data, len); |
567 | 0 | *out = CRYPTO_load_u64_be(sign_extend); |
568 | 0 | return 1; |
569 | 0 | } |
570 | | |
571 | 1.41k | int CBS_get_asn1_bool(CBS *cbs, int *out) { |
572 | 1.41k | CBS bytes; |
573 | 1.41k | if (!CBS_get_asn1(cbs, &bytes, CBS_ASN1_BOOLEAN) || CBS_len(&bytes) != 1) { |
574 | 183 | return 0; |
575 | 183 | } |
576 | | |
577 | 1.23k | const uint8_t value = *CBS_data(&bytes); |
578 | 1.23k | if (value != 0 && value != 0xff) { |
579 | 94 | return 0; |
580 | 94 | } |
581 | | |
582 | 1.13k | *out = !!value; |
583 | 1.13k | return 1; |
584 | 1.23k | } |
585 | | |
586 | | int CBS_get_optional_asn1(CBS *cbs, CBS *out, int *out_present, |
587 | 3.87M | CBS_ASN1_TAG tag) { |
588 | 3.87M | int present = 0; |
589 | | |
590 | 3.87M | if (CBS_peek_asn1_tag(cbs, tag)) { |
591 | 961k | if (!CBS_get_asn1(cbs, out, tag)) { |
592 | 9.54k | return 0; |
593 | 9.54k | } |
594 | 952k | present = 1; |
595 | 952k | } |
596 | | |
597 | 3.86M | if (out_present != nullptr) { |
598 | 3.52M | *out_present = present; |
599 | 3.52M | } |
600 | | |
601 | 3.86M | return 1; |
602 | 3.87M | } |
603 | | |
604 | | int CBS_get_optional_asn1_octet_string(CBS *cbs, CBS *out, int *out_present, |
605 | 1.24M | CBS_ASN1_TAG tag) { |
606 | 1.24M | CBS child; |
607 | 1.24M | int present; |
608 | 1.24M | if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) { |
609 | 80 | return 0; |
610 | 80 | } |
611 | 1.24M | if (present) { |
612 | 270k | assert(out); |
613 | 270k | if (!CBS_get_asn1(&child, out, CBS_ASN1_OCTETSTRING) || |
614 | 270k | CBS_len(&child) != 0) { |
615 | 420 | return 0; |
616 | 420 | } |
617 | 969k | } else { |
618 | 969k | CBS_init(out, nullptr, 0); |
619 | 969k | } |
620 | 1.24M | if (out_present) { |
621 | 549k | *out_present = present; |
622 | 549k | } |
623 | 1.24M | return 1; |
624 | 1.24M | } |
625 | | |
626 | | int CBS_get_optional_asn1_uint64(CBS *cbs, uint64_t *out, CBS_ASN1_TAG tag, |
627 | 830k | uint64_t default_value) { |
628 | 830k | CBS child; |
629 | 830k | int present; |
630 | 830k | if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) { |
631 | 47 | return 0; |
632 | 47 | } |
633 | 830k | if (present) { |
634 | 220k | if (!CBS_get_asn1_uint64(&child, out) || CBS_len(&child) != 0) { |
635 | 60 | return 0; |
636 | 60 | } |
637 | 609k | } else { |
638 | 609k | *out = default_value; |
639 | 609k | } |
640 | 830k | return 1; |
641 | 830k | } |
642 | | |
643 | | int CBS_get_optional_asn1_bool(CBS *cbs, int *out, CBS_ASN1_TAG tag, |
644 | 549k | int default_value) { |
645 | 549k | CBS child, child2; |
646 | 549k | int present; |
647 | 549k | if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) { |
648 | 28 | return 0; |
649 | 28 | } |
650 | 549k | if (present) { |
651 | 146k | uint8_t boolean; |
652 | | |
653 | 146k | if (!CBS_get_asn1(&child, &child2, CBS_ASN1_BOOLEAN) || |
654 | 146k | CBS_len(&child2) != 1 || CBS_len(&child) != 0) { |
655 | 410 | return 0; |
656 | 410 | } |
657 | | |
658 | 146k | boolean = CBS_data(&child2)[0]; |
659 | 146k | if (boolean == 0) { |
660 | 70.8k | *out = 0; |
661 | 75.2k | } else if (boolean == 0xff) { |
662 | 75.2k | *out = 1; |
663 | 75.2k | } else { |
664 | 61 | return 0; |
665 | 61 | } |
666 | 403k | } else { |
667 | 403k | *out = default_value; |
668 | 403k | } |
669 | 549k | return 1; |
670 | 549k | } |
671 | | |
672 | 461 | int CBS_is_valid_asn1_bitstring(const CBS *cbs) { |
673 | 461 | CBS in = *cbs; |
674 | 461 | uint8_t num_unused_bits; |
675 | 461 | if (!CBS_get_u8(&in, &num_unused_bits) || num_unused_bits > 7) { |
676 | 11 | return 0; |
677 | 11 | } |
678 | | |
679 | 450 | if (num_unused_bits == 0) { |
680 | 34 | return 1; |
681 | 34 | } |
682 | | |
683 | | // All num_unused_bits bits must exist and be zeros. |
684 | 416 | uint8_t last; |
685 | 416 | if (!CBS_get_last_u8(&in, &last) || |
686 | 416 | (last & ((1 << num_unused_bits) - 1)) != 0) { |
687 | 8 | return 0; |
688 | 8 | } |
689 | | |
690 | 408 | return 1; |
691 | 416 | } |
692 | | |
693 | 221 | int CBS_asn1_bitstring_has_bit(const CBS *cbs, unsigned bit) { |
694 | 221 | if (!CBS_is_valid_asn1_bitstring(cbs)) { |
695 | 0 | return 0; |
696 | 0 | } |
697 | | |
698 | 221 | const unsigned byte_num = (bit >> 3) + 1; |
699 | 221 | const unsigned bit_num = 7 - (bit & 7); |
700 | | |
701 | | // Unused bits are zero, and this function does not distinguish between |
702 | | // missing and unset bits. Thus it is sufficient to do a byte-level length |
703 | | // check. |
704 | 221 | return byte_num < CBS_len(cbs) && |
705 | 221 | (CBS_data(cbs)[byte_num] & (1 << bit_num)) != 0; |
706 | 221 | } |
707 | | |
708 | 1.58M | int CBS_is_valid_asn1_integer(const CBS *cbs, int *out_is_negative) { |
709 | 1.58M | CBS copy = *cbs; |
710 | 1.58M | uint8_t first_byte, second_byte; |
711 | 1.58M | if (!CBS_get_u8(©, &first_byte)) { |
712 | 8.14k | return 0; // INTEGERs may not be empty. |
713 | 8.14k | } |
714 | 1.57M | if (out_is_negative != nullptr) { |
715 | 1.57M | *out_is_negative = (first_byte & 0x80) != 0; |
716 | 1.57M | } |
717 | 1.57M | if (!CBS_get_u8(©, &second_byte)) { |
718 | 548k | return 1; // One byte INTEGERs are always minimal. |
719 | 548k | } |
720 | 1.02M | if ((first_byte == 0x00 && (second_byte & 0x80) == 0) || |
721 | 1.02M | (first_byte == 0xff && (second_byte & 0x80) != 0)) { |
722 | 5.27k | return 0; // The value is minimal iff the first 9 bits are not all equal. |
723 | 5.27k | } |
724 | 1.02M | return 1; |
725 | 1.02M | } |
726 | | |
727 | 1.02M | int CBS_is_unsigned_asn1_integer(const CBS *cbs) { |
728 | 1.02M | int is_negative; |
729 | 1.02M | return CBS_is_valid_asn1_integer(cbs, &is_negative) && !is_negative; |
730 | 1.02M | } |
731 | | |
732 | 2.13M | int CBS_is_valid_asn1_oid(const CBS *cbs) { |
733 | 2.13M | if (CBS_len(cbs) == 0) { |
734 | 91 | return 0; // OID encodings cannot be empty. |
735 | 91 | } |
736 | | |
737 | 2.13M | CBS copy = *cbs; |
738 | 2.13M | uint8_t v, prev = 0; |
739 | 15.0M | while (CBS_get_u8(©, &v)) { |
740 | | // OID encodings are a sequence of minimally-encoded base-128 integers (see |
741 | | // `CBS_get_asn1_oid_component`). If `prev`'s MSB was clear, it was the last |
742 | | // byte of an integer (or `v` is the first byte). `v` is then the first byte |
743 | | // of the next integer. If first byte of an integer is 0x80, it is not |
744 | | // minimally-encoded. |
745 | 12.8M | if ((prev & 0x80) == 0 && v == 0x80) { |
746 | 112 | return 0; |
747 | 112 | } |
748 | 12.8M | prev = v; |
749 | 12.8M | } |
750 | | |
751 | | // The last byte should must end an integer encoding. |
752 | 2.13M | return (prev & 0x80) == 0; |
753 | 2.13M | } |
754 | | |
755 | 26.8k | char *CBS_asn1_oid_to_text(const CBS *cbs) { |
756 | 26.8k | CBS copy = *cbs; |
757 | 26.8k | CBB cbb; |
758 | 26.8k | if (!CBB_init(&cbb, 32)) { |
759 | 0 | goto err; |
760 | 0 | } |
761 | | |
762 | | // The first component is 40 * value1 + value2, where value1 is 0, 1, or 2. |
763 | 26.8k | uint64_t v; |
764 | 26.8k | if (!CBS_get_asn1_oid_component(©, &v)) { |
765 | 160 | goto err; |
766 | 160 | } |
767 | | |
768 | 26.6k | if (v >= 80) { |
769 | 15.3k | if (!CBB_add_bytes(&cbb, (const uint8_t *)"2.", 2) || |
770 | 15.3k | !cbb_add_decimal_ascii(&cbb, v - 80)) { |
771 | 0 | goto err; |
772 | 0 | } |
773 | 15.3k | } else if (!cbb_add_decimal_ascii(&cbb, v / 40) || !CBB_add_u8(&cbb, '.') || |
774 | 11.2k | !cbb_add_decimal_ascii(&cbb, v % 40)) { |
775 | 0 | goto err; |
776 | 0 | } |
777 | | |
778 | 127k | while (CBS_len(©) != 0) { |
779 | 101k | if (!CBS_get_asn1_oid_component(©, &v) || !CBB_add_u8(&cbb, '.') || |
780 | 100k | !cbb_add_decimal_ascii(&cbb, v)) { |
781 | 209 | goto err; |
782 | 209 | } |
783 | 101k | } |
784 | | |
785 | 26.4k | uint8_t *txt; |
786 | 26.4k | size_t txt_len; |
787 | 26.4k | if (!CBB_add_u8(&cbb, '\0') || !CBB_finish(&cbb, &txt, &txt_len)) { |
788 | 0 | goto err; |
789 | 0 | } |
790 | | |
791 | 26.4k | return (char *)txt; |
792 | | |
793 | 369 | err: |
794 | 369 | CBB_cleanup(&cbb); |
795 | 369 | return nullptr; |
796 | 26.4k | } |
797 | | |
798 | 2.47k | int CBS_is_valid_asn1_relative_oid(const CBS *cbs) { |
799 | 2.47k | return CBS_is_valid_asn1_oid(cbs); |
800 | 2.47k | } |
801 | | |
802 | 0 | char *CBS_asn1_relative_oid_to_text(const CBS *cbs) { |
803 | 0 | ScopedCBB cbb; |
804 | 0 | if (!CBB_init(cbb.get(), 32)) { |
805 | 0 | return nullptr; |
806 | 0 | } |
807 | 0 | if (!CBB_add_asn1_relative_oid_from_der_to_text(cbb.get(), CBS_data(cbs), |
808 | 0 | CBS_len(cbs))) { |
809 | 0 | return nullptr; |
810 | 0 | } |
811 | | |
812 | 0 | uint8_t *txt; |
813 | 0 | size_t txt_len; |
814 | 0 | if (!CBB_add_u8(cbb.get(), '\0') || !CBB_finish(cbb.get(), &txt, &txt_len)) { |
815 | 0 | return nullptr; |
816 | 0 | } |
817 | | |
818 | 0 | return reinterpret_cast<char *>(txt); |
819 | 0 | } |
820 | | |
821 | 2.28M | static int cbs_get_two_digits(CBS *cbs, int *out) { |
822 | 2.28M | uint8_t first_digit, second_digit; |
823 | 2.28M | if (!CBS_get_u8(cbs, &first_digit)) { |
824 | 482 | return 0; |
825 | 482 | } |
826 | 2.28M | if (!OPENSSL_isdigit(first_digit)) { |
827 | 1.36k | return 0; |
828 | 1.36k | } |
829 | 2.28M | if (!CBS_get_u8(cbs, &second_digit)) { |
830 | 372 | return 0; |
831 | 372 | } |
832 | 2.28M | if (!OPENSSL_isdigit(second_digit)) { |
833 | 917 | return 0; |
834 | 917 | } |
835 | 2.28M | *out = (first_digit - '0') * 10 + (second_digit - '0'); |
836 | 2.28M | return 1; |
837 | 2.28M | } |
838 | | |
839 | 379k | static int is_valid_day(int year, int month, int day) { |
840 | 379k | if (day < 1) { |
841 | 38 | return 0; |
842 | 38 | } |
843 | 379k | switch (month) { |
844 | 6.57k | case 1: |
845 | 11.2k | case 3: |
846 | 59.2k | case 5: |
847 | 65.1k | case 7: |
848 | 71.3k | case 8: |
849 | 76.9k | case 10: |
850 | 157k | case 12: |
851 | 157k | return day <= 31; |
852 | 89.1k | case 4: |
853 | 93.7k | case 6: |
854 | 95.8k | case 9: |
855 | 156k | case 11: |
856 | 156k | return day <= 30; |
857 | 66.3k | case 2: |
858 | 66.3k | if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) { |
859 | 31.3k | return day <= 29; |
860 | 35.0k | } else { |
861 | 35.0k | return day <= 28; |
862 | 35.0k | } |
863 | 0 | default: |
864 | 0 | return 0; |
865 | 379k | } |
866 | 379k | } |
867 | | |
868 | | static int CBS_parse_rfc5280_time_internal(const CBS *cbs, int is_gentime, |
869 | | int allow_timezone_offset, |
870 | 382k | struct tm *out_tm) { |
871 | 382k | int year, month, day, hour, min, sec, tmp; |
872 | 382k | CBS copy = *cbs; |
873 | 382k | uint8_t tz; |
874 | | |
875 | 382k | if (is_gentime) { |
876 | 3.69k | if (!cbs_get_two_digits(©, &tmp)) { |
877 | 550 | return 0; |
878 | 550 | } |
879 | 3.14k | year = tmp * 100; |
880 | 3.14k | if (!cbs_get_two_digits(©, &tmp)) { |
881 | 607 | return 0; |
882 | 607 | } |
883 | 2.54k | year += tmp; |
884 | 378k | } else { |
885 | 378k | year = 1900; |
886 | 378k | if (!cbs_get_two_digits(©, &tmp)) { |
887 | 215 | return 0; |
888 | 215 | } |
889 | 378k | year += tmp; |
890 | 378k | if (year < 1950) { |
891 | 363k | year += 100; |
892 | 363k | } |
893 | 378k | if (year >= 2050) { |
894 | 0 | return 0; // A Generalized time must be used. |
895 | 0 | } |
896 | 378k | } |
897 | 381k | if (!cbs_get_two_digits(©, &month) || month < 1 || |
898 | 380k | month > 12 || // Reject invalid months. |
899 | 380k | !cbs_get_two_digits(©, &day) || |
900 | 379k | !is_valid_day(year, month, day) || // Reject invalid days. |
901 | 379k | !cbs_get_two_digits(©, &hour) || |
902 | 379k | hour > 23 || // Reject invalid hours. |
903 | 379k | !cbs_get_two_digits(©, &min) || |
904 | 379k | min > 59 || // Reject invalid minutes. |
905 | 379k | !cbs_get_two_digits(©, &sec) || sec > 59 || !CBS_get_u8(©, &tz)) { |
906 | 2.33k | return 0; |
907 | 2.33k | } |
908 | | |
909 | 378k | int offset_sign = 0; |
910 | 378k | switch (tz) { |
911 | 376k | case 'Z': |
912 | 376k | break; // We correctly have 'Z' on the end as per spec. |
913 | 1.07k | case '+': |
914 | 1.07k | offset_sign = -1; |
915 | 1.07k | break; // Should not be allowed per RFC 5280. |
916 | 605 | case '-': |
917 | 605 | offset_sign = 1; |
918 | 605 | break; // Should not be allowed per RFC 5280. |
919 | 132 | default: |
920 | 132 | return 0; // Reject anything else after the time. |
921 | 378k | } |
922 | | |
923 | | // If allow_timezone_offset is non-zero, allow for a four digit timezone |
924 | | // offset to be specified even though this is not allowed by RFC 5280. We are |
925 | | // permissive of this for UTCTimes due to the unfortunate existence of |
926 | | // artisanally rolled long lived certificates that were baked into places that |
927 | | // are now difficult to change. These certificates were generated with the |
928 | | // 'openssl' command that permissively allowed the creation of certificates |
929 | | // with notBefore and notAfter times specified as strings for direct |
930 | | // certificate inclusion on the command line. For context see cl/237068815. |
931 | | // |
932 | | // TODO(bbe): This has been expunged from public web-pki as the ecosystem has |
933 | | // managed to encourage CA compliance with standards. We should find a way to |
934 | | // get rid of this or make it off by default. |
935 | 378k | int offset_seconds = 0; |
936 | 378k | if (offset_sign != 0) { |
937 | 1.68k | if (!allow_timezone_offset) { |
938 | 24 | return 0; |
939 | 24 | } |
940 | 1.66k | int offset_hours, offset_minutes; |
941 | 1.66k | if (!cbs_get_two_digits(©, &offset_hours) || |
942 | 1.60k | offset_hours > 23 || // Reject invalid hours. |
943 | 1.57k | !cbs_get_two_digits(©, &offset_minutes) || |
944 | 1.53k | offset_minutes > 59) { // Reject invalid minutes. |
945 | 155 | return 0; |
946 | 155 | } |
947 | 1.50k | offset_seconds = offset_sign * (offset_hours * 3600 + offset_minutes * 60); |
948 | 1.50k | } |
949 | | |
950 | 378k | if (CBS_len(©) != 0) { |
951 | 121 | return 0; // Reject invalid lengths. |
952 | 121 | } |
953 | | |
954 | 378k | if (out_tm != nullptr) { |
955 | | // Fill in the tm fields corresponding to what we validated. |
956 | 5.51k | out_tm->tm_year = year - 1900; |
957 | 5.51k | out_tm->tm_mon = month - 1; |
958 | 5.51k | out_tm->tm_mday = day; |
959 | 5.51k | out_tm->tm_hour = hour; |
960 | 5.51k | out_tm->tm_min = min; |
961 | 5.51k | out_tm->tm_sec = sec; |
962 | 5.51k | if (offset_seconds && !OPENSSL_gmtime_adj(out_tm, 0, offset_seconds)) { |
963 | 0 | return 0; |
964 | 0 | } |
965 | 5.51k | } |
966 | 378k | return 1; |
967 | 378k | } |
968 | | |
969 | | int CBS_parse_generalized_time(const CBS *cbs, struct tm *out_tm, |
970 | 3.69k | int allow_timezone_offset) { |
971 | 3.69k | return CBS_parse_rfc5280_time_internal(cbs, 1, allow_timezone_offset, out_tm); |
972 | 3.69k | } |
973 | | |
974 | | int CBS_parse_utc_time(const CBS *cbs, struct tm *out_tm, |
975 | 378k | int allow_timezone_offset) { |
976 | 378k | return CBS_parse_rfc5280_time_internal(cbs, 0, allow_timezone_offset, out_tm); |
977 | 378k | } |