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