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