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