/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 | 679M | static int cbs_get(CBS *cbs, const uint8_t **p, size_t n) { |
31 | 679M | if (cbs->len < n) { |
32 | 8.08M | return 0; |
33 | 8.08M | } |
34 | | |
35 | 671M | *p = cbs->data; |
36 | 671M | cbs->data += n; |
37 | 671M | cbs->len -= n; |
38 | 671M | return 1; |
39 | 679M | } |
40 | | |
41 | 25.5M | int CBS_skip(CBS *cbs, size_t len) { |
42 | 25.5M | const uint8_t *dummy; |
43 | 25.5M | return cbs_get(cbs, &dummy, len); |
44 | 25.5M | } |
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 | 15.4k | int CBS_strdup(const CBS *cbs, char **out_ptr) { |
63 | 15.4k | if (*out_ptr != nullptr) { |
64 | 0 | OPENSSL_free(*out_ptr); |
65 | 0 | } |
66 | 15.4k | *out_ptr = OPENSSL_strndup((const char *)cbs->data, cbs->len); |
67 | 15.4k | return (*out_ptr != nullptr); |
68 | 15.4k | } |
69 | | |
70 | 15.4k | int CBS_contains_zero_byte(const CBS *cbs) { |
71 | 15.4k | return OPENSSL_memchr(cbs->data, 0, cbs->len) != nullptr; |
72 | 15.4k | } |
73 | | |
74 | 71.5k | int CBS_mem_equal(const CBS *cbs, const uint8_t *data, size_t len) { |
75 | 71.5k | if (len != cbs->len) { |
76 | 1.22k | return 0; |
77 | 1.22k | } |
78 | 70.3k | return CRYPTO_memcmp(cbs->data, data, len) == 0; |
79 | 71.5k | } |
80 | | |
81 | 54.7M | static int cbs_get_u(CBS *cbs, uint64_t *out, size_t len) { |
82 | 54.7M | uint64_t result = 0; |
83 | 54.7M | const uint8_t *data; |
84 | | |
85 | 54.7M | if (!cbs_get(cbs, &data, len)) { |
86 | 49.2k | return 0; |
87 | 49.2k | } |
88 | 166M | for (size_t i = 0; i < len; i++) { |
89 | 111M | result <<= 8; |
90 | 111M | result |= data[i]; |
91 | 111M | } |
92 | 54.6M | *out = result; |
93 | 54.6M | return 1; |
94 | 54.7M | } |
95 | | |
96 | 564M | int CBS_get_u8(CBS *cbs, uint8_t *out) { |
97 | 564M | const uint8_t *v; |
98 | 564M | if (!cbs_get(cbs, &v, 1)) { |
99 | 6.39M | return 0; |
100 | 6.39M | } |
101 | 558M | *out = *v; |
102 | 558M | return 1; |
103 | 564M | } |
104 | | |
105 | 44.7M | int CBS_get_u16(CBS *cbs, uint16_t *out) { |
106 | 44.7M | uint64_t v; |
107 | 44.7M | if (!cbs_get_u(cbs, &v, 2)) { |
108 | 22.2k | return 0; |
109 | 22.2k | } |
110 | 44.7M | *out = v; |
111 | 44.7M | return 1; |
112 | 44.7M | } |
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.22M | int CBS_get_u24(CBS *cbs, uint32_t *out) { |
123 | 2.22M | uint64_t v; |
124 | 2.22M | if (!cbs_get_u(cbs, &v, 3)) { |
125 | 14.0k | return 0; |
126 | 14.0k | } |
127 | 2.20M | *out = (uint32_t)v; |
128 | 2.20M | return 1; |
129 | 2.22M | } |
130 | | |
131 | 188k | int CBS_get_u32(CBS *cbs, uint32_t *out) { |
132 | 188k | uint64_t v; |
133 | 188k | if (!cbs_get_u(cbs, &v, 4)) { |
134 | 378 | return 0; |
135 | 378 | } |
136 | 188k | *out = (uint32_t)v; |
137 | 188k | return 1; |
138 | 188k | } |
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 | 80.0k | 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 | 178k | int CBS_get_last_u8(CBS *cbs, uint8_t *out) { |
161 | 178k | if (cbs->len == 0) { |
162 | 131 | return 0; |
163 | 131 | } |
164 | 177k | *out = cbs->data[cbs->len - 1]; |
165 | 177k | cbs->len--; |
166 | 177k | return 1; |
167 | 178k | } |
168 | | |
169 | 34.3M | int CBS_get_bytes(CBS *cbs, CBS *out, size_t len) { |
170 | 34.3M | const uint8_t *v; |
171 | 34.3M | if (!cbs_get(cbs, &v, len)) { |
172 | 1.64M | return 0; |
173 | 1.64M | } |
174 | 32.6M | CBS_init(out, v, len); |
175 | 32.6M | return 1; |
176 | 34.3M | } |
177 | | |
178 | 701 | int CBS_copy_bytes(CBS *cbs, uint8_t *out, size_t len) { |
179 | 701 | const uint8_t *v; |
180 | 701 | if (!cbs_get(cbs, &v, len)) { |
181 | 14 | return 0; |
182 | 14 | } |
183 | 687 | OPENSSL_memcpy(out, v, len); |
184 | 687 | return 1; |
185 | 701 | } |
186 | | |
187 | 4.36M | static int cbs_get_length_prefixed(CBS *cbs, CBS *out, size_t len_len) { |
188 | 4.36M | uint64_t len; |
189 | 4.36M | if (!cbs_get_u(cbs, &len, len_len)) { |
190 | 9.29k | return 0; |
191 | 9.29k | } |
192 | | // If `len_len` <= 3 then we know that `len` will fit into a `size_t`, even on |
193 | | // 32-bit systems. |
194 | 4.36M | assert(len_len <= 3); |
195 | 4.35M | return CBS_get_bytes(cbs, out, len); |
196 | 4.35M | } |
197 | | |
198 | 442k | int CBS_get_u8_length_prefixed(CBS *cbs, CBS *out) { |
199 | 442k | return cbs_get_length_prefixed(cbs, out, 1); |
200 | 442k | } |
201 | | |
202 | 3.43M | int CBS_get_u16_length_prefixed(CBS *cbs, CBS *out) { |
203 | 3.43M | return cbs_get_length_prefixed(cbs, out, 2); |
204 | 3.43M | } |
205 | | |
206 | 493k | int CBS_get_u24_length_prefixed(CBS *cbs, CBS *out) { |
207 | 493k | return cbs_get_length_prefixed(cbs, out, 3); |
208 | 493k | } |
209 | | |
210 | 154k | int CBS_get_until_first(CBS *cbs, CBS *out, uint8_t c) { |
211 | 154k | const uint8_t *split = reinterpret_cast<const uint8_t *>( |
212 | 154k | OPENSSL_memchr(CBS_data(cbs), c, CBS_len(cbs))); |
213 | 154k | if (split == nullptr) { |
214 | 3.28k | return 0; |
215 | 3.28k | } |
216 | 150k | return CBS_get_bytes(cbs, out, split - CBS_data(cbs)); |
217 | 154k | } |
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 | 52.3k | int CBS_get_u64_decimal(CBS *cbs, uint64_t *out) { |
256 | 52.3k | uint64_t v = 0; |
257 | 52.3k | int seen_digit = 0; |
258 | 187k | while (CBS_len(cbs) != 0) { |
259 | 171k | uint8_t c = CBS_data(cbs)[0]; |
260 | 171k | if (!OPENSSL_isdigit(c)) { |
261 | 35.6k | break; |
262 | 35.6k | } |
263 | 135k | CBS_skip(cbs, 1); |
264 | 135k | if (/* Forbid stray leading zeros */ |
265 | 135k | (v == 0 && seen_digit) || |
266 | | // Check for overflow. |
267 | 135k | v > UINT64_MAX / 10 || // |
268 | 135k | v * 10 > UINT64_MAX - (c - '0')) { |
269 | 175 | return 0; |
270 | 175 | } |
271 | 135k | v = v * 10 + (c - '0'); |
272 | 135k | seen_digit = 1; |
273 | 135k | } |
274 | | |
275 | 52.1k | *out = v; |
276 | 52.1k | return seen_digit; |
277 | 52.3k | } |
278 | | |
279 | 309k | int CBS_get_asn1_oid_component(CBS *cbs, uint64_t *out) { |
280 | 309k | uint64_t v = 0; |
281 | 309k | uint8_t b; |
282 | 771k | do { |
283 | 771k | if (!CBS_get_u8(cbs, &b)) { |
284 | 26.3k | return 0; |
285 | 26.3k | } |
286 | 744k | if ((v >> (64 - 7)) != 0) { |
287 | | // The value is too large. |
288 | 1.45k | return 0; |
289 | 1.45k | } |
290 | 743k | if (v == 0 && b == 0x80) { |
291 | | // The value must be minimally encoded. |
292 | 2.96k | return 0; |
293 | 2.96k | } |
294 | 740k | v = (v << 7) | (b & 0x7f); |
295 | | |
296 | | // Values end at an octet with the high bit cleared. |
297 | 740k | } while (b & 0x80); |
298 | | |
299 | 278k | *out = v; |
300 | 278k | return 1; |
301 | 309k | } |
302 | | |
303 | 34.0M | static int parse_asn1_tag(CBS *cbs, CBS_ASN1_TAG *out) { |
304 | 34.0M | uint8_t tag_byte; |
305 | 34.0M | if (!CBS_get_u8(cbs, &tag_byte)) { |
306 | 1.78M | return 0; |
307 | 1.78M | } |
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.3M | CBS_ASN1_TAG tag = ((CBS_ASN1_TAG)tag_byte & 0xe0) << CBS_ASN1_TAG_SHIFT; |
316 | 32.3M | CBS_ASN1_TAG tag_number = tag_byte & 0x1f; |
317 | 32.3M | if (tag_number == 0x1f) { |
318 | | // High tag numbers are encoded in the same format as OID components. |
319 | 183k | uint64_t v; |
320 | 183k | if (!CBS_get_asn1_oid_component(cbs, &v) || |
321 | | // Check the tag number is within our supported bounds. |
322 | 153k | 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 | 58.6k | return 0; |
326 | 58.6k | } |
327 | 124k | tag_number = (CBS_ASN1_TAG)v; |
328 | 124k | } |
329 | | |
330 | 32.2M | 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.2M | if ((tag & ~CBS_ASN1_CONSTRUCTED) == 0) { |
336 | 27.2k | return 0; |
337 | 27.2k | } |
338 | | |
339 | 32.2M | *out = tag; |
340 | 32.2M | return 1; |
341 | 32.2M | } |
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 | 26.2M | int *out_indefinite, int ber_ok) { |
346 | 26.2M | CBS header = *cbs; |
347 | 26.2M | CBS throwaway; |
348 | | |
349 | 26.2M | if (out == nullptr) { |
350 | 2.92M | out = &throwaway; |
351 | 2.92M | } |
352 | 26.2M | if (ber_ok) { |
353 | 1.88M | *out_ber_found = 0; |
354 | 1.88M | *out_indefinite = 0; |
355 | 24.3M | } else { |
356 | 24.3M | assert(out_ber_found == nullptr); |
357 | 24.3M | assert(out_indefinite == nullptr); |
358 | 24.3M | } |
359 | | |
360 | 26.2M | CBS_ASN1_TAG tag; |
361 | 26.2M | if (!parse_asn1_tag(&header, &tag)) { |
362 | 36.5k | return 0; |
363 | 36.5k | } |
364 | 26.2M | if (out_tag != nullptr) { |
365 | 21.9M | *out_tag = tag; |
366 | 21.9M | } |
367 | | |
368 | 26.2M | uint8_t length_byte; |
369 | 26.2M | if (!CBS_get_u8(&header, &length_byte)) { |
370 | 13.0k | return 0; |
371 | 13.0k | } |
372 | | |
373 | 26.2M | size_t header_len = CBS_len(cbs) - CBS_len(&header); |
374 | | |
375 | 26.2M | size_t len; |
376 | | // The format for the length encoding is specified in ITU-T X.690 section |
377 | | // 8.1.3. |
378 | 26.2M | if ((length_byte & 0x80) == 0) { |
379 | | // Short form length. |
380 | 23.0M | len = ((size_t)length_byte) + header_len; |
381 | 23.0M | if (out_header_len != nullptr) { |
382 | 19.5M | *out_header_len = header_len; |
383 | 19.5M | } |
384 | 23.0M | } 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 | 3.12M | const size_t num_bytes = length_byte & 0x7f; |
389 | 3.12M | uint64_t len64; |
390 | | |
391 | 3.12M | if (ber_ok && (tag & CBS_ASN1_CONSTRUCTED) != 0 && num_bytes == 0) { |
392 | | // indefinite length |
393 | 21.9k | if (out_header_len != nullptr) { |
394 | 21.9k | *out_header_len = header_len; |
395 | 21.9k | } |
396 | 21.9k | *out_ber_found = 1; |
397 | 21.9k | *out_indefinite = 1; |
398 | 21.9k | return CBS_get_bytes(cbs, out, header_len); |
399 | 21.9k | } |
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 | 3.10M | if (num_bytes == 0 || num_bytes > 4) { |
405 | 9.39k | return 0; |
406 | 9.39k | } |
407 | 3.09M | if (!cbs_get_u(&header, &len64, num_bytes)) { |
408 | 1.08k | return 0; |
409 | 1.08k | } |
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.09M | if (len64 < 128) { |
415 | | // Length should have used short-form encoding. |
416 | 4.82k | if (ber_ok) { |
417 | 2.25k | *out_ber_found = 1; |
418 | 2.56k | } else { |
419 | 2.56k | return 0; |
420 | 2.56k | } |
421 | 4.82k | } |
422 | 3.08M | if ((len64 >> ((num_bytes - 1) * 8)) == 0) { |
423 | | // Length should have been at least one byte shorter. |
424 | 3.45k | if (ber_ok) { |
425 | 1.48k | *out_ber_found = 1; |
426 | 1.97k | } else { |
427 | 1.97k | return 0; |
428 | 1.97k | } |
429 | 3.45k | } |
430 | 3.08M | len = len64; |
431 | 3.08M | if (len + header_len + num_bytes < len) { |
432 | | // Overflow. |
433 | 0 | return 0; |
434 | 0 | } |
435 | 3.08M | len += header_len + num_bytes; |
436 | 3.08M | if (out_header_len != nullptr) { |
437 | 2.29M | *out_header_len = header_len + num_bytes; |
438 | 2.29M | } |
439 | 3.08M | } |
440 | | |
441 | 26.1M | return CBS_get_bytes(cbs, out, len); |
442 | 26.2M | } |
443 | | |
444 | 1.21k | int CBS_get_any_asn1(CBS *cbs, CBS *out, CBS_ASN1_TAG *out_tag) { |
445 | 1.21k | size_t header_len; |
446 | 1.21k | if (!CBS_get_any_asn1_element(cbs, out, out_tag, &header_len)) { |
447 | 455 | return 0; |
448 | 455 | } |
449 | | |
450 | 756 | if (out && !CBS_skip(out, header_len)) { |
451 | 0 | assert(0); |
452 | 0 | return 0; |
453 | 0 | } |
454 | | |
455 | 756 | return 1; |
456 | 756 | } |
457 | | |
458 | | int CBS_get_any_asn1_element(CBS *cbs, CBS *out, CBS_ASN1_TAG *out_tag, |
459 | 24.3M | size_t *out_header_len) { |
460 | 24.3M | return cbs_get_any_asn1_element(cbs, out, out_tag, out_header_len, nullptr, |
461 | 24.3M | nullptr, |
462 | 24.3M | /*ber_ok=*/0); |
463 | 24.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.88M | int *out_indefinite) { |
468 | 1.88M | int ber_found_temp; |
469 | 1.88M | return cbs_get_any_asn1_element( |
470 | 1.88M | cbs, out, out_tag, out_header_len, |
471 | 1.88M | out_ber_found ? out_ber_found : &ber_found_temp, out_indefinite, |
472 | 1.88M | /*ber_ok=*/1); |
473 | 1.88M | } |
474 | | |
475 | | static int cbs_get_asn1(CBS *cbs, CBS *out, CBS_ASN1_TAG tag_value, |
476 | 15.9M | int skip_header) { |
477 | 15.9M | size_t header_len; |
478 | 15.9M | CBS_ASN1_TAG tag; |
479 | 15.9M | CBS throwaway; |
480 | | |
481 | 15.9M | if (out == nullptr) { |
482 | 645k | out = &throwaway; |
483 | 645k | } |
484 | | |
485 | 15.9M | 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 | 125k | int CBS_get_asn1_element(CBS *cbs, CBS *out, CBS_ASN1_TAG tag_value) { |
503 | 125k | return cbs_get_asn1(cbs, out, tag_value, 0 /* include header */); |
504 | 125k | } |
505 | | |
506 | 7.83M | CBS_ASN1_TAG CBS_peek_any_asn1_tag(const CBS *cbs) { |
507 | 7.83M | CBS copy = *cbs; |
508 | 7.83M | CBS_ASN1_TAG tag; |
509 | 7.83M | if (!parse_asn1_tag(©, &tag)) { |
510 | 1.82M | return 0; |
511 | 1.82M | } |
512 | 6.00M | return tag; |
513 | 7.83M | } |
514 | | |
515 | 7.83M | int CBS_peek_asn1_tag(const CBS *cbs, CBS_ASN1_TAG tag_value) { |
516 | 7.83M | 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.83M | return actual_tag != 0 && actual_tag == tag_value; |
520 | 7.83M | } |
521 | | |
522 | 998k | int CBS_get_asn1_uint64(CBS *cbs, uint64_t *out) { |
523 | 998k | return CBS_get_asn1_uint64_with_tag(cbs, out, CBS_ASN1_INTEGER); |
524 | 998k | } |
525 | | |
526 | 998k | int CBS_get_asn1_uint64_with_tag(CBS *cbs, uint64_t *out, CBS_ASN1_TAG tag) { |
527 | 998k | CBS bytes; |
528 | 998k | if (!CBS_get_asn1(cbs, &bytes, tag) || |
529 | 990k | !CBS_is_unsigned_asn1_integer(&bytes)) { |
530 | 10.8k | return 0; |
531 | 10.8k | } |
532 | | |
533 | 987k | *out = 0; |
534 | 987k | const uint8_t *data = CBS_data(&bytes); |
535 | 987k | size_t len = CBS_len(&bytes); |
536 | 2.63M | for (size_t i = 0; i < len; i++) { |
537 | 1.65M | if ((*out >> 56) != 0) { |
538 | | // Too large to represent as a uint64_t. |
539 | 1.39k | return 0; |
540 | 1.39k | } |
541 | 1.64M | *out <<= 8; |
542 | 1.64M | *out |= data[i]; |
543 | 1.64M | } |
544 | | |
545 | 986k | return 1; |
546 | 987k | } |
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.36k | int CBS_get_asn1_bool(CBS *cbs, int *out) { |
572 | 1.36k | CBS bytes; |
573 | 1.36k | if (!CBS_get_asn1(cbs, &bytes, CBS_ASN1_BOOLEAN) || CBS_len(&bytes) != 1) { |
574 | 166 | return 0; |
575 | 166 | } |
576 | | |
577 | 1.19k | const uint8_t value = *CBS_data(&bytes); |
578 | 1.19k | if (value != 0 && value != 0xff) { |
579 | 46 | return 0; |
580 | 46 | } |
581 | | |
582 | 1.15k | *out = !!value; |
583 | 1.15k | return 1; |
584 | 1.19k | } |
585 | | |
586 | | int CBS_get_optional_asn1(CBS *cbs, CBS *out, int *out_present, |
587 | 3.67M | CBS_ASN1_TAG tag) { |
588 | 3.67M | int present = 0; |
589 | | |
590 | 3.67M | if (CBS_peek_asn1_tag(cbs, tag)) { |
591 | 917k | if (!CBS_get_asn1(cbs, out, tag)) { |
592 | 9.08k | return 0; |
593 | 9.08k | } |
594 | 908k | present = 1; |
595 | 908k | } |
596 | | |
597 | 3.66M | if (out_present != nullptr) { |
598 | 3.35M | *out_present = present; |
599 | 3.35M | } |
600 | | |
601 | 3.66M | return 1; |
602 | 3.67M | } |
603 | | |
604 | | int CBS_get_optional_asn1_octet_string(CBS *cbs, CBS *out, int *out_present, |
605 | 1.17M | CBS_ASN1_TAG tag) { |
606 | 1.17M | CBS child; |
607 | 1.17M | int present; |
608 | 1.17M | if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) { |
609 | 82 | return 0; |
610 | 82 | } |
611 | 1.17M | if (present) { |
612 | 260k | assert(out); |
613 | 260k | if (!CBS_get_asn1(&child, out, CBS_ASN1_OCTETSTRING) || |
614 | 259k | CBS_len(&child) != 0) { |
615 | 393 | return 0; |
616 | 393 | } |
617 | 913k | } else { |
618 | 913k | CBS_init(out, nullptr, 0); |
619 | 913k | } |
620 | 1.17M | if (out_present) { |
621 | 520k | *out_present = present; |
622 | 520k | } |
623 | 1.17M | return 1; |
624 | 1.17M | } |
625 | | |
626 | | int CBS_get_optional_asn1_uint64(CBS *cbs, uint64_t *out, CBS_ASN1_TAG tag, |
627 | 785k | uint64_t default_value) { |
628 | 785k | CBS child; |
629 | 785k | int present; |
630 | 785k | if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) { |
631 | 47 | return 0; |
632 | 47 | } |
633 | 785k | if (present) { |
634 | 210k | if (!CBS_get_asn1_uint64(&child, out) || CBS_len(&child) != 0) { |
635 | 53 | return 0; |
636 | 53 | } |
637 | 575k | } else { |
638 | 575k | *out = default_value; |
639 | 575k | } |
640 | 785k | return 1; |
641 | 785k | } |
642 | | |
643 | | int CBS_get_optional_asn1_bool(CBS *cbs, int *out, CBS_ASN1_TAG tag, |
644 | 519k | int default_value) { |
645 | 519k | CBS child, child2; |
646 | 519k | int present; |
647 | 519k | if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) { |
648 | 32 | return 0; |
649 | 32 | } |
650 | 519k | if (present) { |
651 | 142k | uint8_t boolean; |
652 | | |
653 | 142k | if (!CBS_get_asn1(&child, &child2, CBS_ASN1_BOOLEAN) || |
654 | 141k | CBS_len(&child2) != 1 || CBS_len(&child) != 0) { |
655 | 437 | return 0; |
656 | 437 | } |
657 | | |
658 | 141k | boolean = CBS_data(&child2)[0]; |
659 | 141k | if (boolean == 0) { |
660 | 67.4k | *out = 0; |
661 | 74.3k | } else if (boolean == 0xff) { |
662 | 74.2k | *out = 1; |
663 | 74.2k | } else { |
664 | 63 | return 0; |
665 | 63 | } |
666 | 377k | } else { |
667 | 377k | *out = default_value; |
668 | 377k | } |
669 | 519k | return 1; |
670 | 519k | } |
671 | | |
672 | 438 | int CBS_is_valid_asn1_bitstring(const CBS *cbs) { |
673 | 438 | CBS in = *cbs; |
674 | 438 | uint8_t num_unused_bits; |
675 | 438 | if (!CBS_get_u8(&in, &num_unused_bits) || num_unused_bits > 7) { |
676 | 11 | return 0; |
677 | 11 | } |
678 | | |
679 | 427 | if (num_unused_bits == 0) { |
680 | 34 | return 1; |
681 | 34 | } |
682 | | |
683 | | // All num_unused_bits bits must exist and be zeros. |
684 | 393 | uint8_t last; |
685 | 393 | if (!CBS_get_last_u8(&in, &last) || |
686 | 393 | (last & ((1 << num_unused_bits) - 1)) != 0) { |
687 | 9 | return 0; |
688 | 9 | } |
689 | | |
690 | 384 | return 1; |
691 | 393 | } |
692 | | |
693 | 209 | int CBS_asn1_bitstring_has_bit(const CBS *cbs, unsigned bit) { |
694 | 209 | if (!CBS_is_valid_asn1_bitstring(cbs)) { |
695 | 0 | return 0; |
696 | 0 | } |
697 | | |
698 | 209 | const unsigned byte_num = (bit >> 3) + 1; |
699 | 209 | 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 | 209 | return byte_num < CBS_len(cbs) && |
705 | 209 | (CBS_data(cbs)[byte_num] & (1 << bit_num)) != 0; |
706 | 209 | } |
707 | | |
708 | 1.56M | int CBS_is_valid_asn1_integer(const CBS *cbs, int *out_is_negative) { |
709 | 1.56M | CBS copy = *cbs; |
710 | 1.56M | uint8_t first_byte, second_byte; |
711 | 1.56M | if (!CBS_get_u8(©, &first_byte)) { |
712 | 7.43k | return 0; // INTEGERs may not be empty. |
713 | 7.43k | } |
714 | 1.55M | if (out_is_negative != nullptr) { |
715 | 1.55M | *out_is_negative = (first_byte & 0x80) != 0; |
716 | 1.55M | } |
717 | 1.55M | if (!CBS_get_u8(©, &second_byte)) { |
718 | 534k | return 1; // One byte INTEGERs are always minimal. |
719 | 534k | } |
720 | 1.02M | if ((first_byte == 0x00 && (second_byte & 0x80) == 0) || |
721 | 1.02M | (first_byte == 0xff && (second_byte & 0x80) != 0)) { |
722 | 4.96k | return 0; // The value is minimal iff the first 9 bits are not all equal. |
723 | 4.96k | } |
724 | 1.01M | return 1; |
725 | 1.02M | } |
726 | | |
727 | 994k | int CBS_is_unsigned_asn1_integer(const CBS *cbs) { |
728 | 994k | int is_negative; |
729 | 994k | return CBS_is_valid_asn1_integer(cbs, &is_negative) && !is_negative; |
730 | 994k | } |
731 | | |
732 | 2.17M | int CBS_is_valid_asn1_oid(const CBS *cbs) { |
733 | 2.17M | if (CBS_len(cbs) == 0) { |
734 | 68 | return 0; // OID encodings cannot be empty. |
735 | 68 | } |
736 | | |
737 | 2.17M | CBS copy = *cbs; |
738 | 2.17M | uint8_t v, prev = 0; |
739 | 16.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 | 13.8M | if ((prev & 0x80) == 0 && v == 0x80) { |
746 | 54 | return 0; |
747 | 54 | } |
748 | 13.8M | prev = v; |
749 | 13.8M | } |
750 | | |
751 | | // The last byte should must end an integer encoding. |
752 | 2.17M | return (prev & 0x80) == 0; |
753 | 2.17M | } |
754 | | |
755 | 27.1k | char *CBS_asn1_oid_to_text(const CBS *cbs) { |
756 | 27.1k | CBS copy = *cbs; |
757 | 27.1k | CBB cbb; |
758 | 27.1k | 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 | 27.1k | uint64_t v; |
764 | 27.1k | if (!CBS_get_asn1_oid_component(©, &v)) { |
765 | 166 | goto err; |
766 | 166 | } |
767 | | |
768 | 27.0k | 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.6k | !cbb_add_decimal_ascii(&cbb, v % 40)) { |
775 | 0 | goto err; |
776 | 0 | } |
777 | | |
778 | 125k | while (CBS_len(©) != 0) { |
779 | 98.7k | if (!CBS_get_asn1_oid_component(©, &v) || !CBB_add_u8(&cbb, '.') || |
780 | 98.4k | !cbb_add_decimal_ascii(&cbb, v)) { |
781 | 235 | goto err; |
782 | 235 | } |
783 | 98.7k | } |
784 | | |
785 | 26.7k | uint8_t *txt; |
786 | 26.7k | size_t txt_len; |
787 | 26.7k | if (!CBB_add_u8(&cbb, '\0') || !CBB_finish(&cbb, &txt, &txt_len)) { |
788 | 0 | goto err; |
789 | 0 | } |
790 | | |
791 | 26.7k | return (char *)txt; |
792 | | |
793 | 401 | err: |
794 | 401 | CBB_cleanup(&cbb); |
795 | 401 | return nullptr; |
796 | 26.7k | } |
797 | | |
798 | 0 | int CBS_is_valid_asn1_relative_oid(const CBS *cbs) { |
799 | 0 | return CBS_is_valid_asn1_oid(cbs); |
800 | 0 | } |
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.35M | static int cbs_get_two_digits(CBS *cbs, int *out) { |
822 | 2.35M | uint8_t first_digit, second_digit; |
823 | 2.35M | if (!CBS_get_u8(cbs, &first_digit)) { |
824 | 514 | return 0; |
825 | 514 | } |
826 | 2.35M | if (!OPENSSL_isdigit(first_digit)) { |
827 | 1.11k | return 0; |
828 | 1.11k | } |
829 | 2.35M | if (!CBS_get_u8(cbs, &second_digit)) { |
830 | 356 | return 0; |
831 | 356 | } |
832 | 2.35M | if (!OPENSSL_isdigit(second_digit)) { |
833 | 902 | return 0; |
834 | 902 | } |
835 | 2.35M | *out = (first_digit - '0') * 10 + (second_digit - '0'); |
836 | 2.35M | return 1; |
837 | 2.35M | } |
838 | | |
839 | 390k | static int is_valid_day(int year, int month, int day) { |
840 | 390k | if (day < 1) { |
841 | 40 | return 0; |
842 | 40 | } |
843 | 390k | switch (month) { |
844 | 5.28k | case 1: |
845 | 10.0k | case 3: |
846 | 58.2k | case 5: |
847 | 65.3k | case 7: |
848 | 71.8k | case 8: |
849 | 77.5k | case 10: |
850 | 142k | case 12: |
851 | 142k | return day <= 31; |
852 | 83.3k | case 4: |
853 | 87.7k | case 6: |
854 | 89.9k | case 9: |
855 | 172k | case 11: |
856 | 172k | return day <= 30; |
857 | 75.9k | case 2: |
858 | 75.9k | if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) { |
859 | 36.3k | return day <= 29; |
860 | 39.5k | } else { |
861 | 39.5k | return day <= 28; |
862 | 39.5k | } |
863 | 0 | default: |
864 | 0 | return 0; |
865 | 390k | } |
866 | 390k | } |
867 | | |
868 | | static int CBS_parse_rfc5280_time_internal(const CBS *cbs, int is_gentime, |
869 | | int allow_timezone_offset, |
870 | 393k | struct tm *out_tm) { |
871 | 393k | int year, month, day, hour, min, sec, tmp; |
872 | 393k | CBS copy = *cbs; |
873 | 393k | uint8_t tz; |
874 | | |
875 | 393k | if (is_gentime) { |
876 | 3.49k | if (!cbs_get_two_digits(©, &tmp)) { |
877 | 545 | return 0; |
878 | 545 | } |
879 | 2.94k | year = tmp * 100; |
880 | 2.94k | if (!cbs_get_two_digits(©, &tmp)) { |
881 | 570 | return 0; |
882 | 570 | } |
883 | 2.37k | year += tmp; |
884 | 389k | } else { |
885 | 389k | year = 1900; |
886 | 389k | if (!cbs_get_two_digits(©, &tmp)) { |
887 | 214 | return 0; |
888 | 214 | } |
889 | 389k | year += tmp; |
890 | 389k | if (year < 1950) { |
891 | 372k | year += 100; |
892 | 372k | } |
893 | 389k | if (year >= 2050) { |
894 | 0 | return 0; // A Generalized time must be used. |
895 | 0 | } |
896 | 389k | } |
897 | 391k | if (!cbs_get_two_digits(©, &month) || month < 1 || |
898 | 391k | month > 12 || // Reject invalid months. |
899 | 391k | !cbs_get_two_digits(©, &day) || |
900 | 390k | !is_valid_day(year, month, day) || // Reject invalid days. |
901 | 390k | !cbs_get_two_digits(©, &hour) || |
902 | 390k | hour > 23 || // Reject invalid hours. |
903 | 390k | !cbs_get_two_digits(©, &min) || |
904 | 390k | min > 59 || // Reject invalid minutes. |
905 | 390k | !cbs_get_two_digits(©, &sec) || sec > 59 || !CBS_get_u8(©, &tz)) { |
906 | 2.14k | return 0; |
907 | 2.14k | } |
908 | | |
909 | 389k | int offset_sign = 0; |
910 | 389k | switch (tz) { |
911 | 388k | case 'Z': |
912 | 388k | break; // We correctly have 'Z' on the end as per spec. |
913 | 984 | case '+': |
914 | 984 | offset_sign = -1; |
915 | 984 | break; // Should not be allowed per RFC 5280. |
916 | 658 | case '-': |
917 | 658 | offset_sign = 1; |
918 | 658 | break; // Should not be allowed per RFC 5280. |
919 | 148 | default: |
920 | 148 | return 0; // Reject anything else after the time. |
921 | 389k | } |
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 | 389k | int offset_seconds = 0; |
936 | 389k | if (offset_sign != 0) { |
937 | 1.64k | if (!allow_timezone_offset) { |
938 | 27 | return 0; |
939 | 27 | } |
940 | 1.61k | int offset_hours, offset_minutes; |
941 | 1.61k | if (!cbs_get_two_digits(©, &offset_hours) || |
942 | 1.55k | offset_hours > 23 || // Reject invalid hours. |
943 | 1.52k | !cbs_get_two_digits(©, &offset_minutes) || |
944 | 1.48k | offset_minutes > 59) { // Reject invalid minutes. |
945 | 160 | return 0; |
946 | 160 | } |
947 | 1.45k | offset_seconds = offset_sign * (offset_hours * 3600 + offset_minutes * 60); |
948 | 1.45k | } |
949 | | |
950 | 389k | if (CBS_len(©) != 0) { |
951 | 115 | return 0; // Reject invalid lengths. |
952 | 115 | } |
953 | | |
954 | 389k | if (out_tm != nullptr) { |
955 | | // Fill in the tm fields corresponding to what we validated. |
956 | 5.73k | out_tm->tm_year = year - 1900; |
957 | 5.73k | out_tm->tm_mon = month - 1; |
958 | 5.73k | out_tm->tm_mday = day; |
959 | 5.73k | out_tm->tm_hour = hour; |
960 | 5.73k | out_tm->tm_min = min; |
961 | 5.73k | out_tm->tm_sec = sec; |
962 | 5.73k | if (offset_seconds && !OPENSSL_gmtime_adj(out_tm, 0, offset_seconds)) { |
963 | 0 | return 0; |
964 | 0 | } |
965 | 5.73k | } |
966 | 389k | return 1; |
967 | 389k | } |
968 | | |
969 | | int CBS_parse_generalized_time(const CBS *cbs, struct tm *out_tm, |
970 | 3.49k | int allow_timezone_offset) { |
971 | 3.49k | return CBS_parse_rfc5280_time_internal(cbs, 1, allow_timezone_offset, out_tm); |
972 | 3.49k | } |
973 | | |
974 | | int CBS_parse_utc_time(const CBS *cbs, struct tm *out_tm, |
975 | 389k | int allow_timezone_offset) { |
976 | 389k | return CBS_parse_rfc5280_time_internal(cbs, 0, allow_timezone_offset, out_tm); |
977 | 389k | } |