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