/src/boringssl/pki/parse_values.cc
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright 2015 The Chromium 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 "parse_values.h" |
16 | | |
17 | | #include <stdlib.h> |
18 | | |
19 | | #include <tuple> |
20 | | |
21 | | #include <openssl/base.h> |
22 | | #include <openssl/bytestring.h> |
23 | | #include <openssl/mem.h> |
24 | | |
25 | | BSSL_NAMESPACE_BEGIN |
26 | | namespace der { |
27 | | |
28 | | namespace { |
29 | | |
30 | 1.75k | bool ParseBoolInternal(Input in, bool *out, bool relaxed) { |
31 | | // According to ITU-T X.690 section 8.2, a bool is encoded as a single octet |
32 | | // where the octet of all zeroes is FALSE and a non-zero value for the octet |
33 | | // is TRUE. |
34 | 1.75k | if (in.size() != 1) { |
35 | 51 | return false; |
36 | 51 | } |
37 | 1.70k | ByteReader data(in); |
38 | 1.70k | uint8_t byte; |
39 | 1.70k | if (!data.ReadByte(&byte)) { |
40 | 0 | return false; |
41 | 0 | } |
42 | 1.70k | if (byte == 0) { |
43 | 12 | *out = false; |
44 | 12 | return true; |
45 | 12 | } |
46 | | // ITU-T X.690 section 11.1 specifies that for DER, the TRUE value must be |
47 | | // encoded as an octet of all ones. |
48 | 1.68k | if (byte == 0xff || relaxed) { |
49 | 1.65k | *out = true; |
50 | 1.65k | return true; |
51 | 1.65k | } |
52 | 37 | return false; |
53 | 1.68k | } |
54 | | |
55 | | // Reads a positive decimal number with |digits| digits and stores it in |
56 | | // |*out|. This function does not check that the type of |*out| is large |
57 | | // enough to hold 10^digits - 1; the caller must choose an appropriate type |
58 | | // based on the number of digits they wish to parse. |
59 | | template <typename UINT> |
60 | 74.5k | bool DecimalStringToUint(ByteReader &in, size_t digits, UINT *out) { |
61 | 74.5k | UINT value = 0; |
62 | 230k | for (size_t i = 0; i < digits; ++i) { |
63 | 156k | uint8_t digit; |
64 | 156k | if (!in.ReadByte(&digit)) { |
65 | 350 | return false; |
66 | 350 | } |
67 | 156k | if (digit < '0' || digit > '9') { |
68 | 567 | return false; |
69 | 567 | } |
70 | 155k | value = (value * 10) + (digit - '0'); |
71 | 155k | } |
72 | 73.6k | *out = value; |
73 | 73.6k | return true; |
74 | 74.5k | } parse_values.cc:bool bssl::der::(anonymous namespace)::DecimalStringToUint<unsigned short>(bssl::der::ByteReader&, unsigned long, unsigned short*) Line | Count | Source | 60 | 12.8k | bool DecimalStringToUint(ByteReader &in, size_t digits, UINT *out) { | 61 | 12.8k | UINT value = 0; | 62 | 46.2k | for (size_t i = 0; i < digits; ++i) { | 63 | 33.6k | uint8_t digit; | 64 | 33.6k | if (!in.ReadByte(&digit)) { | 65 | 78 | return false; | 66 | 78 | } | 67 | 33.5k | if (digit < '0' || digit > '9') { | 68 | 113 | return false; | 69 | 113 | } | 70 | 33.4k | value = (value * 10) + (digit - '0'); | 71 | 33.4k | } | 72 | 12.6k | *out = value; | 73 | 12.6k | return true; | 74 | 12.8k | } |
parse_values.cc:bool bssl::der::(anonymous namespace)::DecimalStringToUint<unsigned char>(bssl::der::ByteReader&, unsigned long, unsigned char*) Line | Count | Source | 60 | 61.7k | bool DecimalStringToUint(ByteReader &in, size_t digits, UINT *out) { | 61 | 61.7k | UINT value = 0; | 62 | 183k | for (size_t i = 0; i < digits; ++i) { | 63 | 122k | uint8_t digit; | 64 | 122k | if (!in.ReadByte(&digit)) { | 65 | 272 | return false; | 66 | 272 | } | 67 | 122k | if (digit < '0' || digit > '9') { | 68 | 454 | return false; | 69 | 454 | } | 70 | 122k | value = (value * 10) + (digit - '0'); | 71 | 122k | } | 72 | 60.9k | *out = value; | 73 | 60.9k | return true; | 74 | 61.7k | } |
|
75 | | |
76 | | // Checks that the values in a GeneralizedTime struct are valid. This involves |
77 | | // checking that the year is 4 digits, the month is between 1 and 12, the day |
78 | | // is a day that exists in that month (following current leap year rules), |
79 | | // hours are between 0 and 23, minutes between 0 and 59, and seconds between |
80 | | // 0 and 60 (to allow for leap seconds; no validation is done that a leap |
81 | | // second is on a day that could be a leap second). |
82 | 11.7k | bool ValidateGeneralizedTime(const GeneralizedTime &time) { |
83 | 11.7k | if (time.month < 1 || time.month > 12) { |
84 | 17 | return false; |
85 | 17 | } |
86 | 11.7k | if (time.day < 1) { |
87 | 5 | return false; |
88 | 5 | } |
89 | 11.7k | if (time.hours > 23) { |
90 | 9 | return false; |
91 | 9 | } |
92 | 11.7k | if (time.minutes > 59) { |
93 | 10 | return false; |
94 | 10 | } |
95 | | // Leap seconds are allowed. |
96 | 11.7k | if (time.seconds > 60) { |
97 | 9 | return false; |
98 | 9 | } |
99 | | |
100 | | // validate upper bound for day of month |
101 | 11.6k | switch (time.month) { |
102 | 1.32k | case 4: |
103 | 2.11k | case 6: |
104 | 2.86k | case 9: |
105 | 3.55k | case 11: |
106 | 3.55k | if (time.day > 30) { |
107 | 24 | return false; |
108 | 24 | } |
109 | 3.52k | break; |
110 | 3.52k | case 1: |
111 | 1.63k | case 3: |
112 | 2.19k | case 5: |
113 | 2.82k | case 7: |
114 | 4.09k | case 8: |
115 | 4.96k | case 10: |
116 | 5.60k | case 12: |
117 | 5.60k | if (time.day > 31) { |
118 | 25 | return false; |
119 | 25 | } |
120 | 5.58k | break; |
121 | 5.58k | case 2: |
122 | 2.53k | if (time.year % 4 == 0 && |
123 | 2.53k | (time.year % 100 != 0 || time.year % 400 == 0)) { |
124 | 1.20k | if (time.day > 29) { |
125 | 23 | return false; |
126 | 23 | } |
127 | 1.32k | } else { |
128 | 1.32k | if (time.day > 28) { |
129 | 23 | return false; |
130 | 23 | } |
131 | 1.32k | } |
132 | 2.49k | break; |
133 | 2.49k | default: |
134 | 0 | abort(); |
135 | 11.6k | } |
136 | 11.5k | return true; |
137 | 11.6k | } |
138 | | |
139 | | // Returns the number of bytes of numeric precision in a DER encoded INTEGER |
140 | | // value. |in| must be a valid DER encoding of an INTEGER for this to work. |
141 | | // |
142 | | // Normally the precision of the number is exactly in.size(). However when |
143 | | // encoding positive numbers using DER it is possible to have a leading zero |
144 | | // (to prevent number from being interpreted as negative). |
145 | | // |
146 | | // For instance a 160-bit positive number might take 21 bytes to encode. This |
147 | | // function will return 20 in such a case. |
148 | 2.66k | size_t GetUnsignedIntegerLength(Input in) { |
149 | 2.66k | der::ByteReader reader(in); |
150 | 2.66k | uint8_t first_byte; |
151 | 2.66k | if (!reader.ReadByte(&first_byte)) { |
152 | 0 | return 0; // Not valid DER as |in| was empty. |
153 | 0 | } |
154 | | |
155 | 2.66k | if (first_byte == 0 && in.size() > 1) { |
156 | 497 | return in.size() - 1; |
157 | 497 | } |
158 | 2.16k | return in.size(); |
159 | 2.66k | } |
160 | | |
161 | | } // namespace |
162 | | |
163 | 1.75k | bool ParseBool(Input in, bool *out) { |
164 | 1.75k | return ParseBoolInternal(in, out, false /* relaxed */); |
165 | 1.75k | } |
166 | | |
167 | | // BER interprets any non-zero value as true, while DER requires a bool to |
168 | | // have either all bits zero (false) or all bits one (true). To support |
169 | | // malformed certs, we recognized the BER encoding instead of failing to |
170 | | // parse. |
171 | 0 | bool ParseBoolRelaxed(Input in, bool *out) { |
172 | 0 | return ParseBoolInternal(in, out, true /* relaxed */); |
173 | 0 | } |
174 | | |
175 | | // ITU-T X.690 section 8.3.2 specifies that an integer value must be encoded |
176 | | // in the smallest number of octets. If the encoding consists of more than |
177 | | // one octet, then the bits of the first octet and the most significant bit |
178 | | // of the second octet must not be all zeroes or all ones. |
179 | 4.81k | bool IsValidInteger(Input in, bool *negative) { |
180 | 4.81k | CBS cbs; |
181 | 4.81k | CBS_init(&cbs, in.data(), in.size()); |
182 | 4.81k | int negative_int; |
183 | 4.81k | if (!CBS_is_valid_asn1_integer(&cbs, &negative_int)) { |
184 | 35 | return false; |
185 | 35 | } |
186 | | |
187 | 4.78k | *negative = !!negative_int; |
188 | 4.78k | return true; |
189 | 4.81k | } |
190 | | |
191 | 2.73k | bool ParseUint64(Input in, uint64_t *out) { |
192 | | // Reject non-minimally encoded numbers and negative numbers. |
193 | 2.73k | bool negative; |
194 | 2.73k | if (!IsValidInteger(in, &negative) || negative) { |
195 | 71 | return false; |
196 | 71 | } |
197 | | |
198 | | // Reject (non-negative) integers whose value would overflow the output type. |
199 | 2.66k | if (GetUnsignedIntegerLength(in) > sizeof(*out)) { |
200 | 154 | return false; |
201 | 154 | } |
202 | | |
203 | 2.50k | ByteReader reader(in); |
204 | 2.50k | uint8_t data; |
205 | 2.50k | uint64_t value = 0; |
206 | | |
207 | 9.10k | while (reader.ReadByte(&data)) { |
208 | 6.59k | value <<= 8; |
209 | 6.59k | value |= data; |
210 | 6.59k | } |
211 | 2.50k | *out = value; |
212 | 2.50k | return true; |
213 | 2.66k | } |
214 | | |
215 | 1.09k | bool ParseUint8(Input in, uint8_t *out) { |
216 | | // TODO(eroman): Implement this more directly. |
217 | 1.09k | uint64_t value; |
218 | 1.09k | if (!ParseUint64(in, &value)) { |
219 | 128 | return false; |
220 | 128 | } |
221 | | |
222 | 969 | if (value > 0xFF) { |
223 | 429 | return false; |
224 | 429 | } |
225 | | |
226 | 540 | *out = static_cast<uint8_t>(value); |
227 | 540 | return true; |
228 | 969 | } |
229 | | |
230 | | BitString::BitString(Input bytes, uint8_t unused_bits) |
231 | 2.76k | : bytes_(bytes), unused_bits_(unused_bits) { |
232 | 2.76k | BSSL_CHECK(unused_bits < 8); |
233 | 2.76k | BSSL_CHECK(unused_bits == 0 || !bytes.empty()); |
234 | | // The unused bits must be zero. |
235 | 2.76k | BSSL_CHECK(bytes.empty() || (bytes.back() & ((1u << unused_bits) - 1)) == 0); |
236 | 2.76k | } |
237 | | |
238 | 0 | bool BitString::AssertsBit(size_t bit_index) const { |
239 | | // Index of the byte that contains the bit. |
240 | 0 | size_t byte_index = bit_index / 8; |
241 | | |
242 | | // If the bit is outside of the bitstring, by definition it is not |
243 | | // asserted. |
244 | 0 | if (byte_index >= bytes_.size()) { |
245 | 0 | return false; |
246 | 0 | } |
247 | | |
248 | | // Within a byte, bits are ordered from most significant to least significant. |
249 | | // Convert |bit_index| to an index within the |byte_index| byte, measured from |
250 | | // its least significant bit. |
251 | 0 | uint8_t bit_index_in_byte = 7 - (bit_index - byte_index * 8); |
252 | | |
253 | | // BIT STRING parsing already guarantees that unused bits in a byte are zero |
254 | | // (otherwise it wouldn't be valid DER). Therefore it isn't necessary to check |
255 | | // |unused_bits_| |
256 | 0 | uint8_t byte = bytes_[byte_index]; |
257 | 0 | return 0 != (byte & (1 << bit_index_in_byte)); |
258 | 0 | } |
259 | | |
260 | 2.83k | std::optional<BitString> ParseBitString(Input in) { |
261 | 2.83k | ByteReader reader(in); |
262 | | |
263 | | // From ITU-T X.690, section 8.6.2.2 (applies to BER, CER, DER): |
264 | | // |
265 | | // The initial octet shall encode, as an unsigned binary integer with |
266 | | // bit 1 as the least significant bit, the number of unused bits in the final |
267 | | // subsequent octet. The number shall be in the range zero to seven. |
268 | 2.83k | uint8_t unused_bits; |
269 | 2.83k | if (!reader.ReadByte(&unused_bits)) { |
270 | 3 | return std::nullopt; |
271 | 3 | } |
272 | 2.82k | if (unused_bits > 7) { |
273 | 25 | return std::nullopt; |
274 | 25 | } |
275 | | |
276 | 2.80k | Input bytes; |
277 | 2.80k | if (!reader.ReadBytes(reader.BytesLeft(), &bytes)) { |
278 | 0 | return std::nullopt; // Not reachable. |
279 | 0 | } |
280 | | |
281 | | // Ensure that unused bits in the last byte are set to 0. |
282 | 2.80k | if (unused_bits > 0) { |
283 | | // From ITU-T X.690, section 8.6.2.3 (applies to BER, CER, DER): |
284 | | // |
285 | | // If the bitstring is empty, there shall be no subsequent octets, |
286 | | // and the initial octet shall be zero. |
287 | 630 | if (bytes.empty()) { |
288 | 10 | return std::nullopt; |
289 | 10 | } |
290 | 620 | uint8_t last_byte = bytes.back(); |
291 | | |
292 | | // From ITU-T X.690, section 11.2.1 (applies to CER and DER, but not BER): |
293 | | // |
294 | | // Each unused bit in the final octet of the encoding of a bit string value |
295 | | // shall be set to zero. |
296 | 620 | uint8_t mask = 0xFF >> (8 - unused_bits); |
297 | 620 | if ((mask & last_byte) != 0) { |
298 | 29 | return std::nullopt; |
299 | 29 | } |
300 | 620 | } |
301 | | |
302 | 2.76k | return BitString(bytes, unused_bits); |
303 | 2.80k | } |
304 | | |
305 | 0 | bool GeneralizedTime::InUTCTimeRange() const { |
306 | 0 | return 1950 <= year && year < 2050; |
307 | 0 | } |
308 | | |
309 | 0 | bool operator<(const GeneralizedTime &lhs, const GeneralizedTime &rhs) { |
310 | 0 | return std::tie(lhs.year, lhs.month, lhs.day, lhs.hours, lhs.minutes, |
311 | 0 | lhs.seconds) < std::tie(rhs.year, rhs.month, rhs.day, |
312 | 0 | rhs.hours, rhs.minutes, rhs.seconds); |
313 | 0 | } |
314 | | |
315 | 0 | bool operator>(const GeneralizedTime &lhs, const GeneralizedTime &rhs) { |
316 | 0 | return rhs < lhs; |
317 | 0 | } |
318 | | |
319 | 0 | bool operator<=(const GeneralizedTime &lhs, const GeneralizedTime &rhs) { |
320 | 0 | return !(lhs > rhs); |
321 | 0 | } |
322 | | |
323 | 0 | bool operator>=(const GeneralizedTime &lhs, const GeneralizedTime &rhs) { |
324 | 0 | return !(lhs < rhs); |
325 | 0 | } |
326 | | |
327 | 8.66k | bool ParseUTCTime(Input in, GeneralizedTime *value) { |
328 | 8.66k | ByteReader reader(in); |
329 | 8.66k | GeneralizedTime time; |
330 | 8.66k | if (!DecimalStringToUint(reader, 2, &time.year) || |
331 | 8.66k | !DecimalStringToUint(reader, 2, &time.month) || |
332 | 8.66k | !DecimalStringToUint(reader, 2, &time.day) || |
333 | 8.66k | !DecimalStringToUint(reader, 2, &time.hours) || |
334 | 8.66k | !DecimalStringToUint(reader, 2, &time.minutes) || |
335 | 8.66k | !DecimalStringToUint(reader, 2, &time.seconds)) { |
336 | 341 | return false; |
337 | 341 | } |
338 | 8.32k | uint8_t zulu; |
339 | 8.32k | if (!reader.ReadByte(&zulu) || zulu != 'Z' || reader.HasMore()) { |
340 | 62 | return false; |
341 | 62 | } |
342 | 8.25k | if (time.year < 50) { |
343 | 4.85k | time.year += 2000; |
344 | 4.85k | } else { |
345 | 3.40k | time.year += 1900; |
346 | 3.40k | } |
347 | 8.25k | if (!ValidateGeneralizedTime(time)) { |
348 | 76 | return false; |
349 | 76 | } |
350 | 8.18k | *value = time; |
351 | 8.18k | return true; |
352 | 8.25k | } |
353 | | |
354 | 4.16k | bool ParseGeneralizedTime(Input in, GeneralizedTime *value) { |
355 | 4.16k | ByteReader reader(in); |
356 | 4.16k | GeneralizedTime time; |
357 | 4.16k | if (!DecimalStringToUint(reader, 4, &time.year) || |
358 | 4.16k | !DecimalStringToUint(reader, 2, &time.month) || |
359 | 4.16k | !DecimalStringToUint(reader, 2, &time.day) || |
360 | 4.16k | !DecimalStringToUint(reader, 2, &time.hours) || |
361 | 4.16k | !DecimalStringToUint(reader, 2, &time.minutes) || |
362 | 4.16k | !DecimalStringToUint(reader, 2, &time.seconds)) { |
363 | 576 | return false; |
364 | 576 | } |
365 | 3.59k | uint8_t zulu; |
366 | 3.59k | if (!reader.ReadByte(&zulu) || zulu != 'Z' || reader.HasMore()) { |
367 | 104 | return false; |
368 | 104 | } |
369 | 3.48k | if (!ValidateGeneralizedTime(time)) { |
370 | 69 | return false; |
371 | 69 | } |
372 | 3.41k | *value = time; |
373 | 3.41k | return true; |
374 | 3.48k | } |
375 | | |
376 | 0 | bool ParseIA5String(Input in, std::string *out) { |
377 | 0 | for (uint8_t c : in) { |
378 | 0 | if (c > 127) { |
379 | 0 | return false; |
380 | 0 | } |
381 | 0 | } |
382 | 0 | *out = BytesAsStringView(in); |
383 | 0 | return true; |
384 | 0 | } |
385 | | |
386 | 0 | bool ParseVisibleString(Input in, std::string *out) { |
387 | | // ITU-T X.680: |
388 | | // VisibleString : "Defining registration number 6" + SPACE |
389 | | // 6 includes all the characters from '!' .. '~' (33 .. 126), space is 32. |
390 | | // Also ITU-T X.691 says it much more clearly: |
391 | | // "for VisibleString [the range] is 32 to 126 ... For VisibleString .. all |
392 | | // the values in the range are present." |
393 | 0 | for (uint8_t c : in) { |
394 | 0 | if (c < 32 || c > 126) { |
395 | 0 | return false; |
396 | 0 | } |
397 | 0 | } |
398 | 0 | *out = BytesAsStringView(in); |
399 | 0 | return true; |
400 | 0 | } |
401 | | |
402 | 0 | bool ParsePrintableString(Input in, std::string *out) { |
403 | 0 | for (uint8_t c : in) { |
404 | 0 | if (!(OPENSSL_isalpha(c) || c == ' ' || (c >= '\'' && c <= ':') || |
405 | 0 | c == '=' || c == '?')) { |
406 | 0 | return false; |
407 | 0 | } |
408 | 0 | } |
409 | 0 | *out = BytesAsStringView(in); |
410 | 0 | return true; |
411 | 0 | } |
412 | | |
413 | 0 | bool ParseTeletexStringAsLatin1(Input in, std::string *out) { |
414 | 0 | out->clear(); |
415 | | // Convert from Latin-1 to UTF-8. |
416 | 0 | size_t utf8_length = in.size(); |
417 | 0 | for (size_t i = 0; i < in.size(); i++) { |
418 | 0 | if (in[i] > 0x7f) { |
419 | 0 | utf8_length++; |
420 | 0 | } |
421 | 0 | } |
422 | 0 | out->reserve(utf8_length); |
423 | 0 | for (size_t i = 0; i < in.size(); i++) { |
424 | 0 | uint8_t u = in[i]; |
425 | 0 | if (u <= 0x7f) { |
426 | 0 | out->push_back(u); |
427 | 0 | } else { |
428 | 0 | out->push_back(0xc0 | (u >> 6)); |
429 | 0 | out->push_back(0x80 | (u & 0x3f)); |
430 | 0 | } |
431 | 0 | } |
432 | 0 | BSSL_CHECK(utf8_length == out->size()); |
433 | 0 | return true; |
434 | 0 | } |
435 | | |
436 | 7.62k | bool ParseUniversalString(Input in, std::string *out) { |
437 | 7.62k | if (in.size() % 4 != 0) { |
438 | 186 | return false; |
439 | 186 | } |
440 | | |
441 | 7.43k | CBS cbs; |
442 | 7.43k | CBS_init(&cbs, in.data(), in.size()); |
443 | 7.43k | bssl::ScopedCBB cbb; |
444 | 7.43k | if (!CBB_init(cbb.get(), in.size())) { |
445 | 0 | return false; |
446 | 0 | } |
447 | | |
448 | 15.3k | while (CBS_len(&cbs) != 0) { |
449 | 8.64k | uint32_t c; |
450 | 8.64k | if (!CBS_get_utf32_be(&cbs, &c) || // |
451 | 8.64k | !CBB_add_utf8(cbb.get(), c)) { |
452 | 738 | return false; |
453 | 738 | } |
454 | 8.64k | } |
455 | | |
456 | 6.69k | out->assign(CBB_data(cbb.get()), CBB_data(cbb.get()) + CBB_len(cbb.get())); |
457 | 6.69k | return true; |
458 | 7.43k | } |
459 | | |
460 | 140k | bool ParseBmpString(Input in, std::string *out) { |
461 | 140k | if (in.size() % 2 != 0) { |
462 | 196 | return false; |
463 | 196 | } |
464 | | |
465 | 140k | CBS cbs; |
466 | 140k | CBS_init(&cbs, in.data(), in.size()); |
467 | 140k | bssl::ScopedCBB cbb; |
468 | 140k | if (!CBB_init(cbb.get(), in.size())) { |
469 | 0 | return false; |
470 | 0 | } |
471 | | |
472 | 6.37M | while (CBS_len(&cbs) != 0) { |
473 | 6.23M | uint32_t c; |
474 | 6.23M | if (!CBS_get_ucs2_be(&cbs, &c) || // |
475 | 6.23M | !CBB_add_utf8(cbb.get(), c)) { |
476 | 590 | return false; |
477 | 590 | } |
478 | 6.23M | } |
479 | | |
480 | 139k | out->assign(CBB_data(cbb.get()), CBB_data(cbb.get()) + CBB_len(cbb.get())); |
481 | 139k | return true; |
482 | 140k | } |
483 | | |
484 | | } // namespace der |
485 | | BSSL_NAMESPACE_END |